diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:38:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:38:04 +0000 |
commit | 1ff5c35de5dbd70a782875a91dd2232fd01b002b (patch) | |
tree | 77d9ce5e1bf78b3e6ef79f8f6e7861e2ced3c09b /vendor/ipl/orm/src/Relations.php | |
parent | Initial commit. (diff) | |
download | icinga-php-library-upstream/0.10.1.tar.xz icinga-php-library-upstream/0.10.1.zip |
Adding upstream version 0.10.1.upstream/0.10.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ipl/orm/src/Relations.php')
-rw-r--r-- | vendor/ipl/orm/src/Relations.php | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/vendor/ipl/orm/src/Relations.php b/vendor/ipl/orm/src/Relations.php new file mode 100644 index 0000000..340435f --- /dev/null +++ b/vendor/ipl/orm/src/Relations.php @@ -0,0 +1,212 @@ +<?php + +namespace ipl\Orm; + +use ArrayIterator; +use ipl\Orm\Exception\InvalidRelationException; +use ipl\Orm\Relation\BelongsTo; +use ipl\Orm\Relation\BelongsToMany; +use ipl\Orm\Relation\HasMany; +use ipl\Orm\Relation\HasOne; +use IteratorAggregate; +use Traversable; + +use function ipl\Stdlib\get_php_type; + +/** + * Collection of a model's relations. + */ +class Relations implements IteratorAggregate +{ + /** @var Relation[] */ + protected $relations = []; + + /** + * Get whether a relation with the given name exists + * + * @param string $name + * + * @return bool + */ + public function has($name) + { + return isset($this->relations[$name]); + } + + /** + * Get the relation with the given name + * + * @param string $name + * + * @return Relation + * + * @throws \InvalidArgumentException If the relation with the given name does not exist + */ + public function get($name) + { + $this->assertRelationExists($name); + + return $this->relations[$name]; + } + + /** + * Add the given relation to the collection + * + * @param Relation $relation + * + * @return $this + * + * @throws \InvalidArgumentException If a relation with the given name already exists + */ + public function add(Relation $relation) + { + $name = $relation->getName(); + + $this->assertRelationDoesNotYetExist($name); + + $this->relations[$name] = $relation; + + return $this; + } + + /** + * Create a new relation from the given class, name and target model class + * + * @param string $class Class of the relation to create + * @param string $name Name of the relation + * @param string $targetClass Target model class + * + * @return BelongsTo|BelongsToMany|HasMany|HasOne|Relation + * + * @throws \InvalidArgumentException If the target model class is not of type string + */ + public function create($class, $name, $targetClass) + { + $relation = new $class(); + + if (! $relation instanceof Relation) { + throw new \InvalidArgumentException(sprintf( + '%s() expects parameter 1 to be a subclass of %s, %s given', + __METHOD__, + Relation::class, + get_php_type($relation) + )); + } + + // Test target model + $target = new $targetClass(); + if (! $target instanceof Model) { + throw new \InvalidArgumentException(sprintf( + '%s() expects parameter 3 to be a subclass of %s, %s given', + __METHOD__, + Model::class, + get_php_type($target) + )); + } + + /** @var Relation $relation */ + $relation + ->setName($name) + ->setTarget($target) + ->setTargetClass($targetClass); + + return $relation; + } + + /** + * Define a one-to-one relationship + * + * @param string $name Name of the relation + * @param string $targetClass Target model class + * + * @return HasOne + */ + public function hasOne($name, $targetClass) + { + $relation = $this->create(HasOne::class, $name, $targetClass); + + $this->add($relation); + + return $relation; + } + + /** + * Define a one-to-many relationship + * + * @param string $name Name of the relation + * @param string $targetClass Target model class + * + * @return HasMany + */ + public function hasMany($name, $targetClass) + { + $relation = $this->create(HasMany::class, $name, $targetClass); + + $this->add($relation); + + return $relation; + } + + /** + * Define the inverse of a one-to-one or one-to-many relationship + * + * @param string $name Name of the relation + * @param string $targetClass Target model class + * + * @return BelongsTo + */ + public function belongsTo($name, $targetClass) + { + $relation = $this->create(BelongsTo::class, $name, $targetClass); + + $this->add($relation); + + return $relation; + } + + /** + * Define a many-to-many relationship + * + * @param string $name Name of the relation + * @param string $targetClass Target model class + * + * @return BelongsToMany + */ + public function belongsToMany($name, $targetClass) + { + $relation = $this->create(BelongsToMany::class, $name, $targetClass); + + $this->add($relation); + + return $relation; + } + + public function getIterator(): Traversable + { + return new ArrayIterator($this->relations); + } + + /** + * Throw exception if a relation with the given name already exists + * + * @param string $name + */ + protected function assertRelationDoesNotYetExist($name) + { + if ($this->has($name)) { + throw new \InvalidArgumentException("Relation '$name' already exists"); + } + } + + /** + * Throw exception if a relation with the given name does not exist + * + * @param string $name + */ + protected function assertRelationExists($name) + { + if (! $this->has($name)) { + throw new InvalidRelationException($name); + } + } +} |