diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3f30e91f3a8367ec6c21a82dfada215efe2df678..bde71f43c8f17bdb50c802cebf5fead3424230df 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,11 +49,14 @@ include: # Docs at https://git.drupalcode.org/project/gitlab_templates/-/blob/1.0.x/includes/include.drupalci.variables.yml ################ variables: - _PHPUNIT_CONCURRENT: '1' -# _PHPUNIT_EXTRA: '-c $CI_PROJECT_DIR/$_WEB_ROOT/core --testdox --colors=always' + SKIP_CSPELL: '1' + OPT_IN_TEST_PREVIOUS_MAJOR: '0' OPT_IN_TEST_PREVIOUS_MINOR: '0' OPT_IN_TEST_NEXT_MINOR: '1' OPT_IN_TEST_NEXT_MAJOR: '1' + _PHPUNIT_CONCURRENT: '0' + _PHPUNIT_EXTRA: '-c $CI_PROJECT_DIR/$_WEB_ROOT/core --testdox --colors=always' + BROWSERTEST_OUTPUT_VERBOSE: false phpunit: extends: .phpunit-base diff --git a/file_mdm.install b/file_mdm.install index d3186a56b1a327f291fb69b8cb6ae5e644ca6c63..63ff95e493c54fc103b224edacf2f331def4df17 100644 --- a/file_mdm.install +++ b/file_mdm.install @@ -12,14 +12,14 @@ use Drupal\Core\Logger\RfcLogLevel; /** * Clear caches to discover service changes. */ -function file_mdm_update_8200() { +function file_mdm_update_8200(): void { // Empty function. } /** * Set a default for the 'Log level to use if a file does not exist' setting. */ -function file_mdm_update_8201() { +function file_mdm_update_8201(): void { $config = \Drupal::configFactory()->getEditable('file_mdm.settings'); if ($config->get('missing_file_log_level') !== NULL) { return; diff --git a/file_mdm_exif/src/ExifTagMapper.php b/file_mdm_exif/src/ExifTagMapper.php index 68eed0dd870d6e5527f4f841ce006a78b59f167e..b129314adf9022b449d311bb6fb1d80bcdcbbb7f 100644 --- a/file_mdm_exif/src/ExifTagMapper.php +++ b/file_mdm_exif/src/ExifTagMapper.php @@ -23,6 +23,8 @@ class ExifTagMapper implements ExifTagMapperInterface { * * Maps IFDs or their aliases expressed as literals to the EXIF integer * identifier. + * + * @var array<string,int> */ protected array $stringToIfdMap; @@ -30,20 +32,26 @@ class ExifTagMapper implements ExifTagMapperInterface { * The string to TAG map. * * Maps TAGs expressed as literals to the EXIF integer IFD/TAG identifiers. + * + * @var array<string, array{0: int, 1: int}> */ protected array $stringToTagMap; /** * The supported metadata 'keys'. * - * A simple array of IFD/TAG combinations, expressed as literals. + * A list of IFD/TAG combinations, expressed as literals. + * + * @var list<array{0: string, 1: string}> */ protected array $supportedKeysMap; /** * The supported IFDs. * - * A simple array of IFDs, expressed as literal/integer combinations. + * A list of IFDs, expressed as literal/integer combinations. + * + * @var list<array{0: string, 1: int}> */ protected array $supportedIfdsMap; @@ -73,6 +81,7 @@ class ExifTagMapper implements ExifTagMapperInterface { if (!isset($key[0]) || !isset($key[1])) { throw new FileMetadataException('Invalid $key array specified, must have two values', NULL, __METHOD__); } + // Deal with ifd. if (is_int($key[0])) { $ifd = $key[0]; @@ -83,6 +92,7 @@ class ExifTagMapper implements ExifTagMapperInterface { else { throw new FileMetadataException('Invalid EXIF IFD specified, must be a string or an integer', NULL, __METHOD__); } + // Deal with tag. if (is_string($key[1])) { $tag = $this->stringToTag($key[1])[1]; @@ -93,6 +103,7 @@ class ExifTagMapper implements ExifTagMapperInterface { else { throw new FileMetadataException('Invalid EXIF TAG specified, must be a string or an integer', NULL, __METHOD__); } + return ['ifd' => $ifd, 'tag' => $tag]; } @@ -101,7 +112,7 @@ class ExifTagMapper implements ExifTagMapperInterface { return $this->getSupportedIfdsMap(); } elseif (isset($options['ifd'])) { - return array_filter($this->getSupportedKeysMap(), function ($a) use ($options) { + return array_filter($this->getSupportedKeysMap(), function ($a) use ($options): bool { return strtolower($options['ifd']) === strtolower($a[0]); }); } @@ -115,8 +126,8 @@ class ExifTagMapper implements ExifTagMapperInterface { * * Builds and caches the list as needed. * - * @return array - * A simple array of IFDs, expressed as literal/integer combinations. + * @return list<array{0: string, 1: int}> + * A list of IFDs, expressed as literal/integer combinations. */ protected function getSupportedIfdsMap(): array { if (!isset($this->supportedIfdsMap)) { @@ -147,8 +158,8 @@ class ExifTagMapper implements ExifTagMapperInterface { * * Builds and caches the list as needed. * - * @return array - * A simple array of IFD/TAG combinations, expressed as literals. + * @return list<array{0: string, 1: string}> + * A list of IFD/TAG combinations, expressed as literals. */ protected function getSupportedKeysMap(): array { if (!isset($this->supportedKeysMap)) { @@ -180,8 +191,8 @@ class ExifTagMapper implements ExifTagMapperInterface { * @param string $value * A TAG literal. * - * @return array - * A simple array of with IFD and TAG, expressed as integers. + * @return array{0: int, 1: int} + * An array with IFD and TAG, expressed as integers. * * @throws \Drupal\file_mdm\FileMetadataException * When the IFD/TAG combination could not be found. @@ -199,7 +210,7 @@ class ExifTagMapper implements ExifTagMapperInterface { * * Builds and caches the list as needed. * - * @return array + * @return array<string, array{0: int, 1: int}> * An associative array where keys are TAG literals, and values a simple * array of IFD/TAG integer identifiers. */ @@ -251,7 +262,7 @@ class ExifTagMapper implements ExifTagMapperInterface { * * Builds and caches the list as needed. * - * @return array + * @return array<string,int> * An associative array where keys are IFD literals, and values the IFD * integer identifiers. */ diff --git a/file_mdm_exif/src/ExifTagMapperInterface.php b/file_mdm_exif/src/ExifTagMapperInterface.php index 60484f8c68905fccd2b4c532455d71225d619fd5..c14a78c240bf9c9d2177c226ebb5e75317a082f1 100644 --- a/file_mdm_exif/src/ExifTagMapperInterface.php +++ b/file_mdm_exif/src/ExifTagMapperInterface.php @@ -12,7 +12,7 @@ interface ExifTagMapperInterface { /** * Resolves a metadata 'key' to the default EXIF IFD and TAG. * - * @param string|array $key + * @param string|array{0: int|string, 1: int|string} $key * A metadata 'key' as passed in by the file metadata manager. It can be a * string, in which case the default IFD and TAG are returned. If it is an * array, then the first and the second array elements define respectively @@ -20,7 +20,7 @@ interface ExifTagMapperInterface { * they are converted to EXIF integer identifiers, or integers, in which * case they are returned as such. * - * @return array + * @return array{'ifd': int, 'tag': int} * An associative array with the following keys: * 'ifd' - the IFD EXIF integer identifier. * 'tag' - the TAG EXIF integer identifier. @@ -33,7 +33,7 @@ interface ExifTagMapperInterface { /** * Returns a list of default metadata 'keys' supported. * - * @param array|null $options + * @param array{'ifds'?: bool, 'ifd'?: string}|null $options * (optional) If specified, restricts the results returned. By default, all * the available EXIF IFD/TAG combinations for any IFD are returned. * If $options contains ['ifds' => TRUE], the supported IFDs are returned. @@ -41,7 +41,7 @@ interface ExifTagMapperInterface { * supported by the IFD specified by $value are returned. * If $options is NULL, no restrictions are applied. * - * @return array + * @return list<array{0: string, 1: int|string}> * A simple array. * When returning a list of supported IFDs, each array element is a simple * array with: diff --git a/file_mdm_exif/src/Plugin/FileMetadata/Exif.php b/file_mdm_exif/src/Plugin/FileMetadata/Exif.php index b8c943c3fa883918a11de69f2b16fe5f71ba380c..0993a399a29abb80228aab6c8a644450c086df50 100644 --- a/file_mdm_exif/src/Plugin/FileMetadata/Exif.php +++ b/file_mdm_exif/src/Plugin/FileMetadata/Exif.php @@ -42,6 +42,14 @@ class Exif extends FileMetadataPluginBase { */ protected PelJpeg|PelTiff|false $pelFile; + /** + * @param array<mixed> $configuration + * The plugin configuration. + * @param string $plugin_id + * The plugin id. + * @param array<mixed> $plugin_definition + * The plugin definition. + */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition); $instance->mimeTypeGuesser = $container->get('file.mime_type.guesser'); diff --git a/file_mdm_exif/tests/src/Kernel/FileMetadataExifTest.php b/file_mdm_exif/tests/src/Kernel/FileMetadataExifTest.php index 4dfd64b10064cc2ec4f0fbd488a267fb5d5f1958..9dce7b1bdd0453dd67e714c109800ba4da20dbe1 100644 --- a/file_mdm_exif/tests/src/Kernel/FileMetadataExifTest.php +++ b/file_mdm_exif/tests/src/Kernel/FileMetadataExifTest.php @@ -381,7 +381,7 @@ class FileMetadataExifTest extends FileMetadataManagerTestBase { $this->assertEquals([8, 8, 8, 8], $file_metadata->getMetadata('exif', 'BitsPerSample')['value']); $data['BitsPerSample'] = [7, 6, 5, 4]; $bps_tag = $this->container->get(ExifTagMapperInterface::class)->resolveKeyToIfdAndTag('BitsPerSample'); - $bps = new PelEntryShort($bps_tag['tag'], $data['BitsPerSample']); + $bps = new PelEntryShort($bps_tag['tag'], ...$data['BitsPerSample']); $this->assertTrue($file_metadata->setMetadata('exif', 'BitsPerSample', $bps)); $this->assertEquals($data['BitsPerSample'], $file_metadata->getMetadata('exif', 'BitsPerSample')['value']); diff --git a/file_mdm_font/src/Plugin/FileMetadata/Font.php b/file_mdm_font/src/Plugin/FileMetadata/Font.php index be4e0794eff0968a12c9e4a90b1a35351a52cec0..7865ccd9b1234b703470f05cc6e00ef9469b5caa 100644 --- a/file_mdm_font/src/Plugin/FileMetadata/Font.php +++ b/file_mdm_font/src/Plugin/FileMetadata/Font.php @@ -23,6 +23,9 @@ use FontLib\Table\Type\name; )] class Font extends FileMetadataPluginBase { + /** + * @return list<string> + */ public function getSupportedKeys(?array $options = NULL): array { return array_merge(['FontType', 'FontWeight'], array_values(name::$nameIdCodes)); } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f7df7afc29b14372cbc6d3057f7923f2b7f3cc75..32e2fd43de9a7f8c54956f0b2e94cb6d13471cb9 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,11 +1,115 @@ parameters: ignoreErrors: - - message: "#^Parameter \\#2 \\$value of class lsolesen\\\\pel\\\\PelEntryShort constructor expects int\\|null, array\\<int, int\\> given\\.$#" + message: '#^Method Drupal\\file_mdm\\Element\\FileMetadataCaching\:\:getInfo\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 - path: file_mdm_exif/tests/src/Kernel/FileMetadataExifTest.php + path: src/Element/FileMetadataCaching.php - - message: "#^Parameter \\#2 \\$message of method Drupal\\\\Core\\\\Form\\\\FormStateInterface\\:\\:setError\\(\\) expects string, Drupal\\\\Core\\\\StringTranslation\\\\TranslatableMarkup given\\.$#" + message: '#^Method Drupal\\file_mdm\\Element\\FileMetadataCaching\:\:valueCallback\(\) has parameter \$element with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Element/FileMetadataCaching.php + + - + message: '#^Method Drupal\\file_mdm\\Form\\SettingsForm\:\:buildForm\(\) has parameter \$form with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Form/SettingsForm.php + + - + message: '#^Method Drupal\\file_mdm\\Form\\SettingsForm\:\:buildForm\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Form/SettingsForm.php + + - + message: '#^Method Drupal\\file_mdm\\Form\\SettingsForm\:\:create\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 + path: src/Form/SettingsForm.php + + - + message: '#^Method Drupal\\file_mdm\\Form\\SettingsForm\:\:getEditableConfigNames\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Form/SettingsForm.php + + - + message: '#^Method Drupal\\file_mdm\\Form\\SettingsForm\:\:submitForm\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 + path: src/Form/SettingsForm.php + + - + message: '#^Method Drupal\\file_mdm\\Form\\SettingsForm\:\:submitForm\(\) has parameter \$form with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Form/SettingsForm.php + + - + message: '#^Method Drupal\\file_mdm\\Form\\SettingsForm\:\:validateForm\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 + path: src/Form/SettingsForm.php + + - + message: '#^Method Drupal\\file_mdm\\Form\\SettingsForm\:\:validateForm\(\) has parameter \$form with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Form/SettingsForm.php + + - + message: '#^\\Drupal calls should be avoided in classes, use dependency injection instead$#' + identifier: globalDrupalDependencyInjection.useDependencyInjection + count: 1 + path: src/Hook/FileMetadataHooks.php + + - + message: '#^Method Drupal\\file_mdm\\Plugin\\FileMetadata\\FileMetadataPluginBase\:\:buildConfigurationForm\(\) has parameter \$form with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Plugin/FileMetadata/FileMetadataPluginBase.php + + - + message: '#^Method Drupal\\file_mdm\\Plugin\\FileMetadata\\FileMetadataPluginBase\:\:buildConfigurationForm\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Plugin/FileMetadata/FileMetadataPluginBase.php + + - + message: '#^Method Drupal\\file_mdm\\Plugin\\FileMetadata\\FileMetadataPluginBase\:\:submitConfigurationForm\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 + path: src/Plugin/FileMetadata/FileMetadataPluginBase.php + + - + message: '#^Method Drupal\\file_mdm\\Plugin\\FileMetadata\\FileMetadataPluginBase\:\:submitConfigurationForm\(\) has parameter \$form with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Plugin/FileMetadata/FileMetadataPluginBase.php + + - + message: '#^Method Drupal\\file_mdm\\Plugin\\FileMetadata\\FileMetadataPluginBase\:\:validateConfigurationForm\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 + path: src/Plugin/FileMetadata/FileMetadataPluginBase.php + + - + message: '#^Method Drupal\\file_mdm\\Plugin\\FileMetadata\\FileMetadataPluginBase\:\:validateConfigurationForm\(\) has parameter \$form with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Plugin/FileMetadata/FileMetadataPluginBase.php + + - + message: '#^Method Drupal\\file_mdm\\Plugin\\FileMetadataPluginManager\:\:__construct\(\) has parameter \$namespaces with no value type specified in iterable type Traversable\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Plugin/FileMetadataPluginManager.php + + - + message: '#^Method Drupal\\file_mdm\\Plugin\\FileMetadataPluginManager\:\:createInstance\(\) has parameter \$configuration with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Plugin/FileMetadataPluginManager.php diff --git a/phpstan.neon b/phpstan.neon index a1f5e65d3ac78713e3ced7667fa99d5f41ae33fc..0c74ecc4609c0d87b880d3c79fc610bab3db26e7 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,7 +2,6 @@ includes: - phpstan-baseline.neon - - phar://phpstan.phar/conf/bleedingEdge.neon parameters: @@ -11,6 +10,8 @@ parameters: paths: - . + treatPhpDocTypesAsCertain: false + ignoreErrors: # Ignore common errors for now. - "#^Class .* has an uninitialized readonly property .*\\. Assign it in the constructor\\.#" diff --git a/src/Element/FileMetadataCaching.php b/src/Element/FileMetadataCaching.php index a99382e80610427526bd34384e38b67fca6a9ae8..6a268b9ca342a17d646dfd1f0eef4f4fe95e185f 100644 --- a/src/Element/FileMetadataCaching.php +++ b/src/Element/FileMetadataCaching.php @@ -45,14 +45,14 @@ class FileMetadataCaching extends FormElementBase { /** * Processes a 'file_mdm_caching' form element. * - * @param array $element + * @param array<mixed> $element * The form element to process. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. - * @param array $complete_form + * @param array<mixed> $complete_form * The complete form structure. * - * @return array + * @return array<mixed> * The processed element. */ public static function processCaching(array &$element, FormStateInterface $form_state, array &$complete_form): array { @@ -96,11 +96,11 @@ class FileMetadataCaching extends FormElementBase { /** * Form element validation handler. * - * @param array $element + * @param array<mixed> $element * The form element to process. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. - * @param array $complete_form + * @param array<mixed> $complete_form * The complete form structure. */ public static function validateCaching(array &$element, FormStateInterface $form_state, array &$complete_form): void { diff --git a/src/FileMetadataInterface.php b/src/FileMetadataInterface.php index a3aa16c84eaa2abb9f19fdab649aa6f68a8e0ca6..9946c6952c9766e283536dde3757bc8e4768f731 100644 --- a/src/FileMetadataInterface.php +++ b/src/FileMetadataInterface.php @@ -100,8 +100,8 @@ interface FileMetadataInterface { * (optional) Allows specifying additional options to control the list of * metadata keys returned. * - * @return array - * A simple array of metadata keys supported. + * @return list<string|int> + * A list of metadata keys supported. */ public function getSupportedKeys(string $metadataId, mixed $options = NULL): array; @@ -190,8 +190,8 @@ interface FileMetadataInterface { * * @param string $metadataId * The id of the FileMetadata plugin. - * @param array $tags - * (optional) An array of cache tags to save to cache. + * @param list<string> $tags + * (optional) A list of cache tags to save to cache. * * @return bool * TRUE if metadata was saved successfully, FALSE otherwise. diff --git a/src/Hook/FileMetadataHooks.php b/src/Hook/FileMetadataHooks.php index 75f2a6b5d4d3547bc54f42262b86544660738927..d6f365ee5690881003522d6269f28cf84c86dac6 100644 --- a/src/Hook/FileMetadataHooks.php +++ b/src/Hook/FileMetadataHooks.php @@ -14,19 +14,11 @@ use Drupal\file_mdm\FileMetadataManagerInterface; */ class FileMetadataHooks { - /** - * Implements hook_cache_flush(). - */ - #[Hook('cache_flush')] - function cacheFlush(): void { - // @todo this needs to delete the cache. - } - /** * Implements hook_file_delete(). */ #[Hook('file_delete')] - function fileDelete(EntityInterface $entity): void { + public function fileDelete(EntityInterface $entity): void { // Deletes any cached file metadata information upon deletion of a file // entity. assert($entity instanceof FileInterface); diff --git a/src/Plugin/FileMetadata/FileMetadataPluginBase.php b/src/Plugin/FileMetadata/FileMetadataPluginBase.php index abbd6da86bee6b0d5c36a4aee098b58cdae2e8fa..df09307983f427bc27e28b4aa6bf1e0ca4dc3d13 100644 --- a/src/Plugin/FileMetadata/FileMetadataPluginBase.php +++ b/src/Plugin/FileMetadata/FileMetadataPluginBase.php @@ -65,11 +65,11 @@ abstract class FileMetadataPluginBase extends PluginBase implements FileMetadata /** * Constructs a FileMetadataPluginBase plugin. * - * @param array $configuration + * @param array<mixed> $configuration * A configuration array containing information about the plugin instance. * @param string $plugin_id * The plugin_id for the plugin instance. - * @param array $plugin_definition + * @param array<mixed> $plugin_definition * The plugin implementation definition. * @param \Drupal\Core\Cache\CacheBackendInterface $cache * The cache service. @@ -89,6 +89,14 @@ abstract class FileMetadataPluginBase extends PluginBase implements FileMetadata parent::__construct($configuration, $plugin_id, $plugin_definition); } + /** + * @param array<mixed> $configuration + * The plugin configuration. + * @param string $plugin_id + * The plugin id. + * @param array<mixed> $plugin_definition + * The plugin definition. + */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, @@ -261,7 +269,7 @@ abstract class FileMetadataPluginBase extends PluginBase implements FileMetadata /** * Checks if file metadata should be cached. * - * @return array|bool + * @return array<mixed>|false * The caching settings array retrieved from configuration if file metadata * is cacheable, FALSE otherwise. */ diff --git a/src/Plugin/FileMetadataPluginInterface.php b/src/Plugin/FileMetadataPluginInterface.php index 7464e6410a6053b120545f6aed1f8d1426a2b4f3..06f73f05db4ece68c433d31bf93278d88bad2b6d 100644 --- a/src/Plugin/FileMetadataPluginInterface.php +++ b/src/Plugin/FileMetadataPluginInterface.php @@ -16,7 +16,7 @@ interface FileMetadataPluginInterface extends ContainerFactoryPluginInterface, P /** * Gets default configuration for this plugin. * - * @return array + * @return array<mixed> * An associative array with the default configuration. */ public static function defaultConfiguration(): array; @@ -84,12 +84,12 @@ interface FileMetadataPluginInterface extends ContainerFactoryPluginInterface, P /** * Returns a list of metadata keys supported by the plugin. * - * @param array|null $options + * @param array<mixed>|null $options * (optional) Allows specifying additional options to control the list of * metadata keys returned. If NULL, no additional options are applied. * - * @return array - * A simple array of metadata keys supported. + * @return list<mixed> + * A list of metadata keys supported. */ public function getSupportedKeys(?array $options = NULL): array; @@ -192,7 +192,7 @@ interface FileMetadataPluginInterface extends ContainerFactoryPluginInterface, P * * Uses the 'file_mdm' cache bin. * - * @param array $tags + * @param list<string> $tags * (optional) An array of cache tags to save to cache. * * @return bool