sgd_dashboard-1.0.0-beta1/src/Services/SiteGuardianDataService.php

src/Services/SiteGuardianDataService.php
<?php

namespace Drupal\sgd_dashboard\Services;

use Drupal\Core\Database\Connection;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Node\NodeInterface;
use Drupal\sgd_dashboard\Entity\Bundle\WebsiteBundle;
use Drupal\sgd_dashboard\SgdCompanionPluginManager;
use Psr\Log\LoggerInterface;

/**
 * SiteGuardian dashboard data service.
 *
 * Provides functions for maintaining the SGD data model.
 */
class SiteGuardianDataService {

  /**
   * The SGD API Client service.
   *
   * @var \Drupal\sgd_dashboard\Services\SiteGuardianAPIClientService
   */
  protected $apiService;

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

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

  /**
   * The Site Guardian Dashboard Companion plugin manager.
   *
   * @var \Drupal\sdg_dashboard\SgdCompanionPluginManager
   */
  protected $pluginManager;

  /**
   * Logger.
   *
   * @var Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * {@inheritDoc}
   */
  public function __construct(SiteGuardianAPIClientService $apiService, EntityTypeManagerInterface $entityTypeManager, Connection $database, SgdCompanionPluginManager $pluginManager, LoggerInterface $logger) {
    $this->apiService = $apiService;
    $this->entityTypeManager = $entityTypeManager;
    $this->database = $database;
    $this->pluginManager = $pluginManager;
    $this->logger = $logger;
  }

  /**
   * Helper function to refresh non-user-added Website node fields.
   */
  public function refreshWebsiteFields(NodeInterface $website, $saveNode = TRUE): void {

    // Get the API data from the target website.
    $websiteData = $this->apiService->getStatus($website);
    $enabledProjects = $this->apiService->getEnabledProjects($website);

    // If the website data does not have a 'sgd_update_last_checked' entry then
    // an old version of the API is being used.
    // In this case we get the value in the project data and inject it into the
    // status data.
    if (empty($websiteData['sgd_updates_last_checked'])) {
      $websiteData['sgd_updates_last_checked'] = [
        'value' => $enabledProjects['last_checked'],
      ];
    }

    // In any case we dont want the last checked value in the project data.
    unset($enabledProjects['last_checked']);

    // Update the database as required.
    $this->updateWebsite($website, $enabledProjects, $saveNode);
    $this->updateWebsiteData($website, $websiteData, $enabledProjects);
    $this->updateProjects($website, $enabledProjects);
  }

  /**
   * Update fields on the website node with data from the remote website.
   */
  public function updateWebsite(NodeInterface $website, $enabledProjects, $saveNode): void {

    $coreIsSecure = $enabledProjects['drupal']['status'] != 1;
    $contribIsSecure = TRUE;

    foreach ($enabledProjects as $moduleName => $moduleData) {
      if (!in_array($moduleName, ['drupal'])) {
        if ($moduleData['status'] == 1) {
          $contribIsSecure = FALSE;
          break;
        }
      }
    }

    $siteLastChecked = new DrupalDateTime('1 second ago');

    $website->set('field_core_security', $coreIsSecure);
    $website->set('field_contrib_security', $contribIsSecure);
    $website->set('field_site_last_checked', $siteLastChecked->getTimestamp());

    if ($saveNode) {
      $website->save();
    }
  }

  /**
   * Update name of the website data storage entity.
   */
  public function updateWebsiteDataName(WebsiteBundle $website): void {

    // Get the website data for this website.
    $websiteData = $website->field_sgd_website_data->entity;

    if ($websiteData) {

      // Update the name to match the website node.
      $websiteData->set('label', $website->getTitle());

      // Save the website data.
      $websiteData->save();
    }
  }

