123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- <?php declare(strict_types=1);
- namespace Grav\Framework\Relationships;
- use ArrayIterator;
- use Grav\Framework\Compat\Serializable;
- use Grav\Framework\Contracts\Object\IdentifierInterface;
- use Grav\Framework\Contracts\Relationships\ToManyRelationshipInterface;
- use Grav\Framework\Relationships\Traits\RelationshipTrait;
- use function count;
- use function is_callable;
- /**
- * Class ToManyRelationship
- *
- * @template T of IdentifierInterface
- * @template P of IdentifierInterface
- * @template-implements ToManyRelationshipInterface<T,P>
- */
- class ToManyRelationship implements ToManyRelationshipInterface
- {
- /** @template-use RelationshipTrait<T> */
- use RelationshipTrait;
- use Serializable;
- /** @var IdentifierInterface[] */
- protected $identifiers = [];
- /**
- * ToManyRelationship constructor.
- * @param string $name
- * @param IdentifierInterface $parent
- * @param iterable<IdentifierInterface> $identifiers
- */
- public function __construct(IdentifierInterface $parent, string $name, array $options, iterable $identifiers = [])
- {
- $this->parent = $parent;
- $this->name = $name;
- $this->parseOptions($options);
- $this->addIdentifiers($identifiers);
- $this->modified = false;
- }
- /**
- * @return string
- * @phpstan-pure
- */
- public function getCardinality(): string
- {
- return 'to-many';
- }
- /**
- * @return int
- * @phpstan-pure
- */
- public function count(): int
- {
- return count($this->identifiers);
- }
- /**
- * @return array
- */
- public function fetch(): array
- {
- $list = [];
- foreach ($this->identifiers as $identifier) {
- if (is_callable([$identifier, 'getObject'])) {
- $identifier = $identifier->getObject();
- }
- $list[] = $identifier;
- }
- return $list;
- }
- /**
- * @param string $id
- * @param string|null $type
- * @return bool
- * @phpstan-pure
- */
- public function has(string $id, string $type = null): bool
- {
- return $this->getIdentifier($id, $type) !== null;
- }
- /**
- * @param positive-int $pos
- * @return IdentifierInterface|null
- */
- public function getNthIdentifier(int $pos): ?IdentifierInterface
- {
- $items = array_keys($this->identifiers);
- $key = $items[$pos - 1] ?? null;
- if (null === $key) {
- return null;
- }
- return $this->identifiers[$key] ?? null;
- }
- /**
- * @param string $id
- * @param string|null $type
- * @return IdentifierInterface|null
- * @phpstan-pure
- */
- public function getIdentifier(string $id, string $type = null): ?IdentifierInterface
- {
- if (null === $type) {
- $type = $this->getType();
- }
- if ($type === 'media' && !str_contains($id, '/')) {
- $name = $this->name;
- $id = $this->parent->getType() . '/' . $this->parent->getId() . '/'. $name . '/' . $id;
- }
- $key = "{$type}/{$id}";
- return $this->identifiers[$key] ?? null;
- }
- /**
- * @param string $id
- * @param string|null $type
- * @return T|null
- */
- public function getObject(string $id, string $type = null): ?object
- {
- $identifier = $this->getIdentifier($id, $type);
- if ($identifier && is_callable([$identifier, 'getObject'])) {
- $identifier = $identifier->getObject();
- }
- return $identifier;
- }
- /**
- * @param IdentifierInterface $identifier
- * @return bool
- */
- public function addIdentifier(IdentifierInterface $identifier): bool
- {
- return $this->addIdentifiers([$identifier]);
- }
- /**
- * @param IdentifierInterface|null $identifier
- * @return bool
- */
- public function removeIdentifier(IdentifierInterface $identifier = null): bool
- {
- return !$identifier || $this->removeIdentifiers([$identifier]);
- }
- /**
- * @param iterable<IdentifierInterface> $identifiers
- * @return bool
- */
- public function addIdentifiers(iterable $identifiers): bool
- {
- foreach ($identifiers as $identifier) {
- $type = $identifier->getType();
- $id = $identifier->getId();
- $key = "{$type}/{$id}";
- $this->identifiers[$key] = $this->checkIdentifier($identifier);
- $this->modified = true;
- }
- return true;
- }
- /**
- * @param iterable<IdentifierInterface> $identifiers
- * @return bool
- */
- public function replaceIdentifiers(iterable $identifiers): bool
- {
- $this->identifiers = [];
- $this->modified = true;
- return $this->addIdentifiers($identifiers);
- }
- /**
- * @param iterable<IdentifierInterface> $identifiers
- * @return bool
- */
- public function removeIdentifiers(iterable $identifiers): bool
- {
- foreach ($identifiers as $identifier) {
- $type = $identifier->getType();
- $id = $identifier->getId();
- $key = "{$type}/{$id}";
- unset($this->identifiers[$key]);
- $this->modified = true;
- }
- return true;
- }
- /**
- * @return iterable<IdentifierInterface>
- * @phpstan-pure
- */
- public function getIterator(): iterable
- {
- return new ArrayIterator($this->identifiers);
- }
- /**
- * @return array
- */
- public function jsonSerialize(): array
- {
- $list = [];
- foreach ($this->getIterator() as $item) {
- $list[] = $item->jsonSerialize();
- }
- return $list;
- }
- /**
- * @return array
- */
- public function __serialize(): array
- {
- return [
- 'parent' => $this->parent,
- 'name' => $this->name,
- 'type' => $this->type,
- 'options' => $this->options,
- 'modified' => $this->modified,
- 'identifiers' => $this->identifiers,
- ];
- }
- /**
- * @param array $data
- * @return void
- */
- public function __unserialize(array $data): void
- {
- $this->parent = $data['parent'];
- $this->name = $data['name'];
- $this->type = $data['type'];
- $this->options = $data['options'];
- $this->modified = $data['modified'];
- $this->identifiers = $data['identifiers'];
- }
- }
|