Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy definition #58

Open
wants to merge 37 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
8679688
Add lazy definition
xepozz Nov 20, 2022
a783c5d
Apply fixes from StyleCI
StyleCIBot Nov 20, 2022
5ccf19c
Add missed files
xepozz Nov 20, 2022
908b4d6
Merge remote-tracking branch 'origin/lazy-definition' into lazy-defin…
xepozz Nov 20, 2022
5d6b89f
Fix decorator
xepozz Nov 20, 2022
f5225c2
[ci-review] Apply changes from Rector action.
Nov 20, 2022
8dbcf88
Add suggest section
xepozz Nov 20, 2022
9bd5fb3
Merge remote-tracking branch 'origin/lazy-definition' into lazy-defin…
xepozz Nov 20, 2022
690a335
Merge branch 'master' into lazy-definition
xepozz Dec 3, 2022
f034ae0
Use `friendsofphp/proxy-manager-lts` package
xepozz Dec 3, 2022
e03e225
Rework lazy definition
xepozz Dec 3, 2022
6a8f40e
Apply fixes from StyleCI
StyleCIBot Jul 1, 2023
f7aba27
Merge branch 'master' into lazy-definition
xepozz Jul 29, 2023
de1c7e8
Apply Rector changes (CI)
xepozz Jul 29, 2023
bd65bf9
Add php 8.2 in CI
xepozz Jul 29, 2023
fba80b0
Add php 8.2 in CI
xepozz Jul 29, 2023
a4e6abc
Merge remote-tracking branch 'origin/lazy-definition' into lazy-defin…
xepozz Jul 29, 2023
4ced43c
Fix tests and psalm errors
xepozz Jul 29, 2023
2ca1b5e
Apply suggestions from code review
xepozz Aug 1, 2023
e1d4093
Apply PR suggestions
xepozz Aug 1, 2023
baee300
Add composer-require-checker.json
xepozz Aug 1, 2023
3f99488
Fix null class property
xepozz Aug 1, 2023
bc09d53
Apply fixes from StyleCI
StyleCIBot Aug 1, 2023
cbc4373
Add a hack for already normalized configs
xepozz Aug 1, 2023
fd066f1
Merge branch 'lazy-definition' of github.com:yiisoft/definitions into…
xepozz Aug 1, 2023
6060238
Apply fixes from StyleCI
StyleCIBot Aug 1, 2023
6d4696e
Fix psalm
xepozz Aug 2, 2023
bb401d9
Merge branch 'lazy-definition' of github.com:yiisoft/definitions into…
xepozz Aug 2, 2023
41eef65
Remove PHP 8.2 from psalm CI
xepozz Aug 2, 2023
7993b9b
Merge branch 'master' into lazy-definition
xepozz Aug 2, 2023
29f4c54
Fix psalm error
xepozz Aug 19, 2023
4128323
Merge branch 'master' into lazy-definition
xepozz Aug 19, 2023
e6c3e9b
Merge branch 'master' into lazy-definition
xepozz Mar 3, 2024
23e3ff7
improve
vjik Mar 3, 2024
69be227
Merge pull request #88 from yiisoft/lazy-suggestion
xepozz Apr 16, 2024
5434734
Merge branch 'master' into lazy-definition
xepozz Apr 16, 2024
cf7935f
Apply fixes from StyleCI
StyleCIBot Apr 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
os: >-
['ubuntu-latest', 'windows-latest']
php: >-
['8.0', '8.1']
['8.0', '8.1', '8.2']
2 changes: 1 addition & 1 deletion .github/workflows/mutation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['8.1']
['8.1', '8.2']
xepozz marked this conversation as resolved.
Show resolved Hide resolved
secrets:
STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }}
2 changes: 1 addition & 1 deletion .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['8.0', '8.1']
['8.0', '8.1', '8.2']
4 changes: 4 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,17 @@
},
"require-dev": {
"maglnet/composer-require-checker": "^4.2",
"friendsofphp/proxy-manager-lts": "^1.0",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.17.0",
"roave/infection-static-analysis-plugin": "^1.18",
"spatie/phpunit-watcher": "^1.23",
"vimeo/psalm": "^4.30|^5.6",
"yiisoft/test-support": "^1.4"
},
"suggest": {
"friendsofphp/proxy-manager-lts": "Allows create proxy classes"
xepozz marked this conversation as resolved.
Show resolved Hide resolved
},
"autoload": {
"psr-4": {
"Yiisoft\\Definitions\\": "src"
Expand Down
1 change: 1 addition & 0 deletions src/CallableDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ final class CallableDefinition implements DefinitionInterface
{
/**
* @var array|callable
*
* @psalm-var callable|array{0:class-string,1:string}
*/
private $callable;
Expand Down
2 changes: 2 additions & 0 deletions src/Helpers/DefinitionExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ final class DefinitionExtractor
* @throws NotInstantiableException
*
* @return ParameterDefinition[]
*
* @psalm-return array<string, ParameterDefinition>
*/
public static function fromClassName(string $class): array
Expand Down Expand Up @@ -61,6 +62,7 @@ public static function fromClassName(string $class): array
* Extract dependency definitions from type hints of a function.
*
* @return ParameterDefinition[]
*
* @psalm-return array<string, ParameterDefinition>
*/
public static function fromFunction(ReflectionFunctionAbstract $reflectionFunction): array
Expand Down
6 changes: 5 additions & 1 deletion src/Helpers/Normalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,12 @@
return ArrayDefinition::fromConfig($config);
}

if ($definition instanceof DefinitionInterface) {
xepozz marked this conversation as resolved.
Show resolved Hide resolved
return $definition;

Check warning on line 91 in src/Helpers/Normalizer.php

View check run for this annotation

Codecov / codecov/patch

src/Helpers/Normalizer.php#L91

Added line #L91 was not covered by tests
}

// Ready object
if (is_object($definition) && !($definition instanceof DefinitionInterface)) {
if (is_object($definition)) {
return new ValueDefinition($definition);
}

Expand Down
48 changes: 48 additions & 0 deletions src/LazyDefinition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Definitions;

use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use Psr\Container\ContainerInterface;
use Yiisoft\Definitions\Contract\DefinitionInterface;
use Yiisoft\Definitions\Helpers\Normalizer;

final class LazyDefinition implements DefinitionInterface
{
public function __construct(
private mixed $definition,
/**
* @var class-string
xepozz marked this conversation as resolved.
Show resolved Hide resolved
*/
private string $objectClass,
xepozz marked this conversation as resolved.
Show resolved Hide resolved
) {
}

/**
* @psalm-suppress MixedArgumentTypeCoercion
*/
public function resolve(ContainerInterface $container): mixed
xepozz marked this conversation as resolved.
Show resolved Hide resolved
{
/** @var LazyLoadingValueHolderFactory $factory */
$factory = $container->get(LazyLoadingValueHolderFactory::class);
/**
* @var mixed $definition
*/
$definition = $this->definition;
$objectClass = $this->objectClass;
vjik marked this conversation as resolved.
Show resolved Hide resolved

/** @psalm-suppress InvalidArgument */
return $factory->createProxy(
$objectClass,
function (mixed &$wrappedObject) use ($container, $objectClass, $definition) {
xepozz marked this conversation as resolved.
Show resolved Hide resolved
$definition = Normalizer::normalize($definition, $objectClass);

Check warning on line 40 in src/LazyDefinition.php

View check run for this annotation

Codecov / codecov/patch

src/LazyDefinition.php#L40

Added line #L40 was not covered by tests
/**
* @var mixed $wrappedObject
*/
$wrappedObject = $definition->resolve($container);

Check warning on line 44 in src/LazyDefinition.php

View check run for this annotation

Codecov / codecov/patch

src/LazyDefinition.php#L44

Added line #L44 was not covered by tests
}
);
}
}
1 change: 1 addition & 0 deletions src/ReferencesArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ final class ReferencesArray
* @throws InvalidConfigException
*
* @return Reference[]
*
* @psalm-suppress DocblockTypeContradiction
*/
public static function from(array $ids): array
Expand Down
20 changes: 20 additions & 0 deletions tests/Support/NotFinalClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Definitions\Tests\Support;

class NotFinalClass
{
private array $arguments;

public function __construct(...$arguments)
{
$this->arguments = $arguments;
}

public function getArguments(): array
{
return $this->arguments;
}
}
16 changes: 16 additions & 0 deletions tests/Unit/ArrayDefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use TypeError;
use Yiisoft\Definitions\ArrayDefinition;
use Yiisoft\Definitions\Exception\InvalidConfigException;
use Yiisoft\Definitions\Reference;
Expand Down Expand Up @@ -523,4 +524,19 @@ public function testMagicMethods(): void
$object->getEvents()
);
}

public function testNonArrayArguments(): void
xepozz marked this conversation as resolved.
Show resolved Hide resolved
{
$definition = ArrayDefinition::fromConfig([
ArrayDefinition::CLASS_NAME => Mouse::class,
'setNameAndEngine()' => 'kitty',
]);
$container = new SimpleContainer();

$this->expectException(TypeError::class);
$this->expectExceptionMessage(
'Yiisoft\Definitions\ArrayDefinition::resolveFunctionArguments(): Argument #3 ($arguments) must be of type array, string given'
);
$definition->resolve($container);
}
}
2 changes: 1 addition & 1 deletion tests/Unit/Helpers/DefinitionResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function testEnsureResolvableDefinition(): void
$this->expectException(InvalidConfigException::class);
$this->expectExceptionMessage(
'Only references are allowed in constructor arguments, a definition object was provided: ' .
ValueDefinition::class
var_export(new ValueDefinition(7), true)
);
DefinitionResolver::ensureResolvable(new ValueDefinition(7));
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/Helpers/DefinitionValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ public function testDefinitionInArguments(): void
$this->expectException(InvalidConfigException::class);
$this->expectExceptionMessage(
'Only references are allowed in constructor arguments, a definition object was provided: ' .
ValueDefinition::class
var_export(new ValueDefinition(56), true)
);
DefinitionValidator::validate([
'class' => GearBox::class,
Expand Down
72 changes: 72 additions & 0 deletions tests/Unit/LazyDefinitionDecoratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Definitions\Tests\Unit;

use PHPUnit\Framework\TestCase;
use ProxyManager\Exception\InvalidProxiedClassException;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\Proxy\LazyLoadingInterface;
use Yiisoft\Definitions\ArrayDefinition;
use Yiisoft\Definitions\LazyDefinition;
use Yiisoft\Definitions\Tests\Support\EngineInterface;
use Yiisoft\Definitions\Tests\Support\NotFinalClass;
use Yiisoft\Definitions\Tests\Support\Phone;
use Yiisoft\Test\Support\Container\SimpleContainer;

final class LazyDefinitionDecoratorTest extends TestCase
xepozz marked this conversation as resolved.
Show resolved Hide resolved
{
public function testDecorateFinalClass(): void
{
$container = new SimpleContainer([
LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(),
]);

$class = Phone::class;

$definition = ArrayDefinition::fromConfig([
ArrayDefinition::CLASS_NAME => $class,
]);
$definition = new LazyDefinition($definition, $class);
xepozz marked this conversation as resolved.
Show resolved Hide resolved

$this->expectException(InvalidProxiedClassException::class);
$definition->resolve($container);
}

public function testDecorateNotFinalClass(): void
{
$container = new SimpleContainer([
LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(),
]);

$class = NotFinalClass::class;

$definition = ArrayDefinition::fromConfig([
ArrayDefinition::CLASS_NAME => $class,
]);
$definition = new LazyDefinition($definition, $class);
xepozz marked this conversation as resolved.
Show resolved Hide resolved

$phone = $definition->resolve($container);
xepozz marked this conversation as resolved.
Show resolved Hide resolved

self::assertInstanceOf(LazyLoadingInterface::class, $phone);
}

public function testDecorateInterface(): void
{
$container = new SimpleContainer([
LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(),
]);

$class = EngineInterface::class;

$definition = ArrayDefinition::fromConfig([
ArrayDefinition::CLASS_NAME => $class,
]);
$definition = new LazyDefinition($definition, $class);
xepozz marked this conversation as resolved.
Show resolved Hide resolved

$phone = $definition->resolve($container);
xepozz marked this conversation as resolved.
Show resolved Hide resolved

self::assertInstanceOf(LazyLoadingInterface::class, $phone);
}
}
Loading