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

src/Service/CommunityLearningService.php
<?php

namespace Drupal\ai_upgrade_assistant\Service;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Queue\QueueFactory;
use GuzzleHttp\ClientInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;

/**
 * Service for community learning and pattern sharing.
 */
class CommunityLearningService {
  use DependencySerializationTrait;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * 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 factory.
   *
   * @var \Drupal\Core\Queue\QueueFactory
   */
  protected $queueFactory;

  /**
   * The HTTP client.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $httpClient;

  /**
   * Constructs a new CommunityLearningService object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   The current user.
   * @param \Drupal\Core\State\StateInterface $state
   *   The state service.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
   *   The logger factory.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache backend.
   * @param \Drupal\Core\Queue\QueueFactory $queue_factory
   *   The queue factory.
   * @param \GuzzleHttp\ClientInterface $http_client
   *   The HTTP client.
   */
  public function __construct(
    ConfigFactoryInterface $config_factory,
    Connection $database,
    EntityTypeManagerInterface $entity_type_manager,
    AccountProxyInterface $current_user,
    StateInterface $state,
    LoggerChannelFactoryInterface $logger_factory,
    CacheBackendInterface $cache,
    QueueFactory $queue_factory,
    ClientInterface $http_client
  ) {
    $this->configFactory = $config_factory;
    $this->database = $database;
    $this->entityTypeManager = $entity_type_manager;
    $this->currentUser = $current_user;
    $this->state = $state;
    $this->loggerFactory = $logger_factory;
    $this->cache = $cache;
    $this->queueFactory = $queue_factory;
    $this->httpClient = $http_client;
  }

  /**
   * Creates a forum topic.
   *
   * @param string $title
   *   The topic title.
   * @param string $body
   *   The topic body.
   * @param array $tags
   *   Optional tags for the topic.
   *
   * @return int|bool
   *   The topic ID if successful, FALSE otherwise.
   */
  public function createForumTopic($title, $body, array $tags = []) {
    try {
      $fields = [
        'title' => $title,
        'body' => $body,
        'uid' => $this->currentUser->id(),
        'created' => time(),
        'changed' => time(),
      ];

      if (!empty($tags)) {
        $fields['tags'] = Json::encode($tags);
      }

      $id = $this->database->insert('ai_upgrade_assistant_forum_topics')
        ->fields($fields)
        ->execute();

      $this->loggerFactory->get('ai_upgrade_assistant')->info(
        'Forum topic created: @title',
        ['@title' => $title]
      );

      return $id;
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('ai_upgrade_assistant')->error(
        'Error creating forum topic: @error',
        ['@error' => $e->getMessage()]
      );
      return FALSE;
    }
  }

  /**
   * Gets forum topics with optional filtering.
   *
   * @param array $filters
   *   Filters to apply to the query.
   * @param int $limit
   *   Number of topics to return.
   * @param int $offset
   *   Offset for pagination.
   *
   * @return array
   *   Array of forum topics.
   */
  public function getForumTopics(array $filters = [], $limit = 10, $offset = 0) {
    try {
      $query = $this->database->select('ai_upgrade_assistant_forum_topics', 't')
        ->fields('t')
        ->orderBy('created', 'DESC')
        ->range($offset, $limit);

      if (!empty($filters['uid'])) {
        $query->condition('uid', $filters['uid']);
      }

      if (!empty($filters['tag'])) {
        $query->condition('tags', '%' . $filters['tag'] . '%', 'LIKE');
      }

      $result = $query->execute();
      $topics = [];

      foreach ($result as $record) {
        $topics[] = (array) $record;
      }

      return $topics;
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('ai_upgrade_assistant')->error(
        'Error fetching forum topics: @error',
        ['@error' => $e->getMessage()]
      );
      return [];
    }
  }

  /**
   * Gets shared upgrade patterns for a module.
   *
   * @param array $context
   *   The context array containing module information.
   *
   * @return array
   *   Array of shared patterns.
   */
  public function getSharedPatterns(array $context) {
    $cid = 'ai_upgrade_assistant:shared_patterns:' . md5(serialize($context));
    $cached = $this->cache->get($cid);

    if ($cached) {
      return $cached->data;
    }

    try {
      $query = $this->database->select('ai_upgrade_assistant_patterns', 'p')
        ->fields('p');

      if (!empty($context['task_type'])) {
        $query->condition('p.task_type', $context['task_type']);
      }

      if (!empty($context['project'])) {
        $query->condition('p.module_name', $context['project']);
      }

      $patterns = $query->execute()->fetchAll();

      $this->cache->set($cid, $patterns, time() + 3600);

      return $patterns;
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('ai_upgrade_assistant')->error(
        'Error fetching shared patterns: @error',
        ['@error' => $e->getMessage()]
      );
      return [];
    }
  }

