Окно, с помощью которого, можно будет загружать файлы на сервер из админки.
Архитектура и необходимые файлы
- assets
- components
- doodles
- js
- mgr
- widgets
- items.grid.js
- widgets
- mgr
- js
- doodles
- components
- core
- components
- doodles
- processors
- mgr
- upload.class.php
- mgr
- processors
- doodles
- components
Добавление кнопки
Как правило, в архитектуре административной панели предусматривается функция добавления верхней части с кнопками, поиском и т.д. функцией getTopBar, поэтому если работа ведется над модулем стандартной сборки modExtra то выглядет это будет следующим образом:
getTopBar: function () {
return [{
xtype: 'button',
cls: 'primary-button',
text: _('upload'),
handler: this.uploadFiles,
scope: this
}];
},
Сама функция просто возвращает массив объектов с параметрами, определяющими как будут выглядеть добавляемые элементы.
Параметр handler
объявляет обработчик для поля и это будет специально подготовленная функция uploadFiles
.
Добавление функции-обработчика
Та самая функция uploadFiles
, которая будет вызывать окно загрузки.
uploadFiles: function(btn) {
if (!this.uploader) {
aVer = MODx.config.version.split('.');
uploaddialog = ((aVer[0] == 2) && aVer[1] >= 3)? MODx.util.MultiUploadDialog.Dialog : Ext.ux.UploadDialog.Dialog;
this.uploader = new uploaddialog({
title: _('upload'),
url: this.config.url,
base_params: {
action: 'mgr/upload',
docid: Doodles.config.docid
},
cls: 'ext-ux-uploaddialog-dialog modx-upload-window'
});
this.uploader.on('hide', this.refresh,this);
this.uploader.on('close', this.refresh,this);
}
// Automatically open picker
this.uploader.show(btn);
this.uploader.buttons[0].input_file.dom.click();
},
Основной алгоритм:
- Проверяем версию модыкса. Если версия выше 2.3 то используем Мультизагружочное окно, иначе обычное (которое было в старых версиях);
- В
base_params
указываем параметрaction
- это процессор-обработчик, который будет раскидывать файлы; - По желанию, можем указать автоматическое вызывание проводника через браузер для выбора фйлов (последние 2 строчки функции).
Добавление процессора-обработчика
<?php
/**
* Upload files to a directory
*
* @param string $docid resource ID
*/
class modFileUploadProcessor extends modProcessor {
/** @var modMediaSource $source */
private $source;
private $privatemode;
private $filename;
public $path;
private $localpath;
private $calc_hash;
private $user_folders;
private $doc_folders;
public function checkPermissions() {
return $this->modx->hasPermission('file_upload');
}
public function getLanguageTopics() {
return array('file');
}
public function initialize() {
$this->calc_hash = $this->modx->getOption('fileupload.calchash');
$this->user_folders = $this->modx->getOption('fileupload.user_folders');
$this->doc_folders = $this->modx->getOption('fileupload.put_docid');
$this->path = $this->modx->getOption('fileupload.files_path');
$this->privatemode = $this->modx->getOption('fileupload.private');
$this->translit = $this->modx->getOption('fileupload.translit');
$this->setDefaultProperties(array('docid' => 0));
$this->localpath = '';
if ($this->user_folders)
$this->localpath .= (int) $this->modx->user->get('id') . '/';
if ($this->doc_folders)
$this->localpath .= (int) $this->getProperty('docid') . '/';
$this->setProperty('path', $this->path . $this->localpath);
$this->setProperty('source', $this->modx->getOption('fileupload.mediasource'));
if (!$this->getProperty('path')) return $this->modx->lexicon('file_folder_err_ns');
return true;
}
public function process() {
if (!$this->getSource())
return $this->failure($this->modx->lexicon('permission_denied'));
$this->source->setRequestProperties($this->getProperties());
$this->source->initialize();
if (!$this->source->checkPolicy('create'))
return $this->failure($this->modx->lexicon('permission_denied'));
// Create subfolder
if ($this->user_folders || $this->doc_folders) {
$path = $this->source->getBasePath() . $this->getProperty('path');
$d = $this->source->fileHandler->make($path, array(), 'modDirectory');
if (!$d->exists()) {
if (!$this->source->createContainer($this->getProperty('path'), ''))
return $this->failure($this->modx->lexicon('permission_denied'));
}
}
$path = $this->source->getBasePath() . $this->getProperty('path');
$list = array();
$this->modx->loadClass('FileItem');
// Create serie of FileItem objects
foreach ($_FILES as $file) {
$filename = $file['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$ext = strtolower($ext);
if ($this->translit)
$filename = modResource::filterPathSegment($this->modx, $filename);
// Generate name and check for existence
if ($this->privatemode)
$this->filename = FileItem::generateName() . ".$ext";
else
$this->filename = $filename;
$fullpath = '';
while(1) {
$fullpath = $path . '/' . $this->filename;
$f = $this->source->fileHandler->make($fullpath, array(), 'modFile');
if (!$f->exists()) break;
// Generate new name again
if ($this->privatemode)
$this->filename = FileItem::generateName() . ".$ext";
else
$this->filename = '_' . $this->filename;
}
$success = $this->source->uploadObjectsToContainer(
$this->getProperty('path'),
array(array( // emulate a $_FILES object
"name" => $this->filename,
"tmp_name" => $file['tmp_name'],
"error" => "0")
));
if (empty($success)) {
$msg = '';
$errors = $this->source->getErrors();
foreach ($errors as $k => $msg) {
$this->modx->error->addField($k,$msg);
}
return $this->failure($msg);
} else {
$fid = FileItem::generateName();
$date = date('Y-m-d H:i:s');
$fileitem = $this->modx->newObject('FileItem', array(
'fid' => $fid,
'docid' => $this->getProperty('docid'),
'name' => $filename,
'date' => $date,
'internal_name' => $this->filename,
'path' => $this->localpath,
'private' => $this->privatemode,
'uid' => $this->modx->user->get('id'),
'date' => date('Y-m-d H:i:s', time()),
'hash' => ($this->calc_hash)? sha1_file($fullpath) : NULL
));
if (!$fileitem->save())
return $this->failure($this->modx->lexicon('fileupload.item_err_save'));
$list[] = array(
'id' => $fileitem->get('id'),
'fid' => $fid,
'name' => $filename);
}
}
return $this->outputArray($list, count($list));
}
/**
* Get the active Source
* @return modMediaSource|boolean
*/
public function getSource() {
if (empty($this->source)) {
$this->modx->loadClass('sources.modMediaSource');
$this->source = modMediaSource::getDefaultSource($this->modx,$this->getProperty('source'));
}
if (empty($this->source) || !$this->source->getWorkingContext())
return false;
return $this->source;
}
}
return 'modFileUploadProcessor';
Примечание. За основу взята реализация из модуля FileAttach.