public function set($value, &$node)
 {
     if (empty($value) or !is_array($value)) {
         return;
     }
     switch ($value['error']) {
         case UPLOAD_ERR_OK:
             $value = Node::create('file')->import($value);
             break;
         case UPLOAD_ERR_INI_SIZE:
             throw new RuntimeException(t('Размер файла превышает установленное в системе ограничение (%size).', array('%size' => ini_get('upload_max_filesize'))));
         case UPLOAD_ERR_FORM_SIZE:
             throw new RuntimeException(t('Размер файла превышает установленное в форме ограничение.'));
         case UPLOAD_ERR_PARTIAL:
             throw new RuntimeException(t('Файл получен не полностью.'));
         case UPLOAD_ERR_NO_FILE:
             if (!empty($value['id']) and is_numeric($value['id'])) {
                 $value = Node::load($value['id']);
             } elseif (!empty($value['url'])) {
                 $value = FileNode::fromURL($value['url']);
             } elseif (!empty($value['ftp'])) {
                 $value = Node::create('file')->importFromFTP(array_shift($value['ftp']));
             } elseif (!empty($value['unlink'])) {
                 $node->linkRemoveChild(null, $this->value);
                 $value = null;
             } else {
                 $value = $node->{$this->value};
             }
     }
     if ($this->required and empty($value)) {
         throw new ValidationException($this->label, t('Вы не загрузили файл в поле «%name», хотя оно отмечено как обязательное.', array('%name' => mb_strtolower($this->label))));
     }
     $node->{$this->value} = $value;
 }
Example #2
0
 /**
  * Обработка файла.
  */
 public static function transform(FileNode $node)
 {
     if (0 !== strpos($node->filetype, 'image/')) {
         return;
     }
     $result = array();
     // Относительный путь к исходному файлу
     $source = $node->getRealURL();
     // Путь к файловому хранилищу, используется только чтобы
     // из полного пути сделать относительный после трансформации.
     $storage = Context::last()->config->getPath('modules/files/storage', 'files');
     // Файлы без расширений не обрабатываем, чтобы не нагенерировать каких-нибудь странных имён.
     /*
     if (!($ext = os::getFileExtension($source)))
       return;
     */
     // Правила перевода расширений в типы.
     $typemap = array('png' => 'image/png', 'jpg' => 'image/jpeg');
     foreach (Context::last()->config->getArray(self::confroot) as $name => $settings) {
         if (empty($ext)) {
             $target = $source . '.' . $name . '.' . $settings['format'];
         } else {
             $target = substr($source, 0, -strlen($ext)) . $name . '.' . $settings['format'];
         }
         if (file_exists($target)) {
             unlink($target);
         }
         $im = ImageMagick::getInstance();
         if ($im->open($source, $node->filetype)) {
             $options = array('downsize' => $settings['scalemode'] != 'crop', 'crop' => $settings['scalemode'] == 'crop', 'quality' => intval($settings['quality']));
             if ($im->scale($settings['width'], $settings['height'], $options)) {
                 if ($im->save($target, $typemap[$settings['format']])) {
                     $tmp = array('width' => $im->getWidth(), 'height' => $im->getHeight(), 'filename' => substr($target, strlen($storage) + 1), 'filesize' => filesize($target));
                     $result[$name] = $tmp;
                 }
             }
         }
     }
     return $result;
 }
Example #3
0
 /**
  * Импорт файла из внешнего источника.
  *
  * Используется как для обработки полученных от браузера файлов, так и для
  * ручного добавления файлов в архив.  Путь к файловому архиву определяется
  * конфигурационным файлом (параметр files).
  *
  * Внутреннее имя файла при копировании в архив формируется с использованием
  * md5-суммы его содержимого, поэтому в архив нельзя два раза добавить один
  * файл.  При обнаружении попытки повторной загрузки файла (с таким же
  * filepath) метод прозрачно подменяет содержимое текущей ноды содержимым
  * уже существующей, новую не создаёт.
  *
  * При невозможности скопировать файл в архив возникает UserErrorException.
  *
  * @return void
  * @param array $file описание файла
  * @param bool $uploaded проверять, действительно ли файл пришёл от браузера.
  *
  * Обязательные ключи: tmp_name (полный путь к фалу, который нужно
  * скопировать в архив), опциональные: type, name, size, parent_id.  При
  * отсутствии type, тип файла определяется эвристически.
  *
  * При указании parent_id файл автоматически прикрепляется к указанной в этом
  * параметре ноде, с помощью Node::linkAddParent().
  */
 public function import(array $file, $uploaded = true)
 {
     if (!empty($file['tmp_name'])) {
         $storage = os::path(MCMS_SITE_FOLDER, Context::last()->config->get('modules/files/storage'));
         // Немного валидации.
         if (!file_exists($file['tmp_name'])) {
             throw new Exception(t('Загружаемый файл перестал существовать.'));
         }
         // Угадваем значения некоторых полей, для упрощения скриптинга.
         if (!isset($file['size'])) {
             $file['size'] = filesize($file['tmp_name']);
         }
         if (!isset($file['name'])) {
             $file['name'] = basename($file['tmp_name']);
         }
         if (!isset($file['type'])) {
             $file['type'] = os::getFileType($file['tmp_name']);
         }
         if ($this->id === null and FileNode::isUnzipable($file)) {
             if (null === ($node = $this->unzip($file['tmp_name']))) {
                 throw new InvalidArgumentException("ZIP file was empty");
             }
             $this->data = $node->getRaw();
             return $this;
         }
         $this->filepath = os::mkunique($this->getCleanFileName($file), $storage);
     } elseif (!empty($file['url'])) {
         $this->remoteurl = $file['url'];
     }
     $file = array_merge(array('name' => 'unnamed.bin', 'type' => 'application/octet-stream', 'size' => 0), $file);
     $this->filename = $this->name = $file['name'];
     $this->filetype = $file['type'];
     $this->filesize = $file['size'];
     if ($this->filepath and !empty($file['tmp_name'])) {
         // Сюда будем копировать файл.
         $dest = os::path($storage, $this->filepath);
         if (file_exists($dest)) {
             throw new RuntimeException(t('Такой файл уже есть.'));
         }
         // Создаём каталог для него.
         os::mkdir(dirname($dest), 'Файл не удалось сохранить, т.к. отсутствуют права на запись в каталог, где этот файл должен был бы храниться (%path).  Сообщите об этой проблеме администратору сайта.', array('%path' => dirname($dest)));
         // Копируем файл.
         if (!os::copy($file['tmp_name'], $dest)) {
             throw new RuntimeException(t('Не удалось скопировать файл %src в %dst.', array('%src' => $file['tmp_name'], '%dst' => $dest)));
         }
     }
     // Прикрепляем файл к родительскому объекту.
     if (!empty($file['parent_id'])) {
         $this->linkAddParent($file['parent_id']);
     }
     return $this;
 }