MODX Revolution PHP Cross Reference Content Management Systems

Source: /core/model/modx/sources/modfilemediasource.class.php - 1047 lines - 41713 bytes - Summary - Text - Print

   1  <?php
   2  /**

   3   * @package modx

   4   * @subpackage sources

   5   */
   6  require_once MODX_CORE_PATH . 'model/modx/sources/modmediasource.class.php';
   7  /**

   8   * Implements a file-system-based media source, allowing manipulation and management of files on the server's

   9   * location. Supports basePath and baseUrl parameters, similar to Revolution 2.1 and prior's filemanager_* settings.

  10   *

  11   * @package modx

  12   * @subpackage sources

  13   */
  14  class modFileMediaSource extends modMediaSource implements modMediaSourceInterface {
  15      /** @var modFileHandler */

  16      public $fileHandler;
  17  
  18      /**

  19       * {@inheritDoc}

  20       * @return boolean

  21       */
  22      public function initialize() {
  23          parent::initialize();
  24          $options = array();
  25          if (!$this->ctx) {
  26              $this->ctx =& $this->xpdo->context;
  27          }
  28          $options['context'] = $this->ctx->get('key');
  29          $this->fileHandler = $this->xpdo->getService('fileHandler','modFileHandler', '',$options);
  30          return true;
  31      }
  32  
  33      /**

  34       * Get base paths/urls and sanitize incoming paths

  35       * 

  36       * @param string $path A path to the active directory

  37       * @return array

  38       */
  39      public function getBases($path) {
  40          if (empty($path)) $path = '';
  41          $properties = $this->getProperties();
  42          $bases = array();
  43          $path = $this->fileHandler->sanitizePath($path);
  44          $bases['path'] = $properties['basePath']['value'];
  45          $bases['pathIsRelative'] = false;
  46          if (!empty($properties['basePathRelative']['value'])) {
  47              $bases['pathAbsolute'] = $this->ctx->getOption('base_path',MODX_BASE_PATH).$bases['path'];
  48              $bases['pathIsRelative'] = true;
  49          } else {
  50              $bases['pathAbsolute'] = $bases['path'];
  51          }
  52          
  53          $bases['pathAbsoluteWithPath'] = $bases['pathAbsolute'].ltrim($path,'/');
  54          if (is_dir($bases['pathAbsoluteWithPath'])) {
  55              $bases['pathAbsoluteWithPath'] = $this->fileHandler->postfixSlash($bases['pathAbsoluteWithPath']);
  56          }
  57          $bases['pathRelative'] = ltrim($path,'/');
  58  
  59          /* get relative url */

  60          $bases['urlIsRelative'] = false;
  61          $bases['url'] = $properties['baseUrl']['value'];;
  62          if (!empty($properties['baseUrlRelative']['value'])) {
  63              $bases['urlAbsolute'] = $this->ctx->getOption('base_url',MODX_BASE_URL).$bases['url'];
  64              $bases['urlIsRelative'] = true;
  65          } else {
  66              $bases['urlAbsolute'] = $bases['url'];
  67          }
  68  
  69          $bases['urlAbsoluteWithPath'] = $bases['urlAbsolute'].ltrim($path,'/');
  70          $bases['urlRelative'] = ltrim($path,'/');
  71          return $bases;
  72      }
  73  
  74      /**

  75       * Get the ID of the edit file action

  76       *

  77       * @return boolean|int

  78       */
  79      public function getEditActionId() {
  80          $editAction = false;
  81          /** @var modAction $act */

  82          $act = $this->xpdo->getObject('modAction',array('controller' => 'system/file/edit'));
  83          if ($act) { $editAction = $act->get('id'); }
  84          return $editAction;
  85      }
  86  
  87      /**

  88       * Return an array of files and folders at this current level in the directory structure

  89       * 

  90       * @param string $path

  91       * @return array

  92       */
  93      public function getContainerList($path) {
  94          $properties = $this->getPropertyList();
  95          $path = $this->fileHandler->postfixSlash($path);
  96          $bases = $this->getBases($path);
  97          if (empty($bases['pathAbsolute'])) return array();
  98          $fullPath = $bases['pathAbsolute'].ltrim($path,'/');
  99                  
 100          $useMultibyte = $this->getOption('use_multibyte',$properties,false);
 101          $encoding = $this->getOption('modx_charset',$properties,'UTF-8');
 102          $hideFiles = !empty($properties['hideFiles']) && $properties['hideFiles'] != 'false' ? true : false;
 103          $editAction = $this->getEditActionId();
 104  
 105          $imagesExts = $this->getOption('imageExtensions',$properties,'jpg,jpeg,png,gif');
 106          $imagesExts = explode(',',$imagesExts);
 107          $skipFiles = $this->getOption('skipFiles',$properties,'.svn,.git,_notes,.DS_Store,nbproject,.idea');
 108          $skipFiles = explode(',',$skipFiles);
 109          if ($this->xpdo->getParser()) {
 110              $this->xpdo->parser->processElementTags('',$skipFiles,true,true);
 111          }
 112          $skipFiles[] = '.';
 113          $skipFiles[] = '..';
 114  
 115          $canSave = $this->checkPolicy('save');
 116          $canRemove = $this->checkPolicy('remove');
 117          $canCreate = $this->checkPolicy('create');
 118  
 119          $directories = array();
 120          $files = array();
 121          if (!is_dir($fullPath)) return array();
 122  
 123          /* iterate through directories */

 124          /** @var DirectoryIterator $file */

 125          foreach (new DirectoryIterator($fullPath) as $file) {
 126              if (in_array($file,$skipFiles)) continue;
 127              if (!$file->isReadable()) continue;
 128  
 129              $fileName = $file->getFilename();
 130              if (in_array(trim($fileName,'/'),$skipFiles)) continue;
 131              if (in_array($fullPath.$fileName,$skipFiles)) continue;
 132              $filePathName = $file->getPathname();
 133              $octalPerms = substr(sprintf('%o', $file->getPerms()), -4);
 134  
 135              /* handle dirs */

 136              $cls = array();
 137              if ($file->isDir() && $this->hasPermission('directory_list')) {
 138                  $cls[] = 'folder';
 139                  if ($this->hasPermission('directory_chmod') && $canSave) $cls[] = 'pchmod';
 140                  if ($this->hasPermission('directory_create') && $canCreate) $cls[] = 'pcreate';
 141                  if ($this->hasPermission('directory_remove') && $canRemove) $cls[] = 'premove';
 142                  if ($this->hasPermission('directory_update') && $canSave) $cls[] = 'pupdate';
 143                  if ($this->hasPermission('file_upload') && $canCreate) $cls[] = 'pupload';
 144                  if ($this->hasPermission('file_create') && $canCreate) $cls[] = 'pcreate';
 145  
 146                  $directories[$fileName] = array(
 147                      'id' => $bases['urlRelative'].rtrim($fileName,'/').'/',
 148                      'text' => $fileName,
 149                      'cls' => implode(' ',$cls),
 150                      'type' => 'dir',
 151                      'leaf' => false,
 152                      'path' => $bases['pathAbsoluteWithPath'].$fileName,
 153                      'pathRelative' => $bases['pathRelative'].$fileName,
 154                      'perms' => $octalPerms,
 155                      'menu' => array(),
 156                  );
 157                  $directories[$fileName]['menu'] = array('items' => $this->getListContextMenu($file,$directories[$fileName]));
 158              }
 159  
 160              /* get files in current dir */

 161              if ($file->isFile() && !$hideFiles && $this->hasPermission('file_list')) {
 162                  $ext = pathinfo($filePathName,PATHINFO_EXTENSION);
 163                  $ext = $useMultibyte ? mb_strtolower($ext,$encoding) : strtolower($ext);
 164  
 165                  $cls = array();
 166                  $cls[] = 'icon-file';
 167                  $cls[] = 'icon-'.$ext;
 168  
 169                  if (!empty($properties['currentFile']) && rawurldecode($properties['currentFile']) == $fullPath.$fileName && $properties['currentAction'] == $editAction) {
 170                      $cls[] = 'active-node';
 171                  }
 172  
 173                  if ($this->hasPermission('file_remove') && $canRemove) $cls[] = 'premove';
 174                  if ($this->hasPermission('file_update') && $canSave) $cls[] = 'pupdate';
 175  
 176                  if (!$file->isWritable()) {
 177                      $cls[] = 'icon-lock';
 178                  }
 179                  $encFile = rawurlencode($fullPath.$fileName);
 180                  $page = !empty($editAction) ? '?a='.$editAction.'&file='.$bases['urlRelative'].$fileName.'&wctx='.$this->ctx->get('key').'&source='.$this->get('id') : null;
 181                  $url = ($bases['urlIsRelative'] ? $bases['urlRelative'] : $bases['url']).$fileName;
 182  
 183                  /* get relative url from manager/ */

 184                  $fromManagerUrl = $bases['url'].trim(str_replace('//','/',$path.$fileName),'/');
 185                  $fromManagerUrl = ($bases['urlIsRelative'] ? '../' : '').$fromManagerUrl;
 186                  $files[$fileName] = array(
 187                      'id' => $bases['urlRelative'].$fileName,
 188                      'text' => $fileName,
 189                      'cls' => implode(' ',$cls),
 190                      'type' => 'file',
 191                      'leaf' => true,
 192                      'qtip' => in_array($ext,$imagesExts) ? '<img src="'.$fromManagerUrl.'" alt="'.$fileName.'" />' : '',
 193                      'page' => $this->fileHandler->isBinary($filePathName) ? $page : null,
 194                      'perms' => $octalPerms,
 195                      'path' => $bases['pathAbsoluteWithPath'].$fileName,
 196                      'pathRelative' => $bases['pathRelative'].$fileName,
 197                      'directory' => $bases['path'],
 198                      'url' => $bases['url'].$url,
 199                      'urlAbsolute' => $bases['urlAbsolute'].ltrim($url,'/'),
 200                      'file' => $encFile,
 201                      'menu' => array(),
 202                  );
 203                  $files[$fileName]['menu'] = array('items' => $this->getListContextMenu($file,$files[$fileName]));
 204              }
 205          }
 206  
 207          $ls = array();
 208          /* now sort files/directories */

 209          ksort($directories);
 210          foreach ($directories as $dir) {
 211              $ls[] = $dir;
 212          }
 213          ksort($files);
 214          foreach ($files as $file) {
 215              $ls[] = $file;
 216          }
 217  
 218          return $ls;
 219      }
 220  
 221      /**

 222       * Get the context menu items for a specific object in the list view

 223       * 

 224       * @param DirectoryIterator $file

 225       * @param array $fileArray

 226       * @return array

 227       */
 228      public function getListContextMenu(DirectoryIterator $file,array $fileArray) {
 229          $canSave = $this->checkPolicy('save');
 230          $canRemove = $this->checkPolicy('remove');
 231          $canCreate = $this->checkPolicy('create');
 232          $canView = $this->checkPolicy('view');
 233  
 234          $menu = array();
 235          if (!$file->isDir()) { /* files */
 236              if ($this->hasPermission('file_update') && $canSave) {
 237                  if (!empty($fileArray['page'])) {
 238                      $menu[] = array(
 239                          'text' => $this->xpdo->lexicon('file_edit'),
 240                          'handler' => 'this.editFile',
 241                      );
 242                      $menu[] = array(
 243                          'text' => $this->xpdo->lexicon('quick_update_file'),
 244                          'handler' => 'this.quickUpdateFile',
 245                      );
 246                  }
 247                  $menu[] = array(
 248                      'text' => $this->xpdo->lexicon('rename'),
 249                      'handler' => 'this.renameFile',
 250                  );
 251              }
 252              if ($this->hasPermission('file_view') && $canView) {
 253                  $menu[] = array(
 254                      'text' => $this->xpdo->lexicon('file_download'),
 255                      'handler' => 'this.downloadFile',
 256                  );
 257              }
 258              if ($this->hasPermission('file_remove') && $canRemove) {
 259                  if (!empty($menu)) $menu[] = '-';
 260                  $menu[] = array(
 261                      'text' => $this->xpdo->lexicon('file_remove'),
 262                      'handler' => 'this.removeFile',
 263                  );
 264              }
 265          } else { /* directories */
 266              if ($this->hasPermission('directory_create') && $canCreate) {
 267                  $menu[] = array(
 268                      'text' => $this->xpdo->lexicon('file_folder_create_here'),
 269                      'handler' => 'this.createDirectory',
 270                  );
 271              }
 272              if ($this->hasPermission('directory_chmod') && $canSave) {
 273                  $menu[] = array(
 274                      'text' => $this->xpdo->lexicon('file_folder_chmod'),
 275                      'handler' => 'this.chmodDirectory',
 276                  );
 277              }
 278              if ($this->hasPermission('directory_update') && $canSave) {
 279                  $menu[] = array(
 280                      'text' => $this->xpdo->lexicon('rename'),
 281                      'handler' => 'this.renameDirectory',
 282                  );
 283              }
 284              $menu[] = array(
 285                  'text' => $this->xpdo->lexicon('directory_refresh'),
 286                  'handler' => 'this.refreshActiveNode',
 287              );
 288              if ($this->hasPermission('file_upload') && $canCreate) {
 289                  $menu[] = '-';
 290                  $menu[] = array(
 291                      'text' => $this->xpdo->lexicon('upload_files'),
 292                      'handler' => 'this.uploadFiles',
 293                  );
 294              }
 295              if ($this->hasPermission('file_create') && $canCreate) {
 296                  $menu[] = array(
 297                      'text' => $this->xpdo->lexicon('file_create'),
 298                      'handler' => 'this.createFile',
 299                  );
 300                  $menu[] = array(
 301                      'text' => $this->xpdo->lexicon('quick_create_file'),
 302                      'handler' => 'this.quickCreateFile',
 303                  );
 304              }
 305              if ($this->hasPermission('directory_remove') && $canRemove) {
 306                  $menu[] = '-';
 307                  $menu[] = array(
 308                      'text' => $this->xpdo->lexicon('file_folder_remove'),
 309                      'handler' => 'this.removeDirectory',
 310                  );
 311              }
 312          }
 313          return $menu;
 314      }
 315  
 316      /**

 317       * Create a filesystem folder

 318       *

 319       * @param string $name

 320       * @param string $parentContainer

 321       * @return boolean

 322       */
 323      public function createContainer($name,$parentContainer) {
 324          $bases = $this->getBases($parentContainer.'/'.$name);
 325          if ($parentContainer == '/') {
 326              $parentContainer = $bases['pathAbsolute'];
 327          } else {
 328              $parentContainer = $bases['pathAbsolute'].$parentContainer;
 329          }
 330  
 331          /* create modDirectory instance for containing directory and validate */

 332          /** @var modDirectory $parentDirectory */

 333          $parentDirectory = $this->fileHandler->make($parentContainer);
 334          if (!($parentDirectory instanceof modDirectory)) {
 335              $this->addError('parent',$this->xpdo->lexicon('file_folder_err_parent_invalid'));
 336              return false;
 337          }
 338          if (!$parentDirectory->isReadable() || !$parentDirectory->isWritable()) {
 339              $this->addError('parent',$this->xpdo->lexicon('file_folder_err_perms_parent'));
 340              return false;
 341          }
 342  
 343          /* create modDirectory instance for new path, validate doesnt already exist */

 344          $newDirectoryPath = $parentDirectory->getPath().$name;
 345          /** @var modDirectory $newDirectory */

 346          $newDirectory = $this->fileHandler->make($newDirectoryPath,array(),'modDirectory');
 347          if ($newDirectory->exists()) {
 348              $this->addError('name',$this->xpdo->lexicon('file_folder_err_ae'));
 349              return false;
 350          }
 351  
 352          /* actually create the directory */

 353          $result = $newDirectory->create();
 354          if ($result !== true) {
 355              $this->addError('name',$this->xpdo->lexicon('file_folder_err_create').$result);
 356              return false;
 357          }
 358  
 359          $this->xpdo->logManagerAction('directory_create','',$newDirectory->getPath());
 360          return true;
 361      }
 362  
 363      /**

 364       * Remove a folder at the specified location

 365       * 

 366       * @param string $path

 367       * @return boolean

 368       */
 369      public function removeContainer($path) {
 370          /* instantiate modDirectory object */

 371          /** @var modDirectory $directory */

 372          $path = $this->fileHandler->postfixSlash($path);
 373          $directory = $this->fileHandler->make($path);
 374          
 375          /* validate and check permissions on directory */

 376          if (!($directory instanceof modDirectory)) {
 377              $this->addError('path',$this->xpdo->lexicon('file_folder_err_invalid'));
 378              return false;
 379          }
 380          if (!$directory->isReadable() || !$directory->isWritable()) {
 381              $this->addError('path',$this->xpdo->lexicon('file_folder_err_perms_remove'));
 382              return false;
 383          }
 384  
 385          /* remove the directory */

 386          $result = $directory->remove();
 387          if ($result == false) {
 388              $this->addError('path',$this->xpdo->lexicon('file_folder_err_remove'));
 389          }
 390  
 391          $this->xpdo->logManagerAction('directory_remove','',$directory->getPath());
 392          return true;
 393      }
 394  
 395      /**

 396       * @param string $oldPath

 397       * @param string $newName

 398       * @return bool

 399       */
 400      public function renameContainer($oldPath,$newName) {
 401          $bases = $this->getBases($oldPath);
 402          $oldPath = $bases['pathAbsolute'].$oldPath;
 403  
 404          /** @var modDirectory $oldDirectory */

 405          $oldDirectory = $this->fileHandler->make($oldPath);
 406  
 407          /* make sure is a directory and writable */

 408          if (!($oldDirectory instanceof modDirectory)) {
 409              $this->addError('name',$this->xpdo->lexicon('file_folder_err_invalid'));
 410              return false;
 411          }
 412          if (!$oldDirectory->isReadable() || !$oldDirectory->isWritable()) {
 413              $this->addError('name',$this->xpdo->lexicon('file_folder_err_perms'));
 414              return false;
 415          }
 416  
 417          /* sanitize new path */

 418          $newPath = $this->fileHandler->sanitizePath($newName);
 419          $newPath = $this->fileHandler->postfixSlash($newPath);
 420          $newPath = dirname($oldPath).DIRECTORY_SEPARATOR.$newPath;
 421  
 422          /* rename the dir */

 423          if (!$oldDirectory->rename($newPath)) {
 424              $this->addError('name',$this->xpdo->lexicon('file_folder_err_rename'));
 425              return false;
 426          }
 427  
 428          $this->xpdo->logManagerAction('directory_rename','',$oldDirectory->getPath());
 429          return true;
 430      }
 431  
 432  
 433      /**

 434       * @param string $oldPath

 435       * @param string $newName

 436       * @return bool

 437       */
 438      public function renameObject($oldPath,$newName) {
 439          $bases = $this->getBases($oldPath);
 440          $oldPath = $bases['pathAbsolute'].$oldPath;
 441  
 442          /** @var modFile $oldFile */

 443          $oldFile = $this->fileHandler->make($oldPath);
 444  
 445          /* make sure is a directory and writable */

 446          if (!($oldFile instanceof modFile)) {
 447              $this->addError('name',$this->xpdo->lexicon('file_err_invalid'));
 448              return false;
 449          }
 450          if (!$oldFile->isReadable() || !$oldFile->isWritable()) {
 451              $this->addError('name',$this->xpdo->lexicon('file_folder_err_perms'));
 452              return false;
 453          }
 454  
 455          /* sanitize new path */

 456          $newPath = $this->fileHandler->sanitizePath($newName);
 457          $newPath = dirname($oldPath).DIRECTORY_SEPARATOR.$newPath;
 458  
 459          /* rename the file */

 460          if (!$oldFile->rename($newPath)) {
 461              $this->addError('name',$this->xpdo->lexicon('file_folder_err_rename'));
 462              return false;
 463          }
 464  
 465          $this->xpdo->logManagerAction('file_rename','',$oldFile->getPath());
 466          return true;
 467      }
 468  
 469  
 470      /**

 471       * Get the contents of a specified file

 472       * 

 473       * @param string $objectPath

 474       * @return array

 475       */
 476      public function getObjectContents($objectPath) {
 477          $properties = $this->getPropertyList();
 478          $bases = $this->getBases($objectPath);
 479          /** @var modFile $file */

 480          $file = $this->fileHandler->make($bases['pathAbsoluteWithPath']);
 481  
 482          if (!$file->exists()) {
 483              $this->addError('file',$this->xpdo->lexicon('file_err_nf'));
 484          }
 485          if (!$file->isReadable()) {
 486              $this->addError('file',$this->xpdo->lexicon('file_err_perms'));
 487          }
 488          $imageExtensions = $this->getOption('imageExtensions',$properties,'jpg,jpeg,png,gif');
 489          $imageExtensions = explode(',',$imageExtensions);
 490          $fileExtension = pathinfo($objectPath,PATHINFO_EXTENSION);
 491  
 492          $fa = array(
 493              'name' => $objectPath,
 494              'basename' => basename($file->getPath()),
 495              'path' => $file->getPath(),
 496              'size' => @$file->getSize(),
 497              'last_accessed' => @$file->getLastAccessed(),
 498              'last_modified' => @$file->getLastModified(),
 499              'content' => $file->getContents(),
 500              'image' => in_array($fileExtension,$imageExtensions) ? true : false,
 501              'is_writable' => $file->isWritable(),
 502              'is_readable' => $file->isReadable(),
 503          );
 504          return $fa;
 505      }
 506  
 507      /**

 508       * Remove a file

 509       * 

 510       * @param string $objectPath

 511       * @return boolean

 512       */
 513      public function removeObject($objectPath) {
 514          $bases = $this->getBases($objectPath);
 515  
 516          $fullPath = $bases['pathAbsolute'].$objectPath;
 517          if (!file_exists($fullPath)) {
 518              $this->addError('file',$this->xpdo->lexicon('file_folder_err_ns').': '.$fullPath);
 519              return false;
 520          }
 521  
 522          /** @var modFile $file */

 523          $file = $this->fileHandler->make($fullPath);
 524  
 525          /* verify file exists and is writable */

 526          if (!$file->exists()) {
 527              $this->addError('file',$this->xpdo->lexicon('file_err_nf').': '.$file->getPath());
 528              return false;
 529          } else if (!$file->isReadable() || !$file->isWritable()) {
 530              $this->addError('file',$this->xpdo->lexicon('file_err_perms_remove'));
 531              return false;
 532          } else if (!($file instanceof modFile)) {
 533              $this->addError('file',$this->xpdo->lexicon('file_err_invalid'));
 534              return false;
 535          }
 536  
 537          /* remove file */

 538          if (!$file->remove()) {
 539              $this->addError('file',$this->xpdo->lexicon('file_err_remove'));
 540              return false;
 541          }
 542  
 543          /* log manager action */

 544          $this->xpdo->logManagerAction('file_remove','',$file->getPath());
 545          return true;
 546      }
 547  
 548      /**

 549       * Update the contents of a file

 550       *

 551       * @param string $objectPath

 552       * @param string $content

 553       * @return boolean|string

 554       */
 555      public function updateObject($objectPath,$content) {
 556          $bases = $this->getBases($objectPath);
 557  
 558          $fullPath = $bases['pathAbsolute'].ltrim($objectPath,'/');
 559  
 560          /** @var modFile $file */

 561          $file = $this->fileHandler->make($fullPath);
 562  
 563          /* verify file exists */

 564          if (!$file->exists()) {
 565              $this->addError('file',$this->xpdo->lexicon('file_err_nf').': '.$objectPath);
 566              return false;
 567          }
 568  
 569          /* write file */

 570          $file->setContent($content);
 571          $file->save();
 572  
 573          $this->xpdo->logManagerAction('file_update','',$file->getPath());
 574  
 575          return rawurlencode($file->getPath());
 576      }
 577  
 578  
 579      /**

 580       * Create a file

 581       *

 582       * @param string $objectPath

 583       * @param string $name

 584       * @param string $content

 585       * @return boolean|string

 586       */
 587      public function createObject($objectPath,$name,$content) {
 588          $bases = $this->getBases($objectPath);
 589  
 590          $fullPath = $bases['pathAbsolute'].ltrim($objectPath,'/').ltrim($name,'/');
 591  
 592          /** @var modFile $file */

 593          $file = $this->fileHandler->make($fullPath,array(),'modFile');
 594  
 595          /* write file */

 596          $file->setContent($content);
 597          $file->create($content);
 598          
 599          /* verify file exists */

 600          if (!$file->exists()) {
 601              $this->addError('file',$this->xpdo->lexicon('file_err_nf').': '.$fullPath);
 602              return false;
 603          }
 604  
 605          $this->xpdo->logManagerAction('file_create','',$file->getPath());
 606  
 607          return rawurlencode($file->getPath());
 608      }
 609  
 610      /**

 611       * Upload files to a specific folder on the file system

 612       * 

 613       * @param string $container

 614       * @param array $objects

 615       * @return boolean

 616       */
 617      public function uploadObjectsToContainer($container,array $objects = array()) {
 618          $bases = $this->getBases($container);
 619  
 620          $fullPath = $bases['pathAbsolute'].ltrim($container,'/');
 621  
 622          /** @var modDirectory $directory */

 623          $directory = $this->fileHandler->make($fullPath);
 624  
 625          /* verify target path is a directory and writable */

 626          if (!($directory instanceof modDirectory)) {
 627              $this->addError('path',$this->xpdo->lexicon('file_folder_err_invalid').': '.$fullPath);
 628              return false;
 629          }
 630          if (!($directory->isReadable()) || !$directory->isWritable()) {
 631              $this->addError('path',$this->xpdo->lexicon('file_folder_err_perms_upload').': '.$fullPath);
 632              return false;
 633          }
 634  
 635          $this->xpdo->context->prepare();
 636          $allowedFileTypes = explode(',',$this->xpdo->getOption('upload_files',null,''));
 637          $allowedFileTypes = array_merge(explode(',',$this->xpdo->getOption('upload_images')),explode(',',$this->xpdo->getOption('upload_media')),explode(',',$this->xpdo->getOption('upload_flash')),$allowedFileTypes);
 638          $allowedFileTypes = array_unique($allowedFileTypes);
 639          $maxFileSize = $this->xpdo->getOption('upload_maxsize',null,1048576);
 640  
 641          /* loop through each file and upload */

 642          foreach ($objects as $file) {
 643              if ($file['error'] != 0) continue;
 644              if (empty($file['name'])) continue;
 645              $ext = pathinfo($file['name'],PATHINFO_EXTENSION);
 646              $ext = strtolower($ext);
 647  
 648              if (empty($ext) || !in_array($ext,$allowedFileTypes)) {
 649                  $this->addError('path',$this->xpdo->lexicon('file_err_ext_not_allowed',array(
 650                      'ext' => $ext,
 651                  )));
 652                  continue;
 653              }
 654              $size = filesize($file['tmp_name']);
 655  
 656              if ($size > $maxFileSize) {
 657                  $this->addError('path',$this->xpdo->lexicon('file_err_too_large',array(
 658                      'size' => $size,
 659                      'allowed' => $maxFileSize,
 660                  )));
 661                  continue;
 662              }
 663  
 664              $newPath = $this->fileHandler->sanitizePath($file['name']);
 665              $newPath = $directory->getPath().$newPath;
 666  
 667              if (!move_uploaded_file($file['tmp_name'],$newPath)) {
 668                  $this->addError('path',$this->xpdo->lexicon('file_err_upload'));
 669                  continue;
 670              }
 671          }
 672  
 673          /* invoke event */

 674          $this->xpdo->invokeEvent('OnFileManagerUpload',array(
 675              'files' => &$objects,
 676              'directory' => $container,
 677              'source' => &$this,
 678          ));
 679  
 680          $this->xpdo->logManagerAction('file_upload','',$directory->getPath());
 681  
 682          return !$this->hasErrors();
 683      }
 684  
 685      /**

 686       * Chmod a specific folder

 687       * 

 688       * @param string $directoryPath

 689       * @param string $mode

 690       * @return boolean

 691       */
 692      public function chmodContainer($directoryPath,$mode) {
 693          /** @var modDirectory $directory */

 694          $directory = $this->fileHandler->make($directoryPath);
 695  
 696          /* verify target path is a directory and writable */

 697          if (!($directory instanceof modDirectory)) {
 698              $this->addError('mode',$this->xpdo->lexicon('file_folder_err_invalid').': '.$directoryPath);
 699              return false;
 700          }
 701          if (!$directory->isReadable() || !$directory->isWritable()) {
 702              $this->addError('mode',$this->xpdo->lexicon('file_folder_err_perms_upload').': '.$directoryPath);
 703              return false;
 704          }
 705  
 706          if (!$directory->chmod($mode)) {
 707              $this->addError('mode',$this->xpdo->lexicon('file_err_chmod'));
 708              return false;
 709          }
 710  
 711          $this->xpdo->logManagerAction('directory_chmod','',$directoryPath);
 712          return true;
 713      }
 714  
 715      /**

 716       * Move a file or folder to a specific location

 717       *

 718       * @param string $from The location to move from

 719       * @param string $to The location to move to

 720       * @param string $point

 721       * @return boolean

 722       */
 723      public function moveObject($from,$to,$point = 'append') {
 724          $success = false;
 725          $fromBases = $this->getBases($from);
 726          $toBases = $this->getBases($to);
 727  
 728          $fromPath = $fromBases['pathAbsolute'].$from;
 729          $toPath = $toBases['pathAbsolute'].$to;
 730  
 731          /* verify source path */

 732          if (!file_exists($fromPath)) {
 733              $this->addError('from',$this->xpdo->lexicon('file_err_nf').': '.$fromPath);
 734          }
 735          /** @var modFileSystemResource $fromObject */

 736          $fromObject = $this->fileHandler->make($fromPath);
 737          if (!$fromObject->isReadable() || !$fromObject->isWritable()) {
 738              $this->addError('from',$this->xpdo->lexicon('file_err_nf').': '.$fromPath);
 739              return $success;
 740          }
 741  
 742          /* verify target path */

 743          if (!file_exists($toPath)) {
 744              $this->addError('to',$this->xpdo->lexicon('file_folder_err_invalid').': '.$toPath);
 745          }
 746          /** @var modDirectory $toObject */

 747          $toObject = $this->fileHandler->make($toPath);
 748          if (!($toObject instanceof modDirectory)) {
 749              $this->addError('mode',$this->xpdo->lexicon('file_folder_err_invalid').': '.$toPath);
 750              return $success;
 751          }
 752          if (!$toObject->isReadable() || !$toObject->isWritable()) {
 753              $this->addError('to',$this->xpdo->lexicon('file_folder_err_invalid').': '.$toPath);
 754              return $success;
 755          }
 756  
 757          /* now move object */

 758          $newPath = rtrim($toPath,'/').'/'.basename($fromPath);
 759          $success = $fromObject->rename($newPath);
 760          if (!$success) {
 761              $this->addError('from',$this->xpdo->lexicon('file_err_chmod'));
 762          }
 763          return $success;
 764      }
 765  
 766      /**

 767       * Get a list of files in a specific directory.

 768       *

 769       * @param string $path

 770       * @return array

 771       */
 772      public function getObjectsInContainer($path) {
 773          $properties = $this->getPropertyList();
 774          $dir = $this->fileHandler->postfixSlash($path);
 775          $bases = $this->getBases($dir);
 776          if (empty($bases['pathAbsolute'])) return array();
 777          $fullPath = $bases['pathAbsolute'].$dir;
 778  
 779          $modAuth = $this->xpdo->user->getUserToken($this->xpdo->context->get('key'));
 780  
 781          /* get default settings */

 782          $imageExtensions = $this->getOption('imageExtensions',$properties,'jpg,jpeg,png,gif');
 783          $imageExtensions = explode(',',$imageExtensions);
 784          $use_multibyte = $this->ctx->getOption('use_multibyte', false);
 785          $encoding = $this->ctx->getOption('modx_charset', 'UTF-8');
 786          $allowedFileTypes = $this->getOption('allowedFileTypes',$properties,'');
 787          $allowedFileTypes = !empty($allowedFileTypes) && is_string($allowedFileTypes) ? explode(',',$allowedFileTypes) : $allowedFileTypes;
 788          $thumbnailType = $this->getOption('thumbnailType',$properties,'png');
 789          $thumbnailQuality = $this->getOption('thumbnailQuality',$properties,90);
 790          $skipFiles = $this->getOption('skipFiles',$properties,'.svn,.git,_notes,.DS_Store');
 791          $skipFiles = explode(',',$skipFiles);
 792          $skipFiles[] = '.';
 793          $skipFiles[] = '..';
 794  
 795          /* iterate */

 796          $files = array();
 797          if (!is_dir($fullPath)) {
 798              $this->addError('dir',$this->xpdo->lexicon('file_folder_err_ns').$fullPath);
 799              return array();
 800          }
 801          /** @var DirectoryIterator $file */

 802          foreach (new DirectoryIterator($fullPath) as $file) {
 803              if (in_array($file,$skipFiles)) continue;
 804              if (!$file->isReadable()) continue;
 805  
 806              $fileName = $file->getFilename();
 807              $filePathName = $file->getPathname();
 808  
 809              if (!$file->isDir()) {
 810  
 811                  $fileExtension = pathinfo($filePathName,PATHINFO_EXTENSION);
 812                  $fileExtension = $use_multibyte ? mb_strtolower($fileExtension,$encoding) : strtolower($fileExtension);
 813  
 814                  if (!empty($allowedFileTypes) && !in_array($fileExtension,$allowedFileTypes)) continue;
 815  
 816                  $filesize = @filesize($filePathName);
 817                  $url = urlencode(ltrim($dir.$fileName,'/'));
 818  
 819                  /* get thumbnail */

 820                  if (in_array($fileExtension,$imageExtensions)) {
 821                      $imageWidth = $this->ctx->getOption('filemanager_image_width', 400);
 822                      $imageHeight = $this->ctx->getOption('filemanager_image_height', 300);
 823                      $thumbHeight = $this->ctx->getOption('filemanager_thumb_height', 80);
 824                      $thumbWidth = $this->ctx->getOption('filemanager_thumb_width', 100);
 825  
 826                      $size = @getimagesize($filePathName);
 827                      if (is_array($size)) {
 828                          $imageWidth = $size[0] > 800 ? 800 : $size[0];
 829                          $imageHeight = $size[1] > 600 ? 600 : $size[1];
 830                      }
 831  
 832                      /* ensure max h/w */

 833                      if ($thumbWidth > $imageWidth) $thumbWidth = $imageWidth;
 834                      if ($thumbHeight > $imageHeight) $thumbHeight = $imageHeight;
 835  
 836                      /* generate thumb/image URLs */

 837                      $thumbQuery = http_build_query(array(
 838                          'src' => $url,
 839                          'w' => $thumbWidth,
 840                          'h' => $thumbHeight,
 841                          'f' => $thumbnailType,
 842                          'q' => $thumbnailQuality,
 843                          'far' => 1,
 844                          'HTTP_MODAUTH' => $modAuth,
 845                          'wctx' => $this->ctx->get('key'),
 846                          'source' => $this->get('id'),
 847                      ));
 848                      $imageQuery = http_build_query(array(
 849                          'src' => $url,
 850                          'w' => $imageWidth,
 851                          'h' => $imageHeight,
 852                          'HTTP_MODAUTH' => $modAuth,
 853                          'f' => $thumbnailType,
 854                          'q' => $thumbnailQuality,
 855                          'wctx' => $this->ctx->get('key'),
 856                          'source' => $this->get('id'),
 857                      ));
 858                      $thumb = $this->ctx->getOption('connectors_url', MODX_CONNECTORS_URL).'system/phpthumb.php?'.urldecode($thumbQuery);
 859                      $image = $this->ctx->getOption('connectors_url', MODX_CONNECTORS_URL).'system/phpthumb.php?'.urldecode($imageQuery);
 860                  } else {
 861                      $thumb = $image = $this->ctx->getOption('manager_url', MODX_MANAGER_URL).'templates/default/images/restyle/nopreview.jpg';
 862                      $thumbWidth = $imageWidth = $this->ctx->getOption('filemanager_thumb_width', 100);
 863                      $thumbHeight = $imageHeight = $this->ctx->getOption('filemanager_thumb_height', 80);
 864                  }
 865                  $octalPerms = substr(sprintf('%o', $file->getPerms()), -4);
 866  
 867                  $files[] = array(
 868                      'id' => $bases['urlAbsoluteWithPath'].$fileName,
 869                      'name' => $fileName,
 870                      'cls' => 'icon-'.$fileExtension,
 871                      'image' => $image,
 872                      'image_width' => $imageWidth,
 873                      'image_height' => $imageHeight,
 874                      'thumb' => $thumb,
 875                      'thumb_width' => $thumbWidth,
 876                      'thumb_height' => $thumbHeight,
 877                      'url' => ltrim($dir.$fileName,'/'),
 878                      'relativeUrl' => ltrim($dir.$fileName,'/'),
 879                      'fullRelativeUrl' => rtrim($bases['url']).ltrim($dir.$fileName,'/'),
 880                      'ext' => $fileExtension,
 881                      'pathname' => str_replace('//','/',$filePathName),
 882                      'lastmod' => $file->getMTime(),
 883                      'disabled' => false,
 884                      'perms' => $octalPerms,
 885                      'leaf' => true,
 886                      'size' => $filesize,
 887                      'menu' => array(
 888                          array('text' => $this->xpdo->lexicon('file_remove'),'handler' => 'this.removeFile'),
 889                      ),
 890                  );
 891              }
 892          }
 893          return $files;
 894      }
 895      /**

 896       * Get the name of this source type

 897       * @return string

 898       */
 899      public function getTypeName() {
 900          $this->xpdo->lexicon->load('source');
 901          return $this->xpdo->lexicon('source_type.file');
 902      }
 903  
 904      /**

 905       * Get the description of this source type

 906       * @return string

 907       */
 908      public function getTypeDescription() {
 909          $this->xpdo->lexicon->load('source');
 910          return $this->xpdo->lexicon('source_type.file_desc');
 911      }
 912  
 913      /**

 914       * Get the default properties for the filesystem media source type.

 915       * 

 916       * @return array

 917       */
 918      public function getDefaultProperties() {
 919          return array(
 920              'basePath' => array(
 921                  'name' => 'basePath',
 922                  'desc' => 'prop_file.basePath_desc',
 923                  'type' => 'textfield',
 924                  'options' => '',
 925                  'value' => '',
 926                  'lexicon' => 'core:source',
 927              ),
 928              'basePathRelative' => array(
 929                  'name' => 'basePathRelative',
 930                  'desc' => 'prop_file.basePathRelative_desc',
 931                  'type' => 'combo-boolean',
 932                  'options' => '',
 933                  'value' => true,
 934                  'lexicon' => 'core:source',
 935              ),
 936              'baseUrl' => array(
 937                  'name' => 'baseUrl',
 938                  'desc' => 'prop_file.baseUrl_desc',
 939                  'type' => 'textfield',
 940                  'options' => '',
 941                  'value' => '',
 942                  'lexicon' => 'core:source',
 943              ),
 944              'baseUrlRelative' => array(
 945                  'name' => 'baseUrlRelative',
 946                  'desc' => 'prop_file.baseUrlRelative_desc',
 947                  'type' => 'combo-boolean',
 948                  'options' => '',
 949                  'value' => true,
 950                  'lexicon' => 'core:source',
 951              ),
 952              'allowedFileTypes' => array(
 953                  'name' => 'allowedFileTypes',
 954                  'desc' => 'prop_file.allowedFileTypes_desc',
 955                  'type' => 'textfield',
 956                  'options' => '',
 957                  'value' => '',
 958                  'lexicon' => 'core:source',
 959              ),
 960              'imageExtensions' => array(
 961                  'name' => 'imageExtensions',
 962                  'desc' => 'prop_file.imageExtensions_desc',
 963                  'type' => 'textfield',
 964                  'value' => 'jpg,jpeg,png,gif',
 965                  'lexicon' => 'core:source',
 966              ),
 967              'thumbnailType' => array(
 968                  'name' => 'thumbnailType',
 969                  'desc' => 'prop_file.thumbnailType_desc',
 970                  'type' => 'list',
 971                  'options' => array(
 972                      array('name' => 'PNG','value' => 'png'),
 973                      array('name' => 'JPG','value' => 'jpg'),
 974                      array('name' => 'GIF','value' => 'gif'),
 975                  ),
 976                  'value' => 'png',
 977                  'lexicon' => 'core:source',
 978              ),
 979              'thumbnailQuality' => array(
 980                  'name' => 'thumbnailQuality',
 981                  'desc' => 'prop_s3.thumbnailQuality_desc',
 982                  'type' => 'textfield',
 983                  'options' => '',
 984                  'value' => 90,
 985                  'lexicon' => 'core:source',
 986              ),
 987              'skipFiles' => array(
 988                  'name' => 'skipFiles',
 989                  'desc' => 'prop_file.skipFiles_desc',
 990                  'type' => 'textfield',
 991                  'options' => '',
 992                  'value' => '.svn,.git,_notes,nbproject,.idea,.DS_Store',
 993                  'lexicon' => 'core:source',
 994              ),
 995          );
 996      }
 997  
 998      /**

 999       * Prepare the output values for image/file TVs by prefixing the baseUrl property to them

1000       *

1001       * @param string $value

1002       * @return string

1003       */
1004      public function prepareOutputUrl($value) {
1005          $properties = $this->getPropertyList();
1006          if (!empty($properties['baseUrl'])) {
1007              $value = $properties['baseUrl'].$value;
1008              if (isset($properties['baseUrlRelative']) && !empty($properties['baseUrlRelative'])) {
1009                  $value = $this->xpdo->context->getOption('base_url',null,MODX_BASE_URL).$value;
1010              }
1011          }
1012          return $value;
1013      }
1014  
1015  
1016      /**

1017       * Get the base path for this source. Only applicable to sources that are streams.

1018       * 

1019       * @param string $object An optional file to find the base path of

1020       * @return string

1021       */
1022      public function getBasePath($object = '') {
1023          $bases = $this->getBases($object);
1024          return $bases['pathAbsolute'];
1025      }
1026  
1027      /**

1028       * Get the base URL for this source. Only applicable to sources that are streams.

1029       * 

1030       * @param string $object An optional object to find the base url of

1031       * @return string

1032       */
1033      public function getBaseUrl($object = '') {
1034          $bases = $this->getBases($object);
1035          return $bases['urlAbsolute'];
1036      }
1037  
1038      /**

1039       * Get the absolute URL for a specified object. Only applicable to sources that are streams.

1040       * 

1041       * @param string $object

1042       * @return string

1043       */
1044      public function getObjectUrl($object = '') {
1045          return $this->getBaseUrl().$object;
1046      }
1047  }

title

Description

title

Description

title

Description

title

title

Body