*/ class ToOneRelationship implements ToOneRelationshipInterface { /** @template-use RelationshipTrait */ use RelationshipTrait; use Serializable; /** @var IdentifierInterface|null */ protected $identifier = null; public function __construct(IdentifierInterface $parent, string $name, array $options, IdentifierInterface $identifier = null) { $this->parent = $parent; $this->name = $name; $this->parseOptions($options); $this->replaceIdentifier($identifier); $this->modified = false; } /** * @return string * @phpstan-pure */ public function getCardinality(): string { return 'to-one'; } /** * @return int * @phpstan-pure */ public function count(): int { return $this->identifier ? 1 : 0; } /** * @return object|null */ public function fetch(): ?object { $identifier = $this->identifier; if (is_callable([$identifier, 'getObject'])) { $identifier = $identifier->getObject(); } return $identifier; } /** * @param string|null $id * @param string|null $type * @return bool * @phpstan-pure */ public function has(string $id = null, string $type = null): bool { return $this->getIdentifier($id, $type) !== null; } /** * @param string|null $id * @param string|null $type * @return IdentifierInterface|null * @phpstan-pure */ public function getIdentifier(string $id = null, string $type = null): ?IdentifierInterface { if ($id && $this->getType() === 'media' && !str_contains($id, '/')) { $name = $this->name; $id = $this->parent->getType() . '/' . $this->parent->getId() . '/'. $name . '/' . $id; } $identifier = $this->identifier ?? null; if (null === $identifier || ($type && $type !== $identifier->getType()) || ($id && $id !== $identifier->getId())) { return null; } return $identifier; } /** * @param string|null $id * @param string|null $type * @return T|null */ public function getObject(string $id = null, 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 { $this->identifier = $this->checkIdentifier($identifier); $this->modified = true; return true; } /** * @param IdentifierInterface|null $identifier * @return bool */ public function replaceIdentifier(IdentifierInterface $identifier = null): bool { if ($identifier === null) { $this->identifier = null; $this->modified = true; return true; } return $this->addIdentifier($identifier); } /** * @param IdentifierInterface|null $identifier * @return bool */ public function removeIdentifier(IdentifierInterface $identifier = null): bool { if (null === $identifier || $this->has($identifier->getId(), $identifier->getType())) { $this->identifier = null; $this->modified = true; return true; } return false; } /** * @return iterable * @phpstan-pure */ public function getIterator(): iterable { return new ArrayIterator((array)$this->identifier); } /** * @return array|null */ public function jsonSerialize(): ?array { return $this->identifier ? $this->identifier->jsonSerialize() : null; } /** * @return array */ public function __serialize(): array { return [ 'parent' => $this->parent, 'name' => $this->name, 'type' => $this->type, 'options' => $this->options, 'modified' => $this->modified, 'identifier' => $this->identifier, ]; } /** * @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->identifier = $data['identifier']; } }