ajaxAction = 'files_action'; $this->setTemplateName('files'); $this->isUnionAllowed = true; return true; } /** * Установить поле внутрь объединения полей * @param Union $union */ public function setUnion($union) { # для групового поля, данные о загруженных файлах хранятся вместе с данными других полей parent::setUnion($union); if ($this->group) { $union->activateSavedKey(); } } /** * Генерация основного контента поля * @param array $data @ref данные * @return string HTML */ public function view(array &$data = []) { $union = $this->unionID(); if ($union) { $union = 'Union' . $union; } $data['group'] = $union; $jsName = $this->form->jsObjectName($union . 'files' . $this->id()); $data['jsName'] = $jsName; $data['noJsRender'] = 1; $data['value'] = $this->value(); $data['uploader'] = $this->uploader(); $data['recordID'] = $this->form->recordID(); $html = $this->render($data); $this->form->initionsJavascript($jsName, $this->jsRender()); return $html; } /** * Инициализация загрузчика * @return FilesUploaderField */ public function uploader() { if (! $this->uploader) { $this->uploader = new FilesUploaderField($this); } return $this->uploader; } /** * Обработка ajax запросов * @return array|bool данные для ajax ответа */ public function ajax() { # загрузка нового файла $this->ajaxHandler('upload', function () { $deleted = $this->input->get('deleted', TYPE_ARRAY_STR); if (! empty($deleted)) { $this->uploader()->deleteFiles($deleted); } $result = $this->uploader()->uploadQQ(); $response = array('success' => ($result !== false && $this->errors->no())); if ($result !== false) { $response = array_merge($response, $result); $response['url'] = $this->uploader->getUrl($result, $this->uploader->isTmp()); $response['filesize'] = tpl::filesize($result['filesize']); if ($this->uploader->isTmp()) { # при добавлении записи, данные о новых файлах храним в форме $response['filedata'] = base64_encode(json_encode($result)); } } $response['errors'] = $this->errors->get(); return $this->ajaxResponse($response, true); }); # удаление временного файла, если recordID = 0 $this->ajaxHandler('delete-tmp', function () { $filename = $this->input->post('filename', TYPE_STR); $this->uploader()->setRecordID(0); $this->uploader->deleteTmpFile($filename); return []; }); return parent::ajax(); } /** * Установка значения поля при загрузке данных из БД * @param mixed $data * @return void */ public function setValue($data) { $value = $this->uploader()->getData(); # построим URL для скачивания для загруженных файлов foreach ($value as &$v) { $v['url'] = $this->uploader->getUrl($v); } unset($v); if ($this->unionID() && $this->group) { # если внутри групового поля - порядок файлов записан в груповом поле $result = []; foreach ($data as $v) { foreach ($value as $vv) { if ($v == $vv['filename']) { $result[] = $vv; continue 2; } } } $value = $result; } parent::setValue($value); } /** * Проверка значения поля * @param array $data ['value' => &$value], 'value' - ссылка на значение поля * @return bool true - значение корректно, false - значение некорректно, пропустить (не сохраняется в БД) */ public function validate($data) { if ($this->unionID()) { if ($this->group || ! $this->form->recordID()) { if (empty($data['value'])) { $data['value'] = []; } return true; } } return false; } /** * Выполнение действий после сохранения (точно есть recordID) * @param bool $isInserted - была добавленна новая запись false - редактирование существующей * @param array $params ['saved' => &$saved], 'saved' - сохраненные данные * @return void */ public function validateAfter($isInserted, $params) { $name = $this->name(); $union = $this->unionID(); if ($union) { $groupName = $this->union->name(); if ($isInserted) { $groupKey = $this->union->savedKey; if ($groupKey && isset($params['saved'][$groupName][$groupKey])) { $saved = $params['saved'][$groupName][$groupKey]; } elseif (isset($params['saved'][$groupName][$name])) { $saved = $params['saved'][$groupName][$name]; } if (! empty($saved)) { $data = []; # получим данные о загруженных файлах из сохраненных данных групового поля foreach ($saved as $v) { if ($groupKey && ! empty($v[$name])) { $data = array_merge($data, $v[$name]); } elseif (is_scalar($v)) { $data[] = $v; } } if (! empty($data)) { # переместим файлы из временного каталога в постоянный $filesData = $this->newFilesData(); $this->uploader()->saveTmp($data, $filesData); } } } else { $deleted = $this->input->post($this->deleteName(), TYPE_ARRAY); if (! empty($deleted)) { # удалим удаленные $this->uploader()->deleteFiles($deleted); } } } else { $data = $this->input->post($name, TYPE_ARRAY); if ($isInserted) { # переместим файлы из временного каталога в постоянный $filesData = $this->newFilesData(); $this->uploader()->saveTmp($data, $filesData); } else { if (! empty($data)) { # сохраним порядок $this->uploader()->saveOrder($data); } $deleted = $this->input->post($this->deleteName(), TYPE_ARRAY); if (! empty($deleted)) { # удалим удаленные $this->uploader()->deleteFiles($deleted); } } } } /** * Действия после завершения отрисовки группы * @return string HTML */ public function afterGroupRender() { # могут быть файлы, которые загрузили, но не сохранили в данных о группе, отправим такие файлы на удаление if (! $this->unionID()) { return ''; } # список файлов внутри группы $exist = []; $name = $this->name(); $value = $this->union->value(); foreach ($value as $v) { if (empty($v[$name])) continue; foreach ($v[$name] as $vv) { $exist[] = is_array($vv) ? $vv['filename'] : $vv; } } $exist = array_unique($exist); # список загруженных файлов $data = $this->uploader()->getData(); foreach ($data as $k => $v) { if (in_array($v['filename'], $exist)) { unset($data[$k]); } } # список файлов для удаления $result = []; if (! empty($data)) { foreach ($data as $v) { $result[] = ''; } } return join('', $result); } /** * Генерация имени input hidden содержащих данные о удаляемых файлах * @return string */ public function deleteName() { return 'delete_file_' . $this->id() . ($this->unionID() ? '_' . $this->unionID() : ''); } /** * Генерация имени input hidden содержащих данные о файлах, для добавляемых записях в форме * @return string */ public function newDataName() { return 'data_file_' . $this->id() . ($this->unionID() ? '_' . $this->unionID() : ''); } /** * Получаем данные о загруженных файлах из формы * @return array */ public function newFilesData() { $result = []; $data = $this->input->post($this->newDataName(), TYPE_ARRAY); foreach ($data as $v) { $v = json_decode(base64_decode($v), true); if (empty($v['filename'])) continue; $result[ $v['filename'] ] = $v; } return $result; } /** * Обработка события удаления записи формой * @param int $recordID ID записи */ public function recordDelete($recordID) { $this->uploader()->deleteAllFiles(); } /** * Получение данных о номере записи из формы * @return int */ public function recordID() { return $this->form->recordID(); } /** * Получить папку для хранения загруженных файлов из формы * @return string */ public function folder() { return $this->form->folder(); } /** * Загрузка данных для аплоадера * @return array */ public function loadRecordData() { $union = $this->unionID(); $saved = $this->form->_ajaxData($union ? $union : $this->id(), []); if (! is_array($saved)) { $saved = []; } if ($union) { $name = $this->name(); if (isset($saved[$name])) { $saved = $saved[$name]; } else { $saved = []; } } return $saved; } /** * Сохранение данных аплоадером * @param array $data * @return void */ public function saveRecordData(array $data) { foreach ($data as $k => &$v) { if (! is_array($v)) { continue; } $url = $this->uploader->getURL($v); $url = str_replace(SITEURL_STATIC, '//{sitehost}', $url); $v['url'] = $url; $path = $this->uploader->getPath($v); $path = str_replace(PATH_BASE, '{path_base}', $path); $v['path'] = $path; } unset($v); $union = $this->unionID(); if ($union) { $name = $this->name(); $saved = $this->form->_ajaxData($union, []); if (! is_array($saved)) { $saved = []; } $saved[$name] = $data; $this->form->_ajaxSave($union, $saved); } else { $this->form->_ajaxSave($this->id(), $data); } } /** * Получение значения необходимости раскладывать файлы по папкам * @param bool|null $folderByID * @return bool */ public function folderByID($folderByID = null) { if (! is_null($folderByID)) { $this->folderByID = (bool)$folderByID; } return $this->folderByID; } /** * Загрузка файла из существующего файла * @param string $file путь к файлу */ public function uploadFromFile($file) { $this->uploader()->setRecordID($this->form->recordID()); $this->uploader()->uploadFromFile($file); } /** * Получение значения максимального количества файлов * @return int */ public function limit() { return $this->limit; } /** * Получение значения максимального размера файла * @return int */ public function maxSize() { return $this->maxSize; } /** * Получение значения publicStore * @return bool */ public function publicStore() { return $this->publicStore; } /** * Получение списка разрешенных расширений файлов * @return string */ public function extensions() { return $this->extensions; } }