Skip to content

Commit

Permalink
Merge d831d7e into b6b76d1
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Jan 19, 2020
2 parents b6b76d1 + d831d7e commit 1f4f833
Show file tree
Hide file tree
Showing 11 changed files with 315 additions and 3 deletions.
6 changes: 6 additions & 0 deletions config/set/cakephp-to-symfony/cakephp-24-to-symfony-50.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# from CakePHP 2.4.6 to Symfony 5.1 (May 2020) and Twig 3
services:
# https://github.com/cakephp/cakephp/blob/2.4.6/lib/Cake/Controller/Controller.php
Rector\CakePHPToSymfony\Rector\Class_\CakePHPControllerToSymfonyControllerRector: null
Rector\CakePHPToSymfony\Rector\ClassMethod\CakePHPControllerActionToSymfonyControllerActionRector: null
Rector\CakePHPToSymfony\Rector\Class_\CakePHPControllerHelperToSymfonyRector: null
Rector\CakePHPToSymfony\Rector\Class_\CakePHPControllerComponentToSymfonyRector: null
Rector\CakePHPToSymfony\Rector\ClassMethod\CakePHPControllerRedirectToSymfonyRector: null
Rector\CakePHPToSymfony\Rector\ClassMethod\CakePHPControllerRenderToSymfonyRector: null

# .tpl templates to twig
Rector\CakePHPToSymfony\Rector\Echo_\CakePHPTemplateLinkToTwigRector: null
Rector\CakePHPToSymfony\Rector\Echo_\CakePHPTemplateTranslateToTwigRector: null
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
use PhpParser\Node\Stmt\Return_;
use Rector\CakePHPToSymfony\Rector\AbstractCakePHPRector;
use Rector\CakePHPToSymfony\Rector\Template\TemplateMethodCallManipulator;
use Rector\CakePHPToSymfony\Rector\TemplatePathResolver;
use Rector\CakePHPToSymfony\TemplatePathResolver;
use Rector\CodeQuality\CompactConverter;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php

declare(strict_types=1);

namespace Rector\CakePHPToSymfony\Rector\Echo_;

use Nette\Utils\Html;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Stmt\Echo_;
use PhpParser\Node\Stmt\InlineHTML;
use Rector\CakePHPToSymfony\RouteResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
use Symplify\SmartFileSystem\SmartFileInfo;

/**
* @see \Rector\CakePHPToSymfony\Tests\Rector\Echo_\CakePHPTemplateLinkToTwigRector\CakePHPTemplateToTwigRectorTest
*/
final class CakePHPTemplateLinkToTwigRector extends AbstractRector
{
/**
* @var RouteResolver
*/
private $routeResolver;

public function __construct(RouteResolver $routeResolver)
{
$this->routeResolver = $routeResolver;
}

public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Migrate CakePHP 2.4 template method calls to Twig', [
new CodeSample(
<<<'PHP'
<li>
<?php echo $this->Html->link(__('List Rights'), ['action' => 'index']); ?>
</li>
PHP
,
<<<'PHP'
<li>
<a href="{{ path('index') }}">List Rights</a>
</li>
PHP

),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Echo_::class];
}

/**
* @param Echo_ $node
*/
public function refactor(Node $node): ?Node
{
$firstExpression = $node->exprs[0];
if (! $firstExpression instanceof MethodCall) {
return null;
}

if (! $this->isThisHtmlPropertyFetch($firstExpression->var)) {
return null;
}

$label = $firstExpression->args[0]->value;
$parameters = $firstExpression->args[1]->value;

# e.g. |trans https://symfony.com/doc/current/translation/templates.html#using-twig-filters
$labelFilters = [];
if ($label instanceof FuncCall) {
if ($this->isName($label, '__')) {
$labelFilters[] = 'trans';

$label = $label->args[0]->value;
}
}

$parametersValue = $this->getValue($parameters);

/** @var SmartFileInfo|null $fileInfo */
$fileInfo = $node->getAttribute(AttributeKey::FILE_INFO);
assert($fileInfo instanceof SmartFileInfo);

$routeName = $this->routeResolver->resolveFromParamsAndFileInfo($parametersValue, $fileInfo);
$labelValue = $this->getValue($label);
assert(is_string($labelValue));

$aHtml = $this->createAHtml($routeName, $labelFilters, $labelValue);
return new InlineHTML($aHtml);
}

private function isThisHtmlPropertyFetch(Expr $expr): bool
{
if (! $expr instanceof PropertyFetch) {
return false;
}

if (! $this->isName($expr->var, 'this')) {
return false;
}

if (! $this->isName($expr->name, 'Html')) {
return false;
}

return true;
}

private function createAHtml(string $routeName, array $labelFilters, string $labelValue): string
{
$aHtml = Html::el('a');
$aHtml->href = sprintf('{{ path(\'%s\') }}', $routeName);

if ($labelFilters !== []) {
$labelFilterAsString = implode('|', $labelFilters);

$labelValue = sprintf('{{ \'%s\'|%s }}', $labelValue, $labelFilterAsString);
}

$aHtml->setText($labelValue);

return $aHtml->toHtml();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Rector\CakePHPToSymfony\Rector\Echo_;

use PhpParser\Node;
use PhpParser\Node\Stmt\Echo_;
use PhpParser\Node\Stmt\InlineHTML;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;

/**
* @see \Rector\CakePHPToSymfony\Tests\Rector\Echo_\CakePHPTemplateTranslateToTwigRector\CakePHPTemplateTranslateToTwigRectorTest
*/
final class CakePHPTemplateTranslateToTwigRector extends AbstractRector
{
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Migrate CakePHP 2.4 template method calls with translate to Twig', [
new CodeSample('<h3><?php echo __("Actions"); ?></h3>', '<h3>{{ "Actions"|trans }}</h3>'),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Echo_::class];
}

/**
* @param Echo_ $node
*/
public function refactor(Node $node): ?Node
{
$expr = $node->exprs[0];
if (! $expr instanceof Node\Expr\FuncCall) {
return null;
}

if (! $this->isName($expr, '__')) {
return null;
}

$translatedValue = $expr->args[0]->value;
$translatedValue = $this->getValue($translatedValue);

$html = sprintf('{{ \'%s\'|trans }}', $translatedValue);

return new InlineHTML($html);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Return_;
use Rector\CakePHPToSymfony\Rector\TemplatePathResolver;
use Rector\CakePHPToSymfony\TemplatePathResolver;
use Rector\PhpParser\Node\Resolver\NameResolver;
use Rector\PhpParser\Node\Value\ValueResolver;
use Rector\PhpParser\NodeTraverser\CallableNodeTraverser;
Expand Down
41 changes: 41 additions & 0 deletions packages/CakePHPToSymfony/src/RouteResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Rector\CakePHPToSymfony;

use Nette\Utils\Strings;
use Rector\Exception\ShouldNotHappenException;
use Rector\Util\RectorStrings;
use Symplify\SmartFileSystem\SmartFileInfo;

final class RouteResolver
{
public function resolveFromParamsAndFileInfo(array $parameters, SmartFileInfo $smartFileInfo): string
{
$routeName = '';

if (isset($parameters['controller'])) {
$routeName = RectorStrings::camelCaseToUnderscore($parameters['controller']);
}

if (isset($parameters['action'])) {
$actionUnderscored = RectorStrings::camelCaseToUnderscore($parameters['action']);

if ($routeName !== '') {
return $routeName . '_' . $actionUnderscored;
}

$shortDirectoryName = Strings::after($smartFileInfo->getPath(), '/', -1);
if (! is_string($shortDirectoryName)) {
throw new ShouldNotHappenException();
}

$shortDirectoryNameUnderscored = RectorStrings::camelCaseToUnderscore($shortDirectoryName);

return $shortDirectoryNameUnderscored . '_' . $actionUnderscored;
}

return $routeName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Rector\CakePHPToSymfony\Rector;
namespace Rector\CakePHPToSymfony;

use Nette\Utils\Strings;
use PhpParser\Node;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Rector\CakePHPToSymfony\Tests\Rector\Echo_\CakePHPTemplateLinkToTwigRector;

use Iterator;
use Rector\CakePHPToSymfony\Rector\Echo_\CakePHPTemplateLinkToTwigRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class CakePHPTemplateToTwigRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideDataForTest()
*/
public function test(string $file): void
{
$this->doTestFileWithoutAutoload($file);
}

public function provideDataForTest(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

protected function getRectorClass(): string
{
return CakePHPTemplateLinkToTwigRector::class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<li>
<?php echo $this->Html->link(__('List Rights'), ['action' => 'index']); ?>
</li>
-----
<li>
<?php ?>
<a href="{{ path('rector_temp_tests_index') }}">{{ 'List Rights'|trans }}</a><?php ?>
</li>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Rector\CakePHPToSymfony\Tests\Rector\Echo_\CakePHPTemplateTranslateToTwigRector;

use Iterator;
use Rector\CakePHPToSymfony\Rector\Echo_\CakePHPTemplateTranslateToTwigRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class CakePHPTemplateTranslateToTwigRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideDataForTest()
*/
public function test(string $file): void
{
$this->doTestFileWithoutAutoload($file);
}

public function provideDataForTest(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

protected function getRectorClass(): string
{
return CakePHPTemplateTranslateToTwigRector::class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<h3><?php echo __('Actions'); ?></h3>
-----
<h3><?php ?>
{{ 'Actions'|trans }}<?php ?></h3>

0 comments on commit 1f4f833

Please sign in to comment.