diff --git a/origins_common/src/Plugin/Filter/CookieContentBlockerEmbedFilter.php b/origins_common/src/Plugin/Filter/CookieContentBlockerEmbedFilter.php index c18d47ac..cf27b9c8 100644 --- a/origins_common/src/Plugin/Filter/CookieContentBlockerEmbedFilter.php +++ b/origins_common/src/Plugin/Filter/CookieContentBlockerEmbedFilter.php @@ -148,6 +148,7 @@ function ($matches) { } if ($add_cookie_content_blocker && ($entity && $entity->bundle() === 'remote_video')) { + /** @var \Drupal\media\MediaInterface $entity */ $url = $entity->get('field_media_oembed_video')->getString(); $link_text = $this->settings['replacement_text']; // Despite what the documentation says, we have to base64 encode the diff --git a/origins_media/origins_media.module b/origins_media/origins_media.module index bc6dab0c..eef2ce72 100644 --- a/origins_media/origins_media.module +++ b/origins_media/origins_media.module @@ -165,6 +165,7 @@ function origins_media_form_alter(&$form, FormStateInterface $form_state, $form_ */ function origins_media_file_delete(EntityInterface $entity) { // Purge file URL from Fastly. + /** @var \Drupal\file\FileInterface $entity */ $url = $entity->createFileUrl($relative = FALSE); if (!empty(\Drupal::hasService('fastly.api'))) { $fastly = Drupal::service('fastly.api'); diff --git a/origins_qa/origins_qa.install b/origins_qa/origins_qa.install index dba26ffc..a5b99402 100644 --- a/origins_qa/origins_qa.install +++ b/origins_qa/origins_qa.install @@ -36,6 +36,7 @@ function origins_qa_requirements($phase) { if (!empty($accounts)) { $active = 0; foreach ($accounts as $account) { + /** @var \Drupal\user\UserInterface $account */ ($account->isActive()) ? $active++ : NULL; } diff --git a/origins_qa/src/Controller/QaAccountsManager.php b/origins_qa/src/Controller/QaAccountsManager.php index dffbff9c..3f62b7cf 100644 --- a/origins_qa/src/Controller/QaAccountsManager.php +++ b/origins_qa/src/Controller/QaAccountsManager.php @@ -69,6 +69,7 @@ public function list() { $rows = []; foreach ($accounts as $account) { + /** @var \Drupal\user\UserInterface $account */ $rows[] = [ $account->label(), ($account->isActive()) ? 'Enabled' : 'Disabled', @@ -128,7 +129,7 @@ public function toggleAll($action) { ]); foreach ($accounts as $account) { - + /** @var \Drupal\user\UserInterface $account */ if ($action === 'enable') { if (!$account->isActive()) { $account->activate(); diff --git a/origins_qa/src/Form/QaPasswordSetForm.php b/origins_qa/src/Form/QaPasswordSetForm.php index 8244f4a6..4638e258 100644 --- a/origins_qa/src/Form/QaPasswordSetForm.php +++ b/origins_qa/src/Form/QaPasswordSetForm.php @@ -82,6 +82,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { ]); foreach ($accounts as $account) { + /** @var \Drupal\user\UserInterface $account */ $account->setPassword($password); $account->save(); } diff --git a/origins_toc/origins_toc.module b/origins_toc/origins_toc.module index 116f2b8b..01194589 100644 --- a/origins_toc/origins_toc.module +++ b/origins_toc/origins_toc.module @@ -48,8 +48,11 @@ function origins_toc_help($route_name, RouteMatchInterface $route_match) { * Implements hook_form_BASE_FORM_ID_alter(). */ function origins_toc_form_node_type_form_alter(&$form, FormStateInterface $form_state, $form_id) { - $node = $form_state->getFormObject()->getEntity(); - $node_type = $node->id(); + /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */ + $form_object = $form_state->getFormObject(); + /** @var \Drupal\node\NodeInterface $node */ + $node = $form_object->getEntity(); + $node_type = NodeType::load($node->id()); $form['toc'] = [ '#type' => 'details', @@ -60,7 +63,7 @@ function origins_toc_form_node_type_form_alter(&$form, FormStateInterface $form_ $form['toc']['toc_enable'] = [ '#type' => 'checkbox', '#title' => t('Enable table of contents.'), - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_enable', NULL), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_enable', NULL), ]; $form['toc']['toc_config'] = [ @@ -76,7 +79,7 @@ function origins_toc_form_node_type_form_alter(&$form, FormStateInterface $form_ '#type' => 'textfield', '#title' => t('Title'), '#description' => t('Displayed before the table of contents or blank for no title.'), - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_title', 'Table of contents'), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_title', 'Table of contents'), ]; $form['toc']['toc_config']['toc_location'] = [ @@ -84,7 +87,7 @@ function origins_toc_form_node_type_form_alter(&$form, FormStateInterface $form_ '#title' => t('Location'), '#description' => t('CSS selector of the element where the ToC should be inserted.'), '#size' => 30, - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_location', NULL), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_location', NULL), '#placeholder' => '#location', '#states' => [ 'required' => [ @@ -101,7 +104,7 @@ function origins_toc_form_node_type_form_alter(&$form, FormStateInterface $form_ 'before' => 'Before', ], '#description' => t('Insert the ToC before or after the location element..'), - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_insert', NULL), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_insert', NULL), ]; $form['toc']['toc_config']['toc_source_container'] = [ @@ -109,7 +112,7 @@ function origins_toc_form_node_type_form_alter(&$form, FormStateInterface $form_ '#title' => t('Source container'), '#description' => t('CSS selector of the containing element to generate links for.'), '#size' => 30, - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_source_container', NULL), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_source_container', NULL), '#placeholder' => '#content-container', '#states' => [ 'required' => [ @@ -127,14 +130,14 @@ function origins_toc_form_node_type_form_alter(&$form, FormStateInterface $form_ 'h4' => 'H4 - Heading 4', ], '#description' => t('HTML element to generate the table of contents against.'), - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_element', NULL), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_element', NULL), ]; $form['toc']['toc_config']['toc_exclusions'] = [ '#type' => 'textfield', '#title' => t('Exclusions'), '#description' => t('Comma separated list of class names to exclude from the table of contents.'), - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_exclusions', NULL), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_exclusions', NULL), ]; $form['toc']['toc_config']['toc_screen_depth'] = [ @@ -154,14 +157,14 @@ function origins_toc_form_node_type_form_alter(&$form, FormStateInterface $form_ '11' => '11 screens 🤘', ], '#description' => t('The length of content on the current users display before the ToC will be displayed.'), - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_screen_depth', 1), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_screen_depth', 1), ]; $form['toc']['toc_config']['toc_debug'] = [ '#type' => 'checkbox', '#title' => t('Enable debug'), '#description' => t('Display debugging information in the browser console window.'), - '#default_value' => $node->getThirdPartySetting('origins_toc', 'toc_debug', 0), + '#default_value' => $node_type->getThirdPartySetting('origins_toc', 'toc_debug', 0), ]; $form['#entity_builders'][] = 'origins_toc_form_node_type_form_builder'; @@ -224,6 +227,7 @@ function origins_toc_entity_presave(EntityInterface $entity) { * Implements hook_node_view(). */ function origins_toc_node_view(&$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { + /** @var \Drupal\node\NodeInterface $entity */ $node_type = \Drupal::entityTypeManager()->getStorage('node_type')->load($entity->getType()); $toc_settings = $node_type->getThirdPartySettings('origins_toc'); diff --git a/origins_translations/origins_translations.module b/origins_translations/origins_translations.module index dd850f89..c6364382 100644 --- a/origins_translations/origins_translations.module +++ b/origins_translations/origins_translations.module @@ -56,7 +56,7 @@ function origins_translations_token_info() { */ function origins_translations_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) { $replacements = []; - /** @var Drupal\Core\Render\Renderer $renderer */ + /** @var \Drupal\Core\Render\Renderer $renderer */ $renderer = \Drupal::service('renderer'); if ($type === 'origins') { diff --git a/origins_workflow/origins_workflow.install b/origins_workflow/origins_workflow.install index 0ae3377c..eb4e6d11 100644 --- a/origins_workflow/origins_workflow.install +++ b/origins_workflow/origins_workflow.install @@ -6,6 +6,7 @@ */ use Drupal\user\Entity\User; +use Drupal\user\UserInterface; /** * Implements hook_install(). @@ -80,7 +81,8 @@ function origins_workflow_uninstall() { $prefix = getenv('NW_TEST_USER_PREFIX'); $name = $prefix . $name; $user = user_load_by_name($name); - if (!empty($user)) { + + if ($user instanceof UserInterface) { \Drupal::logger('origins_workflow')->notice(t('Deleting user @name', ['@name' => $name])); $user->delete(); } diff --git a/origins_workflow/origins_workflow.module b/origins_workflow/origins_workflow.module index 688ef79a..2dc5ead1 100644 --- a/origins_workflow/origins_workflow.module +++ b/origins_workflow/origins_workflow.module @@ -6,6 +6,8 @@ */ use Drupal\Component\Utility\NestedArray; +use Drupal\content_moderation\Entity\ContentModerationStateInterface; +use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\RevisionLogInterface; use Drupal\Core\Form\FormStateInterface; @@ -39,7 +41,7 @@ function origins_workflow_entity_presave(EntityInterface $entity) { $audit_types = $config->get('audit_content_types'); // This will fire when nodes are created or edited. - if ($entity->getEntityTypeId() == 'node') { + if ($entity instanceof NodeInterface) { if (isset($audit_types[$entity->bundle()]) && ($audit_types[$entity->bundle()] == $entity->bundle())) { // We have just published a node type that is subject to auditing. if ($entity->isPublished() && $entity->hasField('field_next_audit_due')) { @@ -58,12 +60,10 @@ function origins_workflow_entity_presave(EntityInterface $entity) { $msgobj = $entity->getRevisionLogMessage(); if (!empty($msgobj)) { $thismsg = ($msgobj instanceof TranslatableMarkup) ? $msgobj->getUntranslatedString() : $msgobj; - if (!empty($thismsg)) { - if (preg_match('/^Copy of the revision from/', $thismsg)) { - $entity->setRevisionLogMessage(t('Copy of revision @rev', [ - '@rev' => $source_revision_id, - ])); - } + if (preg_match('/^Copy of the revision from/', $thismsg)) { + $entity->setRevisionLogMessage(t('Copy of revision @rev', [ + '@rev' => $source_revision_id, + ])); } } } @@ -155,21 +155,32 @@ function origins_workflow_entity_update(EntityInterface $entity) { // re-creates the alias, and the code in here deletes it ! // We want the alias deletion to run last so that it really // is deleted. - if (isset($entity->moderation_state)) { - if (($entity->moderation_state->value == 'archived') - && ($entity->original->moderation_state->value == 'published')) { - // This node is being archived, so we need to delete the alias (which - // will enable us to create redirects if we want to). - if (!empty($entity->nid->value)) { - // Get all aliases attached to this node. - $path_alias_storage = \Drupal::entityTypeManager()->getStorage('path_alias'); - $alias_objects = $path_alias_storage->loadByProperties([ - 'path' => '/node/' . $entity->nid->value, - 'langcode' => $entity->language()->getId(), - ]); - // Delete all aliases for this node. - $path_alias_storage->delete($alias_objects); - } + + /** @var \Drupal\content_moderation\Entity\ContentModerationStateInterface $entity_mod_state */ + $entity_mod_state = $entity->moderation_state ?? ''; + + /** @var \Drupal\Core\Entity\ContentEntityBase $original_entity */ + $original_entity = $entity->original ?? ''; + + if (empty($entity->moderation_state) || !$original_entity instanceof ContentEntityBase) { + return; + } + + /** @var \Drupal\content_moderation\Entity\ContentModerationStateInterface $original_mod_state */ + $original_mod_state = $original_entity->moderation_state; + + if ($entity_mod_state->value === 'archived' && $original_mod_state->value === 'published') { + // This node is being archived, so we need to delete the alias (which + // will enable us to create redirects if we want to). + if (!empty($entity->nid->value)) { + // Get all aliases attached to this node. + $path_alias_storage = \Drupal::entityTypeManager()->getStorage('path_alias'); + $alias_objects = $path_alias_storage->loadByProperties([ + 'path' => '/node/' . $entity->nid->value, + 'langcode' => $entity->language()->getId(), + ]); + // Delete all aliases for this node. + $path_alias_storage->delete($alias_objects); } } // Now add processing for moderation sidebar. @@ -630,6 +641,7 @@ function origins_workflow_moderation_sidebar_alter(array &$build, EntityInterfac $build, ['actions', 'primary', 'quick_draft_form', 'draft_of_published'] ); + /** @var \Drupal\Core\Entity\RevisionableInterface $entity */ if ($entity->isLatestRevision() && $dop_link_exists) { // Entity is published, but we have no forward revisions so hide the // draft of published option. @@ -748,12 +760,15 @@ function origins_workflow_entity_operation(EntityInterface $entity) { $revision_id = \Drupal::entityTypeManager() ->getStorage('node') ->getLatestRevisionId($entity->id()); - $revision_moderation_state = \Drupal::entityTypeManager() + + /** @var \Drupal\node\NodeInterface $revision */ + $revision = \Drupal::entityTypeManager() ->getStorage('node') - ->loadRevision($revision_id) - ->moderation_state->value; + ->loadRevision($revision_id); - $node_moderation_state = $entity->moderation_state->value; + $revision_moderation_state = $revision->get('moderation_state')->value; + /** @var \Drupal\node\NodeInterface $entity */ + $node_moderation_state = $entity->get('moderation_state')->value; if ($revision_moderation_state === 'published') { unset($transitions['quick_publish']); diff --git a/origins_workflow/src/Controller/ModerationStateController.php b/origins_workflow/src/Controller/ModerationStateController.php index c4cf5a6e..2f6aedcc 100644 --- a/origins_workflow/src/Controller/ModerationStateController.php +++ b/origins_workflow/src/Controller/ModerationStateController.php @@ -115,15 +115,18 @@ public function changeState($nid, $new_state) { // https://www.drupal.org/project/drupal/issues/2746541 but the answer // seems to be to set it to '1' across the board to solve the problem // of revisions not appearing on the revisions tab. + /** @var \Drupal\Core\Entity\TranslatableRevisionableInterface $entity */ $entity->setRevisionTranslationAffected(1); // Set the owner of the new revision to be the current user // and set an appropriate revision log message. + /** @var \Drupal\Core\Entity\RevisionLogInterface $entity */ $entity->setRevisionUserId($this->currentUser()->id()); $revision_log_message = t('Used quick transition to change state to @new_state', [ '@new_state' => $new_state, ]); $entity->setRevisionLogMessage($revision_log_message); // Request the state change. + /** @var \Drupal\node\NodeInterface $entity */ $entity->set('moderation_state', $new_state); $entity->save(); // Log it. @@ -170,6 +173,7 @@ private function transitionAllowed($entity, String $new_state) { $revision_ids = $this->entityTypeManager->getStorage('node')->revisionIds($entity); $last_revision_id = end($revision_ids); // Load the revision. + /** @var \Drupal\node\NodeInterface $last_revision */ $last_revision = $this->entityTypeManager->getStorage('node')->loadRevision($last_revision_id); $current_state = $last_revision->moderation_state->value; } diff --git a/origins_workflow/src/Form/RevertToModerationStateForm.php b/origins_workflow/src/Form/RevertToModerationStateForm.php index acc8f4bd..17a3b05e 100644 --- a/origins_workflow/src/Form/RevertToModerationStateForm.php +++ b/origins_workflow/src/Form/RevertToModerationStateForm.php @@ -126,6 +126,7 @@ public function getFormId() { * {@inheritdoc} */ public function getQuestion() { + /** @var \Drupal\node\NodeInterface $this */ return t('Are you sure you want to revert the revision @vid as @new_state?', [ '@vid' => $this->vid, '@new_state' => $this->new_state, @@ -136,6 +137,7 @@ public function getQuestion() { * {@inheritdoc} */ public function getCancelUrl() { + /** @var \Drupal\node\NodeInterface $this */ return new Url('entity.node.version_history', ['node' => $this->nid]); } @@ -157,6 +159,7 @@ public function getDescription() { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, $nid = NULL, $vid = NULL, $new_state = 'draft') { + /** @var \Drupal\node\NodeInterface $this */ $this->nid = $nid; $this->vid = $vid; $this->new_state = $new_state; @@ -169,15 +172,19 @@ public function buildForm(array $form, FormStateInterface $form_state, $nid = NU * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { + $node_revision = $this->vid ?? 0; + $node_id = $this->nid ?? 0; + $new_state = $this->new_state ?? ''; // Load the node revision we are reverting. - $node = $this->entityTypeManager->getStorage('node')->loadRevision($this->vid); + /** @var \Drupal\node\NodeInterface $node */ + $node = $this->entityTypeManager->getStorage('node')->loadRevision($node_revision); // Get the moderation state entity. $newStateEntity = $this->moderationInformation ->getWorkflowForEntity($node) ->getTypePlugin() - ->getState($this->new_state); + ->getState($new_state); // Revert the node revision if its valid node and we are reverting to a // valid state. @@ -188,7 +195,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $old_timestamp = $node->getRevisionCreationTime(); // Create new revision in the desired state only if user is allowed. - if ($this->transitionAllowed($old_state, $this->new_state)) { + if ($this->transitionAllowed($old_state, $new_state)) { // Create a new revision. $node->setNewRevision(); @@ -214,7 +221,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Set revision log message. $revision_log_message = t('Copy of revision @vid', [ - '@vid' => $this->vid, + '@vid' => $node_revision, ]); $node->setRevisionLogMessage($revision_log_message); @@ -224,28 +231,28 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Log it. $message = t('Revision @vid of %title (node:@nid) reverted from %old_state to %new_state by %user', [ - '@vid' => $this->vid, + '@vid' => $node_revision, '%title' => $node->getTitle(), - '@nid' => $this->nid, + '@nid' => $node_id, '%old_state' => $old_state, - '%new_state' => $this->new_state, + '%new_state' => $new_state, '%user' => $this->currentUser()->getAccountName(), ]); $this->logger->notice($message); // Show a status message. $this->messenger->addStatus($this->t('Reverted revision %vid from %old_timestamp as %new_state', [ - '%vid' => $this->vid, + '%vid' => $node_revision, '%old_timestamp' => $this->dateFormatter->format($old_timestamp), - '%new_state' => $this->new_state, + '%new_state' => $new_state, ])); } else { $message = t('Revert revision @vid of @title (nid @nid) to @new_state denied to @user', [ - '@vid' => $this->vid, + '@vid' => $node_revision, '@title' => $node->getTitle(), - '@nid' => $this->nid, - '@new_state' => $this->new_state, + '@nid' => $node_id, + '@new_state' => $new_state, '@user' => $this->currentUser()->getAccountName(), ]); $this->logger->error($message); @@ -255,7 +262,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Take the user back to the node revisions overview. $form_state->setRedirect( 'entity.node.version_history', - ['node' => $this->nid] + ['node' => $node_id] ); } diff --git a/origins_workflow/tests/src/Functional/AuditTest.php b/origins_workflow/tests/src/Functional/AuditTest.php index 379e5be6..cd33c03a 100644 --- a/origins_workflow/tests/src/Functional/AuditTest.php +++ b/origins_workflow/tests/src/Functional/AuditTest.php @@ -23,7 +23,7 @@ class AuditTest extends BrowserTestBase { /** * Use install profile so that we have all content types, modules etc. * - * @var installprofile + * @var string */ protected $profile = 'test_profile'; @@ -45,6 +45,20 @@ class AuditTest extends BrowserTestBase { */ protected $entityTypeManager; + /** + * Logger channel service object. + * + * @var \Drupal\Core\Logger\LoggerChannelInterface + */ + protected $logger; + + /** + * User account service object. + * + * @var \Drupal\user\UserInterface + */ + protected $account; + /** * Set to TRUE to strict check all configuration saved. * @@ -59,7 +73,7 @@ class AuditTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->entityTypeManager = $this->container->get('entity_type.manager');