Пример #1
0
    /**
     * @return MetaConfiguration
     **/
    private function processClasses(\SimpleXMLElement $xml, $metafile, $generate)
    {
        $attrs = $xml->classes->attributes();
        if (!isset($attrs['namespace'])) {
            throw new WrongStateException('Element classes should contain a `namespace` attribute');
        }
        $namespace = strval($attrs['namespace']);
        foreach ($xml->classes[0] as $xmlClass) {
            $name = (string) $xmlClass['name'];
            Assert::isFalse(isset($this->classes[$name]), 'class name collision found for ' . $name);
            $class = new MetaClass($name, $namespace);
            if (isset($xmlClass['source'])) {
                $class->setSourceLink((string) $xmlClass['source']);
            }
            if (isset($xmlClass['table'])) {
                $class->setTableName((string) $xmlClass['table']);
            }
            if (isset($xmlClass['type'])) {
                $type = (string) $xmlClass['type'];
                if ($type == 'spooked') {
                    $this->getOutput()->warning($class->getName(), true)->warningLine(': uses obsoleted "spooked" type.')->newLine();
                }
                $class->setType(new MetaClassType((string) $xmlClass['type']));
            }
            // lazy existence checking
            if (isset($xmlClass['extends'])) {
                $this->liaisons[$class->getName()] = (string) $xmlClass['extends'];
            }
            // populate implemented interfaces
            foreach ($xmlClass->implement as $xmlImplement) {
                $class->addInterface((string) $xmlImplement['interface']);
            }
            if (isset($xmlClass->properties[0]->identifier)) {
                $id = $xmlClass->properties[0]->identifier;
                if (!isset($id['name'])) {
                    $name = 'id';
                } else {
                    $name = (string) $id['name'];
                }
                if (!isset($id['type'])) {
                    $type = 'BigInteger';
                } else {
                    $type = (string) $id['type'];
                }
                $property = $this->makeProperty($name, $type, $class, (string) $id['size']);
                if (isset($id['column'])) {
                    $property->setColumnName((string) $id['column']);
                } elseif ($property->getType() instanceof ObjectType && !$property->getType()->isGeneric()) {
                    $property->setColumnName($property->getConvertedName() . '_id');
                } else {
                    $property->setColumnName($property->getConvertedName());
                }
                $property->setIdentifier(true)->required();
                $class->addProperty($property);
                unset($xmlClass->properties[0]->identifier);
            }
            $class->setPattern($this->guessPattern((string) $xmlClass->pattern['name']));
            if ((string) $xmlClass->pattern['fetch'] == 'cascade') {
                $class->setFetchStrategy(FetchStrategy::cascade());
            }
            if ($class->getPattern() instanceof InternalClassPattern) {
                Assert::isTrue($metafile === HESPER_META . 'internal.xml', 'internal classes can be defined only in onPHP, sorry');
            } elseif ($class->getPattern() instanceof SpookedClassPattern || $class->getPattern() instanceof SpookedEnumerationPattern || $class->getPattern() instanceof SpookedEnumPattern || $class->getPattern() instanceof SpookedRegistryPattern) {
                $class->setType(new MetaClassType(MetaClassType::CLASS_SPOOKED));
            }
            // populate properties
            foreach ($xmlClass->properties[0] as $xmlProperty) {
                $property = $this->makeProperty((string) $xmlProperty['name'], (string) $xmlProperty['type'], $class, (string) $xmlProperty['size']);
                if (isset($xmlProperty['column'])) {
                    $property->setColumnName((string) $xmlProperty['column']);
                } elseif ($property->getType() instanceof ObjectType && !$property->getType()->isGeneric()) {
                    if (isset($this->classes[$property->getType()->getClassName()]) && $property->getType()->getClass()->getPattern() instanceof InternalClassPattern) {
                        throw new UnimplementedFeatureException('you can not use internal classes directly atm');
                    }
                    $property->setColumnName($property->getConvertedName() . '_id');
                } else {
                    $property->setColumnName($property->getConvertedName());
                }
                if ((string) $xmlProperty['required'] == 'true') {
                    $property->required();
                }
                if (isset($xmlProperty['identifier'])) {
                    throw new WrongArgumentException('obsoleted identifier description found in ' . "{$class->getName()} class;\n" . 'you must use <identifier /> instead.');
                }
                if (!$property->getType()->isGeneric() && !$class->getPattern() instanceof ValueObjectPattern) {
                    if (!isset($xmlProperty['relation'])) {
                        throw new MissingElementException('relation should be set for non-generic ' . "property '{$property->getName()}' type '" . get_class($property->getType()) . "'" . " of '{$class->getName()}' class");
                    } else {
                        $property->setRelation(MetaRelation::makeFromName((string) $xmlProperty['relation']));
                        if ($fetch = (string) $xmlProperty['fetch']) {
                            Assert::isTrue($property->getRelationId() == MetaRelation::ONE_TO_ONE, 'fetch mode can be specified
									only for OneToOne relations');
                            if ($fetch == 'lazy') {
                                $property->setFetchStrategy(FetchStrategy::lazy());
                            } elseif ($fetch == 'cascade') {
                                $property->setFetchStrategy(FetchStrategy::cascade());
                            } else {
                                throw new WrongArgumentException('strange fetch mode found - ' . $fetch);
                            }
                        }
                        if ($property->getRelationId() == MetaRelation::ONE_TO_ONE && $property->getFetchStrategyId() != FetchStrategy::LAZY && $property->getType()->getClassName() != $class->getName()) {
                            $this->references[$property->getType()->getClassName()][] = $class->getName();
                        }
                    }
                }
                if (isset($xmlProperty['default'])) {
                    // will be correctly autocasted further down the code
                    $property->getType()->setDefault((string) $xmlProperty['default']);
                }
                $class->addProperty($property);
            }
            $class->setBuild($generate);
            $this->classes[$class->getName()] = $class;
        }
        return $this;
    }