diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 1091c55..8037f3f 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -1,5 +1,10 @@ on: pull_request + name: Review + +env: + COMPOSE_USER: runner + jobs: changelog: runs-on: ubuntu-latest @@ -8,7 +13,7 @@ jobs: fail-fast: false steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 2 @@ -17,94 +22,55 @@ jobs: - name: Check that changelog has been updated. run: git diff --exit-code origin/${{ github.base_ref }} -- CHANGELOG.md && exit 1 || exit 0 - test-composer-files: - name: Validate composer + + composer-validate: runs-on: ubuntu-latest - strategy: - matrix: - php-versions: [ '8.1' ] - dependency-version: [ prefer-lowest, prefer-stable ] steps: - - uses: actions/checkout@master - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: json - coverage: none - tools: composer:v2 - # https://github.com/shivammathur/setup-php#cache-composer-dependencies - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- + - uses: actions/checkout@v4 - name: Validate composer files run: | - composer validate --strict composer.json - # Check that dependencies resolve. - composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction - php-check-coding-standards: - name: PHP - Check Coding Standards + docker compose run --rm phpfpm composer validate + - name: Check that dependencies resolve + run: | + docker compose run --rm phpfpm composer update + + check-composer-normalize: runs-on: ubuntu-latest - strategy: - matrix: - php-versions: [ '8.1' ] - dependency-version: [ prefer-lowest, prefer-stable ] steps: - - uses: actions/checkout@master - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: json - coverage: none - tools: composer:v2 - # https://github.com/shivammathur/setup-php#cache-composer-dependencies - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - name: Install Dependencies - run: | - composer install --no-interaction --no-progress - - name: PHPCS - run: | - composer coding-standards-check/phpcs - php-code-analysis: - name: PHP code analysis + - uses: actions/checkout@v4 + - run: | + docker compose run --rm phpfpm composer install + docker compose run --rm phpfpm composer normalize --dry-run + + coding-standards-check-phpcs: runs-on: ubuntu-latest - strategy: - matrix: - php-versions: [ '8.1' ] steps: - - uses: actions/checkout@master - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: json - coverage: none - tools: composer:v2 - # https://github.com/shivammathur/setup-php#cache-composer-dependencies - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - name: Code analysis - run: | + - uses: actions/checkout@v4 + - run: | + docker compose run --rm phpfpm composer install + docker compose run --rm phpfpm composer coding-standards-check/phpcs + + code-analysis: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | ./scripts/code-analysis + + proxy-classes: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | + ./scripts/generate-proxy-classes + - name: Check nothing has changed + run: git diff --exit-code + + rector: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | + ./scripts/rector + - name: Check nothing has changed + run: git diff --exit-code diff --git a/CHANGELOG.md b/CHANGELOG.md index 208fdcc..9f9c0f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ before starting to add changes. ## [Unreleased] +* [PR-70](https://github.com/itk-dev/itk_pretix/pull/70) + Cleaned up and refactored Code +* [PR-69](https://github.com/itk-dev/itk_pretix/pull/69) + Added “Registration deadline” to date + ## 1.2.2 - Allow nullabale pretix client diff --git a/README.md b/README.md index 9e78fcd..e68e3d1 100644 --- a/README.md +++ b/README.md @@ -49,48 +49,40 @@ The available exporters for a node can be run from First, install tools and requirements: ```sh -yarn install +docker compose run --rm node yarn install ``` Build for development: ```sh -yarn encore dev --watch +docker compose run --rm node yarn encore dev --watch ``` Build for production: ```sh -yarn encore production +docker compose run --rm node yarn encore production ``` ## Coding standards The code must follw the [Drupal Coding Standards](https://www.drupal.org/docs/develop/standards) -Check the coding standards by running +Apply and check the coding standards by running ```sh -composer install -composer coding-standards-check -``` - -Apply the coding standards by running - -```sh -composer coding-standards-apply +docker compose run --rm phpfpm composer install +docker compose run --rm phpfpm composer normalize +docker compose run --rm phpfpm composer coding-standards-apply +docker compose run --rm phpfpm composer coding-standards-check ``` ### Assets -Check the coding standards in assets by running - -```sh -yarn coding-standards-check -``` - -Apply the coding standards by running +Apply and check the coding standards in assets by running ```sh -yarn coding-standards-apply +docker compose run --rm node yarn install +docker compose run --rm node yarn coding-standards-apply +docker compose run --rm node yarn coding-standards-check ``` diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..fcd57b0 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,16 @@ +services: + phpfpm: + image: itkdev/php8.3-fpm:latest + user: ${COMPOSE_USER:-deploy} + profiles: + - dev + volumes: + - .:/app + + node: + image: node:22 + profiles: + - dev + working_dir: /app + volumes: + - .:/app diff --git a/composer.json b/composer.json index 662f218..0ab9d7c 100644 --- a/composer.json +++ b/composer.json @@ -1,41 +1,25 @@ { "name": "itk-dev/itk_pretix", - "type": "drupal-module", "description": "A module using pretix API to generate events from field values", - "keywords": ["Drupal"], "license": "MIT", - "minimum-stability": "dev", + "type": "drupal-module", + "keywords": [ + "Drupal" + ], "require": { - "php": "^8.1", - "nicoeg/dawa": "^1.0", - "itk-dev/pretix-api-client-php": "^1.1" + "php": "^8.3", + "itk-dev/pretix-api-client-php": "^1.1", + "nicoeg/dawa": "^1.0" }, "require-dev": { - "drupal/coder": "^8.3.1", - "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "mglaman/phpstan-drupal": "^1.1", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan-deprecation-rules": "^1.1" - }, - "scripts": { - "coding-standards-check/phpcs": [ - "vendor/bin/phpcs --standard=phpcs.xml.dist" - ], - "coding-standards-check": [ - "@coding-standards-check/phpcs" - ], - "coding-standards-apply/phpcs": [ - "vendor/bin/phpcbf --standard=phpcs.xml.dist" - ], - "coding-standards-apply": [ - "@coding-standards-apply/phpcs" - ], - "code-analysis/phpstan": [ - "phpstan analyse --configuration=phpstan.neon" - ], - "code-analysis": [ - "@code-analysis/phpstan" - ] + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", + "drupal/coder": "^8.3", + "ergebnis/composer-normalize": "^2.45", + "mglaman/phpstan-drupal": "^1.3", + "palantirnet/drupal-rector": "^0.20.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^1.12", + "phpstan/phpstan-deprecation-rules": "^1.2" }, "repositories": { "drupal": { @@ -43,10 +27,26 @@ "url": "https://packages.drupal.org/8" } }, + "minimum-stability": "dev", "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true, - "phpstan/extension-installer": true - } + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "phpstan/extension-installer": true + } + }, + "scripts": { + "coding-standards-apply": [ + "@coding-standards-apply/phpcs" + ], + "coding-standards-apply/phpcs": [ + "vendor/bin/phpcbf --standard=phpcs.xml.dist" + ], + "coding-standards-check": [ + "@coding-standards-check/phpcs" + ], + "coding-standards-check/phpcs": [ + "vendor/bin/phpcs --standard=phpcs.xml.dist" + ] } } diff --git a/itk_pretix.info.yml b/itk_pretix.info.yml index 25a5ede..85990b6 100644 --- a/itk_pretix.info.yml +++ b/itk_pretix.info.yml @@ -1,7 +1,8 @@ name: 'ITK Pretix' type: module description: 'A module using pretix API to generate events from field values' -core_version_requirement: ^9 || ^10 +# We're autowiring services and need Drupal 10.2 or newer (cf. https://www.drupal.org/node/3366757) +core_version_requirement: ^10.2 package: 'ITK' dependencies: - drupal:field diff --git a/itk_pretix.install b/itk_pretix.install index cc8e20d..ecf3f3c 100644 --- a/itk_pretix.install +++ b/itk_pretix.install @@ -5,6 +5,8 @@ * Installation file for the itk_pretix module. */ +use Drupal\Core\Entity\Sql\SqlContentEntityStorage; + /** * Implements hook_schema(). */ @@ -93,3 +95,73 @@ function itk_pretix_schema() { ], ]; } + +/** + * Implements hook_update_N(). + */ +function itk_pretix_update_10101(&$sandbox) { + _itk_pretix_field_type_add_properties( + 'pretix_date', + [ + 'registration_deadline_value' => [ + 'description' => 'The registration deadline value.', + 'type' => 'varchar', + 'length' => 20, + ], + ] + ); +} + +/** + * Lifted from https://drupal.stackexchange.com/a/295485. + */ +function _itk_pretix_field_type_add_properties(string $field_type, array $columns): void { + $database_schema = \Drupal::database()->schema(); + + $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + + // First, get all fields of the provided field type. + $field_map = \Drupal::service('entity_field.manager') + ->getFieldMapByFieldType($field_type); + + // Process per entity type (i.e., node, paragraph) all fields. + foreach ($field_map as $entity_type_id => $fields) { + $entity_type_storage = \Drupal::entityTypeManager() + ->getStorage($entity_type_id); + + // Database schema can only be updated, if the values are stored in the + // database, of course. + if ($entity_type_storage instanceof SqlContentEntityStorage) { + foreach (array_keys($fields) as $field_name) { + $field_storage_definition = $entity_definition_update_manager->getFieldStorageDefinition($field_name, + $entity_type_id); + + // Get the table and column names, according to the field definition. + $table_mapping = $entity_type_storage->getTableMapping([ + $field_name => $field_storage_definition, + ]); + $table_names = $table_mapping->getDedicatedTableNames(); + $table_columns = $table_mapping->getColumnNames($field_name); + + // Check if, for the property, the corresponding table exists in the + // database. If not, create the table column (according to the schema + // provided by the field definition). + foreach ($table_names as $table_name) { + $table_exists = $database_schema->tableExists($table_name); + foreach ($columns as $property => $spec) { + $field_exists = $database_schema->fieldExists($table_name, + $table_columns[$property]); + + if ($table_exists && !$field_exists) { + $database_schema->addField($table_name, $table_columns[$property], + $spec); + } + } + } + + // Reflect any changes made to the field storage definition. + $entity_definition_update_manager->updateFieldStorageDefinition($field_storage_definition); + } + } + } +} diff --git a/itk_pretix.module b/itk_pretix.module index fdd962a..d7b593f 100644 --- a/itk_pretix.module +++ b/itk_pretix.module @@ -6,6 +6,9 @@ */ use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\itk_pretix\Exporter\Manager as ExporterManager; +use Drupal\itk_pretix\Exporter\ManagerInterface as ExporterManagerInterface; +use Drupal\itk_pretix\NodeHelper; use Drupal\node\NodeInterface; /** @@ -92,33 +95,47 @@ function _itk_pretix_process_datetime_element(array $element) { * Implements hook_node_insert(). */ function itk_pretix_node_insert(NodeInterface $node) { - \Drupal::service('itk_pretix.node_helper')->synchronizeEvent($node, 'insert'); + _itk_pretix_get_node_helper()->synchronizeEvent($node, 'insert'); } /** * Implements hook_node_update(). */ function itk_pretix_node_update(NodeInterface $node) { - \Drupal::service('itk_pretix.node_helper')->synchronizeEvent($node, 'update'); + _itk_pretix_get_node_helper()->synchronizeEvent($node, 'update'); } /** * Implements hook_node_delete(). */ function itk_pretix_node_delete(NodeInterface $node) { - \Drupal::service('itk_pretix.node_helper')->synchronizeEvent($node, 'delete'); + _itk_pretix_get_node_helper()->synchronizeEvent($node, 'delete'); } /** * Implements hook_cloned_node_alter(). */ function itk_pretix_cloned_node_alter(NodeInterface $node) { - \Drupal::service('itk_pretix.node_helper')->clonedNodeAlter($node); + _itk_pretix_get_node_helper()->clonedNodeAlter($node); } /** * Implements hook_file_download(). */ function itk_pretix_file_download($uri) { - return \Drupal::service('itk_pretix.exporter_manager')->fileDownload($uri); + return _itk_pretix_get_exporter_manager()->fileDownload($uri); +} + +/** + * Get node helper. + */ +function _itk_pretix_get_node_helper(): NodeHelper { + return \Drupal::service(NodeHelper::class); +} + +/** + * Get exporter manager. + */ +function _itk_pretix_get_exporter_manager(): ExporterManagerInterface { + return \Drupal::service(ExporterManager::class); } diff --git a/itk_pretix.services.yml b/itk_pretix.services.yml index cfa301d..9502d54 100644 --- a/itk_pretix.services.yml +++ b/itk_pretix.services.yml @@ -1,61 +1,34 @@ services: - itk_pretix.node_helper: - class: Drupal\itk_pretix\NodeHelper - arguments: - - '@itk_pretix.event_helper' - - '@entity_type.manager' - - '@module_handler' - - '@messenger' - - itk_pretix.event_helper: - class: Drupal\itk_pretix\Pretix\EventHelper - arguments: - - '@database' - - '@config.factory' - - '@logger.factory' - - '@itk_pretix.order_helper' - - '@module_handler' - - itk_pretix.order_helper: - class: Drupal\itk_pretix\Pretix\OrderHelper - arguments: - - '@database' - - '@config.factory' - - '@logger.factory' - - itk_pretix.exporter_manager: - class: Drupal\itk_pretix\Exporter\Manager + # https://www.drupal.org/node/3366757 + _defaults: + autowire: true + + Drupal\itk_pretix\NodeHelper: + + Drupal\itk_pretix\Pretix\EventHelper: + + Drupal\itk_pretix\Pretix\OrderHelper: + + Drupal\itk_pretix\Exporter\Manager: lazy: true - arguments: - - '@file_system' - - '@itk_pretix.access_check' - - '@current_user' - - '@file_url_generator' tags: - { name: service_collector, tag: itk_pretix_exporter, call: addEventExporter } - itk_pretix.exporter.itk_pretix_exporter_check_in_list: - class: Drupal\itk_pretix\Exporter\CheckInListExporter + Drupal\itk_pretix\Exporter\CheckInListExporter: lazy: true tags: - { name: itk_pretix_exporter } - itk_pretix.exporter.itk_pretix_exporter_check_in_list_pdf: - class: Drupal\itk_pretix\Exporter\CheckInListPdfExporter + Drupal\itk_pretix\Exporter\CheckInListPdfExporter: lazy: true tags: - { name: itk_pretix_exporter } - itk_pretix.exporter.itk_pretix_exporter_orderlist: - class: Drupal\itk_pretix\Exporter\OrderListExporter + Drupal\itk_pretix\Exporter\OrderListExporter: lazy: true tags: - { name: itk_pretix_exporter } - itk_pretix.access_check: - class: Drupal\itk_pretix\Access\AccessCheck - arguments: - - '@current_user' - - '@current_route_match' + Drupal\itk_pretix\Access\AccessCheck: tags: - { name: access_check, applies_to: _itk_pretix_export_access_check } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index a6ac5bd..081d381 100755 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -4,13 +4,16 @@ . + rector.php + src/ProxyClass/ vendor/ + node_modules/ - + diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..61dcf01 --- /dev/null +++ b/rector.php @@ -0,0 +1,24 @@ +withPaths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + ->withSkip([ + __DIR__ . '/src/ProxyClass', + ]) + ->withSets([ + Drupal10SetList::DRUPAL_10, + ]) + ->withPhpSets(php83: TRUE) + ->withTypeCoverageLevel(0); diff --git a/scripts/.env b/scripts/.env new file mode 100644 index 0000000..34c4496 --- /dev/null +++ b/scripts/.env @@ -0,0 +1,2 @@ +COMPOSE_PROJECT_NAME=drupal-module +MODULE_NAME=itk_pretix diff --git a/scripts/base b/scripts/base new file mode 100644 index 0000000..7ac4abd --- /dev/null +++ b/scripts/base @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +set -o errexit -o errtrace -o noclobber -o nounset -o pipefail +IFS=$'\n\t' + +execute_name=execute + +usage() { + (cat >&2 </dev/null); then + (cat >&2 <&2 <eventHelper = $container->get('itk_pretix.event_helper'); - $instance->exporterManager = $container->get('itk_pretix.exporter_manager'); + $instance->eventHelper = $container->get(EventHelper::class); + $instance->exporterManager = $container->get(ExporterManager::class); $instance->setMessenger($container->get('messenger')); $instance->session = $container->get('session'); @@ -71,12 +74,10 @@ public function index(Request $request, NodeInterface $node) { $enabled = $config->get('event_exporters_enabled'); $exporters = $this->exporterManager->getEventExporters($enabled); - $exporterForms = array_map(function (AbstractExporter $exporter) use ($node) { - return [ - 'name' => $exporter->getName(), - 'form' => $this->buildForm($node, $exporter), - ]; - }, $exporters); + $exporterForms = array_map(fn(AbstractExporter $exporter) => [ + 'name' => $exporter->getName(), + 'form' => $this->buildForm($node, $exporter), + ], $exporters); return [ '#theme' => 'itk_pretix_event_exporters', diff --git a/src/Controller/PretixWebhookController.php b/src/Controller/PretixWebhookController.php index 02d2ad4..faaa181 100644 --- a/src/Controller/PretixWebhookController.php +++ b/src/Controller/PretixWebhookController.php @@ -50,11 +50,12 @@ class PretixWebhookController extends ControllerBase { /** * {@inheritdoc} */ + #[\Override] public static function create(ContainerInterface $container) { $instance = parent::create($container); - $instance->orderHelper = $container->get('itk_pretix.order_helper'); - $instance->nodeHelper = $container->get('itk_pretix.node_helper'); - $instance->eventHelper = $container->get('itk_pretix.event_helper'); + $instance->orderHelper = $container->get(OrderHelper::class); + $instance->nodeHelper = $container->get(NodeHelper::class); + $instance->eventHelper = $container->get(EventHelper::class); $instance->database = $container->get('database'); return $instance; @@ -80,12 +81,10 @@ public function main(Request $request) { } $action = $payload['action'] ?? NULL; - switch ($action) { - case OrderHelper::PRETIX_EVENT_ORDER_PAID: - case OrderHelper::PRETIX_EVENT_ORDER_CANCELED: - $this->handleOrderUpdated($payload, $action); - break; - } + match ($action) { + OrderHelper::PRETIX_EVENT_ORDER_PAID, OrderHelper::PRETIX_EVENT_ORDER_CANCELED => $this->handleOrderUpdated($payload, $action), + default => new JsonResponse($payload), + }; return new JsonResponse($payload); } diff --git a/src/Exporter/AbstractExporter.php b/src/Exporter/AbstractExporter.php index 8108322..55a7435 100644 --- a/src/Exporter/AbstractExporter.php +++ b/src/Exporter/AbstractExporter.php @@ -44,6 +44,7 @@ abstract class AbstractExporter extends FormBase implements ExporterInterface { /** * {@inheritdoc} */ + #[\Override] public function getId() { if (NULL === static::$id) { throw new \RuntimeException(sprintf('Property id not defined in class %s', static::class)); @@ -54,6 +55,7 @@ public function getId() { /** * {@inheritdoc} */ + #[\Override] public function getName() { if (NULL === static::$name) { throw new \RuntimeException(sprintf('Property name not defined in class %s', static::class)); @@ -64,6 +66,7 @@ public function getName() { /** * {@inheritdoc} */ + #[\Override] public function getFormId() { return 'itk_pretix_exporter_' . $this->getId(); } @@ -71,6 +74,7 @@ public function getFormId() { /** * {@inheritdoc} */ + #[\Override] public function submitForm(array &$form, FormStateInterface $form_state) { throw new \RuntimeException(); } @@ -78,6 +82,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { /** * Process input parameters. */ + #[\Override] public function processInputParameters(array $parameters) { unset($parameters['op'], $parameters['form_build_id'], $parameters['form_token'], $parameters['form_id']); @@ -87,6 +92,7 @@ public function processInputParameters(array $parameters) { /** * Get pretix client. */ + #[\Override] public function setPretixClient(Client $client) { $this->client = $client; @@ -96,6 +102,7 @@ public function setPretixClient(Client $client) { /** * Set event info. */ + #[\Override] public function setEventInfo(array $eventInfo) { $this->eventInfo = $eventInfo; @@ -164,9 +171,7 @@ private function getCheckInLists() { if (!isset(self::$checkInLists[$event])) { $defaultName = 'exporter check-in list (do not delete)'; - $isDefaultList = static function (CheckInList $list) use ($defaultName) { - return $defaultName === $list->getName(); - }; + $isDefaultList = static fn(CheckInList $list) => $defaultName === $list->getName(); $checkInLists = $this->client->getCheckInLists($event); $defaultList = $checkInLists->filter($isDefaultList)->first(); if (!$defaultList) { @@ -179,9 +184,7 @@ private function getCheckInLists() { $checkInLists->add($defaultList); } - [$head, $tail] = $checkInLists->partition(static function ($key, $list) use ($isDefaultList) { - return $isDefaultList($list); - }); + [$head, $tail] = $checkInLists->partition(static fn($key, $list) => $isDefaultList($list)); // Make sure that the default list is first in collection. self::$checkInLists[$event] = new ArrayCollection( diff --git a/src/Exporter/CheckInListExporter.php b/src/Exporter/CheckInListExporter.php index d1d35b7..5bfd75f 100644 --- a/src/Exporter/CheckInListExporter.php +++ b/src/Exporter/CheckInListExporter.php @@ -21,6 +21,7 @@ class CheckInListExporter extends AbstractExporter { /** * {@inheritdoc} */ + #[\Override] public function buildForm(array $form, FormStateInterface $form_state) { $formats = [ 'xlsx' => $this->t('Excel (.xlsx)'), @@ -48,6 +49,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { /** * {@inheritdoc} */ + #[\Override] public function processInputParameters(array $parameters) { $parameters = parent::processInputParameters($parameters); // Make sure that questions is set. diff --git a/src/Exporter/CheckInListPdfExporter.php b/src/Exporter/CheckInListPdfExporter.php index 46310f8..c1443c2 100644 --- a/src/Exporter/CheckInListPdfExporter.php +++ b/src/Exporter/CheckInListPdfExporter.php @@ -21,6 +21,7 @@ class CheckInListPdfExporter extends CheckInListExporter { /** * {@inheritdoc} */ + #[\Override] public function buildForm(array $form, FormStateInterface $form_state) { $form = parent::buildForm($form, $form_state); unset($form['_format']); @@ -31,6 +32,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { /** * {@inheritdoc} */ + #[\Override] public function processInputParameters(array $parameters) { $parameters = parent::processInputParameters($parameters); // Make sure that questions is set. diff --git a/src/Exporter/Manager.php b/src/Exporter/Manager.php index 9a03c73..803fe2e 100644 --- a/src/Exporter/Manager.php +++ b/src/Exporter/Manager.php @@ -2,8 +2,10 @@ namespace Drupal\itk_pretix\Exporter; +use Drupal\Core\File\FileExists; use Drupal\Core\File\FileSystem; -use Drupal\Core\File\FileUrlGenerator; +use Drupal\Core\File\FileSystemInterface; +use Drupal\Core\File\FileUrlGeneratorInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\itk_pretix\Access\AccessCheck; @@ -15,7 +17,7 @@ * Exporter manager. */ class Manager implements ManagerInterface { - private const EXPORTER_RESULT_BASE_URL = 'private://itk_pretix/exporters'; + private const string EXPORTER_RESULT_BASE_URL = 'private://itk_pretix/exporters'; use StringTranslationTrait; @@ -37,15 +39,16 @@ class Manager implements ManagerInterface { * Constructor. */ public function __construct( - private readonly FileSystem $fileSystem, + private readonly FileSystemInterface $fileSystem, private readonly AccessCheck $accessCheck, private readonly AccountInterface $currentUser, - private readonly FileUrlGenerator $fileUrlGenerator + private readonly FileUrlGeneratorInterface $fileUrlGenerator, ) {} /** * Add an event exporter. */ + #[\Override] public function addEventExporter(ExporterInterface $exporter, $priority = 0) { $this->eventExporters[$exporter->getId()] = $exporter; $this->eventExporterForms[$exporter->getFormId()] = $exporter; @@ -56,15 +59,15 @@ public function addEventExporter(ExporterInterface $exporter, $priority = 0) { /** * Get event exporters. */ - public function getEventExporters(array $ids = NULL) { - return array_filter($this->eventExporters, static function (ExporterInterface $exporter) use ($ids) { - return NULL === $ids || in_array($exporter->getId(), $ids, TRUE); - }); + #[\Override] + public function getEventExporters(?array $ids = NULL) { + return array_filter($this->eventExporters, static fn(ExporterInterface $exporter) => NULL === $ids || in_array($exporter->getId(), $ids, TRUE)); } /** * Get event exporter. */ + #[\Override] public function getEventExporter(string $id) { return $this->eventExporters[$id] ?? NULL; } @@ -72,17 +75,18 @@ public function getEventExporter(string $id) { /** * Save exporter result to local file system. */ + #[\Override] public function saveExporterResult(NodeInterface $node, Response $response) { $header = $response->getHeaderLine('content-disposition'); if (preg_match('/filename="(?[^"]+)"/', $header, $matches)) { $filename = $matches['filename']; $url = $this->getExporterResultFileUrl($node, $filename); - $directory = dirname($url); + $directory = dirname((string) $url); $this->fileSystem->prepareDirectory($directory, FileSystem::CREATE_DIRECTORY); $filePath = $this->fileSystem->realpath($url); - $this->fileSystem->saveData((string) $response->getBody(), $filePath, FileSystem::EXISTS_REPLACE); - $this->fileSystem->saveData(json_encode($response->getHeaders()), $filePath . '.headers', FileSystem::EXISTS_REPLACE); + $this->fileSystem->saveData((string) $response->getBody(), $filePath, FileExists::Replace); + $this->fileSystem->saveData(json_encode($response->getHeaders()), $filePath . '.headers', FileExists::Replace); return $this->fileUrlGenerator->generateAbsoluteString($url); } @@ -96,6 +100,7 @@ public function saveExporterResult(NodeInterface $node, Response $response) { * @param string $uri * The file uri. */ + #[\Override] public function fileDownload(string $uri) { $info = $this->getExporterResultFileUrlInfo($uri); if (isset($info['nid'])) { diff --git a/src/Exporter/ManagerInterface.php b/src/Exporter/ManagerInterface.php index e61e22f..750bfd6 100644 --- a/src/Exporter/ManagerInterface.php +++ b/src/Exporter/ManagerInterface.php @@ -24,7 +24,7 @@ public function addEventExporter(ExporterInterface $exporter, $priority = 0); * @return array|ExporterInterface[] * The exporters. */ - public function getEventExporters(array $ids = NULL); + public function getEventExporters(?array $ids = NULL); /** * Get event exporter. diff --git a/src/Exporter/OrderListExporter.php b/src/Exporter/OrderListExporter.php index b79375a..1184572 100644 --- a/src/Exporter/OrderListExporter.php +++ b/src/Exporter/OrderListExporter.php @@ -21,6 +21,7 @@ class OrderListExporter extends AbstractExporter { /** * {@inheritdoc} */ + #[\Override] public function buildForm(array $form, FormStateInterface $form_state) { $formats = [ 'xlsx' => 'xlsx', diff --git a/src/Form/PretixConfigForm.php b/src/Form/PretixConfigForm.php index a227028..ca1ca14 100644 --- a/src/Form/PretixConfigForm.php +++ b/src/Form/PretixConfigForm.php @@ -8,6 +8,7 @@ use Drupal\itk_pretix\Exporter\ManagerInterface as ExporterManagerInterface; use Drupal\itk_pretix\Pretix\EventHelper; use Drupal\itk_pretix\Pretix\OrderHelper; +use Drupal\itk_pretix\Exporter\Manager as ExporterManager; use ItkDev\Pretix\Api\Client; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -15,52 +16,36 @@ * A configuration form for the pretix module. */ final class PretixConfigForm extends ConfigFormBase { - /** - * The event helper. - * - * @var \Drupal\itk_pretix\Pretix\EventHelper - */ - private $eventHelper; - - /** - * The order helper. - * - * @var \Drupal\itk_pretix\Pretix\OrderHelper - */ - private $orderHelper; - - /** - * The exporter manager. - * - * @var ExporterManager - */ - private $exporterManager; /** * {@inheritDoc} */ - public function __construct(ConfigFactoryInterface $config_factory, EventHelper $eventHelper, OrderHelper $orderHelper, ExporterManagerInterface $exporterManager) { + public function __construct( + ConfigFactoryInterface $config_factory, + private readonly EventHelper $eventHelper, + private readonly OrderHelper $orderHelper, + private readonly ExporterManagerInterface $exporterManager, + ) { parent::__construct($config_factory); - $this->eventHelper = $eventHelper; - $this->orderHelper = $orderHelper; - $this->exporterManager = $exporterManager; } /** * {@inheritdoc} */ + #[\Override] public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('itk_pretix.event_helper'), - $container->get('itk_pretix.order_helper'), - $container->get('itk_pretix.exporter_manager') + $container->get(EventHelper::class), + $container->get(OrderHelper::class), + $container->get(ExporterManager::class) ); } /** * {@inheritdoc} */ + #[\Override] protected function getEditableConfigNames() { return [ 'itk_pretix.pretixconfig', @@ -70,6 +55,7 @@ protected function getEditableConfigNames() { /** * {@inheritdoc} */ + #[\Override] public function getFormId() { return 'pretix_config_form'; } @@ -77,6 +63,7 @@ public function getFormId() { /** * {@inheritdoc} */ + #[\Override] public function buildForm(array $form, FormStateInterface $form_state) { $config = $this->config('itk_pretix.pretixconfig'); @@ -149,6 +136,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { /** * {@inheritdoc} */ + #[\Override] public function submitForm(array &$form, FormStateInterface $form_state) { parent::submitForm($form, $form_state); @@ -165,6 +153,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { /** * {@inheritdoc} */ + #[\Override] public function validateForm(array &$form, FormStateInterface $form_state) { parent::validateForm($form, $form_state); @@ -175,7 +164,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) { 'api_token' => $form_state->getValue('api_token'), ]); } - catch (\Exception $exception) { + catch (\Exception) { $form_state->setErrorByName('pretix_url', $this->t('Cannot create pretix api client')); return; } @@ -183,19 +172,19 @@ public function validateForm(array &$form, FormStateInterface $form_state) { try { $client->getOrganizers(); } - catch (\Exception $exception) { + catch (\Exception) { $form_state->setErrorByName('pretix_url', $this->t('Cannot connect to pretix api')); return; } - $templateEventSlugs = array_unique(array_filter(array_map('trim', explode(PHP_EOL, $form_state->getValue('template_event_slugs'))))); + $templateEventSlugs = array_unique(array_filter(array_map('trim', explode(PHP_EOL, (string) $form_state->getValue('template_event_slugs'))))); $templateEvents = []; foreach ($templateEventSlugs as $eventSlug) { try { $event = $client->getEvent($eventSlug); $templateEvents[$event->getSlug()] = $event; } - catch (\Exception $exception) { + catch (\Exception) { } } @@ -231,7 +220,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) { $this->orderHelper->ensureWebhook($client); $this->messenger->addStatus($this->t('pretix webhook created')); } - catch (\Exception $exception) { + catch (\Exception) { $form_state->setErrorByName('pretix_url', $this->t('Cannot create webhook in pretix')); return; } diff --git a/src/NodeHelper.php b/src/NodeHelper.php index b7830f4..194c270 100644 --- a/src/NodeHelper.php +++ b/src/NodeHelper.php @@ -40,7 +40,7 @@ public function __construct( private readonly EventHelper $eventHelper, private readonly EntityTypeManagerInterface $entityTypeManager, private readonly ModuleHandlerInterface $moduleHandler, - MessengerInterface $messenger + MessengerInterface $messenger, ) { $this->setMessenger($messenger); } @@ -117,7 +117,7 @@ public function getTemplateEvents(NodeInterface $node): ArrayCollection|Collecti $event = $client->getEvent($slug); $events[] = $event; } - catch (\Exception $exception) { + catch (\Exception) { } } @@ -226,7 +226,7 @@ private function getPretixDates(NodeInterface $node): ?FieldItemListInterface { if (NULL !== $items) { foreach ($items as $item) { - foreach (['time_from', 'time_to'] as $key) { + foreach (['registration_deadline', 'time_from', 'time_to'] as $key) { if (isset($item->{$key}) && is_string($item->{$key})) { $item->{$key} = new DrupalDateTime($item->{$key}); } diff --git a/src/Plugin/Field/FieldFormatter/PretixDateFormatter.php b/src/Plugin/Field/FieldFormatter/PretixDateFormatter.php index b90494c..5ac372d 100644 --- a/src/Plugin/Field/FieldFormatter/PretixDateFormatter.php +++ b/src/Plugin/Field/FieldFormatter/PretixDateFormatter.php @@ -22,24 +22,26 @@ */ final class PretixDateFormatter extends FormatterBase { - /** - * Event helper. - * - * @var \Drupal\itk_pretix\Pretix\EventHelper - */ - private EventHelper $eventHelper; - /** * Class constructor. */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, EventHelper $eventHelper) { + public function __construct( + $plugin_id, + $plugin_definition, + FieldDefinitionInterface $field_definition, + array $settings, + $label, + $view_mode, + array $third_party_settings, + private readonly EventHelper $eventHelper, + ) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); - $this->eventHelper = $eventHelper; } /** * {@inheritdoc} */ + #[\Override] public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $plugin_id, @@ -49,13 +51,14 @@ public static function create(ContainerInterface $container, array $configuratio $configuration['label'], $configuration['view_mode'], $configuration['third_party_settings'], - $container->get('itk_pretix.event_helper') + $container->get(EventHelper::class) ); } /** * {@inheritdoc} */ + #[\Override] public function viewElements(FieldItemListInterface $items, $langcode) { $elements = []; @@ -67,9 +70,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) { if (NULL !== $sortField) { // Sort ascending. - usort($dates, static function (PretixDate $a, PretixDate $b) use ($sortField) { - return $a->{$sortField} <=> $b->{$sortField}; - }); + usort($dates, static fn(PretixDate $a, PretixDate $b) => $a->{$sortField} <=> $b->{$sortField}); // Reverse if requested. if (0 === strcasecmp('desc', $sortDirection)) { $dates = array_reverse($dates); @@ -83,6 +84,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) { 'entity' => $items->getEntity(), 'location' => $item->location, 'address' => $item->address, + 'registration_deadline' => $item->registration_deadline, 'time_from' => $item->time_from, 'time_to' => $item->time_to, 'spots' => $item->spots, diff --git a/src/Plugin/Field/FieldType/PretixDate.php b/src/Plugin/Field/FieldType/PretixDate.php index 9199743..ed448f8 100644 --- a/src/Plugin/Field/FieldType/PretixDate.php +++ b/src/Plugin/Field/FieldType/PretixDate.php @@ -24,6 +24,7 @@ * @property string uuid * @property string location * @property string address + * @property DateTimeComputed registration_deadline * @property DateTimeComputed time_from * @property DateTimeComputed time_to * @property int spots @@ -34,6 +35,7 @@ class PretixDate extends FieldItemBase { /** * {@inheritdoc} */ + #[\Override] public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { $properties['uuid'] = DataDefinition::create('string') ->setLabel(t('UUID')) @@ -45,6 +47,16 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel ->setLabel(new TranslatableMarkup('Address')) ->setRequired(TRUE); + $properties['registration_deadline_value'] = DataDefinition::create('datetime_iso8601') + ->setLabel(t('Registration deadline value')) + ->setRequired(TRUE); + $properties['registration_deadline'] = DataDefinition::create('any') + ->setLabel(t('Computed registration deadline')) + ->setDescription(t('The computed registration deadline DateTime object.')) + ->setComputed(TRUE) + ->setClass(DateTimeComputed::class) + ->setSetting('date source', 'registration_deadline_value'); + $properties['time_from_value'] = DataDefinition::create('datetime_iso8601') ->setLabel(t('Time from value')) ->setRequired(TRUE); @@ -76,6 +88,7 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel /** * {@inheritdoc} */ + #[\Override] public static function schema(FieldStorageDefinitionInterface $field_definition) { $schema = [ 'columns' => [ @@ -91,6 +104,11 @@ public static function schema(FieldStorageDefinitionInterface $field_definition) 'type' => 'varchar', 'length' => 255, ], + 'registration_deadline_value' => [ + 'description' => 'The registration deadline value.', + 'type' => 'varchar', + 'length' => 20, + ], 'time_from_value' => [ 'description' => 'The time from value.', 'type' => 'varchar', @@ -124,6 +142,7 @@ public static function schema(FieldStorageDefinitionInterface $field_definition) /** * {@inheritdoc} */ + #[\Override] public function isEmpty() { $location = $this->get('location')->getValue(); $timeFrom = $this->get('time_from_value')->getValue(); @@ -134,6 +153,7 @@ public function isEmpty() { /** * {@inheritdoc} */ + #[\Override] public function preSave() { if (empty($this->get('uuid')->getValue())) { $this->get('uuid')->setValue(\Drupal::service('uuid')->generate()); @@ -147,7 +167,7 @@ public function preSave() { $this->addData(['coordinates' => $results[0]->adgangspunkt->koordinater]); } } - catch (\Exception $exception) { + catch (\Exception) { } } } diff --git a/src/Plugin/Field/FieldType/PretixEventSettings.php b/src/Plugin/Field/FieldType/PretixEventSettings.php index 5676ccc..e233fc6 100644 --- a/src/Plugin/Field/FieldType/PretixEventSettings.php +++ b/src/Plugin/Field/FieldType/PretixEventSettings.php @@ -25,9 +25,10 @@ class PretixEventSettings extends FieldItemBase { /** * {@inheritdoc} */ + #[\Override] public static function propertyDefinitions( - FieldStorageDefinitionInterface $field_definition - ) { + FieldStorageDefinitionInterface $field_definition, + ) { $properties['template_event'] = DataDefinition::create('string') ->setLabel(new TranslatableMarkup('Template event')) ->setRequired(TRUE); @@ -41,9 +42,10 @@ public static function propertyDefinitions( /** * {@inheritdoc} */ + #[\Override] public static function schema( - FieldStorageDefinitionInterface $field_definition - ) { + FieldStorageDefinitionInterface $field_definition, + ) { return [ 'columns' => [ 'template_event' => [ @@ -61,6 +63,7 @@ public static function schema( /** * {@inheritdoc} */ + #[\Override] public function isEmpty() { return FALSE; } diff --git a/src/Plugin/Field/FieldWidget/PretixDateWidget.php b/src/Plugin/Field/FieldWidget/PretixDateWidget.php index cd1f8ec..34ffac1 100644 --- a/src/Plugin/Field/FieldWidget/PretixDateWidget.php +++ b/src/Plugin/Field/FieldWidget/PretixDateWidget.php @@ -28,24 +28,24 @@ */ final class PretixDateWidget extends WidgetBase { - /** - * The event helper. - * - * @var \Drupal\itk_pretix\Pretix\EventHelper - */ - private EventHelper $eventHelper; - /** * Date widget constructor. */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EventHelper $eventHelper) { + public function __construct( + $plugin_id, + $plugin_definition, + FieldDefinitionInterface $field_definition, + array $settings, + array $third_party_settings, + private readonly EventHelper $eventHelper, + ) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); - $this->eventHelper = $eventHelper; } /** * {@inheritdoc} */ + #[\Override] public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $plugin_id, @@ -53,19 +53,20 @@ public static function create(ContainerInterface $container, array $configuratio $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], - $container->get('itk_pretix.event_helper') + $container->get(EventHelper::class) ); } /** * {@inheritdoc} */ + #[\Override] public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { $eventHelper = $this->eventHelper; /** @var \Drupal\itk_pretix\Plugin\Field\FieldType\PretixDate $item */ $item = $items[$delta]; - $element['#element_validate'][] = [$this, 'validate']; + $element['#element_validate'][] = $this->validate(...); $element['#attributes']['class'][] = 'pretix-date-widget'; if ($this->hideEndDate()) { $element['#attributes']['class'][] = 'hide-end-date'; @@ -98,6 +99,21 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen '#required' => $element['#required'], ]; + $element['registration_deadline_value'] = [ + '#title' => t('Registration deadline'), + '#type' => 'datetime', + '#default_value' => NULL, + '#date_increment' => 1, + '#date_timezone' => date_default_timezone_get(), + '#required' => $element['#required'], + ]; + + if ($items[$delta]->registration_deadline) { + /** @var \Drupal\Core\Datetime\DrupalDateTime $registration_deadline */ + $registration_deadline = $items[$delta]->registration_deadline; + $element['registration_deadline_value']['#default_value'] = $this->createDefaultValue($registration_deadline, $element['registration_deadline_value']['#date_timezone']); + } + $element['time_from_value'] = [ '#title' => t('Start time'), '#type' => 'datetime', @@ -216,6 +232,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen /** * {@inheritdoc} */ + #[\Override] public function massageFormValues(array $values, array $form, FormStateInterface $form_state) { // The widget form element type has transformed the value to a // DrupalDateTime object at this point. We need to convert it back to the @@ -225,6 +242,14 @@ public function massageFormValues(array $values, array $form, FormStateInterface $user_timezone = new \DateTimeZone(date_default_timezone_get()); foreach ($values as &$item) { + if (!empty($item['registration_deadline_value']) && $item['registration_deadline_value'] instanceof DrupalDateTime) { + /** @var \Drupal\Core\Datetime\DrupalDateTime $time_from */ + $registration_deadline = $item['registration_deadline_value']; + + // Adjust the date for storage. + $item['registration_deadline_value'] = $registration_deadline->setTimezone($storage_timezone)->format($storage_format); + } + if (!empty($item['time_from_value']) && $item['time_from_value'] instanceof DrupalDateTime) { /** @var \Drupal\Core\Datetime\DrupalDateTime $time_from */ $time_from = $item['time_from_value']; @@ -248,6 +273,7 @@ public function massageFormValues(array $values, array $form, FormStateInterface /** * {@inheritdoc} */ + #[\Override] public static function defaultSettings() { return [ 'hide_end_date' => FALSE, @@ -259,6 +285,7 @@ public static function defaultSettings() { /** * {@inheritdoc} */ + #[\Override] public function settingsForm(array $form, FormStateInterface $form_state) { $element['hide_end_date'] = [ '#title' => $this->t('Hide end date'), @@ -287,6 +314,7 @@ public function settingsForm(array $form, FormStateInterface $form_state) { /** * {@inheritdoc} */ + #[\Override] public function settingsSummary() { if ($this->hideEndDate()) { $summary[] = $this->t('Hide end date'); @@ -316,12 +344,13 @@ private function roundedTime($seconds) { /** * {@inheritdoc} */ + #[\Override] public function errorElement( - array $element, - ConstraintViolationInterface $error, - array $form, - FormStateInterface $form_state - ) { + array $element, + ConstraintViolationInterface $error, + array $form, + FormStateInterface $form_state, + ) { $propertyPath = preg_replace('/^\d+\./', '', $error->getPropertyPath()); return $element[$propertyPath] ?? $element; } @@ -341,12 +370,17 @@ public function errorElement( * The complete form structure. */ public function validate(array &$element, FormStateInterface $form_state, array &$complete_form) { - $time_from = $element['time_from_value']['#value']['object']; - $time_to = $element['time_to_value']['#value']['object']; + $time_from = $element['time_from_value']['#value']['object'] ?? NULL; + $time_to = $element['time_to_value']['#value']['object'] ?? NULL; if ($time_from instanceof DrupalDateTime && $time_to instanceof DrupalDateTime && $time_to < $time_from) { $form_state->setError($element['time_to_value'], $this->t('The end time cannot be before the start time')); } + + $registration_deadline = $element['registration_deadline_value']['#value']['object'] ?? NULL; + if ($registration_deadline instanceof DrupalDateTime && $time_from instanceof DrupalDateTime && $time_from < $registration_deadline) { + $form_state->setError($element['registration_deadline_value'], $this->t('The registration deadline must be before the start time')); + } } /** diff --git a/src/Plugin/Field/FieldWidget/PretixEventSettingsWidget.php b/src/Plugin/Field/FieldWidget/PretixEventSettingsWidget.php index c570b26..7063889 100644 --- a/src/Plugin/Field/FieldWidget/PretixEventSettingsWidget.php +++ b/src/Plugin/Field/FieldWidget/PretixEventSettingsWidget.php @@ -24,32 +24,25 @@ */ final class PretixEventSettingsWidget extends WidgetBase { - /** - * The event helper. - * - * @var \Drupal\itk_pretix\Pretix\EventHelper - */ - private EventHelper $eventHelper; - - /** - * Thee node helper. - * - * @var \Drupal\itk_pretix\NodeHelper - */ - private NodeHelper $nodeHelper; - /** * Date widget constructor. */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EventHelper $eventHelper, NodeHelper $nodeHelper) { + public function __construct( + $plugin_id, + $plugin_definition, + FieldDefinitionInterface $field_definition, + array $settings, + array $third_party_settings, + private readonly EventHelper $eventHelper, + private readonly NodeHelper $nodeHelper, + ) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); - $this->eventHelper = $eventHelper; - $this->nodeHelper = $nodeHelper; } /** * {@inheritdoc} */ + #[\Override] public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $plugin_id, @@ -57,21 +50,22 @@ public static function create(ContainerInterface $container, array $configuratio $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], - $container->get('itk_pretix.event_helper'), - $container->get('itk_pretix.node_helper') + $container->get(EventHelper::class), + $container->get(NodeHelper::class) ); } /** * {@inheritdoc} */ + #[\Override] public function formElement( - FieldItemListInterface $items, - $delta, - array $element, - array &$form, - FormStateInterface $form_state - ) { + FieldItemListInterface $items, + $delta, + array $element, + array &$form, + FormStateInterface $form_state, + ) { /** @var \Drupal\node\Entity\Node $node */ $node = $items->getParent()->getEntity(); $helper = $this->nodeHelper; diff --git a/src/Plugin/Validation/Constraint/PretixDateConstraintValidator.php b/src/Plugin/Validation/Constraint/PretixDateConstraintValidator.php index 5c7ae82..fd222e6 100644 --- a/src/Plugin/Validation/Constraint/PretixDateConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/PretixDateConstraintValidator.php @@ -14,6 +14,7 @@ class PretixDateConstraintValidator extends ConstraintValidator { /** * {@inheritdoc} */ + #[\Override] public function validate($item, Constraint $constraint) { if (!$item instanceof PretixDate || !$constraint instanceof PretixDateConstraint) { return; diff --git a/src/Pretix/AbstractHelper.php b/src/Pretix/AbstractHelper.php index c7f79d0..9cdef3d 100644 --- a/src/Pretix/AbstractHelper.php +++ b/src/Pretix/AbstractHelper.php @@ -43,7 +43,7 @@ abstract class AbstractHelper { public function __construct( private readonly Connection $database, private readonly ConfigFactoryInterface $configFactory, - private readonly LoggerChannelFactoryInterface $loggerFactory + private readonly LoggerChannelFactoryInterface $loggerFactory, ) { } @@ -94,7 +94,7 @@ public function getPretixClient(NodeInterface $node): Client { * @return array * The configuration. */ - public function getPretixConfiguration(NodeInterface $node = NULL): array { + public function getPretixConfiguration(?NodeInterface $node = NULL): array { $config = $this->configFactory->get('itk_pretix.pretixconfig'); // @todo Handle node, e.g. to get user specific configuration. @@ -379,7 +379,7 @@ public function getPretixEventUrl($node, $path = ''): ?string { /** * Handle a pretix api client exception. */ - protected function clientException(string $message, \Exception $clientException = NULL): SynchronizeException { + protected function clientException(string $message, ?\Exception $clientException = NULL): SynchronizeException { // @todo Log the exception. if (NULL === $clientException) { $this->loggerFactory->get('itk_pretix')->error($message); diff --git a/src/Pretix/EventHelper.php b/src/Pretix/EventHelper.php index a68575e..e3f04b8 100644 --- a/src/Pretix/EventHelper.php +++ b/src/Pretix/EventHelper.php @@ -24,20 +24,6 @@ class EventHelper extends AbstractHelper { public const DATETIME_FORMAT = \DateTime::ATOM; - /** - * The order helper. - * - * @var \Drupal\itk_pretix\Pretix\OrderHelper - */ - private OrderHelper $orderHelper; - - /** - * The module handler interface. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - private ModuleHandlerInterface $moduleHandler; - /** * Constructor. * @@ -56,12 +42,10 @@ public function __construct( Connection $database, ConfigFactoryInterface $configFactory, LoggerChannelFactoryInterface $loggerFactory, - OrderHelper $orderHelper, - ModuleHandlerInterface $moduleHandler + private readonly OrderHelper $orderHelper, + private readonly ModuleHandlerInterface $moduleHandler, ) { parent::__construct($database, $configFactory, $loggerFactory); - $this->orderHelper = $orderHelper; - $this->moduleHandler = $moduleHandler; } /** @@ -203,7 +187,7 @@ public function synchronizePretixSubEvents(Event $event, NodeInterface $node, Fi $pretixSubEventIds[] = $subEvent->getId(); } } - catch (\Exception $exception) { + catch (\Exception) { // @todo Do something clever here. } @@ -237,7 +221,7 @@ private function synchronizePretixSubEvent(PretixDate $item, Event $event, NodeI $templateSubEvents = $client->getSubEvents($templateEvent); } catch (\Exception $exception) { - throw $this->clientException($this->t('Cannot get template event sub-events'), $exception->getCode(), $exception); + throw $this->clientException($this->t('Cannot get template event sub-events'), $exception->getCode()); } if (0 === $templateSubEvents->count()) { throw $this->clientException($this->t('Cannot get template event sub-events')); @@ -290,7 +274,7 @@ private function synchronizePretixSubEvent(PretixDate $item, Event $event, NodeI 'active' => TRUE, 'is_public' => TRUE, 'date_admission' => NULL, - 'presale_end' => NULL, + 'presale_end' => $this->formatDate($item->registration_deadline), 'seating_plan' => NULL, 'seat_category_mapping' => (object) [], ]); @@ -388,9 +372,7 @@ private function synchronizePretixSubEvent(PretixDate $item, Event $event, NodeI $availabilities = $this->orderHelper ->setPretixClient($client) ->getSubEventAvailabilities($subEvent); - $subEventData['availability'] = $availabilities->map(static function (Quota $quota) { - return $quota->toArray(); - })->toArray(); + $subEventData['availability'] = $availabilities->map(static fn(Quota $quota) => $quota->toArray())->toArray(); } catch (\Exception $exception) { $exception->getCode(); @@ -523,7 +505,7 @@ public function validateTemplateEvent(Event $event, Client $client) { try { $subEvents = $client->getSubEvents($event); } - catch (\Exception $exception) { + catch (\Exception) { return [ 'event_slug' => t('Cannot get sub-events.'), ]; @@ -539,7 +521,7 @@ public function validateTemplateEvent(Event $event, Client $client) { try { $quotas = $client->getQuotas($event, ['subevent' => $subEvent->getId()]); } - catch (\Exception $exception) { + catch (\Exception) { return [ 'event_slug' => t('Cannot get sub-event quotas.'), ]; @@ -601,7 +583,7 @@ public function runExporter(NodeInterface $node, string $identifier, array $para throw new ExporterException($response->getReasonPhrase()); } - return json_decode($response->getBody(), TRUE); + return json_decode((string) $response->getBody(), TRUE); } /** @@ -668,7 +650,7 @@ private function getEventSlug(NodeInterface $node) { $template = $configuration['pretix_event_slug_template'] ?? '!nid'; // Make sure that node id is used in template. - if (FALSE === strpos($template, '!nid')) { + if (!str_contains((string) $template, '!nid')) { $template .= '-!nid'; } @@ -715,7 +697,7 @@ private function getLocation(PretixDate $item) { * * @throws \Exception */ - private function getDate($value) { + private function getDate(mixed $value) { if (NULL === $value) { return NULL; } diff --git a/src/Pretix/OrderHelper.php b/src/Pretix/OrderHelper.php index 1da0a9f..82d7127 100644 --- a/src/Pretix/OrderHelper.php +++ b/src/Pretix/OrderHelper.php @@ -154,7 +154,7 @@ private function indexCollection(Collection $collection, string $property) { * * @throws \Exception */ - public function getOrderLines($order) { + public function getOrderLines($order): never { throw new \RuntimeException(__METHOD__ . ' not implemented'); } @@ -164,7 +164,7 @@ public function getOrderLines($order) { * @param \Drupal\node\NodeInterface $node * The node. */ - public function getAvailability(NodeInterface $node) { + public function getAvailability(NodeInterface $node): never { throw new \RuntimeException(__METHOD__ . ' not implemented'); } diff --git a/src/ProxyClass/Exporter/CheckInListExporter.php b/src/ProxyClass/Exporter/CheckInListExporter.php index ed059cc..591a565 100644 --- a/src/ProxyClass/Exporter/CheckInListExporter.php +++ b/src/ProxyClass/Exporter/CheckInListExporter.php @@ -1,8 +1,8 @@ lazyLoadItself()->__wakeup(); } - /** - * {@inheritdoc} - */ - public function setLinkGenerator(\Drupal\Core\Utility\LinkGeneratorInterface $generator) - { - return $this->lazyLoadItself()->setLinkGenerator($generator); - } - /** * {@inheritdoc} */ @@ -235,14 +227,6 @@ public function setStringTranslation(\Drupal\Core\StringTranslation\TranslationI return $this->lazyLoadItself()->setStringTranslation($translation); } - /** - * {@inheritdoc} - */ - public function setUrlGenerator(\Drupal\Core\Routing\UrlGeneratorInterface $generator) - { - return $this->lazyLoadItself()->setUrlGenerator($generator); - } - } } diff --git a/src/ProxyClass/Exporter/CheckInListPdfExporter.php b/src/ProxyClass/Exporter/CheckInListPdfExporter.php index 0c17707..755aa6a 100644 --- a/src/ProxyClass/Exporter/CheckInListPdfExporter.php +++ b/src/ProxyClass/Exporter/CheckInListPdfExporter.php @@ -1,8 +1,8 @@ lazyLoadItself()->__wakeup(); } - /** - * {@inheritdoc} - */ - public function setLinkGenerator(\Drupal\Core\Utility\LinkGeneratorInterface $generator) - { - return $this->lazyLoadItself()->setLinkGenerator($generator); - } - /** * {@inheritdoc} */ @@ -235,14 +227,6 @@ public function setStringTranslation(\Drupal\Core\StringTranslation\TranslationI return $this->lazyLoadItself()->setStringTranslation($translation); } - /** - * {@inheritdoc} - */ - public function setUrlGenerator(\Drupal\Core\Routing\UrlGeneratorInterface $generator) - { - return $this->lazyLoadItself()->setUrlGenerator($generator); - } - } } diff --git a/src/ProxyClass/Exporter/Manager.php b/src/ProxyClass/Exporter/Manager.php index 2b45cce..5ae48a8 100644 --- a/src/ProxyClass/Exporter/Manager.php +++ b/src/ProxyClass/Exporter/Manager.php @@ -1,8 +1,8 @@ lazyLoadItself()->getEventExporters($ids); } @@ -86,7 +86,7 @@ public function getEventExporters(array $ids = NULL) /** * {@inheritdoc} */ - public function getEventExporter($id) + public function getEventExporter(string $id) { return $this->lazyLoadItself()->getEventExporter($id); } @@ -102,7 +102,7 @@ public function saveExporterResult(\Drupal\node\NodeInterface $node, \GuzzleHttp /** * {@inheritdoc} */ - public function fileDownload($uri) + public function fileDownload(string $uri) { return $this->lazyLoadItself()->fileDownload($uri); } diff --git a/src/ProxyClass/Exporter/OrderListExporter.php b/src/ProxyClass/Exporter/OrderListExporter.php index c09dc3b..dfe38f1 100644 --- a/src/ProxyClass/Exporter/OrderListExporter.php +++ b/src/ProxyClass/Exporter/OrderListExporter.php @@ -1,8 +1,8 @@ lazyLoadItself()->__wakeup(); } - /** - * {@inheritdoc} - */ - public function setLinkGenerator(\Drupal\Core\Utility\LinkGeneratorInterface $generator) - { - return $this->lazyLoadItself()->setLinkGenerator($generator); - } - /** * {@inheritdoc} */ @@ -235,14 +227,6 @@ public function setStringTranslation(\Drupal\Core\StringTranslation\TranslationI return $this->lazyLoadItself()->setStringTranslation($translation); } - /** - * {@inheritdoc} - */ - public function setUrlGenerator(\Drupal\Core\Routing\UrlGeneratorInterface $generator) - { - return $this->lazyLoadItself()->setUrlGenerator($generator); - } - } } diff --git a/tests/src/Functional/LoadTest.php b/tests/src/Functional/LoadTest.php index e6cc87a..653c5a3 100644 --- a/tests/src/Functional/LoadTest.php +++ b/tests/src/Functional/LoadTest.php @@ -36,6 +36,7 @@ class LoadTest extends BrowserTestBase { /** * {@inheritdoc} */ + #[\Override] protected function setUp(): void { parent::setUp(); $this->user = $this->drupalCreateUser(['administer site configuration']);