[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/administrator/components/com_media/src/Model/ -> ApiModel.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Administrator
   5   * @subpackage  com_media
   6   *
   7   * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
   8   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   9   */
  10  
  11  namespace Joomla\Component\Media\Administrator\Model;
  12  
  13  use Joomla\CMS\Component\ComponentHelper;
  14  use Joomla\CMS\Factory;
  15  use Joomla\CMS\Filesystem\File;
  16  use Joomla\CMS\MVC\Model\BaseDatabaseModel;
  17  use Joomla\CMS\Object\CMSObject;
  18  use Joomla\CMS\Plugin\PluginHelper;
  19  use Joomla\Component\Media\Administrator\Event\FetchMediaItemEvent;
  20  use Joomla\Component\Media\Administrator\Event\FetchMediaItemsEvent;
  21  use Joomla\Component\Media\Administrator\Event\FetchMediaItemUrlEvent;
  22  use Joomla\Component\Media\Administrator\Exception\FileExistsException;
  23  use Joomla\Component\Media\Administrator\Exception\FileNotFoundException;
  24  use Joomla\Component\Media\Administrator\Exception\InvalidPathException;
  25  use Joomla\Component\Media\Administrator\Provider\ProviderManagerHelperTrait;
  26  
  27  // phpcs:disable PSR1.Files.SideEffects
  28  \defined('_JEXEC') or die;
  29  // phpcs:enable PSR1.Files.SideEffects
  30  
  31  /**
  32   * Api Model
  33   *
  34   * @since  4.0.0
  35   */
  36  class ApiModel extends BaseDatabaseModel
  37  {
  38      use ProviderManagerHelperTrait;
  39  
  40      /**
  41       * The available extensions.
  42       *
  43       * @var   string[]
  44       * @since  4.0.0
  45       */
  46      private $allowedExtensions = null;
  47  
  48      /**
  49       * Returns the requested file or folder information. More information
  50       * can be found in AdapterInterface::getFile().
  51       *
  52       * @param   string  $adapter  The adapter
  53       * @param   string  $path     The path to the file or folder
  54       * @param   array   $options  The options
  55       *
  56       * @return  \stdClass
  57       *
  58       * @since   4.0.0
  59       * @throws  \Exception
  60       * @see     AdapterInterface::getFile()
  61       */
  62      public function getFile($adapter, $path = '/', $options = [])
  63      {
  64          // Add adapter prefix to the file returned
  65          $file = $this->getAdapter($adapter)->getFile($path);
  66  
  67          // Check if it is a media file
  68          if ($file->type == 'file' && !$this->isMediaFile($file->path)) {
  69              throw new InvalidPathException();
  70          }
  71  
  72          if (isset($options['url']) && $options['url'] && $file->type == 'file') {
  73              $file->url = $this->getUrl($adapter, $file->path);
  74          }
  75  
  76          if (isset($options['content']) && $options['content'] && $file->type == 'file') {
  77              $resource = $this->getAdapter($adapter)->getResource($file->path);
  78  
  79              if ($resource) {
  80                  $file->content = base64_encode(stream_get_contents($resource));
  81              }
  82          }
  83  
  84          $file->path    = $adapter . ":" . $file->path;
  85          $file->adapter = $adapter;
  86  
  87          $event = new FetchMediaItemEvent('onFetchMediaItem', ['item' => $file]);
  88          Factory::getApplication()->getDispatcher()->dispatch($event->getName(), $event);
  89  
  90          return $event->getArgument('item');
  91      }
  92  
  93      /**
  94       * Returns the folders and files for the given path. More information
  95       * can be found in AdapterInterface::getFiles().
  96       *
  97       * @param   string  $adapter  The adapter
  98       * @param   string  $path     The folder
  99       * @param   array   $options  The options
 100       *
 101       * @return  \stdClass[]
 102       *
 103       * @since   4.0.0
 104       * @throws  \Exception
 105       * @see     AdapterInterface::getFile()
 106       */
 107      public function getFiles($adapter, $path = '/', $options = [])
 108      {
 109          // Check whether user searching
 110          if ($options['search'] != null) {
 111              // Do search
 112              $files = $this->search($adapter, $options['search'], $path, $options['recursive']);
 113          } else {
 114              // Grab files for the path
 115              $files = $this->getAdapter($adapter)->getFiles($path);
 116          }
 117  
 118          // Add adapter prefix to all the files to be returned
 119          foreach ($files as $key => $file) {
 120              // Check if the file is valid
 121              if ($file->type == 'file' && !$this->isMediaFile($file->path)) {
 122                  // Remove the file from the data
 123                  unset($files[$key]);
 124                  continue;
 125              }
 126  
 127              // Check if we need more information
 128              if (isset($options['url']) && $options['url'] && $file->type == 'file') {
 129                  $file->url = $this->getUrl($adapter, $file->path);
 130              }
 131  
 132              if (isset($options['content']) && $options['content'] && $file->type == 'file') {
 133                  $resource = $this->getAdapter($adapter)->getResource($file->path);
 134  
 135                  if ($resource) {
 136                      $file->content = base64_encode(stream_get_contents($resource));
 137                  }
 138              }
 139  
 140              $file->path    = $adapter . ":" . $file->path;
 141              $file->adapter = $adapter;
 142          }
 143  
 144          // Make proper indexes
 145          $files = array_values($files);
 146  
 147          $event = new FetchMediaItemsEvent('onFetchMediaItems', ['items' => $files]);
 148          Factory::getApplication()->getDispatcher()->dispatch($event->getName(), $event);
 149  
 150          return $event->getArgument('items');
 151      }
 152  
 153      /**
 154       * Creates a folder with the given name in the given path. More information
 155       * can be found in AdapterInterface::createFolder().
 156       *
 157       * @param   string   $adapter   The adapter
 158       * @param   string   $name      The name
 159       * @param   string   $path      The folder
 160       * @param   boolean  $override  Should the folder being overridden when it exists
 161       *
 162       * @return  string
 163       *
 164       * @since   4.0.0
 165       * @throws  \Exception
 166       * @see     AdapterInterface::createFolder()
 167       */
 168      public function createFolder($adapter, $name, $path, $override)
 169      {
 170          try {
 171              $file = $this->getFile($adapter, $path . '/' . $name);
 172          } catch (FileNotFoundException $e) {
 173              // Do nothing
 174          }
 175  
 176          // Check if the file exists
 177          if (isset($file) && !$override) {
 178              throw new FileExistsException();
 179          }
 180  
 181          $app               = Factory::getApplication();
 182          $object            = new CMSObject();
 183          $object->adapter   = $adapter;
 184          $object->name      = $name;
 185          $object->path      = $path;
 186  
 187          PluginHelper::importPlugin('content');
 188  
 189          $result = $app->triggerEvent('onContentBeforeSave', ['com_media.folder', $object, true, $object]);
 190  
 191          if (in_array(false, $result, true)) {
 192              throw new \Exception($object->getError());
 193          }
 194  
 195          $object->name = $this->getAdapter($object->adapter)->createFolder($object->name, $object->path);
 196  
 197          $app->triggerEvent('onContentAfterSave', ['com_media.folder', $object, true, $object]);
 198  
 199          return $object->name;
 200      }
 201  
 202      /**
 203       * Creates a file with the given name in the given path with the data. More information
 204       * can be found in AdapterInterface::createFile().
 205       *
 206       * @param   string   $adapter   The adapter
 207       * @param   string   $name      The name
 208       * @param   string   $path      The folder
 209       * @param   string   $data      The data
 210       * @param   boolean  $override  Should the file being overridden when it exists
 211       *
 212       * @return  string
 213       *
 214       * @since   4.0.0
 215       * @throws  \Exception
 216       * @see     AdapterInterface::createFile()
 217       */
 218      public function createFile($adapter, $name, $path, $data, $override)
 219      {
 220          try {
 221              $file = $this->getFile($adapter, $path . '/' . $name);
 222          } catch (FileNotFoundException $e) {
 223              // Do nothing
 224          }
 225  
 226          // Check if the file exists
 227          if (isset($file) && !$override) {
 228              throw new FileExistsException();
 229          }
 230  
 231          // Check if it is a media file
 232          if (!$this->isMediaFile($path . '/' . $name)) {
 233              throw new InvalidPathException();
 234          }
 235  
 236          $app               = Factory::getApplication();
 237          $object            = new CMSObject();
 238          $object->adapter   = $adapter;
 239          $object->name      = $name;
 240          $object->path      = $path;
 241          $object->data      = $data;
 242          $object->extension = strtolower(File::getExt($name));
 243  
 244          PluginHelper::importPlugin('content');
 245  
 246          // Also include the filesystem plugins, perhaps they support batch processing too
 247          PluginHelper::importPlugin('media-action');
 248  
 249          $result = $app->triggerEvent('onContentBeforeSave', ['com_media.file', $object, true, $object]);
 250  
 251          if (in_array(false, $result, true)) {
 252              throw new \Exception($object->getError());
 253          }
 254  
 255          $object->name = $this->getAdapter($object->adapter)->createFile($object->name, $object->path, $object->data);
 256  
 257          $app->triggerEvent('onContentAfterSave', ['com_media.file', $object, true, $object]);
 258  
 259          return $object->name;
 260      }
 261  
 262      /**
 263       * Updates the file with the given name in the given path with the data. More information
 264       * can be found in AdapterInterface::updateFile().
 265       *
 266       * @param   string  $adapter  The adapter
 267       * @param   string  $name     The name
 268       * @param   string  $path     The folder
 269       * @param   string  $data     The data
 270       *
 271       * @return  void
 272       *
 273       * @since   4.0.0
 274       * @throws  \Exception
 275       * @see     AdapterInterface::updateFile()
 276       */
 277      public function updateFile($adapter, $name, $path, $data)
 278      {
 279          // Check if it is a media file
 280          if (!$this->isMediaFile($path . '/' . $name)) {
 281              throw new InvalidPathException();
 282          }
 283  
 284          $app               = Factory::getApplication();
 285          $object            = new CMSObject();
 286          $object->adapter   = $adapter;
 287          $object->name      = $name;
 288          $object->path      = $path;
 289          $object->data      = $data;
 290          $object->extension = strtolower(File::getExt($name));
 291  
 292          PluginHelper::importPlugin('content');
 293  
 294          // Also include the filesystem plugins, perhaps they support batch processing too
 295          PluginHelper::importPlugin('media-action');
 296  
 297          $result = $app->triggerEvent('onContentBeforeSave', ['com_media.file', $object, false, $object]);
 298  
 299          if (in_array(false, $result, true)) {
 300              throw new \Exception($object->getError());
 301          }
 302  
 303          $this->getAdapter($object->adapter)->updateFile($object->name, $object->path, $object->data);
 304  
 305          $app->triggerEvent('onContentAfterSave', ['com_media.file', $object, false, $object]);
 306      }
 307  
 308      /**
 309       * Deletes the folder or file of the given path. More information
 310       * can be found in AdapterInterface::delete().
 311       *
 312       * @param   string  $adapter  The adapter
 313       * @param   string  $path     The path to the file or folder
 314       *
 315       * @return  void
 316       *
 317       * @since   4.0.0
 318       * @throws  \Exception
 319       * @see     AdapterInterface::delete()
 320       */
 321      public function delete($adapter, $path)
 322      {
 323          $file = $this->getFile($adapter, $path);
 324  
 325          // Check if it is a media file
 326          if ($file->type == 'file' && !$this->isMediaFile($file->path)) {
 327              throw new InvalidPathException();
 328          }
 329  
 330          $type              = $file->type === 'file' ? 'file' : 'folder';
 331          $app               = Factory::getApplication();
 332          $object            = new CMSObject();
 333          $object->adapter   = $adapter;
 334          $object->path      = $path;
 335  
 336          PluginHelper::importPlugin('content');
 337  
 338          // Also include the filesystem plugins, perhaps they support batch processing too
 339          PluginHelper::importPlugin('media-action');
 340  
 341          $result = $app->triggerEvent('onContentBeforeDelete', ['com_media.' . $type, $object]);
 342  
 343          if (in_array(false, $result, true)) {
 344              throw new \Exception($object->getError());
 345          }
 346  
 347          $this->getAdapter($object->adapter)->delete($object->path);
 348  
 349          $app->triggerEvent('onContentAfterDelete', ['com_media.' . $type, $object]);
 350      }
 351  
 352      /**
 353       * Copies file or folder from source path to destination path
 354       * If forced, existing files/folders would be overwritten
 355       *
 356       * @param   string  $adapter          The adapter
 357       * @param   string  $sourcePath       Source path of the file or folder (relative)
 358       * @param   string  $destinationPath  Destination path(relative)
 359       * @param   bool    $force            Force to overwrite
 360       *
 361       * @return  string
 362       *
 363       * @since   4.0.0
 364       * @throws  \Exception
 365       */
 366      public function copy($adapter, $sourcePath, $destinationPath, $force = false)
 367      {
 368          return $this->getAdapter($adapter)->copy($sourcePath, $destinationPath, $force);
 369      }
 370  
 371      /**
 372       * Moves file or folder from source path to destination path
 373       * If forced, existing files/folders would be overwritten
 374       *
 375       * @param   string  $adapter          The adapter
 376       * @param   string  $sourcePath       Source path of the file or folder (relative)
 377       * @param   string  $destinationPath  Destination path(relative)
 378       * @param   bool    $force            Force to overwrite
 379       *
 380       * @return  string
 381       *
 382       * @since   4.0.0
 383       * @throws  \Exception
 384       */
 385      public function move($adapter, $sourcePath, $destinationPath, $force = false)
 386      {
 387          return $this->getAdapter($adapter)->move($sourcePath, $destinationPath, $force);
 388      }
 389  
 390      /**
 391       * Returns a url for serve media files from adapter.
 392       * Url must provide a valid image type to be displayed on Joomla! site.
 393       *
 394       * @param   string  $adapter  The adapter
 395       * @param   string  $path     The relative path for the file
 396       *
 397       * @return  string  Permalink to the relative file
 398       *
 399       * @since   4.0.0
 400       * @throws  FileNotFoundException
 401       */
 402      public function getUrl($adapter, $path)
 403      {
 404          // Check if it is a media file
 405          if (!$this->isMediaFile($path)) {
 406              throw new InvalidPathException();
 407          }
 408  
 409          $url = $this->getAdapter($adapter)->getUrl($path);
 410  
 411          $event = new FetchMediaItemUrlEvent('onFetchMediaFileUrl', ['adapter' => $adapter, 'path' => $path, 'url' => $url]);
 412          Factory::getApplication()->getDispatcher()->dispatch($event->getName(), $event);
 413  
 414          return $event->getArgument('url');
 415      }
 416  
 417      /**
 418       * Search for a pattern in a given path
 419       *
 420       * @param   string  $adapter    The adapter to work on
 421       * @param   string  $needle     The search therm
 422       * @param   string  $path       The base path for the search
 423       * @param   bool    $recursive  Do a recursive search
 424       *
 425       * @return \stdClass[]
 426       *
 427       * @since   4.0.0
 428       * @throws \Exception
 429       */
 430      public function search($adapter, $needle, $path = '/', $recursive = true)
 431      {
 432          return $this->getAdapter($adapter)->search($path, $needle, $recursive);
 433      }
 434  
 435      /**
 436       * Checks if the given path is an allowed media file.
 437       *
 438       * @param   string  $path  The path to file
 439       *
 440       * @return boolean
 441       *
 442       * @since   4.0.0
 443       */
 444      private function isMediaFile($path)
 445      {
 446          // Check if there is an extension available
 447          if (!strrpos($path, '.')) {
 448              return false;
 449          }
 450  
 451          // Initialize the allowed extensions
 452          if ($this->allowedExtensions === null) {
 453              // Get options from the input or fallback to images only
 454              $mediaTypes = explode(',', Factory::getApplication()->input->getString('mediatypes', '0'));
 455              $types      = [];
 456              $extensions = [];
 457  
 458              // Default to showing all supported formats
 459              if (count($mediaTypes) === 0) {
 460                  $mediaTypes = ['0', '1', '2', '3'];
 461              }
 462  
 463              array_map(
 464                  function ($mediaType) use (&$types) {
 465                      switch ($mediaType) {
 466                          case '0':
 467                              $types[] = 'images';
 468                              break;
 469                          case '1':
 470                              $types[] = 'audios';
 471                              break;
 472                          case '2':
 473                              $types[] = 'videos';
 474                              break;
 475                          case '3':
 476                              $types[] = 'documents';
 477                              break;
 478                          default:
 479                              break;
 480                      }
 481                  },
 482                  $mediaTypes
 483              );
 484  
 485              $images = array_map(
 486                  'trim',
 487                  explode(
 488                      ',',
 489                      ComponentHelper::getParams('com_media')->get(
 490                          'image_extensions',
 491                          'bmp,gif,jpg,jpeg,png,webp'
 492                      )
 493                  )
 494              );
 495              $audios = array_map(
 496                  'trim',
 497                  explode(
 498                      ',',
 499                      ComponentHelper::getParams('com_media')->get(
 500                          'audio_extensions',
 501                          'mp3,m4a,mp4a,ogg'
 502                      )
 503                  )
 504              );
 505              $videos = array_map(
 506                  'trim',
 507                  explode(
 508                      ',',
 509                      ComponentHelper::getParams('com_media')->get(
 510                          'video_extensions',
 511                          'mp4,mp4v,mpeg,mov,webm'
 512                      )
 513                  )
 514              );
 515              $documents = array_map(
 516                  'trim',
 517                  explode(
 518                      ',',
 519                      ComponentHelper::getParams('com_media')->get(
 520                          'doc_extensions',
 521                          'doc,odg,odp,ods,odt,pdf,ppt,txt,xcf,xls,csv'
 522                      )
 523                  )
 524              );
 525  
 526              foreach ($types as $type) {
 527                  if (in_array($type, ['images', 'audios', 'videos', 'documents'])) {
 528                      $extensions = array_merge($extensions, ${$type});
 529                  }
 530              }
 531  
 532              // Make them an array
 533              $this->allowedExtensions = $extensions;
 534          }
 535  
 536          // Extract the extension
 537          $extension = strtolower(substr($path, strrpos($path, '.') + 1));
 538  
 539          // Check if the extension exists in the allowed extensions
 540          return in_array($extension, $this->allowedExtensions);
 541      }
 542  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer