l10n_server-2.x-dev/l10n_community/src/Controller/L10nCommunityProjectsController.php

l10n_community/src/Controller/L10nCommunityProjectsController.php
<?php

declare(strict_types=1);

namespace Drupal\l10n_community\Controller;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ConfigManagerInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Database\Connection;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\l10n_community\L10nStatistics;
use Drupal\l10n_server\Entity\L10nServerProjectInterface;
use Drupal\l10n_server\L10nProjectManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Returns responses for Localization community UI routes.
 */
final class L10nCommunityProjectsController extends ControllerBase {

  /**
   * Community settings.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  private ImmutableConfig $communitySettings;

  /**
   * The controller constructor.
   *
   * @param \Drupal\Core\Database\Connection $connection
   *   The database connection.
   * @param \Drupal\Core\Config\ConfigManagerInterface $configManager
   *   The config manager.
   * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
   *   The route match.
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
   *   The request stack.
   * @param \Drupal\l10n_community\L10nStatistics $statistics
   *   The l10n_community.statistics service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\l10n_server\L10nProjectManager $l10nProjectManager
   *   The l10n project manager service.
   */
  public function __construct(
    private readonly Connection $connection,
    private readonly ConfigManagerInterface $configManager,
    private readonly RouteMatchInterface $routeMatch,
    private readonly RequestStack $requestStack,
    private readonly L10nStatistics $statistics,
    ConfigFactoryInterface $config_factory,
    private readonly L10nProjectManager $l10nProjectManager,
  ) {
    $this->communitySettings = $config_factory->get('l10n_community.settings');
  }

  /**
   * {@inheritdoc}
   */
  public static function create(
    ContainerInterface $container,
  ): self {
    return new L10nCommunityProjectsController(
      $container->get('database'),
      $container->get('config.manager'),
      $container->get('current_route_match'),
      $container->get('request_stack'),
      $container->get('l10n_community.statistics'),
      $container->get('config.factory'),
      $container->get('l10n_server.project_manager'),
    );
  }

  /**
   * Title callback.
   *
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
   *   Translatable markup object.
   */
  public function title(): TranslatableMarkup {
    $project = $this->routeMatch->getParameter('project');

    if ($project instanceof L10nServerProjectInterface) {
      return $this->t('@project_name releases', [
        '@project_name' => $project->label(),
      ]);
    }

    return $this->t('Releases');
  }

  /**
   * Builds the response.
   */
  public function explore(): array {
    if (
      !$this->communitySettings->get('stats_enabled')
      || !$this->communitySettings->get('stats_explore_projects_enabled')
    ) {
      $build['content'] = [
        '#type' => 'item',
        '#markup' => $this->t('Statistics for projects have been disabled.'),
      ];

      return [
        'content' => [
          '#type' => 'item',
          '#markup' => $this->t('Statistics for projects have been disabled.'),
        ],
      ];
    }

    $options = ['pager' => $this->communitySettings->get('project_per_page')];

    if (!is_null($this->requestStack->getCurrentRequest()->get('initial'))) {
      $options['initial'] = strtolower($this->requestStack->getCurrentRequest()->get('initial'));
    }

    if (!$projects = $this->getProjects($options)) {
      $build['content'] = [
        '#type' => 'item',
        '#markup' => $this->t('No projects found.'),
      ];

      return $build;
    }

    $projects_ids = array_map(function ($project) {
      return $project->pid;
    }, $projects);

    $language_count = count($this->languageManager()->getLanguages());
    $string_counts = $this->statistics->getProjectsStringCount(project_ids: array_values($projects_ids));

    $table = [];

    foreach ($projects as $project) {
      $total_strings = ($string_counts[$project->pid]['count'] ?? 0 * $language_count);
      $string_translated = $string_counts[$project->pid]['translations'] ?? 0;
      $string_suggestions = $string_counts[$project->pid]['suggestions'] ?? 0;
      $table[] = [
        [
          'data' => $this->t('<a href="@url">@project</a>', [
            '@project' => $project->title,
            '@url' => Url::fromUri('internal:/translate/projects/' . $project->pid)->toString(),
          ]),
          'class' => ['rowhead'],
        ],
        [
          'data' => [
            '#theme' => 'l10n_community_progress_columns',
            '#sum' => $total_strings,
            '#translated' => $string_translated,
          ],
        ],
      ];
    }

    $build['pre_pager'] = [
      '#type' => 'pager',
    ];
    $build['content'] = [
      '#type' => 'table',
      '#header' => [
        t('Project'),
        t('Progress'),
      ],
      '#rows' => $table,
      '#attributes' => [
        'class' => [
          'l10n-community-overview',
        ],
      ],
      '#cache' => [
        // @todo Fix cache handling.
        // 'max-age' => Cache::PERMANENT,
      ],
    ];

    $build['post_pager'] = [
      '#type' => 'pager',
    ];
    $build['#attached']['library'][] = 'l10n_community/tables';

    return $build;
  }