  /**
   * Update fields on the website data storage entity.
   *
   * Website data entity is updated with data from the remote website
   * by calling each companionion plugin which will update the data it knows
   * about.
   */
  public function updateWebsiteData(WebsiteBundle $website, array $statusReport, array $enabledProjects): void {

    // Get the website data for this website.
    $websiteData = $website->field_sgd_website_data->entity;

    if ($websiteData) {

      // Always update the name to match the website node.
      $websiteData->set('label', $website->getTitle());

      // If we have status data then update the status fields.
      if ($statusReport) {

        // Find all Companion plugins and iterate through them calling their
        // saveData function so each can extract the info they understand from
        // the status report data and save it as required.
        // Get all the companion modules.
        $plugins = $this->pluginManager->getDefinitions();

        // Iterate over them all.
        foreach ($plugins as $plugin) {

          $instance = $this->pluginManager->createInstance($plugin['id']);

          // If the plugin can see data it knows how to handle in the status
          // report.
          if ($instance->canProcessStatus($statusReport)) {

            // Call the 'savedata' function passing the websitedata entity so
            // the plugin can save the data it knows about.
            // By passing the website as well as the status report data the
            // plugin can store the data as it requires.
            $instance->saveStatus($websiteData, $statusReport, $enabledProjects);
          }
        }

        // Save the website data.
        $websiteData->save();
      }

    }
    else {
      $this->logger->error("No website data storage entity was found for %website", [
        '%website' => $website->getTitle(),
      ]);
    }
  }

  /**
   * Delete website data storage entity for remote website.
   */
  public function deleteWebsiteData(NodeInterface $website): void {

    $websiteData = $website->field_sgd_website_data->entity;

    if ($websiteData) {
      $websiteData->delete();
    }
  }

  /**
   * Updates project storage entities with projects from the remote website.
   */
  public function updateProjects(NodeInterface $website, array $enabledProjects): void {

    // If the website node already exists then it may have project data so
    // delete it first.
    if ($website->isNew() == FALSE) {
      $this->deleteProjects($website);
    }

    $enabledProjectStorage = $this->entityTypeManager->getStorage('sgd_enabled_project');

    // Now for each project add a record to the DB.
    foreach ($enabledProjects as $projectName => $project) {

      $enabledProject = $enabledProjectStorage->create([

        'name' => $projectName,
        'website' => $website,
        'status_id' => $project['status'],
        'info' => isset($project['info']) ? json_encode($project['info']) : NULL,
        'datestamp' => $project['datestamp'],
        'includes' => isset($project['includes']) ? json_encode($project['includes']) : NULL,
        'project_type' => $project['project_type'],
        'project_status' => $project['project_status'] == 'unsupported' ?: var_export($project['project_status'], TRUE),
        'existing_version' => $project['existing_version'],
        'existing_major' => $project['existing_major'],
        'install_type' => $project['install_type'],
        'title' => $project['title'] ?? NULL,
        'link' => isset($project['link']) ? ['url' => $project['link'], 'label' => $projectName] : NULL,
        'latest_version' => $project['latest_version'] ?? NULL,
        'releases' => isset($project['releases']) ? json_encode($project['releases']) : NULL,
        'recommended' => $project['recommended'] ?? '',
      ]);

      $enabledProject->save();
    }
  }

  /**
   * Deletes project storage entities for a website.
   */
  public function deleteProjects(NodeInterface $website): void {

    $enabledProjectStorage = $this->entityTypeManager->getStorage('sgd_enabled_project');

    // Get all the websites projects in the DB.
    $projectIds = $enabledProjectStorage->getQuery()
      ->accessCheck(TRUE)
      ->condition('website', $website->id())
      ->execute();

    // Delete them all.
    foreach ($projectIds as $projectId) {
      $project_already_in_db = $enabledProjectStorage->load($projectId);
      $project_already_in_db->delete();
    }
  }

  /**
   * Checks if the passed Site Guardian key is unique across all websites.
   */
  public function isSiteGuardianKeyUnique($key): bool {

    // See if site guardian key has more then 1 entry from the website nodes.
    $query = $this->database->select('node__field_site_guardian_key', 'sgk')
      ->condition('sgk.field_site_guardian_key_value', $key, '=')
      ->fields('sgk', ['field_site_guardian_key_value'])
      ->countQuery();

    $unique = (bool) ($query->execute()->fetchField() < 2);

    return $unique;
  }

}

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

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