ctx) {
$this->ctx =& $this->xpdo->context;
}
$options['context'] = $this->ctx->get('key');
$this->fileHandler = $this->xpdo->getService('fileHandler','modFileHandler', '',$options);
return true;
}
/**
* Get base paths/urls and sanitize incoming paths
*
* @param string $path A path to the active directory
* @return array
*/
public function getBases($path = '') {
$properties = $this->getProperties();
$bases = array();
$path = $this->fileHandler->sanitizePath($path);
$bases['path'] = $properties['basePath']['value'];
$bases['pathIsRelative'] = false;
if (!empty($properties['basePathRelative']['value'])) {
$realpath = realpath($this->ctx->getOption('base_path', MODX_BASE_PATH) . $bases['path']);
$bases['pathAbsolute'] = ($realpath !== false) ? $realpath. '/' : '';
$bases['pathIsRelative'] = true;
} else {
$bases['pathAbsolute'] = $bases['path'];
}
$bases['pathAbsoluteWithPath'] = $bases['pathAbsolute'].ltrim($path,'/');
if (is_dir($bases['pathAbsoluteWithPath'])) {
$bases['pathAbsoluteWithPath'] = $this->fileHandler->postfixSlash($bases['pathAbsoluteWithPath']);
}
$bases['pathRelative'] = ltrim($path,'/');
/* get relative url */
$bases['urlIsRelative'] = false;
$bases['url'] = $properties['baseUrl']['value'];;
if (!empty($properties['baseUrlRelative']['value'])) {
$bases['urlAbsolute'] = $this->ctx->getOption('base_url',MODX_BASE_URL).$bases['url'];
$bases['urlIsRelative'] = true;
} else {
$bases['urlAbsolute'] = $bases['url'];
}
$bases['urlAbsoluteWithPath'] = $bases['urlAbsolute'].ltrim($path,'/');
$bases['urlRelative'] = ltrim($path,'/');
return $bases;
}
/**
* Get the ID of the edit file action
*
* @return boolean|int
*/
public function getEditActionId() {
return 'system/file/edit';
}
/**
* Return an array of files and folders at this current level in the directory structure
*
* @param string $path
* @return array
*/
public function getContainerList($path) {
$properties = $this->getPropertyList();
$path = $this->fileHandler->postfixSlash($path);
$bases = $this->getBases($path);
if (empty($bases['pathAbsolute'])) return array();
$fullPath = $bases['pathAbsolute'].ltrim($path,'/');
$useMultibyte = $this->getOption('use_multibyte',$properties,false);
$encoding = $this->getOption('modx_charset',$properties,'UTF-8');
$hideFiles = !empty($properties['hideFiles']) && $properties['hideFiles'] != 'false' ? true : false;
$hideTooltips = !empty($properties['hideTooltips']) && $properties['hideTooltips'] != 'false' ? true : false;
$editAction = $this->getEditActionId();
$imagesExts = $this->getOption('imageExtensions',$properties,'jpg,jpeg,png,gif,svg');
$imagesExts = explode(',',$imagesExts);
$skipFiles = $this->getOption('skipFiles',$properties,'.svn,.git,_notes,nbproject,.idea,.DS_Store');
$skipFiles = explode(',',$skipFiles);
if ($this->xpdo->getParser()) {
$this->xpdo->parser->processElementTags('',$skipFiles,true,true);
}
$skipFiles[] = '.';
$skipFiles[] = '..';
$allowedExtensions = $this->getOption('allowedFileTypes', $properties, '');
if (is_string($allowedExtensions)) {
if (empty($allowedExtensions)) {
$allowedExtensions = array();
} else {
$allowedExtensions = array_map("trim",explode(',', $allowedExtensions));
}
}
$canSave = $this->checkPolicy('save');
$canRemove = $this->checkPolicy('remove');
$canCreate = $this->checkPolicy('create');
$directories = array();
$dirnames = array();
$files = array();
$filenames = array();
if (!is_dir($fullPath)) return array();
/* iterate through directories */
/** @var DirectoryIterator $file */
foreach (new DirectoryIterator($fullPath) as $file) {
if (in_array($file,$skipFiles)) continue;
if (!$file->isReadable()) continue;
$fileName = $file->getFilename();
if (in_array(trim($fileName,'/'),$skipFiles)) continue;
if (in_array($fullPath.$fileName,$skipFiles)) continue;
$filePathName = $file->getPathname();
$octalPerms = substr(sprintf('%o', $file->getPerms()), -4);
/* handle dirs */
$cls = array();
if ($file->isDir() && $this->hasPermission('directory_list')) {
$cls[] = 'folder';
if ($this->hasPermission('directory_chmod') && $canSave) $cls[] = 'pchmod';
if ($this->hasPermission('directory_create') && $canCreate) $cls[] = 'pcreate';
if ($this->hasPermission('directory_remove') && $canRemove) $cls[] = 'premove';
if ($this->hasPermission('directory_update') && $canSave) $cls[] = 'pupdate';
if ($this->hasPermission('file_upload') && $canCreate) $cls[] = 'pupload';
if ($this->hasPermission('file_create') && $canCreate) $cls[] = 'pcreate';
$dirnames[] = strtoupper($fileName);
$directories[$fileName] = array(
'id' => $bases['urlRelative'].rtrim($fileName,'/').'/',
'text' => $fileName,
'cls' => implode(' ',$cls),
'iconCls' => 'icon icon-folder',
'type' => 'dir',
'leaf' => false,
'path' => $bases['pathAbsoluteWithPath'].$fileName,
'pathRelative' => $bases['pathRelative'].$fileName,
'perms' => $octalPerms,
'menu' => array(),
);
$directories[$fileName]['menu'] = array('items' => $this->getListContextMenu($file,$directories[$fileName]));
}
/* get files in current dir */
if ($file->isFile() && !$hideFiles && $this->hasPermission('file_list')) {
$ext = pathinfo($filePathName, PATHINFO_EXTENSION);
$ext = $useMultibyte ? mb_strtolower($ext, $encoding) : strtolower($ext);
if (!empty($allowedExtensions) && !in_array($ext, $allowedExtensions)) {
continue;
}
$cls = array();
if (!empty($properties['currentFile']) && rawurldecode($properties['currentFile']) == $fullPath.$fileName && $properties['currentAction'] == $editAction) {
$cls[] = 'active-node';
}
if ($this->hasPermission('file_remove') && $canRemove) $cls[] = 'premove';
if ($this->hasPermission('file_update') && $canSave) $cls[] = 'pupdate';
$encFile = rawurlencode($fullPath.$fileName);
$page = !empty($editAction) ? '?a='.$editAction.'&file='.$bases['urlRelative'].$fileName.'&wctx='.$this->ctx->get('key').'&source='.$this->get('id') : null;
$url = $bases['urlRelative'] . $fileName;
/* get relative url from manager/ */
$fromManagerUrl = $bases['url'].trim(str_replace('//','/',$path.$fileName),'/');
$fromManagerUrl = ($bases['urlIsRelative'] ? '../' : '').$fromManagerUrl;
$filenames[] = strtoupper($fileName);
$files[$fileName] = array(
'id' => $bases['urlRelative'].$fileName,
'text' => $fileName,
'cls' => implode(' ',$cls),
'iconCls' => 'icon icon-file icon-'.$ext . ($file->isWritable() ? '' : ' icon-lock'),
'type' => 'file',
'leaf' => true,
// 'qtip' => in_array($ext,$imagesExts) ? '
' : '',
'page' => $this->fileHandler->isBinary($filePathName) ? null : $page,
'perms' => $octalPerms,
'path' => $bases['pathAbsoluteWithPath'].$fileName,
'pathRelative' => $bases['pathRelative'].$fileName,
'directory' => $bases['path'],
'url' => $bases['url'].$url,
'urlAbsolute' => $bases['urlAbsoluteWithPath'].ltrim($fileName,'/'),
'file' => $encFile,
'menu' => array(),
);
$files[$fileName]['menu'] = array('items' => $this->getListContextMenu($file,$files[$fileName]));
// trough tree config we can request a tree without image-preview tooltips, don't do any work if not necessary
if (!$hideTooltips) {
$files[$fileName]['qtip'] = '';
if (in_array($ext, $imagesExts)) {
$modAuth = $this->xpdo->user->getUserToken($this->xpdo->context->get('key'));
$preview = true;
$imageWidth = $this->ctx->getOption('filemanager_image_width', 400);
$imageHeight = $this->ctx->getOption('filemanager_image_height', 300);
$thumbnailType = $this->getOption('thumbnailType', $properties, 'png');
$thumbnailQuality = $this->getOption('thumbnailQuality', $properties, 90);
if ($ext == 'svg') {
$svgString = @file_get_contents($bases['pathAbsoluteWithPath'].$fileName);
preg_match('/(