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

src/Service/AnalysisTracker.php
<?php

namespace Drupal\ai_upgrade_assistant\Service;

use Drupal\Core\State\StateInterface;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Queue\QueueFactory;
use Drupal\Core\Queue\QueueInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\ai_upgrade_assistant\Service\HuggingFaceService;

/**
 * Service for tracking module analysis history and status.
 */
class AnalysisTracker {
  use DependencySerializationTrait;

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

  /**
   * The logger factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $loggerFactory;

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

  /**
   * The queue service.
   *
   * @var \Drupal\Core\Queue\QueueInterface
   */
  protected $queue;

  /**
   * The HuggingFace service.
   *
   * @var \Drupal\ai_upgrade_assistant\Service\HuggingFaceService
   */
  protected $huggingFace;

  /**
   * Constructs a new AnalysisTracker.
   *
   * @param \Drupal\Core\State\StateInterface $state
   *   The state service.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
   *   The logger factory service.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache backend.
   * @param \Drupal\Core\Queue\QueueFactory $queue_factory
   *   The queue factory service.
   * @param \Drupal\ai_upgrade_assistant\Service\HuggingFaceService $hugging_face
   *   The HuggingFace service.
   */
  public function __construct(
    StateInterface $state,
    LoggerChannelFactoryInterface $logger_factory,
    CacheBackendInterface $cache,
    QueueFactory $queue_factory,
    HuggingFaceService $hugging_face
  ) {
    $this->state = $state;
    $this->loggerFactory = $logger_factory;
    $this->cache = $cache;
    $this->queue = $queue_factory->get('ai_upgrade_assistant_analysis');
    $this->huggingFace = $hugging_face;
  }

  /**
   * Initializes a new analysis for a module.
   *
   * @param string $module
   *   The module being analyzed.
   * @param array $context
   *   Additional context about the analysis.
   *
   * @return array
   *   The initialized analysis record.
   */
  public function initializeAnalysis($module, array $context = []) {
    $analysis = [
      'module' => $module,
      'start_time' => time(),
      'status' => 'initialized',
      'context' => $context,
      'results' => [
        'code_analysis' => [],
        'dependency_analysis' => [],
        'patches' => [],
        'security_analysis' => [],
      ],
    ];

    // Clear any previous in-progress analysis
    $this->clearInProgressAnalysis($module);

    // Save the new analysis
    $history = $this->getAnalysisHistory($module);
    array_unshift($history, $analysis);
    $this->saveAnalysisHistory($module, $history);

    return $analysis;
  }

  /**
   * Clears any in-progress analysis for a module.
   *
   * @param string $module
   *   The module name.
   */
  protected function clearInProgressAnalysis($module) {
    $history = $this->getAnalysisHistory($module);
    
    // Remove any in-progress analysis
    foreach ($history as $key => $analysis) {
      if (isset($analysis['status']) && $analysis['status'] === 'in_progress') {
        unset($history[$key]);
      }
    }
    
    $this->saveAnalysisHistory($module, array_values($history));
  }

  /**
   * Updates an analysis record with new data.
   *
   * @param string $module
   *   The module being analyzed.
   * @param array $data
   *   The data to update.
   * @param string $section
   *   The section to update (e.g., 'code_analysis', 'dependency_analysis').
   */
  public function updateAnalysis($module, array $data, $section) {
    $history = $this->getAnalysisHistory($module);
    
    if (!empty($history)) {
      if (!isset($history[0]['results'][$section])) {
        $history[0]['results'][$section] = [];
      }
      $history[0]['results'][$section] = array_merge($history[0]['results'][$section], $data);
      $this->saveAnalysisHistory($module, $history);
    }
  }

  /**
   * Records the start of an analysis.
   *
   * @param string $module
   *   The module being analyzed.
   * @param string $type
   *   The type of analysis (e.g., 'drupal11', 'minor_update').
   * @param array $context
   *   Additional context about the analysis.
   */
  public function startAnalysis($module, $type, array $context = []) {
    $history = $this->getAnalysisHistory($module);
    
    $analysis = [
      'type' => $type,
      'start_time' => time(),
      'status' => 'in_progress',
      'context' => $context,
    ];
    
    array_unshift($history, $analysis);
    $this->saveAnalysisHistory($module, $history);
  }

  /**
   * Records the completion of an analysis.
   *
   * @param string $module
   *   The module being analyzed.
   * @param array $results
   *   The analysis results.
   * @param bool $success
   *   Whether the analysis was successful.
   */
  public function completeAnalysis($module, array $results, $success = TRUE) {
    $history = $this->getAnalysisHistory($module);
    
    if (!empty($history)) {
      $history[0]['end_time'] = time();
      $history[0]['status'] = $success ? 'completed' : 'failed';
      $history[0]['results'] = $results;
      
      $this->saveAnalysisHistory($module, $history);
    }
  }

  /**
   * Gets the analysis history for a module.
   *
   * @param string $module
   *   The module name.
   *
   * @return array
   *   The analysis history.
   */
  public function getAnalysisHistory($module) {
    $key = "ai_upgrade_assistant.analysis_history.$module";
    return $this->state->get($key, []);
  }

