RprtCli/app/src/Utils/TimeTrackingServices/YoutrackRestApi/EntityManager.php

125 lines
3.9 KiB
PHP

<?php
declare(strict_types=1);
namespace RprtCli\Utils\TimeTrackingServices\YoutrackRestApi;
use RprtCli\Utils\TimeTrackingServices\EntityManagerInterface;
use RprtCli\Utils\TimeTrackingServices\EntityDefinition;
use RprtCli\Utils\TimeTrackingServices\EntityInterface;
use Symfony\Component\Finder\Finder;
class EntityManager implements EntityManagerInterface {
protected const ENTITIES_DIR = 'YoutrackEntityTypes';
protected const ENTITIES_NAMESPACE = 'RprtCli\\Utils\\TimeTrackingServices\\YoutrackRestApi';
protected ?array $entityDefinitions = null;
public function __construct(protected Finder $finder) {
$this->finder = $finder;
}
/**
* Attributes based discovery from EntityTypes folder.
*/
public function list() :array {
return $this->listEntityDefinitions();
}
/**
* Returns all the entity definitions.
*/
public function listEntityDefinitions() {
if (!$this->entityDefinitions) {
$this->discoverEntities();
}
return $this->entityDefinitions;
}
/**
* Discovers entity definitions.
*/
private function discoverEntities() {
if (!empty($this->entityDefinitions)) {
return $this->entityDefinitions;
}
$path = __DIR__ . '/' . self::ENTITIES_DIR;
$definitions = [];
// @todo create a proxy service for finder.
$this->finder->files()->in($path);
/** @var SplFileInfo $file */
foreach ($this->finder as $file) {
$class = self::ENTITIES_NAMESPACE . '\\' . self::ENTITIES_DIR . '\\' . $file->getBasename('.php');
$reflection = new \ReflectionClass($class);
$attribute = $this->getAttributeOfInstance($reflection, EntityDefinition::class);
// We expect a single attribute of this kind.
if (!$attribute) {
var_dump($file);
continue;
}
$instance = $attribute->newInstance();
$id = $instance->getId();
$content = $instance->getDefinition();
$content['class'] = $class;
$definitions[$id] = $content;
}
$this->entityDefinitions = $definitions;
return $definitions;
}
/**
* Returns an attribute of a given instance or NULL.
*
* @param \ReflectionClass $reflection
* The reflection class.
* @param string $instance
* The instance the attribute should be of.
*
* @return
* The attribute instance.
*/
protected function getAttributeOfInstance(\ReflectionClass $reflection, string $instance) {
$t = $reflection->getAttributes();
var_dump($t);
var_dump($t[0]->getName());
var_dump($t[0]->getArguments());
var_dump($t[0]->newInstance());
$s = $reflection->getAttributes(EntityDefinition::class, \ReflectionAttribute::IS_INSTANCEOF);
var_dump($s);
$attributes = $reflection->getAttributes($instance, \ReflectionAttribute::IS_INSTANCEOF);
var_dump($attributes);
if (empty($attributes)) {
return NULL;
}
return reset($attributes);
}
public function getDefinition(string $id) :?array {
if (!isset($this->entityDefinitions)) {
$this->list();
}
if (!isset($this->entityDefinitions[$id])) {
// @TODO maybe we should throw an error here.
return NULL;
}
return $this->entityDefinitions[$id];
}
public function createInstance(string $id, array $values) :?EntityInterface {
if (!isset($this->entityDefinitions)) {
$this->list();
}
if (!isset($this->entityDefinitions[$id])) {
// @TODO maybe we should throw an error here.
return NULL;
}
$definition = $this->getDefinition($id);
$reflection = new \ReflectionClass($definition['class']);
return new $reflection->newInstanceArgs($values);
}
}