diff --git a/framework/base/Model.php b/framework/base/Model.php
index 611b12e..7f55239 100644
--- a/framework/base/Model.php
+++ b/framework/base/Model.php
@@ -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.
diff --git a/framework/validators/FileValidator.php b/framework/validators/FileValidator.php
index b05ac2a..c104c05 100644
--- a/framework/validators/FileValidator.php
+++ b/framework/validators/FileValidator.php
@@ -7,47 +7,19 @@
namespace yii\validators;
+use Yii;
+use yii\helpers\FileHelper;
+use yii\web\UploadedFile;
+
/**
- * CFileValidator verifies if an attribute is receiving a valid uploaded file.
- *
- * It uses the model class and attribute name to retrieve the information
- * about the uploaded file. It then checks if a file is uploaded successfully,
- * if the file size is within the limit and if the file type is allowed.
- *
- * This validator will attempt to fetch uploaded data if attribute is not
- * previously set. Please note that this cannot be done if input is tabular:
- *
- * foreach($models as $i=>$model)
- * $model->attribute = CUploadedFile::getInstance($model, "[$i]attribute");
- *
- * Please note that you must use {@link CUploadedFile::getInstances} for multiple
- * file uploads.
- *
- * When using CFileValidator with an active record, the following code is often used:
- *
- * if($model->save())
- * {
- * // single upload
- * $model->attribute->saveAs($path);
- * // multiple upload
- * foreach($model->attribute as $file)
- * $file->saveAs($path);
- * }
- *
- *
- * You can use {@link CFileValidator} to validate the file attribute.
+ * FileValidator verifies if an attribute is receiving a valid uploaded file.
*
* @author Qiang Xue
* @since 2.0
*/
-class CFileValidator extends Validator
+class FileValidator extends Validator
{
/**
- * @var boolean whether the attribute requires a file to be uploaded or not.
- * Defaults to false, meaning a file is required to be uploaded.
- */
- public $allowEmpty = false;
- /**
* @var mixed a list of file name extensions that are allowed to be uploaded.
* This can be either an array or a string consisting of file extension names
* separated by space or comma (e.g. "gif, jpg").
@@ -66,136 +38,179 @@ class CFileValidator extends Validator
* Defaults to null, meaning no limit.
* Note, the size limit is also affected by 'upload_max_filesize' INI setting
* and the 'MAX_FILE_SIZE' hidden field value.
- * @see tooLarge
+ * @see tooBig
*/
public $maxSize;
/**
+ * @var integer the maximum file count the given attribute can hold.
+ * It defaults to 1, meaning single file upload. By defining a higher number,
+ * multiple uploads become possible.
+ */
+ public $maxFiles = 1;
+ /**
+ * @var string the error message used when a file is not uploaded correctly.
+ */
+ public $message;
+ /**
+ * @var string the error message used when no file is uploaded.
+ */
+ public $uploadRequired;
+ /**
* @var string the error message used when the uploaded file is too large.
- * @see maxSize
+ * You may use the following tokens in the message:
+ *
+ * - {attribute}: the attribute name
+ * - {file}: the uploaded file name
+ * - {limit}: the maximum size allowed (see [[getSizeLimit()]])
*/
- public $tooLarge;
+ public $tooBig;
/**
* @var string the error message used when the uploaded file is too small.
- * @see minSize
+ * You may use the following tokens in the message:
+ *
+ * - {attribute}: the attribute name
+ * - {file}: the uploaded file name
+ * - {limit}: the value of [[minSize]]
*/
public $tooSmall;
/**
* @var string the error message used when the uploaded file has an extension name
- * that is not listed among {@link extensions}.
+ * that is not listed in [[extensions]]. You may use the following tokens in the message:
+ *
+ * - {attribute}: the attribute name
+ * - {extensions}: the list of the allowed extensions.
*/
public $wrongType;
/**
- * @var integer the maximum file count the given attribute can hold.
- * It defaults to 1, meaning single file upload. By defining a higher number,
- * multiple uploads become possible.
- */
- public $maxFiles = 1;
- /**
- * @var string the error message used if the count of multiple uploads exceeds
- * limit.
+ * @var string the error message used if the count of multiple uploads exceeds limit.
+ * You may use the following tokens in the message:
+ *
+ * - {attribute}: the attribute name
+ * - {file}: the uploaded file name
+ * - {limit}: the value of [[maxFiles]]
*/
public $tooMany;
/**
- * Set the attribute and then validates using {@link validateFile}.
- * If there is any error, the error message is added to the object.
- * @param \yii\base\Model $object the object being validated
- * @param string $attribute the attribute being validated
+ * Initializes the validator.
*/
- public function validateAttribute($object, $attribute)
+ public function init()
{
- if ($this->maxFiles > 1)
- {
- $files = $object->$attribute;
- if (!is_array($files) || !isset($files[0]) || !$files[0] instanceof CUploadedFile)
- $files = CUploadedFile::getInstances($object, $attribute);
- if (array() === $files)
- return $this->emptyAttribute($object, $attribute);
- if (count($files) > $this->maxFiles)
- {
- $message = $this->tooMany !== null ? $this->tooMany : \Yii::t('yii|{attribute} cannot accept more than {limit} files.');
- $this->addError($object, $attribute, $message, array('{attribute}' => $attribute, '{limit}' => $this->maxFiles));
- } else
- foreach ($files as $file)
- $this->validateFile($object, $attribute, $file);
- } else
- {
- $file = $object->$attribute;
- if (!$file instanceof CUploadedFile)
- {
- $file = CUploadedFile::getInstance($object, $attribute);
- if (null === $file)
- return $this->emptyAttribute($object, $attribute);
- }
- $this->validateFile($object, $attribute, $file);
+ parent::init();
+ if ($this->message === null) {
+ $this->message = Yii::t('yii|File upload failed.');
+ }
+ if ($this->uploadRequired === null) {
+ $this->uploadRequired = Yii::t('yii|Please upload a file.');
}
+ if ($this->tooMany === null) {
+ $this->tooMany = Yii::t('yii|You can upload at most {limit} files.');
+ }
+ if ($this->wrongType === null) {
+ $this->wrongType = Yii::t('yii|Only files with these extensions are allowed: {extensions}.');
+ }
+ if ($this->tooBig === null) {
+ $this->tooBig = Yii::t('yii|The file "{file}" is too big. Its size cannot exceed {limit} bytes.');
+ }
+ if ($this->tooSmall === null) {
+ $this->tooSmall = Yii::t('yii|The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.');
+ }
+ if (!is_array($this->types)) {
+ $this->types = preg_split('/[\s,]+/', strtolower($this->types), -1, PREG_SPLIT_NO_EMPTY);
+ }
}
/**
- * Internally validates a file object.
+ * Validates the attribute.
* @param \yii\base\Model $object the object being validated
* @param string $attribute the attribute being validated
- * @param CUploadedFile $file uploaded file passed to check against a set of rules
*/
- public function validateFile($object, $attribute, $file)
+ public function validateAttribute($object, $attribute)
{
- if (null === $file || ($error = $file->getError()) == UPLOAD_ERR_NO_FILE)
- return $this->emptyAttribute($object, $attribute);
- elseif ($error == UPLOAD_ERR_INI_SIZE || $error == UPLOAD_ERR_FORM_SIZE || $this->maxSize !== null && $file->getSize() > $this->maxSize)
- {
- $message = $this->tooLarge !== null ? $this->tooLarge : \Yii::t('yii|The file "{file}" is too large. Its size cannot exceed {limit} bytes.');
- $this->addError($object, $attribute, $message, array('{file}' => $file->getName(), '{limit}' => $this->getSizeLimit()));
- } elseif ($error == UPLOAD_ERR_PARTIAL)
- throw new CException(\Yii::t('yii|The file "{file}" was only partially uploaded.', array('{file}' => $file->getName())));
- elseif ($error == UPLOAD_ERR_NO_TMP_DIR)
- throw new CException(\Yii::t('yii|Missing the temporary folder to store the uploaded file "{file}".', array('{file}' => $file->getName())));
- elseif ($error == UPLOAD_ERR_CANT_WRITE)
- throw new CException(\Yii::t('yii|Failed to write the uploaded file "{file}" to disk.', array('{file}' => $file->getName())));
- elseif (defined('UPLOAD_ERR_EXTENSION') && $error == UPLOAD_ERR_EXTENSION) // available for PHP 5.2.0 or above
- throw new CException(\Yii::t('yii|File upload was stopped by extension.'));
-
- if ($this->minSize !== null && $file->getSize() < $this->minSize)
- {
- $message = $this->tooSmall !== null ? $this->tooSmall : \Yii::t('yii|The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.');
- $this->addError($object, $attribute, $message, array('{file}' => $file->getName(), '{limit}' => $this->minSize));
- }
-
- if ($this->types !== null)
- {
- if (is_string($this->types))
- $types = preg_split('/[\s,]+/', strtolower($this->types), -1, PREG_SPLIT_NO_EMPTY);
- else
- $types = $this->types;
- if (!in_array(strtolower($file->getExtensionName()), $types))
- {
- $message = $this->wrongType !== null ? $this->wrongType : \Yii::t('yii|The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.');
- $this->addError($object, $attribute, $message, array('{file}' => $file->getName(), '{extensions}' => implode(', ', $types)));
+ if ($this->maxFiles > 1) {
+ $files = $object->$attribute;
+ if (!is_array($files)) {
+ $this->addError($object, $attribute, $this->uploadRequired);
+ return;
+ }
+ foreach ($files as $i => $file) {
+ if (!$file instanceof UploadedFile || $file->getError() == UPLOAD_ERR_NO_FILE) {
+ unset($files[$i]);
+ }
+ }
+ $object->$attribute = array_values($files);
+ if ($files === array()) {
+ $this->addError($object, $attribute, $this->uploadRequired);
+ }
+ if (count($files) > $this->maxFiles) {
+ $this->addError($object, $attribute, $this->tooMany, array('{attribute}' => $attribute, '{limit}' => $this->maxFiles));
+ } else {
+ foreach ($files as $file) {
+ $this->validateFile($object, $attribute, $file);
+ }
+ }
+ } else {
+ $file = $object->$attribute;
+ if ($file instanceof UploadedFile && $file->getError() != UPLOAD_ERR_NO_FILE) {
+ $this->validateFile($object, $attribute, $file);
+ } else {
+ $this->addError($object, $attribute, $this->uploadRequired);
}
}
}
/**
- * Raises an error to inform end user about blank attribute.
+ * Internally validates a file object.
* @param \yii\base\Model $object the object being validated
* @param string $attribute the attribute being validated
+ * @param UploadedFile $file uploaded file passed to check against a set of rules
*/
- public function emptyAttribute($object, $attribute)
+ protected function validateFile($object, $attribute, $file)
{
- if (!$this->allowEmpty)
- {
- $message = $this->message !== null ? $this->message : \Yii::t('yii|{attribute} cannot be blank.');
- $this->addError($object, $attribute, $message);
+ switch ($file->getError()) {
+ case UPLOAD_ERR_OK:
+ if ($this->maxSize !== null && $file->getSize() > $this->maxSize) {
+ $this->addError($object, $attribute, $this->tooBig, array('{file}' => $file->getName(), '{limit}' => $this->getSizeLimit()));
+ }
+ if ($this->minSize !== null && $file->getSize() < $this->minSize) {
+ $this->addError($object, $attribute, $this->tooSmall, array('{file}' => $file->getName(), '{limit}' => $this->minSize));
+ }
+ if (!empty($this->types) && !in_array(strtolower(FileHelper::getExtension($file->getName())), $this->types, true)) {
+ $this->addError($object, $attribute, $this->wrongType, array('{file}' => $file->getName(), '{extensions}' => implode(', ', $this->types)));
+ }
+ break;
+ case UPLOAD_ERR_INI_SIZE:
+ case UPLOAD_ERR_FORM_SIZE:
+ $this->addError($object, $attribute, $this->tooBig, array('{file}' => $file->getName(), '{limit}' => $this->getSizeLimit()));
+ break;
+ case UPLOAD_ERR_PARTIAL:
+ $this->addError($object, $attribute, $this->message);
+ Yii::warning('File was only partially uploaded: ' . $file->getName(), __METHOD__);
+ break;
+ case UPLOAD_ERR_NO_TMP_DIR:
+ $this->addError($object, $attribute, $this->message);
+ Yii::warning('Missing the temporary folder to store the uploaded file: ' . $file->getName(), __METHOD__);
+ break;
+ case UPLOAD_ERR_CANT_WRITE:
+ $this->addError($object, $attribute, $this->message);
+ Yii::warning('Failed to write the uploaded file to disk: ', $file->getName(), __METHOD__);
+ break;
+ case UPLOAD_ERR_EXTENSION:
+ $this->addError($object, $attribute, $this->message);
+ Yii::warning('File upload was stopped by some PHP extension: ', $file->getName(), __METHOD__);
+ break;
+ default:
+ break;
}
}
/**
* Returns the maximum size allowed for uploaded files.
* This is determined based on three factors:
- *
- * - 'upload_max_filesize' in php.ini
- * - 'MAX_FILE_SIZE' hidden field
- * - {@link maxSize}
- *
+ *
+ * - 'upload_max_filesize' in php.ini
+ * - 'MAX_FILE_SIZE' hidden field
+ * - [[maxSize]]
*
* @return integer the size limit for uploaded files.
*/
@@ -203,10 +218,12 @@ class CFileValidator extends Validator
{
$limit = ini_get('upload_max_filesize');
$limit = $this->sizeToBytes($limit);
- if ($this->maxSize !== null && $limit > 0 && $this->maxSize < $limit)
+ if ($this->maxSize !== null && $limit > 0 && $this->maxSize < $limit) {
$limit = $this->maxSize;
- if (isset($_POST['MAX_FILE_SIZE']) && $_POST['MAX_FILE_SIZE'] > 0 && $_POST['MAX_FILE_SIZE'] < $limit)
- $limit = $_POST['MAX_FILE_SIZE'];
+ }
+ if (isset($_POST['MAX_FILE_SIZE']) && $_POST['MAX_FILE_SIZE'] > 0 && $_POST['MAX_FILE_SIZE'] < $limit) {
+ $limit = (int)$_POST['MAX_FILE_SIZE'];
+ }
return $limit;
}
@@ -218,12 +235,18 @@ class CFileValidator extends Validator
*/
private function sizeToBytes($sizeStr)
{
- switch (substr($sizeStr, -1))
- {
- case 'M': case 'm': return (int)$sizeStr * 1048576;
- case 'K': case 'k': return (int)$sizeStr * 1024;
- case 'G': case 'g': return (int)$sizeStr * 1073741824;
- default: return (int)$sizeStr;
+ switch (substr($sizeStr, -1)) {
+ case 'M':
+ case 'm':
+ return (int)$sizeStr * 1048576;
+ case 'K':
+ case 'k':
+ return (int)$sizeStr * 1024;
+ case 'G':
+ case 'g':
+ return (int)$sizeStr * 1073741824;
+ default:
+ return (int)$sizeStr;
}
}
}
\ No newline at end of file
diff --git a/framework/web/UploadedFile.php b/framework/web/UploadedFile.php
new file mode 100644
index 0000000..c67281c
--- /dev/null
+++ b/framework/web/UploadedFile.php
@@ -0,0 +1,246 @@
+
+ * @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);
+ }
+ }
+}
diff --git a/framework/widgets/ActiveForm.php b/framework/widgets/ActiveForm.php
index 8ac5365..48bc181 100644
--- a/framework/widgets/ActiveForm.php
+++ b/framework/widgets/ActiveForm.php
@@ -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);
+ }
}