Skip to content

Commit

Permalink
Merge pull request #3497 from rectorphp/template
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba authored Jun 8, 2020
2 parents f39acba + f29deb6 commit ffb673e
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Return_;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocNode\Sensio\SensioTemplateTagValueNode;
use Rector\Core\PhpParser\Node\Manipulator\FuncCallManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
Expand All @@ -24,6 +29,10 @@
use Symfony\Component\HttpFoundation\Response;

/**
* @see https://github.com/symfony/symfony-docs/pull/12387#discussion_r329551967
* @see https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/view.html
* @see https://github.com/sensiolabs/SensioFrameworkExtraBundle/issues/641
*
* @see \Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\TemplateAnnotationVersion3RectorTest
* @see \Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\TemplateAnnotationVersion5RectorTest
*/
Expand All @@ -39,10 +48,19 @@ final class TemplateAnnotationRector extends AbstractRector
*/
private $templateGuesser;

public function __construct(TemplateGuesser $templateGuesser, int $version = 3)
{
/**
* @var FuncCallManipulator
*/
private $funcCallManipulator;

public function __construct(
TemplateGuesser $templateGuesser,
FuncCallManipulator $funcCallManipulator,
int $version = 3
) {
$this->templateGuesser = $templateGuesser;
$this->version = $version;
$this->funcCallManipulator = $funcCallManipulator;
}

public function getDefinition(): RectorDefinition
Expand Down Expand Up @@ -109,6 +127,10 @@ private function addAbstractControllerParentClassIfMissing(Class_ $node): ?Class

private function replaceTemplateAnnotation(ClassMethod $classMethod): ?Node
{
if (! $classMethod->isPublic()) {
return null;
}

/** @var SensioTemplateTagValueNode|null $sensioTemplateTagValueNode */
$sensioTemplateTagValueNode = $this->getSensioTemplateTagValueNode($classMethod);
if ($sensioTemplateTagValueNode === null) {
Expand All @@ -125,9 +147,9 @@ private function replaceTemplateAnnotation(ClassMethod $classMethod): ?Node
return $classMethod;
}

private function classHasTemplateAnnotations(Class_ $node): bool
private function classHasTemplateAnnotations(Class_ $class): bool
{
foreach ($node->getMethods() as $classMethod) {
foreach ($class->getMethods() as $classMethod) {
/** @var PhpDocInfo|null $phpDocInfo */
$phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
Expand Down Expand Up @@ -161,7 +183,6 @@ private function updateReturnType(ClassMethod $classMethod): void

if ($classMethod->returnType !== null) {
$returnTypeName = $this->getName($classMethod->returnType);

if ($returnTypeName !== null && is_a($returnTypeName, Response::class, true)) {
return;
}
Expand Down Expand Up @@ -193,12 +214,20 @@ private function refactorClassMethod(
if ($returnNode === null) {
// or add as last statement in the method
$classMethod->stmts[] = new Return_($thisRenderMethodCall);
} elseif ($returnNode->expr !== null) {
if ($this->isFuncCallName($returnNode->expr, 'compact')) {
/** @var FuncCall $compactFunCall */
$compactFunCall = $returnNode->expr;

$array = $this->createArrayFromCompactFuncCall($compactFunCall);
$thisRenderMethodCall->args[1] = new Arg($array);
$returnNode->expr = $thisRenderMethodCall;
} elseif (! $returnNode->expr instanceof MethodCall) {
$returnNode->expr = $thisRenderMethodCall;
}
}

// replace Return_ node value if exists and is not already in correct format
if ($returnNode && ! $returnNode->expr instanceof MethodCall) {
$returnNode->expr = $thisRenderMethodCall;
}

$this->updateReturnType($classMethod);
}
Expand Down Expand Up @@ -269,4 +298,16 @@ private function resolveArrayArgumentsFromMethodCall(Return_ $returnNode): array

return $arguments;
}

private function createArrayFromCompactFuncCall(FuncCall $compactFuncCall): Array_
{
$compactVariableNames = $this->funcCallManipulator->extractArgumentsFromCompactFuncCalls([$compactFuncCall]);

$array = new Array_();
foreach ($compactVariableNames as $compactVariableName) {
$arrayItem = new ArrayItem(new Variable($compactVariableName), new String_($compactVariableName));
$array->items[] = $arrayItem;
}
return $array;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php declare (strict_types=1);

namespace Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Fixture\Version3;
namespace Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\FixtureVersion3;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
Expand All @@ -27,7 +27,7 @@ class ResolveAnotherMethodCall extends AbstractController
-----
<?php declare (strict_types=1);

namespace Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Fixture\Version3;
namespace Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\FixtureVersion3;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\FixtureVersion5;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

final class CompactController extends AbstractController
{
/**
* @Template()
*/
public function index()
{
$hello = 'hi';
$world = 'earth';

return compact('hello', 'world');
}
}

?>
-----
<?php

namespace Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\FixtureVersion5;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

final class CompactController extends AbstractController
{
public function index(): \Symfony\Component\HttpFoundation\Response
{
$hello = 'hi';
$world = 'earth';

return $this->render('@FrameworkExtra/index.html.twig', ['hello' => $hello, 'world' => $world]);
}
}

?>

0 comments on commit ffb673e

Please sign in to comment.