CommentFileSizeAuthor
#211 2081585-212.patch52.31 KBandypost
#204 2081585-204.patch50.6 KBnevergone
#198 2081585-198.patch50.87 KBandypost
#198 interdiff.txt2.26 KBandypost
#194 2081585-193.patch48.61 KBandypost
#194 interdiff.txt46.67 KBandypost
#192 2081585-192.patch93.74 KBandypost
#192 interdiff.txt13.3 KBandypost
#183 2081585-183.patch91.01 KBandypost
#183 interdiff.txt4.93 KBandypost
#179 interdiff_2081585_173-179.txt6.63 KBnevergone
#179 2081585-179.patch88.2 KBnevergone
#176 interdiff_2081585_173-176.txt10.95 KBnevergone
#176 2081585-176.patch92.07 KBnevergone
#175 interdiff_2081585_173-175.patch11.21 KBnevergone
#175 2081585-175.patch92.15 KBnevergone
#173 interdiff_2081585_171-173.txt9.32 KBnevergone
#173 2081585-173.patch89.16 KBnevergone
#171 2081585-171.patch91.67 KBnevergone
#171 interdiff_2081585_165-171.txt210 bytesnevergone
#165 2081585-165.patch92 KBpaulocs
#165 interdiff.txt498 bytespaulocs
#164 2081585-164.patch82.01 KBpaulocs
#164 interdiff.txt9.84 KBpaulocs
#162 2081585-162.patch91.93 KBandypost
#162 interdiff.txt585 bytesandypost
#161 2081585-161.patch91.91 KBandypost
#161 interdiff.txt13.34 KBandypost
#159 interdiff_2081585_155-159.txt556 bytesnevergone
#159 2081585-159.patch91.75 KBnevergone
#155 interdiff_2081585_153-155.txt542 bytesnevergone
#155 2081585-155.patch91.75 KBnevergone
#153 interdiff_2081585_150-153.txt3.34 KBnevergone
#153 2081585-153.patch91.46 KBnevergone
#150 interdiff_2081585_148-150.txt6.15 KBnevergone
#150 2081585-150.patch89.61 KBnevergone
#148 interdiff-2081585-146-148.txt1.87 KBvoleger
#148 2081585-148.patch97.29 KBvoleger
#146 interdiff_144-146.txt41.01 KBridhimaabrol24
#146 2081585-146.patch96.55 KBridhimaabrol24
#144 2081585-144.patch56.19 KBridhimaabrol24
#142 2081585-142.patch49.43 KBvladbo
#142 interdiff_2081585_139-142.txt6.86 KBvladbo
#139 interdiff_2081585_134-139.txt9.03 KBvladbo
#139 2081585-139.patch46.41 KBvladbo
#134 2081585-134.patch41.47 KBvladbo
#134 interdiff_2081585_133-134.txt1.05 KBvladbo
#133 2081585-133.patch40.82 KBvladbo
#133 interdiff_2081585_131-133.txt1.3 KBvladbo
#131 interdiff_2081585_128-131.txt6.76 KBvladbo
#131 2081585-131.patch40.96 KBvladbo
#128 2081585-128.patch39.8 KBvladbo
#128 interdiff_2081585_125-128.txt970 bytesvladbo
#125 2081585-125.patch39.55 KBvladbo
#125 interdiff_2081585_120-125.txt2.57 KBvladbo
#120 2081585-120.patch39.46 KBvladbo
#120 interdiff_2081585_117-120.txt3.63 KBvladbo
#117 interdiff_2081585_114-117.txt7.93 KBvladbo
#117 2081585-117.patch36.53 KBvladbo
#114 2081585-114.patch34.92 KBvladbo
#114 interdiff_2081585_113-114.txt665 bytesvladbo
#113 interdiff_2081585_112-113.txt9.23 KBvladbo
#113 2081585-113.patch34.15 KBvladbo
#112 interdiff_2081585_110-112.txt12.14 KBvladbo
#112 2081585-112.patch41.69 KBvladbo
#110 interdiff_107-110.txt5.13 KBvacho
#110 2081585-110.patch35.32 KBvacho
#107 interdiff_2081585_105-107.txt2.65 KBvladbo
#107 2081585-107.patch35.04 KBvladbo
#106 2081585-105.patch32.98 KBvladbo
#105 interdiff_2081585_104-105.txt1.1 KBvladbo
#104 interdiff_2081585_103-104.txt7.51 KBvladbo
#104 2081585-104.patch31.38 KBvladbo
#103 2081585-103.patch26.97 KBvladbo
#77 2081585-history-service-77.patch29.75 KBandypost
#75 2081585-history-service-75.patch29.75 KBandypost
#70 2081585-history-service-70.patch29.71 KBandypost
#70 interdiff.txt4.64 KBandypost
#69 2081585-history-service-69.patch29.47 KBandypost
#66 2081585-history-service-66.patch29.45 KBandypost
#66 interdiff.txt1.75 KBandypost
#64 2081585-history-service-64.patch29.44 KBandypost
#64 interdiff.txt2.54 KBandypost
#62 2081585-history-service-62.patch29.42 KBandypost
#62 interdiff.txt11.26 KBandypost
#60 2081585-history-service-60.patch24.9 KBandypost
#60 interdiff.txt1.82 KBandypost
#59 2081585-history-service-59.patch24.6 KBandypost
#59 interdiff.txt1.42 KBandypost
#57 2081585-history-service-57.patch24.58 KBandypost
#57 interdiff.txt14.63 KBandypost
#52 history-manager-2081585.52.patch25.53 KBandypost
#52 interdiff.txt3.58 KBandypost
#51 history-manager-2081585.50.patch25.55 KBandypost
#51 interdiff.txt6.4 KBandypost
#48 history-manager-2081585.48.patch25.46 KBandypost
#48 interdiff.txt1.1 KBandypost
#44 history-manager-2081585.44.patch25.43 KBandypost
#40 history-manager-2081585.40.patch25.48 KBandypost
#40 interdiff.txt774 bytesandypost
#39 history-manager-2081585.39.patch25.5 KBandypost
#39 interdiff.txt1.54 KBandypost
#35 history-manager-2081585.35.patch25.36 KBandypost
#35 interdiff.txt4.22 KBandypost
#31 history-manager-2081585.31.patch25.36 KBandypost
#31 interdiff.txt6.35 KBandypost
#30 history-manager-2081585.30.patch25.22 KBandypost
#30 interdiff.txt7.67 KBandypost
#28 history-manager-2081585.27.patch22.92 KBandypost
#28 interdiff.txt3.97 KBandypost
#25 history-manager-2081585.25.patch23.28 KBandypost
#25 interdiff.txt3.19 KBandypost
#17 interdiff.txt9.13 KBlarowlan
#17 history-manager-2081585.17.patch23.27 KBlarowlan
#15 interdiff.txt1.99 KBandypost
#15 drupal8.history-module.2081585-15.patch19.64 KBandypost
#12 Screenshot 2013-10-02 09.06.02.png20.62 KBlarowlan
#10 interdiff.txt664 bytesandypost
#10 drupal8.history-module.2081585-10.patch19.63 KBandypost
#9 interdiff.txt1.02 KBandypost
#9 drupal8.history-module.2081585-9.patch19.53 KBandypost
#7 interdiff.txt1.62 KBandypost
#7 drupal8.history-module.2081585-7.patch19.53 KBandypost
#5 interdiff.txt771 bytesandypost
#5 drupal8.history-module.2081585-5.patch19.43 KBandypost
#4 interdiff.txt7.35 KBandypost
#4 drupal8.history-module.2081585-4.patch19.36 KBandypost
#1 interdiff.txt11.64 KBandypost
#1 drupal8.history-module.2081585-1.patch21.06 KBandypost

Issue fork drupal-2081585

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

andypost’s picture

Status: Active » Needs review
Issue tags: +Needs tests
StatusFileSize
new21.06 KB
new11.64 KB

Initial implementation on top of #1029708-60: History table for any entity

The method names are need discussion and tests

Status: Needs review » Needs work

The last submitted patch, drupal8.history-module.2081585-1.patch, failed testing.

dawehner’s picture

+++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
@@ -0,0 +1,128 @@
+    if (!isset($account)) {
+      $account = \Drupal::currentUser();
+    }
+

Any reason to not inject that service?

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new19.36 KB
new7.35 KB

Removed changes to history_read() and write() and mark them deprecated.
Renamed service name to 'history.manager' and should fix most of comment related tests.
No idea how to fix upgrade tests, forum manager depends on new history module...

@dawehner The reason is that scope of current_user service is limited by request scope and using strict=false is ugly here

andypost’s picture

StatusFileSize
new19.43 KB
new771 bytes

Should fix upgrade tests

dawehner’s picture

