migrate to ServiceNameToTypeProvider that better maches use case

This commit is contained in:
TomasVotruba 2017-10-15 11:27:34 +02:00
parent b749d3f5e1
commit 0b86554364
9 changed files with 85 additions and 94 deletions

View File

@ -9,36 +9,38 @@ rectors:
Rector\Rector\Contrib\Nette\Environment\GetServiceToConstructorInjectionRector: ~
```
requires `Rector\Contract\Bridge\ServiceNameToTypeProviderInterface` service that provides **service type for certain service name**.
requires `Rector\Contract\Bridge\ServiceTypeForNameProviderInterface` service that provides **service type for certain service name**.
**Why Interface?**
**Why Should You Implement the Interface?**
This operation could be automated to some level, but Kernel and Container API vary over time, so the implementation is left up to you and your specific case. This allows any framework and container to use these rectors and gives you freedom to provide own types.
This operation could be automated on some level, but Kernel and Container API vary too much over frameworks and their versions. The implementation is left up to you and your specific case. **This allows any framework and container to use these rectors and gives you freedom to provide own desired types if needed**.
## How to Add it?
1. Implement `Rector\Contract\Bridge\ServiceNameToTypeProviderInterface`
1. Implement `Rector\Contract\Bridge\ServiceTypeForNameProviderInterface`
2. And add *name* to *type* map.
**Static implementation** would look like this:
```yaml
```php
<?php declare(strict_types=1);
use Rector\Contract\Bridge\ServiceNameToTypeProviderInterface;
use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
final class StaticProvidero implements ServiceNameToTypeProviderInterface
final class StaticProvidero implements ServiceTypeForNameProviderInterface
{
/**
* @return string[]
/**
* @var string[]
*/
public function provide(): array
private $nameToTypeMap = [
'eventDispatcher' => 'Symfony\Component\EventDispatcher\EventDispatcherInterface',
];
public function provideTypeForName(string $name): ?string
{
return [
'eventDispatcher' => 'Symfony\Component\EventDispatcher\EventDispatcherInterface',
];
return $this->nameToTypeMap[$name] ?? null;
}
}
```
@ -50,7 +52,7 @@ This operation could be automated to some level, but Kernel and Container API va
StaticProvider: ~
# this allows autowiring via interface
Rector\Contract\Bridge\ServiceNameToTypeProviderInterface:
Rector\Contract\Bridge\ServiceTypeForNameProviderInterface:
alias: StaticProvider
```
@ -65,36 +67,35 @@ Of couse we have some prepared examples for Kernel, don't you worry.
```php
use Psr\Container\ContainerInterface;
use Rector\Contract\Bridge\ServiceNameToTypeProviderInterface;
use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
use Symfony\Component\HttpKernel\Kernel;
final class AppKernelProvider implements ServiceNameToTypeProviderInterface
final class AppKernelProvider implements ServiceTypeForNameProviderInterface
{
/**
* @var ContainerInterface
*/
private $container;
// @todo: modify API so it matches
// https://github.com/RectorPHP/Rector/pull/86/commits/0e375e713b3fea3a990762d5f117a019d317e67e#diff-4f9e06675af869311a8729c450e01d2eL26
public function getTypeForName(string $name)
{
}
/**
* @return string[]
*/
public function provide(): array
public function provideTypeForName(string $name): ?string
{
}
private function getContainer(): ContainerInterface
{
// @todo: cache it
if ($this->container) {
return $this->container;
}
/** @var Kernel $kernel */
$kernel = new $kernelClass('rector_dev', true);
$kernel->boot();
return $kernel->getContainer();
return $this->container = $kernel->getContainer();
}
}
```

View File

@ -1,11 +0,0 @@
<?php declare(strict_types=1);
namespace Rector\Contract\Bridge;
interface ServiceNameToTypeProviderInterface
{
/**
* @return string[]
*/
public function provide(): array;
}

View File

@ -0,0 +1,8 @@
<?php declare(strict_types=1);
namespace Rector\Contract\Bridge;
interface ServiceTypeForNameProviderInterface
{
public function provideTypeForName(string $name): ?string;
}

View File

@ -6,7 +6,7 @@ use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use Rector\Builder\Class_\ClassPropertyCollector;
use Rector\Builder\Naming\NameResolver;
use Rector\Contract\Bridge\ServiceNameToTypeProviderInterface;
use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
use Rector\Node\Attribute;
use Rector\NodeAnalyzer\MethodCallAnalyzer;
use Rector\NodeFactory\NodeFactory;
@ -42,25 +42,22 @@ final class GetServiceToConstructorInjectionRector extends AbstractRector
private $methodCallAnalyzer;
/**
* @var ServiceNameToTypeProviderInterface
* @var ServiceTypeForNameProviderInterface
*/
private $serviceNameToTypeProvider;
// @todo: service to type map - any manuall implementation works, use interface
// and register to rector.yml
private $serviceTypeForNameProvider;
public function __construct(
NameResolver $nameResolver,
ClassPropertyCollector $classPropertyCollector,
NodeFactory $nodeFactory,
MethodCallAnalyzer $methodCallAnalyzer,
ServiceNameToTypeProviderInterface $serviceNameToTypeProvider
ServiceTypeForNameProviderInterface $serviceTypeForNameProvider
) {
$this->nameResolver = $nameResolver;
$this->classPropertyCollector = $classPropertyCollector;
$this->nodeFactory = $nodeFactory;
$this->methodCallAnalyzer = $methodCallAnalyzer;
$this->serviceNameToTypeProvider = $serviceNameToTypeProvider;
$this->serviceTypeForNameProvider = $serviceTypeForNameProvider;
}
public function isCandidate(Node $node): bool
@ -75,13 +72,11 @@ final class GetServiceToConstructorInjectionRector extends AbstractRector
{
$serviceName = $methodCallNode->args[0]->value->value;
$serviceToTypeMap = $this->serviceNameToTypeProvider->provide();
if (! isset($serviceToTypeMap[$serviceName])) {
$serviceType = $this->serviceTypeForNameProvider->provideTypeForName($serviceName);
if ($serviceType === null) {
return null;
}
$serviceType = $serviceToTypeMap[$serviceName];
$propertyName = $this->nameResolver->resolvePropertyNameFromType($serviceType);
$this->classPropertyCollector->addPropertyForClass(

View File

@ -8,7 +8,7 @@ use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Name\FullyQualified;
use Rector\Builder\Class_\ClassPropertyCollector;
use Rector\Builder\Naming\NameResolver;
use Rector\Contract\Bridge\ServiceNameToTypeProviderInterface;
use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
use Rector\Node\Attribute;
use Rector\NodeAnalyzer\SymfonyContainerCallsAnalyzer;
use Rector\NodeFactory\NodeFactory;
@ -62,22 +62,22 @@ final class CommandToConstructorInjectionRector extends AbstractRector
private $symfonyContainerCallsAnalyzer;
/**
* @var ServiceNameToTypeProviderInterface
* @var ServiceTypeForNameProviderInterface
*/
private $serviceNameToTypeProvider;
private $serviceTypeForNameProvider;
public function __construct(
ClassPropertyCollector $classPropertyCollector,
NameResolver $nameResolver,
NodeFactory $nodeFactory,
ServiceNameToTypeProviderInterface $serviceNameToTypeProvider,
SymfonyContainerCallsAnalyzer $symfonyContainerCallsAnalyzer
SymfonyContainerCallsAnalyzer $symfonyContainerCallsAnalyzer,
ServiceTypeForNameProviderInterface $serviceTypeForNameProvider
) {
$this->classPropertyCollector = $classPropertyCollector;
$this->nameResolver = $nameResolver;
$this->nodeFactory = $nodeFactory;
$this->serviceNameToTypeProvider = $serviceNameToTypeProvider;
$this->symfonyContainerCallsAnalyzer = $symfonyContainerCallsAnalyzer;
$this->serviceTypeForNameProvider = $serviceTypeForNameProvider;
}
public function isCandidate(Node $node): bool
@ -103,15 +103,11 @@ final class CommandToConstructorInjectionRector extends AbstractRector
$this->replaceParentContainerAwareCommandWithCommand($methodCallNode);
$serviceName = $methodCallNode->args[0]->value->value;
$serviceNameToTypeMap = $this->serviceNameToTypeProvider->provide();
if (! isset($serviceNameToTypeMap[$serviceName])) {
$serviceType = $this->serviceTypeForNameProvider->provideTypeForName($serviceName);
if ($serviceType === null) {
return null;
}
$serviceType = $serviceNameToTypeMap[$serviceName];
$propertyName = $this->nameResolver->resolvePropertyNameFromType($serviceType);
$this->classPropertyCollector->addPropertyForClass(

View File

@ -6,7 +6,7 @@ use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use Rector\Builder\Class_\ClassPropertyCollector;
use Rector\Builder\Naming\NameResolver;
use Rector\Contract\Bridge\ServiceNameToTypeProviderInterface;
use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
use Rector\Node\Attribute;
use Rector\NodeAnalyzer\SymfonyContainerCallsAnalyzer;
use Rector\NodeFactory\NodeFactory;
@ -42,22 +42,22 @@ final class GetterToPropertyRector extends AbstractRector
private $symfonyContainerCallsAnalyzer;
/**
* @var ServiceNameToTypeProviderInterface
* @var ServiceTypeForNameProviderInterface
*/
private $serviceNameToTypeProvider;
private $serviceTypeForNameProvider;
public function __construct(
NameResolver $nameResolver,
ClassPropertyCollector $classPropertyCollector,
NodeFactory $nodeFactory,
SymfonyContainerCallsAnalyzer $symfonyContainerCallsAnalyzer,
ServiceNameToTypeProviderInterface $serviceNameToTypeProvider
ServiceTypeForNameProviderInterface $serviceTypeForNameProvider
) {
$this->nameResolver = $nameResolver;
$this->classPropertyCollector = $classPropertyCollector;
$this->nodeFactory = $nodeFactory;
$this->symfonyContainerCallsAnalyzer = $symfonyContainerCallsAnalyzer;
$this->serviceNameToTypeProvider = $serviceNameToTypeProvider;
$this->serviceTypeForNameProvider = $serviceTypeForNameProvider;
}
public function isCandidate(Node $node): bool
@ -75,15 +75,11 @@ final class GetterToPropertyRector extends AbstractRector
public function refactor(Node $methodCallNode): ?Node
{
$serviceName = $methodCallNode->args[0]->value->value;
$serviceNameToTypeMap = $this->serviceNameToTypeProvider->provide();
if (! isset($serviceNameToTypeMap[$serviceName])) {
$serviceType = $this->serviceTypeForNameProvider->provideTypeForName($serviceName);
if ($serviceType === null) {
return null;
}
$serviceType = $serviceNameToTypeMap[$serviceName];
$propertyName = $this->nameResolver->resolvePropertyNameFromType($serviceType);
$this->classPropertyCollector->addPropertyForClass(

View File

@ -2,17 +2,19 @@
namespace Rector\Tests\Rector\Contrib\Nette\Environment\GetServiceToConstructorInjectionRector\Source;
use Rector\Contract\Bridge\ServiceNameToTypeProviderInterface;
use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
final class DummyProvider implements ServiceNameToTypeProviderInterface
final class DummyProvider implements ServiceTypeForNameProviderInterface
{
/**
* @return string[]
* @var string[]
*/
public function provide(): array
private $nameToTypeMap = [
'someService' => 'someType',
];
public function provideTypeForName(string $name): ?string
{
return [
'someService' => 'someType',
];
return $this->nameToTypeMap[$name] ?? null;
}
}

View File

@ -2,17 +2,19 @@
namespace Rector\Tests\Rector\Contrib\Symfony\Console\CommandToConstructorInjectionRector\Source;
use Rector\Contract\Bridge\ServiceNameToTypeProviderInterface;
use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
final class DummyProvider implements ServiceNameToTypeProviderInterface
final class DummyProvider implements ServiceTypeForNameProviderInterface
{
/**
* @return string[]
* @var string[]
*/
public function provide(): array
private $nameToTypeMap = [
'some_service' => 'stdClass',
];
public function provideTypeForName(string $name): ?string
{
return [
'some_service' => 'stdClass',
];
return $this->nameToTypeMap[$name] ?? null;
}
}

View File

@ -2,17 +2,19 @@
namespace Rector\Tests\Rector\Contrib\Symfony\HttpKernel\GetterToPropertyRector\Source;
use Rector\Contract\Bridge\ServiceNameToTypeProviderInterface;
use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
final class DummyProvider implements ServiceNameToTypeProviderInterface
final class DummyProvider implements ServiceTypeForNameProviderInterface
{
/**
* @return string[]
* @var string[]
*/
public function provide(): array
private $nameToTypeMap = [
'some_service' => 'stdClass',
];
public function provideTypeForName(string $name): ?string
{
return [
'some_service' => 'stdClass',
];
return $this->nameToTypeMap[$name] ?? null;
}
}