/** * @param EntityMetadata[] $metadata * @param IModel $model */ public function validate(array $metadata, IModel $model) { $pairs = [PropertyMetadata::RELATIONSHIP_MANY_HAS_MANY => PropertyMetadata::RELATIONSHIP_MANY_HAS_MANY, PropertyMetadata::RELATIONSHIP_MANY_HAS_ONE => PropertyMetadata::RELATIONSHIP_ONE_HAS_MANY, PropertyMetadata::RELATIONSHIP_ONE_HAS_MANY => PropertyMetadata::RELATIONSHIP_MANY_HAS_ONE, PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE => PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE, PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE_DIRECTED => PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE_DIRECTED]; foreach ($metadata as $entityMeta) { foreach ($entityMeta->getProperties() as $propertyMeta) { if (!$propertyMeta->relationshipType) { continue; } $repositoryName = $propertyMeta->relationshipRepository; if (!$model->hasRepository($repositoryName)) { throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} points to unknown '{$propertyMeta->relationshipRepository}' repository."); } $symetricEntityMeta = $metadata[$repositoryName::getEntityClassNames()[0]]; if (!$symetricEntityMeta->hasProperty($propertyMeta->relationshipProperty)) { throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} has not defined a symetric relationship in {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty}."); } /** @var PropertyMetadata $symetricPropertyMeta */ $symetricPropertyMeta = $symetricEntityMeta->getProperty($propertyMeta->relationshipProperty); if ($propertyMeta->name !== $symetricPropertyMeta->relationshipProperty) { throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} relationship with {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty} is not transitive."); } if ($symetricPropertyMeta->relationshipType === NULL) { throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} has not defined a symetric relationship in {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty}."); } if ($symetricPropertyMeta->relationshipType !== $pairs[$propertyMeta->relationshipType]) { throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} has not defined a propper reverse relationship type in {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty}."); } if ($propertyMeta->relationshipType === PropertyMetadata::RELATIONSHIP_MANY_HAS_MANY || $propertyMeta->relationshipType === PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE_DIRECTED) { if ($propertyMeta->relationshipIsMain && $symetricPropertyMeta->relationshipIsMain) { throw new InvalidStateException("Only one side of relationship {$entityMeta->className}::\${$propertyMeta->name} × {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty} could be defined as a primary."); } elseif (!$propertyMeta->relationshipIsMain && !$symetricPropertyMeta->relationshipIsMain) { throw new InvalidStateException("At least one side of relationship {$entityMeta->className}::\${$propertyMeta->name} × {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty} has to be defined as a primary."); } } } } }