Commit e9f33644 authored by catch's avatar catch Committed by Jess
Browse files

Issue #3371619 by bbrala, andypost, dww, mglaman, Kingdutch, catch, mondrake,...

Issue #3371619 by bbrala, andypost, dww, mglaman, Kingdutch, catch, mondrake, heddn, Charlie ChX Negyesi: Implement utility method for invoking backward compatible code

(cherry picked from commit 7748f463)
parent 63cebe7e
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Component\Utility;

/**
 * Provides a helper method for handling deprecated code paths in projects.
 */
final class DeprecationHelper {

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

    return version_compare($normalizedVersion, $deprecatedVersion, '>=') ? $currentCallable() : $deprecatedCallable();
  }

}
+86 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Tests\Component\Utility;

use Drupal\Component\Utility\DeprecationHelper;
use PHPUnit\Framework\TestCase;

/**
 * @coversDefaultClass \Drupal\Component\Utility\DeprecationHelper
 * @group Utility
 */
class DeprecationHelperTest extends TestCase {

  /**
   * @param string $currentVersion
   *   The core version to test against.
   * @param array $tests
   *   Array of versions and their expected result.
   *
   * @dataProvider deprecatedHelperTestCases
   */
  public function testDeprecationHelper(string $currentVersion, array $tests) {
    foreach ($tests as $deprecatedVersion => $expectedCallable) {
      $result = DeprecationHelper::backwardsCompatibleCall(
        $currentVersion,
        $deprecatedVersion,
        fn() => 'current',
        fn() => 'deprecated',
      );
      $this->assertEquals($expectedCallable, $result, "Change introduced in $deprecatedVersion should return $expectedCallable for core version $currentVersion");
    }
  }

  public static function deprecatedHelperTestCases(): array {
    return [
      [
        'currentVersion' => '10.2.x-dev',
        'tests' => [
          '11.0.0' => 'deprecated',
          '10.3.0' => 'deprecated',
          '10.2.1' => 'deprecated',
          '10.2.0' => 'current',
          '10.1.0' => 'current',
          '10.0.0' => 'current',
          '9.5.0' => 'current',
        ],
      ],
      [
        'currentVersion' => '10.2.1',
        'tests' => [
          '11.0.0' => 'deprecated',
          '10.2.2' => 'deprecated',
          '10.2.1' => 'current',
          '10.2.0' => 'current',
          '10.1.0' => 'current',
          '10.0.0' => 'current',
          '9.5.0' => 'current',
        ],
      ],
      [
        'currentVersion' => '11.0-dev',
        'tests' => [
          '11.5.0' => 'deprecated',
          '11.0.1' => 'deprecated',
          '11.0.0' => 'current',
          '10.1.0' => 'current',
          '9.5.0' => 'current',
        ],
      ],
      [
        'currentVersion' => '11.0.0',
        'tests' => [
          '11.5.0' => 'deprecated',
          '11.2.1' => 'deprecated',
          '11.0.1' => 'deprecated',
          '11.0.0' => 'current',
          '10.1.0' => 'current',
          '9.5.0' => 'current',
        ],
      ],
    ];
  }

}