+++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
@@ -110,6 +111,13 @@ class ForumManager implements ForumManagerInterface {
+   * Translation manager service.
+   *
+   * @var \Drupal\history\HistoryManagerInterface
+   */
+  protected $historyManager;
+
+  /**

@@ -122,13 +130,16 @@ class ForumManager implements ForumManagerInterface {
+  public function __construct(ConfigFactory $config_factory, EntityManager $entity_manager, Connection $connection, FieldInfo $field_info, TranslationInterface $translation_manager, HistoryManagerInterface $history_manager) {

@@ -326,18 +337,16 @@ protected function numberNew($nid, $timestamp) {
+    $this->history[$nid] = $this->historyManager->read('node', array($nid));

If we can't be sure that the history manager is available we should check that the variable exists before we call it?

andypost’s picture

StatusFileSize
new19.53 KB
new1.62 KB

Makes sense

dawehner’s picture

What about marking the HistoryManagerInterface on the constructor = NULL?

andypost’s picture

StatusFileSize
new19.53 KB
new1.02 KB

Yep, this will document that the dependency is optional

andypost’s picture

StatusFileSize
new19.63 KB
new664 bytes

fix exceptions, enough for today!

Status: Needs review » Needs work

The last submitted patch, drupal8.history-module.2081585-10.patch, failed testing.

larowlan’s picture

StatusFileSize
new20.62 KB

Test results for posterity:

Screenshot 2013-10-02 09.06.02.png

larowlan’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests, -WSCCI

Status: Needs review » Needs work
Issue tags: +Needs tests, +WSCCI

The last submitted patch, drupal8.history-module.2081585-10.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new19.64 KB
new1.99 KB

Re-roll and fixes

Status: Needs review » Needs work

The last submitted patch, drupal8.history-module.2081585-15.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new23.27 KB
new9.13 KB
  1. +++ b/core/modules/history/history.install
    @@ -13,13 +13,20 @@ function history_schema() {
    +        'description' => 'The {users}.uid that read the entity_id.',
    

    entity_id => entity

  2. +++ b/core/modules/history/history.install
    @@ -13,13 +13,20 @@ function history_schema() {
    +        'description' => 'The entity_type of the entity was read.',
    
    +++ b/core/modules/node/node.install
    @@ -670,9 +670,37 @@ function node_update_8011() {
    +    'description' => 'The entity_type of the entity was read.',
    

    that was read

  3. +++ b/core/modules/history/history.install
    @@ -13,13 +13,20 @@ function history_schema() {
    +        'description' => 'The entity_id that was read.',
    
    +++ b/core/modules/node/node.install
    @@ -670,9 +670,37 @@ function node_update_8011() {
    +    'description' => 'The entity_id that was read.',
    

    The ID of the entity that was read.

  4. +++ b/core/modules/history/history.module
    @@ -56,85 +58,40 @@ function history_read($nid) {
    +  Drupal::service('history.manager')->write('node', $nid, $account);
    ...
    +  Drupal::service('history.manager')->purge();
    ...
    +  Drupal::service('history.manager')->deleteByEntity('node', $node->id());
    
    @@ -143,9 +100,7 @@ function history_node_delete(EntityInterface $node) {
    +      Drupal::service('history.manager')->deleteByUid($account->id());
    
    @@ -154,9 +109,7 @@ function history_user_cancel($edit, $account, $method) {
    +  Drupal::service('history.manager')->deleteByUid($account->id());
    

    \Drupal

  5. +++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
    @@ -0,0 +1,143 @@
    +   * Array of history keyed by entity type and entity id.
    

    Given uid is an optional parameter, shouldn't that be in the mix here or we'll need a resetCache method.

  6. +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,68 @@
    +   *   The user account id to purge history
    

    ID

Attached patch fixes these and tests.

Status: Needs review » Needs work
Issue tags: -WSCCI

The last submitted patch, history-manager-2081585.17.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
Issue tags: +WSCCI

#17: history-manager-2081585.17.patch queued for re-testing.

dawehner’s picture

Status: Needs review » Needs work
+++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
@@ -326,18 +337,19 @@ protected function numberNew($nid, $timestamp) {
+      $this->history[$nid] = $this->historyManager->read('node', array($nid));

According to HistoryManager::read() this returns history information by entity ID, though on the left side this sets the history information to a specific value.

damiankloip’s picture

Status: Needs work » Needs review

Generally looking pretty good!

  1. +++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
    @@ -110,6 +111,13 @@ class ForumManager implements ForumManagerInterface {
    +   * History manager service.
    

    Nitpick alert: 'The history manager service' ?

  2. +++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
    @@ -326,18 +337,19 @@ protected function numberNew($nid, $timestamp) {
    +      $this->history[$nid] = HISTORY_READ_LIMIT;
    

    Can this constant get converted to a class constant?

  3. +++ b/core/modules/history/lib/Drupal/history/Controller/HistoryController.php
    @@ -54,9 +83,10 @@ public function readNode(Request $request, NodeInterface $node) {
    +    return new JsonResponse((int) $history[$node->id()]);
    

    What's going down here? why the casting? If it's legit, maybe a comment..

  4. +++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
    @@ -0,0 +1,143 @@
    +      ->condition('entity_id', array_keys($entities_to_read), 'IN')
    +      ->execute();
    ...
    +    foreach ($result as $row) {
    +      $entities_to_read[$row->entity_id] = (int) $row->timestamp;
    +    }
    

    We could return an assoc array of the results so they are in the form entity_id => timestamp already. But I guess you want this casting.

  5. +++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
    @@ -0,0 +1,143 @@
    +      $account = \Drupal::currentUser();
    

    Could just inject the current user service instead.

  6. +++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
    @@ -0,0 +1,143 @@
    +    $this->history = array();
    

    This should just call resetCache() instead.

  7. +++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
    @@ -0,0 +1,143 @@
    +    $this->history = array();
    

    And here.

  8. +++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
    @@ -0,0 +1,143 @@
    +    // Clean static cache.
    +    unset($this->history[$entity_type][$entity_id]);
    

    We could let resetCache() take an optional array of entity ids to clear? Just a thought.

  9. +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,73 @@
    +   * Reset the static cache.
    

    Resets

Also, do you think the new HistoryManager class needs it's own unit test?

andypost’s picture

This issue is mostly ready to replace #1029708-54: History table for any entity so once all nitpicks addressed probably one of them should be closed as duplicate. I've started this one to figure out how the service should operate and then move to #1029708-61: History table for any entity

Could just inject the current user service instead.

Having current_user injected breaks a lot of tests that changes users so better have optional argument

We could let resetCache() take an optional array of entity ids to clear? Just a thought.

Makes no sense, because we should pass their entity types as well.

do you think the new HistoryManager class needs it's own unit test?

Makes sense

damiankloip’s picture

+++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
@@ -0,0 +1,143 @@
+      $account = \Drupal::currentUser();

I'm not sure how just changing this for the injected current_user service will stop using $account etc..? You will still have the same logic as now.

andypost’s picture

The reason is #2102027: Add back the request scope to the current user service so service should be agnostic to current_user that could be limited to request scope

+++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
@@ -0,0 +1,143 @@
+  public function read($entity_type, $entity_ids) {
...
+      ->condition('uid', \Drupal::currentUser()->id())
...
+  public function write($entity_type, $entity_id, AccountInterface $account = NULL) {
+    if (!isset($account)) {
+      $account = \Drupal::currentUser();

Seems we need to add $account to read() and check the usage

andypost’s picture

Issue summary: View changes
StatusFileSize
new3.19 KB
new23.28 KB

re-roll with fixes for #21

Status: Needs review » Needs work

The last submitted patch, 25: history-manager-2081585.25.patch, failed testing.

sun’s picture

  1. +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,73 @@
    +/**
    + * Provides history manager interface.
    + */
    +interface HistoryManagerInterface {
    

    The name "HistoryManager" wasn't very intuitive and self-descriptive until I looked at what it actually does.

    I do not have a concrete improvement suggestion, but I wonder whether we're able to find a more intuitive name?

    The goal for a better name would be to at least hint a little bit at what exactly this service is doing (retrieving and updating last viewed timestamps for entities).

    I know that we struggled a lot with finding a proper name for History module in the past already (and IIRC, we still have a dedicated issue open for that even), but perhaps:

    \Drupal\history\EntityViewManager

    ?

  2. +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,73 @@
    +   * Retrieves the timestamp for the current user's last view of the entities.
    ...
    +  public function read($entity_type, $entity_ids);
    ...
    +   * Updates 'last viewed' timestamp of the entity for the current user.
    ...
    +  public function write($entity_type, $entity_id, AccountInterface $account = NULL);
    

    Hm. The "read" and "write" terminology originates from the procedural implementation, in which it was rather unusual to use more descriptive function names.

    In an object-oriented implementation, developers expect more self-explanatory method names.

    Could we rename these methods along the lines of the following?

    getLastViewedTimestamps()
    updateLastViewedTimestamps()

    For brevity, I guess it would be fine to exclude the "Timestamp" part and just go with getLastViewed() and updateLastViewed().

    Such method names would be much more clear compared to read() and write(), wouldn't they?

    Lastly, while I understand the use-case-driven difference of getting multiple last viewed timestamps vs. updating a single last viewed timestamp, I do not understand why only the update method allows to pass a custom user account — if there's a use-case for updating the history for a user account that is not the current user, then there must also be a use-case for getting the history for a user that is not the current user, no?

    Finally, as this is all about entity system entities (as opposed to arbitrary "entity type" strings), would it make sense to replace the $entity_type + $entity_id arguments in the update method with a single EntityInterface $entity argument?

    updateLastViewed(EntityInterface $entity, AccountInterface $account = NULL)

    I consider these aspects to be the most important part of this patch, as we're defining an interface (API) for a service that may be replaced with a different implementation.

  3. +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,73 @@
    +  public function deleteByUid($uid);
    

    I don't know whether it is technically feasible (primarily concerning performance), but would it be possible to replace the $uid argument with AccountInterface $account?

    Otherwise, we would be hard-coding an assumption that $account->uid is the ID of user accounts in this API and all consuming code — whereas AccountInterface properly defines what exactly a user is in Drupal, regardless of the actual implementation.

  4. +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,73 @@
    +  public function deleteByEntity($entity_type, $entity_id);
    

    As above, is it possible to replace the two arguments with EntityInterface $entity?

    Otherwise, deleteByEntity() claims to talk about entities, but an actual entity is not part of the API contract?

  5. +++ b/core/modules/node/node.install
    @@ -720,9 +720,37 @@ function node_update_8011() {
    +  db_add_field('history', 'entity_type', array(
    ...
    +    'default' => 'node',
    

    Unless I'm terribly mistaken, I think you meant 'initial' instead of 'default', no?

    'default' specifies the (permanent) default value for the column, whereas 'initial' specifies the initial value of all existing rows for a newly created column.

  6. +++ b/core/modules/node/node.install
    @@ -720,9 +720,37 @@ function node_update_8011() {
    +    'length' => 255,
    

    In D8, didn't we globally limit the maximum length of entity_type to ~64 characters already?

  7. +++ b/core/modules/node/node.install
    @@ -720,9 +720,37 @@ function node_update_8011() {
    +  // Create new indexes.
    +  db_add_primary_key('history', array(
    +    'uid',
    +    'entity_id',
    +    array('entity_type', 32),
    +  ));
    +  db_add_index('history', 'history_entity', array(
    +    'entity_id',
    +    array('entity_type', 32),
    +  ));
    

    These tables can quickly grow very large.

    For (MySQL) query statement performance optimization, columns that share and have the most repetitive values should always be specified first in the primary key and all other indexes.

    For the history tables, I guess it would be reasonable to expect that values will increasingly vary in this order:

    1) entity_type
    2) uid
    3) entity_id

  8. +++ b/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerTest.php
    @@ -154,6 +154,7 @@ function testTrackerNewNodes() {
         $this->drupalLogin($this->other_user);
    +    \Drupal::service('history.manager')->resetCache();
    

    Why is the history cache manually reset here?

    Since the test uses the internal browser to request pages and logs in another user between assertions, the history functionality should work as-is.

    The manual cache reset in the test runner appears to hide a potentially existing bug?

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new3.97 KB
new22.92 KB

Should fix failure, also trying to address #27.8

@sun thanx a lot for the review, I'm not so good in naming so should think a bit more about 1 and 2,

3) makes sense
4) yep, and convert to ContentEntityInterface
5) not found any references about "initial" but the purpose exactly the same, so added hunk to remove this and @todo about migrate
6) not found any issues about, it there any please point me, it makes sense to file separate issue for that (comment field affected too)
7) probably, no idea how to test this

