mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 14:46:19 +08:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master'
This commit is contained in:
		@ -522,6 +522,24 @@ $customer->loadDefaultValues();
 | 
				
			|||||||
> Совет: вы можете использовать поведение [[yii\behaviors\AttributeTypecastBehavior]] для того, чтобы производить
 | 
					> Совет: вы можете использовать поведение [[yii\behaviors\AttributeTypecastBehavior]] для того, чтобы производить
 | 
				
			||||||
  приведение типов для ActiveRecord во время валидации или сохранения.
 | 
					  приведение типов для ActiveRecord во время валидации или сохранения.
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					Начиная с 2.0.14, Yii ActiveRecord поддерживает сложные типы данных, такие как JSON или многомерные массивы.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### JSON в MySQL и PostgreSQL
 | 
				
			||||||
 | 
					После заполнения данных, значение из столбца JSON будет автоматически декодировано из JSON в соответствии со стандартными правилами декодирования JSON.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Чтобы сохранить значение атрибута в столбец JSON, ActiveRecord автоматически создаст объект [[yii\db\JsonExpression|JsonExpression]], который будет закодирован в строку JSON на уровне [QueryBuilder](db-query-builder.md).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Массивы в PostgreSQL
 | 
				
			||||||
 | 
					После заполнения данных значение из столбца `Array` будет автоматически декодировано из нотации PgSQL в объект [[yii\db\ArrayExpression|ArrayExpression]]. Он реализует интерфейс PHP `ArrayAccess`, так что вы можете использовать его в качестве массива, или вызвать `->getValue ()`, чтобы получить сам массив.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Чтобы сохранить значение атрибута в столбец массива, ActiveRecord автоматически создаст объект [[yii\db\Array Expression|ArrayExpression]], который будет закодирован [QueryBuilder](db-query-builder.md) в строковое представление массива PgSQL.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Можно также использовать условия для столбцов JSON:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```php
 | 
				
			||||||
 | 
					$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Дополнительные сведения о системе построения выражений см. [Query Builder – добавление пользовательских условий и выражений](db-query-builder.md#adding-custom-conditions-and-expressions)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Обновление нескольких строк данных <span id="updating-multiple-rows"></span>
 | 
					### Обновление нескольких строк данных <span id="updating-multiple-rows"></span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,9 @@ Yii Framework 2 Change Log
 | 
				
			|||||||
2.0.17 under development
 | 
					2.0.17 under development
 | 
				
			||||||
------------------------
 | 
					------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Bug #9438, #13740, #15037: Handle DB session callback custom fields before session closed (lubosdz)
 | 
				
			||||||
 | 
					- Bug #16681: `ActiveField::inputOptions` were not used during some widgets rendering (GHopperMSK)
 | 
				
			||||||
 | 
					- Bug #17133: Fixed aliases rendering during help generation for a console command (GHopperMSK)
 | 
				
			||||||
- Bug #17185: Fixed `AssetManager` timestamp appending when a file is published manually (GHopperMSK)
 | 
					- Bug #17185: Fixed `AssetManager` timestamp appending when a file is published manually (GHopperMSK)
 | 
				
			||||||
- Bug #17156: Fixes PHP 7.2 warning when a data provider has no data as a parameter for a GridView (evilito)
 | 
					- Bug #17156: Fixes PHP 7.2 warning when a data provider has no data as a parameter for a GridView (evilito)
 | 
				
			||||||
- Bug #17083: Fixed `yii\validators\EmailValidator::$checkDNS` tells that every domain is correct on alpine linux (mikk150)
 | 
					- Bug #17083: Fixed `yii\validators\EmailValidator::$checkDNS` tells that every domain is correct on alpine linux (mikk150)
 | 
				
			||||||
 | 
				
			|||||||
@ -532,7 +532,7 @@ class HelpController extends Controller
 | 
				
			|||||||
    protected function formatOptionAliases($controller, $option)
 | 
					    protected function formatOptionAliases($controller, $option)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        foreach ($controller->optionAliases() as $name => $value) {
 | 
					        foreach ($controller->optionAliases() as $name => $value) {
 | 
				
			||||||
            if ($value === $option) {
 | 
					            if (Inflector::camel2id($value, '-', true) === $option) {
 | 
				
			||||||
                return ', -' . $name;
 | 
					                return ', -' . $name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -685,7 +685,7 @@ class QueryBuilder extends \yii\base\BaseObject
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Builds a SQL statement for creating a new DB table.
 | 
					     * Builds a SQL statement for creating a new DB table.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * The columns in the new  table should be specified as name-definition pairs (e.g. 'name' => 'string'),
 | 
					     * The columns in the new table should be specified as name-definition pairs (e.g. 'name' => 'string'),
 | 
				
			||||||
     * where name stands for a column name which will be properly quoted by the method, and definition
 | 
					     * where name stands for a column name which will be properly quoted by the method, and definition
 | 
				
			||||||
     * stands for the column type which can contain an abstract DB type.
 | 
					     * stands for the column type which can contain an abstract DB type.
 | 
				
			||||||
     * The [[getColumnType()]] method will be invoked to convert any abstract type into a physical one.
 | 
					     * The [[getColumnType()]] method will be invoked to convert any abstract type into a physical one.
 | 
				
			||||||
 | 
				
			|||||||
@ -76,6 +76,11 @@ class DbSession extends MultiFieldSession
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public $sessionTable = '{{%session}}';
 | 
					    public $sessionTable = '{{%session}}';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * @var array Session fields to be written into session table columns
 | 
				
			||||||
 | 
					    * @since 2.0.17
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    protected $fields = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Initializes the DbSession component.
 | 
					     * Initializes the DbSession component.
 | 
				
			||||||
@ -136,6 +141,19 @@ class DbSession extends MultiFieldSession
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Ends the current session and store session data.
 | 
				
			||||||
 | 
					     * @since 2.0.17
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function close()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->getIsActive()) {
 | 
				
			||||||
 | 
					            // prepare writeCallback fields before session closes
 | 
				
			||||||
 | 
					            $this->fields = $this->composeFields();
 | 
				
			||||||
 | 
					            YII_DEBUG ? session_write_close() : @session_write_close();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Session read handler.
 | 
					     * Session read handler.
 | 
				
			||||||
     * @internal Do not call this method directly.
 | 
					     * @internal Do not call this method directly.
 | 
				
			||||||
@ -169,14 +187,28 @@ class DbSession extends MultiFieldSession
 | 
				
			|||||||
        // exception must be caught in session write handler
 | 
					        // exception must be caught in session write handler
 | 
				
			||||||
        // https://secure.php.net/manual/en/function.session-set-save-handler.php#refsect1-function.session-set-save-handler-notes
 | 
					        // https://secure.php.net/manual/en/function.session-set-save-handler.php#refsect1-function.session-set-save-handler-notes
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            $fields = $this->composeFields($id, $data);
 | 
					            // ensure backwards compatability (fixed #9438)
 | 
				
			||||||
            $fields = $this->typecastFields($fields);
 | 
					            if ($this->writeCallback && !$this->fields) {
 | 
				
			||||||
            $this->db->createCommand()->upsert($this->sessionTable, $fields)->execute();
 | 
					                $this->fields = $this->composeFields();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // ensure data consistency
 | 
				
			||||||
 | 
					            if (!isset($this->fields['data'])) {
 | 
				
			||||||
 | 
					                $this->fields['data'] = $data;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $_SESSION = $this->fields['data'];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // ensure 'id' and 'expire' are never affected by [[writeCallback]]
 | 
				
			||||||
 | 
					            $this->fields = array_merge($this->fields, [
 | 
				
			||||||
 | 
					                'id' => $id,
 | 
				
			||||||
 | 
					                'expire' => time() + $this->getTimeout(),
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					            $this->fields = $this->typecastFields($this->fields);
 | 
				
			||||||
 | 
					            $this->db->createCommand()->upsert($this->sessionTable, $this->fields)->execute();
 | 
				
			||||||
 | 
					            $this->fields = [];
 | 
				
			||||||
        } catch (\Exception $e) {
 | 
					        } catch (\Exception $e) {
 | 
				
			||||||
            Yii::$app->errorHandler->handleException($e);
 | 
					            Yii::$app->errorHandler->handleException($e);
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -89,30 +89,19 @@ abstract class MultiFieldSession extends Session
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Composes storage field set for session writing.
 | 
					     * Composes storage field set for session writing.
 | 
				
			||||||
     * @param string $id session id
 | 
					     * @param string $id Optional session id
 | 
				
			||||||
     * @param string $data session data
 | 
					     * @param string $data Optional session data
 | 
				
			||||||
     * @return array storage fields
 | 
					     * @return array storage fields
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function composeFields($id, $data)
 | 
					    protected function composeFields($id = null, $data = null)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $fields = [
 | 
					        $fields = $this->writeCallback ? call_user_func($this->writeCallback, $this) : [];
 | 
				
			||||||
            'data' => $data,
 | 
					        if ($id !== null) {
 | 
				
			||||||
        ];
 | 
					            $fields['id'] = $id;
 | 
				
			||||||
        if ($this->writeCallback !== null) {
 | 
					        }
 | 
				
			||||||
            $fields = array_merge(
 | 
					        if ($data !== null) {
 | 
				
			||||||
                $fields,
 | 
					            $fields['data'] = $data;
 | 
				
			||||||
                call_user_func($this->writeCallback, $this)
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            if (!is_string($fields['data'])) {
 | 
					 | 
				
			||||||
                $_SESSION = $fields['data'];
 | 
					 | 
				
			||||||
                $fields['data'] = session_encode();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // ensure 'id' and 'expire' are never affected by [[writeCallback]]
 | 
					 | 
				
			||||||
        $fields = array_merge($fields, [
 | 
					 | 
				
			||||||
            'id' => $id,
 | 
					 | 
				
			||||||
            'expire' => time() + $this->getTimeout(),
 | 
					 | 
				
			||||||
        ]);
 | 
					 | 
				
			||||||
        return $fields;
 | 
					        return $fields;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -763,6 +763,11 @@ class ActiveField extends Component
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function widget($class, $config = [])
 | 
					    public function widget($class, $config = [])
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        foreach ($this->inputOptions as $key => $value) {
 | 
				
			||||||
 | 
					            if (!isset($config['options'][$key])) {
 | 
				
			||||||
 | 
					                $config['options'][$key] = $value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        /* @var $class \yii\base\Widget */
 | 
					        /* @var $class \yii\base\Widget */
 | 
				
			||||||
        $config['model'] = $this->model;
 | 
					        $config['model'] = $this->model;
 | 
				
			||||||
        $config['attribute'] = $this->attribute;
 | 
					        $config['attribute'] = $this->attribute;
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@ class ControllerTest extends TestCase
 | 
				
			|||||||
        $this->mockApplication();
 | 
					        $this->mockApplication();
 | 
				
			||||||
        Yii::$app->controllerMap = [
 | 
					        Yii::$app->controllerMap = [
 | 
				
			||||||
            'fake' => 'yiiunit\framework\console\FakeController',
 | 
					            'fake' => 'yiiunit\framework\console\FakeController',
 | 
				
			||||||
 | 
					            'fake_witout_output' => 'yiiunit\framework\console\FakeHelpControllerWithoutOutput',
 | 
				
			||||||
            'help' => 'yiiunit\framework\console\FakeHelpController',
 | 
					            'help' => 'yiiunit\framework\console\FakeHelpController',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -127,6 +128,10 @@ class ControllerTest extends TestCase
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $this->assertFalse(FakeController::getWasActionIndexCalled());
 | 
					        $this->assertFalse(FakeController::getWasActionIndexCalled());
 | 
				
			||||||
        $this->assertEquals(FakeHelpController::getActionIndexLastCallParams(), ['posts/index']);
 | 
					        $this->assertEquals(FakeHelpController::getActionIndexLastCallParams(), ['posts/index']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $helpController = new FakeHelpControllerWithoutOutput('help', Yii::$app);
 | 
				
			||||||
 | 
					        $helpController->actionIndex('fake/aksi1');
 | 
				
			||||||
 | 
					        $this->assertContains('--test-array, -ta', $helpController->outputString);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								tests/framework/console/FakeHelpControllerWithoutOutput.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/framework/console/FakeHelpControllerWithoutOutput.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @link http://www.yiiframework.com/
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2008 Yii Software LLC
 | 
				
			||||||
 | 
					 * @license http://www.yiiframework.com/license/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace yiiunit\framework\console;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use yii\console\controllers\HelpController;
 | 
				
			||||||
 | 
					use yii\helpers\Console;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FakeHelpControllerWithoutOutput extends HelpController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public $outputString = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function stdout($string)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->outputString .= $string;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -10,6 +10,7 @@ namespace yiiunit\framework\web\session;
 | 
				
			|||||||
use Yii;
 | 
					use Yii;
 | 
				
			||||||
use yii\db\Connection;
 | 
					use yii\db\Connection;
 | 
				
			||||||
use yii\db\Query;
 | 
					use yii\db\Query;
 | 
				
			||||||
 | 
					use yii\db\Migration;
 | 
				
			||||||
use yii\web\DbSession;
 | 
					use yii\web\DbSession;
 | 
				
			||||||
use yiiunit\framework\console\controllers\EchoMigrateController;
 | 
					use yiiunit\framework\console\controllers\EchoMigrateController;
 | 
				
			||||||
use yiiunit\TestCase;
 | 
					use yiiunit\TestCase;
 | 
				
			||||||
@ -147,6 +148,33 @@ abstract class AbstractDbSessionTest extends TestCase
 | 
				
			|||||||
        $this->assertSame('changed by callback data', $session->readSession('test'));
 | 
					        $this->assertSame('changed by callback data', $session->readSession('test'));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @depends testReadWrite
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function testWriteCustomFieldWithUserId()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $session = new DbSession();
 | 
				
			||||||
 | 
					        $session->open();
 | 
				
			||||||
 | 
					        $session->set('user_id', 12345);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // add mapped custom column
 | 
				
			||||||
 | 
					        $migration = new Migration;
 | 
				
			||||||
 | 
					        $migration->addColumn($session->sessionTable, 'user_id', $migration->integer());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $session->writeCallback = function ($session) {
 | 
				
			||||||
 | 
					            return ['user_id' => $session['user_id']];
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // here used to be error, fixed issue #9438
 | 
				
			||||||
 | 
					        $session->close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // reopen & read session from DB
 | 
				
			||||||
 | 
					        $session->open();
 | 
				
			||||||
 | 
					        $loadedUserId = empty($session['user_id']) ? null : $session['user_id'];
 | 
				
			||||||
 | 
					        $this->assertSame($loadedUserId, 12345);
 | 
				
			||||||
 | 
					        $session->close();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function buildObjectForSerialization()
 | 
					    protected function buildObjectForSerialization()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $object = new \stdClass();
 | 
					        $object = new \stdClass();
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@ use yii\web\View;
 | 
				
			|||||||
use yii\widgets\ActiveField;
 | 
					use yii\widgets\ActiveField;
 | 
				
			||||||
use yii\widgets\ActiveForm;
 | 
					use yii\widgets\ActiveForm;
 | 
				
			||||||
use yii\widgets\InputWidget;
 | 
					use yii\widgets\InputWidget;
 | 
				
			||||||
 | 
					use yii\widgets\MaskedInput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @author Nelson J Morais <njmorais@gmail.com>
 | 
					 * @author Nelson J Morais <njmorais@gmail.com>
 | 
				
			||||||
@ -584,6 +585,30 @@ HTML;
 | 
				
			|||||||
        $this->assertEqualsWithoutLE($expectedValue, trim($actualValue));
 | 
					        $this->assertEqualsWithoutLE($expectedValue, trim($actualValue));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testInputOptionsTransferToWidget()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $widget = $this->activeField->widget(TestMaskedInput::className(), [
 | 
				
			||||||
 | 
					            'mask' => '999-999-9999',
 | 
				
			||||||
 | 
					            'options' => ['placeholder' => 'pholder_direct'],
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        $this->assertContains('placeholder="pholder_direct"', (string) $widget);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // transfer options from ActiveField to widget
 | 
				
			||||||
 | 
					        $this->activeField->inputOptions = ['placeholder' => 'pholder_input'];
 | 
				
			||||||
 | 
					        $widget = $this->activeField->widget(TestMaskedInput::className(), [
 | 
				
			||||||
 | 
					            'mask' => '999-999-9999',
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        $this->assertContains('placeholder="pholder_input"', (string) $widget);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // set both AF and widget options (second one takes precedence)
 | 
				
			||||||
 | 
					        $this->activeField->inputOptions = ['placeholder' => 'pholder_both_input'];
 | 
				
			||||||
 | 
					        $widget = $this->activeField->widget(TestMaskedInput::className(), [
 | 
				
			||||||
 | 
					            'mask' => '999-999-9999',
 | 
				
			||||||
 | 
					            'options' => ['placeholder' => 'pholder_both_direct']
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        $this->assertContains('placeholder="pholder_both_direct"', (string) $widget);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Helper methods.
 | 
					     * Helper methods.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -667,3 +692,31 @@ class TestInputWidget extends InputWidget
 | 
				
			|||||||
        return 'Render: ' . get_class($this);
 | 
					        return 'Render: ' . get_class($this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestMaskedInput extends MaskedInput
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var static
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static $lastInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function init()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parent::init();
 | 
				
			||||||
 | 
					        self::$lastInstance = $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getOptions() {
 | 
				
			||||||
 | 
					        return $this->options;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function run()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return 'Options: ' . implode(', ', array_map(
 | 
				
			||||||
 | 
					            function ($v, $k) { return sprintf('%s="%s"', $k, $v); },
 | 
				
			||||||
 | 
					            $this->options,
 | 
				
			||||||
 | 
					            array_keys($this->options)
 | 
				
			||||||
 | 
					        ));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user