Skip to content

Commit

Permalink
Merge pull request #2 from yiisoft/master
Browse files Browse the repository at this point in the history
merge upstream
  • Loading branch information
yus-ham authored Nov 20, 2020
2 parents 6b10196 + 22d3255 commit d4272f1
Show file tree
Hide file tree
Showing 17 changed files with 244 additions and 25 deletions.
2 changes: 1 addition & 1 deletion docs/guide-ru/test-environment-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Changed current directory to <directory>
Если вы используете Apache и настроили его как описано в разделе «[Установка Yii](start-installation.md)», то для тестов вам необходимо создать отдельный виртуальный хост который будет работать с той же папкой, но использовать входной скрипт `index-test.php`:
```
<VirtualHost *:80>
DocumentRoot "path/to/basic/webb"
DocumentRoot "path/to/basic/web"
ServerName mysite-test
<Directory "path/to/basic/web">
Order Allow,Deny
Expand Down
8 changes: 7 additions & 1 deletion framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ Yii Framework 2 Change Log
2.0.40 under development
------------------------

- no changes in this release.
- Bug #18396: Fix not throw `InvalidConfigException` when failed to instantiate class via DI container in some cases (vjik)
- Enh #18200: Add `maxlength` attribute by default to the input text when it is an active field within a `yii\grid\DataColumn` (rad8329)

2.0.39.2 November 13, 2020
--------------------------

- Bug #18378: Fix not taking default value when unable to resolve abstract class via DI container (vjik)


2.0.39.1 November 10, 2020
Expand Down
1 change: 1 addition & 0 deletions framework/base/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public function init()
*
* [[\Yii::createObject()]] will be used later to create the requested action
* using the configuration provided here.
* @return array
*/
public function actions()
{
Expand Down
2 changes: 1 addition & 1 deletion framework/base/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class View extends Component implements DynamicContentAwareInterface
*/
public $context;
/**
* @var mixed custom parameters that are shared among view templates.
* @var array custom parameters that are shared among view templates.
*/
public $params = [];
/**
Expand Down
3 changes: 3 additions & 0 deletions framework/console/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ class Controller extends \yii\base\Controller
private $_passedOptions = [];


/**
* {@inheritdoc}
*/
public function beforeAction($action)
{
$silentExit = $this->silentExitOnException !== null ? $this->silentExitOnException : YII_ENV_TEST;
Expand Down
44 changes: 36 additions & 8 deletions framework/di/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

use ReflectionClass;
use ReflectionException;
use ReflectionNamedType;
use ReflectionParameter;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
Expand Down Expand Up @@ -493,7 +495,7 @@ protected function mergeParams($class, $params)
* Returns the dependencies of the specified class.
* @param string $class class name, interface name or alias name
* @return array the dependencies of the specified class.
* @throws InvalidConfigException if a dependency cannot be resolved or if a dependency cannot be fulfilled.
* @throws NotInstantiableException if a dependency cannot be resolved or if a dependency cannot be fulfilled.
*/
protected function getDependencies($class)
{
Expand All @@ -505,7 +507,12 @@ protected function getDependencies($class)
try {
$reflection = new ReflectionClass($class);
} catch (\ReflectionException $e) {
throw new InvalidConfigException('Failed to instantiate component or class "' . $class . '".', 0, $e);
throw new NotInstantiableException(
$class,
'Failed to instantiate component or class "' . $class . '".',
0,
$e
);
}

$constructor = $reflection->getConstructor();
Expand All @@ -522,16 +529,28 @@ protected function getDependencies($class)
try {
$c = $param->getClass();
} catch (ReflectionException $e) {
$c = null;
if (!$this->isNulledParam($param)) {
$notInstantiableClass = null;
if (PHP_VERSION_ID >= 70000) {
$type = $param->getType();
if ($type instanceof ReflectionNamedType) {
$notInstantiableClass = $type->getName();
}
}
throw new NotInstantiableException(
$notInstantiableClass,
$notInstantiableClass === null ? 'Can not instantiate unknown class.' : null
);
} else {
$c = null;
}
}
$isClass = $c !== null;
}
$className = $isClass ? $c->getName() : null;

if ($className !== null &&
($this->has($className) || class_exists($className))
) {
$dependencies[$param->getName()] = Instance::of($className);
if ($className !== null) {
$dependencies[$param->getName()] = Instance::of($className, $this->isNulledParam($param));
} else {
$dependencies[$param->getName()] = $param->isDefaultValueAvailable()
? $param->getDefaultValue()
Expand All @@ -546,6 +565,15 @@ protected function getDependencies($class)
return [$reflection, $dependencies];
}

/**
* @param ReflectionParameter $param
* @return bool
*/
private function isNulledParam($param)
{
return $param->isOptional() || (PHP_VERSION_ID >= 70100 && $param->getType()->allowsNull());
}

/**
* Resolves dependencies by replacing them with the actual object instances.
* @param array $dependencies the dependencies
Expand All @@ -558,7 +586,7 @@ protected function resolveDependencies($dependencies, $reflection = null)
foreach ($dependencies as $index => $dependency) {
if ($dependency instanceof Instance) {
if ($dependency->id !== null) {
$dependencies[$index] = $this->get($dependency->id);
$dependencies[$index] = $dependency->get($this);
} elseif ($reflection !== null) {
$name = $reflection->getConstructor()->getParameters()[$index]->getName();
$class = $reflection->getName();
Expand Down
35 changes: 25 additions & 10 deletions framework/di/Instance.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace yii\di;

use Exception;
use Yii;
use yii\base\InvalidConfigException;

Expand Down Expand Up @@ -59,25 +60,32 @@ class Instance
* @var string the component ID, class name, interface name or alias name
*/
public $id;
/**
* @var bool if null should be returned instead of throwing an exception
*/
public $optional;


/**
* Constructor.
* @param string $id the component ID
* @param bool $optional if null should be returned instead of throwing an exception
*/
protected function __construct($id)
protected function __construct($id, $optional = false)
{
$this->id = $id;
$this->optional = $optional;
}

/**
* Creates a new Instance object.
* @param string $id the component ID
* @param bool $optional if null should be returned instead of throwing an exception
* @return Instance the new Instance object.
*/
public static function of($id)
public static function of($id, $optional = false)
{
return new static($id);
return new static($id, $optional);
}

/**
Expand Down Expand Up @@ -157,14 +165,21 @@ public static function ensure($reference, $type = null, $container = null)
*/
public function get($container = null)
{
if ($container) {
return $container->get($this->id);
}
if (Yii::$app && Yii::$app->has($this->id)) {
return Yii::$app->get($this->id);
}
try {
if ($container) {
return $container->get($this->id);
}
if (Yii::$app && Yii::$app->has($this->id)) {
return Yii::$app->get($this->id);
}

return Yii::$container->get($this->id);
return Yii::$container->get($this->id);
} catch (Exception $e) {
if ($this->optional) {
return null;
}
throw $e;
}
}

/**
Expand Down
3 changes: 2 additions & 1 deletion framework/grid/DataColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,9 @@ protected function renderFilterCellContent()
0 => $this->grid->formatter->booleanFormat[0],
], $options) . $error;
}
$options = array_merge(['maxlength' => true], $this->filterInputOptions);

return Html::activeTextInput($model, $this->attribute, $this->filterInputOptions) . $error;
return Html::activeTextInput($model, $this->attribute, $options) . $error;
}

return parent::renderFilterCellContent();
Expand Down
8 changes: 8 additions & 0 deletions tests/data/base/Singer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,23 @@
*/
class Singer extends Model
{
public static $tableName;

public $firstName;
public $lastName;
public $test;

public static function tableName()
{
return static::$tableName ?: 'singer';
}

public function rules()
{
return [
[['lastName'], 'default', 'value' => 'Lennon'],
[['lastName'], 'required'],
[['lastName'], 'string', 'max' => 25],
[['underscore_style'], 'yii\captcha\CaptchaValidator'],
[['test'], 'required', 'when' => function ($model) { return $model->firstName === 'cebe'; }],
];
Expand Down
47 changes: 47 additions & 0 deletions tests/framework/di/ContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
use yiiunit\framework\di\stubs\Corge;
use yiiunit\framework\di\stubs\Foo;
use yiiunit\framework\di\stubs\FooProperty;
use yiiunit\framework\di\stubs\Kappa;
use yiiunit\framework\di\stubs\Qux;
use yiiunit\framework\di\stubs\QuxInterface;
use yiiunit\framework\di\stubs\QuxFactory;
use yiiunit\framework\di\stubs\Zeta;
use yiiunit\TestCase;

/**
Expand Down Expand Up @@ -547,6 +549,12 @@ public function testNulledConstructorParameters()
$this->assertInstanceOf(Beta::className(), $alpha->beta);
$this->assertInstanceOf($QuxInterface, $alpha->omega);
$this->assertNull($alpha->unknown);
$this->assertNull($alpha->color);

$container = new Container();
$container->set(__NAMESPACE__ . '\stubs\AbstractColor', __NAMESPACE__ . '\stubs\Color');
$alpha = $container->get(Alpha::className());
$this->assertInstanceOf(__NAMESPACE__ . '\stubs\Color', $alpha->color);
}

/**
Expand Down Expand Up @@ -574,4 +582,43 @@ public function testInvalidConstructorParameters()
'Hello',
]);
}

public function dataNotInstantiableException()
{
return [
[Bar::className()],
[Kappa::className()],
];
}

/**
* @dataProvider dataNotInstantiableException
*
* @see https://github.com/yiisoft/yii2/pull/18379
*
* @param string $class
*/
public function testNotInstantiableException($class)
{
$this->expectException('yii\di\NotInstantiableException');
(new Container())->get($class);
}

public function testNullTypeConstructorParameters()
{
if (PHP_VERSION_ID < 70100) {
$this->markTestSkipped('Can not be tested on PHP < 7.1');
return;
}

$zeta = (new Container())->get(Zeta::className());
$this->assertInstanceOf(Beta::className(), $zeta->beta);
$this->assertInstanceOf(Beta::className(), $zeta->betaNull);
$this->assertNull($zeta->color);
$this->assertNull($zeta->colorNull);
$this->assertNull($zeta->qux);
$this->assertNull($zeta->quxNull);
$this->assertNull($zeta->unknown);
$this->assertNull($zeta->unknownNull);
}
}
2 changes: 1 addition & 1 deletion tests/framework/di/InstanceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public function testRestoreAfterVarExport()
$instance = Instance::of('something');
$export = var_export($instance, true);

$this->assertRegExp('~yii\\\\di\\\\Instance::__set_state\(array\(\s+\'id\' => \'something\',\s+\)\)~', $export);
$this->assertRegExp('~yii\\\\di\\\\Instance::__set_state\(array\(\s+\'id\' => \'something\',\s+\'optional\' => false,\s+\)\)~', $export);

$this->assertEquals($instance, Instance::__set_state([
'id' => 'something',
Expand Down
9 changes: 9 additions & 0 deletions tests/framework/di/stubs/AbstractColor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace yiiunit\framework\di\stubs;

use yii\base\BaseObject;

abstract class AbstractColor extends BaseObject
{
}
10 changes: 8 additions & 2 deletions tests/framework/di/stubs/Alpha.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@ class Alpha extends BaseObject
public $beta;
public $omega;
public $unknown = true;
public $color = true;

public function __construct(Beta $beta = null, QuxInterface $omega = null, Unknown $unknown = null)
{
public function __construct(
Beta $beta = null,
QuxInterface $omega = null,
Unknown $unknown = null,
AbstractColor $color = null
) {
$this->beta = $beta;
$this->omega = $omega;
$this->unknown = $unknown;
$this->color = $color;
}
}
7 changes: 7 additions & 0 deletions tests/framework/di/stubs/Color.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace yiiunit\framework\di\stubs;

final class Color extends AbstractColor
{
}
12 changes: 12 additions & 0 deletions tests/framework/di/stubs/Kappa.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace yiiunit\framework\di\stubs;

use yii\base\BaseObject;

class Kappa extends BaseObject
{
public function __construct(Unknown $unknown)
{
}
}
Loading

0 comments on commit d4272f1

Please sign in to comment.