- First draft of current WIP
This commit is contained in:
commit
b73d046e0a
47 files changed
+2797
No files matched your search
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
namespace Ulmus\Common;
|
||||
|
||||
use Ulmus\Annotation\Annotation,
|
||||
Ulmus\Annotation\Classes\Table,
|
||||
Ulmus\Annotation\Property\Field;
|
||||
|
||||
class EntityResolver {
|
||||
|
||||
const KEY_ENTITY_NAME = 01;
|
||||
const KEY_COLUMN_NAME = 02;
|
||||
|
||||
public string $entityClass;
|
||||
|
||||
public array $uses;
|
||||
|
||||
public array $class;
|
||||
|
||||
public array $properties;
|
||||
|
||||
public array $methods;
|
||||
|
||||
public function __construct(string $entityClass)
|
||||
{
|
||||
$this->entityClass = $entityClass;
|
||||
|
||||
list($this->uses, $this->class, $this->methods, $this->properties) = array_values(
|
||||
ObjectReflection::fromClass($entityClass)->read()
|
||||
);
|
||||
|
||||
$this->resolveAnnotations();
|
||||
}
|
||||
|
||||
public function field($name, $fieldKey = self::KEY_ENTITY_NAME) : ? array
|
||||
{
|
||||
try{
|
||||
return $this->fieldList($fieldKey)[$name];
|
||||
}
|
||||
catch(\Throwable $e) {
|
||||
throw new \InvalidArgumentException("Can't find entity field's column named `$name` from entity {$this->entityClass}");
|
||||
}
|
||||
}
|
||||
|
||||
public function fieldList($fieldKey = self::KEY_ENTITY_NAME) : array
|
||||
{
|
||||
$fieldList = [];
|
||||
|
||||
foreach($this->properties as $item) {
|
||||
foreach($item['tags'] ?? [] as $tag) {
|
||||
if ( $tag['object'] instanceof Field ) {
|
||||
switch($fieldKey) {
|
||||
case static::KEY_ENTITY_NAME:
|
||||
$key = $item['name'];
|
||||
break;
|
||||
|
||||
case static::KEY_COLUMN_NAME:
|
||||
$key = $tag['object']->name ?? $item['name'];
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Given `fieldKey` is unknown to the EntityResolver");
|
||||
}
|
||||
|
||||
$fieldList[$key] = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldList;
|
||||
}
|
||||
|
||||
public function tableName() : string
|
||||
{
|
||||
if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
|
||||
throw new \LogicException("Your entity {$this->entityClass} seems to be missing a @Table() annotation");
|
||||
}
|
||||
|
||||
if ( $table->name === "" ) {
|
||||
throw new \ArgumentCountError("Your entity {$this->entityClass} seems to be missing a `name` argument for your @Table() annotation");
|
||||
}
|
||||
|
||||
return $table->name;
|
||||
}
|
||||
|
||||
public function primaryKeys() : array
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform an annotation into it's object's counterpart
|
||||
*/
|
||||
public function getAnnotationFromClassname(string $className) : ? object
|
||||
{
|
||||
if ( $name = $this->uses[$className] ?? false) {
|
||||
|
||||
foreach($this->class['tags'] as $item) {
|
||||
if ( $item['tag'] === $name ) {
|
||||
return $this->instanciateAnnotationObject($item);
|
||||
}
|
||||
|
||||
foreach($this->properties as $item) {
|
||||
foreach($item['tags'] as $item) {
|
||||
if ( $item['tag'] === $name ) {
|
||||
return $this->instanciateAnnotationObject($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->methods as $item) {
|
||||
foreach($item['tags'] as $item) {
|
||||
if ( $item['tag'] === $name ) {
|
||||
return $this->instanciateAnnotationObject($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
throw new \TypeError("Annotation `$className` could not be found within your object `{$this->entityClass}`");
|
||||
}
|
||||
else {
|
||||
throw new \InvalidArgumentException("Class `$className` was not found within {$this->entityClass} uses statement (or it's children / traits)");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function instanciateAnnotationObject(array $tagDefinition) : Annotation
|
||||
{
|
||||
$arguments = $this->extractArguments($tagDefinition['arguments']);
|
||||
|
||||
if ( false === $class = array_search($tagDefinition['tag'], $this->uses) ) {
|
||||
throw new \InvalidArgumentException("Annotation class `{$tagDefinition['tag']}` was not found within {$this->entityClass} uses statement (or it's children / traits)");
|
||||
}
|
||||
|
||||
$obj = new $class(... $arguments['constructor']);
|
||||
|
||||
foreach($arguments['setter'] as $key => $value) {
|
||||
$obj->$key = $value;
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts arguments from an Annotation definition, easing object's declaration.
|
||||
*/
|
||||
protected function extractArguments(array $arguments) : array
|
||||
{
|
||||
$list = [
|
||||
'setter' => [],
|
||||
'constructor' => [],
|
||||
];
|
||||
|
||||
ksort($arguments);
|
||||
|
||||
foreach($arguments as $key => $value) {
|
||||
$list[ is_int($key) ? 'constructor' : 'setter' ][$key] = $value;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
protected function resolveAnnotations()
|
||||
{
|
||||
foreach($this->class['tags'] as &$tag) {
|
||||
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||
}
|
||||
|
||||
foreach($this->properties as &$property) {
|
||||
foreach($property['tags'] as &$tag){
|
||||
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->methods as &$method) {
|
||||
foreach($method['tags'] as &$tag){
|
||||
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user