Commit 9a81ff40 authored by Gábor Hojtsy's avatar Gábor Hojtsy
Browse files

Issue #3264603 by Gábor Hojtsy, mglaman: Check routing.yml files for...

Issue #3264603 by Gábor Hojtsy, mglaman: Check routing.yml files for deprecated `requirements` access checks in extensions
parent b55f96bc
Loading
Loading
Loading
Loading
+22 −25
Changes for src/DeprecationAnalyzer.php: 22 added lines, 25 removed lines.
Original line number Diff line number Diff line
@@ -102,6 +102,13 @@ final class DeprecationAnalyzer {
   */
  protected $themeFunctionDeprecationAnalyzer;

  /**
   * The route deprecation analyzer.
   *
   * @var \Drupal\upgrade_status\RouteDeprecationAnalyzer
   */
  protected $routeDeprecationAnalyzer;

  /**
   * The time service.
   *
@@ -140,6 +147,8 @@ final class DeprecationAnalyzer {
   *   The library deprecation analyzer.
   * @param \Drupal\upgrade_status\ThemeFunctionDeprecationAnalyzer $theme_function_deprecation_analyzer
   *   The theme function deprecation analyzer.
   * @param \Drupal\upgrade_status\RouteDeprecationAnalyzer $route_deprecation_analyzer
   *   The route deprecation analyzer.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   */
@@ -151,6 +160,7 @@ final class DeprecationAnalyzer {
    TwigDeprecationAnalyzer $twig_deprecation_analyzer,
    LibraryDeprecationAnalyzer $library_deprecation_analyzer,
    ThemeFunctionDeprecationAnalyzer $theme_function_deprecation_analyzer,
    RouteDeprecationAnalyzer $route_deprecation_analyzer,
    TimeInterface $time
  ) {
    $this->scanResultStorage = $key_value_factory->get('upgrade_status_scan_results');
@@ -160,6 +170,7 @@ final class DeprecationAnalyzer {
    $this->twigDeprecationAnalyzer = $twig_deprecation_analyzer;
    $this->libraryDeprecationAnalyzer = $library_deprecation_analyzer;
    $this->themeFunctionDeprecationAnalyzer = $theme_function_deprecation_analyzer;
    $this->routeDeprecationAnalyzer = $route_deprecation_analyzer;
    $this->time = $time;
  }

@@ -371,31 +382,17 @@ final class DeprecationAnalyzer {
      'data' => $json,
    ];

    $twig_deprecations = $this->twigDeprecationAnalyzer->analyze($extension);
    foreach ($twig_deprecations as $twig_deprecation) {
      $result['data']['files'][$twig_deprecation->getFile()]['messages'][] = [
        'message' => $twig_deprecation->getMessage(),
        'line' => $twig_deprecation->getLine(),
      ];
      $result['data']['totals']['errors']++;
      $result['data']['totals']['file_errors']++;
    }

    $deprecation_messages = $this->libraryDeprecationAnalyzer->analyze($extension);
    foreach ($deprecation_messages as $deprecation_message) {
      $result['data']['files'][$deprecation_message->getFile()]['messages'][] = [
        'message' => $deprecation_message->getMessage(),
        'line' => $deprecation_message->getLine(),
      ];
      $result['data']['totals']['errors']++;
      $result['data']['totals']['file_errors']++;
    }

    $theme_function_deprecations = $this->themeFunctionDeprecationAnalyzer->analyze($extension);
    foreach ($theme_function_deprecations as $deprecation_message) {
      $result['data']['files'][$deprecation_message->getFile()]['messages'][] = [
        'message' => $deprecation_message->getMessage(),
        'line' => $deprecation_message->getLine(),
    // Run further deprecation analyzers and collect results.
    $more_deprecations = array_merge(
      $this->twigDeprecationAnalyzer->analyze($extension),
      $this->libraryDeprecationAnalyzer->analyze($extension),
      $this->themeFunctionDeprecationAnalyzer->analyze($extension),
      (projectCollector::getDrupalCoreMajorVersion() > 8) ? $this->routeDeprecationAnalyzer->analyze($extension) : []
    );
    foreach ($more_deprecations as $one_deprecation) {
      $result['data']['files'][$one_deprecation->getFile()]['messages'][] = [
        'message' => $one_deprecation->getMessage(),
        'line' => $one_deprecation->getLine(),
      ];
      $result['data']['totals']['errors']++;
      $result['data']['totals']['file_errors']++;
+65 −0
Changes for src/RouteDeprecationAnalyzer.php: 65 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\upgrade_status;

use Drupal\Core\Extension\Extension;

/**
 * The route deprecation analyzer.
 */
final class RouteDeprecationAnalyzer {

  /**
   * Analyzes usages of deprecated route elements in an extension.
   *
   * @param \Drupal\Core\Extension\Extension $extension
   *  The extension to be analyzed.
   *
   * @return \Drupal\upgrade_status\DeprecationMessage[]
   *   A list of deprecation messages.
   *
   * @throws \Exception
   */
  public function analyze(Extension $extension): array {
    $deprecations = [];
    $routing_files = $this->getAllRoutingFiles(DRUPAL_ROOT . '/' . $extension->getPath());
    foreach ($routing_files as $routing_file) {
      $content = file_get_contents($routing_file);
      if (strpos($content, '_access_node_revision')) {
        $deprecations[] = new DeprecationMessage('The _access_node_revision routing requirement is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Use _entity_access instead. See https://www.drupal.org/node/3161210.', $routing_file, 0);
      }
      if (strpos($content, '_access_media_revision')) {
        $deprecations[] = new DeprecationMessage('The _access_media_revision routing requirement is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Use _entity_access instead. See https://www.drupal.org/node/3161210.', $routing_file, 0);
      }
    }
    return $deprecations;
  }

  /**
   * Finds all .routing.yml files for non-test extensions under a path.
   *
   * @param string $path
   *   Base path to find all .routing.yml files in.
   *
   * @return array
   *   A list of paths to .routing.yml files found under the base path.
   */
  private function getAllRoutingFiles(string $path) {
    $files = [];
    foreach(glob($path . '/*.routing.yml') as $file) {
      // Make sure the filename matches rules for an extension. There may be
      // routing.yml files in shipped configuration which would have more parts.
      $parts = explode('.', basename($file));
      if (count($parts) == 3) {
        $files[] = $file;
      }
    }
    foreach (glob($path . '/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
      $files = array_merge($files, $this->getAllRoutingFiles($dir));
    }
    return $files;
  }

}
+13 −0
Changes for tests/modules/upgrade_status_test_error/upgrade_status_test_error.routing.yml: 13 added lines, 0 removed lines.
Original line number Diff line number Diff line
upgrade_status_test_error.node.version_history:
  path: '/node/{node}/upgrade_status_test_error'
  defaults:
    _title: 'Revisions'
    _controller: '\Drupal\node\Controller\NodeController::revisionOverview'
  requirements:
    _access_node_revision: 'view'
    node: \d+
  options:
    _node_operation_route: TRUE
    parameters:
      node:
        type: entity:node
+9 −2
Changes for tests/src/Functional/UpgradeStatusAnalyzeTest.php: 9 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -36,8 +36,8 @@ class UpgradeStatusAnalyzeTest extends UpgradeStatusTestBase {

    $report = $key_value->get('upgrade_status_test_error');
    $this->assertNotEmpty($report);
    $this->assertEquals(5, $report['data']['totals']['file_errors']);
    $this->assertCount(5, $report['data']['files']);
    $this->assertEquals($this->getDrupalCoreMajorVersion() < 9 ? 5 : 6, $report['data']['totals']['file_errors']);
    $this->assertCount($this->getDrupalCoreMajorVersion() < 9 ? 5 : 6, $report['data']['files']);
    $file = reset($report['data']['files']);
    $message = $file['messages'][0];
    $this->assertEquals('fatal.php', basename(key($report['data']['files'])));
@@ -58,6 +58,13 @@ class UpgradeStatusAnalyzeTest extends UpgradeStatusTestBase {
    $message = $file['messages'][0];
    $this->assertEquals("Configuration entity must define a `config_export` key. See https://www.drupal.org/node/2481909", $message['message']);
    $this->assertEquals(15, $message['line']);
    if ($this->getDrupalCoreMajorVersion() > 8) {
      $file = next($report['data']['files']);
      $this->assertEquals('upgrade_status_test_error.routing.yml', basename(key($report['data']['files'])));
      $message = $file['messages'][0];
      $this->assertEquals("The _access_node_revision routing requirement is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Use _entity_access instead. See https://www.drupal.org/node/3161210.", $message['message']);
      $this->assertEquals(0, $message['line']);
    }
    $file = next($report['data']['files']);
    $this->assertEquals('upgrade_status_test_error.info.yml', basename(key($report['data']['files'])));
    $message = $file['messages'][0];
+9 −10
Changes for tests/src/Functional/UpgradeStatusUiTest.php: 9 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ class UpgradeStatusUiTest extends UpgradeStatusTestBase {
    $assert_session->buttonExists('Export selected as HTML');

    // Error and no-error test module results should show.
    $this->assertSame('5 problems', strip_tags($page->find('css', 'tr.project-upgrade_status_test_error td.scan-result')->getHtml()));
    $this->assertSame($this->getDrupalCoreMajorVersion() < 9 ? '5 problems' : '6 problems', strip_tags($page->find('css', 'tr.project-upgrade_status_test_error td.scan-result')->getHtml()));
    $this->assertSame($this->getDrupalCoreMajorVersion() < 9 ? 'No problems found' : '1 problem', strip_tags($page->find('css', 'tr.project-upgrade_status_test_9_compatible td.scan-result')->getHtml()));
    $this->assertSame('No problems found', strip_tags($page->find('css', 'tr.project-upgrade_status_test_10_compatible td.scan-result')->getHtml()));

@@ -66,10 +66,10 @@ class UpgradeStatusUiTest extends UpgradeStatusTestBase {
    $next_major = $this->getDrupalCoreMajorVersion() + 1;
    $this->assertSession()->linkByHrefExists('https://drupal.org/project/issues/upgrade_status_test_contributed_9_compatible?text=Drupal+' . $next_major . '&status=All');

    // Click the first '5 problems' link. Should be the custom project.
    $this->clickLink('5 problems', 1);
    // Check UI of results for the custom project.
    $this->drupalGet('/admin/reports/upgrade-status/project/upgrade_status_test_error');
    $this->assertText('Upgrade status test error');
    $this->assertText('2 errors found. 3 warnings found.');
    $this->assertText('2 errors found. ' . $this->getDrupalCoreMajorVersion() < 9 ? '3' : '4' . ' warnings found.');
    $this->assertText('Syntax error, unexpected T_STRING on line 3');

    // Go forward to the export page and assert that still contains the results
@@ -79,17 +79,16 @@ class UpgradeStatusUiTest extends UpgradeStatusTestBase {
    $this->assertText('Upgrade status test error');
    $this->assertText('Custom projects');
    $this->assertNoText('Contributed projects');
    $this->assertText('2 errors found. 3 warnings found.');
    $this->assertText('2 errors found. ' . $this->getDrupalCoreMajorVersion() < 9 ? '3' : '4' . ' warnings found.');
    $this->assertText('Syntax error, unexpected T_STRING on line 3');

    // Go back to the listing page and click over to exporting in single ASCII.
    $this->drupalGet(Url::fromRoute('upgrade_status.report'));
    $this->clickLink('5 problems', 1);
    // Go back to the results page and click over to exporting in single ASCII.
    $this->drupalGet('/admin/reports/upgrade-status/project/upgrade_status_test_error');
    $this->clickLink('Export as text');
    $this->assertText('Upgrade status test error');
    $this->assertText('CUSTOM PROJECTS');
    $this->assertNoText('CONTRIBUTED PROJECTS');
    $this->assertText('2 errors found. 3 warnings found.');
    $this->assertText('2 errors found. ' . $this->getDrupalCoreMajorVersion() < 9 ? '3' : '4' . ' warnings found.');
    $this->assertText('Syntax error, unexpected T_STRING on line 3');

    // Run partial export of multiple projects.
@@ -111,7 +110,7 @@ class UpgradeStatusUiTest extends UpgradeStatusTestBase {
      $this->assertText('Upgrade status test error');
      $this->assertNoText('Upgrade status test root module');
      $this->assertNoText('Upgrade status test contrib 9 compatbile');
      $this->assertText('2 errors found. 3 warnings found.');
      $this->assertText('2 errors found. ' . $this->getDrupalCoreMajorVersion() < 9 ? '3' : '4' . ' warnings found.');
      $this->assertText('Syntax error, unexpected T_STRING on line 3');
    }
  }
Loading