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,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]);
}
}