diff --git a/composer.json b/composer.json index ab092677db5584b8d736f4504aa869760310591a..9b24499ff48cf172830abae42ab82b8a4446aaaf 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ } ], "require": { - "drupal/core": "^10.3 || ^11.1" + "drupal/core": "^10.3 || ^11.1", + "drupal/project_browser": "^2.0" } } diff --git a/src/Event/ProjectEvent.php b/src/Event/ProjectEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..549a4a92ace1f76bb55289300d7814a91828e17a --- /dev/null +++ b/src/Event/ProjectEvent.php @@ -0,0 +1,74 @@ +<?php + +namespace Drupal\project_browser_gitlab\Event; + +use Drupal\Component\EventDispatcher\Event; +use Drupal\project_browser_gitlab\GitlabSourceInterface; + +/** + * Class for project event to modify the information from Gitlab API if needed. + */ +class ProjectEvent extends Event { + + /** + * The project info from Gitlab. + * + * @var array + */ + protected $project; + + /** + * The gitlab source. + * + * @var \Drupal\project_browser_gitlab\GitlabSourceInterface + */ + protected GitlabSourceInterface $gitlabSource; + + /** + * Constructs the event object. + * + * @param array $project + * The project info from Gitlab API response. + * @param \Drupal\project_browser_gitlab\GitlabSourceInterface $gitlab_source + * The Gitlab Source entity. + */ + public function __construct(array $project, GitlabSourceInterface $gitlab_source) { + $this->project = $project; + $this->gitlabSource = $gitlab_source; + } + + /** + * Gets the project info. + * + * @return array + * The project info. + */ + public function getProject() { + return $this->project; + } + + /** + * Gets the Gitlab Source entity. + * + * @return \Drupal\project_browser_gitlab\GitlabSourceInterface + * The Gitlab Source entity. + */ + public function getGitlabSource() { + return $this->gitlabSource; + } + + /** + * Sets the project. + * + * @param array $project + * The modified project. + * + * @return self + * The event object. + */ + public function setProject(array $project) { + $this->project = $project; + return $this; + } + +} diff --git a/src/Plugin/ProjectBrowserSource/Gitlab.php b/src/Plugin/ProjectBrowserSource/Gitlab.php index dd7a61aa088df9077755b3486eacb514f16739a1..6e8d80f68cf6c58ab51ff1f9eb3377129ed8193d 100644 --- a/src/Plugin/ProjectBrowserSource/Gitlab.php +++ b/src/Plugin/ProjectBrowserSource/Gitlab.php @@ -4,26 +4,32 @@ namespace Drupal\project_browser_gitlab\Plugin\ProjectBrowserSource; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\Core\Url; +use Drupal\project_browser\Attribute\ProjectBrowserSource; use Drupal\project_browser\Plugin\ProjectBrowserSourceBase; +use Drupal\project_browser\ProjectBrowser\Filter\MultipleChoiceFilter; +use Drupal\project_browser\ProjectBrowser\Filter\TextFilter; use Drupal\project_browser\ProjectBrowser\Project; use Drupal\project_browser\ProjectBrowser\ProjectsResultsPage; use Drupal\project_browser\ProjectType; use Drupal\project_browser_gitlab\Entity\GitlabSource; +use Drupal\project_browser_gitlab\Event\ProjectEvent; use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\GuzzleException; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Project Browser Source Plugin for Gitlab. - * - * @ProjectBrowserSource( - * id = "project_browser_gitlab", - * label = @Translation("Gitlab"), - * description = @Translation("Source plugin for Project Browser to search Gitlab."), - * deriver = "Drupal\project_browser_gitlab\Plugin\Derivative\GitlabDeriver", - * ) */ +#[ProjectBrowserSource( + id: 'project_browser_gitlab', + label: new TranslatableMarkup('Gitlab'), + description: new TranslatableMarkup('Source plugin for Project Browser to search Gitlab.'), + deriver: 'Drupal\project_browser_gitlab\Plugin\Derivative\GitlabDeriver', +)] class Gitlab extends ProjectBrowserSourceBase implements ContainerFactoryPluginInterface { /** @@ -47,6 +53,13 @@ class Gitlab extends ProjectBrowserSourceBase implements ContainerFactoryPluginI */ protected GitlabSource $source; + /** + * The event dispatcher. + * + * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface + */ + protected EventDispatcherInterface $eventDispatcher; + /** * Constructor for the plugin. * @@ -59,15 +72,21 @@ class Gitlab extends ProjectBrowserSourceBase implements ContainerFactoryPluginI * @param \GuzzleHttp\ClientInterface $httpClient * The HTTP client. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity type manager. + * The entity type manager. + * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher + * The event dispatcher. * @param \Psr\Log\LoggerInterface $logger * A logger instance. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, ClientInterface $httpClient, EntityTypeManagerInterface $entity_type_manager, LoggerInterface $logger) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, ClientInterface $httpClient, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher, LoggerInterface $logger) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->httpClient = $httpClient; $this->logger = $logger; $this->source = $entity_type_manager->getStorage('project_browser_gitlab_source')->load($plugin_definition['id']); + $this->eventDispatcher = $event_dispatcher; } /** @@ -80,11 +99,11 @@ class Gitlab extends ProjectBrowserSourceBase implements ContainerFactoryPluginI $plugin_definition, $container->get('http_client'), $container->get('entity_type.manager'), + $container->get('event_dispatcher'), $container->get('logger.factory')->get('project_browser'), ); } - /** * {@inheritdoc} * @param array $query @@ -142,15 +161,15 @@ class Gitlab extends ProjectBrowserSourceBase implements ContainerFactoryPluginI } foreach ($response['data'] ?? [] as $project) { - $logo = [ - 'file' => [ - 'uri' => $project['avatar_url'], - 'resource' => 'image', - ], - 'alt' => (string) $this->t('@name logo', [ - '@name' => $project['name'], - ]), - ]; + $project['type'] = ProjectType::Module; + // Allow other modules to modify the project info. + $event = new ProjectEvent($project, $this->source); + $this->eventDispatcher->dispatch($event); + $project = $event->getProject(); + $logo = NULL; + if (!empty($project['avatar_url'])) { + $logo = Url::fromUri($project['avatar_url']); + } $categories = []; foreach ($project['topics'] as $index => $topic) { @@ -159,19 +178,17 @@ class Gitlab extends ProjectBrowserSourceBase implements ContainerFactoryPluginI 'name' => $topic, ]; } - $projects[] = new Project( logo: $logo, isCompatible: TRUE, isCovered: TRUE, projectUsageTotal: 0, - machineName: str_replace('/', '|', $project['path_with_namespace']), + machineName: $project['path'], body: $project['description'] ? ['value' => $project['description']] : [], title: $project['name'] ?? '', - author: [], packageName: $project['path_with_namespace'], categories: $categories, - type: ProjectType::Module, + type: $project['type'], ); } @@ -196,13 +213,10 @@ class Gitlab extends ProjectBrowserSourceBase implements ContainerFactoryPluginI $categories = []; foreach ($response['data'] ?? [] as $category) { - $categories[$category['name']] = [ - 'id' => $category['name'], - 'name' => $category['name'], - ]; + $categories[$category['name']] = $category['name']; } - return array_values($categories); + return $categories; } /** @@ -255,23 +269,25 @@ class Gitlab extends ProjectBrowserSourceBase implements ContainerFactoryPluginI */ public function getSortOptions(): array { return [ - 'created' => [ - 'id' => 'created', - 'text' => $this->t('Newest First'), - ], - 'a_z' => [ - 'id' => 'a_z', - 'text' => $this->t('A-Z'), - ], - 'z_a' => [ - 'id' => 'z_a', - 'text' => $this->t('Z-A'), - ], - 'updated' => [ - 'id' => 'updated', - 'text' => $this->t('Latest Updated First'), - ], + 'created' => $this->t('Newest First'), + 'a_z' => $this->t('A-Z'), + 'z_a' => $this->t('Z-A'), + 'updated' => $this->t('Latest Updated First'), ]; } + /** + * {@inheritdoc} + */ + public function getFilterDefinitions(): array { + $filters = []; + $filters['search'] = new TextFilter('', $this->t('Search')); + $filters['categories'] = new MultipleChoiceFilter( + $this->getCategories(), + [], + $this->t('Categories'), + ); + return $filters; + } + }