* @deprecated Please, use oat\oatbox\reporting\Report::class. */ class common_report_Report implements ReportInterface { /** * Type of the report * * @var string */ private $type; /** * Message of the report * * @var string */ private $message; /** * Elements of the report * * @var array */ private $children = []; /** * Attached to the report data * * @var mixed */ private $data; /** * Report constructor. * * @param string $type * @param string $message * @param null $data * @param array $children * * @throws common_exception_Error */ public function __construct(string $type, string $message = '', $data = null, array $children = []) { if (!self::isValidType($type)) { throw new OutOfBoundsException(sprintf('Type of the report `%s` is unsupported for creation', $type)); } $this->type = $type; $this->message = $message; $this->data = $data; foreach ($children as $child) { $this->add($child); } } /** * Covers static helpers by the next template: Report::create * * @param string $name * @param array $arguments * * @return Report * @throws common_exception_Error */ public static function __callStatic(string $name, array $arguments): self { if (strpos($name, 'create') !== 0) { throw new BadMethodCallException(sprintf('Requested method `%s` is not found or is not allowed in class %s', $name, __CLASS__)); } $type = strtolower(str_replace('create', '', $name)); if (!self::isValidType($type)) { throw new OutOfBoundsException(sprintf('Type of the report `%s` is unsupported for creation', $type)); } return new static($type, ...$arguments); } /** * Covers helpers (methods) by defined templates * * @param string $name * @param array $arguments * * @return bool|array */ public function __call(string $name, array $arguments) { /** Covers methods by template: get[e]s */ if (0 === strpos($name, 'get')) { return $this->handleGetCalls($name, $arguments); } /** Covers methods by template: contains */ if (0 === strpos($name, 'contains')) { return $this->handleContainsCalls($name, $arguments); } throw new BadMethodCallException(sprintf('Requested method `%s` is not found or is not allowed in class %s', $name, __CLASS__)); } /** * Get message of the report * * @return string */ public function getMessage(): string { return $this->message; } /** * Update message of the report * * @param string $message * * @return Report */ public function setMessage(string $message): self { $this->message = $message; return $this; } /** * Return type of the report * * @return string */ public function getType(): string { return $this->type; } /** * Update type of the report * * @param string $type * * @return Report */ public function setType(string $type): self { $this->type = $type; return $this; } /** * Return attached data * * @return mixed|null */ public function getData() { return $this->data; } /** * Attach data to the report * * @param mixed|null $data * * @return $this */ public function setData($data): self { $this->data = $data; return $this; } /** * Whenever or not there are child reports * * @return boolean */ public function hasChildren(): bool { return count($this->children) > 0; } /** * Return child reports * * @return array */ public function getChildren(): array { return $this->children; } /** * Add something (children) to the report * * @param mixed $mixed accepts single values and arrays of Reports and UserReadableExceptions * * @return Report * * @throws common_exception_Error */ public function add($mixed): self { $mixedArray = is_array($mixed) ? $mixed : [$mixed]; foreach ($mixedArray as $element) { if ($element instanceof self) { $this->children[] = $element; } elseif ($element instanceof UserReadableException) { $this->children[] = new static(self::TYPE_ERROR, $element->getUserMessage()); } else { throw new common_exception_Error('Tried to add ' . (is_object($element) ? get_class($element) : gettype($element)) . ' to the report'); } } return $this; } /** * Whenever or not the type can be found in the report * * @param string $type * * @return boolean */ public function contains(string $type): bool { foreach ($this as $child) { if ($child->getType() === $type || $child->contains($type)) { return true; } } return false; } /** * Returns all children based on type * * @param array $types * @param bool $asFlat * * @return array */ public function filterChildrenByTypes(array $types, $asFlat = false): array { $iterator = true === $asFlat ? $this->getRecursiveIterator() : $this; $found = []; foreach ($iterator as $element) { if (in_array($element->getType(), $types, true)) { $found[] = $element; } } return $found; } /** * Returns an iterator over the children */ public function getIterator(): ArrayIterator { return new ArrayIterator($this->getChildren()); } /** * User feedback message */ public function __toString(): string { return $this->getMessage(); } /** * Recursively restores report object from json string or array * * @param string|array $data * * @return self|null * * @throws common_exception_Error */ public static function jsonUnserialize($data): ?self { if (!is_array($data)) { $data = (array) json_decode((string) $data, true); } if (count(array_intersect(['type', 'message', 'data'], array_keys($data))) !== 3) { return null; } $report = new static($data['type'], $data['message'], $data['data']); $data['children'] = (!isset($data['children']) || !is_array($data['children'])) ? [] : $data['children']; foreach ($data['children'] as $child) { $report->add(static::jsonUnserialize($child)); } return $report; } /** * Prepares object data for valid converting to json */ public function jsonSerialize(): array { return [ 'type' => $this->getType(), 'message' => $this->getMessage(), 'data' => $this->getData(), 'children' => $this->getChildren() ]; } /** * Returns array representation of the report, recursively */ public function toArray(): array { return array_merge($this->jsonSerialize(), [ 'children' => array_map(static function (self $report) { return $report->toArray(); }, $this->children) ]); } /** * Convenience method to create a simple failure report * * @param string $message * @param mixed $errors * @param null $data * * @return Report * @throws common_exception_Error * @deprecated Please, use `createError` method instead */ public static function createFailure(string $message, array $errors = [], $data = null): self { return new static(self::TYPE_ERROR, $message, $data, $errors); } private function handleGetCalls(string $name, array $arguments): array { $type = strtolower(str_replace('get', '', $name)); $type = rtrim(substr($type, 0, -1), 'e'); if (!self::isValidType($type)) { throw new OutOfBoundsException(sprintf('Type of report `%s` is unsupported', $type)); } return $this->filterChildrenByTypes([$type], ...$arguments); } private function handleContainsCalls(string $name, array $arguments): bool { $type = strtolower(str_replace('contains', '', $name)); if (!self::isValidType($type)) { throw new OutOfBoundsException(sprintf('Type of report `%s` is unsupported', $type)); } return $this->contains($type); } private function getRecursiveIterator(): RecursiveIteratorIterator { return new RecursiveIteratorIterator( new RecursiveReportIterator($this->getIterator()), RecursiveIteratorIterator::SELF_FIRST ); } private static function isValidType(string $type): bool { return in_array($type, static::ALLOWED_TYPES); } }