  /**
   * Saves the analysis history for a module.
   *
   * @param string $module
   *   The module name.
   * @param array $history
   *   The analysis history to save.
   */
  protected function saveAnalysisHistory($module, array $history) {
    $key = "ai_upgrade_assistant.analysis_history.$module";
    
    // Keep only the last 10 analyses
    $history = array_slice($history, 0, 10);
    
    $this->state->set($key, $history);
  }

  /**
   * Gets the last analysis time for a module.
   *
   * @param string $module
   *   The module name.
   * @param string $type
   *   Optional analysis type to filter by.
   *
   * @return int|null
   *   The timestamp of the last analysis, or NULL if never analyzed.
   */
  public function getLastAnalysisTime($module, $type = NULL) {
    $history = $this->getAnalysisHistory($module);
    
    if (empty($history)) {
      return NULL;
    }

    if ($type) {
      foreach ($history as $analysis) {
        if ($analysis['type'] === $type && $analysis['status'] === 'completed') {
          return $analysis['end_time'];
        }
      }
      return NULL;
    }

    return $history[0]['end_time'] ?? NULL;
  }

  /**
   * Checks if a module needs reanalysis.
   *
   * @param string $module
   *   The module name.
   * @param string $type
   *   The type of analysis.
   *
   * @return bool
   *   TRUE if the module should be reanalyzed.
   */
  public function needsReanalysis($module, $type) {
    $config = \Drupal::config('ai_upgrade_assistant.settings');
    $recheck_interval = $config->get('recheck_interval') ?? 604800; // Default 1 week
    
    $last_analysis = $this->getLastAnalysisTime($module, $type);
    if (!$last_analysis) {
      return TRUE;
    }

    return (time() - $last_analysis) > $recheck_interval;
  }

  /**
   * Gets analysis statistics.
   *
   * @return array
   *   Statistics about analyses performed.
   */
  public function getAnalysisStats() {
    $modules = \Drupal::service('module_handler')->getModuleList();
    $stats = [
      'total_analyzed' => 0,
      'needs_reanalysis' => 0,
      'never_analyzed' => 0,
      'last_analysis' => NULL,
      'by_type' => [],
    ];

    foreach ($modules as $module => $info) {
      $history = $this->getAnalysisHistory($module);
      
      if (!empty($history)) {
        $stats['total_analyzed']++;
        
        if ($this->needsReanalysis($module, $history[0]['type'])) {
          $stats['needs_reanalysis']++;
        }

        foreach ($history as $analysis) {
          $type = $analysis['type'];
          if (!isset($stats['by_type'][$type])) {
            $stats['by_type'][$type] = 0;
          }
          $stats['by_type'][$type]++;
        }

        // Track most recent analysis
        $end_time = $history[0]['end_time'] ?? NULL;
        if ($end_time && (!$stats['last_analysis'] || $end_time > $stats['last_analysis'])) {
          $stats['last_analysis'] = $end_time;
        }
      }
      else {
        $stats['never_analyzed']++;
      }
    }

    return $stats;
  }

  /**
   * Saves analysis results.
   *
   * @param array $results
   *   Analysis results to save. Should contain:
   *   - timestamp: Unix timestamp when analysis completed
   *   - total_files: Total number of files analyzed
   *   - files_processed: Number of files successfully processed
   *   - results: Array of analysis results per file
   *   - errors: Array of errors encountered during analysis
   */
  public function saveResults(array $results) {
    // Validate required fields
    $required_fields = ['timestamp', 'total_files', 'files_processed', 'results', 'errors'];
    foreach ($required_fields as $field) {
      if (!isset($results[$field])) {
        $this->loggerFactory->get('ai_upgrade_assistant')->error(
          'Missing required field @field in analysis results',
          ['@field' => $field]
        );
        return;
      }
    }

    // Add metadata
    $results['metadata'] = [
      'version' => '1.0',
      'generated' => date('c', $results['timestamp']),
      'duration' => isset($results['start_time']) ? ($results['timestamp'] - $results['start_time']) : 0,
    ];

    // Save to state
    $this->state->set('ai_upgrade_assistant.analysis_results', $results);
    $this->state->set('ai_upgrade_assistant.last_analysis', $results['timestamp']);

    // Log success
    $this->loggerFactory->get('ai_upgrade_assistant')->info(
      'Analysis results saved. Processed @processed of @total files with @error_count errors.',
      [
        '@processed' => $results['files_processed'],
        '@total' => $results['total_files'],
        '@error_count' => count($results['errors']),
      ]
    );
  }

  /**
   * Gets saved analysis results.
   *
   * @return array
   *   Saved analysis results.
   */
  public function getResults() {
    return $this->state->get('ai_upgrade_assistant.analysis_results', []);
  }

  /**
   * Gets the timestamp of the last analysis.
   *
   * @return int|null
   *   Unix timestamp of the last analysis, or NULL if no analysis has been run.
   */
  public function getLastAnalysisTimeGlobal() {
    return $this->state->get('ai_upgrade_assistant.last_analysis');
  }

  /**
   * Clears saved analysis results.
   */
  public function clearResults() {
    $this->state->delete('ai_upgrade_assistant.analysis_results');
    $this->state->delete('ai_upgrade_assistant.last_analysis');
    $this->loggerFactory->get('ai_upgrade_assistant')->info('Analysis results cleared.');
  }
}

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

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