ai_upgrade_assistant-0.2.0-alpha2/src/Service/NodeVisitor/HookVisitor.php

src/Service/NodeVisitor/HookVisitor.php
<?php

namespace Drupal\ai_upgrade_assistant\Service\NodeVisitor;

use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;

/**
 * Node visitor that detects hook implementations.
 */
class HookVisitor extends NodeVisitorAbstract {

  /**
   * List of findings.
   *
   * @var array
   */
  protected $findings = [];

  /**
   * The module name.
   *
   * @var string
   */
  protected $moduleName;

  /**
   * List of deprecated hooks and their replacements.
   *
   * @var array
   */
  protected $deprecatedHooks = [
    // Entity hooks
    'hook_entity_load' => [
      'replacement' => 'hook_ENTITY_TYPE_load',
      'version' => '8.7.0',
      'critical' => true,
    ],
    'hook_entity_presave' => [
      'replacement' => 'hook_ENTITY_TYPE_presave',
      'version' => '8.7.0',
      'critical' => true,
    ],
    'hook_entity_insert' => [
      'replacement' => 'hook_ENTITY_TYPE_insert',
      'version' => '8.7.0',
      'critical' => true,
    ],
    'hook_entity_update' => [
      'replacement' => 'hook_ENTITY_TYPE_update',
      'version' => '8.7.0',
      'critical' => true,
    ],
    'hook_entity_delete' => [
      'replacement' => 'hook_ENTITY_TYPE_delete',
      'version' => '8.7.0',
      'critical' => true,
    ],
    // File hooks
    'hook_file_download' => [
      'replacement' => 'hook_file_download_access',
      'version' => '10.0.0',
      'critical' => false,
    ],
    // Theme hooks
    'hook_theme_registry_alter' => [
      'replacement' => 'hook_theme_registry_info_alter',
      'version' => '10.0.0',
      'critical' => false,
    ],
    // Token hooks
    'hook_tokens' => [
      'replacement' => 'hook_token_info and hook_tokens_alter',
      'version' => '10.0.0',
      'critical' => false,
    ],
    // Field hooks
    'hook_field_widget_form_alter' => [
      'replacement' => 'hook_field_widget_complete_form_alter',
      'version' => '10.0.0',
      'critical' => false,
    ],
    // Views hooks
    'hook_views_pre_render' => [
      'replacement' => 'hook_views_pre_build',
      'version' => '10.0.0',
      'critical' => false,
    ],
    // Form hooks
    'hook_form_system_theme_settings_alter' => [
      'replacement' => 'hook_form_system_theme_settings_alter',
      'version' => '10.0.0',
      'critical' => false,
    ],
    // Block hooks
    'hook_block_view_alter' => [
      'replacement' => 'hook_block_build_alter',
      'version' => '10.0.0',
      'critical' => false,
    ],
  ];

  /**
   * List of hooks that require special attention in Drupal 11.
   *
   * @var array
   */
  protected $drupal11Hooks = [
    'hook_update_N' => [
      'attention' => 'Ensure numeric suffix follows Drupal 11 version numbering',
      'example' => 'mymodule_update_110001()',
    ],
    'hook_install' => [
      'attention' => 'Check for deprecated install functions',
      'example' => 'Use \Drupal::configFactory() instead of update_variable_set()',
    ],
    'hook_uninstall' => [
      'attention' => 'Check for deprecated uninstall functions',
      'example' => 'Use State API instead of variable_del()',
    ],
    'hook_requirements' => [
      'attention' => 'Update version requirements for Drupal 11',
      'example' => "return ['php' => ['value' => PHP_VERSION, 'minimum' => '8.1.0']]",
    ],
  ];

  /**
   * Constructs a new HookVisitor.
   *
   * @param string $module_name
   *   The module name.
   */
  public function __construct($module_name) {
    $this->moduleName = $module_name;
  }

  /**
   * {@inheritdoc}
   */
  public function enterNode(Node $node) {
    if ($node instanceof Node\Stmt\Function_) {
      $name = $node->name->toString();
      
      // Check if this is a hook implementation
      if (strpos($name, $this->moduleName . '_') === 0) {
        $hook_name = str_replace($this->moduleName . '_', 'hook_', $name);
        
        $finding = [
          'type' => 'hook',
          'name' => $name,
          'hook' => $hook_name,
          'line' => $node->getLine(),
          'file' => $node->getAttribute('file'),
          'params' => array_map(function($param) {
            return $param->var->name;
          }, $node->params),
        ];

        // Check if this is a deprecated hook
        if (isset($this->deprecatedHooks[$hook_name])) {
          $finding['deprecated'] = true;
          $finding['replacement'] = $this->deprecatedHooks[$hook_name]['replacement'];
          $finding['version'] = $this->deprecatedHooks[$hook_name]['version'];
          $finding['critical'] = $this->deprecatedHooks[$hook_name]['critical'];
        }

        // Check if this hook needs special attention in Drupal 11
        if (isset($this->drupal11Hooks[$hook_name])) {
          $finding['drupal11_attention'] = true;
          $finding['attention_note'] = $this->drupal11Hooks[$hook_name]['attention'];
          $finding['example'] = $this->drupal11Hooks[$hook_name]['example'];
        }

        // Check for update hooks specifically
        if (preg_match('/^' . preg_quote($this->moduleName) . '_update_\d+$/', $name)) {
          $finding['is_update_hook'] = true;
          $number = substr($name, strlen($this->moduleName) + 7);
          if (strlen($number) !== 6 || substr($number, 0, 2) !== '11') {
            $finding['update_hook_warning'] = 'Update hook number should be 6 digits starting with 11 for Drupal 11 (e.g., 110001)';
          }
        }

        $this->findings[] = $finding;
      }
    }
  }

  /**
   * Gets the findings.
   *
   * @return array
   *   Array of findings.
   */
  public function getFindings() {
    return $this->findings;
  }

  /**
   * Resets the findings.
   */
  public function reset() {
    $this->findings = [];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc