Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
19b636e
PHPStan add support of magic methods of Data Object.
Apr 20, 2020
8849d1e
PHPStan add support of magic methods of Data Object.
Apr 20, 2020
dea6c91
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Apr 20, 2020
d825912
PHPStan add support of magic methods of Data Object.
Apr 20, 2020
313fc6f
Merge branch 'PHPStan-support-of-Data-Object-magic-methods' of github…
Apr 20, 2020
6fef300
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Apr 20, 2020
6c2d86f
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Apr 23, 2020
f4b6d5e
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Apr 27, 2020
c7a02e0
PHPStan add support of magic methods of Data Object.
May 2, 2020
23483fb
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma May 2, 2020
c973636
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma May 6, 2020
9fed236
PHPStan add support of magic methods of Data Object.
May 7, 2020
9c1ba5a
Merge branch 'PHPStan-support-of-Data-Object-magic-methods' of github…
May 7, 2020
28dbb69
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma May 9, 2020
5f0c767
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma May 15, 2020
60d6b02
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Jun 20, 2020
64e5016
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Jun 23, 2020
61fe852
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Jun 24, 2020
cb50ff6
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
lenaorobei Jul 17, 2020
347c54f
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Jul 30, 2020
a243302
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
engcom-Charlie Aug 3, 2020
693cc0e
Remove removed file from blacklist.
Aug 5, 2020
46c8981
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Aug 5, 2020
4ff058c
Merge branch '2.4-develop' into PHPStan-support-of-Data-Object-magic-…
swnsma Aug 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\PhpStan\Reflection\Php;

use Magento\Framework\DataObject;
use Magento\Framework\Session\SessionManager;
use PHPStan\DependencyInjection\Container;
use PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;

