From 13ca099d4212d4dbcff76a7a9abd1986367fc57c Mon Sep 17 00:00:00 2001 From: Tim Rohaly <tr@202830.no-reply.drupal.org> Date: Sat, 10 Aug 2024 10:35:06 -0700 Subject: [PATCH 1/8] Issue #3467356 by TR: Drop D9 support --- votingapi.info.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/votingapi.info.yml b/votingapi.info.yml index 1dac996..399dea4 100644 --- a/votingapi.info.yml +++ b/votingapi.info.yml @@ -2,6 +2,6 @@ name: Voting API type: module description: 'Provides a voting API that other modules can make use of.' package: Voting -core_version_requirement: ^9.2 || ^10 +core_version_requirement: ^10.3 || ^11 configure: votingapi.admin_settings -- GitLab From 1a69bd340e2b768e7b7482671fddf7b97f4a75a4 Mon Sep 17 00:00:00 2001 From: Tim Rohaly <tr@202830.no-reply.drupal.org> Date: Sat, 10 Aug 2024 17:28:01 -0700 Subject: [PATCH 2/8] Revert "Issue #3467356 by TR: Drop D9 support" I committed this to the wrong branch. This branch, 8-x-3.x, will not be dropping D9 support. This reverts commit 13ca099d4212d4dbcff76a7a9abd1986367fc57c. --- votingapi.info.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/votingapi.info.yml b/votingapi.info.yml index 399dea4..1dac996 100644 --- a/votingapi.info.yml +++ b/votingapi.info.yml @@ -2,6 +2,6 @@ name: Voting API type: module description: 'Provides a voting API that other modules can make use of.' package: Voting -core_version_requirement: ^10.3 || ^11 +core_version_requirement: ^9.2 || ^10 configure: votingapi.admin_settings -- GitLab From 10d69d21cb4d9dcd09cce804b30a9224d860ccbd Mon Sep 17 00:00:00 2001 From: Tim Rohaly <42475-tr@users.noreply.drupalcode.org> Date: Sat, 10 Aug 2024 21:57:37 +0000 Subject: [PATCH 3/8] Issue #3467380 by TR: Don't use t() in tests --- tests/src/Functional/VoteDeletionTest.php | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/tests/src/Functional/VoteDeletionTest.php b/tests/src/Functional/VoteDeletionTest.php index 0684320..a364611 100644 --- a/tests/src/Functional/VoteDeletionTest.php +++ b/tests/src/Functional/VoteDeletionTest.php @@ -89,19 +89,9 @@ class VoteDeletionTest extends BrowserTestBase { // Delete a vote. $this->drupalGet('admin/vote/' . reset($vote_id) . '/delete'); - $session->pageTextContains( - t('You are about to delete a vote by @user on @entity-type @label. This action cannot be undone.', [ - '@user' => $vote_owner, - '@entity-type' => $entity_type, - '@label' => $label, - ])); + $session->pageTextContains('You are about to delete a vote by ' . $vote_owner . ' on ' . $entity_type . ' ' . $label . '. This action cannot be undone.'); $this->submitForm([], 'Delete'); - $session->pageTextContains( - t('The vote by @user on @entity-type @label has been deleted.', [ - '@user' => $vote_owner, - '@entity-type' => $entity_type, - '@label' => $label, - ])); + $session->pageTextContains('The vote by ' . $vote_owner . ' on ' . $entity_type . ' ' . $label . ' has been deleted.'); // Assert that the vote got deleted and other votes remain. $source_1_votes = $vote_storage->getUserVotes(0, 'vote', 'node', 1, 'source_1'); -- GitLab From cb6f0809b6830c4d7d4b2a92707e91707570e6a9 Mon Sep 17 00:00:00 2001 From: Tim Rohaly <tr@202830.no-reply.drupal.org> Date: Sat, 10 Aug 2024 15:32:25 -0700 Subject: [PATCH 4/8] Issue #3467382 by TR: phpcs: list(...) is forbidden --- modules/votingapi_tokens/votingapi_tokens.tokens.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/votingapi_tokens/votingapi_tokens.tokens.inc b/modules/votingapi_tokens/votingapi_tokens.tokens.inc index f0f52dc..2a09c01 100644 --- a/modules/votingapi_tokens/votingapi_tokens.tokens.inc +++ b/modules/votingapi_tokens/votingapi_tokens.tokens.inc @@ -64,7 +64,7 @@ function votingapi_tokens_tokens($type, $tokens, array $data, array $options, Bu $votes = \Drupal::service('plugin.manager.votingapi.resultfunction') ->getResults($entity_type, $data[$entity_type]->id()); foreach ($tokens as $name => $original) { - list($token_name, $vote_type) = explode(':', $name); + [$token_name, $vote_type] = explode(':', $name); switch ($token_name) { case 'vote_count': $replacements[$original] = $votes[$vote_type]['vote_count']; -- GitLab From 35b7ff206ddac80e9409f992d3d2cf6f91d59b1f Mon Sep 17 00:00:00 2001 From: Tim Rohaly <42475-tr@users.noreply.drupalcode.org> Date: Sat, 10 Aug 2024 22:24:52 +0000 Subject: [PATCH 5/8] Issue #3467381 by TR: cspell changes --- .gitlab-ci.yml | 3 ++- API.txt | 13 ++++++------- src/VoteStorageInterface.php | 2 +- votingapi.api.php | 14 +++++++------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a8671ab..561307e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,7 +50,8 @@ include: # SKIP_ESLINT: '1' variables: - _CSPELL_IGNORE_PATHS: '"phpcs.xml.dist", "tests/fixtures/*.php"' + _CSPELL_IGNORE_PATHS: '"phpcs.xml.dist", "tests/fixtures/*.php", "README.txt"' + _CSPELL_WORDS: 'resultfunction' _SHOW_ENVIRONMENT_VARIABLES: 1 _PHPUNIT_CONCURRENT: 1 OPT_IN_TEST_MIN_PHP: 1 diff --git a/API.txt b/API.txt index 5b8780d..ab4233e 100644 --- a/API.txt +++ b/API.txt @@ -30,7 +30,7 @@ How Data Is Stored VotingAPI manages a raw 'pool' of vote data -- it doesn't keep track of any content directly. Instead, it lets modules store each vote with a 'content type' and 'content id', so that the same APIs can be used to rate nodes, comments, -users, aggregator items, or even other votes (in a Slashdot-esque +users, aggregator items, or even other votes (in a Slashdot-like meta-moderation system). It can also be used by modules that need to store and calculate custom data like polling results -- using a custom entity_type ensures that other modules won't trample on your module's voting data. @@ -175,7 +175,7 @@ comments. If your module casts other types of votes that should be made available via Views, it needs to implement hook_votingapi_relationships(). -function mymodule_votingapi_relationships() { +function my_module_votingapi_relationships() { $relationships[] = [ // 'description' is used to construct the field description in the Views UI. 'description' => t('nodes'), @@ -192,8 +192,7 @@ function mymodule_votingapi_relationships() { // VotingAPI constructs pseudo-tables so that multiple relationships can // point to the same base table (normal and translation-based votes nodes // for example. These two columns allow you to override the names of the - // pseudo-tables. You probably don't need to change this part unless you're - // nedjo. + // pseudo-tables. You probably don't need to change this part. 'pseudo_vote' => 'votingapi_vote', 'pseudo_cache' => 'votingapi_cache', ]; @@ -209,11 +208,11 @@ given VotingAPI view field. For the View field that's passed in, your hook should return an array of key => value pairs, where the key is a the name of a callback function that will format the values from the database. -function mymodule_votingapi_views_formatters($field) { +function my_module_votingapi_views_formatters($field) { if ($field->field == 'value') { - return ['mymodule_funky_formatter' => t('MyModule value formatter')]; + return ['my_module_funky_formatter' => t('MyModule value formatter')]; } if ($field->field == 'tag') { - return ['mymodule_funky_tags' => t('MyModule tag formatter')]; + return ['my_module_funky_tags' => t('MyModule tag formatter')]; } } diff --git a/src/VoteStorageInterface.php b/src/VoteStorageInterface.php index b9c43e4..a818d38 100644 --- a/src/VoteStorageInterface.php +++ b/src/VoteStorageInterface.php @@ -67,7 +67,7 @@ interface VoteStorageInterface extends EntityStorageInterface { public function getVotesSinceMoment(); /** - * Delets votes for deleted entity everywhere in the database. + * Deletes votes for deleted entity everywhere in the database. * * @param string $entity_type_id * The entity type ID. diff --git a/votingapi.api.php b/votingapi.api.php index 4be251c..9f85be0 100644 --- a/votingapi.api.php +++ b/votingapi.api.php @@ -68,7 +68,7 @@ function hook_votingapi_results_alter(array &$vote_results, $entity_type, $entit * * If your module uses custom tags or value_types, or calculates custom * aggregate functions, please implement this hook so other modules can properly - * interperet and display your data. + * interpret and display your data. * * Three major bins of data are stored: tags, value_types, and aggregate result * functions. Each entry in these bins is keyed by the value stored in the @@ -85,25 +85,25 @@ function hook_votingapi_metadata_alter(&$data) { $data['tags']['bread'] = [ 'name' => t('Bread'), 'description' => t('The quality of the food at a restaurant.'), - 'module' => 'mymodule', + 'module' => 'my_module', // This is optional; we can add it for our own purposes. ]; $data['tags']['circuses'] = [ 'name' => t('Circuses'), 'description' => t('The quality of the presentation and atmosphere at a restaurant.'), - 'module' => 'mymodule', + 'module' => 'my_module', ]; // Document two custom aggregate function. $data['functions']['standard_deviation'] = [ 'name' => t('Standard deviation'), 'description' => t('The standard deviation of all votes cast on a given piece of content. Use this to find controversial content.'), - 'module' => 'mymodule', + 'module' => 'my_module', ]; $data['functions']['median'] = [ 'name' => t('Median vote'), 'description' => t('The median vote value cast on a given piece of content. More accurate than a pure average when there are a few outlying votes.'), - 'module' => 'mymodule', + 'module' => 'my_module', ]; } @@ -127,10 +127,10 @@ function hook_votingapi_metadata_alter(&$data) { */ function hook_votingapi_views_formatters($field) { if ($field->field == 'value') { - return ['mymodule_funky_formatter' => t('MyModule value formatter')]; + return ['my_module_funky_formatter' => t('MyModule value formatter')]; } if ($field->field == 'tag') { - return ['mymodule_funky_tags' => t('MyModule tag formatter')]; + return ['my_module_funky_tags' => t('MyModule tag formatter')]; } } -- GitLab From 5f54fecbf02cb1207f8f70cfa7b0e20f28864ea4 Mon Sep 17 00:00:00 2001 From: Tim Rohaly <tr@202830.no-reply.drupal.org> Date: Mon, 26 Aug 2024 15:36:14 -0700 Subject: [PATCH 6/8] Minor PHPCS fixes --- CHANGELOG.txt | 3 ++- src/Entity/VoteResult.php | 1 - src/Entity/VoteType.php | 2 +- src/VoteResultFunctionManager.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d3b39c6..8341358 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -28,7 +28,8 @@ without using esoteric combinations of filters. -------- A new setting has been introduced -- vote result calculation can be deferred until cron-time. This can be useful on heavy-load sites where MANY votes are -being cast and complex, db-intensive calculations are used to weight the results. +being cast and complex, db-intensive calculations are used to weight the +results. 05/01/06 -------- diff --git a/src/Entity/VoteResult.php b/src/Entity/VoteResult.php index a78eb31..2be9841 100644 --- a/src/Entity/VoteResult.php +++ b/src/Entity/VoteResult.php @@ -5,7 +5,6 @@ namespace Drupal\votingapi\Entity; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\user\UserInterface; use Drupal\votingapi\VoteResultInterface; /** diff --git a/src/Entity/VoteType.php b/src/Entity/VoteType.php index 799cbb2..17f9293 100644 --- a/src/Entity/VoteType.php +++ b/src/Entity/VoteType.php @@ -99,7 +99,7 @@ class VoteType extends ConfigEntityBundleBase implements VoteTypeInterface { // Clear the vote type cache to reflect the removal. $storage->resetCache(array_keys($entities)); - // TODO: needed? + // @todo Is this needed? } } diff --git a/src/VoteResultFunctionManager.php b/src/VoteResultFunctionManager.php index 9b49f6a..110e4e7 100644 --- a/src/VoteResultFunctionManager.php +++ b/src/VoteResultFunctionManager.php @@ -176,7 +176,7 @@ class VoteResultFunctionManager extends DefaultPluginManager { // Give other modules a chance to act on the results of vote calculations. $this->moduleHandler->alter('votingapi_results', $vote_results, $entity_type_id, $entity_id); - foreach ($vote_results as $id => $vote_result) { + foreach ($vote_results as $vote_result) { if (!empty($vote_result)) { $this->database->insert('votingapi_result')->fields($vote_result)->execute(); } -- GitLab From 40830e4fcc853463eeff3b19181d8a3661db5911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabien=20Cl=C3=A9ment?= <goz@226961.no-reply.drupal.org> Date: Thu, 12 Sep 2024 12:28:55 +0200 Subject: [PATCH 7/8] Issue #2965603 by jeffdavidgordon: Add support for UUID field to votingapi_result table --- src/Entity/VoteResult.php | 8 +++++++- src/VoteResultFunctionManager.php | 12 +++++++++++- votingapi.install | 13 +++++++++++++ votingapi.post_update.php | 28 ++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 votingapi.post_update.php diff --git a/src/Entity/VoteResult.php b/src/Entity/VoteResult.php index e799912..6a48394 100644 --- a/src/Entity/VoteResult.php +++ b/src/Entity/VoteResult.php @@ -32,7 +32,8 @@ use Drupal\votingapi\VoteResultInterface; * }, * base_table = "votingapi_result", * entity_keys = { - * "id" = "id" + * "id" = "id", + * "uuid" = "uuid" * } * ) */ @@ -133,6 +134,11 @@ class VoteResult extends ContentEntityBase implements VoteResultInterface { ->setReadOnly(TRUE) ->setSetting('unsigned', TRUE); + $fields[$entity_type->getKey('uuid')] = BaseFieldDefinition::create('uuid') + ->setLabel(new TranslatableMarkup('UUID')) + ->setDescription(new TranslatableMarkup('The vote result UUID.')) + ->setReadOnly(TRUE); + $fields['type'] = BaseFieldDefinition::create('entity_reference') ->setLabel(new TranslatableMarkup('Type')) ->setDescription(new TranslatableMarkup('The vote type.')) diff --git a/src/VoteResultFunctionManager.php b/src/VoteResultFunctionManager.php index 595ba2a..999a1a3 100644 --- a/src/VoteResultFunctionManager.php +++ b/src/VoteResultFunctionManager.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Drupal\votingapi; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Component\Uuid\UuidInterface; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityTypeManagerInterface; @@ -46,6 +47,11 @@ class VoteResultFunctionManager extends DefaultPluginManager implements VoteResu */ protected $datetime; + /** + * @var \Drupal\Component\Uuid\UuidInterface + */ + protected $uuid; + /** * Constructs a new VoteResultFunctionManager. * @@ -62,12 +68,15 @@ class VoteResultFunctionManager extends DefaultPluginManager implements VoteResu * The entity_type.manager service. * @param \Drupal\Component\Datetime\TimeInterface $datetime * The datetime.time service. + * @param \Drupal\Component\Uuid\UuidInterface $uuid + * The UUID service. */ - public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, Connection $database, EntityTypeManagerInterface $entity_type_manager, TimeInterface $datetime) { + public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, Connection $database, EntityTypeManagerInterface $entity_type_manager, TimeInterface $datetime, UuidInterface $uuid) { parent::__construct('Plugin/VoteResultFunction', $namespaces, $module_handler, VoteResultFunctionInterface::class, VoteResultFunction::class, 'Drupal\votingapi\Annotation\VoteResultFunction'); $this->database = $database; $this->entityTypeManager = $entity_type_manager; $this->datetime = $datetime; + $this->uuid = $uuid; $this->alterInfo('vote_result_info'); $this->setCacheBackend($cache_backend, 'vote_result_plugins'); } @@ -167,6 +176,7 @@ class VoteResultFunctionManager extends DefaultPluginManager implements VoteResu $plugin = $this->createInstance($plugin_id); $vote_results[] = [ 'entity_id' => $entity_id, + 'uuid' => $this->uuid->generate(), 'entity_type' => $entity_type_id, 'type' => $vote_type, 'function' => $plugin_id, diff --git a/votingapi.install b/votingapi.install index b27ebd6..a524721 100644 --- a/votingapi.install +++ b/votingapi.install @@ -11,3 +11,16 @@ function votingapi_update_last_removed() { return 8304; } + +/** + * Install the definition of 'uuid' field Vote Result entity. + */ +function votingapi_update_8305(&$sandbox) { + $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + if ($vote_result_fields = \Drupal::service('entity_field.manager')->getFieldStorageDefinitions('vote_result')) { + /** @var \Drupal\Core\Field\BaseFieldDefinition $function_field_definition */ + $function_field_definition = $vote_result_fields['uuid']; + $function_field_definition->getSchema(); + $definition_update_manager->installFieldStorageDefinition('uuid', 'vote_result', 'votingapi', $function_field_definition); + } +} diff --git a/votingapi.post_update.php b/votingapi.post_update.php new file mode 100644 index 0000000..6795717 --- /dev/null +++ b/votingapi.post_update.php @@ -0,0 +1,28 @@ +<?php + +/** + * @file + * Post update functions for votingapi. + */ + +/** + * Generate uuids for existing vote_result entities with no uuids. + */ +function votingapi_post_update_generate_vote_result_uuids(&$sandbox) { + $table_name = 'votingapi_result'; + $connection = \Drupal::service('database'); + $rows = $connection->select($table_name, 'votingapi_result') + ->fields('votingapi_result', ['id']) + ->isNull('uuid') + ->execute() + ->fetchAll(); + + $uuidGenerator = \Drupal::service('uuid'); + + foreach ($rows as $row) { + $connection->update($table_name) + ->fields(['uuid' => $uuidGenerator->generate()]) + ->condition('id', $row->id) + ->execute(); + } +} -- GitLab From 64d4ec4920e94bfc97e49683be762ade2ef7d6f9 Mon Sep 17 00:00:00 2001 From: Tim Rohaly <tr@202830.no-reply.drupal.org> Date: Thu, 6 Mar 2025 22:48:23 -0800 Subject: [PATCH 8/8] Use BaseFieldDefinition from parent for id and uuid --- src/Entity/VoteResult.php | 16 +++++----------- votingapi.install | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Entity/VoteResult.php b/src/Entity/VoteResult.php index 6a48394..1981604 100644 --- a/src/Entity/VoteResult.php +++ b/src/Entity/VoteResult.php @@ -33,7 +33,7 @@ use Drupal\votingapi\VoteResultInterface; * base_table = "votingapi_result", * entity_keys = { * "id" = "id", - * "uuid" = "uuid" + * "uuid" = "uuid", * } * ) */ @@ -128,16 +128,10 @@ class VoteResult extends ContentEntityBase implements VoteResultInterface { */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type): array { /** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */ - $fields['id'] = BaseFieldDefinition::create('integer') - ->setLabel(new TranslatableMarkup('ID')) - ->setDescription(new TranslatableMarkup('The vote result ID.')) - ->setReadOnly(TRUE) - ->setSetting('unsigned', TRUE); - - $fields[$entity_type->getKey('uuid')] = BaseFieldDefinition::create('uuid') - ->setLabel(new TranslatableMarkup('UUID')) - ->setDescription(new TranslatableMarkup('The vote result UUID.')) - ->setReadOnly(TRUE); + $fields = parent::baseFieldDefinitions($entity_type); + + // Override parent id description. + $fields['id']->setDescription(new TranslatableMarkup('The vote result ID.')); $fields['type'] = BaseFieldDefinition::create('entity_reference') ->setLabel(new TranslatableMarkup('Type')) diff --git a/votingapi.install b/votingapi.install index a524721..e2915c6 100644 --- a/votingapi.install +++ b/votingapi.install @@ -15,7 +15,7 @@ function votingapi_update_last_removed() { /** * Install the definition of 'uuid' field Vote Result entity. */ -function votingapi_update_8305(&$sandbox) { +function votingapi_update_10400(&$sandbox) { $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); if ($vote_result_fields = \Drupal::service('entity_field.manager')->getFieldStorageDefinitions('vote_result')) { /** @var \Drupal\Core\Field\BaseFieldDefinition $function_field_definition */ -- GitLab