ai_upgrade_assistant-0.2.0-alpha2/src/Service/BatchAnalyzer.php

src/Service/BatchAnalyzer.php
<?php

namespace Drupal\ai_upgrade_assistant\Service;

use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Queue\QueueFactory;

/**
 * Service for handling batch processing of module analysis.
 */
class BatchAnalyzer {
  use StringTranslationTrait;
  use DependencySerializationTrait;

  /**
   * The project analyzer service.
   *
   * @var \Drupal\ai_upgrade_assistant\Service\ProjectAnalyzer
   */
  protected $projectAnalyzer;

  /**
   * The state service.
   *
   * @var \Drupal\Core\State\StateInterface
   */
  protected $state;

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * The analysis tracker service.
   *
   * @var \Drupal\ai_upgrade_assistant\Service\AnalysisTracker
   */
  protected $analysisTracker;

  /**
   * The patch searcher service.
   *
   * @var \Drupal\ai_upgrade_assistant\Service\PatchSearcher
   */
  protected $patchSearcher;

  /**
   * The cache service.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cache;

  /**
   * The queue factory service.
   *
   * @var \Drupal\Core\Queue\QueueFactory
   */
  protected $queueFactory;

  /**
   * The batch size for processing.
   *
   * @var int
   */
  protected $batchSize = 5;

  /**
   * Constructs a new BatchAnalyzer object.
   *
   * @param \Drupal\ai_upgrade_assistant\Service\ProjectAnalyzer $project_analyzer
   *   The project analyzer service.
   * @param \Drupal\Core\State\StateInterface $state
   *   The state service.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   * @param \Drupal\ai_upgrade_assistant\Service\AnalysisTracker $analysis_tracker
   *   The analysis tracker service.
   * @param \Drupal\ai_upgrade_assistant\Service\PatchSearcher $patch_searcher
   *   The patch searcher service.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache service.
   * @param \Drupal\Core\Queue\QueueFactory $queue_factory
   *   The queue factory service.
   */
  public function __construct(
    ProjectAnalyzer $project_analyzer,
    StateInterface $state,
    ModuleHandlerInterface $module_handler,
    AnalysisTracker $analysis_tracker,
    PatchSearcher $patch_searcher,
    CacheBackendInterface $cache,
    QueueFactory $queue_factory
  ) {
    $this->projectAnalyzer = $project_analyzer;
    $this->state = $state;
    $this->moduleHandler = $module_handler;
    $this->analysisTracker = $analysis_tracker;
    $this->patchSearcher = $patch_searcher;
    $this->cache = $cache;
    $this->queueFactory = $queue_factory;
  }

  /**
   * Creates a batch for analyzing modules.
   *
   * @param array $modules
   *   Array of module names to analyze.
   *
   * @return array
   *   Batch definition array.
   */
  public function createBatch(array $modules) {
    // Clear previous analysis results.
    $this->state->delete('ai_upgrade_assistant.last_analysis_results');
    $this->cache->deleteMultiple(['ai_upgrade_assistant_analysis']);

    // Group modules into chunks for better performance
    $chunks = array_chunk($modules, $this->batchSize);
    $operations = [];

    foreach ($chunks as $chunk) {
      $operations[] = [
        [static::class, 'analyzeBatchChunk'],
        [$chunk],
      ];
    }

    return [
      'title' => $this->t('Analyzing modules'),
      'operations' => $operations,
      'finished' => [static::class, 'batchFinished'],
      'file' => drupal_get_path('module', 'ai_upgrade_assistant') . '/src/Service/BatchAnalyzer.php',
      'progressive' => TRUE,
      'init_message' => $this->t('Starting module analysis...'),
      'progress_message' => $this->t('Analyzed @current out of @total module groups.'),
      'error_message' => $this->t('An error occurred during the analysis.'),
    ];
  }

