我正在尝试将设置传递给cakephp-file-storage-plugin提供的行为。但是,设置无法识别。例如,如果我尝试通过将GIF文件排除在阵列之外来排除它们,我仍然可以毫无错误地上传它们。通过日志记录,我可以确认行为是附加到模型的,但是当我记录设置时它们是空的。我知道插件/行为是有效的,但遗憾的是插件/行为的文档很少,所以我希望有人可以帮我弄清楚我做错了什么。
下面是我的模型代码,我通过$actsAs
传递设置以及完整的行为文件,我已经添加了日志记录以试图找出设置无效的原因。该日志记录的输出包含在下面。 ListingPhoto
的别名为Photo
,作为另一个类的hasMany关联,这就是调用输出中出现该名称的原因。但我无法完全解释为什么行为代码似乎为一个请求运行了这么多次。
我的模特:
<?php
App::uses('ImageStorage', 'FileStorage.Model');
class ListingPhoto extends ImageStorage {
public $name = 'ListingPhoto';
public $actsAs = array(
'Imagine.Imagine',
'FileStorage.UploadValidator' => array(
'localFile' => true,
'validate' => false,
'allowedExtensions' => array('jpg', 'jpeg', 'png')
),
);
public function upload($listing_id, $data) {
$data[$this->alias]['adapter'] = 'Local';
$data[$this->alias]['model'] = 'ListingPhoto';
$data[$this->alias]['foreign_key'] = $listing_id;
$this->create();
return $this->save($data);
}
public function afterDelete() {
parent::afterDelete();
$this->log($this->record);
StorageManager::adapter($this->record['Photo']['adapter'])->delete($this->record['Photo']['path']);
}
}
完整的行为文件,添加了我的日志记录:
<?php
App::uses('File', 'Utility');
App::uses('CakeNumber', 'Utility');
/**
* Upload Validation Behavior
*
* This behavior will validate uploaded files, nothing more, it won't take care of storage.
*
* @author Florian Krämer
* @copyright 2012 Florian Krämer
* @license MIT
*/
class UploadValidatorBehavior extends ModelBehavior {
/**
* Settings array
*
* @var array
*/
public $settings = array();
/**
* Default settings array
*
* @var array
*/
protected $_defaults = array(
'fileField' => 'file',
'validate' => true,
'allowNoFileError' => true,
'allowedMime' => null,
'allowedExtensions' => null,
'localFile' => false
);
/**
* Error message
*
* If something fails this is populated with an error message that can be passed to the view
*
* @var string
*/
public $uploadError = null;
/**
* Behavior setup
*
* Merge settings with default config, then it is checking if the target directory
* exists and if it is writeable. It will throw an error if one of both fails.
*
* @param \AppModel|\Model $Model
* @param array $settings
* @throws InvalidArgumentException
* @return void
*/
public function setup(Model $Model, $settings = array()) {
if (!is_array($settings)) {
throw new InvalidArgumentException(__d('file_storage', 'Settings must be passed as array!'));
}
$this->log("SETTINGS for {$Model->alias}:");
$this->log($settings);
// $this->settings[$Model->alias] = array_merge($this->_defaults, $settings);
}
/**
* Before validation callback
*
* Check if the file is really an uploaded file and run custom checks for file
* extensions and / or mime type if configured to do so.
*
* @param Model $Model
* @param array $options
* @return boolean True on success
*/
public function beforeValidate(Model $Model, $options = array()) {
$this->log('beforeValidate...');
$this->log('options');
$this->log( $options );
$this->log('$this->settings[$Model->alias]');
$this->log($this->settings[$Model->alias]);
$this->log('$this->settings');
$this->log($this->settings);
extract($this->settings[$Model->alias]);
$this->log('$validate');
$this->log($validate);
if ($validate === true && isset($Model->data[$Model->alias][$fileField]) && is_array($Model->data[$Model->alias][$fileField])) {
if ($Model->validateUploadError($Model->data[$Model->alias][$fileField]['error']) === false) {
$Model->validationErrors[$fileField] = array($this->uploadError);
return false;
}
if (!empty($Model->data[$Model->alias][$fileField])) {
if (empty($localFile) && !is_uploaded_file($Model->data[$Model->alias][$fileField]['tmp_name'])) {
$this->uploadError = __d('file_storage', 'The uploaded file is no valid upload.');
$Model->invalidate($fileField, $this->uploadError);
return false;
}
}
if (is_array($allowedMime)) {
if (!$this->validateAllowedMimeTypes($Model, $allowedMime)) {
return false;
}
}
$this->log('allowedExtensions');
$this->log($allowedExtensions);
if (is_array($allowedExtensions)) {
if (!$this->validateUploadExtension($Model, $allowedExtensions)) {
return false;
}
}
}
return true;
}
/**
* Validates the extension
*
* @param Model $Model
* @param $validExtensions
* @return boolean True if the extension is allowed
*/
public function validateUploadExtension(Model $Model, $validExtensions) {
$this->log('validateUploadExtension');
extract($this->settings[$Model->alias]);
$extension = $this->fileExtension($Model, $Model->data[$Model->alias][$fileField]['name'], false);
if (!in_array(strtolower($extension), $validExtensions)) {
$this->uploadError = __d('file_storage', 'You are not allowed to upload files of this type.');
$Model->invalidate($fileField, $this->uploadError);
return false;
}
return true;
}
/**
* Validates if the mime type of an uploaded file is allowed
*
* @param Model $Model
* @param array Array of allowed mime types
* @return boolean
*/
public function validateAllowedMimeTypes(Model $Model, $mimeTypes = array()) {
extract($this->settings[$Model->alias]);
if (!empty($mimeTypes)) {
$allowedMime = $mimeTypes;
}
$File = new File($Model->data[$Model->alias][$fileField]['tmp_name']);
$mimeType = $File->mime();
if (!in_array($mimeType, $allowedMime)) {
$this->uploadError = __d('file_storage', 'You are not allowed to upload files of this type.');
$Model->invalidate($fileField, $this->uploadError);
return false;
}
return true;
}
/**
* Valdates the error value that comes with the file input file
*
* @param Model $Model
* @param integer Error value from the form input [file_field][error]
* @return boolean True on success, if false the error message is set to the models field and also set in $this->uploadError
*/
public function validateUploadError(Model $Model, $error = null) {
if (!is_null($error)) {
switch ($error) {
case UPLOAD_ERR_OK:
return true;
break;
case UPLOAD_ERR_INI_SIZE:
$this->uploadError = __d('file_storage', 'The uploaded file exceeds limit of %s.', CakeNumber::toReadableSize(ini_get('upload_max_filesize')));
break;
case UPLOAD_ERR_FORM_SIZE:
$this->uploadError = __d('file_storage', 'The uploaded file is to big, please choose a smaller file or try to compress it.');
break;
case UPLOAD_ERR_PARTIAL:
$this->uploadError = __d('file_storage', 'The uploaded file was only partially uploaded.');
break;
case UPLOAD_ERR_NO_FILE:
if ($this->settings[$Model->alias]['allowNoFileError'] === false) {
$this->uploadError = __d('file_storage', 'No file was uploaded.');
return false;
}
return true;
break;
case UPLOAD_ERR_NO_TMP_DIR:
$this->uploadError = __d('file_storage', 'The remote server has no temporary folder for file uploads. Please contact the site admin.');
break;
case UPLOAD_ERR_CANT_WRITE:
$this->uploadError = __d('file_storage', 'Failed to write file to disk. Please contact the site admin.');
break;
case UPLOAD_ERR_EXTENSION:
$this->uploadError = __d('file_storage', 'File upload stopped by extension. Please contact the site admin.');
break;
default:
$this->uploadError = __d('file_storage', 'Unknown File Error. Please contact the site admin.');
break;
}
return false;
}
return true;
}
/**
* Returns the latest error message
*
* @param \AppModel|\Model $Model
* @return string
* @access public
*/
public function uploadError(Model $Model) {
return $this->uploadError;
}
/**
* Returns an array that matches the structure of a regular upload for a local file
*
* @param Model $Model
* @param $file
* @param string File with path
* @return array Array that matches the structure of a regular upload
*/
public function uploadArray(Model $Model, $file, $filename = null) {
$File = new File($file);
if (empty($fileName)) {
$filename = basename($file);
}
return array(
'name' => $filename,
'tmp_name' => $file,
'error' => 0,
'type' => $File->mime(),
'size' => $File->size());
}
/**
* Return file extension from a given filename
*
* @param Model $Model
* @param $name
* @param bool $realFile
* @internal param $string
* @return boolean string or false
*/
public function fileExtension(Model $Model, $name, $realFile = true) {
if ($realFile) {
return pathinfo($name, PATHINFO_EXTENSION);
}
return substr(strrchr($name,'.'), 1);
}
}
我的记录输出:
2014-12-23 20:04:32 Error: SETTINGS for ImageStorage:
2014-12-23 20:04:32 Error: Array
(
[localFile] => 1
[validate] =>
[allowedExtensions] => Array
(
[0] => jpg
[1] => jpeg
[2] => png
[3] => gif
)
)
2014-12-23 20:04:33 Error: SETTINGS for Photo:
2014-12-23 20:04:33 Error: Array
(
[localFile] => 1
[validate] =>
[allowedExtensions] => Array
(
[0] => jpg
[1] => jpeg
[2] => png
[3] => gif
[4] => jpg
[5] => png
[6] => xxx
)
)
2014-12-23 20:04:33 Error: beforeValidate...
2014-12-23 20:04:33 Error: options
2014-12-23 20:04:33 Error: Array
(
[validate] => 1
[fieldList] => Array
(
)
[callbacks] => 1
[counterCache] => 1
)
2014-12-23 20:04:33 Error: $this->settings[$Model->alias]
2014-12-23 20:04:33 Error:
2014-12-23 20:04:33 Error: $this->settings
2014-12-23 20:04:33 Error: Array
(
[priority] => 10
)
2014-12-23 20:04:33 Error: $validate
2014-12-23 20:04:33 Error:
2014-12-23 20:04:38 Error: SETTINGS for ImageStorage:
2014-12-23 20:04:38 Error: Array
(
[localFile] => 1
[validate] =>
[allowedExtensions] => Array
(
[0] => jpg
[1] => jpeg
[2] => png
[3] => gif
)
)
2014-12-23 20:04:39 Error: SETTINGS for Photo:
2014-12-23 20:04:39 Error: Array
(
[localFile] => 1
[validate] =>
[allowedExtensions] => Array
(
[0] => jpg
[1] => jpeg
[2] => png
[3] => gif
[4] => jpg
[5] => png
[6] => xxx
)
)
UPDATE1
我在日志输出中注意到我的设置似乎被添加到默认设置中,而不是替换它们:
2014-12-23 21:55:07 Error: SETTINGS for Photo:
2014-12-23 21:55:07 Error: Array
(
[localFile] => 1
[validate] =>
[allowedExtensions] => Array
(
[0] => jpg
[1] => jpeg
[2] => png
[3] => gif
[4] => jpg <--my addition
[5] => png <--my addition
[6] => xxx <--my addition
)
)
答案 0 :(得分:0)
如果我的插件,这不是问题。但核心类Object::_mergeVars()
,Model类继承了它。它以你获得它的方式合并$actsAs property
。
除了使用已存在的configureUploadValidation()
行为方法之外,我无法在我的插件中修复此问题。我将在明天将其添加为插件文档的注释。