public static function build(MetaClass $class) { $out = self::getHead(); $out .= <<<EOT namespace {$class->getAutoNamespace()}; EOT; $uses = [IdentifiableObject::class, MetaClassNameBuilder::getClassOfMetaClass($class)]; foreach ($class->getProperties() as $property) { $dependency = null; if ($property->getType() instanceof ObjectType) { if ($property->getRelationId() == MetaRelation::ONE_TO_MANY | $property->getRelationId() == MetaRelation::MANY_TO_MANY) { $dependency = MetaClassNameBuilder::getContainerClassOfMetaProperty($property); } else { $dependency = MetaClassNameBuilder::getClassOfMetaProperty($property); } } elseif ($property->getType() instanceof BooleanType && $property->isOptional()) { $dependency = Assert::class; } if (!is_null($dependency) && !in_array($dependency, $uses)) { $uses[] = $dependency; } } foreach ($uses as $import) { $out .= <<<EOT use {$import}; EOT; } $out .= <<<EOT abstract class Auto{$class->getName()} EOT; $isNamed = false; if ($parent = $class->getParent()) { $out .= " extends \\{$parent->getNamespace()}\\{$parent->getName()}"; } elseif ($class->getPattern() instanceof DictionaryClassPattern && $class->hasProperty('name')) { $out .= " extends NamedObject"; $isNamed = true; } elseif (!$class->getPattern() instanceof ValueObjectPattern) { $out .= " extends IdentifiableObject"; } if ($interfaces = $class->getInterfaces()) { $out .= ' implements ' . implode(', ', $interfaces); } $out .= "\n{\n"; foreach ($class->getProperties() as $property) { if (!self::doPropertyBuild($class, $property, $isNamed)) { continue; } if ($property->getFetchStrategyId() == FetchStrategy::LAZY) { $out .= "protected \${$property->getName()}Id = null;\n"; } else { $out .= "protected \${$property->getName()} = " . "{$property->getType()->getDeclaration()};\n"; } } $valueObjects = []; foreach ($class->getProperties() as $property) { if ($property->getType() instanceof ObjectType && !$property->getType()->isGeneric() && $property->getType()->getClass()->getPattern() instanceof ValueObjectPattern) { $valueObjects[$property->getName()] = $property->getType()->getClassName(); } } if ($valueObjects) { $out .= <<<EOT public function __construct() { EOT; foreach ($valueObjects as $propertyName => $className) { $out .= "\$this->{$propertyName} = new {$className}();\n"; } $out .= "}\n"; } foreach ($class->getProperties() as $property) { if (!self::doPropertyBuild($class, $property, $isNamed)) { continue; } $out .= $property->toMethods($class); } $out .= "}\n"; $out .= self::getHeel(); return $out; }
protected static function buildPointers(MetaClass $class) { $out = null; if (!$class->getPattern() instanceof AbstractClassPattern) { if ($source = $class->getSourceLink()) { $out .= <<<EOT \tprotected \$linkName = '{$source}'; \t EOT; } if ($class->getIdentifier()->getColumnName() !== 'id') { $out .= <<<EOT public function getIdName() { \treturn '{$class->getIdentifier()->getColumnName()}'; } EOT; } $fullClassName = MetaClassNameBuilder::getClassOfMetaClass($class, true); $out .= <<<EOT public function getTable() { \treturn '{$class->getTableName()}'; } public function getObjectName() { \treturn '{$fullClassName}'; } EOT; if ($class->isSequenceless()) { $out .= <<<EOT public function getSequence() { \tthrow new \\Hesper\\Core\\Exception\\UnimplementedFeatureException(); } EOT; } else { $out .= <<<EOT public function getSequence() { \treturn '{$class->getTableName()}_id'; } EOT; } } elseif ($class->getWithInternalProperties()) { $out .= <<<EOT // no get{Table,ObjectName,Sequence} for abstract class EOT; } if ($liaisons = $class->getReferencingClasses()) { $uncachers = []; foreach ($liaisons as $className) { $uncachers[] = $className . '::dao()->uncacheLists();'; } $uncachers = implode("\n", $uncachers); $out .= <<<EOT public function uncacheLists() { {$uncachers} return parent::uncacheLists(); } EOT; } return $out; }
/** * @return MetaConfiguration **/ public function checkIntegrity() { $out = $this->getOutput()->newLine()->infoLine('Checking sanity of generated files: ')->newLine(); $out->info("\t"); $formErrors = []; foreach ($this->classes as $name => $class) { if (!($class->getPattern() instanceof SpookedClassPattern || $class->getPattern() instanceof SpookedEnumerationPattern || $class->getPattern() instanceof SpookedEnumPattern || $class->getPattern() instanceof SpookedRegistryPattern || $class->getPattern() instanceof InternalClassPattern) && class_exists(MetaClassNameBuilder::getClassOfMetaClass($class, true))) { $out->info($name, true); $className = MetaClassNameBuilder::getClassOfMetaClass($class); $info = new \ReflectionClass($className); $this->checkClassSanity($class, $info); if ($info->implementsInterface(Prototyped::class)) { $this->checkClassSanity($class, new \ReflectionClass($class->getProtoClass())); } if ($info->implementsInterface(DAOConnected::class)) { $this->checkClassSanity($class, new \ReflectionClass($class->getDaoClass())); } foreach ($class->getInterfaces() as $interface) { Assert::isTrue($info->implementsInterface($interface), 'class ' . $class->getName() . ' expected to implement interface ' . $interface); } // special handling for Enumeration instances if ($class->getPattern() instanceof EnumerationClassPattern || $class->getPattern() instanceof EnumClassPattern || $class->getPattern() instanceof RegistryClassPattern) { $object = new $className(call_user_func([$className, 'getAnyId'])); Assert::isTrue(unserialize(serialize($object)) == $object); $out->info(', '); if ($this->checkEnumerationRefIntegrity) { if ($object instanceof Enumeration || $object instanceof Enum || $object instanceof Registry) { $this->checkEnumerationReferentialIntegrity($object, $class->getTableName()); } } continue; } if ($class->getPattern() instanceof AbstractClassPattern) { $out->info(', '); continue; } /** @var Prototyped $object */ $object = new $className(); $proto = $object->proto(); $form = $proto->makeForm(); foreach ($class->getProperties() as $name => $property) { Assert::isTrue($property->toLightProperty($class) == $proto->getPropertyByName($name), 'defined property does not match autogenerated one - ' . $class->getName() . '::' . $property->getName()); } if (!$object instanceof DAOConnected) { $out->info(', '); continue; } $dao = $object->dao(); Assert::isEqual($dao->getIdName(), $class->getIdentifier()->getColumnName(), 'identifier name mismatch in ' . $class->getName() . ' class'); try { DBPool::getByDao($dao); } catch (MissingElementException $e) { // skipping $out->info(', '); continue; } $query = Criteria::create($dao)->setLimit(1)->add(Expression::notNull($class->getIdentifier()->getName()))->addOrder($class->getIdentifier()->getName())->toSelectQuery(); $out->warning(' (' . $query->getFieldsCount() . '/' . $query->getTablesCount() . '/'); $clone = clone $object; if (serialize($clone) == serialize($object)) { $out->info('C', true); } else { $out->error('C', true); } $out->warning('/'); try { $object = $dao->getByQuery($query); $form = $object->proto()->makeForm(); FormUtils::object2form($object, $form); if ($errors = $form->getErrors()) { $formErrors[$class->getName()] = $errors; $out->error('F', true); } else { $out->info('F', true); } } catch (ObjectNotFoundException $e) { $out->warning('F'); } $out->warning('/'); if (Criteria::create($dao)->setFetchStrategy(FetchStrategy::cascade())->toSelectQuery() == $dao->makeSelectHead()) { $out->info('H', true); } else { $out->error('H', true); } $out->warning('/'); // cloning once again $clone = clone $object; FormUtils::object2form($object, $form); FormUtils::form2object($form, $object); if ($object != $clone) { $out->error('T', true); } else { $out->info('T', true); } $out->warning(')')->info(', '); } } $out->infoLine('done.'); if ($formErrors) { $out->newLine()->errorLine('Errors found:')->newLine(); foreach ($formErrors as $class => $errors) { $out->errorLine("\t" . $class . ':', true); foreach ($errors as $name => $error) { $out->errorLine("\t\t" . $name . ' - ' . ($error == Form::WRONG ? ' wrong' : ' missing')); } $out->newLine(); } } return $this; }
public static function buildContainer(MetaClass $class, MetaClassProperty $holder) { $out = self::getHead(); $out .= <<<EOT namespace {$class->getDaoNamespace()}; EOT; $containerName = $class->getName() . ucfirst($holder->getName()) . 'DAO'; $containerType = $holder->getRelation()->toString() . 'Linked'; $uses = ['Hesper\\Main\\UnifiedContainer\\' . $containerType, MetaClassNameBuilder::getClassOfMetaClass($class), MetaClassNameBuilder::getClassOfMetaProperty($holder)]; foreach ($uses as $import) { $out .= <<<EOT use {$import}; EOT; } $out .= <<<EOT EOT; $out .= 'final class ' . $containerName . ' extends ' . $containerType . "\n{\n"; $className = $class->getName(); $propertyName = strtolower($className[0]) . substr($className, 1); $remoteColumnName = $holder->getType()->getClass()->getTableName(); $out .= <<<EOT public function __construct({$className} \${$propertyName}, \$lazy = false) { \tparent::__construct( \t\t\${$propertyName}, \t\t{$holder->getType()->getClassName()}::dao(), \t\t\$lazy \t); } /** * @return {$containerName} **/ public static function create({$className} \${$propertyName}, \$lazy = false) { \treturn new self(\${$propertyName}, \$lazy); } EOT; if ($holder->getRelation()->getId() == MetaRelation::MANY_TO_MANY) { $out .= <<<EOT public function getHelperTable() { \treturn '{$class->getTableName()}_{$remoteColumnName}'; } public function getChildIdField() { \treturn '{$remoteColumnName}_id'; } EOT; } $out .= <<<EOT public function getParentIdField() { \treturn '{$class->getTableName()}_id'; } EOT; $out .= "}\n"; $out .= self::getHeel(); return $out; }
/** * @param MetaClass $holder * * @return LightMetaProperty */ public function toLightProperty(MetaClass $holder) { $className = null; $businessClassName = null; if ($this->getRelationId() == MetaRelation::ONE_TO_MANY || $this->getRelationId() == MetaRelation::MANY_TO_MANY) { // collections $primitiveName = 'identifierList'; $businessClassName = MetaClassNameBuilder::getClassOfMetaProperty($this, true); } elseif ($this->isIdentifier()) { if ($this->getType() instanceof IntegerType) { $primitiveName = 'integerIdentifier'; $className = $holder->getName(); } elseif ($this->getType() instanceof StringType) { $primitiveName = 'scalarIdentifier'; $className = $holder->getName(); } elseif ($this->getType() instanceof UuidType) { $primitiveName = 'uuidIdentifier'; $className = $holder->getName(); } else { $primitiveName = $this->getType()->getPrimitiveName(); } $businessClassName = MetaClassNameBuilder::getClassOfMetaClass($holder, true); } elseif (!$this->isIdentifier() && !$this->getType()->isGeneric() && $this->getType() instanceof ObjectType) { $pattern = $this->getType()->getClass()->getPattern(); if ($pattern instanceof EnumerationClassPattern) { $primitiveName = 'enumeration'; $businessClassName = MetaClassNameBuilder::getClassOfMetaProperty($this, true); } elseif ($pattern instanceof EnumClassPattern) { $primitiveName = 'enum'; $businessClassName = MetaClassNameBuilder::getClassOfMetaProperty($this, true); } elseif ($pattern instanceof RegistryClassPattern) { $primitiveName = 'registry'; $businessClassName = MetaClassNameBuilder::getClassOfMetaProperty($this, true); } elseif (($pattern instanceof DictionaryClassPattern || $pattern instanceof StraightMappingPattern) && ($identifier = $this->getType()->getClass()->getIdentifier())) { $businessClassName = MetaClassNameBuilder::getClassOfMetaProperty($this, true); if ($identifier->getType() instanceof IntegerType) { $primitiveName = 'integerIdentifier'; } elseif ($identifier->getType() instanceof StringType) { $primitiveName = 'scalarIdentifier'; } elseif ($identifier->getType() instanceof UuidType) { $primitiveName = 'uuidIdentifier'; } else { $primitiveName = $this->getType()->getPrimitiveName(); } } else { $primitiveName = $this->getType()->getPrimitiveName(); } } else { if ($this->getType() instanceof ObjectType) { $businessClassName = MetaClassNameBuilder::getClassOfMetaProperty($this, true); } $primitiveName = $this->getType()->getPrimitiveName(); } $inner = false; if ($this->getType() instanceof ObjectType) { $className = $this->getType()->getClassName(); if (!$this->getType()->isGeneric()) { $class = $this->getType()->getClass(); $pattern = $class->getPattern(); if ($pattern instanceof InternalClassPattern) { $className = $holder->getName(); } if (($pattern instanceof InternalClassPattern || $pattern instanceof ValueObjectPattern) && $className != $holder->getName()) { $inner = true; } } } $propertyClassName = $inner ? InnerMetaProperty::class : LightMetaProperty::class; if (empty($businessClassName)) { $businessClassName = $className; } if ($this->getType() instanceof IntegerType) { $size = $this->getType()->getSize(); } elseif ($this->getType() instanceof ObjectType && $this->getRelationId() == MetaRelation::ONE_TO_ONE && ($identifier = $this->getType()->getClass()->getIdentifier()) && $this->getType()->isMeasurable()) { $size = $identifier->getType()->getSize(); } elseif ($this->getType()->isMeasurable()) { $size = $this->size; } else { $size = null; } return call_user_func_array([$propertyClassName, 'fill'], [new $propertyClassName(), $this->getName(), $this->getName() != $this->getRelationColumnName() ? $this->getRelationColumnName() : null, $primitiveName, $businessClassName, $size, $this->isRequired(), $this->getType()->isGeneric(), $inner, $this->getRelationId(), $this->getFetchStrategyId()]); }