|null */ public ?Collection $memberIds = null; public ?bool $billable = null; /** * @var Collection|null */ public ?Collection $clientIds = null; /** * @var Collection|null */ public ?Collection $projectIds = null; /** * @var Collection|null */ public ?Collection $tagIds = null; public ?string $tagMatchType = null; /** * @var Collection|null */ public ?Collection $taskIds = null; public ?TimeEntryRoundingType $roundingType = null; public ?int $roundingMinutes = null; /** * Get the caster class to use when casting from / to this cast target. * * @param array $arguments * @return CastsAttributes */ public static function castUsing(array $arguments): CastsAttributes { return new class implements CastsAttributes { private const array REQUIRED_PROPERTIES = [ 'group', 'subGroup', 'historyGroup', 'weekStart', 'timezone', 'start', 'end', 'active', 'memberIds', 'billable', 'clientIds', 'projectIds', 'tagIds', 'taskIds', ]; public function get(Model $model, string $key, mixed $value, array $attributes): ReportPropertiesDto { if (! is_string($value)) { throw new \InvalidArgumentException('The given value is not a string'); } $data = json_decode($value, false); if ($data === null) { throw new \InvalidArgumentException('The given value is not a JSON string'); } foreach (self::REQUIRED_PROPERTIES as $property) { if (! property_exists($data, $property)) { throw new \InvalidArgumentException('The given JSON string does not contain the required property "'.$property.'"'); } } $dto = new ReportPropertiesDto; $dto->end = $data->end !== null ? Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $data->end) : null; $dto->start = $data->start !== null ? Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $data->start) : null; $dto->active = $data->active; $dto->memberIds = $data->memberIds !== null ? ReportPropertiesDto::idArrayToCollection($data->memberIds) : null; $dto->billable = $data->billable; $dto->clientIds = $data->clientIds !== null ? ReportPropertiesDto::idArrayToCollection($data->clientIds) : null; $dto->projectIds = $data->projectIds !== null ? ReportPropertiesDto::idArrayToCollection($data->projectIds) : null; $dto->tagIds = $data->tagIds !== null ? ReportPropertiesDto::idArrayToCollection($data->tagIds) : null; $dto->tagMatchType = isset($data->tagMatchType) ? ReportPropertiesDto::tagMatchTypeValue($data->tagMatchType) : null; $dto->taskIds = $data->taskIds ? ReportPropertiesDto::idArrayToCollection($data->taskIds) : null; $dto->group = TimeEntryAggregationType::from($data->group); $dto->subGroup = TimeEntryAggregationType::from($data->subGroup); $dto->historyGroup = TimeEntryAggregationTypeInterval::from($data->historyGroup); $dto->weekStart = Weekday::from($data->weekStart); $dto->timezone = $data->timezone; // Note: roundingType was added later so it is possible that the value is missing in persisted reports in the DB $dto->roundingType = isset($data->roundingType) ? TimeEntryRoundingType::from($data->roundingType) : null; // Note: roundingMinutes was added later so it is possible that the value is missing in persisted reports in the DB $dto->roundingMinutes = isset($data->roundingMinutes) ? (int) $data->roundingMinutes : null; return $dto; } public function set(Model $model, string $key, mixed $value, array $attributes): string { if (! ($value instanceof ReportPropertiesDto)) { throw new \InvalidArgumentException('The given value is not an instance of ReportPropertiesDto'); } $data = (object) [ 'end' => $value->end->toIso8601ZuluString(), 'start' => $value->start->toIso8601ZuluString(), 'active' => $value->active, 'memberIds' => $value->memberIds?->toArray(), 'billable' => $value->billable, 'clientIds' => $value->clientIds?->toArray(), 'projectIds' => $value->projectIds?->toArray(), 'tagIds' => $value->tagIds?->toArray(), 'tagMatchType' => $value->tagMatchType, 'taskIds' => $value->taskIds?->toArray(), 'group' => $value->group->value, 'subGroup' => $value->subGroup->value, 'historyGroup' => $value->historyGroup->value, 'weekStart' => $value->weekStart->value, 'timezone' => $value->timezone, 'roundingType' => $value->roundingType?->value, 'roundingMinutes' => $value->roundingMinutes, ]; $jsonString = json_encode($data); if ($jsonString === false) { throw new \InvalidArgumentException('Could not encode the given data to a JSON string'); } return $jsonString; } }; } /** * @param array $ids * @return Collection */ public static function idArrayToCollection(array $ids): Collection { $collection = new Collection; foreach ($ids as $id) { if (! is_string($id)) { throw new \InvalidArgumentException('The given ID is not a string'); } if ($id !== TimeEntryFilter::NONE_VALUE && ! Str::isUuid($id)) { throw new \InvalidArgumentException('The given ID is not a valid UUID'); } $collection->push($id); } return $collection; } /** * @return 'contains'|'not_contains'|null */ public static function tagMatchTypeValue(mixed $tagMatchType): ?string { if ($tagMatchType === null) { return null; } if (! is_string($tagMatchType)) { throw new \InvalidArgumentException('The given tag match type is not a string'); } if (! in_array($tagMatchType, [TimeEntryFilter::TAG_MATCH_TYPE_CONTAINS, TimeEntryFilter::TAG_MATCH_TYPE_NOT_CONTAINS], true)) { throw new \InvalidArgumentException('The given tag match type is not valid'); } return $tagMatchType; } /** * @param array|null $memberIds */ public function setMemberIds(?array $memberIds): void { $this->memberIds = $memberIds !== null ? ReportPropertiesDto::idArrayToCollection($memberIds) : null; } /** * @param array|null $clientIds */ public function setClientIds(?array $clientIds): void { $this->clientIds = $clientIds !== null ? ReportPropertiesDto::idArrayToCollection($clientIds) : null; } /** * @param array|null $projectIds */ public function setProjectIds(?array $projectIds): void { $this->projectIds = $projectIds !== null ? ReportPropertiesDto::idArrayToCollection($projectIds) : null; } /** * @param array|null $tagIds */ public function setTagIds(?array $tagIds): void { $this->tagIds = $tagIds !== null ? ReportPropertiesDto::idArrayToCollection($tagIds) : null; } public function setTagMatchType(mixed $tagMatchType): void { $this->tagMatchType = ReportPropertiesDto::tagMatchTypeValue($tagMatchType); } /** * @param array|null $taskIds */ public function setTaskIds(?array $taskIds): void { $this->taskIds = $taskIds !== null ? ReportPropertiesDto::idArrayToCollection($taskIds) : null; } }