rector/rules/Privatization/NodeManipulator/VisibilityManipulator.php

191 lines
4.7 KiB
PHP
Raw Normal View History

2019-10-13 05:59:52 +00:00
<?php
declare(strict_types=1);
namespace Rector\Privatization\NodeManipulator;
use PhpParser\Node;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use Rector\Core\Exception\InvalidNodeTypeException;
2020-12-24 22:01:30 +00:00
use Rector\Core\ValueObject\Visibility;
2020-12-24 23:18:02 +00:00
use Webmozart\Assert\Assert;
final class VisibilityManipulator
{
/**
* @var array<class-string<Stmt>>
*/
private const ALLOWED_NODE_TYPES = [ClassMethod::class, Property::class, ClassConst::class, Class_::class];
2019-02-09 13:22:20 +00:00
/**
* @param ClassMethod|Property|ClassConst $node
*/
public function makeStatic(Node $node): void
{
2020-12-24 22:01:30 +00:00
$this->addVisibilityFlag($node, Visibility::STATIC);
2019-02-09 13:22:20 +00:00
}
/**
* @param ClassMethod|Class_ $node
*/
public function makeAbstract(Node $node): void
{
2020-12-24 22:01:30 +00:00
$this->addVisibilityFlag($node, Visibility::ABSTRACT);
}
/**
2020-09-17 07:34:27 +00:00
* @param ClassMethod|Property $node
*/
public function makeNonStatic(Node $node): void
{
2020-09-17 07:34:27 +00:00
if (! $node->isStatic()) {
return;
}
$node->flags -= Class_::MODIFIER_STATIC;
}
2019-08-25 10:29:15 +00:00
/**
* @param Class_|ClassMethod $node
*/
public function makeFinal(Node $node): void
{
2020-12-24 22:01:30 +00:00
$this->addVisibilityFlag($node, Visibility::FINAL);
2019-08-25 10:29:15 +00:00
}
/**
* @param Class_|ClassMethod $node
*/
public function makeNonFinal(Node $node): void
{
if (! $node->isFinal()) {
return;
}
$node->flags -= Class_::MODIFIER_FINAL;
}
/**
* This way "abstract", "static", "final" are kept
*
* @param ClassMethod|Property|ClassConst $node
*/
2021-01-30 21:41:25 +00:00
public function removeVisibility(Node $node): void
{
$this->ensureIsClassMethodOrProperty($node, __METHOD__);
// no modifier
if ($node->flags === 0) {
return;
}
if ($node->isPublic()) {
$node->flags -= Class_::MODIFIER_PUBLIC;
}
if ($node->isProtected()) {
$node->flags -= Class_::MODIFIER_PROTECTED;
}
if ($node->isPrivate()) {
$node->flags -= Class_::MODIFIER_PRIVATE;
}
}
/**
* @param ClassMethod|Property|ClassConst $node
*/
2020-12-24 22:01:30 +00:00
public function changeNodeVisibility(Node $node, int $visibility): void
{
2020-12-24 23:18:02 +00:00
Assert::oneOf($visibility, [
Visibility::PUBLIC,
Visibility::PROTECTED,
Visibility::PRIVATE,
Visibility::STATIC,
Visibility::ABSTRACT,
Visibility::FINAL,
]);
$this->replaceVisibilityFlag($node, $visibility);
}
/**
* @param ClassMethod|Property|ClassConst $node
*/
public function makePublic(Node $node): void
{
2020-12-24 22:01:30 +00:00
$this->replaceVisibilityFlag($node, Visibility::PUBLIC);
}
/**
* @param ClassMethod|Property|ClassConst $node
*/
public function makeProtected(Node $node): void
{
2020-12-24 22:01:30 +00:00
$this->replaceVisibilityFlag($node, Visibility::PROTECTED);
}
/**
* @param ClassMethod|Property|ClassConst $node
*/
public function makePrivate(Node $node): void
{
2020-12-24 22:01:30 +00:00
$this->replaceVisibilityFlag($node, Visibility::PRIVATE);
}
public function removeFinal(Class_ $class): void
{
$class->flags -= Class_::MODIFIER_FINAL;
}
/**
* @param Class_|ClassMethod|Property|ClassConst $node
*/
2020-12-24 22:01:30 +00:00
private function addVisibilityFlag(Node $node, int $visibility): void
{
$this->ensureIsClassMethodOrProperty($node, __METHOD__);
2020-12-24 22:01:30 +00:00
$node->flags |= $visibility;
}
private function ensureIsClassMethodOrProperty(Node $node, string $location): void
{
foreach (self::ALLOWED_NODE_TYPES as $allowedNodeType) {
if (is_a($node, $allowedNodeType, true)) {
return;
}
}
throw new InvalidNodeTypeException(sprintf(
'"%s" only accepts "%s" types. "%s" given.',
$location,
implode('", "', self::ALLOWED_NODE_TYPES),
get_class($node)
));
}
/**
* @param ClassMethod|Property|ClassConst $node
*/
2020-12-24 22:01:30 +00:00
private function replaceVisibilityFlag(Node $node, int $visibility): void
{
$isStatic = $node instanceof ClassMethod && $node->isStatic();
if ($isStatic) {
2021-01-30 21:41:25 +00:00
$this->removeVisibility($node);
}
2020-12-24 22:01:30 +00:00
if ($visibility !== Visibility::STATIC && $visibility !== Visibility::ABSTRACT && $visibility !== Visibility::FINAL) {
2021-01-30 21:41:25 +00:00
$this->removeVisibility($node);
}
$this->addVisibilityFlag($node, $visibility);
if ($isStatic) {
$this->makeStatic($node);
}
}
}