Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions fixtures/d8/rector_examples/user_password.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

// should not be changed, deprecated in 9.1.0
function user_functions() {
// user_password().
$password = user_password();
$other_password = user_password(8);
$password_length = 12;
$last_password = user_password($password_length);
}
10 changes: 10 additions & 0 deletions fixtures/d8/rector_examples_updated/user_password.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

// should not be changed, deprecated in 9.1.0
function user_functions() {
// user_password().
$password = user_password();
$other_password = user_password(8);
$password_length = 12;
$last_password = user_password($password_length);
}
12 changes: 12 additions & 0 deletions src/Contract/DrupalCoreRectorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace DrupalRector\Contract;

use Rector\Core\Contract\Rector\PhpRectorInterface;

interface DrupalCoreRectorInterface extends PhpRectorInterface
{
public function getVersion(): string;
}
51 changes: 51 additions & 0 deletions src/Rector/AbstractDrupalCoreRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace DrupalRector\Rector;

use Drupal\Component\Utility\DeprecationHelper;
use DrupalRector\Contract\DrupalCoreRectorInterface;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrowFunction;
use Rector\Core\Rector\AbstractRector;

abstract class AbstractDrupalCoreRector extends AbstractRector implements DrupalCoreRectorInterface
{
public function refactor(Node $node)
{
if (version_compare(\Drupal::VERSION, $this->getVersion(), '<')) {
return null;
}

$result = $this->doRefactor($node);

if ($result === null) {
return $result;
}

if($node instanceof Node\Expr\CallLike && $result instanceof Node\Expr\CallLike) {
return $this->createBcCallOnCallLike($node, $result);
}

return $result;
}

/**
* Process Node of matched type
* @return Node|Node[]|null
*/
abstract protected function doRefactor(Node $node);

private function createBcCallOnCallLike(Node\Expr\CallLike $node, Node\Expr\CallLike $result): Node\Expr\StaticCall
{
$clonedNode = clone $node;
return $this->nodeFactory->createStaticCall(DeprecationHelper::class, 'backwardsCompatibleCall', [
$this->nodeFactory->createClassConstFetch(\Drupal::class, 'VERSION'),
$this->getVersion(),
new ArrowFunction(['expr' => $clonedNode]),
new ArrowFunction(['expr' => $result]),
]);
}

}
Empty file.
11 changes: 8 additions & 3 deletions src/Rector/Deprecation/UserPasswordRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace DrupalRector\Rector\Deprecation;

use DrupalRector\Rector\AbstractDrupalCoreRector;
use PhpParser\Node;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

final class UserPasswordRector extends AbstractRector
final class UserPasswordRector extends AbstractDrupalCoreRector
{
/**
* @inheritdoc
Expand Down Expand Up @@ -39,10 +39,15 @@ public function getNodeTypes(): array
];
}

public function getVersion(): string
{
return '9.1.0';
}

/**
* @inheritdoc
*/
public function refactor(Node $node): ?Node
public function doRefactor(Node $node): ?Node
{
assert($node instanceof Node\Expr\FuncCall);
if ($this->getName($node->name) !== 'user_password') {
Expand Down
43 changes: 43 additions & 0 deletions stubs/Drupal/Core/Component/Utility/DeprecationHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace Drupal\Component\Utility;

if (class_exists('Drupal\Core\Component\DeprecationHelper')) {
return;
}

final class DeprecationHelper {

/**
* Helper to run a callback based on the installed version of Drupal.
*
* With this helper, contributed or custom modules can easily run different
* code paths based on the version of Drupal using callbacks.
*
* The below templates help code editors and PHPStan understand the return
* value of this function.
*
* @template Current
* @template Deprecated
*
* @param string $version
* Version to check against.
* @param string $introducedVersion
* Version that deprecated the old code path.
* @param callable(): Current $current
* Callback for the current version of Drupal.
* @param callable(): Deprecated $deprecated
* Callback for older versions of Drupal.
*
* @return Current|Deprecated
*/
public static function backwardsCompatibleCall(string $version, string $introducedVersion, callable $current, callable $deprecated): mixed {
// Normalize the version string when it's a dev version.
$normalizedVersion = str_ends_with($version, '-dev') ? str_replace(['.x-dev', '-dev'], '.0', $version) : $version;

return version_compare($normalizedVersion, $introducedVersion, '>=') ? $current() : $deprecated();
}

}
9 changes: 9 additions & 0 deletions stubs/Drupal/Drupal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

if (class_exists(\Drupal::class)) {
return;
}

class Drupal {
const VERSION = '10.1.0-dev';
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

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

class UserPasswordRectorTest extends AbstractRectorTestCase {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
<?php

function simple_example() {
function simple_example()
{
$password = user_password();
$other_password = user_password(8);
$password_length = 12;
$last_password = user_password($password_length);
}

?>
-----
<?php

function simple_example() {
$password = \Drupal::service('password_generator')->generate();
$other_password = \Drupal::service('password_generator')->generate(8);
function simple_example()
{
$password = \Drupal\Component\Utility\DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '9.1.0', fn() => user_password(), fn() => \Drupal::service('password_generator')->generate());
$other_password = \Drupal\Component\Utility\DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '9.1.0', fn() => user_password(8), fn() => \Drupal::service('password_generator')->generate(8));
$password_length = 12;
$last_password = \Drupal::service('password_generator')->generate($password_length);
$last_password = \Drupal\Component\Utility\DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '9.1.0', fn() => user_password($password_length), fn() => \Drupal::service('password_generator')->generate($password_length));
}

?>