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

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

namespace Drupal\ai_upgrade_assistant\Service\NodeVisitor;

use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;

/**
 * Node visitor that analyzes service usage and dependency injection.
 */
class ServiceVisitor extends NodeVisitorAbstract {

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

  /**
   * List of deprecated services and their replacements.
   *
   * @var array
   */
  protected $deprecatedServices = [
    'entity.manager' => [
      'replacement' => 'entity_type.manager',
      'version' => '8.0.0',
      'critical' => true,
    ],
    'plugin.manager.entity' => [
      'replacement' => 'entity_type.manager',
      'version' => '8.0.0',
      'critical' => true,
    ],
    'string_translation' => [
      'replacement' => 'string_translation',
      'version' => '8.0.0',
      'critical' => false,
      'note' => 'Use StringTranslationTrait instead',
    ],
    'url_generator' => [
      'replacement' => 'url_generator.non_bubbling',
      'version' => '9.0.0',
      'critical' => false,
    ],
    'path.alias_manager' => [
      'replacement' => 'path_alias.manager',
      'version' => '8.8.0',
      'critical' => true,
    ],
    'database' => [
      'replacement' => 'database',
      'version' => '10.0.0',
      'critical' => false,
      'note' => 'Use dependency injection instead of \Drupal::database()',
    ],
  ];

  /**
   * List of services requiring special attention in Drupal 11.
   *
   * @var array
   */
  protected $drupal11Services = [
    'entity_type.manager' => [
      'changes' => [
        'New methods for revision handling',
        'Enhanced bundle support',
      ],
      'example' => 'Use getRevisionableStorages() for revision-enabled entities',
    ],
    'database' => [
      'changes' => [
        'New connection handling',
        'Transaction improvements',
      ],
      'example' => 'Use managed transactions with savepoints',
    ],
  ];

  /**
   * {@inheritdoc}
   */
  public function enterNode(Node $node) {
    // Check for \Drupal::service() calls
    if ($node instanceof Node\Expr\StaticCall) {
      if ($node->class instanceof Node\Name && $node->class->toString() === 'Drupal' && $node->name->toString() === 'service') {
        if (isset($node->args[0]) && $node->args[0]->value instanceof Node\Scalar\String_) {
          $service_name = $node->args[0]->value->value;
          $finding = [
            'type' => 'static_service',
            'service' => $service_name,
            'line' => $node->getLine(),
            'file' => $node->getAttribute('file'),
          ];

          if (isset($this->deprecatedServices[$service_name])) {
            $finding['deprecated'] = true;
            $finding['replacement'] = $this->deprecatedServices[$service_name]['replacement'];
            $finding['version'] = $this->deprecatedServices[$service_name]['version'];
            $finding['critical'] = $this->deprecatedServices[$service_name]['critical'];
            if (isset($this->deprecatedServices[$service_name]['note'])) {
              $finding['note'] = $this->deprecatedServices[$service_name]['note'];
            }
          }

          if (isset($this->drupal11Services[$service_name])) {
            $finding['drupal11_changes'] = $this->drupal11Services[$service_name];
          }

          $this->findings[] = $finding;
        }
      }
    }
    // Check for service container injection
    elseif ($node instanceof Node\Stmt\Class_) {
      $constructor = null;
      $container_inject = false;
      $injected_services = [];

      // Check for ContainerInjectionInterface
      foreach ($node->implements as $interface) {
        if ($interface->toString() === 'ContainerInjectionInterface') {
          $container_inject = true;
          break;
        }
      }

      // Find constructor and create method
      foreach ($node->stmts as $stmt) {
        if ($stmt instanceof Node\Stmt\ClassMethod) {
          if ($stmt->name->toString() === '__construct') {
            $constructor = $stmt;
          }
          elseif ($stmt->isStatic() && $stmt->name->toString() === 'create') {
            foreach ($stmt->stmts as $create_stmt) {
              if ($create_stmt instanceof Node\Stmt\Return_) {
                if ($create_stmt->expr instanceof Node\Expr\New_) {
                  foreach ($create_stmt->expr->args as $arg) {
                    if ($arg->value instanceof Node\Expr\MethodCall) {
                      if ($arg->value->var instanceof Node\Expr\Variable && $arg->value->var->name === 'container' && $arg->value->name->toString() === 'get') {
                        if (isset($arg->value->args[0]) && $arg->value->args[0]->value instanceof Node\Scalar\String_) {
                          $service_name = $arg->value->args[0]->value->value;
                          $injected_services[] = $service_name;
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }

      if ($constructor || $container_inject || !empty($injected_services)) {
        $finding = [
          'type' => 'service_injection',
          'class' => $node->name->toString(),
          'line' => $node->getLine(),
          'file' => $node->getAttribute('file'),
          'has_constructor' => $constructor !== null,
          'container_inject' => $container_inject,
          'injected_services' => $injected_services,
        ];

        // Check for deprecated injected services
        foreach ($injected_services as $service_name) {
          if (isset($this->deprecatedServices[$service_name])) {
            if (!isset($finding['deprecated_services'])) {
              $finding['deprecated_services'] = [];
            }
            $finding['deprecated_services'][] = [
              'service' => $service_name,
              'replacement' => $this->deprecatedServices[$service_name]['replacement'],
              'version' => $this->deprecatedServices[$service_name]['version'],
              'critical' => $this->deprecatedServices[$service_name]['critical'],
            ];
          }
        }

        // Check for D11 service changes
        foreach ($injected_services as $service_name) {
          if (isset($this->drupal11Services[$service_name])) {
            if (!isset($finding['drupal11_services'])) {
              $finding['drupal11_services'] = [];
            }
            $finding['drupal11_services'][] = [
              'service' => $service_name,
              'changes' => $this->drupal11Services[$service_name],
            ];
          }
        }

        $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