/**
* Extension to add support of magic methods (get/set/uns/has) based on @see DataObject
*/
class DataObjectClassReflectionExtension implements MethodsClassReflectionExtension
{
private const MAGIC_METHODS_PREFIXES = [
'get',
'set',
'uns',
'has'
];

private const PREFIX_LENGTH = 3;

/**
* @var Container
*/
private $container;

/**
* @var AnnotationsMethodsClassReflectionExtension
*/
private $annotationsMethodsClassReflectionExtension;

/**
* @param Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
$this->annotationsMethodsClassReflectionExtension = $this->container
->getByType(AnnotationsMethodsClassReflectionExtension::class);
}

/**
* Check if class has relations with DataObject and requested method can be considered as a magic method.
*
* @param ClassReflection $classReflection
* @param string $methodName
*
* @return bool
*/
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
{
// Workaround due to annotation extension always loads last.
if ($this->annotationsMethodsClassReflectionExtension->hasMethod($classReflection, $methodName)) {
// In case when annotation already available for the method, we will not use 'magic methods' approach.
return false;
}
if ($classReflection->isSubclassOf(DataObject::class) || $classReflection->getName() == DataObject::class) {
return in_array($this->getPrefix($methodName), self::MAGIC_METHODS_PREFIXES);
}
/** SessionManager redirects all calls to `__call` to container which extends DataObject */
if ($classReflection->isSubclassOf(SessionManager::class)
|| $classReflection->getName() === SessionManager::class
) {
/** @see \Magento\Framework\Session\SessionManager::__call */
return in_array($this->getPrefix($methodName), self::MAGIC_METHODS_PREFIXES);
}

return false;
}

/**
* Get prefix from method name.
*
* @param string $methodName
*
* @return string
*/
private function getPrefix(string $methodName): string
{
return (string)substr($methodName, 0, self::PREFIX_LENGTH);
}

/**
* Get method reflection instance.
*
* @param ClassReflection $classReflection
* @param string $methodName
*
* @return MethodReflection
*/
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
{
return new DataObjectMethodReflection($classReflection, $methodName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\PhpStan\Reflection\Php;

use PHPStan\Reflection\ClassMemberReflection;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\FunctionVariant;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParameterReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\Php\DummyParameter;
use PHPStan\TrinaryLogic;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use PHPStan\Type\VoidType;

/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class DataObjectMethodReflection implements MethodReflection
{
private const PREFIX_LENGTH = 3;

/**
* @var ClassReflection
*/
private $classReflection;

/**
* @var string
*/
private $methodName;

/**
* @param ClassReflection $classReflection
* @param string $methodName
*/
public function __construct(ClassReflection $classReflection, string $methodName)
{
$this->classReflection = $classReflection;
$this->methodName = $methodName;
}

/**
* Get methods class reflection.
*
* @return ClassReflection
*/
public function getDeclaringClass(): ClassReflection
{
return $this->classReflection;
}

/**
* Get if method is static.
*
* @return bool
*/
public function isStatic(): bool
{
return false;
}

/**
* Get if method is private.
*
* @return bool
*/
public function isPrivate(): bool
{
return false;
}

/**
* Get if method is public.
*
* @return bool
*/
public function isPublic(): bool
{
return true;
}

/**
* Get Method PHP Doc comment message.
*
* @return string|null
*/
public function getDocComment(): ?string
{
return null;
}

/**
* Get Method Name.
*
* @return string
*/
public function getName(): string
{
return $this->methodName;
}

/**
* Get Prototype.
*
* @return ClassMemberReflection
*/
public function getPrototype(): ClassMemberReflection
{
return $this;
}

/**
* Get Magic Methods variant based on type (get/set/has/uns).
*
* @return ParametersAcceptor[]
*/
public function getVariants(): array
{
return [
new FunctionVariant(
TemplateTypeMap::createEmpty(),
TemplateTypeMap::createEmpty(),
$this->getMethodParameters(),
false,
$this->getReturnType()
)
];
}

/**
* Get prefix from method name.
*
* @return string
*/
private function getMethodNamePrefix(): string
{
return (string)substr($this->methodName, 0, self::PREFIX_LENGTH);
}

/**
* Get Magic Methods parameters.
*
* @return ParameterReflection[]
*/
private function getMethodParameters(): array
{
$params = [];
switch ($this->getMethodNamePrefix()) {
case 'set':
$params[] = new DummyParameter(
'value',
new MixedType(),
false,
null,
false,
null
);
break;
case 'get':
$params[] = new DummyParameter(
'index',
new UnionType([new StringType(), new IntegerType()]),
true,
null,
false,
null
);
break;
}

return $params;
}

/**
* Get Magic Methods return type.
*
* @return Type
*/
private function getReturnType(): Type
{
switch ($this->getMethodNamePrefix()) {
case 'set':
case 'uns':
$returnType = new ObjectType($this->classReflection->getName());
break;
case 'has':
$returnType = new BooleanType();
break;
default:
$returnType = new MixedType();
break;
}

return $returnType;
}

/**
* Get if method is deprecated.
*
* @return TrinaryLogic
*/
public function isDeprecated(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

/**
* Get deprecated description.
*
* @return string|null
*/
public function getDeprecatedDescription(): ?string
{
return null;
}

/**
* Get if method is final.
*
* @return TrinaryLogic
*/
public function isFinal(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

/**
* Get if method is internal.
*
* @return TrinaryLogic
*/
public function isInternal(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

/**
* Get method throw type.
*
* @return Type|null
*/
public function getThrowType(): ?Type
{
return new VoidType();
}

/**
* Get if method has side effect.
*
* @return TrinaryLogic
*/
public function hasSideEffects(): TrinaryLogic
{
return TrinaryLogic::createYes();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class PhpStan implements ToolInterface
*
* @see https://github.com/phpstan/phpstan#rule-levels
*/
private const RULE_LEVEL = 0;
private const RULE_LEVEL = 1;

/**
* Memory limit required by PHPStan for full Magento project scan.
Expand Down
Loading