Skip to content

Commit

Permalink
Extension to detect return type of MailerAwareTrait::getMailer
Browse files Browse the repository at this point in the history
  • Loading branch information
rochamarcelo committed Oct 11, 2024
1 parent 2fa5cff commit ab8fb5a
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 0 deletions.
4 changes: 4 additions & 0 deletions extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ services:
class: CakeDC\PHPStan\PhpDoc\TableAssociationTypeNodeResolverExtension
tags:
- phpstan.phpDoc.typeNodeResolverExtension
-
class: CakeDC\PHPStan\Type\GetMailerExpressionTypeResolverExtension
tags:
- phpstan.broker.expressionTypeResolverExtension
102 changes: 102 additions & 0 deletions src/Type/GetMailerExpressionTypeResolverExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
declare(strict_types=1);

/**
* Copyright 2020, Cake Development Corporation (https://www.cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2020, Cake Development Corporation (https://www.cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/

namespace CakeDC\PHPStan\Type;

use Cake\Mailer\MailerAwareTrait;
use CakeDC\PHPStan\Utility\CakeNameRegistry;
use PhpParser\Node\Expr;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\ExpressionTypeResolverExtension;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ThisType;
use PHPStan\Type\Type;

class GetMailerExpressionTypeResolverExtension implements ExpressionTypeResolverExtension
{
/**
* @var string
*/
protected string $methodName;
protected string $namespaceFormat;
protected string $targetTrait;

/**
* Contructor
*/
public function __construct()
{
$this->targetTrait = MailerAwareTrait::class;
$this->methodName = 'getMailer';
$this->namespaceFormat = '%s\\Mailer\\%sMailer';
}

/**
* @param \PhpParser\Node\Expr $expr
* @param \PHPStan\Analyser\Scope $scope
* @return \PHPStan\Type\Type|null
*/
public function getType(Expr $expr, Scope $scope): ?Type
{
if (
!$expr instanceof Expr\MethodCall
|| !$expr->name instanceof Identifier
|| $expr->name->toString() !== $this->methodName
) {
return null;
}

$callerType = $scope->getType($expr->var);

if (
!$callerType instanceof ThisType
|| !$this->isFromTargetTrait($callerType->getClassReflection())
) {
return null;
}

$value = $expr->getArgs()[0]->value ?? null;
if (!$value instanceof String_) {
return null;
}
$className = CakeNameRegistry::getClassName($value->value, $this->namespaceFormat);
if ($className !== null) {
return new ObjectType($className);
}

return null;
}

/**
* @param \PHPStan\Reflection\ClassReflection $reflection
* @return bool
*/
protected function isFromTargetTrait(ClassReflection $reflection): bool
{
foreach ($reflection->getTraits() as $trait) {
if ($trait->getName() === $this->targetTrait) {
return true;
}
}
foreach ($reflection->getParents() as $parent) {
if ($this->isFromTargetTrait($parent)) {
return true;
}
}

return false;
}
}
30 changes: 30 additions & 0 deletions tests/test_app/Command/MyTestExtendedCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);

/**
* Copyright 2020, Cake Development Corporation (https://www.cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2020, Cake Development Corporation (https://www.cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/

namespace App\Command;

use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;

class MyTestExtendedCommand extends MyTestLoadCommand
{
/**
* @inheritDoc
*/
public function execute(Arguments $args, ConsoleIo $io)
{
$this->fetchTable('VeryCustomize00009Articles')->newSample();
$io->helper('MyHeading')->headingOne('Sample Text 02');
$this->getMailer('MyTestLoad')->testing();
}
}
4 changes: 4 additions & 0 deletions tests/test_app/Command/MyTestLoadCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
use Cake\Command\Command;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
use Cake\Mailer\MailerAwareTrait;

class MyTestLoadCommand extends Command
{
use MailerAwareTrait;

/**
* @inheritDoc
*/
Expand All @@ -29,5 +32,6 @@ public function execute(Arguments $args, ConsoleIo $io)
$io->helper('progress')->increment(1);
$io->out($io->helper('BazBaz')->foo());
$io->helper('MyHeading')->headingOne('Sample Text 01');
$this->getMailer('MyTestLoad')->testing();
}
}
7 changes: 7 additions & 0 deletions tests/test_app/Mailer/MyTestLoadMailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,11 @@ protected function sampleLoading()
->newSample();
$this->viewBuilder()->setVar('article', $article);
}

/**
* @return void
*/
public function testing()
{
}
}

0 comments on commit ab8fb5a

Please sign in to comment.