  /**
   * Process a batch chunk of modules.
   *
   * This is a static method to avoid serialization issues.
   *
   * @param array $modules
   *   Array of module names in this chunk.
   * @param array $context
   *   Batch context array.
   */
  public static function analyzeBatchChunk(array $modules, array &$context) {
    // Initialize progress if not set
    if (!isset($context['sandbox']['progress'])) {
      $context['sandbox']['progress'] = 0;
      $context['sandbox']['current_module'] = 0;
      $context['sandbox']['max'] = count($modules);
      $context['results']['analyzed'] = [];
      $context['results']['errors'] = [];
    }

    foreach ($modules as $module) {
      try {
        // Get required services
        $module_handler = \Drupal::service('module_handler');
        $project_analyzer = \Drupal::service('ai_upgrade_assistant.project_analyzer');
        $analysis_tracker = \Drupal::service('ai_upgrade_assistant.analysis_tracker');
        $patch_searcher = \Drupal::service('ai_upgrade_assistant.patch_searcher');
        $state = \Drupal::service('state');

        // Skip if module doesn't exist
        if (!$module_handler->moduleExists($module)) {
          $context['results']['errors'][$module] = t('Module @name does not exist.', [
            '@name' => $module,
          ]);
          continue;
        }

        // Get module info
        $module_info = $project_analyzer->getModuleInfo($module);
        $module_path = $module_info['path'];

        // Initialize analysis
        $analysis_tracker->initializeAnalysis($module);

        // Store module info
        $context['results']['module_info'][$module] = $module_info;

        // Analyze code
        $code_analysis = $project_analyzer->analyzeCode($module, $module_path);
        $analysis_tracker->updateAnalysis($module, $code_analysis, 'code_analysis');
        $context['results']['code_analysis'][$module] = $code_analysis;

        // Analyze dependencies
        $dependencies = $project_analyzer->analyzeDependencies($module);
        $analysis_tracker->updateAnalysis($module, $dependencies, 'dependencies');
        $context['results']['dependencies'][$module] = $dependencies;

        // Search patches
        $patches = $patch_searcher->findPatches($module);
        $analysis_tracker->updateAnalysis($module, $patches, 'patches');
        $context['results']['patches'][$module] = $patches;

        // Analyze security
        $security = $project_analyzer->analyzeSecurityIssues($module);
        $analysis_tracker->updateAnalysis($module, $security, 'security_analysis');
        $context['results']['security_analysis'][$module] = $security;

        // Update progress
        $context['sandbox']['progress']++;
        $context['message'] = t('Analyzed module: @name', [
          '@name' => $module,
        ]);
        $context['results']['analyzed'][] = $module;
      }
      catch (\Exception $e) {
        $context['results']['errors'][$module] = $e->getMessage();
        \Drupal::logger('ai_upgrade_assistant')->error('Error analyzing module @module: @error', [
          '@module' => $module,
          '@error' => $e->getMessage(),
        ]);
      }
    }
  }

  /**
   * Batch finished callback.
   *
   * This is a static method to avoid serialization issues.
   *
   * @param bool $success
   *   Whether the batch succeeded.
   * @param array $results
   *   The batch results.
   * @param array $operations
   *   The operations that remained unprocessed.
   */
  public static function batchFinished($success, array $results, array $operations) {
    if ($success) {
      if (!empty($results['errors'])) {
        foreach ($results['errors'] as $module => $error) {
          \Drupal::messenger()->addError(
            t('Error analyzing @module: @error', [
              '@module' => $module,
              '@error' => $error,
            ])
          );
        }
      }

      $count = count($results['analyzed']);
      \Drupal::messenger()->addStatus(
        t('Successfully analyzed @count modules.', [
          '@count' => $count,
        ])
      );

      // Cache the combined results
      \Drupal::service('cache.default')->set('ai_upgrade_assistant.analysis_results', $results);
    }
    else {
      \Drupal::messenger()->addError(t('An error occurred during module analysis.'));
    }
  }

  /**
   * Sets the batch size.
   *
   * @param int $size
   *   The batch size.
   */
  public function setBatchSize($size) {
    $this->batchSize = max(1, (int) $size);
  }

  /**
   * {@inheritdoc}
   */
  public function __sleep() {
    $vars = get_object_vars($this);
    unset($vars['projectAnalyzer'], $vars['analysisTracker'], $vars['patchSearcher'], $vars['state'], $vars['moduleHandler'], $vars['cache'], $vars['queueFactory']);
    return array_keys($vars);
  }

  /**
   * {@inheritdoc}
   */
  public function __wakeup() {
    $this->projectAnalyzer = \Drupal::service('ai_upgrade_assistant.project_analyzer');
    $this->analysisTracker = \Drupal::service('ai_upgrade_assistant.analysis_tracker');
    $this->patchSearcher = \Drupal::service('ai_upgrade_assistant.patch_searcher');
    $this->state = \Drupal::state();
    $this->moduleHandler = \Drupal::moduleHandler();
    $this->cache = \Drupal::cache();
    $this->queueFactory = \Drupal::service('queue');
  }
}

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

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