* */ class ModuleProperty_EntityValueTypeFile extends ModuleProperty_EntityValueType { public function getValueForDisplay() { return $this->getFileFullName(); } public function validate() { $oValue=$this->getValueObject(); $oProperty=$oValue->getProperty(); $iPropertyId=$oProperty->getId(); $mValue=$this->getValueForValidate(); if (isset($mValue['remove']) and $mValue['remove']) { $this->setValueForValidate(array('remove'=>true)); } $sFileName=$this->_getValueFromFiles($iPropertyId,'name'); $sFileTmpName=$this->_getValueFromFiles($iPropertyId,'tmp_name'); $sFileError=$this->_getValueFromFiles($iPropertyId,'error'); $sFileSize=$this->_getValueFromFiles($iPropertyId,'size'); if (!$sFileTmpName) { if ($oProperty->getValidateRuleOne('allowEmpty')) { return true; } elseif ($aFilePrev=$oValue->getDataOne('file') and isset($aFilePrev['path'])) { return true; } else { return 'Необходимо выбрать файл'; } } /** * Проверяем на ошибки */ if ($sFileError and $sFileError!=UPLOAD_ERR_NO_FILE) { return "При загрузке файла возникла ошибка - {$sFileError}"; } /** * На корректность загрузки */ if (!$sFileName or !$sFileTmpName) { return false; } /** * На ограниечение по размеру файла */ if ($iSizeKb=$oProperty->getValidateRuleOne('size_max') and $iSizeKb*1025 < $sFileSize) { return "Превышен размер файла, максимальный {$iSizeKb}Kb"; } /** * На допустимые типы файлов */ $aPath=pathinfo($sFileName); if (!isset($aPath['extension']) or !$aPath['extension']) { return false; } if ($aTypes=$oProperty->getParam('types') and !in_array($aPath['extension'],$aTypes)) { return 'Неверный тип файла, допустимы '.join(', ',$aTypes); } /** * Пробрасываем данные по файлу */ $this->setValueForValidate(array( 'name'=>$sFileName, 'tmp_name'=>$sFileTmpName, 'error'=>$sFileError, 'size'=>$sFileSize, )); return true; } protected function _getValueFromFiles($iId,$sName) { if (isset($_FILES['property'][$sName][$iId]['file'])) { return $_FILES['property'][$sName][$iId]['file']; } return null; } /** * Устанавливает значение после валидации конкретного поля, а не всех полей * Поэтому здесь нельзя сохранять файл, это нужно делать в beforeSaveValue() * * @param $aValue */ public function setValue($aValue) { $oValue=$this->getValueObject(); /** * Просто пробрасываем данные */ if ($aValue) { $oValue->setDataOne('file_raw',$aValue); } } /** * Дополнительная обработка перед сохранением значения * Здесь нужно выполнять основную загрузку файла */ public function beforeSaveValue() { $oValue=$this->getValueObject(); $oProperty=$oValue->getProperty(); if (!$aFile=$oValue->getDataOne('file_raw')) { return true; } $oValue->setDataOne('file_raw',null); /** * Удаляем предыдущий файл */ if (isset($aFile['remove']) or isset($aFile['name'])) { if ($aFilePrev=$oValue->getDataOne('file')) { $this->RemoveFile($aFilePrev['path']); $oValue->setDataOne('file',array()); $oValue->setValueVarchar(null); } } if (isset($aFile['name'])) { /** * Выполняем загрузку файла */ $aPathInfo=pathinfo($aFile['name']); $sExtension=isset($aPathInfo['extension']) ? $aPathInfo['extension'] : 'unknown'; $sFileName = func_generator(20).'.'.$sExtension; /** * Копируем загруженный файл */ $sDirTmp=Config::Get('path.tmp.server').'/property/'; if (!is_dir($sDirTmp)) { @mkdir($sDirTmp,0777,true); } $sFileTmp=$sDirTmp.$sFileName; if (move_uploaded_file($aFile['tmp_name'],$sFileTmp)) { $sDirSave=Config::Get('path.root.server').$oProperty->getSaveFileDir(); if (!is_dir($sDirSave)) { @mkdir($sDirSave,0777,true); } $sFilePath=$sDirSave.$sFileName; /** * Сохраняем файл */ if ($sFilePathNew=$this->SaveFile($sFileTmp,$sFilePath,null,true)) { /** * Сохраняем данные о файле */ $oValue->setDataOne('file',array( 'path'=>$sFilePathNew, 'size'=>filesize($sFilePath), 'name'=>htmlspecialchars($aPathInfo['filename']), 'extension'=>htmlspecialchars($aPathInfo['extension']), )); /** * Сохраняем уникальный ключ для доступа к файлу */ $oValue->setValueVarchar(func_generator(32)); return true; } } } } public function prepareValidateRulesRaw($aRulesRaw) { $aRules=array(); $aRules['allowEmpty']=isset($aRulesRaw['allowEmpty']) ? false : true; if (isset($aRulesRaw['size_max']) and is_numeric($aRulesRaw['size_max'])) { $aRules['size_max']=(int)$aRulesRaw['size_max']; } return $aRules; } public function prepareParamsRaw($aParamsRaw) { $aParams=array(); $aParams['types']=array(); if (isset($aParamsRaw['types']) and is_array($aParamsRaw['types'])) { foreach($aParamsRaw['types'] as $sType) { if ($sType) { $aParams['types'][]=htmlspecialchars($sType); } } } $aParams['access_only_auth']=isset($aParamsRaw['access_only_auth']) ? true : false; return $aParams; } public function getParamsDefault() { return array( 'types'=>array( 'zip' ), ); } public function removeValue() { $oValue=$this->getValueObject(); /** * Удаляем файл */ if ($aFilePrev=$oValue->getDataOne('file')) { $this->RemoveFile($aFilePrev['path']); } } public function getFileFullName() { $oValue=$this->getValueObject(); if ($aFilePrev=$oValue->getDataOne('file')) { return $aFilePrev['name'].'.'.$aFilePrev['extension']; } return null; } /** * Сохраняет(копирует) файл на сервер * Если переопределить данный метод, то можно сохранять файл, например, на Amazon S3 * * @param string $sFileSource Полный путь до исходного файла * @param string $sFileDest Полный путь до файла для сохранения с типом, например, [server]/home/var/site.ru/book.pdf * @param int|null $iMode Права chmod для файла, например, 0777 * @param bool $bRemoveSource Удалять исходный файл или нет * @return bool | string При успешном сохранении возвращает относительный путь до файла с типом, например, [relative]/image.jpg */ protected function SaveFile($sFileSource,$sFileDest,$iMode=null,$bRemoveSource=false) { if ($this->Fs_SaveFileLocal($sFileSource,$this->Fs_GetPathServer($sFileDest),$iMode,$bRemoveSource)) { return $this->Fs_MakePath($this->Fs_GetPathRelativeFromServer($sFileDest),ModuleFs::PATH_TYPE_RELATIVE); } return false; } /** * Удаляет файл * Если переопределить данный метод, то можно удалять файл, например, с Amazon S3 * * @param string $sPathFile Полный путь до файла с типом, например, [relative]/book.pdf * * @return mixed */ protected function RemoveFile($sPathFile) { $sPathFile=$this->Fs_GetPathServer($sPathFile); return $this->Fs_RemoveFileLocal($sPathFile); } public function DownloadFile() { $oValue=$this->getValueObject(); if ($aFilePrev=$oValue->getDataOne('file')) { $this->Tools_DownloadFile($this->Fs_GetPathServer($aFilePrev['path']),$aFilePrev['name'].'.'.$aFilePrev['extension'],$aFilePrev['size']); } return false; } }