public function toSetter(MetaClass $class, MetaClassProperty $property, MetaClassProperty $holder = null) { $name = $property->getName(); $methodName = 'set' . ucfirst($name); if ($holder) { return <<<EOT /** * @return {$holder->getClass()->getName()} **/ public function {$methodName}(\${$name}) { \t\$this->{$holder->getName()}->{$methodName}(\${$name}); \treturn \$this; } EOT; } else { return <<<EOT /** * @return {$class->getName()} **/ public function {$methodName}(\${$name}) { \t\$this->{$name} = \${$name}; \treturn \$this; } EOT; } }
public static function build(MetaClass $class) { $out = self::getHead(); $out .= <<<EOT namespace {$class->getNamespace()}; use Hesper\\Core\\Base\\Enum; EOT; if ($type = $class->getType()) { $type = "{$type->getName()} "; } else { $type = null; } $out .= <<<EOT {$type}class {$class->getName()} extends Enum { \t// implement me! \tprotected static \$names = []; } EOT; return $out . self::getHeel(); }
public static function build(MetaClass $class) { if (!$class->hasBuildableParent()) { return DictionaryDaoBuilder::build($class); } else { $parent = $class->getParent(); } if ($class->getParent()->getPattern() instanceof InternalClassPattern) { $parentName = 'StorableDAO'; $uses = StorableDAO::class; } else { $parentName = $parent->getName() . 'DAO'; $uses = "{$class->getDaoNamespace()}\\{$parentName}"; } $out = self::getHead(); $out .= <<<EOT namespace {$class->getAutoDaoNamespace()}; use {$uses}; EOT; $out .= <<<EOT abstract class Auto{$class->getName()}DAO extends {$parentName} { EOT; $out .= self::buildPointers($class) . "\n}\n"; return $out . self::getHeel(); }
public static function getClassOfMetaClass(MetaClass $class, $addBackslash = false) { if ($class->getPattern() instanceof InternalClassPattern) { throw new WrongArgumentException(); } else { return ($addBackslash ? '\\' : '') . $class->getNamespace() . '\\' . $class->getName(); } }
/** * @return RegistryClassPattern **/ public function build(MetaClass $class) { $userFile = $class->getPath() . $class->getName() . EXT_CLASS; if (MetaConfiguration::me()->isForcedGeneration() || !file_exists($userFile)) { $this->dumpFile($userFile, Format::indentize(RegistryClassBuilder::build($class))); } return $this; }
public function toSetter(MetaClass $class, MetaClassProperty $property, MetaClassProperty $holder = null) { $name = $property->getName(); $methodName = 'set' . ucfirst($name); $default = $property->isRequired() ? '' : ' = null'; if ($holder) { Assert::isUnreachable(); } else { return <<<EOT /** * @return {$class->getName()} **/ public function {$methodName}(array \${$name}{$default}) { \t\$this->{$name} = \${$name}; \treturn \$this; } EOT; } Assert::isUnreachable(); }
public static function generate(MetaClass $class) { if (!$class->doBuild()) { return null; } $out = ''; $out .= "class " . $class->getName(); $out .= " {\n"; foreach ($class->getProperties() as $property) { $out .= "+get" . ucfirst($property->getName()) . "()\n"; } $out .= "}\n"; if ($class->getParent()) { $out .= $class->getParent()->getName() . " <|-- " . $class->getName() . "\n"; } $out .= "\n"; return $out; }
private static function dumpMetaClass(MetaClass $class) { $propertyList = $class->getWithInternalProperties(); $out = <<<EOT \tprotected function makePropertyList() \t{ EOT; if ($class->hasBuildableParent()) { $out .= <<<EOT \t\treturn \t\t\tarray_merge( \t\t\t\tparent::makePropertyList(), \t\t\t\tarray( EOT; if ($class->getIdentifier()) { $propertyList[$class->getIdentifier()->getName()] = $class->getIdentifier(); } } else { $out .= <<<EOT \t\treturn array( EOT; } $list = []; foreach ($propertyList as $property) { $list[] = "'{$property->getName()}' => " . $property->toLightProperty($class)->toString(); } $out .= implode(",\n", $list); if ($class->hasBuildableParent()) { $out .= "\n)"; } $out .= <<<EOT \t\t); \t} EOT; return $out; }
public static function build(MetaClass $class) { $out = self::getHead(); if ($type = $class->getType()) { $typeName = $type->toString() . ' '; } else { $typeName = null; } $out .= <<<EOT namespace {$class->getProtoNamespace()}; use {$class->getAutoProtoClass()}; EOT; $out .= <<<EOT {$typeName}class Proto{$class->getName()} extends AutoProto{$class->getName()} {/*_*/} EOT; return $out . self::getHeel(); }
public static function build(MetaClass $class) { $out = self::getHead(); $uses = [StorableDAO::class]; if ($class->isSequenceless()) { $uses[] = SequencelessDAO::class; } $out .= <<<EOT namespace {$class->getAutoDaoNamespace()}; EOT; foreach ($uses as $import) { $out .= <<<EOT use {$import}; EOT; } $out .= <<<EOT abstract class Auto{$class->getName()}DAO extends StorableDAO EOT; if ($class->isSequenceless()) { $out .= ' implements SequencelessDAO'; } $out .= <<<EOT { EOT; $pointers = self::buildPointers($class); $out .= <<<EOT {$pointers} } EOT; return $out . self::getHeel(); }
public static function build(MetaClass $class) { $out = self::getHead(); $out .= <<<EOT namespace {$class->getDaoNamespace()}; use {$class->getAutoDaoClass()}; EOT; $type = $class->getType(); if ($type) { switch ($type->getId()) { case MetaClassType::CLASS_ABSTRACT: $abstract = 'abstract '; $notes = 'nothing here yet'; break; case MetaClassType::CLASS_FINAL: $abstract = 'final '; $notes = 'last chance for customization'; break; default: throw new WrongStateException('unknown class type'); } } else { $abstract = null; $notes = 'your brilliant stuff goes here'; } $out .= <<<EOT {$abstract}class {$class->getName()}DAO extends Auto{$class->getName()}DAO { \t// {$notes} } EOT; return $out . self::getHeel(); }
/** * @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()]); }
private static function doPropertyBuild(MetaClass $class, MetaClassProperty $property, $isNamed) { if ($parentProperty = $class->isRedefinedProperty($property->getName())) { // check wheter property fetch strategy becomes lazy if ($parentProperty->getFetchStrategyId() != $property->getFetchStrategyId() && $property->getFetchStrategyId() === FetchStrategy::LAZY) { return true; } return false; } if ($isNamed && $property->getName() == 'name') { return false; } if ($property->getName() == 'id' && !$property->getClass()->getParent()) { return false; } // do not redefine parent's properties if ($property->getClass()->getParent() && array_key_exists($property->getName(), $property->getClass()->getAllParentsProperties())) { return false; } return true; }
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; }
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; }
public function toDropper(MetaClass $class, MetaClassProperty $property, MetaClassProperty $holder = null) { if ($property->getRelationId() == MetaRelation::ONE_TO_MANY || $property->getRelationId() == MetaRelation::MANY_TO_MANY) { // we don't need dropper in such cases return null; } $name = $property->getName(); $methodName = 'drop' . ucfirst($name); if ($holder) { $method = <<<EOT /** * @return {$holder->getClass()->getName()} **/ public function {$methodName}() { \t\$this->{$holder->getName()}->{$methodName}(); \treturn \$this; } EOT; } else { if ($property->getFetchStrategyId() == FetchStrategy::LAZY) { $method = <<<EOT /** * @return {$class->getName()} **/ public function {$methodName}() { \t\$this->{$name} = null; \t\$this->{$name}Id = null; \treturn \$this; } EOT; } else { $method = <<<EOT /** * @return {$class->getName()} **/ public function {$methodName}() { \t\$this->{$name} = null; \treturn \$this; } EOT; } } return $method; }
/** * @return MetaConfiguration **/ private function checkClassSanity(MetaClass $class, \ReflectionClass $info) { switch ($class->getTypeId()) { case null: break; case MetaClassType::CLASS_ABSTRACT: Assert::isTrue($info->isAbstract(), 'class ' . $info->getName() . ' expected to be abstract'); Assert::isTrue($class->getPattern() instanceof AbstractClassPattern, 'class ' . $info->getName() . ' must use AbstractClassPattern'); break; case MetaClassType::CLASS_FINAL: Assert::isTrue($info->isFinal(), 'class ' . $info->getName() . ' expected to be final'); break; case MetaClassType::CLASS_SPOOKED: default: Assert::isUnreachable(); break; } if ($public = $info->getProperties(\ReflectionProperty::IS_PUBLIC)) { Assert::isUnreachable($class->getName() . ' contains properties with evil visibility:' . "\n" . print_r($public, true)); } return $this; }
public static function buildRelations(MetaClass $class) { $out = null; $knownJunctions = []; foreach ($class->getAllProperties() as $property) { if ($relation = $property->getRelation()) { $foreignClass = $property->getType()->getClass(); if ($relation->getId() == MetaRelation::ONE_TO_MANY || !$foreignClass->getPattern()->tableExists() || $class->getParent()) { continue; } elseif ($relation->getId() == MetaRelation::MANY_TO_MANY) { $tableName = $class->getTableName() . '_' . $foreignClass->getTableName(); if (isset($knownJunctions[$tableName])) { continue; } else { $knownJunctions[$tableName] = true; } $foreignPropery = clone $foreignClass->getIdentifier(); $name = $class->getName(); $name = strtolower($name[0]) . substr($name, 1); $name .= 'Id'; $foreignPropery->setName($name)->setColumnName($foreignPropery->getConvertedName())->setIdentifier(false); // we don't want any garbage in such tables $property = clone $property; $property->required(); // prevent name collisions if ($property->getRelationColumnName() == $foreignPropery->getColumnName()) { $foreignPropery->setColumnName($class->getTableName() . '_' . $property->getConvertedName() . '_id'); } $out .= <<<EOT \$schema-> \taddTable( \t\t\\Hesper\\Core\\OSQL\\DBTable::create('{$tableName}')-> \t\t{$property->toColumn()}-> \t\t{$foreignPropery->toColumn()}-> \t\taddUniques('{$property->getRelationColumnName()}', '{$foreignPropery->getColumnName()}') \t); EOT; } else { $sourceTable = $class->getTableName(); $sourceColumn = $property->getRelationColumnName(); $targetTable = $foreignClass->getTableName(); $targetColumn = $foreignClass->getIdentifier()->getColumnName(); $out .= <<<EOT // {$sourceTable}.{$sourceColumn} -> {$targetTable}.{$targetColumn} \$schema-> \tgetTableByName('{$sourceTable}')-> \t\tgetColumnByName('{$sourceColumn}')-> \t\t\tsetReference( \t\t\t\t\$schema-> \t\t\t\t\tgetTableByName('{$targetTable}')-> \t\t\t\t\tgetColumnByName('{$targetColumn}'), \t\t\t\t\\Hesper\\Core\\OSQL\\ForeignChangeAction::restrict(), \t\t\t\t\\Hesper\\Core\\OSQL\\ForeignChangeAction::cascade() \t\t\t); EOT; } } } return $out; }
public function toSetter(MetaClass $class, MetaClassProperty $property, MetaClassProperty $holder = null) { $name = $property->getName(); $methodName = 'set' . ucfirst($name); if ($holder) { return <<<EOT /** * @return {$holder->getClass()->getName()} **/ public function {$methodName}(\${$name}) { \t\$this->{$holder->getName()}->{$methodName}(\${$name}); \treturn \$this; } EOT; } else { if ($property->isRequired()) { $method = <<<EOT /** * @return {$class->getName()} **/ public function {$methodName}(\${$name} = false) { \t\$this->{$name} = (\${$name} === true); \treturn \$this; } EOT; } else { $method = <<<EOT /** * @return {$class->getName()} **/ public function {$methodName}(\${$name} = null) { \tAssert::isTernaryBase(\${$name}); \t \t\$this->{$name} = \${$name}; \treturn \$this; } EOT; } } return $method; }
public static function build(MetaClass $class) { $out = self::getHead(); $uses = [Singleton::class, $class->getAutoBusinessClass()]; if ($type = $class->getType()) { $typeName = $type->toString() . ' '; } else { $typeName = null; } $interfaces = ' implements Prototyped'; $uses[] = Prototyped::class; $uses[] = $class->getProtoClass(); if ($class->getPattern()->daoExists() && !$class->getPattern() instanceof AbstractClassPattern) { $interfaces .= ', DAOConnected'; $uses[] = DAOConnected::class; $daoName = $class->getName() . 'DAO'; $uses[] = $class->getDaoClass(); $dao = <<<EOT \t/** \t * @return {$daoName} \t**/ \tpublic static function dao() \t{ \t\treturn Singleton::getInstance({$daoName}::class); \t} EOT; } else { $dao = null; } $out .= <<<EOT namespace {$class->getNamespace()}; EOT; foreach ($uses as $import) { $out .= <<<EOT use {$import}; EOT; } $out .= <<<EOT {$typeName}class {$class->getName()} extends Auto{$class->getName()}{$interfaces} { EOT; if (!$type || $type->getId() !== MetaClassType::CLASS_ABSTRACT) { $customCreate = null; if ($class->getFinalParent()->getPattern() instanceof InternalClassPattern) { $parent = $class; while ($parent = $parent->getParent()) { $info = new \ReflectionClass('\\' . $parent->getNamespace() . '\\' . $parent->getName()); if ($info->hasMethod('create') && $info->getMethod('create')->getParameters() > 0) { $customCreate = true; break; } } } if ($customCreate) { $creator = $info->getMethod('create'); $declaration = []; foreach ($creator->getParameters() as $parameter) { $declaration[] = '$' . $parameter->getName() . ' = ' . ($parameter->getDefaultValue() ? $parameter->getDefaultValue() : 'null'); } $declaration = implode(', ', $declaration); $out .= <<<EOT \t/** \t * @return {$class->getName()} \t**/ \tpublic static function create({$declaration}) \t{ \t\treturn new self({$declaration}); \t} \t\t EOT; } else { $out .= <<<EOT \t/** \t * @return {$class->getName()} \t**/ \tpublic static function create() \t{ \t\treturn new self; \t} \t\t EOT; } $protoName = 'Proto' . $class->getName(); $out .= <<<EOT {$dao} \t/** \t * @return {$protoName} \t**/ \tpublic static function proto() \t{ \t\treturn Singleton::getInstance({$protoName}::class); \t} EOT; } $out .= <<<EOT \t// your brilliant stuff goes here } EOT; return $out . self::getHeel(); }
/** * @return BasePattern **/ protected function buildDao(MetaClass $class) { $this->dumpFile(HESPER_META_AUTO_DAO_DIR . 'Auto' . $class->getName() . 'DAO' . EXT_CLASS, Format::indentize(AutoDaoBuilder::build($class))); $userFile = HESPER_META_DAO_DIR . $class->getName() . 'DAO' . EXT_CLASS; if (MetaConfiguration::me()->isForcedGeneration() || !file_exists($userFile)) { $this->dumpFile($userFile, Format::indentize(DaoBuilder::build($class))); } return $this; }