EDIT suppose defaults for entity_type and entity_id should be removed like #1029708-69: History table for any entity (70)

PS: related about 1 #1961548: [Policy, no patch] Decide how the module-specific services are made available as static methods (similar to \Drupal::$service())

sun’s picture

Wow, that was quick! :)

4) I do not really see a reason for why history/last-viewed tracking should be limited to content entities? Is there any? Oh, the integer entity ID vs. string entity ID, I guess? Bummer.

That said, is that storage related detail something we want to hard-code in the API/Interface? What if I'm replacing the entire entity history storage with a key/value store, which in turn would enable me to track views of e.g. config entities, too? :)

As a consequence, not sure whether PHP allows for that, but could the interface take a EntityInterface, but the default (SQL) implementation of History module would take a ContentEntityInterface?

5) Indeed, the 'initial' key is poorly documented, but it does exist:
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Database!Schema.p...
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Database!Driver!m...

In short, you can simply specify this:

array(
  'default' => '',
  'initial' => 'node',
)
andypost’s picture

StatusFileSize
new7.67 KB
new25.22 KB

Fixed 3,4,5 and remaining @todo in comment module

andypost’s picture

StatusFileSize
new6.35 KB
new25.36 KB

just go with getLastViewed() and updateLastViewed().

This names better explains and could be grep'ed easily

The last submitted patch, 30: history-manager-2081585.30.patch, failed testing.

The last submitted patch, 30: history-manager-2081585.30.patch, failed testing.

sun’s picture

Great! :)

  1. +++ b/core/modules/comment/comment.module
    @@ -1162,31 +1151,18 @@ function comment_load($cid, $reset = FALSE) {
    +      $timestamp = \Drupal::service('history.manager')->getLastViewed($entity_type, array($entity_id));
    
    +++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
    @@ -329,16 +340,19 @@ protected function numberNew($nid, $timestamp) {
    +      $this->history[$nid] = $this->historyManager->getLastViewed('node', array($nid));
    
    +++ b/core/modules/history/history.module
    @@ -41,9 +42,11 @@ function history_help($path, $arg) {
     function history_read($nid) {
    -  $history = history_read_multiple(array($nid));
    +  $history = \Drupal::service('history.manager')->getLastViewed('node', array($nid));
       return $history[$nid];
     }
    
    +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,72 @@
    +   * @return array
    +   *   Array of timestamps keyed by entity ID. If a entity has been previously
    +   *   viewed by the user, the timestamp in seconds of when the last view
    +   *   occurred; otherwise, zero.
    +   */
    +  public function getLastViewed($entity_type, $entity_ids);
    

    The code was using the _read_multiple() function before; the return value is an array and not the timestamp value of the requested entity ID, so that obviously breaks :)

  2. +++ b/core/modules/history/history.install
    @@ -31,11 +38,19 @@ function history_schema() {
    +    'primary key' => array(
    +      'uid',
    +      'entity_id',
    +      array('entity_type', 32),
    +    ),
         'indexes' => array(
    ...
    +      'history_entity' => array(
    +        'entity_id',
    +        array('entity_type', 32),
    +      ),
         ),
    

    If you can just move the 'entity_type' field in these indexes to come first, then I'm happy and promise to shut up :)

    (identical change in the update function)

  3. +++ b/core/modules/history/history.module
    @@ -41,9 +42,11 @@ function history_help($path, $arg) {
    + * @deprecated Use \Drupal\history\HistoryManager::getLastViewed() instead.
    
    @@ -57,75 +60,33 @@ function history_read($nid) {
    + * @deprecated Use \Drupal\history\HistoryManager::getLastViewed() instead.
    ...
    + * @deprecated Use \Drupal\history\HistoryManager::updateLastViewed() instead.
    

    Do we actually have to keep those deprecated procedural functions around? It looks like the only core consumer is being converted as part of this patch already?

    If possible, let's remove those procedural wrappers directly with this patch?

  4. +++ b/core/modules/history/lib/Drupal/history/Controller/HistoryController.php
    @@ -54,9 +83,10 @@ public function readNode(Request $request, NodeInterface $node) {
    +    $this->historyManager->updateLastViewed('node', $node->id());
    
    +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,72 @@
    +  public function updateLastViewed($entity_type, $entity_id, AccountInterface $account = NULL);
    

    The last remaining API tweak would be to change the signature to updateLastViewed(EntityInterface $entity), too, if possible. :)

andypost’s picture

StatusFileSize
new4.22 KB
new25.36 KB

@sun Thanx a lot for point!
1) fixed
2) changed as proposed
3) No api change to make this in, and related #2042165: Add a 'deprecated' module that includes deprecated functions only when enabled
4) makes sense, fixed

The last submitted patch, 31: history-manager-2081585.31.patch, failed testing.

sun’s picture

  1. +++ b/core/modules/comment/comment.module
    @@ -1162,31 +1151,18 @@ function comment_load($cid, $reset = FALSE) {
    +      $timestamp = \Drupal::service('history.manager')->getLastViewed($entity_type, array($entity_id));
    

    Still an array :)

  2. +++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
    @@ -329,16 +340,19 @@ protected function numberNew($nid, $timestamp) {
    +      $this->history[$nid] = HISTORY_READ_LIMIT;
    

    I guess it would make sense to move this constant into the HistoryManagerInterface?

  3. +++ b/core/modules/history/history.install
    @@ -10,16 +10,23 @@
    +      'entity_type' => array(
    ...
    +        'default' => 'node',
    
    +++ b/core/modules/node/node.install
    @@ -720,9 +720,39 @@ function node_update_8011() {
    +  db_add_field('history', 'entity_type', array(
    ...
    +    'initial' => 'node',
    

    As this column is part of the primary key, we have to specify a default value of 'default' => '' in the update function.

    Also note that the schema still defines "node" as default value.

Status: Needs review » Needs work

The last submitted patch, 35: history-manager-2081585.35.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.54 KB
new25.5 KB

1) fixed
2) this is not constant define('HISTORY_READ_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60); suppose we need separate issue to deal with it
3) fixed, set to empty as 'node' makes no sense as default

andypost’s picture

StatusFileSize
new774 bytes
new25.48 KB

Fixes broken tests

The last submitted patch, 39: history-manager-2081585.39.patch, failed testing.

andypost’s picture

Status: Needs review » Needs work

The last submitted patch, 40: history-manager-2081585.40.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
Issue tags: +DX (Developer Experience)
StatusFileSize
new25.43 KB

re-roll

andypost’s picture

Issue tags: +beta target

Can someone RTBC this?

dawehner’s picture

+++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
@@ -0,0 +1,70 @@
+/**
+ * Provides history manager interface.
+ */
+interface HistoryManagerInterface {

I wonder whether we can find a better description of the capabilities of a history manager, as your current one does not provide any information. "Provides the last view on entities", (maybe?)

joelpittet’s picture

  1. +++ b/core/modules/node/node.install
    @@ -719,9 +719,40 @@ function node_update_8011() {
    +  // @todo replace with proper migrate implementation.
    

    Should this @todo be finished up before RTBC?

  2. +++ b/core/modules/comment/comment.module
    @@ -69,17 +69,6 @@
    -define('COMMENT_NEW_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60);
    

    How is this being treated now, as I don't see that 30 day equation in the new service?

andypost’s picture

StatusFileSize
new1.1 KB
new25.46 KB

#46 fixed

#47.1 fixed
#47.2 HISTORY_READ_LIMIT is the same constant

+++ b/core/modules/comment/comment.module
@@ -69,17 +69,6 @@
-define('COMMENT_NEW_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60);

@@ -1160,20 +1150,8 @@ function comment_num_new($entity_id, $entity_type, $field_name = NULL, $timestam
-          // @todo Remove once http://drupal.org/node/1029708 lands.
-          $timestamp = COMMENT_NEW_LIMIT;

@@ -1160,20 +1150,8 @@ function comment_num_new($entity_id, $entity_type, $field_name = NULL, $timestam
     $timestamp = ($timestamp > HISTORY_READ_LIMIT ? $timestamp : HISTORY_READ_LIMIT);

HISTORY_READ_LIMIT

dawehner’s picture

  1. +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,70 @@
    + * Provides an interface to manage a last view timestamp of entities.
    

    Yeah "manage" does not really tell you a lot.

  2. +++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
    @@ -0,0 +1,70 @@
    +interface HistoryManagerInterface {
    

    /**
    * Defines an interface to store and retrieve last view timestamp information of entities.
    */
    interface HistoryRepositoryInterface {}

amateescu’s picture

  1. +++ b/core/modules/comment/comment.module
    @@ -1119,7 +1108,8 @@ function comment_load($cid, $reset = FALSE) {
      * @param $timestamp
    - *   Time to count from (defaults to time of last user access to node).
    + *   (optional) Time to count from (defaults to time of last user access to
    

    Since we're updating this, we can also put a type hint for $timestamp.

  2. +++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
    @@ -330,16 +341,19 @@ protected function numberNew($nid, $timestamp) {
    +      // History manager service could not be available.
    

    Should we also explain in which case this service might not available?

  3. +++ b/core/modules/history/history.install
    @@ -10,16 +10,23 @@
    +    'description' => 'A record of which {users} have read which {entities}s.',
    

    There is no {entities} table..

andypost’s picture

StatusFileSize
new6.4 KB
new25.55 KB

@dawehner thatx for idea, just fixed to 80 chars limit

andypost’s picture

StatusFileSize
new3.58 KB
new25.53 KB

Let's see if upgrade tests still affected...

dawehner’s picture

Oh, I automatically assumed that we wanna rename the class and all variables as well. Don't you think otherwise it would be confusing?

Status: Needs review » Needs work

The last submitted patch, 52: history-manager-2081585.52.patch, failed testing.

andypost’s picture

Suppose this service needs current user injected otherwise the static cache is invalid
OTOH the history module storage assumes that it should be user to track the last authorized

+++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
@@ -0,0 +1,144 @@
+  public function getLastViewed($entity_type, $entity_ids) {
...
+    $result = $this->connection->select('history', 'h')
...
+      ->condition('uid', \Drupal::currentUser()->id())
...
+      ->condition('entity_id', array_keys($entities_to_read), 'IN')
...
+  public function updateLastViewed(EntityInterface $entity, AccountInterface $account = NULL) {
...
+    if ($account->isAuthenticated()) {
+      $this->connection->merge('history')
...
+          'uid' => $account->id(),
+          'entity_id' => $entity->id(),

$account should be injected or passed as required argument

andypost’s picture

To track anonymous node views there's statistics module so "history" should track authorized

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new14.63 KB
new24.58 KB

Re-roll and clean-up:
- user account is required
- s/manager/repository
- fix forum manager test

Status: Needs review » Needs work

The last submitted patch, 57: 2081585-history-service-57.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.42 KB
new24.6 KB

Fix tests

andypost’s picture

StatusFileSize
new1.82 KB
new24.9 KB

To keep static cache valid the current user should be injected

dawehner’s picture

+++ b/core/modules/history/lib/Drupal/history/HistoryRepository.php
@@ -0,0 +1,150 @@
+  public function getLastViewed($entity_type, $entity_ids) {
...
+  public function updateLastViewed(EntityInterface $entity, AccountInterface $account) {

I think we should make it at least possible to pass in a user/UID to get the information from a different user.

andypost’s picture

StatusFileSize
new11.26 KB
new29.42 KB

Account added as required argument, now we should get rid the static cache and purge functions

Status: Needs review » Needs work

The last submitted patch, 62: 2081585-history-service-62.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new2.54 KB
new29.44 KB

fixed remains of "manager"

Status: Needs review » Needs work

The last submitted patch, 64: 2081585-history-service-64.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.75 KB
new29.45 KB

one more round of bugfixes caused by rename

larowlan’s picture

This looks ok, but leaving for @dawehner to have one last look

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you for the fixes!

andypost’s picture

Title: Introduce HistoryManager service » Introduce HistoryRepository service
Issue summary: View changes
StatusFileSize
new29.47 KB
andypost’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new4.64 KB
new29.71 KB

1) Removed current_user service dependency according #2180109-96: Change the current_user service to a proxy
2) fixed static cache to cache per user.
3) extended service from DependencySerialization to prevent serialization of static cache and database connection
4) filed follow-up for forum manager service #2201659: Fix serialization of the forum manager and dependency on current_user service

andypost’s picture

There's issue with entity_id now according to #2195915-7: Cannot save text filter config using PostgreSQL if Comment is enabled [blocks installation!]
So this kind of storage is fragile, trying to re-think this into field...

otoh this out-of-bound data that does not coupled to entity, that means update of history does not lead to update of entity

larowlan’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC

andypost’s picture

About consistency for entity_id (could be integer or string) suppose we have follow-up #2100203: Make config entities use dots in machine names consistently

Suppose this issue ready, @catch I think for the storage we can at least in 8.0.1 add second table field {bundle_id} with logic return history->id() ?: history->bundle_id

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

2081585-history-service-70.patch no longer applies.

error: patch failed: core/modules/comment/comment.module:568
error: core/modules/comment/comment.module: patch does not apply

andypost’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new29.75 KB
alexpott’s picture

Status: Reviewed & tested by the community » Needs work

2081585-history-service-75.patch no longer applies.

error: patch failed: core/modules/history/history.module:57
error: core/modules/history/history.module: patch does not apply

andypost’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new29.75 KB
sutharsan’s picture

Issue tags: -Needs reroll
catch’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
    @@ -322,24 +333,23 @@ protected function numberNew($nid, $timestamp) {
    @@ -499,7 +509,7 @@ public function checkNodeType(NodeInterface $node) {
    

    This could use an EXPLAIN for the new query, iirc it's pretty bad as it is and this may make it worse.

  2. +++ b/core/modules/history/history.install
    @@ -31,11 +38,19 @@ function history_schema() {
    +        array('entity_type', 32),
    

    Similar to the entity caching issue, we probably want to move to table-per-entity type. This is one of the most frequently written to, read from tables and can have tens of thousands of rows if not more.

  3. +++ b/core/modules/history/lib/Drupal/history/HistoryRepository.php
    @@ -0,0 +1,160 @@
    +    unset($vars['history']);
    

    Why not just $vars['history'] = array() - then we wouldn't need the __wakeup()?

andypost’s picture

It's nice idea about "table-per-entity type" but there's no core api to generate this tables.
Suppose we need to create/drop this tables manually when entity types is defined or make history a configurable field to inherit storage
The same applies to comment table

mgifford’s picture

#1029708: History table for any entity was marked a duplicate of this issue. But it's also in the todo here in Core in comment.module:

/**
 * The time cutoff for comments marked as read for entity types other node.
 *
 * Comments changed before this time are always marked as read.
 * Comments changed after this time may be marked new, updated, or read,
 * depending on their state for the current user. Defaults to 30 days ago.
 *
 * @todo Remove when http://drupal.org/node/1029708 lands.
 */
define('COMMENT_NEW_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60);
joelpittet’s picture

Assigned: catch » Unassigned
Crell’s picture

Issue tags: -WSCCI
Crell’s picture

Version: 8.0.x-dev » 8.1.x-dev
cilefen’s picture

Issue tags: -beta target

I removed the "beta target" tag because this is pushed to 8.1.x.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andypost’s picture

service should be swappable like related issue

jonathanshaw’s picture

This patch stalled 2 years ago on @catch's point:

we probably want to move to table-per-entity type. This is one of the most frequently written to, read from tables and can have tens of thousands of rows if not more.

Is there a reason to block this patch on this point? Would it be better to proceed with this patch and leave table-per-entity for a different issue (by reopening #1029708: History table for any entity as no longer a duplicate)? Does this patch make the lack of table-per-entity worse than it currently is without this patch?

andypost’s picture

Issue tags: +Needs architectural review

there's proper tag

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

nevergone’s picture

And now?

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dillix’s picture

Is there any news with HistoryManager?

nevergone’s picture

I tried again re-roll the patch #77, but not success. Can anyone help me?

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

claudiu.cristea’s picture

jhedstrom’s picture

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

moshe weitzman’s picture

Anyone using this patch in Production? I'm curious how its working for you. Our use case is relatively low volume.

andypost’s picture

@moshe weitzman I used it long ago but then we removed history module at all(

vladbo’s picture

StatusFileSize
new26.97 KB

Re-roll for 8.8.x

vladbo’s picture

StatusFileSize
new31.38 KB
new7.51 KB

Fixed tests and ForumManager constructor.

vladbo’s picture

StatusFileSize
new1.1 KB

Fixed dependencies for some tests

vladbo’s picture

StatusFileSize
new32.98 KB
vladbo’s picture

StatusFileSize
new35.04 KB
new2.65 KB

Added update for scheme which also fixes failed tests.

andypost’s picture

+++ b/core/modules/history/history.install
@@ -98,0 +99,60 @@
+function history_update_8102() {

would be great to start numbering with 8801() because of current version

daffie’s picture

My first quick review:

  1. +++ b/core/modules/comment/comment.module
    @@ -57,17 +57,6 @@
    -/**
    - * The time cutoff for comments marked as read for entity types other node.
    - *
    - * Comments changed before this time are always marked as read.
    - * Comments changed after this time may be marked new, updated, or read,
    - * depending on their state for the current user. Defaults to 30 days ago.
    - *
    - * @todo Remove when https://www.drupal.org/node/1029708 lands.
    - */
    -define('COMMENT_NEW_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60);
    -
    

    This cannot be removed. It must deprecated.

  2. +++ b/core/modules/comment/src/CommentManager.php
    @@ -217,20 +217,8 @@ public function getCountNewComments(EntityInterface $entity, $field_name = NULL,
    +        $timestamp = \Drupal::service('history.repository')->getLastViewed($entity->getEntityTypeId(), array($entity->id()), $this->currentUser);
    

    There are a lot of instances where "array()" is used. Please change it to "[]".

  3. +++ b/core/modules/forum/src/ForumManager.php
    @@ -329,16 +344,14 @@ protected function getTopicOrder($sortby) {
    +    if (isset($this->history[$nid])) {
    +      return $this->history[$nid];
    +    }
    

    I think that this part can be removed.

  4. +++ b/core/modules/history/history.services.yml
    @@ -0,0 +1,4 @@
    +services:
    +  history.repository:
    +    class: Drupal\history\HistoryRepository
    +    arguments: ['@database']
    

    Should this service not be backend overridable?

  5. +++ b/core/modules/history/src/Controller/HistoryController.php
    @@ -14,17 +16,44 @@
    -    if ($this->currentUser()->isAnonymous()) {
    +    $account = $this->currentUser();
    +    if ($account->isAnonymous()) {
    
    @@ -42,16 +71,20 @@ public function getNodeReadTimestamps(Request $request) {
    -    if ($this->currentUser()->isAnonymous()) {
    +    $account = $this->currentUser();
    +    if ($account->isAnonymous()) {
    

    I do not think that these changes are necessary.

vacho’s picture

Issue tags: -Needs reroll
StatusFileSize
new35.32 KB
new5.13 KB

I update the patch #107 solving observations at #108

About observations at #109

  1. I think that it is correctly removed. I don't find any place where is used this.
  2. Solved
  3. It is a validation before do something. If you remove the code made operations without reason
  4. Nothing to do
  5. I am unsure about remove it.
daffie’s picture

For #109.1: Because Drupal core does not use this variable any more does mean that there are contrib or other modules that depend on the variable to be there.

/**
 * The time cutoff for comments marked as read for entity types other node.
 *
 * Comments changed before this time are always marked as read.
 * Comments changed after this time may be marked new, updated, or read,
 * depending on their state for the current user. Defaults to 30 days ago.
 *
 * @deprecated in Drupal 8.8.x and will be removed before Drupal 9.0.0.
 */
define('COMMENT_NEW_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60);

For #109.3: The part can be removed, because right after we test if that variable is empty. If it is empty then we are going to set the variable. After that the value of the variable is returned. The part that you want to add does not help in any way. it only makes the code more complicated. Please remove this change.

For #109.4: The whole idea of this issue is to back history modules database queries swappable. For that to be possible the service needs to be backend overridable. See: https://www.drupal.org/node/2306083.

services:
  history.repository:
    class: Drupal\history\HistoryRepository
    arguments: ['@database']
    tags:
      - { name: backend_overridable }

For #109.5: The value for $this->currentUser() is always set. It can be for an authenticated user or for an anonymous user. Please remove this change.

vladbo’s picture

StatusFileSize
new41.69 KB
new12.14 KB

For #109.1: I've added back define('COMMENT_NEW_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60);
But it's not used in any contrib module.

For #109.3: Fixed.

For #109.4: Fixed.

For #109.5: Fixed.

Also, I've set default value for entity_type column in history table as 'node'.

vladbo’s picture

StatusFileSize
new34.15 KB
new9.23 KB

- Removed rejected changes after applying patch;
- Fixed hook_update_N id as it was said in #108;
- Some minor fixes;

vladbo’s picture

StatusFileSize
new665 bytes
new34.92 KB

Updated lazyBuilder callback.

daffie’s picture

My second review:

  1. +++ b/core/modules/comment/src/CommentManager.php
    @@ -217,20 +217,8 @@ public function getCountNewComments(EntityInterface $entity, $field_name = NULL,
    +        $timestamp = \Drupal::service('history.repository')->getLastViewed($entity->getEntityTypeId(), [$entity->id()], $this->currentUser);
    

    Can we change the variable name to $timestamps. To make clear that it is an array of timestamps and not a single timestamp.

  2. In the function history_update_8801() uses several field and table definitions. Can we use the definition from history_schema(). Single source for the table and field definitions.
  3. I am not a 100 % sure, but I think there needs to be a specific test for the update from the function history_update_8801().
  4. +++ b/core/modules/comment/tests/src/Functional/CommentLinksTest.php
    @@ -77,6 +77,10 @@ public function testCommentLinks() {
    +    // comment_num_new() relies on history_read(), so ensure that no one has
    +    // seen the node of this comment.
    +    \Drupal::service('history.repository')->deleteByEntity($this->node);
    +
    

    Just to be sure. If you remove this change the test will fail? Also, I am unable to find the function comment_num_new().

  5. +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,164 @@
    +    $return = [];
    ...
    +        $return[$entity_id] = $this->history[$entity_type][$account->id()][$entity_id];
    ...
    +      return $return;
    ...
    +    return $return + $entities_to_read;
    

    Can we rename the variable $return to something more descriptive like $entities. If you have a better idea that would be great.

  6. +++ b/core/modules/history/src/HistoryRepositoryInterface.php
    @@ -0,0 +1,71 @@
    +   * Deletes history of the user account.
    

    Maybe better: "Deletes the history for the given user account."

andypost’s picture

#115.2 update hook must never use schema which may change over time and could gone to service with ensureTable like few other core services doing

vladbo’s picture

StatusFileSize
new36.53 KB
new7.93 KB

1. Fixed.
4. Removed as it doesn't affect on test.
5. Fixed.
6. Fixed.

jonathanshaw’s picture

So all review points adressed except #115.3:

a specific test for the update from the function history_update_8801().

and #79.1 and #79.3

daffie’s picture

I would like to state that I agree with @andypost’s point from comment #116.

The patch looks good to me. What I still mis is a specific update test for the function history_update_8801().
There is documentation for how to write such a test. See: https://www.drupal.org/docs/8/api/update-api/writing-automated-update-te....

vladbo’s picture

StatusFileSize
new3.63 KB
new39.46 KB

Added test for function history_update_8801() and fixed failed tests.

vladbo’s picture

Green now.
Regarding #79:
#79.1 - I don't get what should be changed.
#79.3 - The same thing is used in ForumManager.php and TermStorage.php. Do we really need to change it?

daffie’s picture

Issue summary: View changes
Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs issue summary update

Thank you @Vlad Bo for adding the update test.
The issue summary is updated.
The patch is now RTBC for me.

The architectural review needs to be done by a core committer.

catch’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/history/history.install
@@ -6,22 +6,30 @@
+        'default' => 'node',

I don't think 'node' should be the default in the actual schema definition if we're trying to make the module entity-type agnostic.

  1. +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,175 @@
    +   * Array of history keyed by entity type and entity id.
    

    nit: ID.

  2. +++ b/core/modules/history/src/HistoryRepositoryInterface.php
    @@ -0,0 +1,71 @@
    +  public function resetCache();
    

    Does this need to be in the interface?

    Also the protected property here would be a good case for #3047289: Standardize how we implement in-memory caches. We're already using this for some other services.

voleger’s picture

Seems you would not define the default field value so you will fill the value of entity_type field once after the field updates. I suggest moving that insert operation in the separate hook_update_N implementation.

vladbo’s picture

StatusFileSize
new2.57 KB
new39.55 KB

#123.1 - fixed.
#123.2 - removed.

Default value for entity_type field was removed and update query was added to set it.

vladbo’s picture

Status: Needs work » Needs review
daffie’s picture

Status: Needs review » Needs work

I am missing in the update test that the value of the column entity_type is equal to "node".

edit: @Vlad Bo: The changes that you made look good to me.

vladbo’s picture

StatusFileSize
new970 bytes
new39.8 KB

Added check for entity_type value in update test.

daffie’s picture

Status: Needs work » Reviewed & tested by the community

All the points from @catch are fixed. Back to RTBC.

The architectural review needs to be done by a core committer.

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: -Needs architectural review +Needs framework manager review
+++ b/core/modules/history/src/HistoryRepository.php
@@ -0,0 +1,175 @@
+  /**
+   * {@inheritdoc}
+   */
+  public function resetCache() {
+    $this->history = [];
+  }

This is no-longer in the interface but it still has @inheritdoc. I think we should use a memory cache implementation straight off here, which would also allow us to remove this as well as the the __sleep() and __wakeup() methods.

vladbo’s picture

StatusFileSize
new40.96 KB
new6.76 KB

Removed resetCache method and added memory cache implementation.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

vladbo’s picture

StatusFileSize
new1.3 KB
new40.82 KB

Fixed loading timestamp from cache

vladbo’s picture

StatusFileSize
new1.05 KB
new41.47 KB

One more fix for tests

vladbo’s picture

Status: Needs work » Needs review
daffie’s picture

Status: Needs review » Needs work

Everything that @catch asked for has been added to the patch.

I have 2 minor issues left for the patch:

  1. +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,189 @@
    +        $this->time->getRequestTime(), Cache::PERMANENT,
    

    Minor: This needs to be on two lines.

  2. +++ b/core/modules/comment/comment.module
    @@ -65,7 +65,7 @@
    + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0.
    

    I do not think that this patch will land in 8.8.

Thanks @Vlad Bo for your work on this patch.

andypost’s picture

It looks mostly ready, just not sure it fits into 8.8 or 8.9 but that's framework manager review

  1. +++ b/core/modules/comment/comment.module
    @@ -65,7 +65,7 @@
    - * @todo Remove when https://www.drupal.org/node/1029708 lands.
    + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0.
    

    It needs pointed to what use instead and change record link

  2. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -205,7 +205,8 @@ public function buildCommentedEntityLinks(FieldableEntityInterface $entity, arra
    -          $entity_links['comment__' . $field_name]['#attached']['drupalSettings']['history']['lastReadTimestamps'][$entity->id()] = (int) history_read($entity->id());
    +          $timestamps = \Drupal::service('history.repository')->getLastViewed($entity->getEntityTypeId(), [$entity->id()], $this->currentUser);
    

    Builder should inject history repository service

  3. +++ b/core/modules/comment/src/CommentManager.php
    @@ -217,20 +217,8 @@ public function getCountNewComments(EntityInterface $entity, $field_name = NULL,
    +        $timestamp = \Drupal::service('history.repository')->getLastViewed($entity->getEntityTypeId(), [$entity->id()], $this->currentUser);
    

    Nice clean-up but it adds one more optional dependency to comment manager and I'm ok to resurect #2188287: Split CommentManager in two

  4. +++ b/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php
    @@ -87,6 +88,16 @@ protected function setUp() {
    +    $history_repository = $this->getMockBuilder('Drupal\history\HistoryRepositoryInterface')
    

    could use HistoryRepositoryInterface::class

  5. +++ b/core/modules/forum/src/ForumManager.php
    @@ -147,6 +157,11 @@ public function __construct(ConfigFactoryInterface $config_factory, EntityTypeMa
    +      @trigger_error('The history.repository service must be passed to ForumManager::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/2081585.', E_USER_DEPRECATED);
    

    new format is bit different - could be fixed on reroll

  6. +++ b/core/modules/forum/tests/src/Unit/ForumManagerTest.php
    @@ -56,6 +56,10 @@ public function testGetIndex() {
    +    $history_repository = $this->getMockBuilder('\Drupal\history\HistoryRepository')
    

    HistoryRepository::class

  7. +++ b/core/modules/history/src/HistoryRepositoryInterface.php
    @@ -0,0 +1,79 @@
    +  public function deleteByUser(AccountInterface $account);
    ...
    +  public function deleteByEntity(EntityInterface $entity);
    

    it looks like this methods could throw exceptions so needs to document

vladbo’s picture

Issue tags: +LutskGCW20
vladbo’s picture

StatusFileSize
new46.41 KB
new9.03 KB

Mostly fixed:

  • #137.1 - fixed
  • #137.2 - fixed
  • #137.3 - added dependency, need to be split in #2188287: Split CommentManager in two
  • #137.4 - fixed
  • #137.5 - fixed
  • #137.6 - fixed
  • #137.7 - seems like nothing to be thrown
longwave’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 139: 2081585-139.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

vladbo’s picture

StatusFileSize
new6.86 KB
new49.43 KB

Fixed fails, changed format of trigger_error messages and added dependency in comment module.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

ridhimaabrol24’s picture

Status: Needs work » Needs review
StatusFileSize
new56.19 KB

Rerolling patch for 9.1.x and trying to fix test cases.

Status: Needs review » Needs work

The last submitted patch, 144: 2081585-144.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

ridhimaabrol24’s picture

Status: Needs work » Needs review
StatusFileSize
new96.55 KB
new41.01 KB

Fixing test cases!

Status: Needs review » Needs work

The last submitted patch, 146: 2081585-146.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

voleger’s picture

Status: Needs work » Needs review
StatusFileSize
new97.29 KB
new1.87 KB

Keeping fix the tests.
Fixed the fixture location definition in the update test.
Added missing schema installation calls in failing tests.

Status: Needs review » Needs work

The last submitted patch, 148: 2081585-148.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

nevergone’s picture

StatusFileSize
new89.61 KB
new6.15 KB

Patch re-rolled and manual fixed.

nevergone’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 150: 2081585-150.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

nevergone’s picture

Status: Needs work » Needs review
StatusFileSize
new91.46 KB
new3.34 KB

Fix test dependencies and code style.

Status: Needs review » Needs work

The last submitted patch, 153: 2081585-153.patch, failed testing. View results

nevergone’s picture

Status: Needs work » Needs review
StatusFileSize
new91.75 KB
new542 bytes

fix CommentLinkBuilderTest()

nevergone’s picture

EverGreen!
Please test, review and feedback!

nevergone’s picture

Please test and review, thanks!

voleger’s picture

Status: Needs review » Needs work
+++ b/core/modules/comment/comment.module
@@ -35,7 +35,10 @@
+ * @deprecated in drupal:8.9.0 and is removed from drupal:9.0.0.
+ *   No replacement is provided.

The versions needs to be updated.

nevergone’s picture

Status: Needs work » Needs review
StatusFileSize
new91.75 KB
new556 bytes

Fix deprecation comment.

voleger’s picture

+1 for RTBC

andypost’s picture

StatusFileSize
new13.34 KB
new91.91 KB

I think it's not yet ready, because usage of "current user" and history module enabled needs more clean-up

Most of places accessing history only when module enabled and current user is authenticated, that's why I removed account as argument from repository.

I think it needs special api method to return access for current user to api, but maybe it could be done in follow-up
Also the split of arguments for entity type and IDs are confusing - we can't apply type-hint to entity ID[s] as they could be strings or integers

The patch starts it, also using local variables to minimize entity api calls in implementation

  1. +++ b/core/modules/comment/src/CommentManager.php
    @@ -201,20 +216,8 @@ public function getCountNewComments(EntityInterface $entity, $field_name = NULL,
    -          $function = $entity->getEntityTypeId() . '_last_viewed';
    -          if (function_exists($function)) {
    -            $timestamp = $function($entity->id());
    
    +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,189 @@
    +    foreach ($result as $row) {
    +      $timestamp = (int) $row->timestamp;
    

    there's no runtime hook to override last viewed, needs to mention in CR

  2. +++ b/core/modules/history/history.module
    @@ -60,37 +66,13 @@ function history_read($nid) {
    +  return \Drupal::service('history.repository')->getLastViewed('node', $nids, \Drupal::currentUser());
    
    +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,189 @@
    +  public function getLastViewed($entity_type, array $entity_ids, AccountInterface $account) {
    ...
    +        $this->buildCacheId($account->id(), $entity_type, $entity_id
    ...
    +      ->condition('uid', $account->id())
    

    Not sure account itself should be passed as only $user_id used

  3. +++ b/core/modules/history/history.module
    @@ -98,37 +80,28 @@ function history_read_multiple($nids) {
    -function history_write($nid, $account = NULL) {
    +function history_write($nid, AccountInterface $account = NULL) {
    ...
    +  \Drupal::service('history.repository')->updateLastViewed($node, $account);
    
    +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,189 @@
    +  public function updateLastViewed(EntityInterface $entity, AccountInterface $account) {
    +    if ($account->isAuthenticated()) {
    ...
    +          'uid' => $account->id(),
    ...
    +        $this->buildCacheId($account->id(), $entity->getEntityTypeId(), $entity->id()),
    ...
    +        $this->getCacheTags($account->id(), $entity->id())
    

    update using ID and authenticated but can skip

andypost’s picture

StatusFileSize
new585 bytes
new91.93 KB

missed to return value

The last submitted patch, 161: 2081585-161.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

paulocs’s picture

StatusFileSize
new9.84 KB
new82.01 KB

Fixing code standard.

Please, not consider the files attached here. See comment #165.

paulocs’s picture

StatusFileSize
new498 bytes
new92 KB

Ops, patch and interdiff on comment #164 are wrong.
I'm attaching the right files.

paulocs’s picture

The last submitted patch, 164: 2081585-164.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 165: 2081585-165.patch, failed testing. View results

nevergone’s picture

Status: Needs work » Needs review

Green, please review!

longwave’s picture

+++ b/core/modules/comment/comment.info.yml
@@ -5,4 +5,5 @@ package: Core
+  - drupal:history

Should comment really depend on history? Can we make this optional, as it was before?

nevergone’s picture

StatusFileSize
new210 bytes
new91.67 KB

Status: Needs review » Needs work

The last submitted patch, 171: 2081585-171.patch, failed testing. View results

nevergone’s picture

Status: Needs work » Needs review
StatusFileSize
new89.16 KB
new9.32 KB

history.repository is a optional service.

andypost’s picture

Status: Needs review » Needs work

@nevergone looks great! just needs to deal with deprecation and few nitpicks

  1. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -71,6 +79,17 @@ public function __construct(AccountInterface $current_user, CommentManagerInterf
    +   * Set the history repository service.
    +   * @see https://www.drupal.org/node/2081585
    +   *
    +   * @param \Drupal\history\HistoryRepositoryInterface $history_repository
    +   *   The history repository service.
    
    +++ b/core/modules/comment/src/CommentManager.php
    @@ -102,6 +110,17 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Con
    +   * Set the history repository service.
    +   * @see https://www.drupal.org/node/2081585
    +   *
    +   * @param \Drupal\history\HistoryRepositoryInterface $history_repository
    +   *   The history repository service.
    

    Needs fix for CS

  2. +++ b/core/modules/comment/src/CommentManager.php
    @@ -92,7 +100,7 @@ class CommentManager implements CommentManagerInterface {
    -  public function __construct(EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, TranslationInterface $string_translation, ModuleHandlerInterface $module_handler, AccountInterface $current_user, EntityFieldManagerInterface $entity_field_manager, EntityDisplayRepositoryInterface $entity_display_repository) {
    +  public function __construct(EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, TranslationInterface $string_translation, ModuleHandlerInterface $module_handler, AccountInterface $current_user, EntityFieldManagerInterface $entity_field_manager, EntityDisplayRepositoryInterface $entity_display_repository, HistoryRepositoryInterface $history_repository = NULL) {
    

    it needs clean-up cos constructor no longer changing

  3. +++ b/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php
    @@ -72,9 +80,10 @@ protected function setUp(): void {
    -    $this->commentLinkBuilder = new CommentLinkBuilder($this->currentUser, $this->commentManager, $this->moduleHandler, $this->stringTranslation, $this->entityTypeManager);
    +    $this->commentLinkBuilder = new CommentLinkBuilder($this->currentUser, $this->commentManager, $this->moduleHandler, $this->stringTranslation, $this->entityTypeManager, $this->historyRepository);
    
    @@ -87,6 +96,9 @@ protected function setUp(): void {
    +    $this->historyRepository->expects($this->any())
    

    it should use setter instead of that, moreover as it passed - the test works wrong!
    I think $this->any() must be replaced with $this->atLeastOnce()

  4. +++ b/core/modules/comment/tests/src/Unit/CommentManagerTest.php
    @@ -34,6 +35,7 @@ public function testGetFields() {
    +    $history_repository = $this->createMock(HistoryRepositoryInterface::class);
    
    @@ -49,6 +51,10 @@ public function testGetFields() {
    +    $history_repository->expects($this->any())
    +      ->method('getLastViewed')
    
    @@ -56,7 +62,8 @@ public function testGetFields() {
    -      $this->prophesize(EntityDisplayRepositoryInterface::class)->reveal()
    +      $this->prophesize(EntityDisplayRepositoryInterface::class)->reveal(),
    +      $history_repository
    

    the same here - use setter instead of constructor

  5. +++ b/core/modules/history/history.install
    @@ -5,21 +5,31 @@
    +      'entity_type' => [
    +        'description' => 'The type of the entity that was read.',
    +        'type' => 'varchar_ascii',
    +        'not null' => TRUE,
    +        'default' => '',
    +        'length' => EntityTypeInterface::ID_MAX_LENGTH,
    
    @@ -47,3 +57,70 @@ function history_schema() {
    +  $schema->addField('history', 'entity_type', [
    +    'description' => 'The type of the entity that was read.',
    +    'type' => 'varchar_ascii',
    +    'not null' => TRUE,
    +    'default' => '',
    +    'length' => EntityTypeInterface::ID_MAX_LENGTH,
    +  ]);
    +
    +  // Set default value for {history}.entity_type.
    +  $database->update('history')
    +    ->fields(['entity_type' => 'node'])
    +    ->execute();
    ...
    +      'entity_type' => [
    +        'description' => 'The type of the entity that was read.',
    +        'type' => 'varchar_ascii',
    +        'not null' => TRUE,
    +        'default' => '',
    +        'length' => EntityTypeInterface::ID_MAX_LENGTH,
    

    any reason for not-null when default is empty string?

  6. +++ b/core/modules/history/history.install
    @@ -47,3 +57,70 @@ function history_schema() {
    + * Change {history}.nid to {history}.entity_id and add {history}.entity_type.
    + */
    +function history_update_9001() {
    

    maybe it should be 9101?

  7. +++ b/core/modules/history/history.module
    @@ -44,10 +46,14 @@ function history_help($route_name, RouteMatchInterface $route_match) {
    + * @deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use
    + *   \Drupal\history\HistoryRepositoryInterface::getLastViewed() instead.
    + * @see https://www.drupal.org/node/2197189
    ...
     function history_read($nid) {
    -  $history = history_read_multiple([$nid]);
    -  return $history[$nid];
    +  $timestamps = \Drupal::service('history.repository')->getLastViewed('node', [$nid]);
    

    needs to fix CS (empty line before @see)

    Also as deprecation policy states to trigger and add deprecation test https://www.drupal.org/about/core/policies/core-change-policies/drupal-c...

    Moreover would be great to file follow-up issue against D10 to remove it

  8. +++ b/core/modules/history/history.module
    @@ -60,37 +66,13 @@ function history_read($nid) {
    + * @deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use
    + *   \Drupal\history\HistoryRepositoryInterface::getLastViewed() instead.
    + * @see https://www.drupal.org/node/2197189
    ...
     function history_read_multiple($nids) {
    
    @@ -98,27 +80,23 @@ function history_read_multiple($nids) {
    + * @deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use
    + *   \Drupal\history\HistoryRepositoryInterface::updateLastViewed() instead.
    + * @see https://www.drupal.org/node/2197189
      */
    -function history_write($nid, $account = NULL) {
    +function history_write($nid, AccountInterface $account = NULL) {
    

    same here

nevergone’s picture

Status: Needs work » Needs review
StatusFileSize
new92.15 KB
new11.21 KB
nevergone’s picture

StatusFileSize
new92.07 KB
new10.95 KB

Fix database schema

andypost’s picture

Great to see this changes, will check at morning

Status: Needs review » Needs work

The last submitted patch, 176: 2081585-176.patch, failed testing. View results

nevergone’s picture

Status: Needs work » Needs review
StatusFileSize
new88.2 KB
new6.63 KB
longwave’s picture

Status: Needs review » Needs work

The changes look pretty good to me, a couple of things I spotted:

  1. +++ b/core/modules/history/history.module
    @@ -44,10 +46,16 @@ function history_help($route_name, RouteMatchInterface $route_match) {
    +  @trigger_error('history_read() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use \Drupal\history\HistoryRepositoryInterface::getLastViewed() instead. See https://www.drupal.org/node/2197189', E_USER_DEPRECATED);
    

    This needs a deprecation test.

  2. +++ b/core/modules/history/history.module
    @@ -60,37 +68,14 @@ function history_read($nid) {
    +  @trigger_error('history_read_multiple() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use \Drupal\history\HistoryRepositoryInterface::getLastViewed() instead. See https://www.drupal.org/node/2197189', E_USER_DEPRECATED);
    

    This also needs a deprecation test.

  3. +++ b/core/modules/history/history.module
    @@ -98,27 +83,23 @@ function history_read_multiple($nids) {
    -function history_write($nid, $account = NULL) {
    +function history_write($nid, AccountInterface $account = NULL) {
    

    This needs @trigger_error and a deprecation test. Also should we be changing the signature here?

andypost’s picture

nevergone’s picture

Please little help me because history_read() and history_read_multiple() are not tested currently. Thanks!

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new4.93 KB
new91.01 KB

Here's legacy test and few nitpicks

andypost’s picture

  1. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -213,7 +213,7 @@
    -        if ($view_mode == 'teaser' && $this->currentUser->isAuthenticated() && $this->historyRepository) {
    +        if ($view_mode == 'teaser' && $this->historyRepository && $this->currentUser->isAuthenticated()) {
    

    the order of execution reverted to original - no reason to do fiunction call if history missing

  2. +++ b/core/modules/history/history.module
    @@ -83,15 +83,17 @@
    - * @param \Drupal\Core\Session\AccountInterface $account
    + * @param $account
    ...
    -function history_write($nid, AccountInterface $account = NULL) {
    +function history_write($nid, $account = NULL) {
    

    I did revert it because
    - out of scope
    - formal API change

  3. +++ b/core/modules/node/node.module
    @@ -193,7 +193,7 @@ function node_mark($nid, $timestamp) {
    -    $cache[$nid] = history_read($nid);
    +    $cache[$nid] = \Drupal::service('history.repository')->getLastViewed('node', $nid);
    

    remaining legacy usage

nevergone’s picture

Oh, thanks! I also learned something today! :)

longwave’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, this looks ready to go now.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockContentTranslationTest.php
    @@ -23,6 +23,7 @@ class MigrateBlockContentTranslationTest extends MigrateDrupal7TestBase {
    +    'history',
    

    I'm really not sure that having to add the history module to all these tests is a viable approach. Why is this necessary?

  2. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -71,6 +79,18 @@ public function __construct(AccountInterface $current_user, CommentManagerInterf
    +   * @see https://www.drupal.org/node/2081585
    
    +++ b/core/modules/comment/src/CommentManager.php
    @@ -102,6 +110,18 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Con
    +   * @see https://www.drupal.org/node/2081585
    

    What is this here for? Pointing to the issue that adds this is not useful.

  3. +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,205 @@
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function getLastViewed($entity_type, array $entity_ids) {
    
    +++ b/core/modules/history/src/HistoryRepositoryInterface.php
    @@ -0,0 +1,72 @@
    +  /**
    +   * Retrieves the timestamp for the current user's last view of the entities.
    +   *
    +   * @param string $entity_type
    +   *   The entity type.
    +   * @param array $entity_ids
    +   *   The entity IDs.
    +   *
    +   * @return array
    +   *   Array of timestamps keyed by entity ID. If a entity has been previously
    +   *   viewed by the user, the timestamp in seconds of when the last view
    +   *   occurred; otherwise, zero.
    +   */
    +  public function getLastViewed($entity_type, array $entity_ids);
    

    We should have a string typehint and a return type hint here.

  4. +++ b/core/modules/history/src/HistoryRepositoryInterface.php
    @@ -0,0 +1,72 @@
    +   * @return self
    +   */
    +  public function updateLastViewed(EntityInterface $entity);
    ...
    +   * @return string[]
    +   *   An array of cache tags based on the current view.
    +   */
    +  public function getCacheTags($uid, $entity_id);
    ...
    +   * @param \Drupal\Core\Session\AccountInterface $account
    +   *   The user account to purge history.
    +   */
    +  public function deleteByUser(AccountInterface $account);
    ...
    +   * @param \Drupal\Core\Entity\EntityInterface $entity
    +   *   The entity that history should be deleted.
    +   */
    +  public function deleteByEntity(EntityInterface $entity);
    

    Need return typehints.

alexpott’s picture

  1. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -71,6 +79,18 @@ public function __construct(AccountInterface $current_user, CommentManagerInterf
    +  /**
    +   * Set the history repository service.
    +   *
    +   * @param \Drupal\history\HistoryRepositoryInterface $history_repository
    +   *   The history repository service.
    +   *
    +   * @see https://www.drupal.org/node/2081585
    +   */
    +  public function setHistoryRepositoryService(HistoryRepositoryInterface $history_repository) {
    +    $this->historyRepository = $history_repository;
    +  }
    

    Why are we using setter injection over constructor injection?

  2. +++ b/core/modules/comment/src/CommentManager.php
    @@ -196,25 +216,11 @@ public function forbiddenMessage(EntityInterface $entity, $field_name) {
    -          $function = $entity->getEntityTypeId() . '_last_viewed';
    -          if (function_exists($function)) {
    -            $timestamp = $function($entity->id());
    -          }
    

    This needs documenting in the CR. Also this functionality we pretty undocumented and does not look to be used by contrib. But a custom implementation on a site will break after this change.

  3. +++ b/core/modules/comment/tests/src/Kernel/CommentBaseFieldTest.php
    @@ -22,6 +22,7 @@ class CommentBaseFieldTest extends KernelTestBase {
    +    'history',
    

    I've reverted this change and the test still passes. I guess the change to add this to all tests was done prior to adding a way to only add the history repository if it exists.

  4. function comment_views_data_alter(&$data) {
      // New comments are only supported for node table because it requires the
      // history table.
      $data['node']['new_comments'] = [
    

    This comment is now incorrect. So I guess we need a follow-up to expand what the new comments thing is attached to. Also this has a implicit dependency on the history module that's not managed very well.

alexpott’s picture

  1. +++ b/core/modules/forum/forum.services.yml
    @@ -2,6 +2,8 @@ services:
    +    calls:
    +      - [setHistoryRepositoryService, ['@?history.repository']]
    
    +++ b/core/modules/forum/src/ForumManager.php
    @@ -138,6 +146,17 @@ public function __construct(ConfigFactoryInterface $config_factory, EntityTypeMa
    +  /**
    +   * Set the history repository service.
    +   * @see https://www.drupal.org/node/2081585
    +   *
    +   * @param \Drupal\history\HistoryRepositoryInterface $history_repository
    +   *   The history repository service.
    +   */
    +  public function setHistoryRepositoryService(HistoryRepositoryInterface $history_repository) {
    +    $this->historyRepository = $history_repository;
    +  }
    

    The forum module depends on history. This service should definitely be injected into the constructor and do the deprecation dance because it is mandatory.

  2. +++ b/core/modules/forum/src/ForumManager.php
    @@ -318,16 +337,13 @@ protected function getTopicOrder($sortby) {
       protected function lastVisit($nid, AccountInterface $account) {
    +    if ($this->historyRepository) {
    +      $this->history += $this->historyRepository->getLastViewed('node', [$nid]);
    +    }
         if (empty($this->history[$nid])) {
    -      $result = $this->connection->select('history', 'h')
    -        ->fields('h', ['nid', 'timestamp'])
    -        ->condition('uid', $account->id())
    -        ->execute();
    -      foreach ($result as $t) {
    -        $this->history[$t->nid] = $t->timestamp > HISTORY_READ_LIMIT ? $t->timestamp : HISTORY_READ_LIMIT;
    -      }
    ...
         }
    -    return isset($this->history[$nid]) ? $this->history[$nid] : HISTORY_READ_LIMIT;
    +    return $this->history[$nid];
       }
    

    The changes here are a performance regression. Prior to the change it was only doing a read when it hadn't before.

longwave’s picture

Re #188.1 we need setter injection here because history is not a dependency of comment and might not be enabled, iirc you can't do constructor injection with optional services in Symfony?

andypost’s picture

Assigned: Unassigned » andypost

Working on to get rid of setter, optional services should work https://symfony.com/doc/current/service_container/optional_dependencies....

on #189.2 - repository should care about caching (guess memory cache) but that could use follow-up

Meantime I'm not sure the change fits into beta target, as it adds new API and deprecates
So I think about removal of hook_schema here at all for implementation of storage based on core's keyvalue.expirable

Having separate collection per entity type looks less API surface and easy to scale using redis/keydb existing modules

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
@@ -154,6 +154,10 @@ function setEnvironment(array $info) {
+        // comment_num_new() relies on history_read(), so ensure that no one has
+        // seen the node of this comment.
+        $this->container->get('history.manager')->deleteByEntity('node', $this->node->id());

+++ b/core/modules/forum/forum.services.yml
@@ -1,7 +1,8 @@
+    # The history.manager service is optional to allow upgrade path.
+    arguments: ['@config.factory', '@plugin.manager.entity', '@database', '@field.info', '@string_translation', '@?history.manager']

+++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
@@ -122,13 +130,16 @@ class ForumManager implements ForumManagerInterface {
-  public function __construct(ConfigFactory $config_factory, EntityManager $entity_manager, Connection $connection, FieldInfo $field_info, TranslationInterface $translation_manager) {
+  public function __construct(ConfigFactory $config_factory, EntityManager $entity_manager, Connection $connection, FieldInfo $field_info, TranslationInterface $translation_manager, HistoryManagerInterface $history_manager = NULL) {

It was suggested initially #17

andypost’s picture

Assigned: andypost » Unassigned
Status: Needs work » Needs review
StatusFileSize
new13.3 KB
new93.74 KB

Patch should address type hints and service injection

I think only \Drupal\comment\Plugin\views\field\NodeNewComments::preRender() makes query using history table without check that history enabled, and that's why all this fixes in tests appeared

Tests classes (40kb interdiff) is comment #146

PS: I set HistoryRepositoryInterface as return type for updateLastViewed() because self works only since PHP 7.4

alexpott’s picture

Status: Needs review » Needs work

@andypost I removed it from one test and it still passed. This change should not make the history module necessary for all these tests. That part of the patch needs to be reverted and fixed.

Re #190 ah I see. I wonder if we should try to invert or decouple the dependency stuff.

  1. +++ b/core/modules/comment/src/CommentManager.php
    @@ -196,25 +216,11 @@ public function forbiddenMessage(EntityInterface $entity, $field_name) {
    -            $timestamp = COMMENT_NEW_LIMIT;
    

    COMMENT_NEW_LIMIT is no longer used.

  2. +++ b/core/modules/comment/src/CommentManager.php
    @@ -196,25 +216,11 @@ public function forbiddenMessage(EntityInterface $entity, $field_name) {
           $timestamp = ($timestamp > HISTORY_READ_LIMIT ? $timestamp : HISTORY_READ_LIMIT);
    

    This couples comment to the history module. Did we consider dispatching an event instead of setting a history service.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new46.67 KB
new48.61 KB

Only forum require history dependency (maybe we should replace setter with optional argument)

Patch does clean-up of history dependencies in tests

alexpott’s picture

+++ b/core/modules/forum/forum.services.yml
@@ -2,6 +2,8 @@ services:
+    calls:
+      - [setHistoryRepositoryService, ['@history.repository']]

Forum depends on history - I don't see why we need setter inject here. This can be a normal constructor argument.

Status: Needs review » Needs work

The last submitted patch, 194: 2081585-193.patch, failed testing. View results

longwave’s picture

+++ b/core/modules/comment/comment.services.yml
@@ -7,7 +7,7 @@ services:
+    arguments: ['@entity_type.manager', '@config.factory', '@string_translation', '@module_handler', '@current_user', '@entity_field.manager', '@entity_display.repository', '@?history.repository']

Oh I thought from reading https://symfony.com/doc/current/service_container/optional_dependencies.... that this didn't work in YAML:

You can use the null strategy to explicitly set the argument to null if the service does not exist:

Note

The “null” strategy is not currently supported by the YAML driver.

but now I see

If the argument to the method call is a collection of arguments and any of them is missing, those elements are removed but the method call is still made with the remaining elements of the collection.

I think this means that if we need to inject another new service here in the future, it will be more tricky, but I guess we can deal with that if/when it happens.

andypost’s picture

StatusFileSize
new2.26 KB
new50.87 KB

I applied for issue forks and meantime fix for failed tests

Leaving NW as it needs deprecation fix for forum manager

Also wanna explore tempstore way in issue fork

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

nevergone’s picture

9.2.x??? :((((

nevergone’s picture

Is there a realistic chance of you getting to the 9.1.0?

nevergone’s picture

StatusFileSize
new50.6 KB
nevergone’s picture

Status: Needs work » Needs review

Please testbot, needs review. :)

andypost’s picture

Bot failed on new code styles pre checks

daffie’s picture

And which one should be reviewed? The patch or the MR?

longwave’s picture

Status: Needs review » Needs work

The patch in #204 has some formatting issues, and the MR has deprecations referring to 9.1.x but these will need to be bumped to 9.2.x now. Not sure which of the patch and MR is most up to date here.

andypost’s picture

Status: Needs work » Needs review

Updated MR and fixed it for 9.2

  1. +++ b/core/modules/comment/comment.module
    @@ -35,7 +35,10 @@
    + * @deprecated in drupal:9.1.0 and is removed from drupal:10.0.0.
    
    +++ b/core/modules/history/history.module
    @@ -44,10 +45,16 @@ function history_help($route_name, RouteMatchInterface $route_match) {
    ++ * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use
    
    +++ b/core/modules/history/tests/src/Kernel/HistoryLegacyTest.php
    @@ -0,0 +1,61 @@
    +    $this->expectDeprecation('history_write() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use \Drupal\history\HistoryRepositoryInterface::updateLastViewed() instead. See https://www.drupal.org/node/2197189');
    ...
    +    $this->expectDeprecation('history_read() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use \Drupal\history\HistoryRepositoryInterface::getLastViewed() instead. See https://www.drupal.org/node/2197189');
    ...
    +    $this->expectDeprecation('history_read_multiple() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use \Drupal\history\HistoryRepositoryInterface::getLastViewed() instead. See https://www.drupal.org/node/2197189');
    

    fixed deprecation

  2. +++ b/core/modules/history/history.module
    @@ -44,10 +45,16 @@ function history_help($route_name, RouteMatchInterface $route_match) {
    ++ *   \Drupal\history\HistoryRepositoryInterface::getLastViewed() instead.
    

    patch is broken

andypost’s picture

StatusFileSize
new52.31 KB

For some reason CI fails, trying as a patch from last rebase

drumm made their first commit to this issue’s fork.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

daffie’s picture

Status: Needs review » Needs work

The patch looks good. A couple of minor points:

  1. +++ b/core/modules/comment/src/CommentManager.php
    @@ -196,25 +207,11 @@ public function forbiddenMessage(EntityInterface $entity, $field_name) {
    -          $function = $entity->getEntityTypeId() . '_last_viewed';
    -          if (function_exists($function)) {
    -            $timestamp = $function($entity->id());
    -          }
    

    Technically we are doing a BC here. Only when I do a search on http://grep.xnddx.ru/search?text=_last_viewed&filename=, nobody is making use of the functionality.

  2. +++ b/core/modules/history/history.module
    @@ -44,10 +45,16 @@ function history_help($route_name, RouteMatchInterface $route_match) {
    + * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use
    

    I think we missed the 9.2 release window, therefore it should be changed to 9.3.

  3. +++ b/core/modules/history/history.install
    @@ -47,3 +56,68 @@ function history_schema() {
    +function history_update_9101() {
    

    This needs to be updated to 9.3.

  4. +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,198 @@
    +        $time, Cache::PERMANENT,
    

    The variable both need their own line.

  5. +++ b/core/modules/history/src/HistoryRepository.php
    @@ -0,0 +1,198 @@
    +      $time = $this->time->getRequestTime();
    

    Can we change the variable name to $timestamp to be in line with the other ones in this file.

andypost’s picture

Unpublished patch as MR used and rebased it against 9.3.x

berdir’s picture

This is a tough one. It's mixing making this a service, with restructuring the storage, caching with a memory cache service all in a single issue. No wonder this has been going since 2013 ;)

First, not fond of the cache tags. The entity cache tag is actually missing the entity type so that's kinda broken and both entity and user cache tags are only invalidated if a user or entity is deleted. That's pointless as nobody is going to request that information then. If we want to use a memory cache for this and not just a protected property (why, exactly?) then this actually seems like a good case to instantiate a separate bin and _not_ misuse the entity service, then you can just deleteAll() and be done with it.

Unsure about the storage changes. We can't add add the service now and add support for other entity types later, that's clear, but it makes what should be a fairly trivial issue many times as complicated. Kinda serious suggestion: Keep the API, but the default implementation would throw an exception on anything but node being passed in. Then either contrib or a follow-up issue later on could fill in the gaps.

nevergone’s picture

What can be done to move this forward?

andypost’s picture

I like steps in #216 - let's split it somehow

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

jonathanshaw’s picture

#161 Most of places accessing history only when module enabled and current user is authenticated, that's why I removed account as argument from repository.

I disagree with this reason, it severely limits the functioning of the API for very little benefit. I have a custom use case that needs to specify the user.

jonathanshaw’s picture

berdir’s picture

I'm not sure if you can split the first 3 tasks like that. That would result in a parallel API that is not used yet, which would in turn also require duplicated tests. Likely makes sense to introduce the service, replace all current usages and deprecate the existing functions at once?

jonathanshaw’s picture

There is no existing test coverage of the existing procedural API, so maybe we wouldnt need to create duplicate test coverage.

geek-merlin’s picture

Issue summary: View changes

I agree with @jonathanshaw that we need to agree on a battle plan, and with @berdir, that the exact split of issues is debatable.

Added #3274480: Make history repository optionally support "edit" besides "view" to the wishlist, of course open to dabate.

Also i feel this might win from maturing in contrib.

andypost’s picture

++ to split, it will help to commit while D10 minors

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

History module is going to contrib to iterate faster #3520462: [meta] Tasks to deprecate the History module

quietone’s picture

Status: Active » Postponed

The History Module was approved for removal in #3336276: [Policy] Deprecate History module.

This is Postponed. The status is set according to two policies. The Remove a core extension and move it to a contributed project and the Extensions approved for removal policies.

The deprecation work is in #3520462: [meta] Tasks to deprecate the History module and the removal work in #3520468: [meta] Tasks to remove History module.

History will be moved to a contributed project after the Drupal 12.x branch is open.

needs-review-queue-bot’s picture

Version: 11.x-dev » main

Updated MR target branch from 11.x to main branch.

longwave’s picture

Project: Drupal core » Node History
Version: main » 1.0.0
Component: history.module » Code
Status: Postponed » Active