Commit bb5b6a41 by Qiang Xue

Finished FileValidator and UploadedFile.

Added Model::formName().
parent 421e31ec
......@@ -8,8 +8,8 @@
namespace yii\base;
use yii\helpers\StringHelper;
use yii\validators\Validator;
use yii\validators\RequiredValidator;
use yii\validators\Validator;
/**
* Model is the base class for data models.
......@@ -169,6 +169,26 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
}
/**
* Returns the form name that this model class should use.
*
* The form name is mainly used by [[\yii\web\ActiveForm]] to determine how to name
* the input fields for the attributes in a model. If the form name is "A" and an attribute
* name is "b", then the corresponding input name would be "A[b]". If the form name is
* an empty string, then the input name would be "b".
*
* By default, this method returns the model class name (without the namespace part)
* as the form name. You may override it when the model is used in different forms.
*
* @return string the form name of this model class.
*/
public function formName()
{
$class = get_class($this);
$pos = strrpos($class, '\\');
return $pos === false ? $class : substr($class, $pos + 1);
}
/**
* Returns the list of attribute names.
* By default, this method returns all public non-static properties of the class.
* You may override this method to change the default behavior.
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
use yii\widgets\ActiveForm;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class UploadedFile extends \yii\base\Object
{
private static $_files;
private $_name;
private $_tempName;
private $_type;
private $_size;
private $_error;
/**
* Constructor.
* Instead of using the constructor to create a new instance,
* you should normally call [[getInstance()]] or [[getInstances()]]
* to obtain new instances.
* @param string $name the original name of the file being uploaded
* @param string $tempName the path of the uploaded file on the server.
* @param string $type the MIME-type of the uploaded file (such as "image/gif").
* @param integer $size the actual size of the uploaded file in bytes
* @param integer $error the error code
*/
public function __construct($name, $tempName, $type, $size, $error)
{
$this->_name = $name;
$this->_tempName = $tempName;
$this->_type = $type;
$this->_size = $size;
$this->_error = $error;
}
/**
* String output.
* This is PHP magic method that returns string representation of an object.
* The implementation here returns the uploaded file's name.
* @return string the string representation of the object
*/
public function __toString()
{
return $this->_name;
}
/**
* Returns an uploaded file for the given model attribute.
* The file should be uploaded using [[ActiveForm::fileInput()]].
* @param \yii\base\Model $model the data model
* @param string $attribute the attribute name. The attribute name may contain array indexes.
* For example, '[1]file' for tabular file uploading; and 'file[1]' for an element in a file array.
* @return UploadedFile the instance of the uploaded file.
* Null is returned if no file is uploaded for the specified model attribute.
* @see getInstanceByName
*/
public static function getInstance($model, $attribute)
{
$name = ActiveForm::getInputName($model, $attribute);
return static::getInstanceByName($name);
}
/**
* Returns all uploaded files for the given model attribute.
* @param \yii\base\Model $model the data model
* @param string $attribute the attribute name. The attribute name may contain array indexes
* for tabular file uploading, e.g. '[1]file'.
* @return UploadedFile[] array of UploadedFile objects.
* Empty array is returned if no available file was found for the given attribute.
*/
public static function getInstances($model, $attribute)
{
$name = ActiveForm::getInputName($model, $attribute);
return static::getInstancesByName($name);
}
/**
* Returns an uploaded file according to the given file input name.
* The name can be a plain string or a string like an array element (e.g. 'Post[imageFile]', or 'Post[0][imageFile]').
* @param string $name the name of the file input field.
* @return UploadedFile the instance of the uploaded file.
* Null is returned if no file is uploaded for the specified name.
*/
public static function getInstanceByName($name)
{
$files = static::loadFiles();
return isset($files[$name]) ? $files[$name] : null;
}
/**
* Returns an array of uploaded files corresponding to the specified file input name.
* This is mainly used when multiple files were uploaded and saved as 'files[0]', 'files[1]',
* 'files[n]'..., and you can retrieve them all by passing 'files' as the name.
* @param string $name the name of the array of files
* @return UploadedFile[] the array of CUploadedFile objects. Empty array is returned
* if no adequate upload was found. Please note that this array will contain
* all files from all sub-arrays regardless how deeply nested they are.
*/
public static function getInstancesByName($name)
{
$files = static::loadFiles();
if (isset($files[$name])) {
return array($files[$name]);
}
$results = array();
foreach ($files as $key => $file) {
if (strpos($key, "{$name}[") === 0) {
$results[] = self::$_files[$key];
}
}
return $results;
}
/**
* Cleans up the loaded UploadedFile instances.
* This method is mainly used by test scripts to set up a fixture.
*/
public static function reset()
{
self::$_files = null;
}
/**
* Saves the uploaded file.
* Note that this method uses php's move_uploaded_file() method. If the target file `$file`
* already exists, it will be overwritten.
* @param string $file the file path used to save the uploaded file
* @param boolean $deleteTempFile whether to delete the temporary file after saving.
* If true, you will not be able to save the uploaded file again in the current request.
* @return boolean true whether the file is saved successfully
* @see error
*/
public function saveAs($file, $deleteTempFile = true)
{
if ($this->_error == UPLOAD_ERR_OK) {
if ($deleteTempFile) {
return move_uploaded_file($this->_tempName, $file);
} elseif (is_uploaded_file($this->_tempName)) {
return copy($this->_tempName, $file);
}
}
return false;
}
/**
* @return string the original name of the file being uploaded
*/
public function getName()
{
return $this->_name;
}
/**
* @return string the path of the uploaded file on the server.
* Note, this is a temporary file which will be automatically deleted by PHP
* after the current request is processed.
*/
public function getTempName()
{
return $this->_tempName;
}
/**
* @return string the MIME-type of the uploaded file (such as "image/gif").
* Since this MIME type is not checked on the server side, do not take this value for granted.
* Instead, use [[FileHelper::getMimeType()]] to determine the exact MIME type.
*/
public function getType()
{
return $this->_type;
}
/**
* @return integer the actual size of the uploaded file in bytes
*/
public function getSize()
{
return $this->_size;
}
/**
* Returns an error code describing the status of this file uploading.
* @return integer the error code
* @see http://www.php.net/manual/en/features.file-upload.errors.php
*/
public function getError()
{
return $this->_error;
}
/**
* @return boolean whether there is an error with the uploaded file.
* Check [[error]] for detailed error code information.
*/
public function getHasError()
{
return $this->_error != UPLOAD_ERR_OK;
}
/**
* Creates UploadedFile instances from $_FILE.
* @return array the UploadedFile instances
*/
private static function loadFiles()
{
if (self::$_files === null) {
self::$_files = array();
if (isset($_FILES) && is_array($_FILES)) {
foreach ($_FILES as $class => $info) {
self::loadFilesRecursive($class, $info['name'], $info['tmp_name'], $info['type'], $info['size'], $info['error']);
}
}
}
return self::$_files;
}
/**
* Creates UploadedFile instances from $_FILE recursively.
* @param string $key key for identifying uploaded file: class name and sub-array indexes
* @param mixed $names file names provided by PHP
* @param mixed $tempNames temporary file names provided by PHP
* @param mixed $types file types provided by PHP
* @param mixed $sizes file sizes provided by PHP
* @param mixed $errors uploading issues provided by PHP
*/
private static function loadFilesRecursive($key, $names, $tempNames, $types, $sizes, $errors)
{
if (is_array($names)) {
foreach ($names as $i => $name) {
self::loadFilesRecursive($key . '[' . $i . ']', $name, $tempNames[$i], $types[$i], $sizes[$i], $errors[$i]);
}
} else {
self::$_files[$key] = new self($names, $tempNames, $types, $sizes, $errors);
}
}
}
......@@ -52,10 +52,6 @@ class ActiveForm extends Widget
public $enableClientValidation = false;
public $options = array();
/**
* @var array model-class mapped to name prefix
*/
public $modelMap;
/**
* @param Model|Model[] $models
......@@ -240,35 +236,6 @@ class ActiveForm extends Widget
return Html::radioList($name, $checked, $items, $options);
}
public function getInputName($model, $attribute)
{
$class = get_class($model);
if (isset($this->modelMap[$class])) {
$class = $this->modelMap[$class];
} elseif (($pos = strrpos($class, '\\')) !== false) {
$class = substr($class, $pos + 1);
}
if (!preg_match('/(^|.*\])(\w+)(\[.*|$)/', $attribute, $matches)) {
throw new InvalidParamException('Attribute name must contain word characters only.');
}
$prefix = $matches[1];
$attribute = $matches[2];
$suffix = $matches[3];
if ($class === '' && $prefix === '') {
return $attribute . $suffix;
} elseif ($class !== '') {
return $class . $prefix . "[$attribute]" . $suffix;
} else {
throw new InvalidParamException('Model name cannot be mapped to empty for tabular inputs.');
}
}
public function getInputId($model, $attribute)
{
$name = $this->getInputName($model, $attribute);
return str_replace(array('[]', '][', '[', ']', ' '), array('', '-', '-', '', '-'), $name);
}
public function getAttributeValue($model, $attribute)
{
if (!preg_match('/(^|.*\])(\w+)(\[.*|$)/', $attribute, $matches)) {
......@@ -299,4 +266,34 @@ class ActiveForm extends Widget
throw new InvalidParamException('Attribute name must contain word characters only.');
}
}
/**
* @param Model $model
* @param string $attribute
* @return string
* @throws \yii\base\InvalidParamException
*/
public static function getInputName($model, $attribute)
{
$formName = $model->formName();
if (!preg_match('/(^|.*\])(\w+)(\[.*|$)/', $attribute, $matches)) {
throw new InvalidParamException('Attribute name must contain word characters only.');
}
$prefix = $matches[1];
$attribute = $matches[2];
$suffix = $matches[3];
if ($formName === '' && $prefix === '') {
return $attribute . $suffix;
} elseif ($formName !== '') {
return $formName . $prefix . "[$attribute]" . $suffix;
} else {
throw new InvalidParamException(get_class($model) . '::formName() cannot be empty for tabular inputs.');
}
}
public static function getInputId($model, $attribute)
{
$name = static::getInputName($model, $attribute);
return str_replace(array('[]', '][', '[', ']', ' '), array('', '-', '-', '', '-'), $name);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment