Skip to content

Commit

Permalink
Use PageRenderer and IconFactory directly
Browse files Browse the repository at this point in the history
Resolves: #2672
  • Loading branch information
sabbelasichon committed Jan 12, 2022
1 parent 0df0380 commit 61e1477
Show file tree
Hide file tree
Showing 5 changed files with 297 additions and 0 deletions.
3 changes: 3 additions & 0 deletions config/v11/typo3-115.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@
$services->set(\Ssch\TYPO3Rector\Rector\v11\v5\ReplaceTSFEATagParamsCallOnGlobalsRector::class);
$services->set(\Ssch\TYPO3Rector\Rector\v11\v5\HandleCObjRendererATagParamsMethodRector::class);
$services->set(\Ssch\TYPO3Rector\Rector\v11\v5\SubstituteBackendTemplateViewWithModuleTemplateRector::class);
$services->set(
\Ssch\TYPO3Rector\Rector\v11\v5\SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRector::class
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
<?php

declare(strict_types=1);

namespace Ssch\TYPO3Rector\Rector\v11\v5;

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Type\ObjectType;
use Rector\Core\NodeManipulator\ClassDependencyManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\PostRector\Collector\NodesToReplaceCollector;
use Rector\PostRector\ValueObject\PropertyMetadata;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @changelog https://docs.typo3.org/c/typo3/cms-core/master/en-us/Changelog/11.5/Deprecation-95235-PublicGetterOfServicesInModuleTemplate.html
* @see \Ssch\TYPO3Rector\Tests\Rector\v11\v5\SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRector\SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRectorTest
*/
final class SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRector extends AbstractRector
{
public function __construct(
private ClassDependencyManipulator $classDependencyManipulator,
private NodesToReplaceCollector $nodesToReplaceCollector
) {
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Class_::class];
}

/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
$iconFactoryMethodCalls = $this->findModuleTemplateMethodCallsByName($node, 'getIconFactory');
$pageRendererMethodCalls = $this->findModuleTemplateMethodCallsByName($node, 'getPageRenderer');

if ([] === $iconFactoryMethodCalls && [] === $pageRendererMethodCalls) {
return null;
}

if ([] !== $iconFactoryMethodCalls) {
$this->addIconFactoryToConstructor($node);

foreach ($iconFactoryMethodCalls as $iconFactoryMethodCall) {
$this->nodesToReplaceCollector->addReplaceNodeWithAnotherNode(
$iconFactoryMethodCall,
$this->nodeFactory->createPropertyFetch('this', 'iconFactory')
);
}
}

if ([] !== $pageRendererMethodCalls) {
$this->addPageRendererToConstructor($node);

foreach ($pageRendererMethodCalls as $pageRendererMethodCall) {
$this->nodesToReplaceCollector->addReplaceNodeWithAnotherNode(
$pageRendererMethodCall,
$this->nodeFactory->createPropertyFetch('this', 'pageRenderer')
);
}
}

// change the node
return $node;
}

/**
* @codeCoverageIgnore
*/
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Use PageRenderer and IconFactory directly instead of getting them from the ModuleTemplate',
[
new CodeSample(
<<<'CODE_SAMPLE'
class MyController extends ActionController
{
protected ModuleTemplateFactory $moduleTemplateFactory;
public function __construct(ModuleTemplateFactory $moduleTemplateFactory)
{
$this->moduleTemplateFactory = $moduleTemplateFactory;
}
public function myAction(): ResponseInterface
{
$moduleTemplate = $this->moduleTemplateFactory->create($this->request);
$moduleTemplate->getPageRenderer()->loadRequireJsModule('Vendor/Extension/MyJsModule');
$moduleTemplate->setContent($moduleTemplate->getIconFactory()->getIcon('some-icon', Icon::SIZE_SMALL)->render());
return $this->htmlResponse($moduleTemplate->renderContent());
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class MyController extends ActionController
{
protected ModuleTemplateFactory $moduleTemplateFactory;
protected IconFactory $iconFactory;
protected PageRenderer $pageRenderer;
public function __construct(
ModuleTemplateFactory $moduleTemplateFactory,
IconFactory $iconFactory,
PageRenderer $pageRenderer
) {
$this->moduleTemplateFactory = $moduleTemplateFactory;
$this->iconFactory = $iconFactory;
$this->pageRenderer = $pageRenderer;
}
public function myAction(): ResponseInterface
{
$moduleTemplate = $this->moduleTemplateFactory->create($this->request);
$this->pageRenderer->loadRequireJsModule('Vendor/Extension/MyJsModule');
$moduleTemplate->setContent($this->iconFactory->getIcon('some-icon', Icon::SIZE_SMALL)->render());
return $this->htmlResponse($moduleTemplate->renderContent());
}
}
CODE_SAMPLE
),

]
);
}

/**
* @return Node[]
*/
private function findModuleTemplateMethodCallsByName(Class_ $node, string $methodCallName): array
{
return $this->betterNodeFinder->find($node->stmts, function (Node $node) use ($methodCallName) {
if (! $node instanceof MethodCall) {
return false;
}

if (! $this->nodeTypeResolver->isMethodStaticCallOrClassMethodObjectType(
$node,
new ObjectType('TYPO3\CMS\Backend\Template\ModuleTemplate')
)) {
return false;
}

return $this->nodeNameResolver->isName($node->name, $methodCallName);
});
}

private function addIconFactoryToConstructor(Class_ $node): void
{
$this->classDependencyManipulator->addConstructorDependency(
$node,
new PropertyMetadata(
'iconFactory',
new ObjectType('TYPO3\CMS\Core\Imaging\IconFactory'),
Class_::MODIFIER_PRIVATE
)
);
}

private function addPageRendererToConstructor(Class_ $node): void
{
$this->classDependencyManipulator->addConstructorDependency(
$node,
new PropertyMetadata(
'pageRenderer',
new ObjectType('TYPO3\CMS\Core\Page\PageRenderer'),
Class_::MODIFIER_PRIVATE
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\v11\v5\SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRector\Fixture;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class MyController extends ActionController
{
protected ModuleTemplateFactory $moduleTemplateFactory;

public function __construct(ModuleTemplateFactory $moduleTemplateFactory)
{
$this->moduleTemplateFactory = $moduleTemplateFactory;
}

public function myAction(): ResponseInterface
{
$moduleTemplate = $this->moduleTemplateFactory->create($this->request);
$moduleTemplate->getPageRenderer()->loadRequireJsModule('Vendor/Extension/MyJsModule');
$moduleTemplate->setContent($moduleTemplate->getIconFactory()->getIcon('some-icon', Icon::SIZE_SMALL)->render());
return $this->htmlResponse($moduleTemplate->renderContent());
}
}

?>
-----
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\v11\v5\SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRector\Fixture;

use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Page\PageRenderer;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class MyController extends ActionController
{
protected ModuleTemplateFactory $moduleTemplateFactory;
private IconFactory $iconFactory;
private PageRenderer $pageRenderer;

public function __construct(ModuleTemplateFactory $moduleTemplateFactory, IconFactory $iconFactory, PageRenderer $pageRenderer)
{
$this->moduleTemplateFactory = $moduleTemplateFactory;
$this->iconFactory = $iconFactory;
$this->pageRenderer = $pageRenderer;
}

public function myAction(): ResponseInterface
{
$moduleTemplate = $this->moduleTemplateFactory->create($this->request);
$this->pageRenderer->loadRequireJsModule('Vendor/Extension/MyJsModule');
$moduleTemplate->setContent($this->iconFactory->getIcon('some-icon', Icon::SIZE_SMALL)->render());
return $this->htmlResponse($moduleTemplate->renderContent());
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Ssch\TYPO3Rector\Tests\Rector\v11\v5\SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

final class SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}

/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

use Rector\Core\Configuration\Option;
use Rector\Core\ValueObject\PhpVersion;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::PHP_VERSION_FEATURES, PhpVersion::PHP_74);

$containerConfigurator->import(__DIR__ . '/../../../../../../config/config_test.php');

$services = $containerConfigurator->services();
$services->set(
\Ssch\TYPO3Rector\Rector\v11\v5\SubstituteGetIconFactoryAndGetPageRendererFromModuleTemplateRector::class
);
};

0 comments on commit 61e1477

Please sign in to comment.