diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 187aceb1..612b7bc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,8 +65,11 @@ jobs: - name: Run PHPCS working-directory: ${{ env.DRUPAL_ROOT }} - run: | - vendor/bin/phpcs $MODULE_FOLDER --standard=Drupal --extensions=php,module,inc,install,test,info + run: vendor/bin/phpcs $MODULE_FOLDER --standard=Drupal,DrupalPractice --extensions=php,module,install + + - name: Run phpstan + working-directory: ${{ env.DRUPAL_ROOT }} + run: vendor/bin/phpstan analyze -c $MODULE_FOLDER/phpstan.neon $MODULE_FOLDER - name: Start services working-directory: ${{ env.DRUPAL_ROOT }} @@ -90,6 +93,6 @@ jobs: with: name: results path: | - ${{ env.DRUPAL_ROOT }}/sites/simpletest/browser_output/ + ${{ env.DRUPAL_ROOT }}/public/sites/simpletest/browser_output/ ${{ env.DRUPAL_ROOT }}/coverage.xml retention-days: 1 diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..161570ff --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,20 @@ +parameters: + fileExtensions: + - php + - module + - install + paths: + - ./ + excludePaths: + - vendor + level: 3 + checkMissingIterableValueType: false + treatPhpDocTypesAsCertain: false + ignoreErrors: + - + message: '#^Method Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface::dispatch\(\) invoked with 2 parameters, 1 required.#' + path: src/Commands/DeployCommands.php + count: 2 + - + message: '#^Unsafe usage of new static#' + path: src/Plugin/migrate/source/HttpSourcePluginBase.php diff --git a/src/Azure/PubSub/PubSubManager.php b/src/Azure/PubSub/PubSubManager.php index 272740d1..c4867654 100644 --- a/src/Azure/PubSub/PubSubManager.php +++ b/src/Azure/PubSub/PubSubManager.php @@ -118,7 +118,7 @@ public function setTimeout(int $timeout) : self { * * This is used to exit early if required settings are not populated. */ - private function assertSettings() : self { + private function assertSettings() : void { $vars = get_object_vars($this->settings); foreach ($vars as $key => $value) { @@ -126,15 +126,14 @@ private function assertSettings() : self { throw new ConnectionException("Azure PubSub '$key' is not configured."); } } - return $this; } /** * {@inheritdoc} */ public function sendMessage(array $message) : self { - $this->assertSettings() - ->joinGroup(); + $this->assertSettings(); + $this->joinGroup(); $this->client ->text( @@ -155,8 +154,9 @@ public function sendMessage(array $message) : self { * {@inheritdoc} */ public function receive() : string { - $this->assertSettings() - ->joinGroup(); + $this->assertSettings(); + $this->joinGroup(); + $message = (string) $this->client->receive(); $json = $this->decodeMessage($message); diff --git a/src/Azure/PubSub/SettingsFactory.php b/src/Azure/PubSub/SettingsFactory.php index 22619445..610413ca 100644 --- a/src/Azure/PubSub/SettingsFactory.php +++ b/src/Azure/PubSub/SettingsFactory.php @@ -29,7 +29,7 @@ public function __construct( * The PubSub settings object. */ public function create() : Settings { - $data = (object) [ + $data = [ 'hub' => '', 'group' => '', 'endpoint' => '', @@ -41,9 +41,10 @@ public function create() : Settings { if (!isset($settings->data()->{$key})) { continue; } - $data->{$key} = $settings->data()->{$key}; + $data[$key] = $settings->data()->{$key}; } } + $data = (object) $data; return new Settings( $data->hub ?: '', diff --git a/src/Entity/Form/MenuLinkFormTrait.php b/src/Entity/Form/MenuLinkFormTrait.php index 50171361..4344e9ee 100644 --- a/src/Entity/Form/MenuLinkFormTrait.php +++ b/src/Entity/Form/MenuLinkFormTrait.php @@ -4,6 +4,7 @@ namespace Drupal\helfi_api_base\Entity\Form; +use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Menu\MenuParentFormSelectorInterface; use Drupal\Core\Site\Settings; @@ -13,8 +14,8 @@ /** * A trait to allow entity forms to provide a menu link form. * - * To use this, call the ::attachMenuLinkForm() method in your - * ::buildForm() method, like: + * To use this, call the '::attachMenuLinkForm()' method in your + * '::buildForm()' method, like: * * @code * $form = $this->attachMenuLinkForm($form, $form_state); @@ -48,6 +49,7 @@ trait MenuLinkFormTrait { */ protected function getDefaultMenuLink() : MenuLinkContentInterface { $entity = $this->getEntity(); + assert($entity instanceof FieldableEntityInterface); if (!$menuLink = $entity->get($this->menuLinkFieldName)->entity) { $storage = $this->entityTypeManager @@ -64,7 +66,10 @@ protected function getDefaultMenuLink() : MenuLinkContentInterface { $menuLink = empty($results) ? MenuLinkContent::create([]) : MenuLinkContent::load(reset($results)); } - return $this->entityRepository->getTranslationFromContext($menuLink); + $entity = $this->entityRepository->getTranslationFromContext($menuLink); + assert($entity instanceof MenuLinkContentInterface); + + return $entity; } /** @@ -173,6 +178,7 @@ protected function attachMenuLinkForm(array $form, FormStateInterface $formState */ public function attachMenuLinkFormSubmit(array $form, FormStateInterface $formState) : void { $entity = $this->getEntity(); + assert($entity instanceof FieldableEntityInterface); /** @var \Drupal\menu_link_content\MenuLinkContentInterface $menuLink */ $menuLink = $formState->get('menu_link'); diff --git a/src/Entity/Form/RevisionRevertTranslationForm.php b/src/Entity/Form/RevisionRevertTranslationForm.php index b74d83b2..75a844c4 100644 --- a/src/Entity/Form/RevisionRevertTranslationForm.php +++ b/src/Entity/Form/RevisionRevertTranslationForm.php @@ -5,8 +5,11 @@ namespace Drupal\helfi_api_base\Entity\Form; use Drupal\Core\Entity\RevisionableInterface; +use Drupal\Core\Entity\RevisionLogInterface; +use Drupal\Core\Entity\TranslatableRevisionableInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageManagerInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\entity\Form\RevisionRevertForm; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -33,7 +36,7 @@ final class RevisionRevertTranslationForm extends RevisionRevertForm { /** * {@inheritdoc} */ - public static function create(ContainerInterface $container) { + public static function create(ContainerInterface $container) : self { $instance = parent::create($container); $instance->languageManager = $container->get('language_manager'); return $instance; @@ -42,14 +45,15 @@ public static function create(ContainerInterface $container) { /** * {@inheritdoc} */ - public function getFormId() { + public function getFormId() : string { return 'revision_revert_translation_confirm'; } /** * {@inheritdoc} */ - public function getQuestion() { + public function getQuestion() : TranslatableMarkup { + assert($this->revision instanceof RevisionLogInterface); return $this->t('Are you sure you want to revert @language translation to the revision from %revision-date?', [ '@language' => $this->languageManager->getLanguageName($this->langcode), '%revision-date' => $this->dateFormatter->format($this->revision->getRevisionCreationTime()), @@ -59,14 +63,14 @@ public function getQuestion() { /** * {@inheritdoc} */ - public function getDescription() { - return ''; + public function getDescription() : TranslatableMarkup { + return $this->t('This action cannot be undone.'); } /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, $_entity_revision = NULL, Request $request = NULL) { + public function buildForm(array $form, FormStateInterface $form_state, $_entity_revision = NULL, Request $request = NULL) : array { $this->langcode = $request->attributes->get('langcode'); return parent::buildForm($form, $form_state, $_entity_revision); @@ -75,7 +79,8 @@ public function buildForm(array $form, FormStateInterface $form_state, $_entity_ /** * {@inheritdoc} */ - protected function prepareRevision(RevisionableInterface $revision) { + protected function prepareRevision(RevisionableInterface $revision) : RevisionableInterface { + assert($revision instanceof TranslatableRevisionableInterface); $translation = $revision->getTranslation($this->langcode); return parent::prepareRevision($translation); } diff --git a/src/Entity/Revision/RevisionManager.php b/src/Entity/Revision/RevisionManager.php index 7907272f..12d2dbec 100644 --- a/src/Entity/Revision/RevisionManager.php +++ b/src/Entity/Revision/RevisionManager.php @@ -9,6 +9,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Entity\TranslatableInterface; /** * A class to manage revisions. @@ -149,10 +150,11 @@ public function getRevisionsPerLanguage( krsort($revision_ids); foreach ($revision_ids as $vid) { - /** @var \Drupal\Core\Entity\RevisionableInterface $revision */ + /** @var \Drupal\Core\Entity\TranslatableRevisionableInterface $revision */ $revision = $storage->loadRevision($vid); foreach ($revision->getTranslationLanguages() as $langcode => $language) { + assert($revision instanceof TranslatableInterface); if ($revision->hasTranslation($langcode) && $revision->getTranslation($langcode)->isRevisionTranslationAffected()) { $revisions[$langcode][] = $revision->getLoadedRevisionId(); } diff --git a/src/Entity/Routing/RevisionRouteProvider.php b/src/Entity/Routing/RevisionRouteProvider.php index ce889255..e5975fc1 100644 --- a/src/Entity/Routing/RevisionRouteProvider.php +++ b/src/Entity/Routing/RevisionRouteProvider.php @@ -10,7 +10,7 @@ use Symfony\Component\Routing\Route; /** - * Providers extended revision routes for content entikties. + * Providers extended revision routes for content entities. */ final class RevisionRouteProvider extends EntityRevisionRouteProvider { @@ -31,11 +31,12 @@ public function getRoutes(EntityTypeInterface $entity_type) { /** * {@inheritdoc} */ - protected function getRevisionHistoryRoute(EntityTypeInterface $entity_type) { + protected function getRevisionHistoryRoute(EntityTypeInterface $entity_type): ?Route { if ($route = parent::getRevisionHistoryRoute($entity_type)) { $route->setDefault('_controller', RevisionController::class . '::revisionOverviewController'); return $route; } + return NULL; } /** diff --git a/src/EventSubscriber/MigrationSubscriber.php b/src/EventSubscriber/MigrationSubscriber.php index 9d274a50..21ae9b1a 100644 --- a/src/EventSubscriber/MigrationSubscriber.php +++ b/src/EventSubscriber/MigrationSubscriber.php @@ -116,7 +116,9 @@ public function onPostImport(MigrateImportEvent $event) : void { ->execute(); foreach ($results as $id) { - $storage->load($id)->delete(TRUE); + $entity = $storage->load($id); + assert($entity instanceof RemoteEntityBase); + $entity->delete(TRUE); } } diff --git a/src/Logger/JsonLog.php b/src/Logger/JsonLog.php index 667d67df..fb341d56 100644 --- a/src/Logger/JsonLog.php +++ b/src/Logger/JsonLog.php @@ -61,7 +61,7 @@ public function log($level, $message, array $context = []) : void { } // Populate the message placeholders and then replace them in the message. $variables = $this->parser->parseMessagePlaceholders($message, $context); - $message = empty($variables) ? $message : strtr($message, $variables); + $message = empty($variables) ? $message : strtr((string) $message, $variables); $this->output([ 'base_url' => $base_url, diff --git a/src/Plugin/Action/MigrationUpdateAction.php b/src/Plugin/Action/MigrationUpdateAction.php index 73184a27..03f6f4d6 100644 --- a/src/Plugin/Action/MigrationUpdateAction.php +++ b/src/Plugin/Action/MigrationUpdateAction.php @@ -25,7 +25,7 @@ * deriver = "Drupal\helfi_api_base\Plugin\Derivative\MigrationUpdateActionDerivative", * ) */ -class MigrationUpdateAction extends ActionBase implements ContainerFactoryPluginInterface { +final class MigrationUpdateAction extends ActionBase implements ContainerFactoryPluginInterface { use MigrateTrait; @@ -51,8 +51,8 @@ public static function create( array $configuration, $plugin_id, $plugin_definition - ) { - $instance = new static($configuration, $plugin_definition, $plugin_definition); + ) : self { + $instance = new self($configuration, $plugin_definition, $plugin_definition); $instance->migrationPluginManager = $container->get('plugin.manager.migration'); $instance->entityTypeManager = $container->get('entity_type.manager'); diff --git a/src/Plugin/DebugDataItem/Composer.php b/src/Plugin/DebugDataItem/Composer.php index 2f45bee7..7fd3f9cd 100644 --- a/src/Plugin/DebugDataItem/Composer.php +++ b/src/Plugin/DebugDataItem/Composer.php @@ -19,7 +19,7 @@ * description = @Translation("Composer") * ) */ -class Composer extends DebugDataItemPluginBase implements ContainerFactoryPluginInterface { +final class Composer extends DebugDataItemPluginBase implements ContainerFactoryPluginInterface { /** * The composer info. @@ -38,8 +38,8 @@ class Composer extends DebugDataItemPluginBase implements ContainerFactoryPlugin /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - $instance = new static($configuration, $plugin_id, $plugin_definition); + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) : self { + $instance = new self($configuration, $plugin_id, $plugin_definition); $instance->composerInfo = $container->get('helfi_api_base.composer_info'); return $instance; } diff --git a/src/Plugin/DebugDataItem/MaintenanceMode.php b/src/Plugin/DebugDataItem/MaintenanceMode.php index 6876f1e4..7e3407c0 100644 --- a/src/Plugin/DebugDataItem/MaintenanceMode.php +++ b/src/Plugin/DebugDataItem/MaintenanceMode.php @@ -18,7 +18,7 @@ * description = @Translation("Maintenance mode") * ) */ -class MaintenanceMode extends DebugDataItemPluginBase implements ContainerFactoryPluginInterface { +final class MaintenanceMode extends DebugDataItemPluginBase implements ContainerFactoryPluginInterface { /** * The state service. @@ -30,8 +30,8 @@ class MaintenanceMode extends DebugDataItemPluginBase implements ContainerFactor /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - $instance = new static($configuration, $plugin_id, $plugin_definition); + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) : self { + $instance = new self($configuration, $plugin_id, $plugin_definition); $instance->state = $container->get('state'); return $instance; } diff --git a/src/Plugin/DebugDataItem/Migrate.php b/src/Plugin/DebugDataItem/Migrate.php index 82039476..6aafcc32 100644 --- a/src/Plugin/DebugDataItem/Migrate.php +++ b/src/Plugin/DebugDataItem/Migrate.php @@ -22,7 +22,7 @@ * description = @Translation("Migrate data") * ) */ -class Migrate extends DebugDataItemPluginBase implements ContainerFactoryPluginInterface, CacheableDependencyInterface { +final class Migrate extends DebugDataItemPluginBase implements ContainerFactoryPluginInterface, CacheableDependencyInterface { /** * The migration plugin manager. @@ -41,8 +41,8 @@ class Migrate extends DebugDataItemPluginBase implements ContainerFactoryPluginI /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - $instance = new static($configuration, $plugin_id, $plugin_definition); + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) : self { + $instance = new self($configuration, $plugin_id, $plugin_definition); $instance->migrationPluginManager = $container->get('plugin.manager.migration'); $instance->keyValue = $container->get('keyvalue') ->get('migrate_last_imported'); diff --git a/src/Plugin/Derivative/MigrationUpdateActionDerivative.php b/src/Plugin/Derivative/MigrationUpdateActionDerivative.php index 97efa22d..334b7e72 100644 --- a/src/Plugin/Derivative/MigrationUpdateActionDerivative.php +++ b/src/Plugin/Derivative/MigrationUpdateActionDerivative.php @@ -15,7 +15,7 @@ /** * Provides an action to update singular migration. */ -class MigrationUpdateActionDerivative extends DeriverBase implements ContainerDeriverInterface { +final class MigrationUpdateActionDerivative extends DeriverBase implements ContainerDeriverInterface { use StringTranslationTrait; @@ -30,7 +30,7 @@ class MigrationUpdateActionDerivative extends DeriverBase implements ContainerDe * {@inheritdoc} */ public static function create(ContainerInterface $container, $base_plugin_id) { - $instance = new static(); + $instance = new self(); $instance->entityTypeManager = $container->get('entity_type.manager'); return $instance; diff --git a/src/Plugin/Validation/Constraint/JsonSchemaConstraintValidator.php b/src/Plugin/Validation/Constraint/JsonSchemaConstraintValidator.php index 0bc533f8..4530ad8d 100644 --- a/src/Plugin/Validation/Constraint/JsonSchemaConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/JsonSchemaConstraintValidator.php @@ -5,6 +5,7 @@ namespace Drupal\helfi_api_base\Plugin\Validation\Constraint; use Drupal\Core\Field\FieldItemListInterface; +use Drupal\Core\Field\FieldStorageDefinitionInterface; use JsonSchema\Validator; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -18,6 +19,9 @@ final class JsonSchemaConstraintValidator extends ConstraintValidator { * {@inheritdoc} */ public function validate($value, Constraint $constraint) : void { + if (!isset($constraint->schema)) { + return; + } if (!file_exists($constraint->schema)) { $this->context->addViolation('Failed to load JSON schema: "@schema"', [ '@schema' => $constraint->schema, @@ -26,6 +30,8 @@ public function validate($value, Constraint $constraint) : void { } if ($value instanceof FieldItemListInterface) { + assert($value->getFieldDefinition() instanceof FieldStorageDefinitionInterface); + $propertyName = $value->getFieldDefinition() ->getMainPropertyName(); $value = $value->{$propertyName}; diff --git a/src/Plugin/migrate/destination/TranslatableEntity.php b/src/Plugin/migrate/destination/TranslatableEntity.php index 10d160ec..60f71bf2 100644 --- a/src/Plugin/migrate/destination/TranslatableEntity.php +++ b/src/Plugin/migrate/destination/TranslatableEntity.php @@ -6,6 +6,7 @@ use Drupal\Core\Entity\ContentEntityStorageInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\TranslatableInterface; use Drupal\helfi_api_base\Entity\RemoteEntityBase; use Drupal\migrate\MigrateException; use Drupal\migrate\Plugin\migrate\destination\EntityContentBase; @@ -29,6 +30,7 @@ class TranslatableEntity extends EntityContentBase { * The storage. */ public function getStorage() : ContentEntityStorageInterface { + assert($this->storage instanceof ContentEntityStorageInterface); return $this->storage; } @@ -60,6 +62,7 @@ protected function getEntity(Row $row, array $old_destination_id_values) { $entity = $this->storage->create($row->getDestination()); $entity->enforceIsNew(); } + assert($entity instanceof TranslatableInterface); if ($entity->hasTranslation($langcode)) { // Update existing translation. diff --git a/src/Plugin/migrate/source/HttpSourcePluginBase.php b/src/Plugin/migrate/source/HttpSourcePluginBase.php index 9790043f..4b79ae03 100644 --- a/src/Plugin/migrate/source/HttpSourcePluginBase.php +++ b/src/Plugin/migrate/source/HttpSourcePluginBase.php @@ -32,13 +32,13 @@ abstract class HttpSourcePluginBase extends SourcePluginBase implements Cacheabl protected bool $useRequestCache = TRUE; /* - * The number of ignored rows until we stop the migrate. + * The number of ignored rows until we stop the migration. * * This assumes that your API can be sorted in a way that the newest * changes are listed first. * * For this to have any effect 'track_changes' source setting must be set to - * true, and you must run the migrate with PARTIAL_MIGRATE=1 setting. + * true, and you must run the migration with PARTIAL_MIGRATE=1 setting. * * @var int */ @@ -221,11 +221,11 @@ protected function initializeIterator() : \Iterator { /** * {@inheritdoc} */ - public function next() { + public function next() : void { parent::next(); // Check if the current row has changes and increment ignoredRows variable - // to allow us to stop migrate early if we have no changes. + // to allow us to stop migration early if we have no changes. if ($this->isPartialMigrate() && $this->currentRow && !$this->currentRow->changed()) { $this->ignoredRows++; } diff --git a/src/Vault/Json.php b/src/Vault/Json.php index d7655985..1cd22846 100644 --- a/src/Vault/Json.php +++ b/src/Vault/Json.php @@ -14,7 +14,7 @@ final class Json implements VaultItemInterface { /** * The json decoded data. * - * @var object|mixed + * @var object */ private readonly object $data; diff --git a/src/Vault/VaultItemInterface.php b/src/Vault/VaultItemInterface.php index 563dd625..26fd7ac5 100644 --- a/src/Vault/VaultItemInterface.php +++ b/src/Vault/VaultItemInterface.php @@ -9,6 +9,8 @@ */ interface VaultItemInterface { + public const PLUGIN = ''; + /** * Gets the id. * diff --git a/tests/modules/remote_entity_test/src/Entity/RemoteEntityForm.php b/tests/modules/remote_entity_test/src/Entity/RemoteEntityForm.php index a8a646ff..5890d0aa 100644 --- a/tests/modules/remote_entity_test/src/Entity/RemoteEntityForm.php +++ b/tests/modules/remote_entity_test/src/Entity/RemoteEntityForm.php @@ -45,11 +45,9 @@ public function buildForm(array $form, FormStateInterface $form_state) : array { /** * {@inheritdoc} */ - public function save(array $form, FormStateInterface $form_state) { + public function save(array $form, FormStateInterface $form_state) : int { $entityTypeId = $this->entity->getEntityTypeId(); - parent::save($form, $form_state); - $this->messenger() ->addStatus($this->t('%title saved.', [ '%title' => $this->entity->label(), @@ -58,6 +56,7 @@ public function save(array $form, FormStateInterface $form_state) { $form_state->setRedirect('entity.' . $entityTypeId . '.canonical', [ $entityTypeId => $this->entity->id(), ]); + return parent::save($form, $form_state); } } diff --git a/tests/src/Functional/BrowserTestBase.php b/tests/src/Functional/BrowserTestBase.php index e88f0cd9..49311cd1 100644 --- a/tests/src/Functional/BrowserTestBase.php +++ b/tests/src/Functional/BrowserTestBase.php @@ -41,7 +41,7 @@ public function setUp() : void { 'language_interface[weight][language-session]' => -12, ]; $this->drupalGet('/admin/config/regional/language/detection'); - $this->submitForm($edit, t('Save settings')); + $this->submitForm($edit, 'Save settings'); // Make sure we are not logged in. $this->drupalLogout(); diff --git a/tests/src/Functional/InstallTest.php b/tests/src/Functional/InstallTest.php index 4f0de686..da488f27 100644 --- a/tests/src/Functional/InstallTest.php +++ b/tests/src/Functional/InstallTest.php @@ -78,7 +78,9 @@ public function testInstall() : void { } $moduleInstaller->install(['helfi_api_base']); - $this->assertTrue(Role::load('debug_api')->hasPermission('restful get helfi_debug_data')); + /** @var \Drupal\user\Entity\Role $role */ + $role = Role::load('debug_api'); + $this->assertTrue($role->hasPermission('restful get helfi_debug_data')); } } diff --git a/tests/src/Functional/MenuLinkFormTest.php b/tests/src/Functional/MenuLinkFormTest.php index 75411828..4d7c8199 100644 --- a/tests/src/Functional/MenuLinkFormTest.php +++ b/tests/src/Functional/MenuLinkFormTest.php @@ -5,6 +5,7 @@ namespace Drupal\Tests\helfi_api_base\Functional; use Drupal\Core\Url; +use Drupal\remote_entity_test\Entity\RemoteEntityTest; use Drupal\Tests\helfi_api_base\Traits\ApiTestTrait; /** @@ -84,8 +85,9 @@ public function testMenuLinkForm() : void { ]); $this->drupalLogin($account); - $entity = $storage->create(['id' => 1, 'name' => 'Test en']) - ->addTranslation('fi', ['name' => 'Test fi']); + $entity = $storage->create(['id' => 1, 'name' => 'Test en']); + $this->assertInstanceOf(RemoteEntityTest::class, $entity); + $entity->addTranslation('fi', ['name' => 'Test fi']); $entity->save(); foreach (['en', 'fi'] as $langcode) { @@ -114,12 +116,13 @@ public function testMenuLinkForm() : void { $storage->resetCache([$entity->id()]); // Make sure menu link is referenced in entity. - $menuLink = $storage->load($entity->id()) - ->getTranslation($langcode) + $entity = $storage->load($entity->id()); + $this->assertInstanceOf(RemoteEntityTest::class, $entity); + /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $menuLink */ + $menuLink = $entity->getTranslation($langcode) ->get('menu_link') - ->entity - ->getTranslation($langcode); - + ->entity; + $menuLink = $menuLink->getTranslation($langcode); $this->assertEquals(9, $menuLink->getWeight()); $this->assertEquals('Test title ' . $langcode, $menuLink->getTitle()); } @@ -136,10 +139,13 @@ public function testMenuLinkForm() : void { // Make sure english menu link still exists. $storage->resetCache([$entity->id()]); - $menuLink = $storage->load($entity->id()) - ->getTranslation('en') + $entity = $storage->load($entity->id()); + $this->assertInstanceOf(RemoteEntityTest::class, $entity); + /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $menuLink */ + $menuLink = $entity->getTranslation($langcode) ->get('menu_link') ->entity; + $menuLink = $menuLink->getTranslation('en'); $this->assertEquals('Test title en', $menuLink->getTitle()); // Re-add finnish menu link and remove the default translation. diff --git a/tests/src/Kernel/Cache/CacheTagInvalidatorTest.php b/tests/src/Kernel/Cache/CacheTagInvalidatorTest.php index 9c35b256..5ee49319 100644 --- a/tests/src/Kernel/Cache/CacheTagInvalidatorTest.php +++ b/tests/src/Kernel/Cache/CacheTagInvalidatorTest.php @@ -6,7 +6,7 @@ use Drupal\helfi_api_base\Azure\PubSub\PubSubManager; use Drupal\KernelTests\KernelTestBase; -use Drupal\Tests\helfi_api_base\Traits\CacheTagInvalidatorTrait; +use Drupal\Tests\helfi_api_base\Traits\CacheTagInvalidator; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use WebSocket\Client; @@ -20,7 +20,6 @@ class CacheTagInvalidatorTest extends KernelTestBase { use ProphecyTrait; - use CacheTagInvalidatorTrait; /** * {@inheritdoc} @@ -62,7 +61,7 @@ public function testInvalidateTags() : void { // the event subscriber is actually run and the invalidation logic is // actually triggered. // @see \Drupal\helfi_api_base\EventSubscriber\CacheTagInvalidatorSubscriber - $cacheTagInvalidator = $this->mockCacheInvalidator(); + $cacheTagInvalidator = new CacheTagInvalidator(); $this->container->set('cache_tags.invalidator', $cacheTagInvalidator); $client = $this->prophesize(Client::class); diff --git a/tests/src/Kernel/Entity/Revision/RevisionManagerTest.php b/tests/src/Kernel/Entity/Revision/RevisionManagerTest.php index 3a2fa9c4..f1127589 100644 --- a/tests/src/Kernel/Entity/Revision/RevisionManagerTest.php +++ b/tests/src/Kernel/Entity/Revision/RevisionManagerTest.php @@ -5,6 +5,7 @@ namespace Drupal\Tests\helfi_api_base\Kernel\Entity\Revision; use Drupal\helfi_api_base\Entity\Revision\RevisionManager; +use Drupal\remote_entity_test\Entity\RemoteEntityTest; use Drupal\Tests\helfi_api_base\Kernel\ApiKernelTestBase; use Drupal\Tests\helfi_api_base\Traits\LanguageManagerTrait; @@ -144,6 +145,7 @@ public function testRevision() : void { for ($i = 0; $i < 10; $i++) { $rmt = $storage->load($entity->id()); + $this->assertInstanceOf(RemoteEntityTest::class, $rmt); $rmt->set('name', 'test en ' . $i); $rmt->getTranslation('fi') diff --git a/tests/src/Kernel/EventSubscriber/EnsureApiAccountsSubscriberTest.php b/tests/src/Kernel/EventSubscriber/EnsureApiAccountsSubscriberTest.php index 28ffb71c..b6954463 100644 --- a/tests/src/Kernel/EventSubscriber/EnsureApiAccountsSubscriberTest.php +++ b/tests/src/Kernel/EventSubscriber/EnsureApiAccountsSubscriberTest.php @@ -10,6 +10,7 @@ use Drupal\Tests\helfi_api_base\Traits\EnvironmentResolverTrait; use Drupal\Tests\user\Traits\UserCreationTrait; use Drupal\user\Entity\Role; +use Drupal\user\UserInterface; use Symfony\Contracts\EventDispatcher\Event; /** @@ -79,6 +80,7 @@ public function testPasswordReset(): void { $service = $this->container->get('helfi_api_base.ensure_api_accounts_subscriber'); $service->onPostDeploy(new Event()); $account = user_load_by_name('helfi-admin'); + $this->assertInstanceOf(UserInterface::class, $account); $this->assertTrue($account->hasRole('debug_api')); $this->assertTrue($passwordHasher->check('123', $account->getPassword())); @@ -96,6 +98,7 @@ public function testPasswordReset(): void { ->save(); $service->onPostDeploy(new Event()); $account = user_load_by_name('helfi-admin'); + $this->assertInstanceOf(UserInterface::class, $account); $this->assertEquals('drupal+helfi-admin@hel.fi', $account->getEmail()); $this->assertTrue($account->hasRole('test')); $this->assertFalse($account->isBlocked()); diff --git a/tests/src/Kernel/MigrationSubscriberTest.php b/tests/src/Kernel/MigrationSubscriberTest.php index df5d9d7f..5117e573 100644 --- a/tests/src/Kernel/MigrationSubscriberTest.php +++ b/tests/src/Kernel/MigrationSubscriberTest.php @@ -37,9 +37,9 @@ class MigrationSubscriberTest extends ApiKernelTestBase { /** * The migration subscriber. * - * @var null|\Drupal\helfi_api_base\EventSubscriber\MigrationSubscriber + * @var \Drupal\helfi_api_base\EventSubscriber\MigrationSubscriber */ - protected ?MigrationSubscriber $migrationSubscriber; + protected MigrationSubscriber $migrationSubscriber; /** * {@inheritdoc} @@ -101,6 +101,7 @@ public function testIncrement() : void { $this->migrationSubscriber->onPreImport($event); $entity = $this->reloadEntity($entity); + $this->assertInstanceOf(RemoteEntityTest::class, $entity); $this->assertEquals($entity->getSyncAttempts(), 1); } diff --git a/tests/src/Traits/ApiTestTrait.php b/tests/src/Traits/ApiTestTrait.php index 2a2f5c9b..f7520c24 100644 --- a/tests/src/Traits/ApiTestTrait.php +++ b/tests/src/Traits/ApiTestTrait.php @@ -8,7 +8,6 @@ use Drupal\Core\Extension\ExtensionPathResolver; use Drupal\Core\Http\ClientFactory; use GuzzleHttp\Client; -use GuzzleHttp\ClientInterface; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Middleware; @@ -20,6 +19,13 @@ */ trait ApiTestTrait { + /** + * The container. + * + * @var \Drupal\Component\DependencyInjection\ContainerInterface + */ + protected $container; + /** * Creates HTTP client stub. * @@ -53,16 +59,16 @@ protected function setupMockHttpClient(array $responses) : Client { /** * Constructs a new instance. * - * @param \GuzzleHttp\ClientInterface $client + * @param \GuzzleHttp\Client $client * The http client. */ - public function __construct(private readonly ClientInterface $client) { + public function __construct(private readonly Client $client) { } /** * {@inheritdoc} */ - public function fromOptions(array $config = []) : ClientInterface { + public function fromOptions(array $config = []) : Client { return $this->client; } diff --git a/tests/src/Traits/CacheTagInvalidator.php b/tests/src/Traits/CacheTagInvalidator.php new file mode 100644 index 00000000..256f6864 --- /dev/null +++ b/tests/src/Traits/CacheTagInvalidator.php @@ -0,0 +1,47 @@ +tags[$tag] = $tag; + } + } + + /** + * Add missing resetChecksums() method. + * + * @see \Drupal\Core\Cache\CacheTagsInvalidator::resetChecksums() + */ + public function resetChecksums() : void { + $this->checkSumResets++; + } + +} diff --git a/tests/src/Traits/CacheTagInvalidatorTrait.php b/tests/src/Traits/CacheTagInvalidatorTrait.php deleted file mode 100644 index 2a42d04b..00000000 --- a/tests/src/Traits/CacheTagInvalidatorTrait.php +++ /dev/null @@ -1,62 +0,0 @@ -tags[$tag] = $tag; - } - } - - /** - * Add missing resetChecksums() method. - * - * @see \Drupal\Core\Cache\CacheTagsInvalidator::resetChecksums() - */ - public function resetChecksums() : void { - $this->checkSumResets++; - } - - }; - } - -} diff --git a/tests/src/Traits/EnvironmentResolverTrait.php b/tests/src/Traits/EnvironmentResolverTrait.php index 9358ae54..55a5f5c3 100644 --- a/tests/src/Traits/EnvironmentResolverTrait.php +++ b/tests/src/Traits/EnvironmentResolverTrait.php @@ -14,6 +14,13 @@ */ trait EnvironmentResolverTrait { + /** + * The container. + * + * @var \Drupal\Component\DependencyInjection\ContainerInterface + */ + protected $container; + /** * Sets the active project. * @@ -55,9 +62,11 @@ protected function getConfigStub(mixed $projectName = NULL, mixed $envName = NUL } if ($this instanceof UnitTestCase) { - return $this->getConfigFactoryStub([ + /** @var \Drupal\Core\Config\ConfigFactoryInterface $configFactory */ + $configFactory = $this->getConfigFactoryStub([ 'helfi_api_base.environment_resolver.settings' => $config, ]); + return $configFactory; } $this->setActiveProject($projectName, $envName); diff --git a/tests/src/Traits/LanguageManagerTrait.php b/tests/src/Traits/LanguageManagerTrait.php index 55b2581f..cd5c0163 100644 --- a/tests/src/Traits/LanguageManagerTrait.php +++ b/tests/src/Traits/LanguageManagerTrait.php @@ -4,6 +4,7 @@ namespace Drupal\Tests\helfi_api_base\Traits; +use Drupal\helfi_language_negotiator_test\LanguageNegotiator; use Drupal\language\ConfigurableLanguageManagerInterface; use Drupal\language\Entity\ConfigurableLanguage; @@ -15,9 +16,9 @@ trait LanguageManagerTrait { /** * The language manager. * - * @var \Drupal\language\ConfigurableLanguageManagerInterface|null + * @var \Drupal\language\ConfigurableLanguageManagerInterface */ - protected ?ConfigurableLanguageManagerInterface $languageManager = NULL; + protected ConfigurableLanguageManagerInterface $languageManager; /** * Setup languages. @@ -48,9 +49,10 @@ protected function setupLanguages() : void { * The language manager. */ protected function languageManager() : ConfigurableLanguageManagerInterface { - if (!$this->languageManager) { - /** @var \Drupal\language\ConfigurableLanguageManagerInterface $languageManager */ - $this->languageManager = $this->container->get('language_manager'); + if (!isset($this->languageManager)) { + $languageManager = $this->container->get('language_manager'); + assert($languageManager instanceof ConfigurableLanguageManagerInterface); + $this->languageManager = $languageManager; /** @var \Drupal\helfi_language_negotiator_test\LanguageNegotiator $customLanguageManager */ $customLanguageManager = $this->container->get('helfi_language_negotiator_test.language_negotiator'); $this->languageManager->setNegotiator($customLanguageManager); @@ -66,7 +68,9 @@ protected function languageManager() : ConfigurableLanguageManagerInterface { */ protected function setOverrideLanguageCode(string $langcode) : void { $this->languageManager()->reset(); - $this->languageManager()->getNegotiator()->setLanguageCode($langcode); + $negotiator = $this->languageManager()->getNegotiator(); + assert($negotiator instanceof LanguageNegotiator); + $negotiator->setLanguageCode($langcode); } } diff --git a/tests/src/Traits/TestLoggerTrait.php b/tests/src/Traits/TestLoggerTrait.php index 8dd0fb51..e944ef21 100644 --- a/tests/src/Traits/TestLoggerTrait.php +++ b/tests/src/Traits/TestLoggerTrait.php @@ -5,7 +5,6 @@ namespace Drupal\Tests\helfi_api_base\Traits; use Drupal\helfi_api_base\Logger\RfcTestLogger; -use Psr\Log\LoggerInterface; /** * Provides a test logger trait to catch log messages. @@ -15,9 +14,9 @@ trait TestLoggerTrait { /** * The test logger. * - * @var null|\Psr\Log\LoggerInterface + * @var \Drupal\helfi_api_base\Logger\RfcTestLogger|null */ - protected ?LoggerInterface $testLogger = NULL; + protected ?RfcTestLogger $testLogger = NULL; /** * The expected log messages. diff --git a/tests/src/Unit/Environment/EnvironmentResolverTest.php b/tests/src/Unit/Environment/EnvironmentResolverTest.php index 4d543949..830d077a 100644 --- a/tests/src/Unit/Environment/EnvironmentResolverTest.php +++ b/tests/src/Unit/Environment/EnvironmentResolverTest.php @@ -138,7 +138,7 @@ public function testGetEnvironmentException( /** * Data provider. * - * @return \string[][] + * @return array * The data. */ public function resolveEnvironmentExceptionData() : array { @@ -177,7 +177,7 @@ public function testEnvironmentMap(string $envName, string $expected) : void { /** * Data provider for testEnvironmentMap(). * - * @return \string[][] + * @return array * The data. */ public function environmentMapData() : array { diff --git a/tests/src/Unit/EventSubscriber/CacheInvalidatorSubscriberTest.php b/tests/src/Unit/EventSubscriber/CacheInvalidatorSubscriberTest.php index 42f8320b..b56d6669 100644 --- a/tests/src/Unit/EventSubscriber/CacheInvalidatorSubscriberTest.php +++ b/tests/src/Unit/EventSubscriber/CacheInvalidatorSubscriberTest.php @@ -9,7 +9,7 @@ use Drupal\helfi_api_base\Environment\EnvironmentEnum; use Drupal\helfi_api_base\Environment\Project; use Drupal\helfi_api_base\EventSubscriber\CacheTagInvalidatorSubscriber; -use Drupal\Tests\helfi_api_base\Traits\CacheTagInvalidatorTrait; +use Drupal\Tests\helfi_api_base\Traits\CacheTagInvalidator; use Drupal\Tests\helfi_api_base\Traits\EnvironmentResolverTrait; use Drupal\Tests\UnitTestCase; use Prophecy\PhpUnit\ProphecyTrait; @@ -21,7 +21,6 @@ class CacheInvalidatorSubscriberTest extends UnitTestCase { use ProphecyTrait; - use CacheTagInvalidatorTrait; use EnvironmentResolverTrait; /** @@ -57,7 +56,7 @@ public function testInvalidServiceException() : void { public function testInvalidProject() : void { // Make sure a project is considered valid if environment resolver // fails to find an active project. - $mock = $this->mockCacheInvalidator(); + $mock = new CacheTagInvalidator(); $environmentResolver = $this->getEnvironmentResolver('invalid_project'); $sut = new CacheTagInvalidatorSubscriber($mock, $environmentResolver); $sut->onReceive(new PubSubMessage([ @@ -77,7 +76,7 @@ public function testInvalidProject() : void { * @covers \Drupal\helfi_api_base\Azure\PubSub\PubSubMessage::__construct */ public function testInvalidCacheTags() : void { - $mock = $this->mockCacheInvalidator(); + $mock = new CacheTagInvalidator(); $environmentResolver = $this->getEnvironmentResolver(); $sut = new CacheTagInvalidatorSubscriber($mock, $environmentResolver); $sut->onReceive(new PubSubMessage([])); @@ -91,7 +90,7 @@ public function testInvalidCacheTags() : void { * @covers \Drupal\helfi_api_base\Azure\PubSub\PubSubMessage::__construct */ public function testValidCacheTags() : void { - $mock = $this->mockCacheInvalidator(); + $mock = new CacheTagInvalidator(); $environmentResolver = $this->getEnvironmentResolver(); $sut = new CacheTagInvalidatorSubscriber($mock, $environmentResolver); $sut->onReceive(new PubSubMessage(['data' => ['tags' => ['node:123']]])); @@ -107,7 +106,7 @@ public function testValidCacheTags() : void { * @covers \Drupal\helfi_api_base\Azure\PubSub\PubSubMessage::__construct */ public function testValidInstances() : void { - $mock = $this->mockCacheInvalidator(); + $mock = new CacheTagInvalidator(); $environmentResolver = $this->getEnvironmentResolver(Project::ASUMINEN, EnvironmentEnum::Local); $sut = new CacheTagInvalidatorSubscriber($mock, $environmentResolver); diff --git a/tests/src/Unit/Link/LinkProcessorTest.php b/tests/src/Unit/Link/LinkProcessorTest.php index d6405467..a7ef99c8 100644 --- a/tests/src/Unit/Link/LinkProcessorTest.php +++ b/tests/src/Unit/Link/LinkProcessorTest.php @@ -13,6 +13,7 @@ use Drupal\helfi_api_base\Link\LinkProcessor; use Drupal\Tests\UnitTestCase; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; /** * @coversDefaultClass \Drupal\helfi_api_base\Link\LinkProcessor @@ -20,6 +21,8 @@ */ class LinkProcessorTest extends UnitTestCase { + use ProphecyTrait; + /** * @covers ::preRenderLink * @covers \Drupal\helfi_api_base\Link\InternalDomainResolver::__construct diff --git a/tests/src/Unit/Vault/VaultManagerTest.php b/tests/src/Unit/Vault/VaultManagerTest.php index 3dace152..2f62fdcf 100644 --- a/tests/src/Unit/Vault/VaultManagerTest.php +++ b/tests/src/Unit/Vault/VaultManagerTest.php @@ -112,9 +112,9 @@ public function testFactory() : void { $instance = $sut->create(); $this->assertInstanceOf(VaultManager::class, $instance); - foreach ($accounts as $acccount) { - $this->assertSame($acccount['id'], $instance->get($acccount['id'])->id()); - $this->assertSame($acccount['plugin'], $instance->get($acccount['id'])::PLUGIN); + foreach ($accounts as $account) { + $this->assertSame($account['id'], $instance->get($account['id'])->id()); + $this->assertSame($account['plugin'], $instance->get($account['id'])::PLUGIN); } }