This commit is contained in:
cutemeli
2025-12-22 10:35:30 +00:00
parent 0bfc6c8425
commit 5ce7ca2c5d
38927 changed files with 0 additions and 4594700 deletions

View File

@@ -1,144 +0,0 @@
# Changelog
## [2.3.0](https://github.com/schmittjoh/metadata/tree/2.3.0) (2020-06-06)
**Merged pull requests:**
- Allow PSR-11 container [\#92](https://github.com/schmittjoh/metadata/pull/92) ([goetas](https://github.com/goetas))
## [2.2.0](https://github.com/schmittjoh/metadata/tree/2.2.0) (2020-05-31)
**Merged pull requests:**
- Add cache support for anonymous classes \(\#79\) [\#90](https://github.com/schmittjoh/metadata/pull/90) ([goetas](https://github.com/goetas))
- Merge 1.x [\#91](https://github.com/schmittjoh/metadata/pull/91) ([goetas](https://github.com/goetas))
- add .gitattributes [\#86](https://github.com/schmittjoh/metadata/pull/86) ([Tobion](https://github.com/Tobion))
- Test enhancement [\#84](https://github.com/schmittjoh/metadata/pull/84) ([peter279k](https://github.com/peter279k))
- Improve cache error message [\#80](https://github.com/schmittjoh/metadata/pull/80) ([thePanz](https://github.com/thePanz))
## [2.1.0](https://github.com/schmittjoh/metadata/tree/2.1.0) (2019-09-17)
**Merged pull requests:**
- make sure we only use the cache if write was successful [\#82](https://github.com/schmittjoh/metadata/pull/82) ([dbu](https://github.com/dbu))
- Handle errors when restoring from cache [\#81](https://github.com/schmittjoh/metadata/pull/81) ([dbu](https://github.com/dbu))
- Do not create MethodMetadata::$reflection on constructor/unserialize,… [\#78](https://github.com/schmittjoh/metadata/pull/78) ([ThomasNunninger](https://github.com/ThomasNunninger))
## [2.0.0](https://github.com/schmittjoh/metadata/tree/2.0.0) (2018-11-09)
No changes from **2.0.0-RC1**
## [1.7.0](https://github.com/schmittjoh/metadata/tree/1.7.0) (2018-10-26)
**Merged pull requests:**
- Allow Read-only Cache [\#74](https://github.com/schmittjoh/metadata/pull/74) ([goetas](https://github.com/goetas))
## [2.0.0-RC1](https://github.com/schmittjoh/metadata/tree/2.0.0-RC1) (2018-10-17)
**Merged pull requests:**
- Moved to psr-4 [\#73](https://github.com/schmittjoh/metadata/pull/73) ([samnela](https://github.com/samnela))
## [2.0.0-beta1](https://github.com/schmittjoh/metadata/tree/2.0.0-beta1) (2018-09-12)
**Closed issues:**
- Read-Only Filesystem Support [\#71](https://github.com/schmittjoh/metadata/issues/71)
- Change license to MIT [\#68](https://github.com/schmittjoh/metadata/issues/68)
- Composer.lock is out of date [\#55](https://github.com/schmittjoh/metadata/issues/55)
- consider changing chmod to @chmod [\#50](https://github.com/schmittjoh/metadata/issues/50)
- Big performance hit when upgrading from 1.4.2 to 1.5.0 [\#44](https://github.com/schmittjoh/metadata/issues/44)
- metadata name not present leads to exception [\#39](https://github.com/schmittjoh/metadata/issues/39)
**Merged pull requests:**
- Allow Read-only Cache [\#72](https://github.com/schmittjoh/metadata/pull/72) ([pdugas](https://github.com/pdugas))
- Code style [\#70](https://github.com/schmittjoh/metadata/pull/70) ([goetas](https://github.com/goetas))
- Change license to MIT [\#69](https://github.com/schmittjoh/metadata/pull/69) ([goetas](https://github.com/goetas))
- simplified class metadata [\#67](https://github.com/schmittjoh/metadata/pull/67) ([goetas](https://github.com/goetas))
- Fix an exception message [\#65](https://github.com/schmittjoh/metadata/pull/65) ([hason](https://github.com/hason))
- Actualized version constant. [\#64](https://github.com/schmittjoh/metadata/pull/64) ([Aliance](https://github.com/Aliance))
## [1.6.0](https://github.com/schmittjoh/metadata/tree/1.6.0) (2016-12-05)
**Closed issues:**
- Consider switching to the MIT/BSD license or a dual license otherwise [\#58](https://github.com/schmittjoh/metadata/issues/58)
- Unexpected return value [\#52](https://github.com/schmittjoh/metadata/issues/52)
- Why 0666 mode for cache file [\#48](https://github.com/schmittjoh/metadata/issues/48)
- Tons of I/O operations caused by NullMetadata [\#45](https://github.com/schmittjoh/metadata/issues/45)
**Merged pull requests:**
- Add PsrCacheAdapter [\#63](https://github.com/schmittjoh/metadata/pull/63) ([nicolas-grekas](https://github.com/nicolas-grekas))
- 50 suspress chmod warning [\#53](https://github.com/schmittjoh/metadata/pull/53) ([gusdecool](https://github.com/gusdecool))
- Adaption for complying with SPDX identifiers [\#51](https://github.com/schmittjoh/metadata/pull/51) ([valioDOTch](https://github.com/valioDOTch))
## [1.5.1](https://github.com/schmittjoh/metadata/tree/1.5.1) (2014-07-12)
**Merged pull requests:**
- Added more PHP versions and HHVM [\#47](https://github.com/schmittjoh/metadata/pull/47) ([Nyholm](https://github.com/Nyholm))
- Fix NullMetadata performance issue [\#46](https://github.com/schmittjoh/metadata/pull/46) ([adrienbrault](https://github.com/adrienbrault))
- Fixed logic bug. [\#41](https://github.com/schmittjoh/metadata/pull/41) ([flip111](https://github.com/flip111))
- Update FileCache.php added fallback option when rename fails on windows [\#40](https://github.com/schmittjoh/metadata/pull/40) ([flip111](https://github.com/flip111))
## [1.5.0](https://github.com/schmittjoh/metadata/tree/1.5.0) (2013-11-05)
**Closed issues:**
- Branch alias [\#38](https://github.com/schmittjoh/metadata/issues/38)
**Merged pull requests:**
- Don't make MetadataFactory final [\#37](https://github.com/schmittjoh/metadata/pull/37) ([bakura10](https://github.com/bakura10))
- Cache when there is no metadata for a class [\#36](https://github.com/schmittjoh/metadata/pull/36) ([adrienbrault](https://github.com/adrienbrault))
- Allow to add drivers to a driver chain [\#35](https://github.com/schmittjoh/metadata/pull/35) ([bakura10](https://github.com/bakura10))
## [1.4.2](https://github.com/schmittjoh/metadata/tree/1.4.2) (2013-09-13)
**Closed issues:**
- Update changelog [\#33](https://github.com/schmittjoh/metadata/issues/33)
- Error in Symfony2's production environment \(only\) caused with version \>= 1.4.0 [\#32](https://github.com/schmittjoh/metadata/issues/32)
**Merged pull requests:**
- Set cache files to be world readable [\#34](https://github.com/schmittjoh/metadata/pull/34) ([tommygnr](https://github.com/tommygnr))
## [1.4.1](https://github.com/schmittjoh/metadata/tree/1.4.1) (2013-08-27)
## [1.4.0](https://github.com/schmittjoh/metadata/tree/1.4.0) (2013-08-25)
## [1.3.0](https://github.com/schmittjoh/metadata/tree/1.3.0) (2013-01-22)
**Closed issues:**
- Ability to eager-load possible metadata [\#19](https://github.com/schmittjoh/metadata/issues/19)
**Merged pull requests:**
- misc cleanup [\#23](https://github.com/schmittjoh/metadata/pull/23) ([vicb](https://github.com/vicb))
- \[Cache\] Remove a race condition [\#22](https://github.com/schmittjoh/metadata/pull/22) ([vicb](https://github.com/vicb))
- Added configs for ci services [\#21](https://github.com/schmittjoh/metadata/pull/21) ([j](https://github.com/j))
- Advanced metadata implementation. [\#20](https://github.com/schmittjoh/metadata/pull/20) ([j](https://github.com/j))
- Remove incorrect docblocks [\#18](https://github.com/schmittjoh/metadata/pull/18) ([adrienbrault](https://github.com/adrienbrault))
## [1.2.0-RC](https://github.com/schmittjoh/metadata/tree/1.2.0-RC) (2012-08-21)
**Closed issues:**
- install version 1.0.0 with composer [\#9](https://github.com/schmittjoh/metadata/issues/9)
- create version/tag 1.1.1 [\#3](https://github.com/schmittjoh/metadata/issues/3)
**Merged pull requests:**
- Added the branch alias and changed the constraint on common [\#8](https://github.com/schmittjoh/metadata/pull/8) ([stof](https://github.com/stof))
- Add trait test [\#6](https://github.com/schmittjoh/metadata/pull/6) ([Seldaek](https://github.com/Seldaek))
- Fix locating files for classes without namespace [\#5](https://github.com/schmittjoh/metadata/pull/5) ([Seldaek](https://github.com/Seldaek))
- Add ApcCache [\#4](https://github.com/schmittjoh/metadata/pull/4) ([henrikbjorn](https://github.com/henrikbjorn))
## [1.1.1](https://github.com/schmittjoh/metadata/tree/1.1.1) (2012-01-02)
**Closed issues:**
- More documentation requested [\#1](https://github.com/schmittjoh/metadata/issues/1)
**Merged pull requests:**
- Add composer.json [\#2](https://github.com/schmittjoh/metadata/pull/2) ([Seldaek](https://github.com/Seldaek))
## [1.1.0](https://github.com/schmittjoh/metadata/tree/1.1.0) (2011-10-04)
## [1.0.0](https://github.com/schmittjoh/metadata/tree/1.0.0) (2011-07-09)
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

View File

@@ -1,44 +0,0 @@
# Contribute
Thank you for contributing!
Before we can merge your Pull-Request here are some guidelines that you need to follow.
These guidelines exist not to annoy you, but to keep the code base clean, unified and future proof.
## Coding Standard
This project uses [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) to enforce coding standards.
The coding standard rules are defined in the **phpcs.xml.dist** file (part of this repository).
The project follows a relaxed version of the Doctrine Coding standards v4.
Your Pull-Request must be compliant with the said standard.
To check your code you can run `vendor/bin/phpcs`. This command will give you a list of violations in your code (if any).
The most common errors can be automatically fixed just by running `vendor/bin/phpcbf`.
## Unit-Tests
Please try to add a test for your pull-request. This project uses [PHPUnit](https://phpunit.de/) as testing framework.
You can run the unit-tests by calling `vendor/bin/phpunit`.
New features without tests can't be merged.
## CI
We automatically run your pull request through [Travis CI](https://www.travis-ci.org)
and [Scrutinizer CI](https://scrutinizer-ci.com/).
If you break the tests, we cannot merge your code,
so please make sure that your code is working before opening up a Pull-Request.
## Issues and Bugs
To create a new issue, you can use the GitHub issue tracking system.
Please try to avoid opening support-related tickets. For support related questions please use more appropriate
channels as Q&A platforms (such as Stackoverflow), Forums, Local PHP user groups.
## Getting merged
Please allow us time to review your pull requests.
We will give our best to review everything as fast as possible, but cannot always live up to our own expectations.
Thank you very much again for your contribution!

View File

@@ -1,19 +0,0 @@
Copyright (c) 2018 Johannes M. Schmitt
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,55 +0,0 @@
Metadata is a library for class/method/property metadata management in PHP
==========================================================================
| [Master (2.x)][Master] | [1.x][1.x] |
|:----------------:|:----------:|
| [![Build status][Master image]][Master] | [![Build status][1.x image]][1.x] |
| [![Coverage Status][Master coverage image]][Master coverage] | [![Coverage Status][1.x coverage image]][1.x coverage] |
Overview
--------
This library provides some commonly needed base classes for managing metadata
for classes, methods and properties. The metadata can come from many different
sources (annotations, YAML/XML/PHP configuration files).
The metadata classes are used to abstract away that source and provide a common
interface for all of them.
Usage
-----
The library provides three classes that you can extend to add your application
specific properties, and flags: ``ClassMetadata``, ``MethodMetadata``, and
``PropertyMetadata``
After you have added, your properties in sub-classes, you also need to add
``DriverInterface`` implementations which know how to populate these classes
from the different metadata sources.
Finally, you can use the ``MetadataFactory`` to retrieve the metadata::
```php
<?php
use Metadata\MetadataFactory;
use Metadata\Driver\DriverChain;
$driver = new DriverChain(array(
/** Annotation, YAML, XML, PHP, ... drivers */
));
$factory = new MetadataFactory($driver);
$metadata = $factory->getMetadataForClass('MyNamespace\MyObject');
```
[Master image]: https://img.shields.io/travis/schmittjoh/metadata/master.svg?style=flat-square
[Master]: https://travis-ci.org/schmittjoh/metadata
[Master coverage image]: https://img.shields.io/scrutinizer/coverage/g/schmittjoh/metadata/master.svg?style=flat-square
[Master coverage]: https://scrutinizer-ci.com/g/schmittjoh/metadata/?branch=master
[1.x image]: https://img.shields.io/travis/schmittjoh/metadata/1.x.svg?style=flat-square
[1.x]: https://github.com/schmittjoh/metadata/tree/1.x
[1.x coverage image]: https://img.shields.io/scrutinizer/coverage/g/schmittjoh/metadata/1.x.svg?style=flat-square
[1.x coverage]: https://scrutinizer-ci.com/g/schmittjoh/metadata/?branch=1.x

View File

@@ -1,62 +0,0 @@
From 2.2.3 to 2.3.0
====================
- The `\Serializable` PHP interface is deprecated, the methods of this interface will be removed in 3.0.
This change is done to allow the use of the new `__serialize` and `__unserialize` PHP's strategy.
If you were extending the metadata classes, your custom serialization methods were looking probably as something as this:
```php
class MyMetadata extends PropertyMetadata
{
// ... more code
public function serialize()
{
$data = parent::serialize();
return \serialize([$data, $this->customMetadataProp]);
}
public function unserialize($str)
{
list($str, $this->customMetadataProp) = \unserialize($str);
parent::unserialize($str);
}
}
```
After this change, your code should look like this:
```php
class MyMetadata extends PropertyMetadata
{
// ... more code
protected function serializeToArray(): array
{
$data = parent::serializeToArray();
return [$data, $this->customMetadataProp];
}
protected function unserializeFromArray(array $data): void
{
list($data, $this->customMetadataProp) = $data;
parent::unserializeFromArray($data);
}
}
```
From 1.7.0 to 2.0.0
====================
- Type-hinting everywhere where allowed by PHP 7.2 and strict types are used now
- `Metadata\Cache\CacheInterface` changed, methods have different names and signature; all the classes implementing
that interface have been modified accordingly
- `getValue` and `setValue` methods have been removed from `Metadata\PropertyMetadata`, getting/setting properties is not
responsibility of this library anymore
- the `$reflection` property has been removed from `Metadata\PropertyMetadata`;
metadata information do not require (and do not offer) reflection anymore

View File

@@ -1,45 +0,0 @@
{
"name": "jms/metadata",
"description": "Class/method/property metadata management in PHP",
"keywords": ["annotations","metadata","yaml","xml"],
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Johannes M. Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Asmir Mustafic",
"email": "goetas@gmail.com"
}
],
"require": {
"php": "^7.2|^8.0"
},
"require-dev" : {
"doctrine/cache" : "^1.0",
"doctrine/coding-standard": "^8.0",
"phpunit/phpunit": "^8.5|^9.0",
"psr/container": "^1.0|^2.0",
"symfony/cache" : "^3.1|^4.0|^5.0",
"symfony/dependency-injection" : "^3.1|^4.0|^5.0",
"mikey179/vfsstream": "^1.6.7"
},
"autoload": {
"psr-4": { "Metadata\\": "src/" }
},
"autoload-dev": {
"psr-4": { "Metadata\\Tests\\": "tests/" }
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}

View File

@@ -1,23 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
/**
* Interface for advanced Metadata Factory implementations.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Jordan Stout <j@jrdn.org>
*/
interface AdvancedMetadataFactoryInterface extends MetadataFactoryInterface
{
/**
* Gets all the possible classes.
*
* @return string[]
*
* @throws \RuntimeException When driver does not an advanced driver.
*/
public function getAllClassNames(): array;
}

View File

@@ -1,25 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Cache;
use Metadata\ClassMetadata;
interface CacheInterface
{
/**
* Loads a class metadata instance from the cache
*/
public function load(string $class): ?ClassMetadata;
/**
* Puts a class metadata instance into the cache
*/
public function put(ClassMetadata $metadata): void;
/**
* Evicts the class metadata for the given class from the cache.
*/
public function evict(string $class): void;
}

View File

@@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Cache;
/**
* @author Alexander Strizhak <gam6itko@gmail.com>
*/
interface ClearableCacheInterface
{
/**
* Clear all classes metadata from the cache.
*/
public function clear(): bool;
}

View File

@@ -1,55 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Cache;
use Doctrine\Common\Cache\Cache;
use Metadata\ClassMetadata;
/**
* @author Henrik Bjornskov <henrik@bjrnskov.dk>
*/
class DoctrineCacheAdapter implements CacheInterface, ClearableCacheInterface
{
/**
* @var string
*/
private $prefix;
/**
* @var Cache
*/
private $cache;
public function __construct(string $prefix, Cache $cache)
{
$this->prefix = $prefix;
$this->cache = $cache;
}
public function load(string $class): ?ClassMetadata
{
$cache = $this->cache->fetch($this->prefix . $class);
return false === $cache ? null : $cache;
}
public function put(ClassMetadata $metadata): void
{
$this->cache->save($this->prefix . $metadata->name, $metadata);
}
public function evict(string $class): void
{
$this->cache->delete($this->prefix . $class);
}
public function clear(): bool
{
if (method_exists($this->cache, 'deleteAll')) { // or $this->cache instanceof ClearableCache
return call_user_func([$this->cache, 'deleteAll']);
}
return false;
}
}

View File

@@ -1,134 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Cache;
use Metadata\ClassMetadata;
class FileCache implements CacheInterface, ClearableCacheInterface
{
/**
* @var string
*/
private $dir;
public function __construct(string $dir)
{
if (!is_dir($dir) && false === @mkdir($dir, 0777, true)) {
throw new \InvalidArgumentException(sprintf('Can\'t create directory for cache at "%s"', $dir));
}
$this->dir = rtrim($dir, '\\/');
}
public function load(string $class): ?ClassMetadata
{
$path = $this->getCachePath($class);
if (!is_readable($path)) {
return null;
}
try {
$metadata = include $path;
if ($metadata instanceof ClassMetadata) {
return $metadata;
}
// if the file does not return anything, the return value is integer `1`.
} catch (\Error $e) {
// ignore corrupted cache
}
return null;
}
public function put(ClassMetadata $metadata): void
{
if (!is_writable($this->dir)) {
throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable.', $this->dir));
}
$path = $this->getCachePath($metadata->name);
if (!is_writable(dirname($path))) {
throw new \RuntimeException(sprintf('Cache file "%s" is not writable.', $path));
}
$tmpFile = tempnam($this->dir, 'metadata-cache');
if (false === $tmpFile) {
$this->evict($metadata->name);
return;
}
$data = '<?php return unserialize(' . var_export(serialize($metadata), true) . ');';
$bytesWritten = file_put_contents($tmpFile, $data);
// use strlen and not mb_strlen. if there is utf8 in the code, it also writes more bytes.
if ($bytesWritten !== strlen($data)) {
@unlink($tmpFile);
// also evict the cache to not use an outdated version.
$this->evict($metadata->name);
return;
}
// Let's not break filesystems which do not support chmod.
@chmod($tmpFile, 0666 & ~umask());
$this->renameFile($tmpFile, $path);
}
/**
* Renames a file with fallback for windows
*/
private function renameFile(string $source, string $target): void
{
if (false === @rename($source, $target)) {
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
if (false === copy($source, $target)) {
throw new \RuntimeException(sprintf('(WIN) Could not write new cache file to %s.', $target));
}
if (false === unlink($source)) {
throw new \RuntimeException(sprintf('(WIN) Could not delete temp cache file to %s.', $source));
}
} else {
throw new \RuntimeException(sprintf('Could not write new cache file to %s.', $target));
}
}
}
public function evict(string $class): void
{
$path = $this->getCachePath($class);
if (file_exists($path)) {
@unlink($path);
}
}
public function clear(): bool
{
$result = true;
$files = glob($this->dir . '/*.cache.php');
foreach ($files as $file) {
if (is_file($file)) {
$result = $result && @unlink($file);
}
}
return $result;
}
/**
* This function computes the cache file path.
*
* If anonymous class is to be cached, it contains invalid path characters that need to be removed/replaced
* Example of anonymous class name: class@anonymous\x00/app/src/Controller/DefaultController.php0x7f82a7e026ec
*/
private function getCachePath(string $key): string
{
$fileName = str_replace(['\\', "\0", '@', '/', '$', '{', '}', ':'], '-', $key);
return $this->dir . '/' . $fileName . '.cache.php';
}
}

View File

@@ -1,69 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Cache;
use Metadata\ClassMetadata;
use Psr\Cache\CacheItemPoolInterface;
class PsrCacheAdapter implements CacheInterface, ClearableCacheInterface
{
/**
* @var string
*/
private $prefix;
/**
* @var CacheItemPoolInterface
*/
private $pool;
/**
* @var CacheItemPoolInterface
*/
private $lastItem;
public function __construct(string $prefix, CacheItemPoolInterface $pool)
{
$this->prefix = $prefix;
$this->pool = $pool;
}
public function load(string $class): ?ClassMetadata
{
$this->lastItem = $this->pool->getItem($this->sanitizeCacheKey($this->prefix . $class));
return $this->lastItem->get();
}
public function put(ClassMetadata $metadata): void
{
$key = $this->sanitizeCacheKey($this->prefix . $metadata->name);
if (null === $this->lastItem || $this->lastItem->getKey() !== $key) {
$this->lastItem = $this->pool->getItem($key);
}
$this->pool->save($this->lastItem->set($metadata));
}
public function evict(string $class): void
{
$this->pool->deleteItem($this->sanitizeCacheKey($this->prefix . $class));
}
public function clear(): bool
{
return $this->pool->clear();
}
/**
* If anonymous class is to be cached, it contains invalid path characters that need to be removed/replaced
* Example of anonymous class name: class@anonymous\x00/app/src/Controller/DefaultController.php0x7f82a7e026ec
*/
private function sanitizeCacheKey(string $key): string
{
return str_replace(['\\', "\0", '@', '/', '$', '{', '}', ':'], '-', $key);
}
}

View File

@@ -1,44 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
/**
* Represents the metadata for the entire class hierarchy.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ClassHierarchyMetadata
{
/**
* @var ClassMetadata[]
*/
public $classMetadata = [];
public function addClassMetadata(ClassMetadata $metadata): void
{
$this->classMetadata[$metadata->name] = $metadata;
}
public function getRootClassMetadata(): ?ClassMetadata
{
return reset($this->classMetadata);
}
public function getOutsideClassMetadata(): ?ClassMetadata
{
return end($this->classMetadata);
}
public function isFresh(int $timestamp): bool
{
foreach ($this->classMetadata as $metadata) {
if (!$metadata->isFresh($timestamp)) {
return false;
}
}
return true;
}
}

View File

@@ -1,100 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
/**
* Base class for class metadata.
*
* This class is intended to be extended to add your own application specific
* properties, and flags.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ClassMetadata implements \Serializable
{
use SerializationHelper;
/**
* @var string
*/
public $name;
/**
* @var MethodMetadata[]
*/
public $methodMetadata = [];
/**
* @var PropertyMetadata[]
*/
public $propertyMetadata = [];
/**
* @var string[]
*/
public $fileResources = [];
/**
* @var int
*/
public $createdAt;
public function __construct(string $name)
{
$this->name = $name;
$this->createdAt = time();
}
public function addMethodMetadata(MethodMetadata $metadata): void
{
$this->methodMetadata[$metadata->name] = $metadata;
}
public function addPropertyMetadata(PropertyMetadata $metadata): void
{
$this->propertyMetadata[$metadata->name] = $metadata;
}
public function isFresh(?int $timestamp = null): bool
{
if (null === $timestamp) {
$timestamp = $this->createdAt;
}
foreach ($this->fileResources as $filepath) {
if (!file_exists($filepath)) {
return false;
}
if ($timestamp < filemtime($filepath)) {
return false;
}
}
return true;
}
protected function serializeToArray(): array
{
return [
$this->name,
$this->methodMetadata,
$this->propertyMetadata,
$this->fileResources,
$this->createdAt,
];
}
protected function unserializeFromArray(array $data): void
{
[
$this->name,
$this->methodMetadata,
$this->propertyMetadata,
$this->fileResources,
$this->createdAt,
] = $data;
}
}

View File

@@ -1,56 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
use Metadata\ClassMetadata;
/**
* Base file driver implementation.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
abstract class AbstractFileDriver implements AdvancedDriverInterface
{
/**
* @var FileLocatorInterface|FileLocator
*/
private $locator;
public function __construct(FileLocatorInterface $locator)
{
$this->locator = $locator;
}
public function loadMetadataForClass(\ReflectionClass $class): ?ClassMetadata
{
if (null === $path = $this->locator->findFileForClass($class, $this->getExtension())) {
return null;
}
return $this->loadMetadataFromFile($class, $path);
}
/**
* {@inheritDoc}
*/
public function getAllClassNames(): array
{
if (!$this->locator instanceof AdvancedFileLocatorInterface) {
throw new \RuntimeException(sprintf('Locator "%s" must be an instance of "AdvancedFileLocatorInterface".', get_class($this->locator)));
}
return $this->locator->findAllClasses($this->getExtension());
}
/**
* Parses the content of the file, and converts it to the desired metadata.
*/
abstract protected function loadMetadataFromFile(\ReflectionClass $class, string $file): ?ClassMetadata;
/**
* Returns the extension of the file.
*/
abstract protected function getExtension(): string;
}

View File

@@ -1,20 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
/**
* Forces advanced logic to drivers.
*
* @author Jordan Stout <j@jrdn.org>
*/
interface AdvancedDriverInterface extends DriverInterface
{
/**
* Gets all the metadata class names known to this driver.
*
* @return string[]
*/
public function getAllClassNames(): array;
}

View File

@@ -1,20 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
/**
* Forces advanced logic on a file locator.
*
* @author Jordan Stout <j@jrdn.org>
*/
interface AdvancedFileLocatorInterface extends FileLocatorInterface
{
/**
* Finds all possible metadata files.*
*
* @return string[]
*/
public function findAllClasses(string $extension): array;
}

View File

@@ -1,65 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
use Metadata\ClassMetadata;
final class DriverChain implements AdvancedDriverInterface
{
/**
* @var DriverInterface[]
*/
private $drivers;
/**
* @param DriverInterface[] $drivers
*/
public function __construct(array $drivers = [])
{
$this->drivers = $drivers;
}
public function addDriver(DriverInterface $driver): void
{
$this->drivers[] = $driver;
}
public function loadMetadataForClass(\ReflectionClass $class): ?ClassMetadata
{
foreach ($this->drivers as $driver) {
if (null !== $metadata = $driver->loadMetadataForClass($class)) {
return $metadata;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getAllClassNames(): array
{
$classes = [];
foreach ($this->drivers as $driver) {
if (!$driver instanceof AdvancedDriverInterface) {
throw new \RuntimeException(
sprintf(
'Driver "%s" must be an instance of "AdvancedDriverInterface" to use ' .
'"DriverChain::getAllClassNames()".',
get_class($driver)
)
);
}
$driverClasses = $driver->getAllClassNames();
if (!empty($driverClasses)) {
$classes = array_merge($classes, $driverClasses);
}
}
return $classes;
}
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
use Metadata\ClassMetadata;
interface DriverInterface
{
public function loadMetadataForClass(\ReflectionClass $class): ?ClassMetadata;
}

View File

@@ -1,80 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
class FileLocator implements AdvancedFileLocatorInterface, TraceableFileLocatorInterface
{
/**
* @var string[]
*/
private $dirs;
/**
* @param string[] $dirs
*/
public function __construct(array $dirs)
{
$this->dirs = $dirs;
}
/**
* @return array<string, bool>
*/
public function getPossibleFilesForClass(\ReflectionClass $class, string $extension): array
{
$possibleFiles = [];
foreach ($this->dirs as $prefix => $dir) {
if ('' !== $prefix && 0 !== strpos($class->getNamespaceName(), $prefix)) {
continue;
}
$len = '' === $prefix ? 0 : strlen($prefix) + 1;
$path = $dir . '/' . str_replace('\\', '.', substr($class->name, $len)) . '.' . $extension;
$existsPath = file_exists($path);
$possibleFiles[$path] = $existsPath;
if ($existsPath) {
return $possibleFiles;
}
}
return $possibleFiles;
}
public function findFileForClass(\ReflectionClass $class, string $extension): ?string
{
foreach ($this->getPossibleFilesForClass($class, $extension) as $path => $existsPath) {
if ($existsPath) {
return $path;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function findAllClasses(string $extension): array
{
$classes = [];
foreach ($this->dirs as $prefix => $dir) {
/** @var \RecursiveIteratorIterator|\SplFileInfo[] $iterator */
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($dir),
\RecursiveIteratorIterator::LEAVES_ONLY
);
$nsPrefix = '' !== $prefix ? $prefix . '\\' : '';
foreach ($iterator as $file) {
if (($fileName = $file->getBasename('.' . $extension)) === $file->getBasename()) {
continue;
}
$classes[] = $nsPrefix . str_replace('.', '\\', $fileName);
}
}
return $classes;
}
}

View File

@@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
interface FileLocatorInterface
{
public function findFileForClass(\ReflectionClass $class, string $extension): ?string;
}

View File

@@ -1,40 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
use Metadata\ClassMetadata;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LazyLoadingDriver implements DriverInterface
{
/**
* @var ContainerInterface|PsrContainerInterface
*/
private $container;
/**
* @var string
*/
private $realDriverId;
/**
* @param ContainerInterface|PsrContainerInterface $container
*/
public function __construct($container, string $realDriverId)
{
if (!$container instanceof PsrContainerInterface && !$container instanceof ContainerInterface) {
throw new \InvalidArgumentException(sprintf('The container must be an instance of %s or %s (%s given).', PsrContainerInterface::class, ContainerInterface::class, \is_object($container) ? \get_class($container) : \gettype($container)));
}
$this->container = $container;
$this->realDriverId = $realDriverId;
}
public function loadMetadataForClass(\ReflectionClass $class): ?ClassMetadata
{
return $this->container->get($this->realDriverId)->loadMetadataForClass($class);
}
}

View File

@@ -1,15 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata\Driver;
interface TraceableFileLocatorInterface extends FileLocatorInterface
{
/**
* Finds all possible metadata files for a class
*
* @return string[]
*/
public function getPossibleFilesForClass(\ReflectionClass $class, string $extension): array;
}

View File

@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
class MergeableClassMetadata extends ClassMetadata implements MergeableInterface
{
public function merge(MergeableInterface $object): void
{
if (!$object instanceof MergeableClassMetadata) {
throw new \InvalidArgumentException('$object must be an instance of MergeableClassMetadata.');
}
$this->name = $object->name;
$this->methodMetadata = array_merge($this->methodMetadata, $object->methodMetadata);
$this->propertyMetadata = array_merge($this->propertyMetadata, $object->propertyMetadata);
$this->fileResources = array_merge($this->fileResources, $object->fileResources);
if ($object->createdAt < $this->createdAt) {
$this->createdAt = $object->createdAt;
}
}
}

View File

@@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
interface MergeableInterface
{
public function merge(MergeableInterface $object): void;
}

View File

@@ -1,217 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
use Metadata\Cache\CacheInterface;
use Metadata\Driver\AdvancedDriverInterface;
use Metadata\Driver\DriverInterface;
class MetadataFactory implements AdvancedMetadataFactoryInterface
{
/**
* @var DriverInterface
*/
private $driver;
/**
* @var CacheInterface
*/
private $cache;
/**
* @var ClassMetadata[]
*/
private $loadedMetadata = [];
/**
* @var ClassMetadata[]
*/
private $loadedClassMetadata = [];
/**
* @var string|null
*/
private $hierarchyMetadataClass;
/**
* @var bool
*/
private $includeInterfaces = false;
/**
* @var bool
*/
private $debug = false;
public function __construct(DriverInterface $driver, ?string $hierarchyMetadataClass = 'Metadata\ClassHierarchyMetadata', bool $debug = false)
{
$this->driver = $driver;
$this->hierarchyMetadataClass = $hierarchyMetadataClass;
$this->debug = $debug;
}
public function setIncludeInterfaces(bool $include): void
{
$this->includeInterfaces = $include;
}
public function setCache(CacheInterface $cache): void
{
$this->cache = $cache;
}
/**
* {@inheritDoc}
*/
public function getMetadataForClass(string $className)
{
if (isset($this->loadedMetadata[$className])) {
return $this->filterNullMetadata($this->loadedMetadata[$className]);
}
$metadata = null;
foreach ($this->getClassHierarchy($className) as $class) {
if (isset($this->loadedClassMetadata[$name = $class->getName()])) {
if (null !== $classMetadata = $this->filterNullMetadata($this->loadedClassMetadata[$name])) {
$this->addClassMetadata($metadata, $classMetadata);
}
continue;
}
// check the cache
if (null !== $this->cache) {
if (($classMetadata = $this->cache->load($class->getName())) instanceof NullMetadata) {
$this->loadedClassMetadata[$name] = $classMetadata;
continue;
}
if (null !== $classMetadata) {
if (!$classMetadata instanceof ClassMetadata) {
throw new \LogicException(sprintf(
'The cache must return instances of ClassMetadata for class %s, but got %s.',
$className,
var_export($classMetadata, true)
));
}
if ($this->debug && !$classMetadata->isFresh()) {
$this->cache->evict($classMetadata->name);
} else {
$this->loadedClassMetadata[$name] = $classMetadata;
$this->addClassMetadata($metadata, $classMetadata);
continue;
}
}
}
// load from source
if (null !== $classMetadata = $this->driver->loadMetadataForClass($class)) {
$this->loadedClassMetadata[$name] = $classMetadata;
$this->addClassMetadata($metadata, $classMetadata);
if (null !== $this->cache) {
$this->cache->put($classMetadata);
}
continue;
}
if (null !== $this->cache && !$this->debug) {
$this->cache->put(new NullMetadata($class->getName()));
}
}
if (null === $metadata) {
$metadata = new NullMetadata($className);
}
return $this->filterNullMetadata($this->loadedMetadata[$className] = $metadata);
}
/**
* {@inheritDoc}
*/
public function getAllClassNames(): array
{
if (!$this->driver instanceof AdvancedDriverInterface) {
throw new \RuntimeException(
sprintf('Driver "%s" must be an instance of "AdvancedDriverInterface".', get_class($this->driver))
);
}
return $this->driver->getAllClassNames();
}
/**
* @param MergeableInterface|ClassHierarchyMetadata $metadata
*/
private function addClassMetadata(&$metadata, ClassMetadata $toAdd): void
{
if ($toAdd instanceof MergeableInterface) {
if (null === $metadata) {
$metadata = clone $toAdd;
} else {
$metadata->merge($toAdd);
}
} else {
if (null === $metadata) {
$class = $this->hierarchyMetadataClass;
$metadata = new $class();
}
$metadata->addClassMetadata($toAdd);
}
}
/**
* @return \ReflectionClass[]
*/
private function getClassHierarchy(string $class): array
{
$classes = [];
$refl = new \ReflectionClass($class);
do {
$classes[] = $refl;
$refl = $refl->getParentClass();
} while (false !== $refl);
$classes = array_reverse($classes, false);
if (!$this->includeInterfaces) {
return $classes;
}
$addedInterfaces = [];
$newHierarchy = [];
foreach ($classes as $class) {
foreach ($class->getInterfaces() as $interface) {
if (isset($addedInterfaces[$interface->getName()])) {
continue;
}
$addedInterfaces[$interface->getName()] = true;
$newHierarchy[] = $interface;
}
$newHierarchy[] = $class;
}
return $newHierarchy;
}
/**
* @param ClassMetadata|ClassHierarchyMetadata|MergeableInterface $metadata
*
* @return ClassMetadata|ClassHierarchyMetadata|MergeableInterface
*/
private function filterNullMetadata($metadata = null)
{
return !$metadata instanceof NullMetadata ? $metadata : null;
}
}

View File

@@ -1,29 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
/**
* Interface for Metadata Factory implementations.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface MetadataFactoryInterface
{
/**
* Returns the gathered metadata for the given class name.
*
* If the drivers return instances of MergeableClassMetadata, these will be
* merged prior to returning. Otherwise, all metadata for the inheritance
* hierarchy will be returned as ClassHierarchyMetadata unmerged.
*
* If no metadata is available, null is returned.
*
* @return ClassHierarchyMetadata|MergeableClassMetadata|null
*
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.UselessReturnAnnotation
*/
public function getMetadataForClass(string $className);
}

View File

@@ -1,90 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
/**
* Base class for method metadata.
*
* This class is intended to be extended to add your application specific
* properties, and flags.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @property $reflection
*/
class MethodMetadata implements \Serializable
{
use SerializationHelper;
/**
* @var string
*/
public $class;
/**
* @var string
*/
public $name;
/**
* @var \ReflectionMethod
*/
private $reflection;
public function __construct(string $class, string $name)
{
$this->class = $class;
$this->name = $name;
}
/**
* @param mixed[] $args
*
* @return mixed
*/
public function invoke(object $obj, array $args = [])
{
return $this->getReflection()->invokeArgs($obj, $args);
}
/**
* @return mixed
*/
public function __get(string $propertyName)
{
if ('reflection' === $propertyName) {
return $this->getReflection();
}
return $this->$propertyName;
}
/**
* @param mixed $value
*/
public function __set(string $propertyName, $value): void
{
$this->$propertyName = $value;
}
private function getReflection(): \ReflectionMethod
{
if (null === $this->reflection) {
$this->reflection = new \ReflectionMethod($this->class, $this->name);
$this->reflection->setAccessible(true);
}
return $this->reflection;
}
protected function serializeToArray(): array
{
return [$this->class, $this->name];
}
protected function unserializeFromArray(array $data): void
{
[$this->class, $this->name] = $data;
}
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
/**
* Represents the metadata for a class that has not metadata.
*
* @author Adrien Brault <adrien.brault@gmail.com>
*/
class NullMetadata extends ClassMetadata
{
}

View File

@@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
/**
* Base class for property metadata.
*
* This class is intended to be extended to add your application specific
* properties, and flags.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class PropertyMetadata implements \Serializable
{
use SerializationHelper;
/**
* @var string
*/
public $class;
/**
* @var string
*/
public $name;
public function __construct(string $class, string $name)
{
$this->class = $class;
$this->name = $name;
}
protected function serializeToArray(): array
{
return [
$this->class,
$this->name,
];
}
protected function unserializeFromArray(array $data): void
{
[$this->class, $this->name] = $data;
}
}

View File

@@ -1,40 +0,0 @@
<?php
declare(strict_types=1);
namespace Metadata;
trait SerializationHelper
{
/**
* @deprecated Use serializeToArray
*
* @return string
*/
public function serialize()
{
return serialize($this->serializeToArray());
}
/**
* @deprecated Use unserializeFromArray
*
* @param string $str
*
* @return void
*/
public function unserialize($str)
{
$this->unserializeFromArray(unserialize($str));
}
public function __serialize(): array
{
return [$this->serialize()];
}
public function __unserialize(array $data): void
{
$this->unserialize($data[0]);
}
}