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

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

namespace Drupal\ai_upgrade_assistant\Service\NodeVisitor;

use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\MethodCall;

/**
 * Analyzes Drupal dependencies and service usage patterns.
 */
class DrupalDependencyVisitor extends NodeVisitorAbstract {

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

  /**
   * Service dependencies found in constructor injection.
   *
   * @var array
   */
  protected $serviceDependencies = [];

  /**
   * Static service calls found.
   *
   * @var array
   */
  protected $staticServiceCalls = [];

  /**
   * {@inheritdoc}
   */
  public function enterNode(Node $node) {
    // Check for constructor injection
    if ($node instanceof Node\Stmt\ClassMethod && $node->name->toString() === '__construct') {
      foreach ($node->params as $param) {
        if ($param->type instanceof Node\Name) {
          $typeName = $param->type->toString();
          if (strpos($typeName, 'Drupal\\') === 0) {
            $this->serviceDependencies[] = [
              'type' => 'constructor_injection',
              'service' => $typeName,
              'parameter' => $param->var->name,
              'line' => $node->getLine(),
            ];
          }
        }
      }
    }

    // Check for \Drupal::service() calls
    if ($node instanceof StaticCall) {
      if ($node->class instanceof Node\Name && $node->class->toString() === 'Drupal') {
        if ($node->name->toString() === 'service') {
          $this->staticServiceCalls[] = [
            'type' => 'static_service_call',
            'service' => $this->getServiceName($node),
            'line' => $node->getLine(),
          ];
        }
      }
    }

    // Check for module dependencies in hook_requirements
    if ($node instanceof FuncCall && $node->name instanceof Node\Name) {
      $funcName = $node->name->toString();
      if ($funcName === 'hook_requirements') {
        $this->analyzeRequirements($node);
      }
    }

    // Check for service container calls
    if ($node instanceof MethodCall) {
      if ($node->var instanceof Node\Expr\PropertyFetch) {
        $prop = $node->var->name->toString();
        if ($prop === 'container' && $node->name->toString() === 'get') {
          $this->staticServiceCalls[] = [
            'type' => 'container_get',
            'service' => $this->getServiceName($node),
            'line' => $node->getLine(),
          ];
        }
      }
    }
  }

  /**
   * Analyzes hook_requirements for module dependencies.
   *
   * @param \PhpParser\Node\Expr\FuncCall $node
   *   The function call node.
   */
  protected function analyzeRequirements(FuncCall $node) {
    // Look for module_exists, module_load_include calls
    $visitor = $this;
    $this->findings['requirements'] = [];
    
    $nodeTraverser = new \PhpParser\NodeTraverser();
    $nodeTraverser->addVisitor(new class($visitor->findings['requirements']) extends NodeVisitorAbstract {
      protected $requirements;
      
      public function __construct(&$requirements) {
        $this->requirements = &$requirements;
      }
      
      public function enterNode(Node $node) {
        if ($node instanceof FuncCall && $node->name instanceof Node\Name) {
          $name = $node->name->toString();
          if (in_array($name, ['module_exists', 'module_load_include'])) {
            if (isset($node->args[0])) {
              $this->requirements[] = [
                'type' => 'module_dependency',
                'function' => $name,
                'module' => $this->getArgValue($node->args[0]->value),
                'line' => $node->getLine(),
              ];
            }
          }
        }
      }

      protected function getArgValue($value) {
        if ($value instanceof Node\Scalar\String_) {
          return $value->value;
        }
        return null;
      }
    });
    
    if (isset($node->stmts)) {
      $nodeTraverser->traverse($node->stmts);
    }
  }

  /**
   * Gets the service name from a service call node.
   *
   * @param \PhpParser\Node $node
   *   The node containing the service call.
   *
   * @return string|null
   *   The service name or null if not found.
   */
  protected function getServiceName(Node $node) {
    if (isset($node->args[0])) {
      $arg = $node->args[0]->value;
      if ($arg instanceof Node\Scalar\String_) {
        return $arg->value;
      }
    }
    return null;
  }

  /**
   * Gets all findings.
   *
   * @return array
   *   Array of findings.
   */
  public function getFindings() {
    return [
      'service_dependencies' => $this->serviceDependencies,
      'static_service_calls' => $this->staticServiceCalls,
      'requirements' => $this->findings['requirements'] ?? [],
    ];
  }

  /**
   * Resets the visitor's state.
   */
  public function reset() {
    $this->findings = [];
    $this->serviceDependencies = [];
    $this->staticServiceCalls = [];
  }
}

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

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