mirror of
https://github.com/rectorphp/rector.git
synced 2025-04-19 06:52:51 +02:00
add FQN route + check for existing one
This commit is contained in:
parent
a9338ab9c8
commit
c29c09348a
@ -40,7 +40,7 @@ final class RouteTagValueNode implements PhpDocChildNode
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$string = sprintf('@%s(', $this->routeClass);
|
||||
$string = sprintf('@\\%s(', $this->routeClass);
|
||||
|
||||
$string .= sprintf('path="%s"', $this->path);
|
||||
if ($this->name) {
|
||||
|
@ -7,6 +7,7 @@ use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\NetteToSymfony\Annotation\RouteTagValueNode;
|
||||
use Rector\NetteToSymfony\Route\RouteInfo;
|
||||
@ -19,6 +20,7 @@ use Rector\PhpParser\Node\Maintainer\ClassMethodMaintainer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
use Rector\Util\RectorStrings;
|
||||
use ReflectionMethod;
|
||||
|
||||
/**
|
||||
@ -275,36 +277,22 @@ CODE_SAMPLE
|
||||
|
||||
foreach ($presenterClassNodes as $presenterClassNode) {
|
||||
foreach ((array) $presenterClassNode->stmts as $classStmt) {
|
||||
if (! $classStmt instanceof ClassMethod) {
|
||||
if ($this->shouldSkipClassStmt($classStmt)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// not an action method
|
||||
if (! $classStmt->isPublic()) {
|
||||
continue;
|
||||
}
|
||||
/** @var ClassMethod $classStmt */
|
||||
$path = $this->resolvePathFromClassAndMethodNodes($presenterClassNode, $classStmt);
|
||||
$phpDocTagNode = new RouteTagValueNode($this->routeAnnotationClass, $path);
|
||||
|
||||
if (! $this->matchName($classStmt, '#^(render|action)#')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// already has Route tag
|
||||
if ($this->docBlockAnalyzer->hasTag($classStmt, $this->routerClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$presenterName = $this->getName($presenterClassNode);
|
||||
$shortPresenterName = Strings::after($presenterName, '\\', -1);
|
||||
die;
|
||||
|
||||
dump($this->getName($classStmt));
|
||||
die;
|
||||
$this->docBlockAnalyzer->addTag($classStmt, $phpDocTagNode);
|
||||
}
|
||||
}
|
||||
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo allow extension with custom resolvers
|
||||
*/
|
||||
private function isRouteStaticCallMatch(StaticCall $node): bool
|
||||
{
|
||||
$className = $this->getName($node->class);
|
||||
@ -332,4 +320,36 @@ CODE_SAMPLE
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function shouldSkipClassStmt(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof ClassMethod) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// not an action method
|
||||
if (! $node->isPublic()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! $this->matchName($node, '#^(render|action)#')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// already has Route tag
|
||||
return $this->docBlockAnalyzer->hasTag($node, $this->routeAnnotationClass);
|
||||
}
|
||||
|
||||
private function resolvePathFromClassAndMethodNodes(Class_ $classNode, ClassMethod $classMethodNode): string
|
||||
{
|
||||
$presenterName = $this->getName($classNode);
|
||||
$presenterPart = Strings::after($presenterName, '\\', -1);
|
||||
$presenterPart = Strings::substring($presenterPart, 0, -Strings::length('Presenter'));
|
||||
$presenterPart = RectorStrings::camelCaseToDashes($presenterPart);
|
||||
|
||||
$match = Strings::match($this->getName($classMethodNode), '#^(action|render)(?<short_action_name>.*?$)#sm');
|
||||
$actionPart = lcfirst($match['short_action_name']);
|
||||
|
||||
return $presenterPart . '/' . $actionPart;
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ final class ConstantReferenceRouterFactory
|
||||
final class ConstantReferenceSomePresenter
|
||||
{
|
||||
/**
|
||||
* @Symfony\Component\Routing\Annotation\Route(path="/some-path", methods={"GET"})
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/some-path", methods={"GET"})
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
|
@ -41,7 +41,6 @@ final class GeneralMethodNamedRoutesRouterFactory
|
||||
public function create(): RouteList
|
||||
{
|
||||
$routeList = new RouteList();
|
||||
$routeList[] = new Route('<presenter>/<action>', 'Homepage:default');
|
||||
|
||||
return $routeList;
|
||||
}
|
||||
@ -50,14 +49,14 @@ final class GeneralMethodNamedRoutesRouterFactory
|
||||
final class GeneralMethodNamedRoutesSomePresenter
|
||||
{
|
||||
/**
|
||||
* @Symfony\Component\Routing\Annotation\Route(path="general-method-named-routes-some/first")
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="general-method-named-routes-some/first")
|
||||
*/
|
||||
public function actionFirst()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Symfony\Component\Routing\Annotation\Route(path="general-method-named-routes-some/second")
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="general-method-named-routes-some/second")
|
||||
*/
|
||||
public function actionSecond()
|
||||
{
|
||||
|
@ -51,14 +51,14 @@ final class MethodNamedRoutesRouterFactory
|
||||
final class MethodNamedRoutesSomePresenter
|
||||
{
|
||||
/**
|
||||
* @Symfony\Component\Routing\Annotation\Route(path="hi")
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="hi")
|
||||
*/
|
||||
public function actionFirst()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Symfony\Component\Routing\Annotation\Route(path="hello")
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="hello")
|
||||
*/
|
||||
public function actionSecond()
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ final class NewRouterFactory
|
||||
final class NewSomePresenter
|
||||
{
|
||||
/**
|
||||
* @Symfony\Component\Routing\Annotation\Route(path="some-path")
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="some-path")
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ final class StaticRouterFactory
|
||||
final class StaticSomePresenter
|
||||
{
|
||||
/**
|
||||
* @Symfony\Component\Routing\Annotation\Route(path="some-path", methods={"GET"})
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="some-path", methods={"GET"})
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
|
@ -12,10 +12,10 @@ final class RouterListToControllerAnnotationsRetorTest extends AbstractRectorTes
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFiles([
|
||||
// __DIR__ . '/Fixture/new_route_to_annotation.php.inc',
|
||||
// __DIR__ . '/Fixture/static_route_to_annotation.php.inc',
|
||||
// __DIR__ . '/Fixture/constant_reference_route_to_annotation.php.inc',
|
||||
// __DIR__ . '/Fixture/method_named_routes.php.inc',
|
||||
__DIR__ . '/Fixture/new_route_to_annotation.php.inc',
|
||||
__DIR__ . '/Fixture/static_route_to_annotation.php.inc',
|
||||
__DIR__ . '/Fixture/constant_reference_route_to_annotation.php.inc',
|
||||
__DIR__ . '/Fixture/method_named_routes.php.inc',
|
||||
__DIR__ . '/Fixture/general_method_named_routes.php.inc',
|
||||
]);
|
||||
}
|
||||
|
@ -68,8 +68,16 @@ final class DocBlockAnalyzer
|
||||
return false;
|
||||
}
|
||||
|
||||
// normalize tag name
|
||||
$name = ltrim($name, '@');
|
||||
|
||||
// simple check
|
||||
if (Strings::contains($node->getDocComment()->getText(), '@' . $name)) {
|
||||
if (Strings::contains($node->getDocComment()->getText(), '@' . ltrim($name, '@'))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// fqn class annotation
|
||||
if (Strings::contains($node->getDocComment()->getText(), '@\\' . ltrim($name, '@'))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ parameters:
|
||||
- '#Call to function method_exists\(\) with string and (.*?) will always evaluate to false#'
|
||||
- '#PHPDoc tag \@param for parameter \$node with type float is incompatible with native type PhpParser\\Node#'
|
||||
- '#Result of && is always true#'
|
||||
- '#Parameter \#2 \$classMethodNode of method Rector\\NetteToSymfony\\Rector\\RouterListToControllerAnnotationsRector\:\:resolvePathFromClassAndMethodNodes\(\) expects PhpParser\\Node\\Stmt\\ClassMethod, PhpParser\\Node\\Stmt given#'
|
||||
|
||||
# missuse of interface and class
|
||||
- '#Parameter \#1 (.*?) expects Symfony\\Component\\DependencyInjection\\ContainerBuilder, Symfony\\Component\\DependencyInjection\\ContainerInterface given#'
|
||||
|
Loading…
x
Reference in New Issue
Block a user