<?php declare(strict_types=1); namespace Xentral\Modules\GoogleCalendar\Data; use DateTime; use DateTimeInterface; use JsonSerializable; use Xentral\Modules\GoogleCalendar\Exception\InvalidArgumentException; final class GoogleCalendarEventData implements JsonSerializable { /** @var string STATUS_CONFIRMED */ public const STATUS_CONFIRMED = 'confirmed'; /** @var string STATUS_TENTATIVE */ public const STATUS_TENTATIVE = 'tentative'; /** @var string STATUS_CANCELLED */ public const STATUS_CANCELLED = 'cancelled'; /** @var string VISIBILITY_PUBLIC */ public const VISIBILITY_PUBLIC = 'public'; /** @var string VISIBILITY_PRIVATE */ public const VISIBILITY_PRIVATE = 'private'; /** @var string VISIBILITY_DEFAULT */ public const VISIBILITY_DEFAULT = 'default'; /** @var string TRANSPARENCY_OPAQUE */ public const TRANSPARENCY_OPAQUE = 'opaque'; /** @var string TRANSPARENCY_TRANSPARENT */ public const TRANSPARENCY_TRANSPARENT = 'transparent'; /** @var string $kind */ private static $kind = 'calendar#event'; /** @var string $id */ private $id; /** @var string $etag */ private $etag; /** @var string $status */ private $status; /** @var GoogleCalendarEventTimeValue $time */ private $time; /** @var string $iCalUid */ private $iCalUid; /** @var string $summary */ private $summary; /** @var string $description */ private $description; /** @var string $location */ private $location; /** @var string $colorId */ private $colorId; /** @var DateTime $created */ private $created; /** @var DateTime $updated */ private $updated; /** @var GoogleCalendarEventAttendeeValue $creator */ private $creator; /** @var GoogleCalendarEventAttendeeValue $organizer */ private $organizer; /** @var GoogleCalendarEventAttendeeValue[] $attendees */ private $attendees; /** @var string $visibility */ private $visibility; /** @var string $transparency */ private $transparency; /** @var GoogleCalendarEventReminderValue[] */ private $reminders; /** @var int $sequence */ private $sequence; /** @var string $htmlLink */ private $htmlLink; /** * @param string $id * @param string $etag * @param string $status * @param string $iCalUid * @param DateTimeInterface $created * @param DateTimeInterface $updated * @param GoogleCalendarEventAttendeeValue $creator * @param GoogleCalendarEventAttendeeValue $organizer * @param GoogleCalendarEventTimeValue $time * @param string $summary * @param string $description * @param string $location * @param GoogleCalendarEventAttendeeValue[] $attendees * @param GoogleCalendarEventReminderValue[] $reminders * @param string $visibility * @param string $transparency * @param int $sequence * @param string $colorId * @param string $htmlLink */ public function __construct( string $id, string $etag, string $status, string $iCalUid = '', DateTimeInterface $created = null, DateTimeInterface $updated = null, GoogleCalendarEventAttendeeValue $creator = null, GoogleCalendarEventAttendeeValue $organizer = null, GoogleCalendarEventTimeValue $time = null, string $summary = '', string $description = '', string $location = '', array $attendees = [], array $reminders = [], string $visibility = self::VISIBILITY_DEFAULT, string $transparency = self::TRANSPARENCY_OPAQUE, int $sequence = 0, string $colorId = '', string $htmlLink = '' ) { $this->id = $id; $this->etag = $etag; if ( $status !== self::STATUS_CONFIRMED && $status !== self::STATUS_TENTATIVE && $status !== self::STATUS_CANCELLED ) { throw new InvalidArgumentException( 'Invalid event status; only "confirmed", "tentative" and "cancelled" are allowed' ); } $this->status = $status; $this->iCalUid = $iCalUid; $this->summary = $summary; $this->description = $description; $this->location = $location; $this->colorId = $colorId; $this->created = $created; $this->updated = $updated; $this->creator = $creator; $this->organizer = $organizer; $this->attendees = $attendees; $this->time = $time; if ( $visibility !== self::VISIBILITY_DEFAULT && $visibility !== self::VISIBILITY_PRIVATE && $visibility !== self::VISIBILITY_PUBLIC ) { throw new InvalidArgumentException( 'Invalid event visibility; only "default", "private" or "public" are allowed' ); } $this->visibility = $visibility; if ($transparency !== self::TRANSPARENCY_OPAQUE && $transparency !== self::TRANSPARENCY_TRANSPARENT) { throw new InvalidArgumentException( 'Invalid event transparency; only "opaque" or "transparent" are allowed' ); } $this->transparency = $transparency; $this->reminders = $reminders; $this->sequence = $sequence; $this->htmlLink = $htmlLink; } /** * @param array $data * * @throws InvalidArgumentException * * @return GoogleCalendarEventData */ public static function fromArray(array $data): GoogleCalendarEventData { if (!isset($data['kind']) || $data['kind'] !== self::$kind) { throw new InvalidArgumentException('Invalid resource type. Expected: calendar#event'); } if (!isset($data['id'])) { throw new InvalidArgumentException('Missing required resorce field "id".'); } if (!isset($data['etag'])) { throw new InvalidArgumentException('Missing required resorce field "etag".'); } if (!isset($data['status'])) { throw new InvalidArgumentException('Missing required resorce field "etag".'); } //mandatory $id = $data['id']; $etag = $data['etag']; $status = $data['status']; //optional $iCalUid = ''; if (isset($data['iCalUID'])) { $iCalUid = $data['iCalUID']; } $created = null; if (isset($data['created'])) { $created = DateTime::createFromFormat('Y-m-d\TH:i:s.uP', $data['created']); if ($created === false) { throw new InvalidArgumentException('Invalid DateTime Format in "created".'); } } $updated = null; if (isset($data['updated'])) { $updated = DateTime::createFromFormat('Y-m-d\TH:i:s.uP', $data['updated']); if ($updated === false) { throw new InvalidArgumentException('Invalid DateTime Format in "updated".'); } } $creator = null; if (isset($data['creator'])) { $creator = GoogleCalendarEventAttendeeValue::createFromJsonArray($data['creator']); } $organizer = null; if (isset($data['organizer'])) { $organizer = GoogleCalendarEventAttendeeValue::createFromJsonArray($data['organizer']); } $time = null; if (isset($data['start'], $data['end'])) { $time = GoogleCalendarEventTimeValue::createFromJsonArray($data); } $sequence = 0; if (isset($data['sequence'])) { $sequence = $data['sequence']; } $summary = ''; if (isset($data['summary'])) { $summary = $data['summary']; } $description = ''; if (isset($data['description'])) { $description = $data['description']; } $location = ''; if (isset($data['location'])) { $location = $data['location']; } $visibility = self::VISIBILITY_DEFAULT; if (isset($data['visibility'])) { $visibility = $data['visibility']; } $transparency = self::TRANSPARENCY_OPAQUE; if (isset($data['transparency'])) { $transparency = $data['transparency']; } $colorId = ''; if (isset($data['colorId'])) { $colorId = $data['colorId']; } $htmlLink = ''; if (isset($data['htmlLink'])) { $htmlLink = $data['htmlLink']; } $attendees = []; if (isset($data['attendees']) && is_array($data['attendees'])) { foreach ($data['attendees'] as $attendee) { $attendees[] = GoogleCalendarEventAttendeeValue::createFromJsonArray($attendee); } } $reminders = []; if (isset($data['reminders']['overrides']) && is_array($data['reminders']['overrides'])) { foreach ($data['reminders']['overrides'] as $reminder) { $reminders[] = GoogleCalendarEventReminderValue::fromArray($reminder); } } return new self( $id, $etag, $status, $iCalUid, $created, $updated, $creator, $organizer, $time, $summary, $description, $location, $attendees, $reminders, $visibility, $transparency, $sequence, $colorId, $htmlLink ); } /** * @return array */ public function toArray(): array { $data = []; if ($this->getTime() !== null) { $time = $this->getTime()->toDataArray(); $data = array_merge($data, $time); } if ($this->getCreator() !== null) { $data['creator'] = $this->getCreator()->toDataArray(); } if ($this->getOrganizer() !== null) { $data['organizer'] = $this->getOrganizer()->toDataArray(); } $data['attendees'] = []; foreach ($this->getAttendees() as $attendee) { $data['attendees'][] = $attendee->toDataArray(); } $data['reminders']['overrides'] = []; foreach ($this->getReminders() as $reminder) { $data['reminders']['overrides'][] = $reminder->toArray(); } if ($this->getColorId() !== '') { $data['colorId'] = $this->getColorId(); } //$data['id'] = $this->getId(); $data['status'] = $this->getStatus(); //$data['iCalUid'] = $this->getICalUid(); $data['summary'] = $this->getSummary(); $data['description'] = $this->getDescription(); $data['location'] = $this->getLocation(); $data['visibility'] = $this->getVisibility(); $data['transparency'] = $this->getTransparency(); return $data; } /** * @return string */ public function getId(): string { return $this->id; } /** * @return string */ public function getEtag(): string { return $this->etag; } /** * @return string */ public function getStatus(): string { return $this->status; } /** * @return GoogleCalendarEventTimeValue */ public function getTime(): GoogleCalendarEventTimeValue { return $this->time; } /** * @return string */ public function getICalUid(): string { return $this->iCalUid; } /** * @return string */ public function getSummary(): string { return $this->summary; } /** * @return string */ public function getDescription(): string { return $this->description; } /** * @return string */ public function getLocation(): string { return $this->location; } /** * @return string */ public function getColorId(): string { return $this->colorId; } /** * @return DateTimeInterface */ public function getCreated(): DateTimeInterface { return $this->created; } /** * @return DateTimeInterface */ public function getUpdated(): DateTimeInterface { return $this->updated; } /** * @return GoogleCalendarEventAttendeeValue|null */ public function getCreator(): ?GoogleCalendarEventAttendeeValue { return $this->creator; } /** * @return GoogleCalendarEventAttendeeValue|null */ public function getOrganizer(): ?GoogleCalendarEventAttendeeValue { return $this->organizer; } /** * @return GoogleCalendarEventAttendeeValue[] */ public function getAttendees(): array { return $this->attendees; } /** * @return string */ public function getVisibility(): string { return $this->visibility; } /** * @return string */ public function getTransparency(): string { return $this->transparency; } /** * @return GoogleCalendarEventReminderValue[] */ public function getReminders(): array { return $this->reminders; } /** * @return int */ public function getSequence(): int { return $this->sequence; } /** * @return string */ public function getHtmlLink(): string { return $this->htmlLink; } /** * @param string $status * * @throws InvalidArgumentException * * @return GoogleCalendarEventData */ public function setStatus(string $status): GoogleCalendarEventData { if ( $status !== self::STATUS_CONFIRMED && $status !== self::STATUS_TENTATIVE && $status !== self::STATUS_CANCELLED ) { throw new InvalidArgumentException( 'Invalid event status; only "confirmed", "tentative" and "cancelled" are allowed.' ); } $eventData = $this->cloneDeep(); $eventData->status = $status; return $eventData; } /** * @param DateTimeInterface $beginning * @param DateTimeInterface $end * @param bool $wholeday * @param string $timezone * * @return GoogleCalendarEventData */ public function setTime( DateTimeInterface $beginning, DateTimeInterface $end, bool $wholeday = false, string $timezone = '' ): GoogleCalendarEventData { $time = new GoogleCalendarEventTimeValue($beginning, $end, $wholeday, $timezone); $eventData = $this->cloneDeep(); $eventData->time = $time; return $eventData; } /** * @param string $summary * * @return GoogleCalendarEventData */ public function setSummary(string $summary): GoogleCalendarEventData { $eventData = $this->cloneDeep(); $eventData->summary = $summary; return $eventData; } /** * @param string $description * * @return GoogleCalendarEventData */ public function setDescription(string $description): GoogleCalendarEventData { $eventData = $this->cloneDeep(); $eventData->description = $description; return $eventData; } /** * @param string $location * * @return GoogleCalendarEventData */ public function setLocation(string $location): GoogleCalendarEventData { $eventData = $this->cloneDeep(); $eventData->location = $location; return $eventData; } /** * @param string $colorId * * @return GoogleCalendarEventData */ public function setColorId(string $colorId): GoogleCalendarEventData { $eventData = $this->cloneDeep(); $eventData->colorId = $colorId; return $eventData; } /** * @param string $visibility * * @throws InvalidArgumentException * * @return GoogleCalendarEventData */ public function setVisibility(string $visibility): GoogleCalendarEventData { if ( $visibility !== self::VISIBILITY_DEFAULT && $visibility !== self::VISIBILITY_PRIVATE && $visibility !== self::VISIBILITY_PUBLIC ) { throw new InvalidArgumentException( 'Invalid event visibility; only "default", "private" or "public" are allowed' ); } $eventData = $this->cloneDeep(); $eventData->visibility = $visibility; return $eventData; } /** * @param string $transparency * * @throws InvalidArgumentException * * @return GoogleCalendarEventData */ public function setTransparency(string $transparency): GoogleCalendarEventData { if ($transparency !== self::TRANSPARENCY_OPAQUE && $transparency !== self::TRANSPARENCY_TRANSPARENT) { throw new InvalidArgumentException( 'Invalid event transparency; only "opaque" or "transparent" are allowed' ); } $eventData = $this->cloneDeep(); $eventData->transparency = $transparency; return $eventData; } /** * @param GoogleCalendarEventAttendeeValue|null $organizer * * @return GoogleCalendarEventData */ public function setOrganizer(GoogleCalendarEventAttendeeValue $organizer = null): GoogleCalendarEventData { $eventData = $this->cloneDeep(); $eventData->organizer = $organizer; return $eventData; } /** * @param string $email * @param string $displayName * @param bool $optional * * @return GoogleCalendarEventData */ public function addAttendee( string $email, string $displayName = '', bool $optional = false ): GoogleCalendarEventData { $attendee = new GoogleCalendarEventAttendeeValue($email, $displayName, $optional); $attendees = array_values($this->attendees); $attendees[] = $attendee; $eventData = $this->cloneDeep(); $eventData->attendees = $attendees; return $eventData; } /** * @return GoogleCalendarEventData */ public function removeAttendees(): GoogleCalendarEventData { $eventData = $this->cloneDeep(); $eventData->attendees = []; return $eventData; } /** * @param string $method * @param int $minutes * * @throws InvalidArgumentException * * @return GoogleCalendarEventData */ public function addReminder(string $method, int $minutes): GoogleCalendarEventData { $reminder = new GoogleCalendarEventReminderValue($method, $minutes); $reminders = array_values($this->reminders); $reminders[] = $reminder; $eventData = $this->cloneDeep(); $eventData->reminders = $reminders; return $eventData; } /** * @return GoogleCalendarEventData */ public function removeReminders(): GoogleCalendarEventData { $eventData = $this->cloneDeep(); $eventData->reminders = []; return $eventData; } /** * @return array */ public function jsonSerialize(): array { return $this->toArray(); } /** * @return GoogleCalendarEventData */ private function cloneDeep(): GoogleCalendarEventData { $time = $this->time; if ($this->time !== null) { $time = new GoogleCalendarEventTimeValue( $this->time->getBeginning(), $this->time->getEnd(), $this->time->isWholeday(), $this->time->getTimezone() ); } $created = null; if ($this->created !== null) { $created = clone $this->created; } $updated = null; if ($this->updated !== null) { $updated = clone $this->updated; } $creator = null; if ($this->creator !== null) { $creator = clone $this->creator; } $organizer = null; if ($this->organizer !== null) { $organizer = clone $this->organizer; } return new self( $this->id, $this->etag, $this->status, $this->iCalUid, $created, $updated, $creator, $organizer, $time, $this->summary, $this->description, $this->location, $this->attendees, $this->reminders, $this->visibility, $this->transparency, $this->sequence, $this->colorId, $this->htmlLink ); } }