diff --git a/administrator/components/com_media/src/Event/FetchMediaFileEvent.php b/administrator/components/com_media/src/Event/FetchMediaFileEvent.php index c42d53e5af60c..1d4ae9c0749ec 100644 --- a/administrator/components/com_media/src/Event/FetchMediaFileEvent.php +++ b/administrator/components/com_media/src/Event/FetchMediaFileEvent.php @@ -11,57 +11,155 @@ \defined('_JEXEC') or die; -use Joomla\CMS\Event\AbstractEvent; +use BadMethodCallException; +use Joomla\CMS\Date\Date; +use Joomla\CMS\Event\AbstractImmutableEvent; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Text; /** * Event object for fetch media file. * * @since __DEPLOY_VERSION__ */ -class FetchMediaFileEvent extends AbstractEvent +final class FetchMediaFileEvent extends AbstractImmutableEvent { - /** - * @var \stdClass - * @since __DEPLOY_VERSION__ - */ - private $file; - /** * Constructor. * - * @param string $name The event name. - * @param \stdClass $file The file. + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @throws BadMethodCallException * * @since __DEPLOY_VERSION__ */ - public function __construct($name, \stdClass $file) + public function __construct($name, array $arguments = array()) { - parent::__construct($name, []); + parent::__construct($name, $arguments); - $this->file = $file; + // Check for required arguments + if (!\array_key_exists('file', $arguments) || !is_object($arguments['file'])) + { + throw new BadMethodCallException("Argument 'file' of event $name is not of the expected type"); + } } /** - * Returns the event file. + * Validate $value to have all attributes with a valid type * - * @return \stdClass + * Validation based on \Joomla\Component\Media\Administrator\Adapter\AdapterInterface::getFile() * - * @since __DEPLOY_VERSION__ - */ - public function getFile(): \stdClass - { - return $this->file; - } - - /** - * Sets the event file. + * Properties validated: + * - type: The type can be file or dir + * - name: The name of the file + * - path: The relative path to the root + * - extension: The file extension + * - size: The size of the file + * - create_date: The date created + * - modified_date: The date modified + * - mime_type: The mime type + * - width: The width, when available + * - height: The height, when available * - * @param \stdClass $file The file. + * Generation based on \Joomla\Plugin\Filesystem\Local\Adapter\LocalAdapter::getPathInformation() * - * @since __DEPLOY_VERSION__ + * Properties generated: + * - created_date_formatted: DATE_FORMAT_LC5 formatted string based on create_date + * - modified_date_formatted: DATE_FORMAT_LC5 formatted string based on modified_date + * + * @param \stdClass $value The value to set + * + * @return \stdClass + * + * @since __DEPLOY_VERSION__ + * + * @throws BadMethodCallException */ - public function setFile(\stdClass $file): void + protected function setFile(\stdClass $value): \stdClass { - $this->file = $file; + // Make immutable object + $value = clone $value; + + // Only "dir" or "file" is allowed + if (!isset($value->type) || ($value->type !== 'dir' && $value->type !== 'file')) + { + throw new BadMethodCallException("Property 'type' of argument 'file' of event {$this->name} has a wrong value. Valid: 'dir' or 'file'"); + } + + // Non empty string + if (empty($value->name) || !is_string($value->name)) + { + throw new BadMethodCallException("Property 'name' of argument 'file' of event {$this->name} has a wrong value. Valid: non empty string"); + } + + // Non empty string + if (empty($value->path) || !is_string($value->path)) + { + throw new BadMethodCallException("Property 'path' of argument 'file' of event {$this->name} has a wrong value. Valid: non empty string"); + } + + // A string + if (!isset($value->extension) || !is_string($value->extension)) + { + throw new BadMethodCallException("Property 'extension' of argument 'file' of event {$this->name} has a wrong value. Valid: string"); + } + + // An empty string or an integer + if (!isset($value->size) || + (!is_integer($value->size) && !is_string($value->size)) || + (is_string($value->size) && $value->size !== '') + ) + { + throw new BadMethodCallException("Property 'size' of argument 'file' of event {$this->name} has a wrong value. Valid: empty string or integer"); + } + + // A string + if (!isset($value->mime_type) || !is_string($value->mime_type)) + { + throw new BadMethodCallException("Property 'mime_type' of argument 'file' of event {$this->name} has a wrong value. Valid: string"); + } + + // An integer + if (!isset($value->width) || !is_integer($value->width)) + { + throw new BadMethodCallException("Property 'width' of argument 'file' of event {$this->name} has a wrong value. Valid: integer"); + } + + // An integer + if (!isset($value->height) || !is_integer($value->height)) + { + throw new BadMethodCallException("Property 'height' of argument 'file' of event {$this->name} has a wrong value. Valid: integer"); + } + + // A ISO 8601 date string + if (empty($value->create_date)) { + throw new BadMethodCallException("Property 'create_date' of argument 'file' of event {$this->name} has a wrong value. Valid: ISO 8601 date string"); + } + + // Validate date format + $date = Date::createFromFormat(\DATE_ISO8601, $value->create_date); + if (!$date) { + throw new BadMethodCallException("Property 'create_date' of argument 'file' of event {$this->name} has a wrong value. Valid: ISO 8601 date string"); + } + + // Create formated string based on \Joomla\Plugin\Filesystem\Local\Adapter\LocalAdapter::getPathInformation() + $value->create_date_formatted = HTMLHelper::_('date', $date, Text::_('DATE_FORMAT_LC5')); + + // A ISO 8601 date string + if (empty($value->modified_date)) { + throw new BadMethodCallException("Property 'modified_date' of argument 'file' of event {$this->name} has a wrong value. Valid: ISO 8601 date string"); + } + + // Validate date format + $date = Date::createFromFormat(\DATE_ISO8601, $value->modified_date); + if (!$date) { + throw new BadMethodCallException("Property 'modified_date' of argument 'file' of event {$this->name} has a wrong value. Valid: ISO 8601 date string"); + } + + // Create formated string based on \Joomla\Plugin\Filesystem\Local\Adapter\LocalAdapter::getPathInformation() + $value->modified_date_formatted = HTMLHelper::_('date', $date, Text::_('DATE_FORMAT_LC5')); + + return $value; } } diff --git a/administrator/components/com_media/src/Event/FetchMediaFileUrlEvent.php b/administrator/components/com_media/src/Event/FetchMediaFileUrlEvent.php index a79a0eeef516e..afcdf18985da0 100644 --- a/administrator/components/com_media/src/Event/FetchMediaFileUrlEvent.php +++ b/administrator/components/com_media/src/Event/FetchMediaFileUrlEvent.php @@ -11,57 +11,94 @@ \defined('_JEXEC') or die; -use Joomla\CMS\Event\AbstractEvent; +use BadMethodCallException; +use Joomla\CMS\Event\AbstractImmutableEvent; /** * Event object to set an url. * * @since __DEPLOY_VERSION__ */ -class FetchMediaFileUrlEvent extends AbstractEvent +final class FetchMediaFileUrlEvent extends AbstractImmutableEvent { - /** - * @var string - * @since __DEPLOY_VERSION__ - */ - private $url; - /** * Constructor. * - * @param string $name The event name. - * @param string $url The url. + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @throws BadMethodCallException * * @since __DEPLOY_VERSION__ */ - public function __construct($name, string $url) + public function __construct($name, array $arguments = array()) { - parent::__construct($name, []); + // Check for required arguments + if (!\array_key_exists('adapter', $arguments) || !is_string($arguments['adapter'])) + { + throw new BadMethodCallException("Argument 'adapter' of event $name is not of the expected type"); + } + + $this->arguments[$arguments['adapter']] = $arguments['adapter']; + unset($arguments['adapter']); - $this->url = $url; + // Check for required arguments + if (!\array_key_exists('path', $arguments) || !is_string($arguments['path'])) + { + throw new BadMethodCallException("Argument 'path' of event $name is not of the expected type"); + } + + $this->arguments[$arguments['path']] = $arguments['path']; + unset($arguments['path']); + + // Check for required arguments + if (!\array_key_exists('url', $arguments) || !is_string($arguments['url'])) + { + throw new BadMethodCallException("Argument 'url' of event $name is not of the expected type"); + } + + parent::__construct($name, $arguments); } /** - * Returns the event url. + * Validate $value to be a string * - * @return stdClass + * @param string $value The value to set * - * @since __DEPLOY_VERSION__ + * @return string + * + * @since __DEPLOY_VERSION__ */ - public function getUrl(): string + protected function setUrl(string $value): string { - return $this->url; + return $value; } /** - * Sets the event url. + * Forbid setting $path * - * @param stdClass + * @param string $value The value to set * - * @since __DEPLOY_VERSION__ + * @since __DEPLOY_VERSION__ + * + * @throws BadMethodCallException + */ + protected function setPath(string $value): string + { + throw new BadMethodCallException('Cannot set the argument "path" of the immutable event ' . $this->name . '.'); + } + + /** + * Forbid setting $path + * + * @param string $value The value to set + * + * @since __DEPLOY_VERSION__ + * + * @throws BadMethodCallException */ - public function setUrl(string $url): void + protected function setAdapter(string $value): string { - $this->url = $url; + throw new BadMethodCallException('Cannot set the argument "adapter" of the immutable event ' . $this->name . '.'); } } diff --git a/administrator/components/com_media/src/Event/FetchMediaFilesEvent.php b/administrator/components/com_media/src/Event/FetchMediaFilesEvent.php index 53c6fb99abfb5..52220fd2d0fb5 100644 --- a/administrator/components/com_media/src/Event/FetchMediaFilesEvent.php +++ b/administrator/components/com_media/src/Event/FetchMediaFilesEvent.php @@ -11,57 +11,186 @@ \defined('_JEXEC') or die; -use Joomla\CMS\Event\AbstractEvent; +use BadMethodCallException; +use Joomla\CMS\Date\Date; +use Joomla\CMS\Event\AbstractImmutableEvent; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Text; /** * Event object for fetch media files. * * @since __DEPLOY_VERSION__ */ -class FetchMediaFilesEvent extends AbstractEvent +final class FetchMediaFilesEvent extends AbstractImmutableEvent { - /** - * @var array - * @since __DEPLOY_VERSION__ - */ - private $files; - /** * Constructor. * - * @param string $name The event name. - * @param \stdClass $files The files. + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @throws BadMethodCallException * * @since __DEPLOY_VERSION__ */ - public function __construct($name, array $files) + public function __construct($name, array $arguments = array()) { - parent::__construct($name, []); + parent::__construct($name, $arguments); - $this->files = $files; + // Check for required arguments + if (!\array_key_exists('files', $arguments) || !is_array($arguments['files'])) + { + throw new BadMethodCallException("Argument 'files' of event $name is not of the expected type"); + } } /** - * Returns the event files. + * Validate $value to be an array + * + * @param array $values The value to set * * @return array * - * @since __DEPLOY_VERSION__ + * @since __DEPLOY_VERSION__ */ - public function getFiles(): array + protected function setFiles(array $values): array { - return $this->files; + $result = []; + + foreach($values as $value) { + $result[] = $this->validateFile($value); + } + + return $result; } - /** - * Sets the event files. - * - * @param array - * - * @since __DEPLOY_VERSION__ - */ - public function setFiles(array $files): void - { - $this->files = $files; + protected function getFiles(array $values) { + $result = []; + + foreach($values as $value) { + $result[] = clone $value; + } + + return $result; } + + /** + * Validate $value to have all attributes with a valid type + * + * Validation based on \Joomla\Component\Media\Administrator\Adapter\AdapterInterface::getFile() + * + * Properties validated: + * - type: The type can be file or dir + * - name: The name of the file + * - path: The relative path to the root + * - extension: The file extension + * - size: The size of the file + * - create_date: The date created + * - modified_date: The date modified + * - mime_type: The mime type + * - width: The width, when available + * - height: The height, when available + * + * Generation based on \Joomla\Plugin\Filesystem\Local\Adapter\LocalAdapter::getPathInformation() + * + * Properties generated: + * - created_date_formatted: DATE_FORMAT_LC5 formatted string based on create_date + * - modified_date_formatted: DATE_FORMAT_LC5 formatted string based on modified_date + * + * @param \stdClass $value The value to set + * + * @return \stdClass + * + * @since __DEPLOY_VERSION__ + * + * @throws BadMethodCallException + */ + private function validateFile(\stdClass $value): \stdClass + { + // Make immutable object + $value = clone $value; + + // Only "dir" or "file" is allowed + if (!isset($value->type) || ($value->type !== 'dir' && $value->type !== 'file')) + { + throw new BadMethodCallException("Property 'type' of argument 'file' of event {$this->name} has a wrong value. Valid: 'dir' or 'file'"); + } + + // Non empty string + if (empty($value->name) || !is_string($value->name)) + { + throw new BadMethodCallException("Property 'name' of argument 'file' of event {$this->name} has a wrong value. Valid: non empty string"); + } + + // Non empty string + if (empty($value->path) || !is_string($value->path)) + { + throw new BadMethodCallException("Property 'path' of argument 'file' of event {$this->name} has a wrong value. Valid: non empty string"); + } + + // A string + if (!isset($value->extension) || !is_string($value->extension)) + { + throw new BadMethodCallException("Property 'extension' of argument 'file' of event {$this->name} has a wrong value. Valid: string"); + } + + // An empty string or an integer + if (!isset($value->size) || + (!is_integer($value->size) && !is_string($value->size)) || + (is_string($value->size) && $value->size !== '') + ) + { + throw new BadMethodCallException("Property 'size' of argument 'file' of event {$this->name} has a wrong value. Valid: empty string or integer"); + } + + // A string + if (!isset($value->mime_type) || !is_string($value->mime_type)) + { + throw new BadMethodCallException("Property 'mime_type' of argument 'file' of event {$this->name} has a wrong value. Valid: string"); + } + + // An integer + if (!isset($value->width) || !is_integer($value->width)) + { + throw new BadMethodCallException("Property 'width' of argument 'file' of event {$this->name} has a wrong value. Valid: integer"); + } + + // An integer + if (!isset($value->height) || !is_integer($value->height)) + { + throw new BadMethodCallException("Property 'height' of argument 'file' of event {$this->name} has a wrong value. Valid: integer"); + } + + // A ISO 8601 date string + if (empty($value->create_date)) { + throw new BadMethodCallException("Property 'create_date' of argument 'file' of event {$this->name} has a wrong value. Valid: ISO 8601 date string"); + } + + // Validate date format + $date = Date::createFromFormat(\DATE_ISO8601, $value->create_date); + if (!$date) { + throw new BadMethodCallException("Property 'create_date' of argument 'file' of event {$this->name} has a wrong value. Valid: ISO 8601 date string"); + } + + // Create formated string based on \Joomla\Plugin\Filesystem\Local\Adapter\LocalAdapter::getPathInformation() + $value->create_date_formatted = HTMLHelper::_('date', $date, Text::_('DATE_FORMAT_LC5')); + + // A ISO 8601 date string + if (empty($value->modified_date)) { + throw new BadMethodCallException("Property 'modified_date' of argument 'file' of event {$this->name} has a wrong value. Valid: ISO 8601 date string"); + } + + // Validate date format + $date = Date::createFromFormat(\DATE_ISO8601, $value->modified_date); + if (!$date) { + throw new BadMethodCallException("Property 'modified_date' of argument 'file' of event {$this->name} has a wrong value. Valid: ISO 8601 date string"); + } + + // Create formated string based on \Joomla\Plugin\Filesystem\Local\Adapter\LocalAdapter::getPathInformation() + $value->modified_date_formatted = HTMLHelper::_('date', $date, Text::_('DATE_FORMAT_LC5')); + + return $value; + } + } diff --git a/administrator/components/com_media/src/Model/ApiModel.php b/administrator/components/com_media/src/Model/ApiModel.php index 9d9db2cc3bf1b..74f510c5bac79 100644 --- a/administrator/components/com_media/src/Model/ApiModel.php +++ b/administrator/components/com_media/src/Model/ApiModel.php @@ -119,10 +119,10 @@ public function getFile($adapter, $path = '/', $options = []) $file->path = $adapter . ":" . $file->path; $file->adapter = $adapter; - $event = new FetchMediaFileEvent('onFetchMediaFile', $file); + $event = new FetchMediaFileEvent('onFetchMediaFile', ['file' => $file]); Factory::getApplication()->getDispatcher()->dispatch($event->getName(), $event); - return $event->getFile(); + return $event->getArgument('file'); } /** @@ -187,10 +187,10 @@ public function getFiles($adapter, $path = '/', $options = []) // Make proper indexes $files = array_values($files); - $event = new FetchMediaFilesEvent('onFetchMediaFiles', $files); + $event = new FetchMediaFilesEvent('onFetchMediaFiles', ['files' => $files]); Factory::getApplication()->getDispatcher()->dispatch($event->getName(), $event); - return $event->getFiles(); + return $event->getArgument('files'); } /** @@ -467,10 +467,10 @@ public function getUrl($adapter, $path) $url = $this->getAdapter($adapter)->getUrl($path); - $event = new FetchMediaFileUrlEvent('onFetchMediaFileUrl', $url); + $event = new FetchMediaFileUrlEvent('onFetchMediaFileUrl', ['adapter' => $adapter, 'path' => $path, 'url' => $url]); Factory::getApplication()->getDispatcher()->dispatch($event->getName(), $event); - return $event->getUrl(); + return $event->getArgument('url'); } /**