init(); $this->setSettings($settings); $this->files = $files ?? bff('files'); $this->initField($field); } /** * Установить номер записи * @param int|string $id * @return void */ public function setRecordID($id) { $this->recordID = (int)$id; } /** * Настройки по умолчанию * @return void */ public function initSettings() { $this->filenameLetters = 10; $this->sizes = []; $this->limit = 1000; $this->extensionsAllowed = ['jpg', 'jpeg', 'gif', 'png']; } /** * Инициализания настроек в зависимости от настроек поля Files * @param Files $field * @return void */ public function initField(Files $field) { $this->field = $field; $this->setRecordID($this->field->recordID()); $this->folderByID = $this->field->folderByID(); $this->publicStore = $field->publicStore(); $maxSize = $this->field->maxSize(); if (! empty($maxSize)) { $this->maxSize = $maxSize; } if (! empty($field->extensions())) { $this->extensionsAllowed = $field->extensions(); } // if (! $field->unionID()) { // todo // $this->setLimit($field->limit()); // } $folder = $this->field->folder(); if ($this->files->isDirectory($folder)) { $this->path = $folder; if ($this->isPublicStore()) { $this->url = str_replace($this->app->publicPath(), SITEURL_STATIC . DS, $folder); } } else { if ($this->isPublicStore()) { $this->path = $this->app->publicPath('files/extensions/' . $folder . '/'); $this->url = bff::url('extensions') . $folder . DS; } else { $this->path = $this->app->basePath('files/extensions/' . $folder . '/'); } } $this->pathTmp = $this->app->publicPath('files/images/tmp/'); $this->urlTmp = bff::url('tmp', 'images'); if (! $this->files->isDirectory($this->path)) { $this->files->makeDirectory($this->path); if (! $this->files->isDirectory($this->path)) { $this->errors->set(_t('@', 'Can\'t create the folder: [path]', ['path' => $this->path])); return; } } if (! $this->files->isWritable($this->path)) { $this->errors->set(_t('@', 'Can\'t write to the folder: [path]', ['path' => $this->path])); return; } } /** * Получаем способ хранения файлов * @return bool */ public function isPublicStore() { return $this->publicStore; } /** * Установка разрешенных расширений * @param string $extensions * @return void */ public function setAllowedExtensions($extensions) { $this->extensionsAllowed = $extensions; } /** * Инициализация компонента загрузки файлов * @return void */ protected function initAttach() { if ($this->attach) { return; } $this->attach = new Attachment($this->pathTmp, $this->maxSize); $this->attach->setAllowedExtensions(( is_array($this->extensionsAllowed) ? $this->extensionsAllowed : explode(',', $this->extensionsAllowed) )); $this->attach->setFiledataAsString(false); $this->attach->setCheckFreeDiskSpace(false); $this->attach->setAssignErrors($this->assignErrors); } /** * Загрузка файла при помощи QQ-загрузчика * @return mixed */ public function uploadQQ() { $this->initAttach(); $file = $this->attach->uploadQQ(); if ($this->recordID) { $this->saveFile($file); } return $file; } /** * Загрузка файла из существующего файла * @param string $file путь к файлу * @return void */ public function uploadFromFile($file) { if (! $this->files->exists($file)) { return; } $extension = $this->files->extension($file); $fileName = func::generator(14, false) . '.' . $extension; $path = $this->getPath(['filename' => $fileName], true); $this->files->copy($file, $path); if (! $this->files->exists($path)) { return; } $this->saveFile([ 'filename' => $fileName, 'filesize' => $this->files->size($path), 'rfilename' => $this->files->basename($file), 'extension' => $extension, ]); } /** * Получение данных о загруженных файлах * @return array */ public function getData() { return $this->loadRecordData(); } /** * Максимальный размер загружаемого файла * @param bool $format * @param bool $formatExtTitle * @return int|string */ public function getMaxSize($format = false, $formatExtTitle = false) { if ($format) { return tpl::filesize($this->maxSize, $formatExtTitle); } return $this->maxSize; } /** * Сохранение данных о загруженном файле * @param array $file * @return void */ public function saveFile($file) { if (empty($file)) { return; } if (! empty($file['error'])) { return; } $data = $this->loadRecordData(); unset($file['error']); $tmp = $this->getPath($file, true); if (! $this->files->exists($tmp)) { return; } $new = $this->getPath($file); $this->files->move($tmp, $new); $data[] = $file; $this->saveRecordData($data); } /** * Перенос файлов из временной папки в постоянную * @param array $files список имен файлов * @param array $filesData массив с данными о файлах * @return void */ public function saveTmp(array $files, array $filesData) { $save = []; foreach ($files as $v) { $tmp = $this->getPath(['filename' => $v], true); if (! $this->files->exists($tmp)) { continue; } if (! isset($filesData[ $v ])) { continue; } $file = $filesData[ $v ]; unset($file['error']); $new = $this->getPath($file); $this->files->move($tmp, $new); if (! $this->files->exists($new)) { continue; } $save[] = $file; } $this->saveRecordData($save); } /** * Формирование url для скачивания файла * @param array $file данные о файле * @param bool $tmp временый файл * @return string */ public function getUrl($file, $tmp = false) { if ($this->isPublicStore()) { if ($tmp) { return $this->urlTmp . $file['filename']; } return $this->url . ($this->folderByID ? $this->getDir() . '/' : '') . $this->recordID . $file['filename']; } return 'javascript:'; } /** * Формирование пути к файлу * @param array $file данные о файле * @param bool $tmp временый файл * @return string */ public function getPath($file, $tmp = false) { if (! isset($file['filename'])) { return ''; } if ($tmp) { return $this->pathTmp . $file['filename']; } return $this->path . ($this->folderByID ? $this->getDir() . DS : '') . $this->recordID . $file['filename']; } /** * Формирование пути к временному файлу * @param string $file * @return bool */ public function getPathTmp($file) { if (! $this->isTmp()) { return false; } return $this->getPath(['filename' => $file], true); } /** * Сохранение порядка файлов * @param array $files * @return void */ public function saveOrder($files) { if (empty($files) || ! is_array($files)) { return; } $data = $this->loadRecordData(); $save = []; foreach ($files as $v) { foreach ($data as $kk => $vv) { if ($v == $vv['filename']) { $save[] = $vv; unset($data[$kk]); break; } } } foreach ($data as $v) { $save[] = $v; } $this->saveRecordData($save); } /** * Удаление файлов * @param array $files */ public function deleteFiles($files) { if (empty($files)) { return; } if (! is_array($files)) { $files = array($files); } $data = $this->loadRecordData(); foreach ($data as $k => $v) { if (in_array($v['filename'], $files)) { $path = $this->getPath($v); if ($this->files->exists($path)) { $this->files->delete($path); } unset($data[$k]); } } $this->saveRecordData($data); } /** * Удаление временного файла * @param string $file * @return void */ public function deleteTmpFile($file) { $path = $this->getPath(['filename' => $file], true); if ($this->files->exists($path)) { $this->files->delete($path); } } /** * Удаления всех файлов записи * @param bool $updateDB обновить данные в БД * @return void */ public function deleteAllFiles($updateDB = false) { $data = $this->loadRecordData(); foreach ($data as $v) { $path = $this->getPath($v); if ($this->files->exists($path)) { $this->files->delete($path); } } if ($updateDB) { $this->saveRecordData([]); } } /** * Флаг новая запись или нет * @return bool */ public function isTmp() { return $this->recordID ? false : true; } /** * Формирование названия директории исходя из ID записи * @return string название директории */ protected function getDir() { $dir = (string)intval($this->recordID / $this->folderByID_RecordsLimit); if (! $this->files->exists($this->path.$dir)) { $this->files->makeDirectory($this->path . $dir, 0775, true); } return $dir; } /** * Загрузка данных о загруженных файлах для текущей записи * @return array */ protected function loadRecordData() { return $this->field->loadRecordData(); } /** * Сохранение данных о загруженных файлах для текущей записи * @param array $data * @return void */ protected function saveRecordData(array $data) { $this->field->saveRecordData($data); } }