CakePHP:无法从插件加载行为设置


CakePHP: Unable to load behavior settings from plugin

我正在尝试将设置传递给由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
        )
)

更新1

我在日志输出中注意到我的设置似乎被添加到默认值中,而不是替换它们:

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
        )
)

如果我的插件,这不是问题。但是核心类Object::_mergeVars(),模型类继承了它。它以您获得的方式合并$actsAs property

除了

您使用已经存在的configureUploadValidation()行为方法之外,我无法在我的插件中解决此问题。明天我会把它作为注释添加到插件的文档中。