  /**
   * Builds the response.
   *
   * @param \Drupal\l10n_server\Entity\L10nServerProjectInterface $project
   *   The project entity.
   *
   * @return array
   *   A render array.
   */
  public function overview(L10nServerProjectInterface $project): array {
    $build['content'] = [
      '#type' => 'item',
      '#markup' => __METHOD__ . '::' . $project->label(),
    ];

    return $build;
  }

  /**
   * Builds the response.
   *
   * @param \Drupal\l10n_server\Entity\L10nServerProjectInterface $project
   *   The project entity.
   *
   * @return array
   *   A render array.
   */
  public function export(L10nServerProjectInterface $project): array {
    $build['content'] = [
      '#type' => 'item',
      '#markup' => __METHOD__ . '::' . $project->label(),
    ];

    return $build;
  }

  /**
   * Builds the response.
   *
   * @param \Drupal\l10n_server\Entity\L10nServerProjectInterface $project
   *   The project entity.
   *
   * @return array
   *   A render array.
   */
  public function releases(L10nServerProjectInterface $project): array {
    $build['content'] = [
      '#type' => 'item',
      '#markup' => __METHOD__ . '::' . $project->label(),
    ];

    return $build;
  }

  /**
   * Provides a list of projects from the database, ordered by uri.
   *
   * @param array $options
   *   Associative array of options
   *    - 'uri': Project URI, if requesting information about one project only.
   *      If not specified, information about all projects is returned.
   *    - 'pager': Number of projects to return a pager query result with. If
   *      NULL, no pager is used.
   *    - 'all': If not specified, unpublished projects are excluded (default).
   *      If TRUE, even unpublished projects are returned (for admin pages).
   *
   * @return array
   *   An associative array keyed with project uris.
   *
   * @throws \Exception
   */
  private function getProjects(array $options = []): array {
    static $projects = [];

    $select = $this->connection
      ->select('l10n_server_project', 'p')
      ->fields('p', []);

    // Consider returning all projects or just published ones.
    if (empty($options['all'])) {
      $select->condition('status', 1);
    }

    if (!empty($options['pager'])) {
      if (!empty($options['initial'])) {
        $initials = $this->l10nProjectManager->getProjectInitials();

        if (isset($initials[$options['initial']])) {
          $args = $initials[$options['initial']]['values'];
          for ($i = 0; $i < count($args); $i++) {
            $arguments[':p_' . $i] = $args[$i];
          }
          $placeholders = implode(',', array_keys($arguments));
          $select->where("SUBSTRING(title, 1, 1) IN ($placeholders)", $arguments);
        }
      }

      // If a pager view was asked for, collect data independently.
      $select->orderBy('title');
      $result = $select
        ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
        ->limit($options['pager'])
        ->execute();
      $pager_results = $result
        ->fetchAllAssoc('uri');

      // Save project information for later, if someone asks for it by uri.
      $projects = array_merge($projects, $pager_results);

      return $pager_results;
    }
    else {
      if (isset($options['uri'])) {
        // A specific project was asked for.
        if (isset($projects[$options['uri']])) {
          // Can be served from the local cache.
          return $projects[$options['uri']];
        }
        // Not found in cache, so query and cache before returning.
        $result = $this->connection
          ->query("SELECT * FROM {l10n_server_project} WHERE uri = :uri", [
            ':uri' => $options['uri'],
          ]);
        if ($project = $result->fetchObject()) {
          $projects[$options['uri']] = $project;
          return $project;
        }
      }
      else {
        // A list of *all* projects was asked for.
        $results = $select->orderBy('uri')->execute();
        foreach ($results as $project) {
          $projects[$project->uri] = $project;
        }
        return $projects;
      }
    }

    return $projects;
  }

}

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

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