  /**
   * Gets security advisories for a module.
   *
   * @param string $module
   *   The module name.
   *
   * @return array
   *   Array of security advisories.
   */
  public function getSecurityAdvisories($module) {
    $cid = 'ai_upgrade_assistant:security_advisories:' . $module;
    
    if ($cache = $this->cache->get($cid)) {
      return $cache->data;
    }

    try {
      // Fetch security advisories from Drupal.org
      $url = sprintf('https://www.drupal.org/api/sa?project=%s', $module);
      $response = $this->httpClient->get($url);
      $data = Json::decode($response->getBody());

      $advisories = [];
      if (!empty($data['list'])) {
        foreach ($data['list'] as $advisory) {
          $advisories[] = [
            'title' => $advisory['title'],
            'link' => $advisory['url'],
            'severity' => $advisory['field_security_advisory_severity'] ?? 'Unknown',
            'date' => $advisory['created'],
            'status' => $advisory['field_sa_status'] ?? 'Unknown',
          ];
        }
      }

      // Cache for 1 hour
      $this->cache->set($cid, $advisories, time() + 3600);

      return $advisories;
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('ai_upgrade_assistant')->error(
        'Error fetching security advisories for @module: @error',
        [
          '@module' => $module,
          '@error' => $e->getMessage(),
        ]
      );
      return [];
    }
  }

  /**
   * Gets statistics about the community patterns.
   *
   * @return array
   *   Array of statistics.
   */
  public function getDatasetStats() {
    $cid = 'ai_upgrade_assistant:community_stats';
    
    if ($cache = $this->cache->get($cid)) {
      return $cache->data;
    }

    try {
      $stats = [
        'total_patterns' => $this->database->select('ai_upgrade_assistant_patterns', 'p')
          ->countQuery()
          ->execute()
          ->fetchField(),
        'total_topics' => $this->database->select('ai_upgrade_assistant_forum_topics', 't')
          ->countQuery()
          ->execute()
          ->fetchField(),
        'unique_contributors' => $this->database->select('ai_upgrade_assistant_patterns', 'p')
          ->fields('p', ['uid'])
          ->distinct()
          ->countQuery()
          ->execute()
          ->fetchField(),
        'last_update' => $this->database->select('ai_upgrade_assistant_patterns', 'p')
          ->fields('p', ['created'])
          ->orderBy('created', 'DESC')
          ->range(0, 1)
          ->execute()
          ->fetchField(),
      ];

      $this->cache->set($cid, $stats, time() + 3600);
      return $stats;
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('ai_upgrade_assistant')->error(
        'Error fetching community statistics: @error',
        ['@error' => $e->getMessage()]
      );
      return [];
    }
  }

  /**
   * Shares a pattern with the community.
   *
   * @param string $title
   *   Pattern title.
   * @param string $description
   *   Pattern description.
   * @param array $pattern_data
   *   The pattern data to share.
   * @param array $tags
   *   Optional tags for the pattern.
   *
   * @return bool
   *   TRUE if successful, FALSE otherwise.
   */
  public function sharePattern($title, $description, array $pattern_data, array $tags = []) {
    try {
      $fields = [
        'type' => $pattern_data['type'] ?? 'general',
        'module_name' => $pattern_data['module_name'],
        'pattern_data' => Json::encode($pattern_data),
        'created' => time(),
      ];

      $this->database->insert('ai_upgrade_assistant_patterns')
        ->fields($fields)
        ->execute();

      $this->loggerFactory->get('ai_upgrade_assistant')->info(
        'Pattern shared: @title',
        ['@title' => $title]
      );

      // Invalidate relevant caches
      $this->cache->invalidateTags(['ai_upgrade_assistant:patterns']);

      return TRUE;
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('ai_upgrade_assistant')->error(
        'Error sharing pattern: @error',
        ['@error' => $e->getMessage()]
      );
      return FALSE;
    }
  }

  /**
   * Finds similar patterns for a file.
   *
   * @param string $file
   *   The file path.
   *
   * @return array
   *   Array of similar patterns.
   */
  public function findSimilarPatterns($file) {
    try {
      // Extract module name from file path
      if (preg_match('#modules/(?:contrib|custom)/([^/]+)/#', $file, $matches)) {
        $module_name = $matches[1];
      }
      else {
        $this->loggerFactory->get('ai_upgrade_assistant')->notice(
          'Could not extract module name from file path: @file',
          ['@file' => $file]
        );
        return [];
      }

      // Skip empty module names
      if (empty($module_name)) {
        $this->loggerFactory->get('ai_upgrade_assistant')->notice(
          'Empty module name extracted from file path: @file',
          ['@file' => $file]
        );
        return [];
      }

      // Get all patterns and filter in PHP
      $query = $this->database->select('ai_upgrade_assistant_patterns', 'p')
        ->fields('p');
      
      $patterns = $query->execute()->fetchAll();
      
      // Filter patterns based on module name and task type
      return array_filter($patterns, function ($pattern) use ($module_name) {
        // If we have a module_name column and it matches, use that
        if (isset($pattern->module_name) && $pattern->module_name === $module_name) {
          return TRUE;
        }
        
        // Otherwise check the pattern data
        try {
          $data = unserialize($pattern->pattern_data);
          if (!empty($data['module']) && $data['module'] === $module_name) {
            return TRUE;
          }
        }
        catch (\Exception $e) {
          $this->loggerFactory->get('ai_upgrade_assistant')->warning(
            'Error unserializing pattern data: @error',
            ['@error' => $e->getMessage()]
          );
        }
        
        return FALSE;
      });
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('ai_upgrade_assistant')->error(
        'Error fetching shared patterns: @error',
        ['@error' => $e->getMessage()]
      );
      return [];
    }
  }
}

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

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