[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |