diff --git a/.gitignore b/.gitignore index 1ac1b8d872c5a67cc9059cbb8fc5605ab2910fa2..2b9dc5aae04a4a614122dbb7bef8ca480fa82ba0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ /.gitattributes /.prettierignore /.prettierrc.json -/phpcs.xml.dist /phpstan-baseline.neon /phpstan.neon /vendor/ diff --git a/config/schema/private_message.schema.yml b/config/schema/private_message.schema.yml index a5a8680c738381f017b87f9b39b7380b2b7e4cf2..b6dd17df126e977af19b91dc2ab7f90f889d7dcc 100644 --- a/config/schema/private_message.schema.yml +++ b/config/schema/private_message.schema.yml @@ -26,6 +26,10 @@ private_message.settings: ban_mode: type: string label: 'The blocking mode.' + constraints: + Choice: + - passive + - active ban_message: type: string label: 'The message to show to the user when they are blocked.' diff --git a/modules/private_message_notify/private_message_notify.api.php b/modules/private_message_notify/private_message_notify.api.php index 2a57e695f5cd440b58018b999612b80e36fae014..7e39ca55a6d8a31ebe553585bc7fe9312c23bfb5 100644 --- a/modules/private_message_notify/private_message_notify.api.php +++ b/modules/private_message_notify/private_message_notify.api.php @@ -5,6 +5,8 @@ * Hook documentation for Private Message Notify module hooks. */ +declare(strict_types=1); + use Drupal\private_message\Entity\PrivateMessageInterface; use Drupal\private_message\Entity\PrivateMessageThreadInterface; diff --git a/modules/private_message_notify/private_message_notify.info.yml b/modules/private_message_notify/private_message_notify.info.yml index 4d664be40b8b7717d15c8072199c1c01d163301f..95b8411384b31a6fa623e7ba85f11de2bb6d88cc 100644 --- a/modules/private_message_notify/private_message_notify.info.yml +++ b/modules/private_message_notify/private_message_notify.info.yml @@ -2,7 +2,7 @@ name: Private Message Notify type: module description: Implements new message notifications. package: Private Message -core_version_requirement: ^9.3 || ^10 || ^11 +core_version_requirement: ^10.3 || ^11 dependencies: - message_notify:message_notify - private_message:private_message diff --git a/modules/private_message_notify/private_message_notify.module b/modules/private_message_notify/private_message_notify.module index 93b8b83810d65666601eb1f72452f6869de4bba5..b70f1db1fd71b0224d1d45b9fa41166f8a1fc77d 100644 --- a/modules/private_message_notify/private_message_notify.module +++ b/modules/private_message_notify/private_message_notify.module @@ -5,13 +5,15 @@ * Primary module hooks for Private Message Notify module. */ +declare(strict_types=1); + use Drupal\private_message\Entity\PrivateMessageInterface; use Drupal\private_message\Entity\PrivateMessageThreadInterface; /** * Implements hook_private_message_new_message(). */ -function private_message_notify_private_message_new_message(PrivateMessageInterface $privateMessage, PrivateMessageThreadInterface $thread) { +function private_message_notify_private_message_new_message(PrivateMessageInterface $privateMessage, PrivateMessageThreadInterface $thread): void { /** @var \Drupal\private_message_notify\Service\PrivateMessageNotifierInterface $notifier */ $notifier = \Drupal::service('private_message_notify.notifier'); $notifier->notify($privateMessage, $thread); diff --git a/modules/private_message_notify/private_message_notify.services.yml b/modules/private_message_notify/private_message_notify.services.yml index 1af995bd3715c6b8c6cf92b9ecdab2844bacde1b..45c72776fa029f0d53df5a02e13121249ead4ba9 100644 --- a/modules/private_message_notify/private_message_notify.services.yml +++ b/modules/private_message_notify/private_message_notify.services.yml @@ -1,12 +1,8 @@ services: + + _defaults: + autoconfigure: true + autowire: true + private_message_notify.notifier: class: Drupal\private_message_notify\Service\PrivateMessageNotifier - arguments: - - '@private_message.service' - - '@current_user' - - '@user.data' - - '@config.factory' - - '@entity_type.manager' - - '@message_notify.sender' - - '@module_handler' - - '@logger.factory' diff --git a/modules/private_message_notify/src/Service/PrivateMessageNotifier.php b/modules/private_message_notify/src/Service/PrivateMessageNotifier.php index 18d7f7355b8577cebe77425f6599d38a5879493f..fc052ea599978a9e9ab6af9e9eb3818087d70df4 100644 --- a/modules/private_message_notify/src/Service/PrivateMessageNotifier.php +++ b/modules/private_message_notify/src/Service/PrivateMessageNotifier.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message_notify\Service; use Drupal\Core\Config\ConfigFactoryInterface; @@ -12,114 +14,34 @@ use Drupal\message_notify\MessageNotifier; use Drupal\private_message\Entity\PrivateMessageInterface; use Drupal\private_message\Entity\PrivateMessageThreadInterface; use Drupal\private_message\Service\PrivateMessageServiceInterface; +use Drupal\private_message\Traits\PrivateMessageSettingsTrait; use Drupal\user\UserDataInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * A service class for sending notifications of private messages. */ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { - /** - * The private message service. - * - * @var \Drupal\private_message\Service\PrivateMessageServiceInterface - */ - protected $privateMessageService; - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected $currentUser; - - /** - * The user data service. - * - * @var \Drupal\user\UserDataInterface - */ - protected $userData; - - /** - * The configuration factory service. - * - * @var \Drupal\Core\Config\ImmutableConfig - */ - protected $config; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * The message notification service. - * - * @var \Drupal\message_notify\MessageNotifier - */ - protected $messageNotifier; - - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * The logger service for private message notifications. - * - * @var \Drupal\Core\Logger\LoggerChannelInterface - */ - protected $logger; + use PrivateMessageSettingsTrait; - /** - * Constructs a new PrivateMessageNotifier object. - * - * @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService - * The private message service. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\user\UserDataInterface $userData - * The user data service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * The configuration factory service. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager service. - * @param \Drupal\message_notify\MessageNotifier $messageNotifier - * The message notification service. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler - * The module handler service. - * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerFactory - * The logger channel factory. - */ public function __construct( - PrivateMessageServiceInterface $privateMessageService, - AccountProxyInterface $currentUser, - UserDataInterface $userData, - ConfigFactoryInterface $configFactory, - EntityTypeManagerInterface $entityTypeManager, - MessageNotifier $messageNotifier, - ModuleHandlerInterface $moduleHandler, - LoggerChannelFactoryInterface $loggerFactory, - ) { - $this->privateMessageService = $privateMessageService; - $this->currentUser = $currentUser; - $this->userData = $userData; - $this->config = $configFactory->get('private_message.settings'); - $this->entityTypeManager = $entityTypeManager; - $this->messageNotifier = $messageNotifier; - $this->moduleHandler = $moduleHandler; - $this->logger = $loggerFactory->get('private_message_notify'); - } + protected readonly PrivateMessageServiceInterface $privateMessageService, + protected readonly AccountProxyInterface $currentUser, + protected readonly UserDataInterface $userData, + protected readonly ConfigFactoryInterface $configFactory, + protected readonly EntityTypeManagerInterface $entityTypeManager, + #[Autowire(service: 'message_notify.sender')] + protected readonly MessageNotifier $messageNotifier, + protected readonly ModuleHandlerInterface $moduleHandler, + protected readonly LoggerChannelFactoryInterface $loggerFactory, + ) {} /** * {@inheritdoc} */ - public function notify(PrivateMessageInterface $message, PrivateMessageThreadInterface $thread) { - $members = $this->getNotificationRecipients($message, $thread); + public function notify(PrivateMessageInterface $message, PrivateMessageThreadInterface $thread): void { + $members = $this->getRecipients($message, $thread); foreach ($members as $member) { // Skip the current user and any member without a valid email. @@ -131,7 +53,10 @@ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { $email = $member->getEmail(); if (empty($email)) { // Log a warning if the email is missing, then skip this member. - $this->logger->warning('Notification not sent to user ID @uid due to missing email.', ['@uid' => $member->id()]); + $this->loggerFactory->get('private_message_notify') + ->warning('Notification not sent to user ID @uid due to missing email.', [ + '@uid' => $member->id(), + ]); continue; } @@ -143,14 +68,12 @@ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { // Create and send the notification. $notification = $this->entityTypeManager ->getStorage('message') - ->create( - [ - 'template' => 'private_message_notification', - 'uid' => $member->id(), - ] - ); - $notification->set('field_message_private_message', $message); - $notification->set('field_message_pm_thread', $thread); + ->create([ + 'template' => 'private_message_notification', + 'uid' => $member->id(), + 'field_message_private_message' => $message, + 'field_message_pm_thread' => $thread, + ]); $notification->setLanguage($member->getPreferredLangcode()); $notification->save(); @@ -171,15 +94,14 @@ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { * The private message thread. * * @return bool - * A boolean indicating whether or not the message should be sent. + * A boolean indicating whether the message should be sent. */ - private function shouldSend(AccountInterface $recipient, PrivateMessageInterface $message, PrivateMessageThreadInterface $thread) { - + private function shouldSend(AccountInterface $recipient, PrivateMessageInterface $message, PrivateMessageThreadInterface $thread): bool { // Don't notify the user by default. $notify = FALSE; // Check if notifications have been enabled. - if ($this->config->get('enable_notifications')) { + if ($this->getPrivateMessageSettings()->get('enable_notifications')) { // Eligibility to receive notifications will be checked. $eligible_to_receive = FALSE; @@ -192,7 +114,7 @@ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { } // Check if the user has not made any selection, and the system default is // to send: - elseif (is_null($user_default) && $this->config->get('notify_by_default')) { + elseif (is_null($user_default) && $this->getPrivateMessageSettings()->get('notify_by_default')) { $eligible_to_receive = TRUE; } @@ -207,7 +129,7 @@ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { // Check if the user has not yet set a value. if (is_null($notify_when_using)) { // The user has not yet set a value, so use the system default. - $notify_when_using = $this->config->get('notify_when_using'); + $notify_when_using = $this->getPrivateMessageSettings()->get('notify_when_using'); } // Get the number of seconds a user has set in their profile, after @@ -216,7 +138,7 @@ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { // Check if the user has not yet set a value. if (is_null($away_time)) { // The user has not yet set a value, so use the system default. - $away_time = $this->config->get('number_of_seconds_considered_away'); + $away_time = $this->getPrivateMessageSettings()->get('number_of_seconds_considered_away'); } // Check if users should always be notified. @@ -234,26 +156,22 @@ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { } /** - * The users to receive notifications. + * Returns the list of recipients as user accounts. * * @return \Drupal\Core\Session\AccountInterface[] - * An array of Account objects of the thread members who are to receive - * the notification. + * Array of thread members user entities receiving the notification. */ - public function getNotificationRecipients(PrivateMessageInterface $message, PrivateMessageThreadInterface $thread) { + protected function getRecipients(PrivateMessageInterface $message, PrivateMessageThreadInterface $thread): array { $recipients = $thread->getMembers(); $exclude = []; // Allow other modules to alter notification recipients. - $this->moduleHandler->invokeAll( - 'private_message_notify_exclude', [ - $message, - $thread, - &$exclude, - ] - ); + $this->moduleHandler->invokeAll('private_message_notify_exclude', [ + $message, + $thread, + &$exclude, + ]); - // @phpstan-ignore-next-line if (empty($exclude)) { return $recipients; } @@ -267,4 +185,21 @@ class PrivateMessageNotifier implements PrivateMessageNotifierInterface { ); } + /** + * The users to receive notifications. + * + * @return \Drupal\Core\Session\AccountInterface[] + * An array of Account objects of the thread members who are to receive + * the notification. + * + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. Instead, use self ::getRecipients() + * + * @see https://www.drupal.org/node/3490530 + */ + public function getNotificationRecipients(PrivateMessageInterface $message, PrivateMessageThreadInterface $thread) { + @trigger_error(__METHOD__ . '() is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. Instead, use self ::getRecipients(). See https://www.drupal.org/node/3490530', E_USER_DEPRECATED); + return $this->getRecipients($message, $thread); + } + } diff --git a/modules/private_message_notify/src/Service/PrivateMessageNotifierInterface.php b/modules/private_message_notify/src/Service/PrivateMessageNotifierInterface.php index e43c62af352c6943814c945e44d32e225b5ac5d2..eafcd09deb82b660cdd0ecc4dac7ad9181182e11 100644 --- a/modules/private_message_notify/src/Service/PrivateMessageNotifierInterface.php +++ b/modules/private_message_notify/src/Service/PrivateMessageNotifierInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message_notify\Service; use Drupal\private_message\Entity\PrivateMessageInterface; diff --git a/modules/private_message_notify/tests/modules/private_message_notify_test/private_message_notify_test.info.yml b/modules/private_message_notify/tests/modules/private_message_notify_test/private_message_notify_test.info.yml index 1189ffd6b469979cdac59cb432a56a1ba80ee749..88d983caca7d5ec39706c0e90473b8e8e04eebcb 100644 --- a/modules/private_message_notify/tests/modules/private_message_notify_test/private_message_notify_test.info.yml +++ b/modules/private_message_notify/tests/modules/private_message_notify_test/private_message_notify_test.info.yml @@ -1,6 +1,6 @@ type: module name: Private Message Notify Test package: Testing -core_version_requirement: ^9.3 || ^10 || ^11 +core_version_requirement: ^10.3 || ^11 dependencies: - private_message:private_message_notify diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000000000000000000000000000000000000..e7717fd532318bfd39c17af05deb8eac2d76a0f2 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ruleset name="private_message"> + <description>PHP CodeSniffer configuration for Private Message module.</description> + <rule ref="vendor/drupal/coder/coder_sniffer/Drupal/ruleset.xml"/> + <arg name="extensions" value="php,inc,module,install,info,test,profile,theme"/> + + <!-- Strict typing & type hinting rules --> + <rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing"> + <severity>5</severity> + <!-- TODO: Remove these two exclusions in private_message:5.0.0 --> + <exclude-pattern>src/Mapper/PrivateMessageMapper.php</exclude-pattern> + <exclude-pattern>src/Mapper/PrivateMessageMapperInterface.php</exclude-pattern> + </rule> +</ruleset> diff --git a/private_message.api.php b/private_message.api.php index 383a616fc2e52c3da6d6a76bfd06828e1460af13..d8aec0e1fbb621fa84b9600195b40c1d6d36108a 100644 --- a/private_message.api.php +++ b/private_message.api.php @@ -5,6 +5,8 @@ * Hook documentation for Private Message module hooks. */ +declare(strict_types=1); + use Drupal\Core\Entity\EntityInterface; use Drupal\private_message\Entity\PrivateMessageInterface; use Drupal\private_message\Entity\PrivateMessageThreadInterface; @@ -19,7 +21,7 @@ use Drupal\private_message\Entity\PrivateMessageThreadInterface; * @param string $viewMode * The view mode being rendered on the private message. */ -function hook_private_message_view_alter(array &$build, EntityInterface $privateMessage, $viewMode) { +function hook_private_message_view_alter(array &$build, EntityInterface $privateMessage, string $viewMode): void { // Create a new class specific to the author of the message. $class = 'private-message-author-' . $privateMessage->getOwnerId(); // Add the class to the wrapper. diff --git a/private_message.info.yml b/private_message.info.yml index c0428b7f3e02792189d0cca54ee1e543197eee2a..bda6a9055b82ed60e549d033e82e4ee5aad41d59 100644 --- a/private_message.info.yml +++ b/private_message.info.yml @@ -1,6 +1,6 @@ name: Private Message description: A private message system for users to send messages to each other -core_version_requirement: ^10 || ^11 +core_version_requirement: ^10.3 || ^11 type: module package: Private Message diff --git a/private_message.install b/private_message.install index 6b3379dc7755300e5808a4bbb0df85c1e163b626..c84a9875ec2e582c487399195aee342349af79a1 100644 --- a/private_message.install +++ b/private_message.install @@ -5,14 +5,16 @@ * Holds install and update hooks for the Private Message module. */ +declare(strict_types=1); + use Drupal\Core\Database\IntegrityConstraintViolationException; use Drupal\Core\Field\BaseFieldDefinition; -use Drupal\private_message\Form\ConfigForm as Config; +use Drupal\private_message\Model\BlockType; /** * Implements hook_install(). */ -function private_message_install() { +function private_message_install(): void { $messenger = \Drupal::messenger(); $messenger->addStatus(t('Make sure you granted "use private messaging system" and "access user profiles" permissions for roles you want to provide access to use private messages.')); $messenger->addStatus(t('Enable "Private Message Actions" and "Private Message Inbox" block to have simple private message UI from the box.')); @@ -21,7 +23,7 @@ function private_message_install() { /** * Implements hook_uninstall(). */ -function private_message_uninstall() { +function private_message_uninstall(): void { \Drupal::configFactory()->getEditable('core.entity_view_display.user.user.private_message_author')->delete(); \Drupal::configFactory()->getEditable('core.entity_view_mode.user.private_message_author')->delete(); \Drupal::configFactory()->getEditable('message.template.private_message_notification')->delete(); @@ -31,41 +33,10 @@ function private_message_uninstall() { \Drupal::configFactory()->getEditable('core.entity_view_display.message.private_message_notification.default')->delete(); } -/** - * Implements hook_update_n(). - */ -function private_message_update_8001() { - $config_factory = \Drupal::configFactory(); - - $config_factory->getEditable('private_message.settings') - ->set('enable_email_notifications', TRUE) - ->set('send_by_default', TRUE) - ->save(TRUE); - - $message_notification_mail_map = [ - 'subject' => 'Private message at [site:name]', - 'body' => "[user:display-name],\n\nYou have received a private message at [site:name] from [private_message:author_name]\n\nThe message is as follows:\n\n[private_message:message]\n\nYou can view the entire thread and reply to this message at:\n\n[private_message_thread:url]\n\n\nThank you,\n\n-- [site:name]", - ]; - - $config_factory->getEditable('private_message.mail') - ->set('message_notification', $message_notification_mail_map) - ->save(TRUE); -} - -/** - * Add the create private message label. - */ -function private_message_update_8002() { - $config_factory = \Drupal::configFactory(); - $config_factory->getEditable('private_message.settings') - ->set('create_message_label', 'Create Private Message') - ->save(TRUE); -} - /** * Implements hook_schema(). */ -function private_message_schema() { +function private_message_schema(): array { $schema['pm_thread_history'] = [ 'description' => 'A record of which {users} have read which {node}s.', 'fields' => [ @@ -104,10 +75,41 @@ function private_message_schema() { return $schema; } +/** + * Implements hook_update_n(). + */ +function private_message_update_8001(): void { + $config_factory = \Drupal::configFactory(); + + $config_factory->getEditable('private_message.settings') + ->set('enable_email_notifications', TRUE) + ->set('send_by_default', TRUE) + ->save(TRUE); + + $message_notification_mail_map = [ + 'subject' => 'Private message at [site:name]', + 'body' => "[user:display-name],\n\nYou have received a private message at [site:name] from [private_message:author_name]\n\nThe message is as follows:\n\n[private_message:message]\n\nYou can view the entire thread and reply to this message at:\n\n[private_message_thread:url]\n\n\nThank you,\n\n-- [site:name]", + ]; + + $config_factory->getEditable('private_message.mail') + ->set('message_notification', $message_notification_mail_map) + ->save(TRUE); +} + /** * Add the create private message label. */ -function private_message_update_8003() { +function private_message_update_8002(): void { + $config_factory = \Drupal::configFactory(); + $config_factory->getEditable('private_message.settings') + ->set('create_message_label', 'Create Private Message') + ->save(TRUE); +} + +/** + * Add the create private message label. + */ +function private_message_update_8003(): void { $config_factory = \Drupal::configFactory(); $config_factory->getEditable('private_message.settings') ->set('create_message_label', 'Create Private Message') @@ -117,7 +119,7 @@ function private_message_update_8003() { /** * Install the module schema. */ -function private_message_update_8004() { +function private_message_update_8004(): void { $database = \Drupal::database(); // Create database table. @@ -162,7 +164,7 @@ function private_message_update_8004() { /** * Migrate the records into a new table. */ -function private_message_update_8005(&$sandbox) { +function private_message_update_8005(?array &$sandbox = NULL): void { // Store last processed thread ID, so the sites with a huge amount of threads // will have at least some chances to complete this update in a few runs. $last_processed = \Drupal::state()->get('scalable_bridge_last', 0); @@ -259,7 +261,7 @@ function private_message_update_8005(&$sandbox) { /** * Drop the old entity types and field definitions. */ -function private_message_update_8006(&$sandbox) { +function private_message_update_8006(?array &$sandbox = NULL): void { $entity_update_manager = \Drupal::entityDefinitionUpdateManager(); foreach (['pm_thread_access_time', 'pm_thread_delete_time'] as $entity_type_id) { if ($entity_type = $entity_update_manager->getEntityType($entity_type_id)) { @@ -276,7 +278,7 @@ function private_message_update_8006(&$sandbox) { /** * Enable notifications submodule. */ -function private_message_update_8007() { +function private_message_update_8007(): void { // Delete the configs that will be migrated to private_message_notify. // Only delete configurations if private_message_notify is not installed // already. @@ -361,7 +363,7 @@ function private_message_update_8008() { /** * Skip update because of unnecessary. */ -function private_message_update_8009() { +function private_message_update_8009(): void { // Leave this hook update empty because it already passed who applied patch // from issue https://www.drupal.org/project/private_message/issues/3265901 } @@ -369,7 +371,7 @@ function private_message_update_8009() { /** * Skip update because of unnecessary. */ -function private_message_update_8010() { +function private_message_update_8010(): void { // Leave this hook update empty because it already passed who applied patch // from issue https://www.drupal.org/project/private_message/issues/3265901 } @@ -377,24 +379,21 @@ function private_message_update_8010() { /** * Install the private_message_ban entity type. */ -function private_message_update_8011() { - - if (!\Drupal::database()->schema()->tableExists('private_message_ban')) { - \Drupal::entityTypeManager()->clearCachedDefinitions(); - \Drupal::entityDefinitionUpdateManager()->installEntityType(\Drupal::entityTypeManager()->getDefinition('private_message_ban')); - } - else { +function private_message_update_8011(): string { + if (\Drupal::database()->schema()->tableExists('private_message_ban')) { return 'Private Message Ban entity already exists'; } - + \Drupal::entityTypeManager()->clearCachedDefinitions(); + \Drupal::entityDefinitionUpdateManager()->installEntityType(\Drupal::entityTypeManager()->getDefinition('private_message_ban')); + return 'Installed Private Message Ban entity'; } /** * Sets default values for the block functionality. */ -function private_message_update_8012() { +function private_message_update_8012(): void { \Drupal::configFactory()->getEditable('private_message.settings') - ->set('ban_mode', Config::PASSIVE) + ->set('ban_mode', BlockType::Passive->value) ->set('ban_message', 'User is unable to receive your message') ->set('ban_label', 'Block') ->set('unban_label', 'Unblock') @@ -404,7 +403,7 @@ function private_message_update_8012() { /** * Install the `subject` field to 'private_message_thread' entity. */ -function private_message_update_8013() { +function private_message_update_8013(): void { $storage_definition = BaseFieldDefinition::create('string') ->setLabel(t('Subject')) ->setSetting('max_length', 64) @@ -422,7 +421,7 @@ function private_message_update_8013() { /** * Show input formats functionality. */ -function private_message_update_8014() { +function private_message_update_8014(): void { $config = \Drupal::configFactory() ->getEditable('private_message.settings'); $rows = $config->getRawData(); diff --git a/private_message.module b/private_message.module index 0f4efb742b830409b151e3d653f83478a6afa0c9..26f2452ca6e068941452018dc6fa9cace57cd5f4 100644 --- a/private_message.module +++ b/private_message.module @@ -5,6 +5,9 @@ * Contains hooks for the private message module. */ +declare(strict_types=1); + +use Drupal\Component\Render\MarkupInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; @@ -17,7 +20,7 @@ use Drupal\user\Entity\User; /** * Implements hook_views_data(). */ -function private_message_views_data() { +function private_message_views_data(): array { $data['private_message_threads']['has_history'] = [ 'title' => t('Clean history'), 'group' => t('Private Message Thread'), @@ -86,7 +89,7 @@ function private_message_views_data() { /** * Implements hook_entity_extra_field_info(). */ -function private_message_entity_extra_field_info() { +function private_message_entity_extra_field_info(): array { $fields = []; $private_message_thread_bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo('private_message_thread'); @@ -206,7 +209,7 @@ function private_message_entity_extra_field_info() { * * @see hook_entity_view() */ -function private_message_private_message_thread_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { +function private_message_private_message_thread_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void { if ($display->getComponent('last_message')) { $messages = $entity->getMessages(); if ($messages) { @@ -276,8 +279,7 @@ function private_message_private_message_thread_view(array &$build, EntityInterf * * @see hook_entity_view() */ -function private_message_user_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { - +function private_message_user_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void { if ($display->getComponent('linked_username')) { if (\Drupal::currentUser()->hasPermission('access user profiles')) { $url = Url::fromRoute('entity.user.canonical', ['user' => $entity->id()]); @@ -347,7 +349,7 @@ function private_message_user_view(array &$build, EntityInterface $entity, Entit * * @see hook_entity_view() */ -function private_message_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { +function private_message_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void { \Drupal::service('private_message.service')->createRenderablePrivateMessageThreadLink($build, $entity, $display, $view_mode); } @@ -358,7 +360,7 @@ function private_message_node_view(array &$build, EntityInterface $entity, Entit * * @see hook_entity_view() */ -function private_message_comment_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { +function private_message_comment_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void { \Drupal::service('private_message.service')->createRenderablePrivateMessageThreadLink($build, $entity, $display, $view_mode); } @@ -369,14 +371,14 @@ function private_message_comment_view(array &$build, EntityInterface $entity, En * * @see hook_entity_view() */ -function private_message_profile_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { +function private_message_profile_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void { \Drupal::service('private_message.service')->createRenderablePrivateMessageThreadLink($build, $entity, $display, $view_mode); } /** * Implements hook_form_alter(). */ -function private_message_form_alter(&$form, FormStateInterface $formState, $form_id) { +function private_message_form_alter(array &$form, FormStateInterface $formState, string $form_id): void { // Act on any implementation of the private message entity form. This form // can potentially exist multiple times on a page, so the form ID will be // dynamic in such a case. @@ -403,8 +405,7 @@ function private_message_form_alter(&$form, FormStateInterface $formState, $form * * @see hook_form_alter() */ -function private_message_form_user_form_alter(array &$form, FormStateInterface $formState) { - +function private_message_form_user_form_alter(array &$form, FormStateInterface $formState): void { $config = \Drupal::config('private_message.settings'); // Get the user whose account is being modified. @@ -503,7 +504,7 @@ function private_message_form_user_form_alter(array &$form, FormStateInterface $ * * @see private_message_form_user_form_alter() */ -function private_message_user_form_submit(array &$form, FormStateInterface $formState) { +function private_message_user_form_submit(array &$form, FormStateInterface $formState): void { // Get the user whose account object is being modified. $user = $formState->getFormObject()->getEntity(); $user_data = \Drupal::service('user.data'); @@ -525,7 +526,7 @@ function private_message_user_form_submit(array &$form, FormStateInterface $form /** * Implements hook_theme(). */ -function private_message_theme() { +function private_message_theme(): array { return [ 'private_message_thread' => [ 'render element' => 'elements', @@ -557,7 +558,7 @@ function private_message_theme() { * - private_message_thread: The private message thread object. * - view_mode: View mode; e.g., 'full', 'teaser', etc. */ -function template_preprocess_private_message_thread(array &$variables) { +function template_preprocess_private_message_thread(array &$variables): void { $variables['view_mode'] = $variables['elements']['#view_mode']; // Provide a distinct $teaser boolean. $variables['private_message_thread'] = $variables['elements']['#private_message_thread']; @@ -587,7 +588,7 @@ function template_preprocess_private_message_thread(array &$variables) { * - private_message: The private message object. * - view_mode: View mode; e.g., 'full', 'teaser', etc. */ -function template_preprocess_private_message(array &$variables) { +function template_preprocess_private_message(array &$variables): void { $variables['view_mode'] = $variables['elements']['#view_mode']; // Provide a distinct $teaser boolean. $variables['private_message'] = $variables['elements']['#private_message']; @@ -608,7 +609,7 @@ function template_preprocess_private_message(array &$variables) { /** * Implements hook_help(). */ -function private_message_help($route_name, RouteMatchInterface $route_match) { +function private_message_help($route_name, RouteMatchInterface $route_match): string|array|MarkupInterface { switch ($route_name) { case 'help.page.private_message': return t( @@ -619,6 +620,7 @@ function private_message_help($route_name, RouteMatchInterface $route_match) { ] ); } + return []; } /** @@ -628,7 +630,7 @@ function private_message_help($route_name, RouteMatchInterface $route_match) { * may be altered in themes/templates, and therefore should not be depended * upon. */ -function private_message_preprocess_field__private_message_thread__private_messages(&$vars) { +function private_message_preprocess_field__private_message_thread__private_messages(array &$vars): void { foreach (array_keys($vars['items']) as $index) { $vars['items'][$index]['attributes']->setAttribute('class', 'private-message-wrapper'); } @@ -641,7 +643,7 @@ function private_message_preprocess_field__private_message_thread__private_messa * classes may be altered in themes/templates, and therefore should not be * depended upon. */ -function private_message_preprocess_container(&$vars) { +function private_message_preprocess_container(array &$vars): void { if (!empty($vars['element']['#id'])) { if (str_starts_with($vars['element']['#id'], 'edit-members-wrapper')) { // Add a custom class to the private message members widget container. @@ -659,7 +661,7 @@ function private_message_preprocess_container(&$vars) { * * Swaps out tokens with values. */ -function private_message_message_view_alter(array &$build) { +function private_message_message_view_alter(array &$build): void { if ($build['#message']->bundle() == 'private_message_notification') { $data = [ 'private_message' => $build['#message']->get('field_message_private_message')->entity, @@ -679,13 +681,13 @@ function private_message_message_view_alter(array &$build) { /** * Implements hook_suggestions_HOOK_alter(). */ -function private_message_theme_suggestions_private_message_thread_alter(&$suggestions, &$vars) { +function private_message_theme_suggestions_private_message_thread_alter(array &$suggestions, array &$vars): void { $suggestions[] = 'private_message_thread__' . $vars['elements']['#view_mode']; } /** * Implements hook_suggestions_HOOK_alter(). */ -function private_message_theme_suggestions_private_message_alter(&$suggestions, &$vars) { +function private_message_theme_suggestions_private_message_alter(array &$suggestions, array &$vars): void { $suggestions[] = 'private_message__' . $vars['elements']['#view_mode']; } diff --git a/private_message.routing.yml b/private_message.routing.yml index 8eba08914a39333084590ca8ea77070d525e96be..b389f2f2fbf636ae01eba95bc2bdf3e4548c8cfd 100644 --- a/private_message.routing.yml +++ b/private_message.routing.yml @@ -7,7 +7,7 @@ private_message.private_message_page: _permission: 'use private messaging system,access user profiles' _user_is_logged_in: 'TRUE' options: - no_cache: 'TRUE' + no_cache: TRUE entity.private_message_thread.canonical: path: '/private-messages/{private_message_thread}' @@ -147,6 +147,7 @@ private_message.ban_user_form: requirements: _permission: 'use private messaging system,access user profiles' _user_is_logged_in: 'TRUE' + user: \d+ options: parameters: user: diff --git a/private_message.services.yml b/private_message.services.yml index 97f8362dcb89185301733db0ab10d5d6181fb0ef..ba9c4c535ea0e2200dbbb8c6869a62d1d3fcec32 100644 --- a/private_message.services.yml +++ b/private_message.services.yml @@ -1,44 +1,35 @@ services: - private_message.mapper: - class: Drupal\private_message\Mapper\PrivateMessageMapper - arguments: - - '@database' - - '@current_user' + + _defaults: + autoconfigure: true + autowire: true private_message.service: class: Drupal\private_message\Service\PrivateMessageService - arguments: - - '@private_message.mapper' - - '@current_user' - - '@config.factory' - - '@user.data' - - '@cache_tags.invalidator' - - '@entity_type.manager' - - '@datetime.time' + Drupal\private_message\Service\PrivateMessageServiceInterface: '@private_message.service' private_message.uninstaller: class: Drupal\private_message\Service\PrivateMessageUninstaller + Drupal\private_message\Service\PrivateMessageUninstallerInterface: '@private_message.uninstaller' private_message.ban_manager: class: Drupal\private_message\Service\PrivateMessageBanManager - arguments: - - '@current_user' - - '@entity_type.manager' - - '@database' - - '@messenger' + Drupal\private_message\Service\PrivateMessageBanManagerInterface: '@private_message.ban_manager' cache_context.private_message_thread: class: Drupal\private_message\Cache\Context\PrivateMessageThreadCacheContext - arguments: - - '@current_route_match' tags: - { name: cache.context } private_message.thread_manager: class: Drupal\private_message\Service\PrivateMessageThreadManager - arguments: - - '@private_message.service' + Drupal\private_message\Service\PrivateMessageThreadManagerInterface: '@private_message.thread_manager' private_message.private_message_config_form_manager: class: Drupal\private_message\PluginManager\PrivateMessageConfigFormManager parent: default_plugin_manager + Drupal\private_message\PluginManager\PrivateMessageConfigFormManagerInterface: '@private_message.private_message_config_form_manager' + + private_message.mapper: + class: Drupal\private_message\Mapper\PrivateMessageMapper + deprecated: The "%service_id%" service is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. No replacement is provided. See https://www.drupal.org/node/3490530 diff --git a/private_message.theme.inc b/private_message.theme.inc index c9d672142a4b21f65af19374d1d7658fd6f88d42..7cd903f13913533cb19f18d457efc488545b5516 100644 --- a/private_message.theme.inc +++ b/private_message.theme.inc @@ -5,13 +5,15 @@ * Contains preprocess functions for the private message module. */ +declare(strict_types=1); + use Drupal\Core\Link; use Drupal\Core\Url; /** * Implements hook_preprocess_private_message_notification_block(). */ -function template_preprocess_private_message_notification_block(&$vars) { +function template_preprocess_private_message_notification_block(array &$vars): void { $vars['notification_image_path'] = base_path() . \Drupal::service('extension.list.module')->getPath('private_message') . '/images/private-message-notification-icon.png'; switch ($vars['count_method']) { diff --git a/private_message.tokens.inc b/private_message.tokens.inc index 429f4b17e8f4447781b0a0c9202d688ff1ff9705..7c5dec4b5b8c9ece10e77d7b26ebe09f27b756cb 100644 --- a/private_message.tokens.inc +++ b/private_message.tokens.inc @@ -5,6 +5,8 @@ * Provides tokens for the Private Message module. */ +declare(strict_types=1); + use Drupal\Core\Datetime\Entity\DateFormat; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Render\BubbleableMetadata; @@ -14,8 +16,7 @@ use Drupal\user\Entity\User; /** * Implements hook_token_info(). */ -function private_message_token_info() { - +function private_message_token_info(): array { // Defined the private message token type. $private_message_type = [ 'name' => t('Private Messages'), @@ -89,7 +90,7 @@ function private_message_token_info() { /** * Implements hook_tokens(). */ -function private_message_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) { +function private_message_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata): array { $replacements = []; $token_service = \Drupal::token(); diff --git a/src/Ajax/PrivateMessageInboxInsertThreadsCommand.php b/src/Ajax/PrivateMessageInboxInsertThreadsCommand.php index bdc11efcdc0a0feb4177dac5eb2750cce54d2fb1..7aec9232b6272dc26c094c1c2bef9a16c2d39a9b 100644 --- a/src/Ajax/PrivateMessageInboxInsertThreadsCommand.php +++ b/src/Ajax/PrivateMessageInboxInsertThreadsCommand.php @@ -1,49 +1,31 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Ajax; +use Drupal\Component\Render\MarkupInterface; use Drupal\Core\Ajax\CommandInterface; /** - * Ajax Command to insert private message inbox threads. + * Ajax command to insert private message inbox threads. */ class PrivateMessageInboxInsertThreadsCommand implements CommandInterface { - /** - * The HTML for the threads to be inserted in the page. - * - * @var string - */ - protected $threads; - - /** - * Boolean to determine if there are more threads to come. - * - * @var bool - */ - protected $hasNext; - - /** - * Constructs a PrivateMessageInboxInsertThreadsCommand object. - * - * @param string $threads - * The HTML for the threads to be inserted in the page. - * @param bool $has_next - * A boolean to know if there are more threads after. - */ - public function __construct($threads, $has_next) { - $this->threads = $threads; - $this->hasNext = $has_next; + public function __construct( + protected readonly MarkupInterface|string $threads, + protected readonly bool $hasMoreThreads, + ) { } /** * {@inheritdoc} */ - public function render() { + public function render(): array { return [ 'command' => 'insertInboxOldPrivateMessageThreads', - 'threads' => $this->threads, - 'hasNext' => $this->hasNext, + 'threads' => (string) $this->threads, + 'hasNext' => $this->hasMoreThreads, ]; } diff --git a/src/Ajax/PrivateMessageInboxTriggerUpdateCommand.php b/src/Ajax/PrivateMessageInboxTriggerUpdateCommand.php index 0e89b4c60563fefe15dc45fe9f7b029043bd35d8..bfac8d884f39751ba50814bf725524325cb8f5bb 100644 --- a/src/Ajax/PrivateMessageInboxTriggerUpdateCommand.php +++ b/src/Ajax/PrivateMessageInboxTriggerUpdateCommand.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Ajax; use Drupal\Core\Ajax\CommandInterface; @@ -12,7 +14,7 @@ class PrivateMessageInboxTriggerUpdateCommand implements CommandInterface { /** * {@inheritdoc} */ - public function render() { + public function render(): array { return [ 'command' => 'privateMessageTriggerInboxUpdate', ]; diff --git a/src/Ajax/PrivateMessageInboxUpdateCommand.php b/src/Ajax/PrivateMessageInboxUpdateCommand.php index e155e242b5e97345957c31e9e75de74272ce0e79..c2e2c5a547877fb4f44d8260d01a5b5ad5044fa5 100644 --- a/src/Ajax/PrivateMessageInboxUpdateCommand.php +++ b/src/Ajax/PrivateMessageInboxUpdateCommand.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Ajax; use Drupal\Core\Ajax\CommandInterface; @@ -10,21 +12,7 @@ use Drupal\Core\Ajax\CommandInterface; class PrivateMessageInboxUpdateCommand implements CommandInterface { /** - * The thread IDs, in the order that they should appear upon update. - * - * @var array - */ - protected $threadIds; - - /** - * HTML for any threads that don't currently exist in the inbox. - * - * @var array - */ - protected $newThreads; - - /** - * Constructs a PrivateMessageInboxUpdateCommand object. + * Constructs a new command instance. * * @param array $threadIds * The thread IDs, in the order that they should appear when the inbox is @@ -32,15 +20,15 @@ class PrivateMessageInboxUpdateCommand implements CommandInterface { * @param array $newThreads * The HTML for the messages to be inserted in the page. */ - public function __construct(array $threadIds, array $newThreads) { - $this->threadIds = $threadIds; - $this->newThreads = $newThreads; - } + public function __construct( + protected readonly array $threadIds, + protected readonly array $newThreads, + ) {} /** * {@inheritdoc} */ - public function render() { + public function render(): array { return [ 'command' => 'privateMessageInboxUpdate', 'threadIds' => $this->threadIds, diff --git a/src/Ajax/PrivateMessageInsertMessagesCommand.php b/src/Ajax/PrivateMessageInsertMessagesCommand.php deleted file mode 100644 index f80155f24473b7b7dc998671850cd0bb29b22c7a..0000000000000000000000000000000000000000 --- a/src/Ajax/PrivateMessageInsertMessagesCommand.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -namespace Drupal\private_message\Ajax; - -use Drupal\Core\Ajax\CommandInterface; - -/** - * Base class for Ajax command to insert messages into a private message thread. - */ -abstract class PrivateMessageInsertMessagesCommand implements CommandInterface { - - /** - * The type of messages to be inserted in the page. - * - * Possible values: - * - new - * - previous. - * - * @var string - */ - protected $insertType; - - /** - * The HTML for the messages to be inserted in the page. - * - * @var string - */ - protected $messages; - - /** - * The number of messages. - * - * @var int - */ - protected $messagesCount; - - /** - * Construct a PrivateMessageInsertMessagesCommand object. - * - * @param string $insertType - * The type of messages to be inserted in the page. Possible values: - * - new - * - previous. - * @param string $messages - * The HTML for the messages to be inserted in the page. - * @param int $messagesCount - * The number of messages. - */ - public function __construct($insertType, $messages, $messagesCount) { - $this->insertType = $insertType; - $this->messages = $messages; - $this->messagesCount = $messagesCount; - } - - /** - * {@inheritdoc} - */ - public function render() { - return [ - 'command' => 'insertPrivateMessages', - 'insertType' => $this->insertType, - 'messages' => $this->messages, - 'messagesCount' => $this->messagesCount, - ]; - } - -} diff --git a/src/Ajax/PrivateMessageInsertMessagesCommandBase.php b/src/Ajax/PrivateMessageInsertMessagesCommandBase.php new file mode 100644 index 0000000000000000000000000000000000000000..6bb0d2387a0db7dac311eded9253c86bb04ed4f8 --- /dev/null +++ b/src/Ajax/PrivateMessageInsertMessagesCommandBase.php @@ -0,0 +1,42 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\private_message\Ajax; + +use Drupal\Core\Ajax\CommandInterface; + +/** + * Base class for Ajax command to insert messages into a private message thread. + */ +abstract class PrivateMessageInsertMessagesCommandBase implements CommandInterface { + + /** + * Constructs a new command instance. + * + * @param string $insertType + * The type of messages to be inserted in the page: 'new', 'previous'. + * @param string $messages + * The HTML for the messages to be inserted in the page. + * @param int $messagesCount + * The number of messages. + */ + public function __construct( + protected readonly string $insertType, + protected readonly string $messages, + protected readonly int $messagesCount, + ) {} + + /** + * {@inheritdoc} + */ + public function render(): array { + return [ + 'command' => 'insertPrivateMessages', + 'insertType' => $this->insertType, + 'messages' => $this->messages, + 'messagesCount' => $this->messagesCount, + ]; + } + +} diff --git a/src/Ajax/PrivateMessageInsertNewMessagesCommand.php b/src/Ajax/PrivateMessageInsertNewMessagesCommand.php index 0c4f6e318187336e5c31fb9c572568a23113944f..856851b1f992389dbb1f0944ba13ea4655f7a3f9 100644 --- a/src/Ajax/PrivateMessageInsertNewMessagesCommand.php +++ b/src/Ajax/PrivateMessageInsertNewMessagesCommand.php @@ -1,21 +1,23 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Ajax; /** * Class to insert new private messages into a private message thread. */ -class PrivateMessageInsertNewMessagesCommand extends PrivateMessageInsertMessagesCommand { +class PrivateMessageInsertNewMessagesCommand extends PrivateMessageInsertMessagesCommandBase { /** - * Constructs a PrivateMessageInsertNewMessagesCommand object. + * Constructs a new command instance. * * @param string $messages * The HTML for the messages to be inserted in the page. * @param int $messagesCount * The number of messages. */ - public function __construct($messages, $messagesCount) { + public function __construct(string $messages, int $messagesCount) { parent::__construct('new', $messages, $messagesCount); } diff --git a/src/Ajax/PrivateMessageInsertPreviousMessagesCommand.php b/src/Ajax/PrivateMessageInsertPreviousMessagesCommand.php index 9cf3edb564c6c27a85a55513aaa50620d8cd26cc..5efeeff80632e1cf475de6c5e755c8a2607c7a5e 100644 --- a/src/Ajax/PrivateMessageInsertPreviousMessagesCommand.php +++ b/src/Ajax/PrivateMessageInsertPreviousMessagesCommand.php @@ -1,38 +1,36 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Ajax; /** * Class to insert older private messages into a private message thread. */ -class PrivateMessageInsertPreviousMessagesCommand extends PrivateMessageInsertMessagesCommand { - - /** - * Boolean to determine if there are more threads to come. - * - * @var bool - */ - protected $hasNext; +class PrivateMessageInsertPreviousMessagesCommand extends PrivateMessageInsertMessagesCommandBase { /** - * Constructs a PrivateMessageInsertPreviousMessagesCommand object. + * Constructs a new command instance. * * @param string $messages * The HTML for the messages to be inserted in the page. * @param int $messagesCount * The number of messages. - * @param bool $has_next + * @param bool $hasNext * A boolean to know if there are more messages after. */ - public function __construct($messages, $messagesCount, $has_next) { + public function __construct( + string $messages, + int $messagesCount, + protected readonly bool $hasNext, + ) { parent::__construct('previous', $messages, $messagesCount); - $this->hasNext = $has_next; } /** * {@inheritdoc} */ - public function render() { + public function render(): array { $return = parent::render(); $return['hasNext'] = $this->hasNext; return $return; diff --git a/src/Ajax/PrivateMessageInsertThreadCommand.php b/src/Ajax/PrivateMessageInsertThreadCommand.php index 687cba832bb4ee6447e77f9469ceef603e308572..52a28911c63af4d75491c62c18cc6d5f63103c51 100644 --- a/src/Ajax/PrivateMessageInsertThreadCommand.php +++ b/src/Ajax/PrivateMessageInsertThreadCommand.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Ajax; use Drupal\Core\Ajax\CommandInterface; @@ -9,30 +11,15 @@ use Drupal\Core\Ajax\CommandInterface; */ class PrivateMessageInsertThreadCommand implements CommandInterface { - /** - * The HTML of the thread to be inserted. - * - * @var string - */ - protected $thread; - - /** - * Constructs a PrivateMessageInsertThreadCommand object. - * - * @param string $thread - * The HTML of the thread to be inserted. - */ - public function __construct($thread) { - $this->thread = $thread; - } + public function __construct(protected readonly string $threadHtml) {} /** * {@inheritdoc} */ - public function render() { + public function render(): array { return [ 'command' => 'privateMessageInsertThread', - 'thread' => $this->thread, + 'thread' => $this->threadHtml, ]; } diff --git a/src/Ajax/PrivateMessageLoadNewMessagesCommand.php b/src/Ajax/PrivateMessageLoadNewMessagesCommand.php index d19011e346e245aa94603703edf83f0481bb3145..f64ca2c17b6c503f992fd6dcb29782c19466e569 100644 --- a/src/Ajax/PrivateMessageLoadNewMessagesCommand.php +++ b/src/Ajax/PrivateMessageLoadNewMessagesCommand.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Ajax; use Drupal\Core\Ajax\CommandInterface; @@ -12,7 +14,7 @@ class PrivateMessageLoadNewMessagesCommand implements CommandInterface { /** * {@inheritdoc} */ - public function render() { + public function render(): array { return [ 'command' => 'loadNewPrivateMessages', ]; diff --git a/src/Ajax/PrivateMessageUpdateUnreadItemsCountCommand.php b/src/Ajax/PrivateMessageUpdateUnreadItemsCountCommand.php index c1c5dc9bcca1401c5bfafa537b76f8a93bbdf288..d1ab471938fd54ba0b37c255a3397b4a37140614 100644 --- a/src/Ajax/PrivateMessageUpdateUnreadItemsCountCommand.php +++ b/src/Ajax/PrivateMessageUpdateUnreadItemsCountCommand.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Ajax; use Drupal\Core\Ajax\CommandInterface; @@ -12,30 +14,15 @@ use Drupal\Core\Ajax\CommandInterface; */ class PrivateMessageUpdateUnreadItemsCountCommand implements CommandInterface { - /** - * The number of unread threads. - * - * @var int - */ - protected $unreadItemsCount; - - /** - * Constructs a PrivateMessageUpdateUnreadItemsCountCommand object. - * - * @param int $unreadItemsCount - * The number of unread threads. - */ - public function __construct($unreadItemsCount) { - $this->unreadItemsCount = $unreadItemsCount; - } + public function __construct(protected readonly int $unreadThreadsCount) {} /** * {@inheritdoc} */ - public function render() { + public function render(): array { return [ 'command' => 'privateMessageUpdateUnreadItemsCount', - 'unreadItemsCount' => $this->unreadItemsCount, + 'unreadItemsCount' => $this->unreadThreadsCount, ]; } diff --git a/src/Annotation/PrivateMessageConfigForm.php b/src/Annotation/PrivateMessageConfigForm.php index fb28869004685399a2d1d97fed0c0965e88544b0..7d0d4feb77db0152842356476975371e669cb8ed 100644 --- a/src/Annotation/PrivateMessageConfigForm.php +++ b/src/Annotation/PrivateMessageConfigForm.php @@ -1,8 +1,11 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Annotation; use Drupal\Component\Annotation\Plugin; +use Drupal\Core\Annotation\Translation; /** * Annotation definition for the Private Message Configuration Form plugin. @@ -13,18 +16,14 @@ class PrivateMessageConfigForm extends Plugin { /** * The plugin ID. - * - * @var string */ - public $id; + public string $id; /** * The name of the form plugin. * - * @var \Drupal\Core\Annotation\Translation - * * @ingroup plugin_translatable */ - public $name; + public Translation $name; } diff --git a/src/Attribute/PrivateMessageConfigForm.php b/src/Attribute/PrivateMessageConfigForm.php new file mode 100644 index 0000000000000000000000000000000000000000..1fae7d05c1f9c3d411f4feca267c6ee1bc07df2c --- /dev/null +++ b/src/Attribute/PrivateMessageConfigForm.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\private_message\Attribute; + +use Drupal\Component\Plugin\Attribute\Plugin; +use Drupal\Core\StringTranslation\TranslatableMarkup; + +/** + * The private message configuration form plugin attribute. + */ +#[\Attribute(\Attribute::TARGET_CLASS)] +class PrivateMessageConfigForm extends Plugin { + + /** + * Constructs a new PrivateMessageConfigForm attribute. + * + * @param string $id + * The plugin ID. + * @param \Drupal\Core\StringTranslation\TranslatableMarkup $name + * The name of the form plugin. + */ + public function __construct( + public readonly string $id, + public readonly TranslatableMarkup $name, + ) {} + +} diff --git a/src/Cache/Context/PrivateMessageThreadCacheContext.php b/src/Cache/Context/PrivateMessageThreadCacheContext.php index a8f23f1e6d24588babfc3346db8347e3c32af3fa..bb81bb881c07bca6aad375ee9589a05db3216c91 100644 --- a/src/Cache/Context/PrivateMessageThreadCacheContext.php +++ b/src/Cache/Context/PrivateMessageThreadCacheContext.php @@ -1,10 +1,12 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Cache\Context; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Cache\Context\CacheContextInterface; -use Drupal\Core\Routing\ResettableStackedRouteMatchInterface; +use Drupal\Core\Routing\RouteMatchInterface; /** * Defines the PrivateMessageThread service, for "per thread" caching. @@ -13,22 +15,9 @@ use Drupal\Core\Routing\ResettableStackedRouteMatchInterface; */ class PrivateMessageThreadCacheContext implements CacheContextInterface { - /** - * The current route matcher. - * - * @var \Drupal\Core\Routing\ResettableStackedRouteMatchInterface - */ - protected $currentRouteMatcher; - - /** - * Constructs a new UserCacheContextBase class. - * - * @param \Drupal\Core\Routing\ResettableStackedRouteMatchInterface $currentRouteMatcher - * The current route matcher. - */ - public function __construct(ResettableStackedRouteMatchInterface $currentRouteMatcher) { - $this->currentRouteMatcher = $currentRouteMatcher; - } + public function __construct( + protected readonly RouteMatchInterface $currentRouteMatch, + ) {} /** * {@inheritdoc} @@ -40,10 +29,10 @@ class PrivateMessageThreadCacheContext implements CacheContextInterface { /** * {@inheritdoc} */ - public function getContext() { - $thread = $this->currentRouteMatcher->getParameter('private_message_thread'); + public function getContext(): string { + $thread = $this->currentRouteMatch->getParameter('private_message_thread'); if ($thread) { - return $thread->id(); + return (string) $thread->id(); } return 'none'; } @@ -51,7 +40,7 @@ class PrivateMessageThreadCacheContext implements CacheContextInterface { /** * {@inheritdoc} */ - public function getCacheableMetadata() { + public function getCacheableMetadata(): CacheableMetadata { return new CacheableMetadata(); } diff --git a/src/Controller/AjaxController.php b/src/Controller/AjaxController.php index 0c825c0f6f58291c40fdf25955b00fe99bd373eb..1e8a4e5651ae2475a630cbc684aeefeb058921d8 100644 --- a/src/Controller/AjaxController.php +++ b/src/Controller/AjaxController.php @@ -1,22 +1,21 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Controller; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\SettingsCommand; -use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Controller\ControllerBase; -use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Render\RendererInterface; -use Drupal\Core\Session\AccountProxyInterface; use Drupal\private_message\Ajax\PrivateMessageInboxInsertThreadsCommand; use Drupal\private_message\Ajax\PrivateMessageInboxUpdateCommand; use Drupal\private_message\Ajax\PrivateMessageInsertNewMessagesCommand; use Drupal\private_message\Ajax\PrivateMessageInsertPreviousMessagesCommand; use Drupal\private_message\Ajax\PrivateMessageInsertThreadCommand; use Drupal\private_message\Ajax\PrivateMessageUpdateUnreadItemsCountCommand; +use Drupal\private_message\Entity\PrivateMessageThreadInterface; use Drupal\private_message\Service\PrivateMessageServiceInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RequestStack; /** @@ -24,149 +23,50 @@ use Symfony\Component\HttpFoundation\RequestStack; */ class AjaxController extends ControllerBase implements AjaxControllerInterface { - /** - * The renderer service. - * - * @var \Drupal\Core\Render\RendererInterface - */ - protected $renderer; - - /** - * The request stack. - * - * @var \Symfony\Component\HttpFoundation\RequestStack - */ - protected $requestStack; - - /** - * The entity manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * The configuration factory. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected $configFactory; - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected $currentUser; - - /** - * The private message service. - * - * @var \Drupal\private_message\Service\PrivateMessageServiceInterface - */ - protected $privateMessageService; - public function __construct( - RendererInterface $renderer, - RequestStack $requestStack, - EntityTypeManagerInterface $entityTypeManager, - ConfigFactoryInterface $configFactory, - AccountProxyInterface $currentUser, - PrivateMessageServiceInterface $privateMessageService, - ) { - $this->renderer = $renderer; - $this->requestStack = $requestStack; - $this->entityTypeManager = $entityTypeManager; - $this->configFactory = $configFactory; - $this->currentUser = $currentUser; - $this->privateMessageService = $privateMessageService; - } + protected readonly RendererInterface $renderer, + protected readonly RequestStack $requestStack, + protected readonly PrivateMessageServiceInterface $privateMessageService, + ) {} /** * {@inheritdoc} */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('renderer'), - $container->get('request_stack'), - $container->get('entity_type.manager'), - $container->get('config.factory'), - $container->get('current_user'), - $container->get('private_message.service'), - ); - } - - /** - * {@inheritdoc} - */ - public function ajaxCallback($op) { - $response = new AjaxResponse(); - - switch ($op) { - - case 'get_new_messages': - $this->getNewPrivateMessages($response); - - break; - - case 'get_old_messages': - $this->getOldPrivateMessages($response); - - break; - - case 'get_old_inbox_threads': - $this->getOldInboxThreads($response); - - break; - - case 'get_new_inbox_threads': - $this->getNewInboxThreads($response); - - break; - - case 'get_new_unread_thread_count': - $this->getNewUnreadThreadCount($response); - - break; - - case 'get_new_unread_message_count': - $this->getNewUnreadMessageCount($response); - - break; - - case 'load_thread': - $this->loadThread($response); - - break; - } - - return $response; + public function ajaxCallback(string $op): AjaxResponse { + return match($op) { + 'get_new_messages' => $this->getNewPrivateMessages(), + 'get_old_messages' => $this->getOldPrivateMessages(), + 'get_old_inbox_threads' => $this->getOldInboxThreads(), + 'get_new_inbox_threads' => $this->getNewInboxThreads(), + 'get_new_unread_thread_count' => $this->getNewUnreadThreadCount(), + 'get_new_unread_message_count' => $this->getNewUnreadMessageCount(), + 'load_thread' => $this->loadThread(), + }; } /** * Creates an Ajax Command containing new private message. * - * @param \Drupal\Core\Ajax\AjaxResponse $response + * @return \Drupal\Core\Ajax\AjaxResponse * The response to which any commands should be attached. */ - protected function getNewPrivateMessages(AjaxResponse $response) { + protected function getNewPrivateMessages(): AjaxResponse { + $response = new AjaxResponse(); $thread_id = $this->requestStack->getCurrentRequest()->get('threadid'); $message_id = $this->requestStack->getCurrentRequest()->get('messageid'); - $count = 0; + if (is_numeric($thread_id) && is_numeric($message_id)) { - /** @var \Drupal\private_message\Entity\PrivateMessageThreadInterface $thread */ - $thread = $this->entityTypeManager - ->getStorage('private_message_thread') + $thread = $this->entityTypeManager()->getStorage('private_message_thread') ->load($thread_id); - if ($thread) { + if ($thread instanceof PrivateMessageThreadInterface) { $new_messages = $this->privateMessageService->getNewMessages($thread_id, $message_id); $this->privateMessageService->updateThreadAccessTime($thread); $count = count($new_messages); if ($count) { $messages = []; - $view_builder = $this->entityTypeManager->getViewBuilder('private_message'); + $view_builder = $this->entityTypeManager()->getViewBuilder('private_message'); foreach ($new_messages as $message) { - if ($message->access('view', $this->currentUser)) { + if ($message->access('view', $this->currentUser())) { $message_view = $view_builder->view($message); $message_view['#prefix'] = '<div class="private-message-wrapper field__item">'; $message_view['#suffix'] = '</div>'; @@ -178,18 +78,22 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { $messages['#attached']['drupalSettings']['privateMessageThread']['threadId'] = (int) $thread->id(); } - $response->addCommand(new PrivateMessageInsertNewMessagesCommand($this->renderer->renderRoot($messages), $count)); + $response->addCommand(new PrivateMessageInsertNewMessagesCommand((string) $this->renderer->renderRoot($messages), $count)); } } + + return $response; } /** * Create an Ajax Command containing old private messages. * - * @param \Drupal\Core\Ajax\AjaxResponse $response + * @return \Drupal\Core\Ajax\AjaxResponse * The response to which any commands should be attached. */ - protected function getOldPrivateMessages(AjaxResponse $response) { + protected function getOldPrivateMessages(): AjaxResponse { + $response = new AjaxResponse(); + $current_request = $this->requestStack->getCurrentRequest(); $thread_id = $current_request->get('threadid'); $message_id = $current_request->get('messageid'); @@ -198,10 +102,10 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { if (count($message_info['messages'])) { $messages = []; - $view_builder = $this->entityTypeManager->getViewBuilder('private_message'); + $view_builder = $this->entityTypeManager()->getViewBuilder('private_message'); $has_next = $message_info['next_exists']; foreach ($message_info['messages'] as $message) { - if ($message->access('view', $this->currentUser)) { + if ($message->access('view', $this->currentUser())) { $message_view = $view_builder->view($message); $message_view['#prefix'] = '<div class="private-message-wrapper field__item">'; $message_view['#suffix'] = '</div>'; @@ -209,31 +113,35 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { } } - $response->addCommand(new PrivateMessageInsertPreviousMessagesCommand($this->renderer->renderRoot($messages), count($message_info['messages']), $has_next)); + $response->addCommand(new PrivateMessageInsertPreviousMessagesCommand((string) $this->renderer->renderRoot($messages), count($message_info['messages']), $has_next)); } else { $response->addCommand(new PrivateMessageInsertPreviousMessagesCommand('', 0, FALSE)); } } + + return $response; } /** * Creates and Ajax Command containing old threads for the inbox. * - * @param \Drupal\Core\Ajax\AjaxResponse $response + * @return \Drupal\Core\Ajax\AjaxResponse * The response to which any commands should be attached. */ - protected function getOldInboxThreads(AjaxResponse $response) { + protected function getOldInboxThreads(): AjaxResponse { + $response = new AjaxResponse(); + $timestamp = $this->requestStack->getCurrentRequest()->get('timestamp'); - $thread_count = $this->requestStack->getCurrentRequest()->get('count'); + $thread_count = (int) $this->requestStack->getCurrentRequest()->get('count'); if (is_numeric($timestamp)) { - $thread_info = $this->privateMessageService->getThreadsForUser($thread_count, $timestamp); + $thread_info = $this->privateMessageService->getThreadsForUser($thread_count, intval($timestamp)); $has_next = FALSE; if (count($thread_info['threads'])) { - $view_builder = $this->entityTypeManager->getViewBuilder('private_message_thread'); + $view_builder = $this->entityTypeManager()->getViewBuilder('private_message_thread'); $threads = []; foreach ($thread_info['threads'] as $thread) { - if ($thread->access('view', $this->currentUser)) { + if ($thread->access('view', $this->currentUser())) { $has_next = $thread_info['next_exists']; $threads[] = $view_builder->view($thread, 'inbox'); } @@ -244,15 +152,19 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { $response->addCommand(new PrivateMessageInboxInsertThreadsCommand('', FALSE)); } } + + return $response; } /** * Creates an Ajax Command with new threads for the private message inbox. * - * @param \Drupal\Core\Ajax\AjaxResponse $response + * @return \Drupal\Core\Ajax\AjaxResponse * The response to which any commands should be attached. */ - protected function getNewInboxThreads(AjaxResponse $response) { + protected function getNewInboxThreads(): AjaxResponse { + $response = new AjaxResponse(); + $info = $this->requestStack->getCurrentRequest()->get('ids'); // Check to see if any thread IDs were POSTed. @@ -263,18 +175,19 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { else { // No IDs were posted, so the maximum possible number of threads to be // returned is retrieved from the block settings. - $thread_count = $this->configFactory->get('block.block.privatemessageinbox')->get('settings.thread_count'); + $thread_count = $this->config('block.block.privatemessageinbox') + ->get('settings.thread_count'); $inbox_threads = $this->privateMessageService->getUpdatedInboxThreads([], $thread_count); } // Only need to do something if any thread IDS were found. if (count($inbox_threads['thread_ids'])) { - $view_builder = $this->entityTypeManager->getViewBuilder('private_message_thread'); + $view_builder = $this->entityTypeManager()->getViewBuilder('private_message_thread'); // Render any new threads as HTML to be sent to the browser. $rendered_threads = []; foreach (array_keys($inbox_threads['new_threads']) as $thread_id) { - if ($inbox_threads['new_threads'][$thread_id]->access('view', $this->currentUser)) { + if ($inbox_threads['new_threads'][$thread_id]->access('view', $this->currentUser())) { $renderable = $view_builder->view($inbox_threads['new_threads'][$thread_id], 'inbox'); $rendered_threads[$thread_id] = $this->renderer->renderRoot($renderable); } @@ -283,6 +196,8 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { // Add the command that will tell the inbox which thread items to update. $response->addCommand(new PrivateMessageInboxUpdateCommand($inbox_threads['thread_ids'], $rendered_threads)); } + + return $response; } /** @@ -291,13 +206,14 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { * Only messages created since the current user last visited the private * message page are shown. * - * @param \Drupal\Core\Ajax\AjaxResponse $response + * @return \Drupal\Core\Ajax\AjaxResponse * The response to which any commands should be attached. */ - protected function getNewUnreadThreadCount(AjaxResponse $response) { + protected function getNewUnreadThreadCount(): AjaxResponse { + $response = new AjaxResponse(); $unread_thread_count = $this->privateMessageService->getUnreadThreadCount(); - $response->addCommand(new PrivateMessageUpdateUnreadItemsCountCommand($unread_thread_count)); + return $response; } /** @@ -306,32 +222,35 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { * Only messages created since the current user last visited the private * message page are shown. * - * @param \Drupal\Core\Ajax\AjaxResponse $response + * @return \Drupal\Core\Ajax\AjaxResponse * The response to which any commands should be attached. */ - protected function getNewUnreadMessageCount(AjaxResponse $response) { + protected function getNewUnreadMessageCount(): AjaxResponse { + $response = new AjaxResponse(); $unread_message_count = $this->privateMessageService->getUnreadMessageCount(); - $response->addCommand(new PrivateMessageUpdateUnreadItemsCountCommand($unread_message_count)); + return $response; } /** * Load a private message thread to be dynamically inserted into the page. * - * @param \Drupal\Core\Ajax\AjaxResponse $response + * @return \Drupal\Core\Ajax\AjaxResponse * The response to which any commands should be attached. */ - protected function loadThread(AjaxResponse $response) { + protected function loadThread(): AjaxResponse { + $response = new AjaxResponse(); + $thread_id = $this->requestStack->getCurrentRequest()->get('id'); if ($thread_id) { - $thread = $this->entityTypeManager->getStorage('private_message_thread')->load($thread_id); + $thread = $this->entityTypeManager()->getStorage('private_message_thread')->load($thread_id); - if ($thread && $thread->access('view', $this->currentUser)) { + if ($thread && $thread->access('view', $this->currentUser())) { $this->privateMessageService->updateLastCheckTime(); - $view_builder = $this->entityTypeManager->getViewBuilder('private_message_thread'); + $view_builder = $this->entityTypeManager()->getViewBuilder('private_message_thread'); $renderable = $view_builder->view($thread); - $rendered_thread = $this->renderer->renderRoot($renderable); + $rendered_thread = (string) $this->renderer->renderRoot($renderable); $response->addCommand(new SettingsCommand($renderable['#attached']['drupalSettings'], TRUE)); $response->addCommand(new PrivateMessageInsertThreadCommand($rendered_thread)); @@ -339,6 +258,8 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface { $response->addCommand(new PrivateMessageUpdateUnreadItemsCountCommand($unread_thread_count)); } } + + return $response; } } diff --git a/src/Controller/AjaxControllerInterface.php b/src/Controller/AjaxControllerInterface.php index 9b72988ed4f36329886014f2e508a2a0eb68638e..978fdc3986877c86537005f9441bc4966a26a81e 100644 --- a/src/Controller/AjaxControllerInterface.php +++ b/src/Controller/AjaxControllerInterface.php @@ -1,7 +1,11 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Controller; +use Drupal\Core\Ajax\AjaxResponse; + /** * Interface for the Private Message module's AjaxController. */ @@ -16,6 +20,6 @@ interface AjaxControllerInterface { * @return \Drupal\Core\Ajax\AjaxResponse * The ajax response */ - public function ajaxCallback($op); + public function ajaxCallback(string $op): AjaxResponse; } diff --git a/src/Controller/PrivateMessageController.php b/src/Controller/PrivateMessageController.php index 5ddb07da506182120b6819daf7199c628e20ab78..8edb7796915652b1b617d89e65668aed2b458cc3 100644 --- a/src/Controller/PrivateMessageController.php +++ b/src/Controller/PrivateMessageController.php @@ -1,120 +1,41 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Controller; -use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Controller\ControllerBase; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Link; -use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\Url; use Drupal\private_message\Form\BanUserForm; use Drupal\private_message\Service\PrivateMessageServiceInterface; use Drupal\user\UserDataInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Private message page controller. Returns render arrays for the page. */ class PrivateMessageController extends ControllerBase implements PrivateMessageControllerInterface { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected $currentUser; - - /** - * The entity manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * The form builder interface. - * - * @var \Drupal\Core\Form\FormBuilderInterface - */ - protected $formBuilder; - - /** - * The user data service. - * - * @var \Drupal\user\UserDataInterface - */ - protected $userData; - - /** - * The private message service. - * - * @var \Drupal\private_message\Service\PrivateMessageServiceInterface - */ - protected $privateMessageService; - - /** - * The configuration factory service. - * - * @var \Drupal\Core\Config\ImmutableConfig - */ - protected $config; - - /** - * Constructs a PrivateMessageForm object. - * - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity manager service. - * @param \Drupal\Core\Form\FormBuilderInterface $formBuilder - * The form builder service. - * @param \Drupal\user\UserDataInterface $userData - * The user data service. - * @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService - * The private message service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * The config factory service. - */ - public function __construct(AccountProxyInterface $currentUser, EntityTypeManagerInterface $entityTypeManager, FormBuilderInterface $formBuilder, UserDataInterface $userData, PrivateMessageServiceInterface $privateMessageService, ConfigFactoryInterface $configFactory) { - $this->currentUser = $currentUser; - $this->entityTypeManager = $entityTypeManager; - $this->formBuilder = $formBuilder; - $this->userData = $userData; - $this->privateMessageService = $privateMessageService; - $this->config = $configFactory->get('private_message.settings'); - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('current_user'), - $container->get('entity_type.manager'), - $container->get('form_builder'), - $container->get('user.data'), - $container->get('private_message.service'), - $container->get('config.factory') - ); - } + public function __construct( + protected readonly UserDataInterface $userData, + protected readonly PrivateMessageServiceInterface $privateMessageService, + ) {} /** * {@inheritdoc} */ - public function privateMessagePage() { + public function privateMessagePage(): array { $this->privateMessageService->updateLastCheckTime(); /** @var \Drupal\user\UserInterface $user */ - $user = $this->entityTypeManager + $user = $this->entityTypeManager() ->getStorage('user') - ->load($this->currentUser->id()); + ->load($this->currentUser()->id()); $private_message_thread = $this->privateMessageService->getFirstThreadForUser($user); if ($private_message_thread) { - $view_builder = $this->entityTypeManager->getViewBuilder('private_message_thread'); + $view_builder = $this->entityTypeManager()->getViewBuilder('private_message_thread'); // No wrapper is provided, as the full view mode of the entity already // provides the #private-message-page wrapper. $page = $view_builder->view($private_message_thread); @@ -137,7 +58,7 @@ class PrivateMessageController extends ControllerBase implements PrivateMessageC /** * {@inheritdoc} */ - public function pmSettingsPage() { + public function pmSettingsPage(): array { $url = Url::fromRoute('private_message.admin_config.config')->toString(); $message = $this->t('You can find module settings here: <a href="@url">page</a>', ['@url' => $url]); return [ @@ -148,7 +69,7 @@ class PrivateMessageController extends ControllerBase implements PrivateMessageC /** * {@inheritdoc} */ - public function pmThreadSettingsPage() { + public function pmThreadSettingsPage(): array { return [ '#markup' => $this->t('Private Message Threads'), ]; @@ -157,18 +78,18 @@ class PrivateMessageController extends ControllerBase implements PrivateMessageC /** * {@inheritdoc} */ - public function configPage() { + public function configPage(): array { return [ '#prefix' => '<div id="private_message_configuration_page">', '#suffix' => '</div>', - 'form' => $this->formBuilder->getForm('Drupal\private_message\Form\ConfigForm'), + 'form' => $this->formBuilder()->getForm('Drupal\private_message\Form\ConfigForm'), ]; } /** * {@inheritdoc} */ - public function adminUninstallPage() { + public function adminUninstallPage(): array { return [ 'message' => [ '#prefix' => '<div id="private_message_admin_uninstall_page">', @@ -190,8 +111,8 @@ class PrivateMessageController extends ControllerBase implements PrivateMessageC * {@inheritdoc} */ public function banUnbanPage(): array { - $user_has_permission = $this->currentUser->hasPermission('use private messaging system') - && $this->currentUser->hasPermission('access user profiles'); + $user_has_permission = $this->currentUser()->hasPermission('use private messaging system') + && $this->currentUser()->hasPermission('access user profiles'); $table = []; @@ -200,13 +121,13 @@ class PrivateMessageController extends ControllerBase implements PrivateMessageC $header = [t('User'), t('Operations')]; /** @var \Drupal\private_message\Entity\PrivateMessageBan[] $private_message_bans */ - $private_message_bans = $this->entityTypeManager + $private_message_bans = $this->entityTypeManager() ->getStorage('private_message_ban') - ->loadByProperties(['owner' => $this->currentUser->id()]); + ->loadByProperties(['owner' => $this->currentUser()->id()]); $destination = Url::fromRoute('<current>')->getInternalPath(); foreach ($private_message_bans as $private_message_ban) { - $label = $this->config->get('unban_label'); + $label = $this->config('private_message.settings')->get('unban_label'); $url = Url::fromRoute('private_message.unban_user_form', ['user' => $private_message_ban->getTargetId()], ['query' => ['destination' => $destination]], @@ -230,7 +151,7 @@ class PrivateMessageController extends ControllerBase implements PrivateMessageC 'content' => [ $table, [ - 'form' => $this->formBuilder->getForm(BanUserForm::class), + 'form' => $this->formBuilder()->getForm(BanUserForm::class), ], ], ]; diff --git a/src/Controller/PrivateMessageControllerInterface.php b/src/Controller/PrivateMessageControllerInterface.php index 05be08e1466252f56fdc5f4beccd5866a613cc46..5ec0c2d96a7de4b6f401d9769dc39b0be22171af 100644 --- a/src/Controller/PrivateMessageControllerInterface.php +++ b/src/Controller/PrivateMessageControllerInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Controller; /** @@ -9,26 +11,49 @@ interface PrivateMessageControllerInterface { /** * The Private message page. + * + * @return array + * Render array. */ - public function privateMessagePage(); + public function privateMessagePage(): array; /** * The private message module settings page. + * + * @return array + * Render array. */ - public function pmSettingsPage(); + public function pmSettingsPage(): array; /** * The settings page specific to private message threads. + * + * @return array + * Render array. + */ + public function pmThreadSettingsPage(): array; + + /** + * Provides a controller for the private_message.admin_config.config route. + * + * @return array + * Render array. */ - public function pmThreadSettingsPage(); + public function configPage(): array; /** * The page for preparing to uninstall the module. + * + * @return array + * Render array. */ - public function adminUninstallPage(); + public function adminUninstallPage(): array; /** * The page for banning and unbanning users. + * + * @return array + * Render array. */ public function banUnbanPage(): array; diff --git a/src/Drush/Commands/PrivateMessageCommands.php b/src/Drush/Commands/PrivateMessageCommands.php index fab1647903ecf95696e59554e7012c2b6aea54a0..ae4377c1ad203832cc623cc7ed2ae427d8d75bee 100644 --- a/src/Drush/Commands/PrivateMessageCommands.php +++ b/src/Drush/Commands/PrivateMessageCommands.php @@ -1,8 +1,10 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Drush\Commands; -use Drupal\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\private_message\Service\PrivateMessageUninstallerInterface; use Drush\Attributes as CLI; @@ -13,6 +15,7 @@ use Drush\Commands\DrushCommands; */ final class PrivateMessageCommands extends DrushCommands { + use AutowireTrait; use StringTranslationTrait; public function __construct( @@ -21,15 +24,6 @@ final class PrivateMessageCommands extends DrushCommands { parent::__construct(); } - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container): self { - return new static( - $container->get('private_message.uninstaller') - ); - } - /** * Prepares the Private Message module for uninstallation. */ diff --git a/src/Entity/Access/PrivateMessageAccessControlHandler.php b/src/Entity/Access/PrivateMessageAccessControlHandler.php index fb1845f2de2f0f9b68278d96fa58558684d5a16d..cad95a2a7fded0d05e36474918069b5a3422410a 100644 --- a/src/Entity/Access/PrivateMessageAccessControlHandler.php +++ b/src/Entity/Access/PrivateMessageAccessControlHandler.php @@ -1,13 +1,17 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity\Access; use Drupal\Core\Access\AccessResult; +use Drupal\Core\Access\AccessResultInterface; use Drupal\Core\Entity\EntityAccessControlHandler; use Drupal\Core\Entity\EntityHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\private_message\Entity\PrivateMessageInterface; use Drupal\private_message\Service\PrivateMessageServiceInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -16,24 +20,11 @@ use Symfony\Component\DependencyInjection\ContainerInterface; */ class PrivateMessageAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface { - /** - * The private message service. - * - * @var \Drupal\private_message\Service\PrivateMessageServiceInterface - */ - protected $privateMessageService; - - /** - * Constructs a PrivateMessageThreadAccessControlHandler entity. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService - * The private message service. - */ - public function __construct(EntityTypeInterface $entity_type, PrivateMessageServiceInterface $privateMessageService) { + public function __construct( + EntityTypeInterface $entity_type, + protected readonly PrivateMessageServiceInterface $privateMessageService, + ) { parent::__construct($entity_type); - $this->privateMessageService = $privateMessageService; } /** @@ -52,7 +43,9 @@ class PrivateMessageAccessControlHandler extends EntityAccessControlHandler impl * Link the activities to the permissions. checkAccess is called with the * $operation as defined in the routing.yml file. */ - protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account): AccessResultInterface { + assert($entity instanceof PrivateMessageInterface); + if ($account->hasPermission('use private messaging system')) { switch ($operation) { case 'view': @@ -68,7 +61,6 @@ class PrivateMessageAccessControlHandler extends EntityAccessControlHandler impl if ($account->hasPermission('administer private messages')) { return AccessResult::allowed(); } - break; case 'delete': @@ -81,7 +73,6 @@ class PrivateMessageAccessControlHandler extends EntityAccessControlHandler impl } return AccessResult::allowedIfHasPermission($account, 'delete any private message'); - } } @@ -94,7 +85,7 @@ class PrivateMessageAccessControlHandler extends EntityAccessControlHandler impl * Separate from the checkAccess because the entity does not yet exist, it * will be created during the 'add' process. */ - protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL): AccessResultInterface { return AccessResult::allowedIfHasPermission($account, 'use private messaging system'); } diff --git a/src/Entity/Access/PrivateMessageBanAccessControlHandler.php b/src/Entity/Access/PrivateMessageBanAccessControlHandler.php index a4171f8c0f3723474bf13f8d439ef56c5a6fe1b4..adefdb80756a8186dc21e77007ed21d8922833c6 100644 --- a/src/Entity/Access/PrivateMessageBanAccessControlHandler.php +++ b/src/Entity/Access/PrivateMessageBanAccessControlHandler.php @@ -1,11 +1,15 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity\Access; use Drupal\Core\Access\AccessResult; +use Drupal\Core\Access\AccessResultInterface; use Drupal\Core\Entity\EntityAccessControlHandler; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\private_message\Entity\PrivateMessageBanInterface; /** * Access controller for the Private Message Ban entities. @@ -17,8 +21,9 @@ class PrivateMessageBanAccessControlHandler extends EntityAccessControlHandler { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { - /** @var \Drupal\private_message\Entity\PrivateMessageBanInterface $entity */ + protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account): AccessResultInterface { + assert($entity instanceof PrivateMessageBanInterface); + switch ($operation) { case 'view': return AccessResult::allowedIfHasPermission($account, 'view private message ban entities'); @@ -37,7 +42,7 @@ class PrivateMessageBanAccessControlHandler extends EntityAccessControlHandler { /** * {@inheritdoc} */ - protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL): AccessResultInterface { return AccessResult::allowedIfHasPermission($account, 'add private message ban entities'); } diff --git a/src/Entity/Access/PrivateMessageThreadAccessControlHandler.php b/src/Entity/Access/PrivateMessageThreadAccessControlHandler.php index 47d0716e7f901c0722951a4319537a544cbcbf41..d5a917d1ada67a918614a7cf25410e1677e4f0ca 100644 --- a/src/Entity/Access/PrivateMessageThreadAccessControlHandler.php +++ b/src/Entity/Access/PrivateMessageThreadAccessControlHandler.php @@ -1,11 +1,15 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity\Access; use Drupal\Core\Access\AccessResult; +use Drupal\Core\Access\AccessResultInterface; use Drupal\Core\Entity\EntityAccessControlHandler; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\private_message\Entity\PrivateMessageThreadInterface; /** * Access control handler for private message thread entities. @@ -15,7 +19,8 @@ class PrivateMessageThreadAccessControlHandler extends EntityAccessControlHandle /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account): AccessResultInterface { + assert($entity instanceof PrivateMessageThreadInterface); if ($account->hasPermission('administer private messages')) { return AccessResult::allowed(); @@ -30,17 +35,15 @@ class PrivateMessageThreadAccessControlHandler extends EntityAccessControlHandle return AccessResult::allowed(); } } - break; case 'delete': - // Allow delete if we are member of this thread - // And if we have permission to delete thread for everyone. + // Allow to delete if we are member of this thread and if we have + // permission to delete thread for everyone. if ($entity->isMember($account->id()) && $account->hasPermission('delete private message thread for all')) { return AccessResult::allowed(); } - break; case 'clear_personal_history': @@ -48,7 +51,6 @@ class PrivateMessageThreadAccessControlHandler extends EntityAccessControlHandle if ($entity->isMember($account->id())) { return AccessResult::allowed(); } - break; } } @@ -62,7 +64,7 @@ class PrivateMessageThreadAccessControlHandler extends EntityAccessControlHandle * Separate from the checkAccess because the entity does not yet exist, it * will be created during the 'add' process. */ - protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL): AccessResultInterface { return AccessResult::allowedIfHasPermission($account, 'use private messaging system'); } diff --git a/src/Entity/Builder/PrivateMessageBanListBuilder.php b/src/Entity/Builder/PrivateMessageBanListBuilder.php index 8f727a3e6dd13ae28289fea4d79f6694bef92026..6a6ca426b081b79a3d8961bdd592f30eba39cc10 100644 --- a/src/Entity/Builder/PrivateMessageBanListBuilder.php +++ b/src/Entity/Builder/PrivateMessageBanListBuilder.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity\Builder; use Drupal\Core\Entity\EntityInterface; @@ -8,15 +10,13 @@ use Drupal\Core\Link; /** * Defines a class to build a listing of Private Message Ban entities. - * - * @ingroup private_message */ class PrivateMessageBanListBuilder extends EntityListBuilder { /** * {@inheritdoc} */ - public function buildHeader() { + public function buildHeader(): array { // @todo Make this useful by adding the ban owner and target fields. $header['id'] = $this->t('Private Message Ban ID'); $header['name'] = $this->t('Name'); @@ -26,7 +26,7 @@ class PrivateMessageBanListBuilder extends EntityListBuilder { /** * {@inheritdoc} */ - public function buildRow(EntityInterface $entity) { + public function buildRow(EntityInterface $entity): array { /** @var \Drupal\private_message\Entity\PrivateMessageBanInterface $entity */ $row['id'] = $entity->id(); $row['name'] = Link::createFromRoute( diff --git a/src/Entity/Builder/PrivateMessageThreadViewBuilder.php b/src/Entity/Builder/PrivateMessageThreadViewBuilder.php index 563f7b51c235c7fc9dfbf088104ac14fcad11b86..ce32ab002eed32c093760d5b665a26e78bc97cc9 100644 --- a/src/Entity/Builder/PrivateMessageThreadViewBuilder.php +++ b/src/Entity/Builder/PrivateMessageThreadViewBuilder.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity\Builder; use Drupal\Core\Cache\Cache; @@ -12,6 +14,7 @@ use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\Theme\Registry; use Drupal\Core\Url; +use Drupal\private_message\Entity\PrivateMessageThreadInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -19,45 +22,21 @@ use Symfony\Component\DependencyInjection\ContainerInterface; */ class PrivateMessageThreadViewBuilder extends EntityViewBuilder { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * Constructs a PrivateMessageThreadViewBuilder object. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository - * The entity repository service. - * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager - * The language manager service. - * @param \Drupal\Core\Theme\Registry $theme_registry - * The theme register. - * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository - * The entity display repository. - * @param \Drupal\Core\Session\AccountProxyInterface $current_user - * The current user. - */ public function __construct( EntityTypeInterface $entity_type, EntityRepositoryInterface $entity_repository, LanguageManagerInterface $language_manager, Registry $theme_registry, EntityDisplayRepositoryInterface $entity_display_repository, - AccountProxyInterface $current_user, + protected readonly AccountProxyInterface $currentUser, ) { parent::__construct($entity_type, $entity_repository, $language_manager, $theme_registry, $entity_display_repository); - $this->currentUser = $current_user; } /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type): PrivateMessageThreadViewBuilder { + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type): self { return new static( $entity_type, $container->get('entity.repository'), @@ -72,6 +51,8 @@ class PrivateMessageThreadViewBuilder extends EntityViewBuilder { * {@inheritdoc} */ public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL): array { + assert($entity instanceof PrivateMessageThreadInterface); + $build = parent::view($entity, $view_mode, $langcode); $classes = ['private-message-thread']; diff --git a/src/Entity/Builder/PrivateMessageViewBuilder.php b/src/Entity/Builder/PrivateMessageViewBuilder.php index 3ccf3c04da9da2d38084c27a3dfbceb61932c031..b2fa129aecc9ae9934ce368806f2720f3be3c431 100644 --- a/src/Entity/Builder/PrivateMessageViewBuilder.php +++ b/src/Entity/Builder/PrivateMessageViewBuilder.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity\Builder; use Drupal\Core\Entity\EntityDisplayRepositoryInterface; @@ -10,6 +12,7 @@ use Drupal\Core\Entity\EntityViewBuilder; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\Theme\Registry; +use Drupal\private_message\Entity\PrivateMessageInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -17,45 +20,21 @@ use Symfony\Component\DependencyInjection\ContainerInterface; */ class PrivateMessageViewBuilder extends EntityViewBuilder { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * Constructs a PrivateMessageViewBuilder object. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type definition. - * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository - * The entity repository service. - * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager - * The language manager. - * @param \Drupal\Core\Theme\Registry $theme_registry - * The theme registry. - * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository - * The entity display repository. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - */ public function __construct( EntityTypeInterface $entity_type, EntityRepositoryInterface $entity_repository, LanguageManagerInterface $language_manager, Registry $theme_registry, EntityDisplayRepositoryInterface $entity_display_repository, - AccountProxyInterface $currentUser, + protected readonly AccountProxyInterface $currentUser, ) { parent::__construct($entity_type, $entity_repository, $language_manager, $theme_registry, $entity_display_repository); - $this->currentUser = $currentUser; } /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type): PrivateMessageViewBuilder { + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type): self { return new static( $entity_type, $container->get('entity.repository'), @@ -70,6 +49,8 @@ class PrivateMessageViewBuilder extends EntityViewBuilder { * {@inheritdoc} */ public function view(EntityInterface $entity, $view_mode = 'default', $langcode = NULL): array { + assert($entity instanceof PrivateMessageInterface); + $message = parent::view($entity, $view_mode, $langcode); $classes = ['private-message']; diff --git a/src/Entity/PrivateMessage.php b/src/Entity/PrivateMessage.php index 6928aa6fa2a5b8d85932c0325118a42baf1b7bb8..0209eb0ee58b3c4750e52c1ffbe7856183b6f1a3 100644 --- a/src/Entity/PrivateMessage.php +++ b/src/Entity/PrivateMessage.php @@ -1,15 +1,16 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity; use Drupal\Core\Entity\ContentEntityBase; -use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; -use Drupal\user\UserInterface; +use Drupal\user\EntityOwnerTrait; /** - * Thee Private Message entity definition. + * The Private Message entity definition. * * @ContentEntityType( * id = "private_message", @@ -28,7 +29,8 @@ use Drupal\user\UserInterface; * fieldable = TRUE, * entity_keys = { * "id" = "id", - * "uuid" = "uuid" + * "uuid" = "uuid", + * "owner" = "owner", * }, * links = { * "canonical" = "/private-message/{private_message}", @@ -39,78 +41,37 @@ use Drupal\user\UserInterface; */ class PrivateMessage extends ContentEntityBase implements PrivateMessageInterface { - /** - * {@inheritdoc} - * - * When a new private message is created, set the owner entity reference to - * the current user as the creator of the instance. - */ - public static function preCreate(EntityStorageInterface $storage_controller, array &$values) { - parent::preCreate($storage_controller, $values); - $values += [ - 'owner' => \Drupal::currentUser()->id(), - ]; - } - - /** - * {@inheritdoc} - */ - public function getCreatedTime() { - return $this->get('created')->value; - } - - /** - * {@inheritdoc} - */ - public function getOwner() { - return $this->get('owner')->entity; - } - - /** - * {@inheritdoc} - */ - public function getOwnerId() { - return $this->get('owner')->target_id; - } + use EntityOwnerTrait; /** * {@inheritdoc} */ - public function setOwnerId($uid) { - $this->set('owner', $uid); - return $this; - } - - /** - * {@inheritdoc} - */ - public function setOwner(UserInterface $account) { - $this->set('owner', $account->id()); - return $this; + public function getCreatedTime(): int { + return (int) $this->get('created')->value; } /** * {@inheritdoc} */ public function getMessage() { + @trigger_error(__METHOD__ . "() is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. Instead, access the 'message' field. See https://www.drupal.org/node/3490530", E_USER_DEPRECATED); return $this->get('message')->value; } /** * {@inheritdoc} */ - public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { + public static function baseFieldDefinitions(EntityTypeInterface $entity_type): array { $fields = parent::baseFieldDefinitions($entity_type); + $fields += static::ownerBaseFieldDefinitions($entity_type); + $fields['id']->setLabel(t('Private message ID')) ->setDescription(t('The private message ID.')); $fields['uuid']->setDescription(t('The custom private message UUID.')); - // Owner of the private message. - // Entity reference field, holds the reference to the user object. The view - // shows the user name field of the user. No form field is provided, as the - // user will always be the current user. - $fields['owner'] = BaseFieldDefinition::create('entity_reference') + // No form field is provided, as the user will always be the current user. + $fields['owner'] ->setLabel(t('From')) ->setDescription(t('The author of the private message')) ->setSetting('target_type', 'user') diff --git a/src/Entity/PrivateMessageBan.php b/src/Entity/PrivateMessageBan.php index 2dd09e1c4d4e91dc517eb5563a5066ff3de84d7a..e4da0afb445b71b2da31bf43e83de6a3d296d75a 100644 --- a/src/Entity/PrivateMessageBan.php +++ b/src/Entity/PrivateMessageBan.php @@ -1,14 +1,14 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity; use Drupal\Core\Entity\ContentEntityBase; -use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; -use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; -use Drupal\user\Entity\User; +use Drupal\user\EntityOwnerTrait; use Drupal\user\UserInterface; /** @@ -16,8 +16,6 @@ use Drupal\user\UserInterface; * * This is a lightweight entity type used to store banned users. * - * @ingroup private_message - * * @ContentEntityType( * id = "private_message_ban", * label = @Translation("Private Message Ban"), @@ -41,7 +39,7 @@ use Drupal\user\UserInterface; * entity_keys = { * "id" = "id", * "uuid" = "uuid", - * "uid" = "owner", + * "owner" = "owner", * }, * links = { * "add-form" = "/admin/structure/private_message_ban/add", @@ -51,32 +49,24 @@ use Drupal\user\UserInterface; * }, * constraints = { * "UniquePrivateMessageBan" = {} - * } + * }, * ) */ class PrivateMessageBan extends ContentEntityBase implements PrivateMessageBanInterface { - /** - * {@inheritdoc} - */ - public static function preCreate(EntityStorageInterface $storage_controller, array &$values) { - parent::preCreate($storage_controller, $values); - $values += [ - 'owner' => \Drupal::currentUser()->id(), - ]; - } + use EntityOwnerTrait; /** * {@inheritdoc} */ public function getCreatedTime(): int { - return $this->get('created')->value; + return (int) $this->get('created')->value; } /** * {@inheritdoc} */ - public function setCreatedTime($timestamp) { + public function setCreatedTime(int $timestamp): PrivateMessageBanInterface { $this->set('created', $timestamp); return $this; } @@ -84,61 +74,34 @@ class PrivateMessageBan extends ContentEntityBase implements PrivateMessageBanIn /** * {@inheritdoc} */ - public function getOwner() { - return $this->get('owner')->entity; - } - - /** - * {@inheritdoc} - */ - public function getOwnerId() { - return $this->get('owner')->target_id; - } - - /** - * {@inheritdoc} - */ - public function setOwnerId($uid) { - $this->set('owner', $uid); - return $this; + public function getTarget(): UserInterface { + $targetUser = $this->get('target')->entity; + assert($targetUser instanceof UserInterface); + return $targetUser; } /** * {@inheritdoc} */ - public function setOwner(UserInterface $account) { - $this->set('owner', $account->id()); - return $this; - } - - /** - * {@inheritDoc} - */ - public function getTarget(): User { - return $this->get('target')->entity; - } - - /** - * {@inheritDoc} - */ public function getTargetId(): int { - return $this->get('target')->target_id; + return (int) $this->get('target')->target_id; } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function setTarget(AccountInterface $user): PrivateMessageBanInterface { + public function setTarget(UserInterface $user): PrivateMessageBanInterface { return $this->set('target', $user->id()); } /** * {@inheritdoc} */ - public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { + public static function baseFieldDefinitions(EntityTypeInterface $entity_type): array { $fields = parent::baseFieldDefinitions($entity_type); + $fields += static::ownerBaseFieldDefinitions($entity_type); - $fields['owner'] = BaseFieldDefinition::create('entity_reference') + $fields['owner'] ->setLabel(t('Owned by')) ->setDescription(t('The ID of user who performed the ban.')) ->setSetting('target_type', 'user') @@ -182,8 +145,10 @@ class PrivateMessageBan extends ContentEntityBase implements PrivateMessageBanIn /** * {@inheritdoc} */ - public function label() { - return new TranslatableMarkup('Private Message Ban by @username', ['@username' => $this->getOwner()->getDisplayName()]); + public function label(): TranslatableMarkup { + return new TranslatableMarkup('Private Message Ban by @username', [ + '@username' => $this->getOwner()->getDisplayName(), + ]); } } diff --git a/src/Entity/PrivateMessageBanInterface.php b/src/Entity/PrivateMessageBanInterface.php index 5c1fcbfd66e332e936b027df4f3b50463cd1d517..7071220f51a6b4fbf3425c5455c13e84ab25522e 100644 --- a/src/Entity/PrivateMessageBanInterface.php +++ b/src/Entity/PrivateMessageBanInterface.php @@ -1,11 +1,12 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity; use Drupal\Core\Entity\ContentEntityInterface; -use Drupal\Core\Session\AccountInterface; -use Drupal\user\Entity\User; use Drupal\user\EntityOwnerInterface; +use Drupal\user\UserInterface; /** * The Private Message Ban entity interface. @@ -28,15 +29,14 @@ interface PrivateMessageBanInterface extends ContentEntityInterface, EntityOwner * @param int $timestamp * The Private Message Ban creation timestamp. * - * @return \Drupal\private_message\Entity\PrivateMessageBanInterface - * The called Private Message Ban entity. + * @return $this */ - public function setCreatedTime($timestamp); + public function setCreatedTime(int $timestamp): self; /** * Gets banned user. */ - public function getTarget(): User; + public function getTarget(): UserInterface; /** * Gets target id. @@ -46,6 +46,6 @@ interface PrivateMessageBanInterface extends ContentEntityInterface, EntityOwner /** * Sets banned user. */ - public function setTarget(AccountInterface $user): self; + public function setTarget(UserInterface $user): self; } diff --git a/src/Entity/PrivateMessageInterface.php b/src/Entity/PrivateMessageInterface.php index 22fa1ea1795d40a665e18a8a7a897e0585eabb14..3ec7e25d67ec33f1e0e320e50031004f35513c99 100644 --- a/src/Entity/PrivateMessageInterface.php +++ b/src/Entity/PrivateMessageInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity; use Drupal\Core\Entity\ContentEntityInterface; @@ -7,18 +9,16 @@ use Drupal\user\EntityOwnerInterface; /** * Provides an interface defining a Private Message entity. - * - * @ingroup private_message */ interface PrivateMessageInterface extends ContentEntityInterface, EntityOwnerInterface { /** - * Get the time at which the private message was created. + * Gets the time at which the private message was created. * * @return int * A Unix timestamp indicating the time at which the private message was * created. */ - public function getCreatedTime(); + public function getCreatedTime(): int; } diff --git a/src/Entity/PrivateMessageThread.php b/src/Entity/PrivateMessageThread.php index 943a12d3e754a8dd444bfe861e10949c08bf3fbf..dc5e291eaf881d594268ff10ca56f14eeb06edf2 100644 --- a/src/Entity/PrivateMessageThread.php +++ b/src/Entity/PrivateMessageThread.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity; use Drupal\Core\Cache\Cache; @@ -44,39 +46,37 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function addMember(AccountInterface $account) { + public function addMember(AccountInterface $account): PrivateMessageThreadInterface { if (!$this->isMember($account->id())) { $this->get('members')->appendItem($account->id()); } - return $this; } /** * {@inheritdoc} */ - public function addMemberById($id) { + public function addMemberById(int|string $id): PrivateMessageThreadInterface { if (!$this->isMember($id)) { $this->get('members')->appendItem($id); } - return $this; } /** * {@inheritdoc} */ - public function getMembers() { + public function getMembers(): array { return $this->get('members')->referencedEntities(); } /** * {@inheritdoc} */ - public function getMembersId() { + public function getMemberIds(): array { $members = []; foreach ($this->get('members')->getValue() as $member_item) { - $members[] = $member_item['target_id']; + $members[] = (int) $member_item['target_id']; } return $members; } @@ -84,14 +84,22 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function isMember($id) { - return in_array($id, $this->getMembersId()); + public function getMembersId(): array { + @trigger_error(__METHOD__ . '() is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. Use self::getMemberIds() instead. See https://www.drupal.org/node/3490530', E_USER_DEPRECATED); + return $this->getMemberIds(); + } + + /** + * {@inheritdoc} + */ + public function isMember(int|string $id): bool { + return in_array((int) $id, $this->getMemberIds(), TRUE); } /** * {@inheritdoc} */ - public function addMessage(PrivateMessageInterface $privateMessage) { + public function addMessage(PrivateMessageInterface $privateMessage): PrivateMessageThreadInterface { $this->get('private_messages')->appendItem($privateMessage->id()); // Allow other modules to react on a new message in thread. // @todo Inject when entity dependency serialization core issues resolved. @@ -105,18 +113,17 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function addMessageById($id) { + public function addMessageById(int|string $id): PrivateMessageThreadInterface { $this->get('private_messages')->appendItem($id); - return $this; } /** * {@inheritdoc} */ - public function getMessages(bool $include_banned = FALSE) { + public function getMessages(bool $includeBlocked = FALSE): array { $messages = $this->get('private_messages')->referencedEntities(); - if ($include_banned) { + if ($includeBlocked) { return $messages; } @@ -132,6 +139,8 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh * {@inheritdoc} */ public function filterNewestMessages() { + @trigger_error(__METHOD__ . "() is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. No replacement is provided. See https://www.drupal.org/node/3490530", E_USER_DEPRECATED); + $messages = $this->getMessages(); if (count($messages) > \Drupal::config('private_message_thread.settings')->get('message_count')) { $list = $this->get('private_messages'); @@ -152,11 +161,11 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function getNewestMessageCreationTimestamp() { + public function getNewestMessageCreationTimestamp(): int { $messages = $this->getMessages(); $last_timestamp = 0; foreach ($messages as $message) { - $creation_date = $message->get('created')->value; + $creation_date = (int) $message->get('created')->value; $last_timestamp = max($creation_date, $last_timestamp); } @@ -166,7 +175,7 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function addHistoryRecord(AccountInterface $account) { + public function addHistoryRecord(AccountInterface $account): void { \Drupal::database()->insert('pm_thread_history') ->fields([ 'uid' => $account->id(), @@ -177,8 +186,8 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function getLastAccessTimestamp(AccountInterface $account) { - return \Drupal::database()->select('pm_thread_history', 'pm_thread_history') + public function getLastAccessTimestamp(AccountInterface $account): int { + return (int) \Drupal::database()->select('pm_thread_history', 'pm_thread_history') ->condition('uid', $account->id()) ->condition('thread_id', $this->id()) ->fields('pm_thread_history', ['access_timestamp']) @@ -189,7 +198,7 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function updateLastAccessTime(AccountInterface $account) { + public function updateLastAccessTime(AccountInterface $account): PrivateMessageThreadInterface { \Drupal::database()->update('pm_thread_history') ->condition('uid', $account->id()) ->condition('thread_id', $this->id()) @@ -201,8 +210,8 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function getLastDeleteTimestamp(AccountInterface $account) { - return \Drupal::database()->select('pm_thread_history', 'pm_thread_history') + public function getLastDeleteTimestamp(AccountInterface $account): int { + return (int) \Drupal::database()->select('pm_thread_history', 'pm_thread_history') ->condition('uid', $account->id()) ->condition('thread_id', $this->id()) ->fields('pm_thread_history', ['delete_timestamp']) @@ -213,7 +222,7 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function updateLastDeleteTime(AccountInterface $account) { + public function updateLastDeleteTime(AccountInterface $account): PrivateMessageThreadInterface { \Drupal::database()->update('pm_thread_history') ->condition('uid', $account->id()) ->condition('thread_id', $this->id()) @@ -226,6 +235,7 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh * {@inheritdoc} */ public function save() { + // @todo This should be investigated. $this->clearCacheTags(); return parent::save(); } @@ -233,11 +243,12 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public static function preDelete(EntityStorageInterface $storage, array $entities) { + public static function preDelete(EntityStorageInterface $storage, array $entities): void { parent::preDelete($storage, $entities); // Delete the thread from the database, as well as all reference entities. foreach ($entities as $entity) { + assert($entity instanceof PrivateMessageThreadInterface); $messages = $entity->getMessages(TRUE); foreach ($messages as $message) { $message->delete(); @@ -251,9 +262,10 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public static function postDelete(EntityStorageInterface $storage, array $entities) { + public static function postDelete(EntityStorageInterface $storage, array $entities): void { parent::postDelete($storage, $entities); foreach ($entities as $entity) { + assert($entity instanceof PrivateMessageThreadInterface); $entity->clearCacheTags(); } } @@ -261,7 +273,7 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function clearAccountHistory(?AccountInterface $account = NULL) { + public function clearAccountHistory(?AccountInterface $account = NULL): void { if (!$account) { $account = \Drupal::currentUser(); } @@ -287,7 +299,7 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function filterUserDeletedMessages(AccountInterface $account) { + public function filterUserDeletedMessages(AccountInterface $account): array { $last_delete_timestamp = $this->getLastDeleteTimestamp($account); $messages = $this->getMessages(); $start_index = FALSE; @@ -309,14 +321,14 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function getUpdatedTime() { - return $this->get('updated')->value; + public function getUpdatedTime(): int { + return (int) $this->get('updated')->value; } /** * {@inheritdoc} */ - public function clearCacheTags() { + public function clearCacheTags(): void { $tags = []; foreach ($this->getMembers() as $member) { @@ -334,8 +346,8 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public static function baseFieldDefinitions(EntityTypeInterface $entityType) { - $fields = parent::baseFieldDefinitions($entityType); + public static function baseFieldDefinitions(EntityTypeInterface $entity_type): array { + $fields = parent::baseFieldDefinitions($entity_type); $fields['id']->setLabel(t('Private message thread ID')) ->setDescription(t('The private message thread ID.')); @@ -406,7 +418,7 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function getCacheTags() { + public function getCacheTags(): array { $tags = parent::getCacheTags(); $tags[] = 'private_message_thread:' . $this->id() . ':view:uid:' . \Drupal::currentUser()->id(); @@ -416,7 +428,7 @@ class PrivateMessageThread extends ContentEntityBase implements PrivateMessageTh /** * {@inheritdoc} */ - public function postSave(EntityStorageInterface $storage, $update = TRUE) { + public function postSave(EntityStorageInterface $storage, $update = TRUE): void { parent::postSave($storage, $update); if (!$update) { $members = $this->getMembers(); diff --git a/src/Entity/PrivateMessageThreadInterface.php b/src/Entity/PrivateMessageThreadInterface.php index cab0cebb16a66fee55af7448163ed3e084a3a860..c21fec7a94da56706b0c1b6096e1e73abe7a0e0b 100644 --- a/src/Entity/PrivateMessageThreadInterface.php +++ b/src/Entity/PrivateMessageThreadInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Entity; use Drupal\Core\Entity\ContentEntityInterface; @@ -7,112 +9,130 @@ use Drupal\Core\Session\AccountInterface; /** * Provides an interface defining a Private Message thread entity. - * - * @ingroup private_message */ interface PrivateMessageThreadInterface extends ContentEntityInterface { /** - * Add a member to the private message thread. + * Adds a member to the private message thread. * - * @param \Drupal\user\AccountInterface $account + * @param \Drupal\Core\Session\AccountInterface $account * The account to be set as a member of the private message thread. * - * @return \Drupal\private_message\Entity\PrivateMessageInterface - * Returns the class itself to allow for chaining. + * @return $this */ - public function addMember(AccountInterface $account); + public function addMember(AccountInterface $account): self; /** - * Add a member to the private message thread. + * Adds a member to the private message thread by its ID. * - * @param int $id - * The ID of the account to be set as a member of the private message - * thread. + * @param int|string $id + * The ID of the user to be set as a member of the private message thread. * - * @return \Drupal\private_message\Entity\PrivateMessageInterface - * Returns the class itself to allow for chaining. + * @return $this */ - public function addMemberById($id); + public function addMemberById(int|string $id): self; /** - * Retrieve the ids of the members of the private message thread. + * Retrieves the IDs of the members of the private message thread. + * + * @return int[] + * A list of member IDs */ - public function getMembersId(); + public function getMemberIds(): array; /** - * Retrieve the members of the private message thread. + * Retrieves the IDs of the members of the private message thread. + * + * @return int[] + * A list of member IDs + * + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. Use self::getMemberIds() instead. + * + * @see https://www.drupal.org/node/3490530 */ - public function getMembers(); + public function getMembersId(): array; /** - * Check if the user with the given ID is a member of the thread. + * Retrieves the members of the private message thread. * - * @param int $id + * @return \Drupal\user\UserInterface[] + * A list of members user accounts. + */ + public function getMembers(): array; + + /** + * Checks if the user with the given ID is a member of the thread. + * + * @param int|string $id * The User ID of the user to check. * * @return bool - * - TRUE if the user is a member of the thread - * - FALSE if they are not + * Whether the user is member of the thread. */ - public function isMember($id); + public function isMember(int|string $id): bool; /** - * Add a private message to the list of messages in this thread. + * Adds a private message to the list of messages in this thread. * * @param \Drupal\private_message\Entity\PrivateMessageInterface $privateMessage * The private message to be added to the thread. * - * @return \Drupal\private_message\Entity\PrivateMessageThread - * The private message thread. + * @return $this */ - public function addMessage(PrivateMessageInterface $privateMessage); + public function addMessage(PrivateMessageInterface $privateMessage): self; /** - * Add a private message by ID to the list of the messages in this thread. + * Adds a private message by ID to the list of the messages in this thread. * - * @param int $id + * @param int|string $id * The ID of the private message to be added to the thread. + * + * @return $this */ - public function addMessageById($id); + public function addMessageById(int|string $id): self; /** - * Retrieve all private messages attached to this thread. + * Retrieves all private messages attached to this thread. * - * @param bool $include_banned - * (Optional) Whether to include messages from banned users. Defaults to - * FALSE. + * @param bool $includeBlocked + * (optional) Include messages from blocked users? Defaults to FALSE. * - * @return \Drupal\Core\Field\EntityReferenceFieldItemListInterface + * @return \Drupal\private_message\Entity\PrivateMessageInterface[] * A list of private messages attached to this thread */ - public function getMessages(bool $include_banned = FALSE); + public function getMessages(bool $includeBlocked = FALSE): array; /** - * Filter the list down to only the newest messages. + * Filters the list down to only the newest messages. * * Note that other messages will be loadable through AJAX. + * + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. No replacement is provided. + * + * @see https://www.drupal.org/node/3490530 */ public function filterNewestMessages(); /** - * Get the created timestamp of the newest private message in the thread. + * Gets the created timestamp of the newest private message in the thread. * * @return int * The Unix timestamp of the newest message in the thread */ - public function getNewestMessageCreationTimestamp(); + public function getNewestMessageCreationTimestamp(): int; /** - * Add a history record to the current thread for the given user. + * Adds a history record to the current thread for the given user. * * @param \Drupal\Core\Session\AccountInterface $account * The user whose access time should be updated. */ - public function addHistoryRecord(AccountInterface $account); + public function addHistoryRecord(AccountInterface $account): void; /** - * Get the last access timestamp for the given user. + * Gets the last access timestamp for the given user. * * @param \Drupal\Core\Session\AccountInterface $account * The user whose last access time should be retrieved. @@ -120,18 +140,20 @@ interface PrivateMessageThreadInterface extends ContentEntityInterface { * @return int * The timestamp at which the user last accessed the thread */ - public function getLastAccessTimestamp(AccountInterface $account); + public function getLastAccessTimestamp(AccountInterface $account): int; /** - * Update the last access time for the given user. + * Updates the last access time for the given user. * * @param \Drupal\Core\Session\AccountInterface $account * The user whose last access time should be updated. + * + * @return $this */ - public function updateLastAccessTime(AccountInterface $account); + public function updateLastAccessTime(AccountInterface $account): self; /** - * Get the last delete timestamp for the given user. + * Gets the last delete timestamp for the given user. * * @param \Drupal\Core\Session\AccountInterface $account * The user whose last delete time should be retrieved. @@ -140,22 +162,17 @@ interface PrivateMessageThreadInterface extends ContentEntityInterface { * A UNIX timestamp indicating the last time the user marked the thread as * deleted. */ - public function getLastDeleteTimestamp(AccountInterface $account); + public function getLastDeleteTimestamp(AccountInterface $account): int; /** - * Update the last delete time for the given user. + * Updates the last delete time for the given user. * * @param \Drupal\Core\Session\AccountInterface $account * The user whose last delete time should be updated. - */ - public function updateLastDeleteTime(AccountInterface $account); - - /** - * Performs a complete delete action on the private message thread. * - * Includes deleting of all messages. + * @return $this */ - public function delete(); + public function updateLastDeleteTime(AccountInterface $account): self; /** * Provides clear thread history feature. @@ -173,10 +190,10 @@ interface PrivateMessageThreadInterface extends ContentEntityInterface { * (Optional) Account for which thread history will be cleared. * If no account provided, the current user will be used. */ - public function clearAccountHistory(?AccountInterface $account = NULL); + public function clearAccountHistory(?AccountInterface $account = NULL): void; /** - * Filter messages in the thread deleted by the given account. + * Filters messages in the thread deleted by the given account. * * Only messages created after the last time the user deleted the thread will * be shown. If they have never deleted the thread, all messages are returned. @@ -184,14 +201,22 @@ interface PrivateMessageThreadInterface extends ContentEntityInterface { * @param \Drupal\Core\Session\AccountInterface $account * The user for whom private messages should be returned. * - * @return Drupal\private_message\Entity\PrivateMessage[] + * @return \Drupal\private_message\Entity\PrivateMessageInterface[] * An array of private messages */ - public function filterUserDeletedMessages(AccountInterface $account); + public function filterUserDeletedMessages(AccountInterface $account): array; + + /** + * Returns the thread last updated time. + * + * @return int + * Thread last updated time. + */ + public function getUpdatedTime(): int; /** - * Clear cache tags related to private message thread entities. + * Clears cache tags related to private message thread entities. */ - public function clearCacheTags(); + public function clearCacheTags(): void; } diff --git a/src/Form/AdminUninstallForm.php b/src/Form/AdminUninstallForm.php index 748f7664323bda48d1d41c02373f0f4e6d6a9536..97fea4fe71d6280f46a234e88845d620140faa78 100644 --- a/src/Form/AdminUninstallForm.php +++ b/src/Form/AdminUninstallForm.php @@ -1,9 +1,12 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; use Drupal\private_message\Service\PrivateMessageUninstallerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -20,7 +23,7 @@ class AdminUninstallForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public static function create(ContainerInterface $container) { + public static function create(ContainerInterface $container): self { return new static( $container->get('private_message.uninstaller') ); @@ -29,35 +32,35 @@ class AdminUninstallForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function getFormId() { + public function getFormId(): string { return 'private_message_admin_uninstall_form'; } /** * {@inheritdoc} */ - public function getQuestion() { + public function getQuestion(): TranslatableMarkup { return $this->t('Are you sure you want to delete all private message content from the system?'); } /** * {@inheritdoc} */ - public function getCancelUrl() { + public function getCancelUrl(): Url { return Url::fromRoute('private_message.admin_config.uninstall'); } /** * {@inheritdoc} */ - public function getDescription() { + public function getDescription(): TranslatableMarkup|string { return $this->t('Clicking the button below will delete all private message content from the system, allowing the module to be uninstalled.') . '<br><strong>' . $this->t('THIS ACTION CANNOT BE REVERSED') . '</strong>'; } /** * {@inheritdoc} */ - public function submitForm(array &$form, FormStateInterface $form_state) { + public function submitForm(array &$form, FormStateInterface $form_state): void { $this->privateMessageUninstaller->initiateBatch(); $this->messenger() diff --git a/src/Form/BanUserForm.php b/src/Form/BanUserForm.php index 6e1ebadfa217dbeaac7e3f7c6d8bbf34478464e9..b73c88cedaa36101bdd772b4d16edf1543464577 100644 --- a/src/Form/BanUserForm.php +++ b/src/Form/BanUserForm.php @@ -1,83 +1,26 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; -use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Session\AccountProxyInterface; use Drupal\private_message\Service\PrivateMessageBanManagerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Private Message users banning form. */ class BanUserForm extends FormBase { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The entity type manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected EntityTypeManagerInterface $entityTypeManager; - - /** - * The private message configuration. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected $configFactory; - - /** - * The Private Message Ban manager. - * - * @var \Drupal\private_message\Service\PrivateMessageBanManagerInterface - */ - private PrivateMessageBanManagerInterface $privateMessageBanManager; + use AutowireTrait; - /** - * Constructs a BanUserForm object. - * - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * The configuration factory service. - * @param \Drupal\private_message\Service\PrivateMessageBanManagerInterface $privateMessageBanManager - * The Private Message Ban manager. - */ public function __construct( - AccountProxyInterface $currentUser, - EntityTypeManagerInterface $entityTypeManager, - ConfigFactoryInterface $configFactory, - PrivateMessageBanManagerInterface $privateMessageBanManager, - ) { - $this->currentUser = $currentUser; - $this->entityTypeManager = $entityTypeManager; - $this->configFactory = $configFactory; - $this->privateMessageBanManager = $privateMessageBanManager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container): self { - return new static( - $container->get('current_user'), - $container->get('entity_type.manager'), - $container->get('config.factory'), - $container->get('private_message.ban_manager'), - ); - } + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly PrivateMessageBanManagerInterface $privateMessageBanManager, + ) {} /** * {@inheritdoc} @@ -90,7 +33,7 @@ class BanUserForm extends FormBase { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state): array { - $config = $this->configFactory->get('private_message.settings'); + $config = $this->config('private_message.settings'); $form['banned_user'] = [ '#title' => $this->t('Select User'), @@ -118,7 +61,7 @@ class BanUserForm extends FormBase { public function validateForm(array &$form, FormStateInterface $form_state): void { $userId = $form_state->getValue('banned_user'); // Add security to prevent blocking ourselves. - if ($userId === $this->currentUser->id()) { + if ($userId === $this->currentUser()->id()) { $form_state->setErrorByName($userId, $this->t("You can't block yourself.")); } diff --git a/src/Form/ConfigForm.php b/src/Form/ConfigForm.php index 1993bdce8a4f53a61d24ecfa44c9136451e0ef99..841cfc79d1b1b62494e1607a6a244b877fa311d2 100644 --- a/src/Form/ConfigForm.php +++ b/src/Form/ConfigForm.php @@ -1,65 +1,66 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\TypedConfigManagerInterface; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\Core\Form\ConfigFormBase; +use Drupal\Core\Form\ConfigTarget; use Drupal\Core\Form\FormStateInterface; -use Drupal\private_message\PluginManager\PrivateMessageConfigFormManager; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\private_message\Model\BlockType; +use Drupal\private_message\PluginManager\PrivateMessageConfigFormManagerInterface; /** * Defines the configuration form for the private message module. */ class ConfigForm extends ConfigFormBase { + use AutowireTrait; + /** - * Ban types. + * Blocking type: passive. * - * @todo Move to Enum. + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. Instead, use + * \Drupal\private_message\Model\BlockType::Passive. + * + * @see https://www.drupal.org/node/3490530 */ const PASSIVE = 'passive'; - const ACTIVE = 'active'; /** - * The private message config form plugin manager. + * Blocking type: active. * - * @var \Drupal\private_message\PluginManager\PrivateMessageConfigFormManager + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. Instead, use + * \Drupal\private_message\Model\BlockType::Active. + * + * @see https://www.drupal.org/node/3490530 */ - protected $privateMessageConfigFormManager; + const ACTIVE = 'active'; public function __construct( ConfigFactoryInterface $configFactory, TypedConfigManagerInterface $typedConfigManager, - PrivateMessageConfigFormManager $privateMessageConfigFormManager, + protected readonly PrivateMessageConfigFormManagerInterface $privateMessageConfigFormManager, ) { parent::__construct($configFactory, $typedConfigManager); - $this->privateMessageConfigFormManager = $privateMessageConfigFormManager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('config.factory'), - $container->get('config.typed'), - $container->get('private_message.private_message_config_form_manager') - ); } /** * {@inheritdoc} */ - public function getFormId() { + public function getFormId(): string { return 'private_message_config_form'; } /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $formState) { + public function buildForm(array $form, FormStateInterface $form_state): array { $config = $this->config('private_message.settings'); $form['pm_core'] = [ @@ -77,7 +78,11 @@ class ConfigForm extends ConfigFormBase { $form['pm_core']['notifications']['enable_notifications'] = [ '#type' => 'checkbox', '#title' => $this->t('Enable notifications'), - '#default_value' => $config->get('enable_notifications'), + '#config_target' => new ConfigTarget( + configName: 'private_message.settings', + propertyPath: 'enable_notifications', + toConfig: fn($value): bool => boolval($value), + ), ]; $form['pm_core']['notifications']['notify_by_default'] = [ @@ -87,7 +92,12 @@ class ConfigForm extends ConfigFormBase { $this->t('Do not send notifications (users can opt-in)'), $this->t('Send notifications (users can opt-out)'), ], - '#default_value' => (int) $config->get('notify_by_default'), + '#config_target' => new ConfigTarget( + configName: 'private_message.settings', + propertyPath: 'notify_by_default', + fromConfig: fn($value): int => intval($value), + toConfig: fn($value): bool => boolval($value), + ), '#states' => [ 'visible' => [ ':input[name="enable_notifications"]' => ['checked' => TRUE], @@ -102,7 +112,7 @@ class ConfigForm extends ConfigFormBase { 'yes' => $this->t('For every private message'), 'no' => $this->t('Only when the user is not viewing the thread'), ], - '#default_value' => $config->get('notify_when_using'), + '#config_target' => 'private_message.settings:notify_when_using', '#description' => $this->t("Whether or not notifications should be sent when the user is viewing a given thread. Users will be able to override this value on their profile settings page."), '#states' => [ 'visible' => [ @@ -114,7 +124,11 @@ class ConfigForm extends ConfigFormBase { $form['pm_core']['notifications']['number_of_seconds_considered_away'] = [ '#type' => 'number', '#title' => $this->t('The number of seconds after which a user should be considered as not viewing a thread'), - '#default_value' => $config->get('number_of_seconds_considered_away'), + '#config_target' => new ConfigTarget( + configName: 'private_message.settings', + propertyPath: 'number_of_seconds_considered_away', + toConfig: fn($value): int => intval($value), + ), '#description' => $this->t('When users have a private message thread open, calls to the server update the last time they have accessed the thread. This setting determines how many seconds after they have closed the thread, they should be considered as not accessing the thread anymore. Users will be able to override this value on their profile settings page.'), '#states' => [ 'visible' => [ @@ -128,14 +142,22 @@ class ConfigForm extends ConfigFormBase { '#type' => 'checkbox', '#title' => $this->t('Hide recipient field when recipient is in the URL'), '#description' => $this->t('Links can be created to the private message page, passing the recipient in the URL. If this box is checked, the recipient field will be hidden when the recipient is passed in the URL.'), - '#default_value' => (int) $config->get('hide_recipient_field_when_prefilled'), + '#config_target' => new ConfigTarget( + configName: 'private_message.settings', + propertyPath: 'hide_recipient_field_when_prefilled', + toConfig: fn($value): bool => boolval($value), + ), ]; $form['pm_core']['autofocus_enable'] = [ '#type' => 'checkbox', '#title' => $this->t('Enable autofocus'), '#description' => $this->t('This option allows you to put the autofocus in the message textarea.'), - '#default_value' => (int) $config->get('autofocus_enable'), + '#config_target' => new ConfigTarget( + configName: 'private_message.settings', + propertyPath: 'autofocus_enable', + toConfig: fn($value): bool => boolval($value), + ), ]; $form['pm_core']['keys_send'] = [ @@ -147,14 +169,18 @@ class ConfigForm extends ConfigFormBase { '@key-list' => 'https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values', '@keycode-list' => 'https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode', ]), - '#default_value' => $config->get('keys_send'), + '#config_target' => 'private_message.settings:keys_send', ]; $form['pm_core']['remove_css'] = [ '#type' => 'checkbox', '#title' => $this->t('Remove the default CSS of the module'), '#description' => $this->t('This option can break the features of the module and it is only for developers who want to override the styles more easily.'), - '#default_value' => (int) $config->get('remove_css'), + '#config_target' => new ConfigTarget( + configName: 'private_message.settings', + propertyPath: 'remove_css', + toConfig: fn($value): bool => boolval($value), + ), ]; $form['pm_labels'] = [ @@ -166,13 +192,13 @@ class ConfigForm extends ConfigFormBase { $form['pm_labels']['create_message_label'] = [ '#type' => 'textfield', '#title' => $this->t("Text To Create Private Message"), - '#default_value' => $config->get('create_message_label'), + '#config_target' => 'private_message.settings:create_message_label', ]; $form['pm_labels']['save_message_label'] = [ '#type' => 'textfield', '#title' => $this->t("Text to submit a new message"), - '#default_value' => $config->get('save_message_label'), + '#config_target' => 'private_message.settings:save_message_label', '#description' => $this->t('The label of the button to send a new message.'), ]; @@ -185,17 +211,12 @@ class ConfigForm extends ConfigFormBase { $form['pm_block']['ban_mode'] = [ '#type' => 'radios', '#title' => $this->t("Blocking mode"), - '#default_value' => $config->get('ban_mode') ?: self::PASSIVE, - '#options' => [ - self::PASSIVE => $this - ->t('Passive'), - self::ACTIVE => $this - ->t('Active'), - ], - self::PASSIVE => [ + '#config_target' => 'private_message.settings:ban_mode', + '#options' => BlockType::asOptions(), + BlockType::Passive->value => [ '#description' => $this->t('Blocked members do not know they are blocked and can message the user that blocked them. The user who blocked them will not see the message.'), ], - self::ACTIVE => [ + BlockType::Active->value => [ '#description' => $this->t('Blocked members cannot message users that blocked them and instead a message is shown.'), ], ]; @@ -203,25 +224,25 @@ class ConfigForm extends ConfigFormBase { $form['pm_block']['ban_label'] = [ '#type' => 'textfield', '#title' => $this->t("Button label to ban a user"), - '#default_value' => $config->get('ban_label'), + '#config_target' => 'private_message.settings:ban_label', ]; $form['pm_block']['unban_label'] = [ '#type' => 'textfield', '#title' => $this->t("Button label to unban a user"), - '#default_value' => $config->get('unban_label'), + '#config_target' => 'private_message.settings:unban_label', ]; $form['pm_block']['ban_page_label'] = [ '#type' => 'textfield', '#title' => $this->t("Text to go to the ban page"), - '#default_value' => $config->get('ban_page_label'), + '#config_target' => 'private_message.settings:ban_page_label', ]; $form['pm_block']['ban_message'] = [ '#type' => 'textfield', '#title' => $this->t("Text to show when a blocked user tries to send a message."), - '#default_value' => $config->get('ban_message'), + '#config_target' => 'private_message.settings:ban_message', ]; $definitions = $this->privateMessageConfigFormManager->getDefinitions(); @@ -233,60 +254,42 @@ class ConfigForm extends ConfigFormBase { '#tree' => TRUE, '#open' => TRUE, ]; - foreach ($instance->buildForm($formState) as $key => $element) { + foreach ($instance->buildForm($form_state) as $key => $element) { $form[$instance->getId()][$key] = $element; } } - return parent::buildForm($form, $formState); + return parent::buildForm($form, $form_state); } /** * {@inheritdoc} */ - public function validateForm(array &$form, FormStateInterface $formState) { + public function validateForm(array &$form, FormStateInterface $form_state): void { $definitions = $this->privateMessageConfigFormManager->getDefinitions(); foreach ($definitions as $definition) { $instance = $this->privateMessageConfigFormManager->createInstance($definition['id']); - $instance->validateForm($form, $formState); + $instance->validateForm($form, $form_state); } } /** * {@inheritdoc} */ - public function submitForm(array &$form, FormStateInterface $formState) { - $this->config('private_message.settings') - ->set('enable_notifications', (bool) $formState->getValue('enable_notifications')) - ->set('notify_by_default', (bool) $formState->getValue('notify_by_default')) - ->set('notify_when_using', (string) $formState->getValue('notify_when_using')) - ->set('number_of_seconds_considered_away', (int) $formState->getValue('number_of_seconds_considered_away')) - ->set('hide_recipient_field_when_prefilled', (bool) $formState->getValue('hide_recipient_field_when_prefilled')) - ->set('create_message_label', $formState->getValue('create_message_label')) - ->set('save_message_label', $formState->getValue('save_message_label')) - ->set('ban_mode', $formState->getValue('ban_mode')) - ->set('ban_label', $formState->getValue('ban_label')) - ->set('unban_label', $formState->getValue('unban_label')) - ->set('ban_page_label', $formState->getValue('ban_page_label')) - ->set('ban_message', $formState->getValue('ban_message')) - ->set('autofocus_enable', (bool) $formState->getValue('autofocus_enable')) - ->set('keys_send', $formState->getValue('keys_send')) - ->set('remove_css', (bool) $formState->getValue('remove_css')) - ->save(); - + public function submitForm(array &$form, FormStateInterface $form_state): void { $definitions = $this->privateMessageConfigFormManager->getDefinitions(); foreach ($definitions as $definition) { $instance = $this->privateMessageConfigFormManager->createInstance($definition['id']); - $instance->submitForm($formState->getValue($instance->getId())); + $instance->submitForm($form_state->getValue($instance->getId())); } - parent::submitForm($form, $formState); + parent::submitForm($form, $form_state); } /** * {@inheritdoc} */ - protected function getEditableConfigNames() { + protected function getEditableConfigNames(): array { return [ 'private_message.settings', ]; diff --git a/src/Form/ConfirmBanUserForm.php b/src/Form/ConfirmBanUserForm.php index 456520b4ed0eabedcfad5ac95f50f5d2c0c69ad3..1aaaca275d129ace97f23b7bf21c4d428dd75d1e 100644 --- a/src/Form/ConfirmBanUserForm.php +++ b/src/Form/ConfirmBanUserForm.php @@ -1,79 +1,37 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; +use Drupal\private_message\Model\BlockType; use Drupal\private_message\Service\PrivateMessageBanManagerInterface; use Drupal\user\UserInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** - * The User Ban confirmation form. + * The user block confirmation form. */ class ConfirmBanUserForm extends ConfirmFormBase { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The entity type manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected EntityTypeManagerInterface $entityTypeManager; - - /** - * The Private Message Ban manager. - * - * @var \Drupal\private_message\Service\PrivateMessageBanManagerInterface - */ - protected PrivateMessageBanManagerInterface $privateMessageBanManager; + use AutowireTrait; /** * The user to block. - * - * @var \Drupal\user\UserInterface|null */ - protected ?UserInterface $user; + protected UserInterface $user; - /** - * Constructs a ConfirmBanUserForm object. - * - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager service. - * @param \Drupal\private_message\Service\PrivateMessageBanManagerInterface $privateMessageBanManager - * The Private Message Ban manager. - */ public function __construct( - AccountProxyInterface $currentUser, - EntityTypeManagerInterface $entityTypeManager, - PrivateMessageBanManagerInterface $privateMessageBanManager, - ) { - $this->currentUser = $currentUser; - $this->entityTypeManager = $entityTypeManager; - $this->privateMessageBanManager = $privateMessageBanManager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('current_user'), - $container->get('entity_type.manager'), - $container->get('private_message.ban_manager'), - ); - } + protected readonly AccountProxyInterface $currentUser, + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly PrivateMessageBanManagerInterface $privateMessageBanManager, + ) {} /** * {@inheritdoc} @@ -85,28 +43,19 @@ class ConfirmBanUserForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, $user = NULL): array { - if (is_scalar($user)) { - @trigger_error('Passing $user as ' . gettype($user) . ' is deprecated in private_message:3.0.3 and is removed from private_message:4.0.0. The $user parameter should be of type UserInterface. See https://www.drupal.org/node/3484561', E_USER_DEPRECATED); - $this->user = $this->entityTypeManager->getStorage('user')->load($user); - } - elseif ($user instanceof UserInterface) { - $this->user = $user; - } - elseif ($user === NULL) { - return []; - } - + public function buildForm(array $form, FormStateInterface $form_state, ?UserInterface $user = NULL): array { + $this->user = $user; return parent::buildForm($form, $form_state); } /** * {@inheritdoc} */ - public function validateForm(array &$form, FormStateInterface $form_state) { + public function validateForm(array &$form, FormStateInterface $form_state): void { // Add a security if the user id is unknown. if (empty($this->user)) { $form_state->setError($form, $this->t('The user id is unknown.')); + return; } // Add security to prevent blocking ourselves. @@ -118,7 +67,7 @@ class ConfirmBanUserForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function submitForm(array &$form, FormStateInterface $form_state) { + public function submitForm(array &$form, FormStateInterface $form_state): void { $form_state->setRedirect('private_message.private_message_page'); // If user is already banned, do nothing. @@ -135,17 +84,17 @@ class ConfirmBanUserForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function getQuestion() { + public function getQuestion(): TranslatableMarkup { return $this->t('Are you sure you want to block user <em>%user</em>?', ['%user' => $this->user->getDisplayName()]); } /** * {@inheritdoc} */ - public function getDescription() { + public function getDescription(): TranslatableMarkup { $config = $this->config('private_message.settings'); - if ($config->get('ban_mode') == ConfigForm::PASSIVE) { + if ($config->get('ban_mode') === BlockType::Passive->value) { return $this->t('By confirming, you will no longer be able to send messages to this user.'); } else { @@ -156,7 +105,7 @@ class ConfirmBanUserForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function getCancelUrl() { + public function getCancelUrl(): Url { return new Url('private_message.ban_page'); } diff --git a/src/Form/ConfirmUnbanUserForm.php b/src/Form/ConfirmUnbanUserForm.php index 5fdd732337232ddbcb596471e02f6fd85f128132..cf7c84f2d313914e79088b7240e1f5853fff76dd 100644 --- a/src/Form/ConfirmUnbanUserForm.php +++ b/src/Form/ConfirmUnbanUserForm.php @@ -1,79 +1,36 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; use Drupal\private_message\Service\PrivateMessageBanManagerInterface; use Drupal\user\UserInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * User unban confirmation form. */ class ConfirmUnbanUserForm extends ConfirmFormBase { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The entity type manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected EntityTypeManagerInterface $entityTypeManager; - - /** - * The Private Message Ban manager. - * - * @var \Drupal\private_message\Service\PrivateMessageBanManagerInterface - */ - private PrivateMessageBanManagerInterface $privateMessageBanManager; + use AutowireTrait; /** * The user to unban. - * - * @var \Drupal\user\UserInterface|null */ - private ?UserInterface $user; + private UserInterface $user; - /** - * Constructs a BlockUserForm object. - * - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager service. - * @param \Drupal\private_message\Service\PrivateMessageBanManagerInterface $privateMessageBanManager - * The Private Message Ban manager. - */ public function __construct( - AccountProxyInterface $currentUser, - EntityTypeManagerInterface $entityTypeManager, - PrivateMessageBanManagerInterface $privateMessageBanManager, - ) { - $this->currentUser = $currentUser; - $this->entityTypeManager = $entityTypeManager; - $this->privateMessageBanManager = $privateMessageBanManager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('current_user'), - $container->get('entity_type.manager'), - $container->get('private_message.ban_manager'), - ); - } + protected readonly AccountProxyInterface $currentUser, + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly PrivateMessageBanManagerInterface $privateMessageBanManager, + ) {} /** * {@inheritdoc} @@ -85,25 +42,15 @@ class ConfirmUnbanUserForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, $user = NULL): array { - if (is_scalar($user)) { - @trigger_error('Passing $user as ' . gettype($user) . ' is deprecated in private_message:3.0.3 and is removed from private_message:4.0.0. The $user parameter should be of type UserInterface. See https://www.drupal.org/node/3484561', E_USER_DEPRECATED); - $this->user = $this->entityTypeManager->getStorage('user')->load($user); - } - elseif ($user instanceof UserInterface) { - $this->user = $user; - } - elseif ($user === NULL) { - return []; - } - + public function buildForm(array $form, FormStateInterface $form_state, ?UserInterface $user = NULL): array { + $this->user = $user; return parent::buildForm($form, $form_state); } /** * {@inheritdoc} */ - public function validateForm(array &$form, FormStateInterface $form_state) { + public function validateForm(array &$form, FormStateInterface $form_state): void { // Add a security if the user id is unknown. if (empty($this->user)) { $form_state->setError($form, $this->t('The user id is unknown.')); @@ -118,7 +65,7 @@ class ConfirmUnbanUserForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function submitForm(array &$form, FormStateInterface $form_state) { + public function submitForm(array &$form, FormStateInterface $form_state): void { $form_state->setRedirect('private_message.private_message_page'); // If user not banned, do nothing. @@ -135,7 +82,7 @@ class ConfirmUnbanUserForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function getQuestion() { + public function getQuestion(): TranslatableMarkup { return $this->t('Are you sure you want to unblock user <em>%user</em>?', [ '%user' => $this->user->getDisplayName(), ]); @@ -144,14 +91,14 @@ class ConfirmUnbanUserForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function getDescription() { + public function getDescription(): TranslatableMarkup { return $this->t('By confirming, you will be able to send messages to this user.'); } /** * {@inheritdoc} */ - public function getCancelUrl() { + public function getCancelUrl(): Url { return new Url('private_message.ban_page'); } diff --git a/src/Form/PrivateMessageBanForm.php b/src/Form/PrivateMessageBanForm.php index 01992c69d208c8cb2e4d35979472d9093598bc96..a945807a0357703171a026480abb50e80e53d12c 100644 --- a/src/Form/PrivateMessageBanForm.php +++ b/src/Form/PrivateMessageBanForm.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; use Drupal\Core\Entity\ContentEntityForm; @@ -7,15 +9,13 @@ use Drupal\Core\Form\FormStateInterface; /** * Form controller for Private Message Ban edit forms. - * - * @ingroup private_message */ class PrivateMessageBanForm extends ContentEntityForm { /** * {@inheritdoc} */ - public function save(array $form, FormStateInterface $form_state) { + public function save(array $form, FormStateInterface $form_state): int { $status = parent::save($form, $form_state); switch ($status) { diff --git a/src/Form/PrivateMessageDeleteForm.php b/src/Form/PrivateMessageDeleteForm.php index a7e34722707cf9dc7a1ed17fd5ed17e155e31508..0eb95cce585c860035734f9eb9d7c8f25530f04d 100644 --- a/src/Form/PrivateMessageDeleteForm.php +++ b/src/Form/PrivateMessageDeleteForm.php @@ -1,7 +1,10 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; +use Drupal\Component\Render\MarkupInterface; use Drupal\Core\Entity\ContentEntityDeleteForm; /** @@ -12,14 +15,14 @@ class PrivateMessageDeleteForm extends ContentEntityDeleteForm { /** * {@inheritdoc} */ - protected function getDeletionMessage(): string { + protected function getDeletionMessage(): MarkupInterface|string { return $this->t('The message has been deleted.'); } /** * {@inheritdoc} */ - protected function logDeletionMessage() { + protected function logDeletionMessage(): void { $this->logger('private_message') ->notice('@user deleted a private message.', [ '@user' => $this->currentUser()->getDisplayName(), diff --git a/src/Form/PrivateMessageForm.php b/src/Form/PrivateMessageForm.php index 6b36b39bc2e9d130491a8d6447da43ca59b2640b..5d9f5d5015caabf1e3a76fdf41cd8874cdd924c6 100644 --- a/src/Form/PrivateMessageForm.php +++ b/src/Form/PrivateMessageForm.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; use Drupal\Component\Datetime\TimeInterface; @@ -7,178 +9,55 @@ use Drupal\Component\Utility\Html; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Config\ImmutableConfig; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormState; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element\StatusMessages; -use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\TypedData\TypedDataManagerInterface; use Drupal\private_message\Ajax\PrivateMessageInboxTriggerUpdateCommand; use Drupal\private_message\Ajax\PrivateMessageLoadNewMessagesCommand; use Drupal\private_message\Entity\PrivateMessage; use Drupal\private_message\Entity\PrivateMessageThread; use Drupal\private_message\Entity\PrivateMessageThreadInterface; +use Drupal\private_message\Model\BlockType; use Drupal\private_message\Service\PrivateMessageBanManagerInterface; use Drupal\private_message\Service\PrivateMessageServiceInterface; use Drupal\private_message\Service\PrivateMessageThreadManagerInterface; -use Drupal\user\UserDataInterface; +use Drupal\private_message\Traits\PrivateMessageSettingsTrait; use Drupal\user\UserInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines the private message form. */ class PrivateMessageForm extends ContentEntityForm { - /** - * A unique instance identifier for the form. - * - * @var int - */ - protected $formId; - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected $currentUser; - - /** - * The entity type manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * The typed data manager service. - * - * @var \Drupal\Core\TypedData\TypedDataManagerInterface - */ - protected $typedDataManager; - - /** - * The user data service. - * - * @var \Drupal\user\UserDataInterface - */ - protected $userData; - - /** - * The private message service. - * - * @var \Drupal\private_message\Service\PrivateMessageServiceInterface - */ - protected $privateMessageService; - - /** - * The private message thread manager service. - * - * @var \Drupal\private_message\Service\PrivateMessageThreadManagerInterface - */ - protected $privateMessageThreadManager; - - /** - * The Private Message Ban manager. - * - * @var \Drupal\private_message\Service\PrivateMessageBanManagerInterface - */ - protected PrivateMessageBanManagerInterface $privateMessageBanManager; + use AutowireTrait; + use PrivateMessageSettingsTrait; /** - * The Form Builder service. - * - * @var \Drupal\Core\Form\FormBuilderInterface - */ - protected $formBuilder; - - /** - * The message configuration. - * - * @var \Drupal\Core\Config\ImmutableConfig + * A unique instance identifier for the form. */ - protected ImmutableConfig $config; + protected string $formId = ''; - /** - * Constructs a PrivateMessageForm object. - * - * @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository - * The entity repository service. - * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info - * The entity type bundle service. - * @param \Drupal\Component\Datetime\TimeInterface $time - * The time service. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager service. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typedDataManager - * The typed data manager service. - * @param \Drupal\user\UserDataInterface $userData - * The user data service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * The configuration factory service. - * @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService - * The private message service. - * @param \Drupal\private_message\Service\PrivateMessageThreadManagerInterface $privateMessageThreadManager - * The private message thread manager service. - * @param \Drupal\private_message\Service\PrivateMessageBanManagerInterface $privateMessageBanManager - * The Private Message Ban manager. - * @param \Drupal\Core\Form\FormBuilderInterface $formBuilder - * The Form Builder service. - */ public function __construct( EntityRepositoryInterface $entityRepository, EntityTypeBundleInfoInterface $entity_type_bundle_info, TimeInterface $time, - EntityTypeManagerInterface $entityTypeManager, - AccountProxyInterface $currentUser, - TypedDataManagerInterface $typedDataManager, - UserDataInterface $userData, ConfigFactoryInterface $configFactory, - PrivateMessageServiceInterface $privateMessageService, - PrivateMessageThreadManagerInterface $privateMessageThreadManager, - PrivateMessageBanManagerInterface $privateMessageBanManager, - FormBuilderInterface $formBuilder, + protected readonly TypedDataManagerInterface $typedDataManager, + protected readonly PrivateMessageServiceInterface $privateMessageService, + protected readonly PrivateMessageThreadManagerInterface $privateMessageThreadManager, + protected readonly PrivateMessageBanManagerInterface $privateMessageBanManager, + protected readonly FormBuilderInterface $formBuilder, ) { parent::__construct($entityRepository, $entity_type_bundle_info, $time); - $this->entityTypeManager = $entityTypeManager; - $this->currentUser = $currentUser; - $this->typedDataManager = $typedDataManager; - $this->userData = $userData; - $this->config = $configFactory->get('private_message.settings'); - $this->privateMessageService = $privateMessageService; - $this->privateMessageThreadManager = $privateMessageThreadManager; - $this->privateMessageBanManager = $privateMessageBanManager; - $this->formBuilder = $formBuilder; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity.repository'), - $container->get('entity_type.bundle.info'), - $container->get('datetime.time'), - $container->get('entity_type.manager'), - $container->get('current_user'), - $container->get('typed_data_manager'), - $container->get('user.data'), - $container->get('config.factory'), - $container->get('private_message.service'), - $container->get('private_message.thread_manager'), - $container->get('private_message.ban_manager'), - $container->get('form_builder'), - ); + $this->configFactory = $configFactory; } /** @@ -188,15 +67,21 @@ class PrivateMessageForm extends ContentEntityForm { * * @param mixed $id * An ID required to be unique each time the form is called on a page. + * + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. No replacement is provided. + * + * @see https://www.drupal.org/node/3490530 */ public function setFormId($id) { + @trigger_error(__METHOD__ . '() is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. No replacement is provided. See https://www.drupal.org/node/3490530', E_USER_DEPRECATED); $this->formId = Html::escape($id); } /** * {@inheritdoc} */ - public function getFormId() { + public function getFormId(): string { $form_id = parent::getFormId(); if ($this->formId) { @@ -209,21 +94,21 @@ class PrivateMessageForm extends ContentEntityForm { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, ?PrivateMessageThreadInterface $privateMessageThread = NULL) { + public function buildForm(array $form, FormStateInterface $form_state, ?PrivateMessageThreadInterface $privateMessageThread = NULL): array { $form = parent::buildForm($form, $form_state); if ($privateMessageThread) { - $threadMembers = $privateMessageThread->getMembersId(); - $bannedUsers = $this->privateMessageBanManager->getBannedUsers($this->currentUser->id()); + $threadMembers = $privateMessageThread->getMemberIds(); + $bannedUsers = $this->privateMessageBanManager->getBannedUsers($this->currentUser()->id()); $banned = FALSE; foreach ($bannedUsers as $bannedUser) { if (\in_array($bannedUser, $threadMembers)) { - if (!empty($this->config->get('ban_message'))) { + if (!empty($this->getPrivateMessageSettings()->get('ban_message'))) { $this->messenger() - ->addError($this->config->get('ban_message')); + ->addError($this->getPrivateMessageSettings()->get('ban_message')); $form['message_for_user'] = [ StatusMessages::renderMessages(), @@ -239,16 +124,16 @@ class PrivateMessageForm extends ContentEntityForm { // Block messaging form for active blocking mode. if (!$banned) { - $ban_mode = $this->config->get('ban_mode'); - if ($ban_mode === ConfigForm::ACTIVE) { + $ban_mode = $this->getPrivateMessageSettings()->get('ban_mode'); + if ($ban_mode === BlockType::Active) { foreach ($threadMembers as $threadMember) { $bannedUsers = $this->privateMessageBanManager->getBannedUsers($threadMember); - if (in_array($this->currentUser->id(), $bannedUsers)) { + if (in_array($this->currentUser()->id(), $bannedUsers)) { - if (!empty($this->config->get('ban_message'))) { + if (!empty($this->getPrivateMessageSettings()->get('ban_message'))) { $this->messenger() - ->addError($this->config->get('ban_message')); + ->addError($this->getPrivateMessageSettings()->get('ban_message')); $form['message_for_user'] = [ StatusMessages::renderMessages(), @@ -272,8 +157,8 @@ class PrivateMessageForm extends ContentEntityForm { // Only to do these when using #ajax. $form['#attached']['library'][] = 'private_message/message_form'; - $form['#attached']['drupalSettings']['privateMessageSendKey'] = $this->config->get('keys_send'); - $autofocus_enabled = $this->config->get('autofocus_enable'); + $form['#attached']['drupalSettings']['privateMessageSendKey'] = $this->getPrivateMessageSettings()->get('keys_send'); + $autofocus_enabled = $this->getPrivateMessageSettings()->get('autofocus_enable'); if ($autofocus_enabled) { $form['message']['widget'][0]['#attributes']['autofocus'] = 'autofocus'; } @@ -311,7 +196,7 @@ class PrivateMessageForm extends ContentEntityForm { $form['#validate'][] = '::validateBannedMembers'; - if ($save_label = $this->config->get('save_message_label')) { + if ($save_label = $this->getPrivateMessageSettings()->get('save_message_label')) { $form['actions']['submit']['#value'] = $save_label; } @@ -319,7 +204,7 @@ class PrivateMessageForm extends ContentEntityForm { } /** - * Validate members that have been added to a private message thread. + * Validates members that have been added to a private message thread. * * Validates that submitted members have permission to use the Private * message system. This validation is not added automatically, as the members @@ -330,7 +215,7 @@ class PrivateMessageForm extends ContentEntityForm { * * @see \Drupal\private_message\Entity\PrivateMessageThead::baseFieldDefinitions */ - public function validateMembers(array &$form, FormStateInterface $formState) { + public function validateMembers(array &$form, FormStateInterface $formState): void { // The members form element was loaded from the PrivateMessageThread entity // type. As it is not a part of the PrivateMessage entity, for which this // form is built, the constraints that are a part of the field on the @@ -367,7 +252,7 @@ class PrivateMessageForm extends ContentEntityForm { } } - if ((count($members) === 1 && $this->currentUser->id() === $members[0]->id())) { + if ((count($members) === 1 && $this->currentUser()->id() === $members[0]->id())) { $formState->setError($form['members'], $this->t('You can not send a message to yourself only.')); } @@ -393,12 +278,11 @@ class PrivateMessageForm extends ContentEntityForm { /** * Validates that the current user isn't replying to a banned member. */ - public function validateBannedMembers(array &$form, FormStateInterface $formState) { - + public function validateBannedMembers(array &$form, FormStateInterface $formState): void { /** @var \Drupal\private_message\Entity\PrivateMessageThread|null $privateMessageThread */ $privateMessageThread = $formState->get('thread'); - $threadMembers = $privateMessageThread ? $privateMessageThread->getMembersId() : []; - $bannedUsers = $this->privateMessageBanManager->getBannedUsers($this->currentUser->id()); + $threadMembers = $privateMessageThread ? $privateMessageThread->getMemberIds() : []; + $bannedUsers = $this->privateMessageBanManager->getBannedUsers($this->currentUser()->id()); foreach ($bannedUsers as $bannedUser) { if (in_array($bannedUser, $threadMembers)) { @@ -413,7 +297,7 @@ class PrivateMessageForm extends ContentEntityForm { * * Re-render form after submission, so user could write new message. */ - public function ajaxCallback(array $form, FormStateInterface $formState) { + public function ajaxCallback(array $form, FormStateInterface $formState): AjaxResponse { $response = new AjaxResponse(); // Return early if there are any form validation errors. @@ -466,27 +350,27 @@ class PrivateMessageForm extends ContentEntityForm { /** * After build callback for the Private Message Form. */ - public function afterBuild(array $form, FormStateInterface $formState) { - $form['message']['widget'][0]['format']['#attributes']['class'][] = 'hidden'; - return $form; + public function afterBuild(array $element, FormStateInterface $form_state): array { + $element['message']['widget'][0]['format']['#attributes']['class'][] = 'hidden'; + return $element; } /** * {@inheritdoc} */ - public function save(array $form, FormStateInterface $formState) { - $status = parent::save($form, $formState); + public function save(array $form, FormStateInterface $form_state): int { + $status = parent::save($form, $form_state); /** @var \Drupal\private_message\Entity\PrivateMessageThreadInterface $entity */ - $entity = $formState->get('pmt_entity'); + $entity = $form_state->get('pmt_entity'); /** @var \Drupal\private_message\Entity\PrivateMessageThreadInterface $private_message_thread */ - $private_message_thread = $formState->get('thread'); + $private_message_thread = $form_state->get('thread'); if (!$private_message_thread) { // Generate an array containing the members of the thread. $current_user = $this->entityTypeManager ->getStorage('user') - ->load($this->currentUser->id()); + ->load($this->currentUser()->id()); $members = [$current_user]; @@ -511,11 +395,11 @@ class PrivateMessageForm extends ContentEntityForm { $this->privateMessageThreadManager->saveThread($this->entity, $private_message_thread->getMembers(), $private_message_thread); // Save the thread to the form state. - $formState->set('private_message_thread', $private_message_thread); + $form_state->set('private_message_thread', $private_message_thread); // Send the user to the private message page. As this thread is the newest, // it wll be at the top of the list. - $formState->setRedirect('entity.private_message_thread.canonical', ['private_message_thread' => $private_message_thread->id()]); + $form_state->setRedirect('entity.private_message_thread.canonical', ['private_message_thread' => $private_message_thread->id()]); return $status; } diff --git a/src/Form/PrivateMessageThreadClearPersonalHistoryForm.php b/src/Form/PrivateMessageThreadClearPersonalHistoryForm.php index dd874040100663090e9f25307694d8e7ca431608..c141083e5f5ce21e645d11b0c33840f179dd3c76 100644 --- a/src/Form/PrivateMessageThreadClearPersonalHistoryForm.php +++ b/src/Form/PrivateMessageThreadClearPersonalHistoryForm.php @@ -1,9 +1,12 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; use Drupal\Core\Entity\ContentEntityConfirmFormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; /** @@ -16,7 +19,7 @@ class PrivateMessageThreadClearPersonalHistoryForm extends ContentEntityConfirmF /** * {@inheritdoc} */ - public function getQuestion() { + public function getQuestion(): TranslatableMarkup { $members = $this->getEntity()->getMembers(); $member_names = []; foreach ($members as $member) { @@ -31,25 +34,24 @@ class PrivateMessageThreadClearPersonalHistoryForm extends ContentEntityConfirmF /** * {@inheritdoc} */ - public function getCancelUrl() { + public function getCancelUrl(): Url { return Url::fromRoute('entity.private_message_thread.canonical', ['private_message_thread' => $this->getEntity()->id()]); } /** * {@inheritdoc} */ - public function getConfirmText() { + public function getConfirmText(): TranslatableMarkup { return $this->t('Clear history'); } /** * {@inheritdoc} */ - public function submitForm(array &$form, FormStateInterface $form_state) { + public function submitForm(array &$form, FormStateInterface $form_state): void { parent::submitForm($form, $form_state); $this->getEntity()->clearAccountHistory($this->currentUser()); - $form_state->setRedirect('private_message.private_message_page'); } diff --git a/src/Form/PrivateMessageThreadDeleteForm.php b/src/Form/PrivateMessageThreadDeleteForm.php index 897d23d716d3b70bd7ba430a908d900625506d57..1e7ed19f36a2b4c3f474c942226a596d25e75947 100644 --- a/src/Form/PrivateMessageThreadDeleteForm.php +++ b/src/Form/PrivateMessageThreadDeleteForm.php @@ -1,9 +1,12 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Form; use Drupal\Core\Entity\ContentEntityConfirmFormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; /** @@ -16,7 +19,7 @@ class PrivateMessageThreadDeleteForm extends ContentEntityConfirmFormBase { /** * {@inheritdoc} */ - public function getQuestion() { + public function getQuestion(): TranslatableMarkup { $members = $this->getEntity()->getMembers(); $member_names = []; foreach ($members as $member) { @@ -31,25 +34,24 @@ class PrivateMessageThreadDeleteForm extends ContentEntityConfirmFormBase { /** * {@inheritdoc} */ - public function getCancelUrl() { + public function getCancelUrl(): Url { return Url::fromRoute('entity.private_message_thread.canonical', ['private_message_thread' => $this->getEntity()->id()]); } /** * {@inheritdoc} */ - public function getConfirmText() { + public function getConfirmText(): TranslatableMarkup { return $this->t('Delete thread'); } /** * {@inheritdoc} */ - public function submitForm(array &$form, FormStateInterface $form_state) { + public function submitForm(array &$form, FormStateInterface $form_state): void { parent::submitForm($form, $form_state); $this->getEntity()->delete(); - $form_state->setRedirect('private_message.private_message_page'); } diff --git a/src/Mapper/PrivateMessageMapper.php b/src/Mapper/PrivateMessageMapper.php index 3b085b9a17888df44cd7857fcb8599051a944252..24a086c207b45fbb23a3e3ecb1b23b6b94cce944 100644 --- a/src/Mapper/PrivateMessageMapper.php +++ b/src/Mapper/PrivateMessageMapper.php @@ -2,6 +2,8 @@ namespace Drupal\private_message\Mapper; +@trigger_error(__CLASS__ . ' is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. No replacement is provided. See https://www.drupal.org/node/3490530', E_USER_DEPRECATED); + use Drupal\Core\Database\Connection; use Drupal\Core\Database\Query\SelectInterface; use Drupal\Core\Session\AccountProxyInterface; @@ -10,35 +12,18 @@ use Drupal\user\UserInterface; /** * Interface for the Private Message Mapper class. + * + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. No replacement is provided. + * + * @see https://www.drupal.org/node/3490530 */ class PrivateMessageMapper implements PrivateMessageMapperInterface { - /** - * The database connection. - * - * @var \Drupal\Core\Database\Connection - */ - protected Connection $database; - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * Constructs a PrivateMessageMapper object. - * - * @param \Drupal\Core\Database\Connection $database - * The database connection. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - */ - public function __construct(Connection $database, AccountProxyInterface $currentUser) { - $this->database = $database; - $this->currentUser = $currentUser; - } + public function __construct( + protected readonly Connection $database, + protected readonly AccountProxyInterface $currentUser, + ) {} /** * {@inheritdoc} diff --git a/src/Mapper/PrivateMessageMapperInterface.php b/src/Mapper/PrivateMessageMapperInterface.php index 63ddc1cf3400a468588cc29225718573b487aee7..45294330e1c3cda369bc27a4f4e13873144eca4c 100644 --- a/src/Mapper/PrivateMessageMapperInterface.php +++ b/src/Mapper/PrivateMessageMapperInterface.php @@ -2,11 +2,18 @@ namespace Drupal\private_message\Mapper; +@trigger_error(__CLASS__ . ' is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. No replacement is provided. See https://www.drupal.org/node/3490530', E_USER_DEPRECATED); + use Drupal\private_message\Entity\PrivateMessageInterface; use Drupal\user\UserInterface; /** * Interface for the Private Message Thread mapper class. + * + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. No replacement is provided. + * + * @see https://www.drupal.org/node/3490530 */ interface PrivateMessageMapperInterface { diff --git a/src/Model/BlockType.php b/src/Model/BlockType.php new file mode 100644 index 0000000000000000000000000000000000000000..e4abd195ffafc938e84d32ee939298e7fe0e52b6 --- /dev/null +++ b/src/Model/BlockType.php @@ -0,0 +1,28 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\private_message\Model; + +/** + * Blocking type. + */ +enum BlockType: string { + + case Passive = 'passive'; + case Active = 'active'; + + /** + * Returns the enum as options. + * + * @return array + * Options. + */ + public static function asOptions(): array { + return [ + self::Passive->value => t('Passive'), + self::Active->value => t('Active'), + ]; + } + +} diff --git a/src/Plugin/Block/PrivateMessageActionsBlock.php b/src/Plugin/Block/PrivateMessageActionsBlock.php index fb2b0538ba58116b73b37ef1f3c1ace3dc4fe86a..b4f88a208aa6aef685c8c61d5d24c893964b5a3f 100644 --- a/src/Plugin/Block/PrivateMessageActionsBlock.php +++ b/src/Plugin/Block/PrivateMessageActionsBlock.php @@ -1,14 +1,18 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Block; use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\AccessResultInterface; +use Drupal\Core\Block\Attribute\Block; use Drupal\Core\Block\BlockBase; -use Drupal\Core\Config\ConfigFactory; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -16,60 +20,28 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * Provides the private message actions block. * * This block holds links to perform actions on a private message thread. - * - * @Block( - * id = "private_message_actions_block", - * admin_label = @Translation("Private Message Actions"), - * category = @Translation("Private Message"), - * ) */ +#[Block( + id: 'private_message_actions_block', + admin_label: new TranslatableMarkup('Private Message Actions'), + category: new TranslatableMarkup('Private Message'), +)] class PrivateMessageActionsBlock extends BlockBase implements ContainerFactoryPluginInterface { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * Configuration Factory. - * - * @var \Drupal\Core\Config\ConfigFactory - */ - protected ConfigFactory $configFactory; - - /** - * Constructs a PrivateMessageForm object. - * - * @param array $configuration - * The block configuration. - * @param string $plugin_id - * The ID of the plugin. - * @param mixed $plugin_definition - * The plugin definition. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Config\ConfigFactory $configFactory - * The config factory service. - */ public function __construct( array $configuration, $plugin_id, $plugin_definition, - AccountProxyInterface $currentUser, - ConfigFactory $configFactory, + protected readonly AccountProxyInterface $currentUser, + protected readonly ConfigFactoryInterface $configFactory, ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - - $this->currentUser = $currentUser; - $this->configFactory = $configFactory; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): PrivateMessageActionsBlock { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, @@ -90,7 +62,7 @@ class PrivateMessageActionsBlock extends BlockBase implements ContainerFactoryPl /** * {@inheritdoc} */ - public function build() { + public function build(): array { if (!$this->currentUser->hasPermission('use private messaging system')) { return []; } diff --git a/src/Plugin/Block/PrivateMessageInboxBlock.php b/src/Plugin/Block/PrivateMessageInboxBlock.php index c5b582b1d63322f4e7e836c2376b25855f62f23b..5ab73635969d94cea27c7b0ca63a88f3be1f7034 100644 --- a/src/Plugin/Block/PrivateMessageInboxBlock.php +++ b/src/Plugin/Block/PrivateMessageInboxBlock.php @@ -1,113 +1,57 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Block; use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\AccessResultInterface; use Drupal\Core\Access\CsrfTokenGenerator; +use Drupal\Core\Block\Attribute\Block; use Drupal\Core\Block\BlockBase; use Drupal\Core\Block\BlockPluginInterface; use Drupal\Core\Cache\Cache; -use Drupal\Core\Config\Config; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; use Drupal\private_message\Service\PrivateMessageServiceInterface; +use Drupal\private_message\Traits\PrivateMessageSettingsTrait; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides the private message inbox block. - * - * @Block( - * id = "private_message_inbox_block", - * admin_label = @Translation("Private Message Inbox"), - * category = @Translation("Private Message"), - * ) */ +#[Block( + id: 'private_message_inbox_block', + admin_label: new TranslatableMarkup('Private Message Inbox'), + category: new TranslatableMarkup('Private Message'), + )] class PrivateMessageInboxBlock extends BlockBase implements BlockPluginInterface, ContainerFactoryPluginInterface { - /** - * The private message service. - * - * @var \Drupal\private_message\Service\PrivateMessageServiceInterface - */ - protected PrivateMessageServiceInterface $privateMessageService; - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The entity manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected EntityTypeManagerInterface $entityTypeManager; - - /** - * The CSRF token generator service. - * - * @var \Drupal\Core\Access\CsrfTokenGenerator - */ - protected CsrfTokenGenerator $csrfToken; + use PrivateMessageSettingsTrait; - /** - * The private message configuration. - * - * @var \Drupal\Core\Config\Config - */ - protected Config $privateMessageConfig; - - /** - * Constructs a PrivateMessageForm object. - * - * @param array $configuration - * The block configuration. - * @param string $plugin_id - * The ID of the plugin. - * @param mixed $plugin_definition - * The plugin definition. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService - * The private message service. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity manager service. - * @param \Drupal\Core\Access\CsrfTokenGenerator $csrfToken - * The CSRF token generator service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config - * The config service. - */ public function __construct( array $configuration, $plugin_id, $plugin_definition, - AccountProxyInterface $currentUser, - PrivateMessageServiceInterface $privateMessageService, - EntityTypeManagerInterface $entityTypeManager, - CsrfTokenGenerator $csrfToken, - ConfigFactoryInterface $config, + protected readonly AccountProxyInterface $currentUser, + protected readonly PrivateMessageServiceInterface $privateMessageService, + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly CsrfTokenGenerator $csrfToken, + protected readonly ConfigFactoryInterface $configFactory, ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - - $this->currentUser = $currentUser; - $this->privateMessageService = $privateMessageService; - $this->entityTypeManager = $entityTypeManager; - $this->csrfToken = $csrfToken; - $this->privateMessageConfig = $config->get('private_message.settings'); } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): PrivateMessageInboxBlock { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, @@ -146,7 +90,7 @@ class PrivateMessageInboxBlock extends BlockBase implements BlockPluginInterface } $block['#attached']['library'][] = 'private_message/inbox_block_script'; - $style_disabled = $this->privateMessageConfig->get('remove_css'); + $style_disabled = $this->getPrivateMessageSettings()->get('remove_css'); if (!$style_disabled) { $block['#attached']['library'][] = 'private_message/inbox_block_style'; } diff --git a/src/Plugin/Block/PrivateMessageNotificationBlock.php b/src/Plugin/Block/PrivateMessageNotificationBlock.php index 5286dac9f27e6f99eb9c9d86b47b9c657a809376..08a74cb1dec2b4c91936971950cb9d4b10e6fef6 100644 --- a/src/Plugin/Block/PrivateMessageNotificationBlock.php +++ b/src/Plugin/Block/PrivateMessageNotificationBlock.php @@ -1,101 +1,55 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Block; use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\AccessResultInterface; use Drupal\Core\Access\CsrfTokenGenerator; +use Drupal\Core\Block\Attribute\Block; use Drupal\Core\Block\BlockBase; use Drupal\Core\Block\BlockPluginInterface; use Drupal\Core\Cache\Cache; -use Drupal\Core\Config\Config; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; use Drupal\private_message\Service\PrivateMessageServiceInterface; +use Drupal\private_message\Traits\PrivateMessageSettingsTrait; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides the private message notification block. - * - * @Block( - * id = "private_message_notification_block", - * admin_label = @Translation("Private Message Notification"), - * category = @Translation("Private Message"), - * ) */ +#[Block( + id: "private_message_notification_block", + admin_label: new TranslatableMarkup('Private Message Notification'), + category: new TranslatableMarkup('Private Message'), +)] class PrivateMessageNotificationBlock extends BlockBase implements BlockPluginInterface, ContainerFactoryPluginInterface { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The CSRF token generator service. - * - * @var \Drupal\Core\Access\CsrfTokenGenerator - */ - protected CsrfTokenGenerator $csrfToken; + use PrivateMessageSettingsTrait; - /** - * The private message service. - * - * @var \Drupal\private_message\Service\PrivateMessageServiceInterface - */ - protected PrivateMessageServiceInterface $privateMessageService; - - /** - * The private message configuration. - * - * @var \Drupal\Core\Config\Config - */ - protected Config $privateMessageConfig; - - /** - * Constructs a PrivateMessageForm object. - * - * @param array $configuration - * The block configuration. - * @param string $plugin_id - * The ID of the plugin. - * @param mixed $plugin_definition - * The plugin definition. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Access\CsrfTokenGenerator $csrfToken - * The CSRF token generator service. - * @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService - * The private message service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config - * The config service. - */ public function __construct( array $configuration, $plugin_id, $plugin_definition, - AccountProxyInterface $currentUser, - CsrfTokenGenerator $csrfToken, - PrivateMessageServiceInterface $privateMessageService, - ConfigFactoryInterface $config, + protected readonly AccountProxyInterface $currentUser, + protected readonly CsrfTokenGenerator $csrfToken, + protected readonly PrivateMessageServiceInterface $privateMessageService, + protected readonly ConfigFactoryInterface $configFactory, ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - - $this->currentUser = $currentUser; - $this->csrfToken = $csrfToken; - $this->privateMessageService = $privateMessageService; - $this->privateMessageConfig = $config->get('private_message.settings'); } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): PrivateMessageNotificationBlock { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, @@ -148,7 +102,7 @@ class PrivateMessageNotificationBlock extends BlockBase implements BlockPluginIn $block['#attached']['drupalSettings']['privateMessageNotificationBlock']['ajaxRefreshRate'] = $config['ajax_refresh_rate']; $block['#attached']['library'][] = 'private_message/notification_block_script'; - $style_disabled = $this->privateMessageConfig->get('remove_css'); + $style_disabled = $this->getPrivateMessageSettings()->get('remove_css'); if (!$style_disabled) { $block['#attached']['library'][] = 'private_message/notification_block_style'; } @@ -165,7 +119,7 @@ class PrivateMessageNotificationBlock extends BlockBase implements BlockPluginIn /** * {@inheritdoc} */ - public function getCacheTags() { + public function getCacheTags(): array { $tags = [ 'private_message:status:uid:' . $this->currentUser->id(), // This cache tag is @deprecated, since we have added the cache tag above. diff --git a/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMemberFormatter.php b/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMemberFormatter.php index c30079bb32ae2630e41ae49955c298955bcaf784..d65267a5b41303f748acbdbfa9913b6c9bc13a97 100644 --- a/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMemberFormatter.php +++ b/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMemberFormatter.php @@ -1,10 +1,13 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Field\FieldFormatter; use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Entity\EntityDisplayRepositoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Field\Attribute\FieldFormatter; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; @@ -12,76 +15,22 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Render\RendererInterface; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines the private message member field formatter. - * - * @FieldFormatter( - * id = "private_message_thread_member_formatter", - * label = @Translation("Private Message Thread Members"), - * field_types = { - * "entity_reference" - * }, - * ) */ +#[FieldFormatter( + id: 'private_message_thread_member_formatter', + label: new TranslatableMarkup('Private Message Thread Members'), + field_types: [ + 'entity_reference', + ], +)] class PrivateMessageThreadMemberFormatter extends FormatterBase implements ContainerFactoryPluginInterface { - /** - * The entity manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected EntityTypeManagerInterface $entityTypeManager; - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The entity display repository. - * - * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface - */ - protected EntityDisplayRepositoryInterface $entityDisplayRepository; - - /** - * The renderer service. - * - * @var \Drupal\Core\Render\RendererInterface - */ - protected RendererInterface $renderer; - - /** - * Construct a PrivateMessageThreadFormatter object. - * - * @param string $plugin_id - * The ID of the plugin. - * @param mixed $plugin_definition - * The plugin definition. - * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition - * The field definition. - * @param array $settings - * The field settings. - * @param mixed $label - * The label of the field. - * @param string $view_mode - * The current view mode. - * @param array $third_party_settings - * The third party settings. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity manager service. - * @param \Drupal\Core\Session\AccountProxyInterface $current_user - * The current user. - * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository - * The entity display repository. - * @param \Drupal\Core\Render\Renderer $renderer - * The renderer. - */ public function __construct( $plugin_id, $plugin_definition, @@ -90,23 +39,18 @@ class PrivateMessageThreadMemberFormatter extends FormatterBase implements Conta $label, $view_mode, array $third_party_settings, - EntityTypeManagerInterface $entity_type_manager, - AccountProxyInterface $current_user, - EntityDisplayRepositoryInterface $entity_display_repository, - RendererInterface $renderer, + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly AccountProxyInterface $currentUser, + protected readonly EntityDisplayRepositoryInterface $entityDisplayRepository, + protected readonly RendererInterface $renderer, ) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); - - $this->entityTypeManager = $entity_type_manager; - $this->currentUser = $current_user; - $this->entityDisplayRepository = $entity_display_repository; - $this->renderer = $renderer; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): PrivateMessageThreadMemberFormatter { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $plugin_id, $plugin_definition, diff --git a/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMembersNumberFormatter.php b/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMembersNumberFormatter.php index 5f1548bf8eda4cbfc41feee0a36338fc75cfaea2..83aa25cd8ddfca95c318cbe1b96da551333f771c 100644 --- a/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMembersNumberFormatter.php +++ b/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMembersNumberFormatter.php @@ -1,48 +1,49 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Field\FieldFormatter; +use Drupal\Core\Field\Attribute\FieldFormatter; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; /** * Defines the private message member field formatter. - * - * @FieldFormatter( - * id = "private_message_thread_members_number_formatter", - * label = @Translation("Private Message Thread Members Number"), - * field_types = { - * "entity_reference" - * }, - * ) */ +#[FieldFormatter( + id: 'private_message_thread_members_number_formatter', + label: new TranslatableMarkup('Private Message Thread Members Number'), + field_types: [ + 'entity_reference', + ], +)] class PrivateMessageThreadMembersNumberFormatter extends FormatterBase implements ContainerFactoryPluginInterface { /** * {@inheritdoc} */ - public static function isApplicable(FieldDefinitionInterface $field_definition) { + public static function isApplicable(FieldDefinitionInterface $field_definition): bool { return ($field_definition->getFieldStorageDefinition()->getTargetEntityTypeId() == 'private_message_thread' && $field_definition->getFieldStorageDefinition()->getSetting('target_type') == 'user'); } /** * {@inheritdoc} */ - public function settingsSummary() { + public function settingsSummary(): array { $summary = []; - $summary['members_number_suffix'] = $this->t('The members number suffix text: %members_number_suffix. Example: 5 %members_number_suffix', ['%members_number_suffix' => $this->getSetting('members_number_suffix')]); - return $summary; } /** * {@inheritdoc} */ - public static function defaultSettings() { + public static function defaultSettings(): array { return [ 'members_number_suffix' => 'users', ] + parent::defaultSettings(); @@ -51,7 +52,7 @@ class PrivateMessageThreadMembersNumberFormatter extends FormatterBase implement /** * {@inheritdoc} */ - public function settingsForm(array $form, FormStateInterface $form_state) { + public function settingsForm(array $form, FormStateInterface $form_state): array { $element = []; $element['members_number_suffix'] = [ @@ -66,18 +67,15 @@ class PrivateMessageThreadMembersNumberFormatter extends FormatterBase implement /** * {@inheritdoc} */ - public function viewElements(FieldItemListInterface $items, $langcode) { - + public function viewElements(FieldItemListInterface $items, $langcode): array { $users_num = count($items); $suffix = $this->getSetting('members_number_suffix'); - $element = [ + return [ '#prefix' => '<div class="private-message-recipients-number">', '#suffix' => '</div>', '#markup' => "$users_num $suffix", ]; - - return $element; } } diff --git a/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMessageFormatter.php b/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMessageFormatter.php index a80ff7fe5aba8206ba324e2b028c9ecef5fc7668..ad44e31127311c3ceb12c44c527c5d6cd453f656 100644 --- a/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMessageFormatter.php +++ b/src/Plugin/Field/FieldFormatter/PrivateMessageThreadMessageFormatter.php @@ -1,97 +1,39 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Field\FieldFormatter; use Drupal\Core\Access\CsrfTokenGenerator; -use Drupal\Core\Config\Config; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityDisplayRepositoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Field\Attribute\FieldFormatter; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; +use Drupal\private_message\Traits\PrivateMessageSettingsTrait; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines the private message thread message field formatter. - * - * @FieldFormatter( - * id = "private_message_thread_message_formatter", - * label = @Translation("Private Message Messages"), - * field_types = { - * "entity_reference" - * } - * ) */ +#[FieldFormatter( + id: 'private_message_thread_message_formatter', + label: new TranslatableMarkup('Private Message Messages'), + field_types: [ + 'entity_reference', + ], +)] class PrivateMessageThreadMessageFormatter extends FormatterBase implements ContainerFactoryPluginInterface { - /** - * The entity manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected EntityTypeManagerInterface $entityTypeManager; - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The CSRF token generator. - * - * @var \Drupal\Core\Access\CsrfTokenGenerator - */ - protected CsrfTokenGenerator $csrfTokenGenerator; - - /** - * The configuration factory. - * - * @var \Drupal\Core\Config\Config - */ - protected Config $config; - - /** - * The entity display repository. - * - * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface - */ - protected EntityDisplayRepositoryInterface $entityDisplayRepository; + use PrivateMessageSettingsTrait; - /** - * Construct a PrivateMessageThreadFormatter object. - * - * @param string $plugin_id - * The ID of the plugin. - * @param mixed $plugin_definition - * The plugin definition. - * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition - * The field definition. - * @param array $settings - * The field settings. - * @param mixed $label - * The label of the field. - * @param string $view_mode - * The current view mode. - * @param array $third_party_settings - * The third party settings. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity manager service. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Access\CsrfTokenGenerator $csrfTokenGenerator - * The CSRF token generator. - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * The configuration factory. - * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository - * The entity display repository. - */ public function __construct( $plugin_id, $plugin_definition, @@ -100,25 +42,19 @@ class PrivateMessageThreadMessageFormatter extends FormatterBase implements Cont $label, $view_mode, array $third_party_settings, - EntityTypeManagerInterface $entityTypeManager, - AccountProxyInterface $currentUser, - CsrfTokenGenerator $csrfTokenGenerator, - ConfigFactoryInterface $configFactory, - EntityDisplayRepositoryInterface $entity_display_repository, + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly AccountProxyInterface $currentUser, + protected readonly CsrfTokenGenerator $csrfTokenGenerator, + protected readonly ConfigFactoryInterface $configFactory, + protected readonly EntityDisplayRepositoryInterface $entityDisplayRepository, ) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); - - $this->entityTypeManager = $entityTypeManager; - $this->currentUser = $currentUser; - $this->csrfTokenGenerator = $csrfTokenGenerator; - $this->config = $configFactory->get('private_message.settings'); - $this->entityDisplayRepository = $entity_display_repository; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): PrivateMessageThreadMessageFormatter { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $plugin_id, $plugin_definition, @@ -139,7 +75,7 @@ class PrivateMessageThreadMessageFormatter extends FormatterBase implements Cont * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition): bool { - return ($field_definition->getFieldStorageDefinition()->getTargetEntityTypeId() == 'private_message_thread' && $field_definition->getFieldStorageDefinition()->getSetting('target_type') == 'private_message'); + return $field_definition->getFieldStorageDefinition()->getTargetEntityTypeId() === 'private_message_thread' && $field_definition->getFieldStorageDefinition()->getSetting('target_type') === 'private_message'; } /** @@ -236,7 +172,7 @@ class PrivateMessageThreadMessageFormatter extends FormatterBase implements Cont $element['view_mode'] = [ '#type' => 'select', '#title' => $this->t('Private Message view mode'), - '#options' => $this->entityDisplayRepository->getViewModeOptions('private_message', TRUE), + '#options' => $this->entityDisplayRepository->getViewModeOptions('private_message'), '#default_value' => $this->getSetting('view_mode'), ]; @@ -303,7 +239,7 @@ class PrivateMessageThreadMessageFormatter extends FormatterBase implements Cont ]; $element['#attached']['library'][] = 'private_message/private_message_thread_script'; - $style_disabled = $this->config->get('remove_css'); + $style_disabled = $this->getPrivateMessageSettings()->get('remove_css'); if (!$style_disabled) { $element['#attached']['library'][] = 'private_message/private_message_thread_style'; } @@ -316,10 +252,10 @@ class PrivateMessageThreadMessageFormatter extends FormatterBase implements Cont * * @param string $type * The type of string being translated. - * @param string $value + * @param string|null $value * The value to be translated. * - * @return mixed + * @return \Drupal\Core\StringTranslation\TranslatableMarkup|string|null * - If a translated value exists for the given type/value combination, a * \Drupal\Core\StringTranslation\TranslatableMarkup object containing the * translated value is returned. @@ -327,7 +263,7 @@ class PrivateMessageThreadMessageFormatter extends FormatterBase implements Cont * a string is returned. * - If the type does not exist, the untranslated value is returned. */ - private function translateKey($type, $value) { + private function translateKey(string $type, ?string $value): TranslatableMarkup|string|null { if ($type == 'order') { $keys = [ 'asc' => $this->t('Ascending'), diff --git a/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php b/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php index 6eb05932346c0742d3fca3dda24c473526674e05..c429729e4bba968232ea631d097e3a947d55c7cd 100644 --- a/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php +++ b/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace Drupal\private_message\Plugin\Field\FieldWidget; use Drupal\Component\Utility\NestedArray; -use Drupal\Core\Config\Config; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\Attribute\FieldWidget; @@ -15,6 +14,7 @@ use Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\private_message\Traits\PrivateMessageSettingsTrait; use Drupal\user\UserInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RequestStack; @@ -31,12 +31,7 @@ use Symfony\Component\HttpFoundation\RequestStack; )] class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget implements ContainerFactoryPluginInterface { - /** - * The configuration factory. - * - * @var \Drupal\Core\Config\Config - */ - protected Config $config; + use PrivateMessageSettingsTrait; public function __construct( string $plugin_id, @@ -44,19 +39,17 @@ class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, - protected RequestStack $requestStack, - protected EntityTypeManagerInterface $entityTypeManager, - ConfigFactoryInterface $config_factory, + protected readonly RequestStack $requestStack, + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly ConfigFactoryInterface $configFactory, ) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); - - $this->config = $config_factory->get('private_message.settings'); } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): PrivateMessageThreadMemberWidget { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $plugin_id, $plugin_definition, @@ -97,7 +90,6 @@ class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget $summary = parent::settingsSummary(); unset($summary[0]); - $summary[] = $this->t('Maximum thread members: @count', ['@count' => $this->getSetting('max_members')]); return $summary; @@ -143,7 +135,7 @@ class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget $element['target_id']['#default_value'] = $recipient; } - if ($recipient && $this->config->get('hide_recipient_field_when_prefilled')) { + if ($recipient && $this->getPrivateMessageSettings()->get('hide_recipient_field_when_prefilled')) { $maxMembers = 1; } @@ -192,8 +184,8 @@ class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget /** * {@inheritdoc} */ - public function massageFormValues(array $values, array $form, FormStateInterface $form_state) { - return $values['target_id']; + public function massageFormValues(array $values, array $form, FormStateInterface $form_state): array { + return $values['target_id'] ?? []; } } diff --git a/src/Plugin/Menu/PrivateMessageTab.php b/src/Plugin/Menu/PrivateMessageTab.php index b56b992409364fb9670c8b45f88f09097fba6e6f..56fa56075afb58986bdbee57c265f4385d67ad02 100644 --- a/src/Plugin/Menu/PrivateMessageTab.php +++ b/src/Plugin/Menu/PrivateMessageTab.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Menu; use Drupal\Core\Menu\LocalTaskDefault; diff --git a/src/Plugin/PrivateMessageConfigForm/PrivateMessageConfigFormBase.php b/src/Plugin/PrivateMessageConfigForm/PrivateMessageConfigFormBase.php index 986c7a3b0c92698a66ad0a06c46fe02f6cd34385..99b7ab0a49d7b5d176e1a7b284cb59aef35d6023 100644 --- a/src/Plugin/PrivateMessageConfigForm/PrivateMessageConfigFormBase.php +++ b/src/Plugin/PrivateMessageConfigForm/PrivateMessageConfigFormBase.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\PrivateMessageConfigForm; use Drupal\Core\Config\ConfigFactoryInterface; @@ -12,40 +14,19 @@ use Symfony\Component\DependencyInjection\ContainerInterface; */ abstract class PrivateMessageConfigFormBase extends PluginBase implements PrivateMessageConfigFormPluginInterface { - /** - * The private message config form plugin manager. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected ConfigFactoryInterface $configFactory; - - /** - * Constructs a PrivateMessageForm object. - * - * @param array $configuration - * The plugin configuration. - * @param string $plugin_id - * The plugin ID. - * @param mixed $plugin_definition - * The plugin definitions. - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * The configuration factory service. - */ public function __construct( array $configuration, - $plugin_id, - $plugin_definition, - ConfigFactoryInterface $configFactory, + string $plugin_id, + mixed $plugin_definition, + protected ConfigFactoryInterface $configFactory, ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - - $this->configFactory = $configFactory; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, @@ -57,14 +38,14 @@ abstract class PrivateMessageConfigFormBase extends PluginBase implements Privat /** * {@inheritdoc} */ - public function getName() { + public function getName(): string { return $this->pluginDefinition['name']; } /** * {@inheritdoc} */ - public function getId() { + public function getId(): string { return $this->pluginDefinition['id']; } diff --git a/src/Plugin/PrivateMessageConfigForm/PrivateMessageConfigFormPluginInterface.php b/src/Plugin/PrivateMessageConfigForm/PrivateMessageConfigFormPluginInterface.php index 26d2e91ae640b8db44dd1763669d1acbeed6fdc0..2bb8271637155016046fc251d8c18f9802c4db9d 100644 --- a/src/Plugin/PrivateMessageConfigForm/PrivateMessageConfigFormPluginInterface.php +++ b/src/Plugin/PrivateMessageConfigForm/PrivateMessageConfigFormPluginInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\PrivateMessageConfigForm; use Drupal\Component\Plugin\PluginInspectionInterface; @@ -17,7 +19,7 @@ interface PrivateMessageConfigFormPluginInterface extends PluginInspectionInterf * @return string * The name of the plugin. */ - public function getName(); + public function getName(): string; /** * Return the id of the crm tester plugin. @@ -25,7 +27,7 @@ interface PrivateMessageConfigFormPluginInterface extends PluginInspectionInterf * @return string * The id of the plugin. */ - public function getId(); + public function getId(): string; /** * Build the section of the form as it will appear on the settings page. @@ -36,7 +38,7 @@ interface PrivateMessageConfigFormPluginInterface extends PluginInspectionInterf * @return array * A render array containing the form elements this plugin provides. */ - public function buildForm(FormStateInterface $formState); + public function buildForm(FormStateInterface $formState): array; /** * Validate this section of the form. diff --git a/src/Plugin/RulesAction/SendPrivateMessage.php b/src/Plugin/RulesAction/SendPrivateMessage.php index 5d6eb982a42617e007866c61bd175007fc272854..d5a6accb886c81c78214626b4b811b8a825379f6 100644 --- a/src/Plugin/RulesAction/SendPrivateMessage.php +++ b/src/Plugin/RulesAction/SendPrivateMessage.php @@ -1,52 +1,65 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\RulesAction; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\private_message\Entity\PrivateMessage; +use Drupal\private_message\Service\PrivateMessageServiceInterface; +use Drupal\rules\Context\ContextDefinition; +use Drupal\rules\Core\Attribute\RulesAction; use Drupal\rules\Core\RulesActionBase; use Drupal\user\UserInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides "Send private message" rules action. - * - * @RulesAction( - * id = "private_message_send_message", - * label = @Translation("Send private message"), - * category = @Translation("System"), - * context_definitions = { - * "author" = @ContextDefinition("entity:user", - * label = @Translation("From"), - * description = @Translation("The author of the message.") - * ), - * "recipient" = @ContextDefinition("entity:user", - * label = @Translation("To"), - * description = @Translation("The recipient of the message.") - * ), - * "message" = @ContextDefinition("string", - * label = @Translation("Message"), - * description = @Translation("The message.") - * ), - * } - * ) */ +#[RulesAction( + id: 'private_message_send_message', + label: new TranslatableMarkup('Send private message'), + category: new TranslatableMarkup('System'), + context_definitions: [ + 'author' => new ContextDefinition( + data_type: 'entity:user', + label: new TranslatableMarkup('From'), + description: new TranslatableMarkup('The author of the message.') + ), + 'recipient' => new ContextDefinition( + data_type: 'entity:user', + label: new TranslatableMarkup('To'), + description: new TranslatableMarkup('The recipient of the message.') + ), + 'message' => new ContextDefinition( + data_type: 'string', + label: new TranslatableMarkup('Message'), + description: new TranslatableMarkup('The message.') + ), + ], +)] class SendPrivateMessage extends RulesActionBase implements ContainerFactoryPluginInterface { - /** - * The Private Message service. - * - * @var \Drupal\private_message\Service\PrivateMessageService - */ - protected $privateMessageService; + public function __construct( + array $configuration, + $plugin_id, + $plugin_definition, + protected readonly PrivateMessageServiceInterface $privateMessageService, + ) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - $instance = new static($configuration, $plugin_id, $plugin_definition); - $instance->privateMessageService = $container->get('private_message.service'); - return $instance; + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('private_message.service'), + ); } /** @@ -59,7 +72,7 @@ class SendPrivateMessage extends RulesActionBase implements ContainerFactoryPlug * @param string $message * The text of the message. */ - protected function doExecute(UserInterface $author, UserInterface $recipient, $message) { + protected function doExecute(UserInterface $author, UserInterface $recipient, string $message): void { $members = [$author, $recipient]; // Create a thread if one does not exist. $private_message_thread = $this->privateMessageService->getThreadForMembers($members); diff --git a/src/Plugin/Validation/Constraint/PrivateMessageThreadMemberConstraint.php b/src/Plugin/Validation/Constraint/PrivateMessageThreadMemberConstraint.php index 9415a0d3caa812214bd78f472cce569ba03fc98c..753c6d5ab021edfb6fc441b7ca766d885ff2363b 100644 --- a/src/Plugin/Validation/Constraint/PrivateMessageThreadMemberConstraint.php +++ b/src/Plugin/Validation/Constraint/PrivateMessageThreadMemberConstraint.php @@ -1,18 +1,22 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Validation\Constraint; -use Symfony\Component\Validator\Constraint; +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\Core\Validation\Attribute\Constraint; +use Symfony\Component\Validator\Constraint as SymfonyConstraint; /** * Checks that members of the thread have permission to use private messages. - * - * @Constraint( - * id = "private_message_thread_member", - * label = @Translation("Private Message Thread Member", context = "Validation"), - * ) */ -class PrivateMessageThreadMemberConstraint extends Constraint { +#[Constraint( + id: 'private_message_thread_member', + label: new TranslatableMarkup('Private Message Thread Member', [], ['context' => 'Validation']), +)] +class PrivateMessageThreadMemberConstraint extends SymfonyConstraint { + /** * Constraint violation error. * diff --git a/src/Plugin/Validation/Constraint/PrivateMessageThreadMemberConstraintValidator.php b/src/Plugin/Validation/Constraint/PrivateMessageThreadMemberConstraintValidator.php index 2099fa51aedb20707be472421c10866877c6c3a5..bf751e7649cbffedb256e091ceecd061566e9680 100644 --- a/src/Plugin/Validation/Constraint/PrivateMessageThreadMemberConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/PrivateMessageThreadMemberConstraintValidator.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Validation\Constraint; use Symfony\Component\Validator\Constraint; @@ -16,8 +18,8 @@ class PrivateMessageThreadMemberConstraintValidator extends ConstraintValidator /** * {@inheritdoc} */ - public function validate($items, Constraint $constraint) { - $users = $items->referencedEntities(); + public function validate($value, Constraint $constraint): void { + $users = $value->referencedEntities(); foreach ($users as $user) { if (!$user->hasPermission('use private messaging system')) { $this->context->addViolation($constraint->userPrivateMessagePermissionError, ['%user' => $user->getDisplayName()]); diff --git a/src/Plugin/Validation/Constraint/UniqueBanConstraint.php b/src/Plugin/Validation/Constraint/UniqueBanConstraint.php index 787f6d2ed1ad1acb5db2bf32d947c88e1a63e835..07c7672c850bfaec182b3f10fa17097e747c2450 100644 --- a/src/Plugin/Validation/Constraint/UniqueBanConstraint.php +++ b/src/Plugin/Validation/Constraint/UniqueBanConstraint.php @@ -1,18 +1,22 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Validation\Constraint; -use Symfony\Component\Validator\Constraint; +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\Core\Validation\Attribute\Constraint; +use Symfony\Component\Validator\Constraint as SymfonyConstraint; /** * Validation constraint for unique bans. - * - * @Constraint( - * id = "UniquePrivateMessageBan", - * label = @Translation("Unique ban.", context = "Validation"), - * ) */ -class UniqueBanConstraint extends Constraint { +#[Constraint( + id: 'UniquePrivateMessageBan', + label: new TranslatableMarkup('Unique ban', [], ['context' => 'Validation']), +)] + +class UniqueBanConstraint extends SymfonyConstraint { /** * The default violation message. diff --git a/src/Plugin/Validation/Constraint/UniqueBanConstraintValidator.php b/src/Plugin/Validation/Constraint/UniqueBanConstraintValidator.php index f816342a281d79b818ac5a516e96548a8b34fdfd..77e697d711d6893701ae343672188dc3536b8cd4 100644 --- a/src/Plugin/Validation/Constraint/UniqueBanConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/UniqueBanConstraintValidator.php @@ -1,11 +1,13 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\Validation\Constraint; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\private_message\Entity\PrivateMessageBan; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -14,47 +16,27 @@ use Symfony\Component\Validator\ConstraintValidator; */ class UniqueBanConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface { - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; + use AutowireTrait; - /** - * Creates a new UniqueBanConstraintValidator instance. - * - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity type manager. - */ - public function __construct(EntityTypeManagerInterface $entity_type_manager) { - $this->entityTypeManager = $entity_type_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity_type.manager') - ); - } + public function __construct( + protected readonly EntityTypeManagerInterface $entityTypeManager, + ) {} /** * {@inheritdoc} */ - public function validate($entity, Constraint $constraint) { - assert($entity instanceof PrivateMessageBan); + public function validate($value, Constraint $constraint): void { + assert($value instanceof PrivateMessageBan); $storage = $this->entityTypeManager->getStorage('private_message_ban'); $query = $storage->getQuery() ->accessCheck(FALSE) - ->condition('owner', $entity->getOwnerId(), '=') - ->condition('target', $entity->getTargetId(), '='); + ->condition('owner', $value->getOwnerId(), '=') + ->condition('target', $value->getTargetId(), '='); if ($query->range(0, 1)->execute()) { $this->context->buildViolation($constraint->message, [ - '%user' => $entity->getTarget()->getDisplayName(), + '%user' => $value->getTarget()->getDisplayName(), ])->addViolation(); } } diff --git a/src/Plugin/views/field/PrivateMessageThreadHasNewMessage.php b/src/Plugin/views/field/PrivateMessageThreadHasNewMessage.php index fa50fc4ae68f46f23d09b9148de138afe5f7601d..b771adda96c426581134b7b6dcbc2fbba09afbe0 100644 --- a/src/Plugin/views/field/PrivateMessageThreadHasNewMessage.php +++ b/src/Plugin/views/field/PrivateMessageThreadHasNewMessage.php @@ -1,9 +1,13 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\views\field; +use Drupal\Component\Render\MarkupInterface; use Drupal\Core\Session\AccountInterface; -use Drupal\private_message\Mapper\PrivateMessageMapperInterface; +use Drupal\private_message\Service\PrivateMessageServiceInterface; +use Drupal\views\Attribute\ViewsField; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\ResultRow; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -12,68 +16,48 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * Outputs thread new messages count. * * @ingroup views_field_handlers - * - * @ViewsField("private_message_thread_has_new_message_marker") */ +#[ViewsField("private_message_thread_has_new_message_marker")] class PrivateMessageThreadHasNewMessage extends FieldPluginBase { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $currentUser; - - /** - * The private message mapper service. - * - * @var \Drupal\private_message\Mapper\PrivateMessageMapperInterface - */ - protected PrivateMessageMapperInterface $mapper; - - /** - * Creates an instance of PrivateMessageThreadHasNewMessage. - */ public function __construct( array $configuration, $plugin_id, $plugin_definition, - AccountInterface $current_user, - PrivateMessageMapperInterface $mapper, + protected readonly AccountInterface $currentUser, + protected readonly PrivateMessageServiceInterface $privateMessageService, ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->currentUser = $current_user; - $this->mapper = $mapper; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('current_user'), - $container->get('private_message.mapper') + $container->get('private_message.service') ); } /** * {@inheritdoc} */ - public function query() { + public function query(): void { // Disable query. } /** * {@inheritdoc} */ - public function render(ResultRow $values) { + public function render(ResultRow $values): MarkupInterface { /** @var \Drupal\private_message\Entity\PrivateMessageThread $thread */ $thread = $this->getEntity($values); - return $this->mapper->getThreadUnreadMessageCount($this->currentUser->id(), $thread->id()) > 0 ? + return $this->privateMessageService->getThreadUnreadMessageCount($this->currentUser->id(), $thread->id()) > 0 ? $this->t('New message!') : $this->t('No new messages'); } diff --git a/src/Plugin/views/field/PrivateMessageThreadMessagesCount.php b/src/Plugin/views/field/PrivateMessageThreadMessagesCount.php index 6cd318a53fdc24b10bdc933ae856abcb5af75c83..e9d9dc80658930f6efdbb131cf6081ba346797d6 100644 --- a/src/Plugin/views/field/PrivateMessageThreadMessagesCount.php +++ b/src/Plugin/views/field/PrivateMessageThreadMessagesCount.php @@ -1,8 +1,11 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\views\field; use Drupal\Core\Session\AccountInterface; +use Drupal\views\Attribute\ViewsField; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\ResultRow; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -11,40 +14,23 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * Outputs thread messages count. * * @ingroup views_field_handlers - * - * @ViewsField("private_message_thread_all_messages_number") */ +#[ViewsField("private_message_thread_all_messages_number")] class PrivateMessageThreadMessagesCount extends FieldPluginBase { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $currentUser; - - /** - * Constructs a PrivateMessageThreadMessagesCount object. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin_id for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\Core\Session\AccountInterface $current_user - * The current user. - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, AccountInterface $current_user) { + public function __construct( + array $configuration, + $plugin_id, + $plugin_definition, + protected readonly AccountInterface $currentUser, + ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - - $this->currentUser = $current_user; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, @@ -56,18 +42,17 @@ class PrivateMessageThreadMessagesCount extends FieldPluginBase { /** * {@inheritdoc} */ - public function query() { + public function query(): void { // Leave empty to avoid a query on this field. } /** * {@inheritdoc} */ - public function render(ResultRow $values) { + public function render(ResultRow $values): string { /** @var \Drupal\private_message\Entity\PrivateMessageThread $thread */ $thread = $this->getEntity($values); - - return count($thread->filterUserDeletedMessages($this->currentUser)); + return (string) count($thread->filterUserDeletedMessages($this->currentUser)); } } diff --git a/src/Plugin/views/field/PrivateMessageThreadNewMessagesCount.php b/src/Plugin/views/field/PrivateMessageThreadNewMessagesCount.php index f2ca43d8739b61345775ac2dae3cbbc033655f20..dfd8cb77caabdfe90336a92e4b26a4777e178ae0 100644 --- a/src/Plugin/views/field/PrivateMessageThreadNewMessagesCount.php +++ b/src/Plugin/views/field/PrivateMessageThreadNewMessagesCount.php @@ -1,9 +1,12 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\views\field; use Drupal\Core\Session\AccountInterface; -use Drupal\private_message\Mapper\PrivateMessageMapperInterface; +use Drupal\private_message\Service\PrivateMessageServiceInterface; +use Drupal\views\Attribute\ViewsField; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\ResultRow; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -12,69 +15,49 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * Outputs thread new messages count. * * @ingroup views_field_handlers - * - * @ViewsField("private_message_thread_new_messages_count") */ +#[ViewsField("private_message_thread_new_messages_count")] class PrivateMessageThreadNewMessagesCount extends FieldPluginBase { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $currentUser; - - /** - * The private message mapper service. - * - * @var \Drupal\private_message\Mapper\PrivateMessageMapperInterface - */ - protected PrivateMessageMapperInterface $mapper; - - /** - * Creates an instance of PrivateMessageThreadNewMessagesCount. - */ public function __construct( array $configuration, $plugin_id, $plugin_definition, - AccountInterface $current_user, - PrivateMessageMapperInterface $mapper, + protected readonly AccountInterface $currentUser, + protected readonly PrivateMessageServiceInterface $privateMessageService, ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->currentUser = $current_user; - $this->mapper = $mapper; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('current_user'), - $container->get('private_message.mapper') + $container->get('private_message.service') ); } /** * {@inheritdoc} */ - public function query() { + public function query(): void { // Disable query. } /** * {@inheritdoc} */ - public function render(ResultRow $values) { + public function render(ResultRow $values): string { /** @var \Drupal\private_message\Entity\PrivateMessageThread $thread */ $thread = $this->getEntity($values); // @todo Optimize this, consider deletions and banned users. - return $this->mapper->getThreadUnreadMessageCount($this->currentUser->id(), $thread->id()); + return (string) $this->privateMessageService->getThreadUnreadMessageCount($this->currentUser->id(), $thread->id()); } } diff --git a/src/Plugin/views/filter/PrivateMessageThreadCleanHistory.php b/src/Plugin/views/filter/PrivateMessageThreadCleanHistory.php index 5f87cc68917d77f72c8b47375bf35bf089145f7d..f17b4d3c0243b44dfaff97421ff982aaba9deded 100644 --- a/src/Plugin/views/filter/PrivateMessageThreadCleanHistory.php +++ b/src/Plugin/views/filter/PrivateMessageThreadCleanHistory.php @@ -1,8 +1,11 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\views\filter; use Drupal\Core\Session\AccountInterface; +use Drupal\views\Attribute\ViewsFilter; use Drupal\views\Plugin\ViewsHandlerManager; use Drupal\views\Plugin\views\filter\FilterPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -11,44 +14,24 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * Filters threads by the fact they are not cleared. * * @ingroup views_filter_handlers - * - * @ViewsFilter("private_message_thread_has_history") */ +#[ViewsFilter('private_message_thread_has_history')] class PrivateMessageThreadCleanHistory extends FilterPluginBase { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $currentUser; - - /** - * Views Handler Plugin Manager. - * - * @var \Drupal\views\Plugin\ViewsHandlerManager - */ - protected $joinHandler; - - /** - * Creates an instance of PrivateMessageThreadCleanHistory. - */ public function __construct( array $configuration, $plugin_id, $plugin_definition, - AccountInterface $current_user, - ViewsHandlerManager $join_handler, + protected readonly AccountInterface $currentUser, + protected readonly ViewsHandlerManager $joinHandler, ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->currentUser = $current_user; - $this->joinHandler = $join_handler; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, @@ -63,7 +46,7 @@ class PrivateMessageThreadCleanHistory extends FilterPluginBase { * * No filtering takes place if the user doesn't select any options. */ - public function query() { + public function query(): void { $current_user_id = $this->currentUser->id(); $definition = [ @@ -87,12 +70,14 @@ class PrivateMessageThreadCleanHistory extends FilterPluginBase { /** * {@inheritdoc} */ - public function adminSummary() {} + public function adminSummary(): \Stringable|string { + return ''; + } /** * {@inheritdoc} */ - public function canExpose() { + public function canExpose(): bool { return FALSE; } diff --git a/src/Plugin/views/filter/PrivateMessageThreadIsUnread.php b/src/Plugin/views/filter/PrivateMessageThreadIsUnread.php index f05dd22f7e2cf11764862f7c98925315e4d94f7e..d37d3c3990aa49d121f2af829e31cc4044ba49ab 100644 --- a/src/Plugin/views/filter/PrivateMessageThreadIsUnread.php +++ b/src/Plugin/views/filter/PrivateMessageThreadIsUnread.php @@ -1,8 +1,12 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Plugin\views\filter; +use Drupal\Component\Render\MarkupInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\views\Attribute\ViewsFilter; use Drupal\views\Plugin\ViewsHandlerManager; use Drupal\views\Plugin\views\filter\FilterPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -11,44 +15,24 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * Filters threads by the fact they are unread. * * @ingroup views_filter_handlers - * - * @ViewsFilter("private_message_thread_is_unread") */ +#[ViewsFilter('private_message_thread_is_unread')] class PrivateMessageThreadIsUnread extends FilterPluginBase { - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $currentUser; - - /** - * Views Handler Plugin Manager. - * - * @var \Drupal\views\Plugin\ViewsHandlerManager - */ - protected $joinHandler; - - /** - * Creates an instance of PrivateMessageThreadCleanHistory. - */ public function __construct( array $configuration, $plugin_id, $plugin_definition, - AccountInterface $current_user, - ViewsHandlerManager $join_handler, + protected readonly AccountInterface $currentUser, + protected readonly ViewsHandlerManager $joinHandler, ) { parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->currentUser = $current_user; - $this->joinHandler = $join_handler; } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self { return new static( $configuration, $plugin_id, @@ -61,7 +45,7 @@ class PrivateMessageThreadIsUnread extends FilterPluginBase { /** * Override the views query. */ - public function query() { + public function query(): void { $current_user_id = $this->currentUser->id(); $definition = [ @@ -85,12 +69,14 @@ class PrivateMessageThreadIsUnread extends FilterPluginBase { /** * {@inheritdoc} */ - public function adminSummary() {} + public function adminSummary(): MarkupInterface|string { + return ''; + } /** * {@inheritdoc} */ - public function canExpose() { + public function canExpose(): bool { return FALSE; } diff --git a/src/PluginManager/PrivateMessageConfigFormManager.php b/src/PluginManager/PrivateMessageConfigFormManager.php index 8c93ed9e5d468f2d132ea9fe874ae6747b943124..aa4a5cb6565b0316fdec2c77c9c7938d3142d80a 100644 --- a/src/PluginManager/PrivateMessageConfigFormManager.php +++ b/src/PluginManager/PrivateMessageConfigFormManager.php @@ -1,29 +1,34 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\PluginManager; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\DefaultPluginManager; +use Drupal\private_message\Annotation\PrivateMessageConfigForm as PrivateMessageConfigFormAnnotation; +use Drupal\private_message\Attribute\PrivateMessageConfigForm as PrivateMessageConfigFormAttribute; +use Drupal\private_message\Plugin\PrivateMessageConfigForm\PrivateMessageConfigFormPluginInterface; /** - * Plugin Manager to detect PrivateMessageConfigForm plugins. + * Plugin manager for detect PrivateMessageConfigForm plugins. */ class PrivateMessageConfigFormManager extends DefaultPluginManager implements PrivateMessageConfigFormManagerInterface { - /** - * Constructs a PrivateMessageConfigFormManager object. - * - * @param \Traversable $namespaces - * Namespaces to be searched for the plugin. - * @param \Drupal\Core\Cache\CacheBackendInterface $cacheBackend - * The cache backend. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler - * The module handler service. - */ - public function __construct(\Traversable $namespaces, CacheBackendInterface $cacheBackend, ModuleHandlerInterface $moduleHandler) { - parent::__construct('Plugin/PrivateMessageConfigForm', $namespaces, $moduleHandler, 'Drupal\private_message\Plugin\PrivateMessageConfigForm\PrivateMessageConfigFormPluginInterface', 'Drupal\private_message\Annotation\PrivateMessageConfigForm'); - + public function __construct( + \Traversable $namespaces, + CacheBackendInterface $cacheBackend, + ModuleHandlerInterface $moduleHandler, + ) { + parent::__construct( + 'Plugin/PrivateMessageConfigForm', + $namespaces, + $moduleHandler, + PrivateMessageConfigFormPluginInterface::class, + PrivateMessageConfigFormAttribute::class, + PrivateMessageConfigFormAnnotation::class, + ); $this->alterInfo('private_message_config_form_info'); $this->setCacheBackend($cacheBackend, 'private_message_config_form'); } diff --git a/src/PluginManager/PrivateMessageConfigFormManagerInterface.php b/src/PluginManager/PrivateMessageConfigFormManagerInterface.php index 6c79a74ffc15743b6f0150275b08d3ed53c8f9a8..7ac5d621e1cc395600ca887c4ddbd764ff9a779c 100644 --- a/src/PluginManager/PrivateMessageConfigFormManagerInterface.php +++ b/src/PluginManager/PrivateMessageConfigFormManagerInterface.php @@ -1,8 +1,12 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\PluginManager; +use Drupal\Component\Plugin\PluginManagerInterface; + /** * Plugin Manager to detect PrivateMessageConfigForm plugins. */ -interface PrivateMessageConfigFormManagerInterface {} +interface PrivateMessageConfigFormManagerInterface extends PluginManagerInterface {} diff --git a/src/Service/PrivateMessageBanManager.php b/src/Service/PrivateMessageBanManager.php index 589a379f3c0383664d0800c1c595cd21a9648215..8fefd94459fe12e13b2345c1a4d664cdf1400708 100644 --- a/src/Service/PrivateMessageBanManager.php +++ b/src/Service/PrivateMessageBanManager.php @@ -1,10 +1,11 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Service; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\private_message\Entity\PrivateMessageBanInterface; @@ -16,62 +17,16 @@ class PrivateMessageBanManager implements PrivateMessageBanManagerInterface { use StringTranslationTrait; - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * The database. - * - * @var \Drupal\Core\Database\Connection - */ - private Connection $database; - - /** - * The messenger service. - * - * @var \Drupal\Core\Messenger\MessengerInterface - */ - private MessengerInterface $messenger; - - /** - * Constructs a PrivateMessageBanManager object. - * - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager interface. - * @param \Drupal\Core\Database\Connection $database - * The database. - * @param \Drupal\Core\Messenger\MessengerInterface $messenger - * The messenger service. - */ public function __construct( - AccountProxyInterface $currentUser, - EntityTypeManagerInterface $entityTypeManager, - Connection $database, - MessengerInterface $messenger, - ) { - $this->currentUser = $currentUser; - $this->entityTypeManager = $entityTypeManager; - $this->database = $database; - $this->messenger = $messenger; - } + protected readonly AccountProxyInterface $currentUser, + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly Connection $database, + ) {} /** * {@inheritdoc} */ - public function isBanned(int $user_id): bool { + public function isBanned(int|string $user_id): bool { $select = $this ->database ->select('private_message_ban', 'pmb'); @@ -88,6 +43,8 @@ class PrivateMessageBanManager implements PrivateMessageBanManagerInterface { * {@inheritdoc} */ public function isCurrentUserBannedByUser(int $user_id): bool { + @trigger_error(__METHOD__ . '() is deprecated in private_message:4.0.0 and is removed from private_message:5.0.0. No replacement is provided. See https://www.drupal.org/node/3490530', E_USER_DEPRECATED); + $select = $this ->database ->select('private_message_ban', 'pmb'); @@ -103,7 +60,7 @@ class PrivateMessageBanManager implements PrivateMessageBanManagerInterface { /** * {@inheritdoc} */ - public function getBannedUsers(int $user_id): array { + public function getBannedUsers(int|string $user_id): array { return $this ->database ->select('private_message_ban', 'pmb') @@ -116,8 +73,8 @@ class PrivateMessageBanManager implements PrivateMessageBanManagerInterface { /** * {@inheritdoc} */ - public function unbanUser(int $user_id) { - $ban = $this->findBanEntity($this->currentUser->id(), $user_id); + public function unbanUser(int|string $user_id): void { + $ban = $this->findBanEntity((int) $this->currentUser->id(), (int) $user_id); if (!$ban) { // The user is not banned; just return. return; @@ -130,8 +87,8 @@ class PrivateMessageBanManager implements PrivateMessageBanManagerInterface { /** * {@inheritdoc} */ - public function banUser(int $user_id) { - $ban = $this->findBanEntity($this->currentUser->id(), $user_id); + public function banUser(int|string $user_id): void { + $ban = $this->findBanEntity((int) $this->currentUser->id(), (int) $user_id); if ($ban) { // The user is already banned; just return. return; @@ -169,7 +126,9 @@ class PrivateMessageBanManager implements PrivateMessageBanManagerInterface { // reset() returns the first element of the array or FALSE if the array is // empty, but we want the return value to be NULL if the array is empty. - return reset($bans) ?: NULL; + $ban = reset($bans) ?: NULL; + assert($ban === NULL || $ban instanceof PrivateMessageBanInterface); + return $ban; } } diff --git a/src/Service/PrivateMessageBanManagerInterface.php b/src/Service/PrivateMessageBanManagerInterface.php index 8d230708435eb20c24d639e88519660b5af51b77..92d5ad867d3921a33719061fa75838f2281dbd89 100644 --- a/src/Service/PrivateMessageBanManagerInterface.php +++ b/src/Service/PrivateMessageBanManagerInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Service; /** @@ -10,13 +12,13 @@ interface PrivateMessageBanManagerInterface { /** * Check if the user is banned by the current user. * - * @param int $user_id + * @param int|string $user_id * ID of the target user to test. * * @return bool * TRUE if the given user is banned by the current user. FALSE otherwise. */ - public function isBanned(int $user_id): bool; + public function isBanned(int|string $user_id): bool; /** * Checks if the current user is banned by the user. @@ -26,34 +28,39 @@ interface PrivateMessageBanManagerInterface { * * @return bool * TRUE if the current user is banned by the given user. FALSE otherwise. + * + * @deprecated in private_message:4.0.0 and is removed from + * private_message:5.0.0. No replacement is provided. + * + * @see https://www.drupal.org/node/3490530 */ public function isCurrentUserBannedByUser(int $user_id): bool; /** * Returns list of users banned by a user with given ID. * - * @param int $user_id + * @param int|string $user_id * ID of the user to test. * * @return array * An array of user ids that the user has banned. */ - public function getBannedUsers(int $user_id): array; + public function getBannedUsers(int|string $user_id): array; /** * Adds a user to the current user's banned users list. * - * @param int $user_id + * @param int|string $user_id * ID of the user to ban. */ - public function banUser(int $user_id); + public function banUser(int|string $user_id): void; /** * Removes a banned user from their banned users list. * - * @param int $user_id + * @param int|string $user_id * ID of the user to unban. */ - public function unbanUser(int $user_id); + public function unbanUser(int|string $user_id): void; } diff --git a/src/Service/PrivateMessageService.php b/src/Service/PrivateMessageService.php index ce0464c915dcd3245ab5fd74654f738cadf48153..7316e0632804f34773b7bc6ae08152d88cf0b950 100644 --- a/src/Service/PrivateMessageService.php +++ b/src/Service/PrivateMessageService.php @@ -1,10 +1,14 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Service; use Drupal\Component\Datetime\TimeInterface; use Drupal\Core\Cache\CacheTagsInvalidatorInterface; use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Database\Connection; +use Drupal\Core\Database\Query\SelectInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; @@ -12,105 +16,45 @@ use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\Url; use Drupal\private_message\Entity\PrivateMessageInterface; use Drupal\private_message\Entity\PrivateMessageThreadInterface; -use Drupal\private_message\Mapper\PrivateMessageMapperInterface; use Drupal\user\UserDataInterface; use Drupal\user\UserInterface; /** - * The Private Message service for the private message module. + * The private message service for the private message module. + * + * @todo This service refactoring is postponed to #3489224. To be implemented: + * - Replacement of direct calls to database with entity API calls and + * removing the $database class property + * - Strict typing with respect to BC. + * @see https://www.drupal.org/project/private_message/issues/3489224 */ class PrivateMessageService implements PrivateMessageServiceInterface { /** - * The private message mapper service. - * - * @var \Drupal\private_message\Mapper\PrivateMessageMapperInterface - */ - protected PrivateMessageMapperInterface $mapper; - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected AccountProxyInterface $currentUser; - - /** - * The configuration factory. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected ConfigFactoryInterface $configFactory; - - /** - * The user data service. - * - * @var \Drupal\user\UserDataInterface - */ - protected UserDataInterface $userData; - - /** - * Cache Tags Invalidator. - * - * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface - */ - protected CacheTagsInvalidatorInterface $cacheTagsInvalidator; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface + * The machine name of the private message module. */ - protected $entityTypeManager; + private const MODULE_KEY = 'private_message'; /** - * The time service. - * - * @var \Drupal\Component\Datetime\TimeInterface + * The timestamp at which unread private messages were marked as read. */ - protected TimeInterface $time; + private const LAST_CHECK_KEY = 'last_notification_check_timestamp'; - /** - * Constructs a PrivateMessageService object. - * - * @param \Drupal\private_message\Mapper\PrivateMessageMapperInterface $mapper - * The private message mapper service. - * @param \Drupal\Core\Session\AccountProxyInterface $currentUser - * The current user. - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * The configuration factory. - * @param \Drupal\user\UserDataInterface $userData - * The user data service. - * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cacheTagsInvalidator - * The cache tags invalidator interface. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager interface. - * @param \Drupal\Component\Datetime\TimeInterface $time - * The time service. - */ public function __construct( - PrivateMessageMapperInterface $mapper, - AccountProxyInterface $currentUser, - ConfigFactoryInterface $configFactory, - UserDataInterface $userData, - CacheTagsInvalidatorInterface $cacheTagsInvalidator, - EntityTypeManagerInterface $entityTypeManager, - TimeInterface $time, - ) { - $this->mapper = $mapper; - $this->currentUser = $currentUser; - $this->configFactory = $configFactory; - $this->userData = $userData; - $this->cacheTagsInvalidator = $cacheTagsInvalidator; - $this->entityTypeManager = $entityTypeManager; - $this->time = $time; - } + protected readonly AccountProxyInterface $currentUser, + protected readonly ConfigFactoryInterface $configFactory, + protected readonly UserDataInterface $userData, + protected readonly CacheTagsInvalidatorInterface $cacheTagsInvalidator, + protected readonly EntityTypeManagerInterface $entityTypeManager, + protected readonly TimeInterface $time, + protected readonly Connection $database, + ) {} /** * {@inheritdoc} */ - public function getThreadForMembers(array $members) { - $thread_id = $this->mapper->getThreadIdForMembers($members); + public function getThreadForMembers(array $members): PrivateMessageThreadInterface { + $thread_id = $this->getThreadIdForMembers($members); if ($thread_id) { return $this->entityTypeManager @@ -124,8 +68,8 @@ class PrivateMessageService implements PrivateMessageServiceInterface { /** * {@inheritdoc} */ - public function getFirstThreadForUser(UserInterface $user) { - $thread_id = $this->mapper->getFirstThreadIdForUser($user); + public function getFirstThreadForUser(UserInterface $user): PrivateMessageThreadInterface|false { + $thread_id = $this->getFirstThreadIdForUser($user); if ($thread_id) { return $this->entityTypeManager ->getStorage('private_message_thread') @@ -138,7 +82,13 @@ class PrivateMessageService implements PrivateMessageServiceInterface { /** * {@inheritdoc} */ - public function getThreadsForUser($count, $timestamp = FALSE) { + public function getThreadsForUser(int $count, /* ?int */$timestamp = NULL): array { + if ($timestamp === FALSE) { + // @deprecated + @trigger_error('Passing FALSE to second argument of ' . __METHOD__ . '() is deprecated in private_message:4.0.0 and removed from private_message:5.0.0. Pass NULL instead. See https://www.drupal.org/node/3490530', E_USER_DEPRECATED); + $timestamp = NULL; + } + $return = [ 'threads' => [], 'next_exists' => FALSE, @@ -147,7 +97,7 @@ class PrivateMessageService implements PrivateMessageServiceInterface { $user = $this->entityTypeManager ->getStorage('user') ->load($this->currentUser->id()); - $thread_ids = $this->mapper->getThreadIdsForUser($user, $count, $timestamp); + $thread_ids = $this->getThreadIdsForUser($user, $count, $timestamp); if (count($thread_ids)) { $threads = $this->entityTypeManager ->getStorage('private_message_thread') @@ -155,7 +105,7 @@ class PrivateMessageService implements PrivateMessageServiceInterface { if (count($threads)) { $last_thread = end($threads); $last_timestamp = $last_thread->get('updated')->value; - $return['next_exists'] = $this->mapper->checkForNextThread($user, $last_timestamp); + $return['next_exists'] = $this->checkForNextThread($user, $last_timestamp); $return['threads'] = $threads; } } @@ -166,11 +116,11 @@ class PrivateMessageService implements PrivateMessageServiceInterface { /** * {@inheritdoc} */ - public function getCountThreadsForUser() { + public function getCountThreadsForUser(): int { $user = $this->entityTypeManager ->getStorage('user') ->load($this->currentUser->id()); - $thread_ids = $this->mapper->getThreadIdsForUser($user); + $thread_ids = $this->getThreadIdsForUser($user); return count($thread_ids); } @@ -255,7 +205,7 @@ class PrivateMessageService implements PrivateMessageServiceInterface { * {@inheritdoc} */ public function getUpdatedInboxThreads(array $existingThreadInfo, $count = FALSE) { - $thread_info = $this->mapper->getUpdatedInboxThreadIds(array_keys($existingThreadInfo), $count); + $thread_info = $this->getUpdatedInboxThreadIds(array_keys($existingThreadInfo), $count); $new_threads = []; $thread_ids = []; $ids_to_load = []; @@ -286,7 +236,7 @@ class PrivateMessageService implements PrivateMessageServiceInterface { $last_check_timestamp = $this->userData->get(self::MODULE_KEY, $uid, self::LAST_CHECK_KEY); $last_check_timestamp = is_numeric($last_check_timestamp) ? $last_check_timestamp : 0; - return (int) $this->mapper->getUnreadThreadCount($uid, $last_check_timestamp); + return (int) $this->getUnreadThreadCountHelper($uid, $last_check_timestamp); } /** @@ -297,7 +247,7 @@ class PrivateMessageService implements PrivateMessageServiceInterface { $last_check_timestamp = $this->userData->get(self::MODULE_KEY, $uid, self::LAST_CHECK_KEY); $last_check_timestamp = is_numeric($last_check_timestamp) ? $last_check_timestamp : 0; - return (int) $this->mapper->getUnreadMessageCount($uid, $last_check_timestamp); + return (int) $this->getUnreadMessageCountHelper($uid, $last_check_timestamp); } /** @@ -324,7 +274,7 @@ class PrivateMessageService implements PrivateMessageServiceInterface { * {@inheritdoc} */ public function getThreadFromMessage(PrivateMessageInterface $privateMessage) { - $thread_id = $this->mapper->getThreadIdFromMessage($privateMessage); + $thread_id = $this->getThreadIdFromMessage($privateMessage); if ($thread_id) { return $this->entityTypeManager ->getStorage('private_message_thread') @@ -349,7 +299,7 @@ class PrivateMessageService implements PrivateMessageServiceInterface { if ($current_user->isAuthenticated()) { if ($current_user->hasPermission('use private messaging system') && $current_user->id() != $author->id()) { $members = [$current_user, $author]; - $thread_id = $this->mapper->getThreadIdForMembers($members); + $thread_id = $this->getThreadIdForMembers($members); if ($thread_id) { $url = Url::fromRoute('entity.private_message_thread.canonical', ['private_message_thread' => $thread_id], ['attributes' => ['class' => ['private_message_link']]]); $build['private_message_link'] = [ @@ -389,7 +339,32 @@ class PrivateMessageService implements PrivateMessageServiceInterface { * {@inheritdoc} */ public function getThreadIds() { - return $this->mapper->getThreadIds(); + return $this->database->select('private_message_threads', 'pmt') + ->fields('pmt', ['id']) + ->execute() + ->fetchCol(); + } + + /** + * {@inheritdoc} + */ + public function getThreadUnreadMessageCount($uid, $thread_id) { + // @todo Optimize this, consider deletions and banned users. + $query = $this->database->select('pm_thread_history', 'pm_thread_history') + ->condition('uid', $uid) + ->condition('thread_id', $thread_id); + $query->join( + 'private_message_thread__private_messages', + 'thread_message', + 'thread_message.entity_id = pm_thread_history.thread_id' + ); + $query->join( + 'private_messages', + 'messages_data', + 'messages_data.id = thread_message.private_messages_target_id' + ); + $query->where('[messages_data].[created] > [pm_thread_history].[access_timestamp]'); + return $query->countQuery()->execute()->fetchField(); } /** @@ -415,4 +390,325 @@ class PrivateMessageService implements PrivateMessageServiceInterface { return $thread; } + /** + * Retrieves the ID of a thread from the database given a list of members. + * + * @param \Drupal\user\UserInterface[] $members + * A list of users, members of a given thread. + * + * @return int|false + * The thread ID, if a thread is found, or FALSE. + */ + protected function getThreadIdForMembers(array $members) { + $uids = array_map(fn(UserInterface $user) => (int) $user->id(), $members); + + // Select threads common for the given members. + $query = $this->database->select('private_message_thread__members', 'pmt') + ->fields('pmt', ['entity_id']) + ->groupBy('entity_id'); + // Add conditions where the threads are in the set of threads for each of + // the users. + foreach ($uids as $uid) { + $subQuery = $this->database->select('private_message_thread__members', 'pmt') + ->fields('pmt', ['entity_id']) + ->condition('members_target_id', $uid); + $query->condition('entity_id', $subQuery, 'IN'); + } + $thread_ids = $query->execute()->fetchCol(); + + // Exclude threads with other participants. + foreach ($thread_ids as $thread_id) { + $query = $this->database->select('private_message_thread__members', 'pmt') + ->condition('members_target_id', $uids, 'NOT IN') + ->condition('entity_id', $thread_id); + if ($query->countQuery()->execute()->fetchField() == 0) { + return (int) $thread_id; + } + } + + return FALSE; + } + + /** + * Retrieves the ID of the most recently updated thread for the given user. + * + * @param \Drupal\user\UserInterface $user + * The user whose most recently updated thread should be retrieved. + * + * @return int|false + * The ID of the most recently updated thread where the user is a member, or + * FALSE if one doesn't exist. + */ + protected function getFirstThreadIdForUser(UserInterface $user) { + $bannedThreadsQuery = $this->getBannedThreads($user->id()); + + $query = $this->database->select('private_message_threads', 'thread'); + $query->addField('thread', 'id'); + $query->innerJoin('pm_thread_history', 'thread_history', 'thread_history.thread_id = thread.id AND thread_history.uid = :uid', [':uid' => $user->id()]); + $query->innerJoin('private_message_thread__members', 'thread_member', 'thread_member.entity_id = thread.id AND thread_member.members_target_id = :uid', [':uid' => $user->id()]); + $query->innerJoin('private_message_thread__private_messages', 'thread_messages', 'thread_messages.entity_id = thread.id'); + $query->innerJoin('private_messages', 'messages', 'messages.id = thread_messages.private_messages_target_id AND thread_history.delete_timestamp <= messages.created'); + $query->condition('thread.id', $bannedThreadsQuery, 'NOT IN'); + $query->orderBy('thread.updated', 'desc'); + $query->range(0, 1); + $return = $query->execute()->fetchField(); + + return $return !== FALSE ? (int) $return : FALSE; + } + + /** + * Retrieves a list of thread IDs for threads the user belongs to. + * + * @param \Drupal\user\UserInterface $user + * The user whose most recently thread IDs should be retrieved. + * @param mixed $count + * The number of thread IDs to retrieve or FALSE to retrieve them all. + * @param int $timestamp + * A timestamp relative to which only thread IDs with an earlier timestamp + * should be returned. + * + * @return array + * An array of thread IDs if any threads exist. + */ + protected function getThreadIdsForUser(UserInterface $user, $count = FALSE, $timestamp = FALSE): array { + $bannedThreadsQuery = $this->getBannedThreads($user->id()); + + $query = $this->database->select('private_message_threads', 'thread'); + $query->addField('thread', 'id'); + $query->addExpression('MAX(thread.updated)', 'last_updated'); + $query->innerJoin('pm_thread_history', 'thread_history', 'thread_history.thread_id = thread.id AND thread_history.uid = :uid', [':uid' => $user->id()]); + $query->innerJoin('private_message_thread__members', 'thread_member', 'thread_member.entity_id = thread.id AND thread_member.members_target_id = :uid', [':uid' => $user->id()]); + $query->innerJoin('private_message_thread__private_messages', 'thread_messages', 'thread_messages.entity_id = thread.id'); + $query->innerJoin('private_messages', 'messages', 'messages.id = thread_messages.private_messages_target_id AND thread_history.delete_timestamp <= messages.created'); + + $query->condition('thread.id', $bannedThreadsQuery, 'NOT IN'); + + if ($timestamp) { + $query->condition('updated', $timestamp, '<'); + } + + $query->groupBy('thread.id'); + $query->orderBy('last_updated', 'desc'); + $query->orderBy('thread.id'); + + if ($count > 0) { + $query->range(0, $count); + } + + return $query->execute()->fetchCol(); + } + + /** + * Checks if a thread exists after with an ID greater than a given thread ID. + * + * @param \Drupal\user\UserInterface $user + * The user for whom to check. + * @param int $timestamp + * The timestamp to check against. + * + * @return bool + * TRUE if a previous thread exists, FALSE if one doesn't. + */ + protected function checkForNextThread(UserInterface $user, $timestamp): bool { + $query = 'SELECT DISTINCT(thread.id) ' . + 'FROM {private_message_threads} AS thread ' . + 'JOIN {pm_thread_history} pm_thread_history ' . + 'ON pm_thread_history.thread_id = thread.id AND pm_thread_history.uid = :history_uid ' . + 'JOIN {private_message_thread__members} AS thread_member ' . + 'ON thread_member.entity_id = thread.id AND thread_member.members_target_id = :uid ' . + 'JOIN {private_message_thread__private_messages} AS thread_messages ' . + 'ON thread_messages.entity_id = thread.id ' . + 'JOIN {private_messages} AS messages ' . + 'ON messages.id = thread_messages.private_messages_target_id ' . + 'WHERE pm_thread_history.delete_timestamp <= messages.created ' . + 'AND thread.updated < :timestamp'; + $vars = [ + ':uid' => $user->id(), + ':history_uid' => $user->id(), + ':timestamp' => $timestamp, + ]; + + return (bool) $this->database->queryRange( + $query, + 0, 1, + $vars + )->fetchField(); + } + + /** + * Retrieves a list of recently updated private message thread IDs. + * + * The last updated timestamp will also be returned. If any ids are provided + * in $existingThreadIds, the IDs of all threads that have been updated since + * the oldest updated timestamp for the given thread IDs will be returned. + * Otherwise the number of IDs returned will be the number provided for + * $count. + * + * @param array $existingThreadIds + * An array of thread IDs to be compared against. + * @param int $count + * The number of threads to return if no existing thread IDs were provided. + * + * @return array + * An array, keyed by thread ID, with each element of the array containing + * an object with the following two properties: + * - id: The thread ID + * - updated: The timestamp at which the thread was last updated + */ + protected function getUpdatedInboxThreadIds(array $existingThreadIds, $count = FALSE): array { + $bannedThreadsQuery = $this->getBannedThreads($this->currentUser->id()); + + $query = $this->database->select('private_message_threads', 'thread'); + $query->addField('thread', 'id'); + $query->addField('thread', 'updated'); + $query->innerJoin('pm_thread_history', 'thread_history', 'thread_history.thread_id = thread.id AND thread_history.uid = :uid', [':uid' => $this->currentUser->id()]); + $query->innerJoin('private_message_thread__members', 'thread_member', 'thread_member.entity_id = thread.id AND thread_member.members_target_id = :uid', [':uid' => $this->currentUser->id()]); + $query->innerJoin('private_message_thread__private_messages', 'thread_messages', 'thread_messages.entity_id = thread.id'); + $query->innerJoin('private_messages', 'messages', 'messages.id = thread_messages.private_messages_target_id AND thread_history.delete_timestamp <= messages.created'); + $query->condition('thread.id', $bannedThreadsQuery, 'NOT IN'); + $query->orderBy('thread.updated', 'desc'); + $query->groupBy('thread.id'); + + if (count($existingThreadIds)) { + $subquery = $this->database->select('private_message_threads', 'thread'); + $subquery->addExpression('MIN(updated)'); + $subquery->condition('id', $existingThreadIds, 'IN'); + + $query->condition('thread.updated', $subquery, '>='); + } + else { + $query->range(0, $count); + } + + return $query->execute()->fetchAllAssoc('id'); + } + + /** + * Gets the current user's unread thread count. + * + * Retrieves the number of the current user's threads that have been updated + * since the last time this number was checked. + * + * @param int $uid + * The user ID of the user whose count should be retrieved. + * @param int $lastCheckTimestamp + * A UNIX timestamp indicating the time after which to check. + * + * @return int + * The number of threads updated since the given timestamp + */ + protected function getUnreadThreadCountHelper($uid, $lastCheckTimestamp) { + $bannedThreadsQuery = $this->getBannedThreads($uid); + + $query = $this->database->select('private_messages', 'message'); + $query->addField('thread', 'id'); + $query->innerJoin('private_message_thread__private_messages', 'thread_message', 'message.id = thread_message.private_messages_target_id'); + $query->innerJoin('private_message_threads', 'thread', 'thread_message.entity_id = thread.id'); + $query->innerJoin('pm_thread_history', 'thread_history', 'thread_history.thread_id = thread.id AND thread_history.access_timestamp < thread.updated AND thread_history.uid = :uid', [':uid' => $uid]); + $query->innerJoin('private_message_thread__members', 'thread_member', 'thread_member.entity_id = thread.id AND thread_member.members_target_id = :uid', [':uid' => $uid]); + $query->condition('thread.updated', $lastCheckTimestamp, '>'); + $query->condition('message.created', $lastCheckTimestamp, '>'); + $query->condition('message.owner', $uid, '<>'); + $query->condition('thread.id', $bannedThreadsQuery, 'NOT IN'); + $query->groupBy('thread.id'); + + return $query->countQuery()->execute()->fetchField(); + } + + /** + * Gets the current user's unread message count. + * + * Retrieves the number of the current user's messages that have been updated + * since the last time this number was checked. + * + * @param int $uid + * The user ID of the user whose count should be retrieved. + * @param int $lastCheckTimestamp + * A UNIX timestamp indicating the time after which to check. + * + * @return int + * The number of threads updated since the given timestamp + */ + protected function getUnreadMessageCountHelper($uid, $lastCheckTimestamp) { + $query = $this->database->select('private_messages', 'message'); + $query->join( + 'private_message_thread__private_messages', + 'thread_message', + 'message.id = thread_message.private_messages_target_id' + ); + $query->join( + 'private_message_threads', + 'thread', + 'thread_message.entity_id = thread.id' + ); + $query->join( + 'pm_thread_history', + 'thread_history', + 'thread_history.thread_id = thread.id AND thread_history.uid = :uid', + [':uid' => $uid] + ); + $query->join( + 'private_message_thread__members', + 'thread_member', + 'thread_member.entity_id = thread.id AND thread_member.members_target_id = :uid', + [':uid' => $uid] + ); + $query + ->condition('thread.updated ', $lastCheckTimestamp, '>') + ->condition('message.created', $lastCheckTimestamp, '>') + ->condition('message.owner', $uid, '<>') + ->where('thread_history.access_timestamp < thread.updated'); + $query = $query->countQuery(); + return $query->execute()->fetchField(); + } + + /** + * Loads the thread id of the thread that a private message belongs to. + * + * @param \Drupal\private_message\Entity\PrivateMessageInterface $privateMessage + * The private message for which the thread ID of the thread it belongs to + * should be returned. + * + * @return int + * The private message thread ID of the thread to which the private message + * belongs. + */ + protected function getThreadIdFromMessage(PrivateMessageInterface $privateMessage) { + $query = $this->database->select('private_message_threads', 'thread'); + $query->fields('thread', ['id']); + $query->join('private_message_thread__private_messages', + 'messages', + 'messages.entity_id = thread.id AND messages.private_messages_target_id = :message_id', + [':message_id' => $privateMessage->id()] + ); + return $query + ->range(0, 1) + ->execute() + ->fetchField(); + } + + /** + * Returns query object of banned threads for the user. + * + * @param int|string $user_id + * The user id. + * + * @return \Drupal\Core\Database\Query\SelectInterface + * The select query object. + */ + protected function getBannedThreads(int|string $user_id): SelectInterface { + // Get the list of banned users for this user. + $subquery = $this->database->select('private_message_ban', 'pmb'); + $subquery->addField('pmb', 'target'); + $subquery->condition('pmb.owner', $user_id); + + // Get list of threads with banned users. + $bannedThreadsQuery = $this->database->select('private_message_thread__members', 'thread_member'); + $bannedThreadsQuery->addField('thread_member', 'entity_id'); + $bannedThreadsQuery->condition('thread_member.members_target_id', $subquery, 'IN'); + $bannedThreadsQuery->groupBy('entity_id'); + + return $bannedThreadsQuery; + } + } diff --git a/src/Service/PrivateMessageServiceInterface.php b/src/Service/PrivateMessageServiceInterface.php index 785c410882bec89fc83b462beb48f339c12dce9c..6aa63562f144c3c52a87925145e155e60f9bff1e 100644 --- a/src/Service/PrivateMessageServiceInterface.php +++ b/src/Service/PrivateMessageServiceInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Service; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; @@ -9,70 +11,65 @@ use Drupal\private_message\Entity\PrivateMessageThreadInterface; use Drupal\user\UserInterface; /** - * The interface for the Private Message Service. + * The interface for the private message service. + * + * @todo This service refactoring is postponed to #3489224. To be implemented: + * - Replacement of direct calls to database with entity API calls and + * removing the $database class property + * - Strict typing with respect to BC. + * @see https://www.drupal.org/project/private_message/issues/3489224 */ interface PrivateMessageServiceInterface { - /** - * The machine name of the private message module. - */ - const MODULE_KEY = 'private_message'; - - /** - * The timestamp at which unread private messages were marked as read. - */ - const LAST_CHECK_KEY = 'last_notification_check_timestamp'; - /** * Retrieves the private message thread for the given members. * * If no thread exists, one will be created. * * @param \Drupal\user\UserInterface[] $members - * An array of User objects for whom the private message - * thread should be retrieved. + * List of users for whom the private message thread should be retrieved. * - * @return \Drupal\private_message\Entity\PrivateMessageThread + * @return \Drupal\private_message\Entity\PrivateMessageThreadInterface * A private message thread that contains all members in the thread. */ - public function getThreadForMembers(array $members); + public function getThreadForMembers(array $members): PrivateMessageThreadInterface; /** - * Get the most recently updated thread for the given user. + * Returns the most recently updated thread for the given user. * * @param \Drupal\user\UserInterface $user * The user whose most recently updated thread should be retrieved. + * + * @return \Drupal\private_message\Entity\PrivateMessageThreadInterface|false + * The most recently updated thread for the given user or FALSE. */ - public function getFirstThreadForUser(UserInterface $user); + public function getFirstThreadForUser(UserInterface $user): PrivateMessageThreadInterface|false; /** - * Retrieve private message threads for a given user. + * Retrieves private message threads for a given user. * * @param int $count * The number of threads to retrieve. - * @param int $timestamp - * A timestamp relative to which only threads with an earlier timestamp - * should be returned. + * @param int|null $timestamp + * Only threads with an earlier timestamp should be returned. * - * @return array + * @return array{threads: array<int, PrivateMessageThreadInterface>, next_exists: bool} * An array with two keys: - * - threads: an array of - * \Drupal\private_message\Entity\PrivateMessageThread - * - next_exists: a boolean indicating whether any more private message - * threads exist after the last one + * - threads: Array of private message threads keyed by their ID. + * - next_exists: Whether more threads exist after the last one. */ - public function getThreadsForUser($count, $timestamp = FALSE); + public function getThreadsForUser(int $count, /* ?int */$timestamp = NULL): array; /** - * Retrieve the number of threads a user has. + * Retrieves the number of threads a user has. * * @return int * The number of threads a user has. */ - public function getCountThreadsForUser(); + public function getCountThreadsForUser(): int; /** - * Retrieve a users private messages created after the given ID. + * Retrieves a users private messages created after the given ID. * * @param int $threadId * The ID of the thread from which messages should be retrieved. @@ -191,4 +188,20 @@ interface PrivateMessageServiceInterface { */ public function getThreadIds(); + /** + * Get the current user's unread message count by thread id. + * + * Retrieves the number of the current user's messages that have been updated + * since user last thread access. + * + * @param int $uid + * The user ID of the user whose count should be retrieved. + * @param int $thread_id + * The thread ID which messages should be checked. + * + * @return int + * The number of threads updated since the given timestamp + */ + public function getThreadUnreadMessageCount($uid, $thread_id); + } diff --git a/src/Service/PrivateMessageThreadManager.php b/src/Service/PrivateMessageThreadManager.php index 5ae691cc0acb9ab1f646bcf2700400bdafa14a49..74409d2ec2b446dabbfe75a2119abad8038d117f 100644 --- a/src/Service/PrivateMessageThreadManager.php +++ b/src/Service/PrivateMessageThreadManager.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Service; use Drupal\private_message\Entity\PrivateMessageInterface; @@ -7,87 +9,24 @@ use Drupal\private_message\Entity\PrivateMessageThreadInterface; /** * The Private Message generator class. - * - * @package Drupal\private_message\Service */ class PrivateMessageThreadManager implements PrivateMessageThreadManagerInterface { - /** - * The private message service. - * - * @var \Drupal\private_message\Service\PrivateMessageServiceInterface - */ - private PrivateMessageServiceInterface $privateMessageService; - - /** - * The private message. - * - * @var \Drupal\private_message\Entity\PrivateMessageInterface|null - */ - private ?PrivateMessageInterface $message; - - /** - * The message recipients. - * - * @var \Drupal\Core\Session\AccountInterface[] - */ - private array $recipients = []; - - /** - * The private message thread. - * - * @var \Drupal\private_message\Entity\PrivateMessageThreadInterface|null - */ - private ?PrivateMessageThreadInterface $thread; - - /** - * PrivateMessageThreadManager constructor. - * - * @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService - * The private message service. - */ public function __construct( - PrivateMessageServiceInterface $privateMessageService, - ) { - $this->privateMessageService = $privateMessageService; - } + protected readonly PrivateMessageServiceInterface $privateMessageService, + ) {} /** * {@inheritdoc} */ - public function saveThread(PrivateMessageInterface $message, array $recipients = [], ?PrivateMessageThreadInterface $thread = NULL): void { - $this->message = $message; - $this->thread = $thread; - $this->recipients = $recipients; - - $this->getThread()->addMessage(); - } - - /** - * If no thread is defined, load one from the thread members. - * - * @return $this - */ - private function getThread(): PrivateMessageThreadManagerInterface { - if (is_null($this->thread)) { - $this->thread = $this->privateMessageService->getThreadForMembers($this->recipients); + public function saveThread(PrivateMessageInterface $message, array $members = [], ?PrivateMessageThreadInterface $thread = NULL): void { + if ($thread === NULL && $members) { + $thread = $this->privateMessageService->getThreadForMembers($members); } - return $this; - } - - /** - * Add the new message to the thread. - * - * @return $this - */ - private function addMessage(): PrivateMessageThreadManagerInterface { - if ($this->thread) { - $this->thread->addMessage($this->message); - $this->thread->save(); + if ($thread instanceof PrivateMessageThreadInterface) { + $thread->addMessage($message)->save(); } - - return $this; } } diff --git a/src/Service/PrivateMessageThreadManagerInterface.php b/src/Service/PrivateMessageThreadManagerInterface.php index 07f7e720bce05727559419f7e98510975bbd6851..a2c882bb93409ca2c724cade7396b90b64baf70d 100644 --- a/src/Service/PrivateMessageThreadManagerInterface.php +++ b/src/Service/PrivateMessageThreadManagerInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Drupal\private_message\Service; use Drupal\private_message\Entity\PrivateMessageInterface; @@ -7,8 +9,6 @@ use Drupal\private_message\Entity\PrivateMessageThreadInterface; /** * Handles the generation/update of private messages, threads, and metadata. - * - * @package Drupal\private_message\Service */ interface PrivateMessageThreadManagerInterface { @@ -19,12 +19,12 @@ interface PrivateMessageThreadManagerInterface { * * @param \Drupal\private_message\Entity\PrivateMessageInterface $message * The new message object. - * @param array $recipients - * (optional) An array of message recipients. Defaults to an empty array. + * @param array $members + * (optional) An array of thread members. Defaults to an empty array. * @param \Drupal\private_message\Entity\PrivateMessageThreadInterface|null $thread * (optional) The private message thread. If NULL, one will be loaded - * using the recipients array. + * using the members array. */ - public function saveThread(PrivateMessageInterface $message, array $recipients = [], ?PrivateMessageThreadInterface $thread = NULL); + public function saveThread(PrivateMessageInterface $message, array $members = [], ?PrivateMessageThreadInterface $thread = NULL); } diff --git a/src/Service/PrivateMessageUninstaller.php b/src/Service/PrivateMessageUninstaller.php index cd1043597b7c487034e2b0ba78ef89574b985f3e..2b4d1c4988379593d768b4764108249c8675d19c 100644 --- a/src/Service/PrivateMessageUninstaller.php +++ b/src/Service/PrivateMessageUninstaller.php @@ -110,7 +110,7 @@ class PrivateMessageUninstaller implements PrivateMessageUninstallerInterface { * Thread id. */ public static function deleteThread(int $threadId): void { - /** @var \Drupal\private_message\Entity\PrivateMessageThreadInterface $thread */ + /** @var \Drupal\private_message\Entity\PrivateMessageThreadInterface|null $thread */ $thread = \Drupal::entityTypeManager() ->getStorage('private_message_thread') ->load($threadId); diff --git a/src/Traits/PrivateMessageSettingsTrait.php b/src/Traits/PrivateMessageSettingsTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..4201c2f0f52df36726b3ba26cc34a0abbc1f72ed --- /dev/null +++ b/src/Traits/PrivateMessageSettingsTrait.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\private_message\Traits; + +use Drupal\Core\Config\ImmutableConfig; + +/** + * Private Message module settings. + */ +trait PrivateMessageSettingsTrait { + + /** + * Static cache of Private Message module settings. + */ + protected ImmutableConfig $privateMessageSettings; + + /** + * Returns the private message module settings. + * + * @return \Drupal\Core\Config\ImmutableConfig + * The private message module settings. + */ + protected function getPrivateMessageSettings(): ImmutableConfig { + assert(property_exists($this, 'configFactory')); + if (!isset($this->privateMessageSettings)) { + $this->privateMessageSettings = $this->configFactory->get('private_message.settings'); + } + return $this->privateMessageSettings; + } + +} diff --git a/tests/modules/private_message_test/private_message_test.info.yml b/tests/modules/private_message_test/private_message_test.info.yml index 6c0acfadcdec506e3808d61b0bfaac751af91dae..aea113eea6be1128c1c9e46a7df398ddadea9504 100644 --- a/tests/modules/private_message_test/private_message_test.info.yml +++ b/tests/modules/private_message_test/private_message_test.info.yml @@ -1,6 +1,6 @@ type: module name: Private Message Test package: Testing -core_version_requirement: ^9.3 || ^10 || ^11 +core_version_requirement: ^10.3 || ^11 dependencies: - private_message:private_message diff --git a/tests/src/Kernel/EntityDeleteTest.php b/tests/src/Kernel/EntityDeleteTest.php index 7c7ef235942e1d239a8441709cfefce71c6abd01..be7e603c07a7d67d084247a780ed195045d59a6c 100644 --- a/tests/src/Kernel/EntityDeleteTest.php +++ b/tests/src/Kernel/EntityDeleteTest.php @@ -8,12 +8,12 @@ use Drupal\KernelTests\KernelTestBase; use Drupal\Tests\private_message\Traits\PrivateMessageTestTrait; use Drupal\private_message\Entity\PrivateMessageBan; use Drupal\private_message\Entity\PrivateMessageThreadInterface; -use PHPUnit\Framework\Attributes\Group; /** * Tests deletion of private message entities. + * + * @group private_message */ -#[Group('private_message')] final class EntityDeleteTest extends KernelTestBase { use PrivateMessageTestTrait;