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