Problem/Motivation

When no summary is specified, token [node:summary] uses formatter settings of teaser view mode in order to generate trimmed version of body field. If 'teaser' view mode is not configured, default text_summary_or_trimmed trim lengths will be used (600 characters atm)

However, existing code does not check what formatter is being used. Instead, it checks for trim_length setting only.

When some other field formatter (like Smart trim) is being used for teasers, summary is being generated incorrectly. This happens because Smart trim uses exactly the same trim_length setting, but it can be words, not characters.

In particular case, smart trim is configured to use 30 words. Token [node:summary] gives 30 characters, instead of default 600.

Proposed resolution

Add extra check for the formatter that is being used for teaser view mode for body field.

Remaining tasks

  • Review patch

User interface changes

No

API changes

No

Data model changes

No

CommentFileSizeAuthor
#53 interdiff_48-53.txt1.63 KBravi.shankar
#53 2854930-53.patch12.05 KBravi.shankar
#48 2854930-48.patch12.06 KBSuresh Prabhu Parkala
#43 interdiff-39-43.txt673 bytesnaresh_bavaskar
#43 2854930-43.patch12.04 KBnaresh_bavaskar
#40 2854930-39.patch12.04 KBHenry Tran
#38 2854930-38.patch12.04 KBravi.shankar
#36 interdiff_33-36.txt984 bytesravi.shankar
#36 2854930-36.patch12.03 KBravi.shankar
#33 drupal-node_summary_token-2854930-27.patch12.44 KBHenry Tran
#26 interdiff-19-26.txt8.29 KBTaran2L
#26 drupal-node_summary_token-2854930-26.patch11.64 KBTaran2L
#25 interdiff-19-25.txt8.33 KBTaran2L
#25 drupal-node_summary_token-2854930-25.patch11.65 KBTaran2L
#19 interdiff-15-19.txt2.37 KBTaran2L
#19 drupal-node_summary_token-2854930-19.patch10.55 KBTaran2L
#17 drupal-node_summary_token-2854930-15-reroll.patch10.06 KBgnuget
#15 interdiff-11-15.txt1.95 KBTaran2L
#15 drupal-node_summary_token-2854930-15.patch10.12 KBTaran2L
#11 interdiff-9-11.txt1.67 KBTaran2L
#11 drupal-node_summary_token-2854930-11.patch10 KBTaran2L
#9 drupal-node_summary_token-2854930-9.patch9.37 KBTaran2L
#4 drupal-core-node_summary_token-2854930-2.patch876 bytesAndrew147
#2 drupal-core-node_summary_token-2854930-1.patch908 bytesAndrew147
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Andrew147 created an issue. See original summary.

Andrew147’s picture

Assigned: Andrew147 » Unassigned
Status: Needs work » Needs review
FileSize
908 bytes

Status: Needs review » Needs work

The last submitted patch, 2: drupal-core-node_summary_token-2854930-1.patch, failed testing.

Andrew147’s picture

Fixed incorrect paths.

Taran2L’s picture

Version: 8.2.x-dev » 8.3.x-dev
Issue summary: View changes

Updating summary.

Probably this will not end up in 8.2.x; moving to 8.3.x

gnuget’s picture

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

First, needs to be fixed on 8.4.x and after can be cherry-picked to 8.3.x.

Taran2L’s picture

gnuget’s picture

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

looks great but this needs tests.

Thanks.

Taran2L’s picture

Added tests

Status: Needs review » Needs work

The last submitted patch, 9: drupal-node_summary_token-2854930-9.patch, failed testing.

Taran2L’s picture

Status: Needs work » Needs review
FileSize
10 KB
1.67 KB

Huh, DrupalCI PHP does not have mbstring extension enabled causing new tests to fail.

Unicode::substr() expects string input, and not a \Drupal\Component\Render\MarkupInterface

Also fixed coding standards issues

gnuget’s picture

Status: Needs review » Needs work

Hi! Taran2L

It looks great, just a few comments:

  1. /**
    +   * User account used as node author.
    +   *
    +   * @var \Drupal\user\Entity\User
    +   */
    +  protected $account;
    +
    +  /**
    

    We need to keep the changes in the scope and at the minimum (so the core commiter can review this easier and quicker) let's revert this change, and all the $this->account changes, if you think to we really need these changes let's create a follow-up.

  2. /**
    -   * Creates a node, then tests the tokens generated from it.
    +   * Tests all node tokens.
        */

    The same as above, not sure if it is really necessary change the comment.

  3. -      $this->assertEqual($output, $expected, format_string('Node token %token replaced.', ['%token' => $input]));
    +      $this->assertEqual($output, $expected, new FormattableMarkup('Node token %token replaced.', ['%token' => $input]));
    

    The same as above, There is already an issue to replace all the format_strings methods (see #2228741: Replace calls to format_string() with Drupal\Component\Render\FormattableMarkup), so let's revert this as well.

  4. . 'Fusce tempor tincidunt lorem vitae mollis.'; // 828
    Put the comment int is own line above the variable please (per https://www.drupal.org/docs/develop/coding-standards/api-documentation-a...).
  5. // Token [node:summary] should not pickup trim length setting of any other
        // formatter rather than "Summary or trimmed", even if setting name matches.
        // Fallbacks to "Summary or trimmed" default trim length setting (600).
        $view_display->setComponent('body', [
          'type' => 'text_trimmed',
          'settings' => ['trim_length' => 42],
        ]);
        $view_display->save();
        $expected_trimmed_to_600 = Html::escape('<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. '
            . 'Morbi diam dui, finibus et purus ac, elementum pretium augue. Fusce lacus nisl, feugiat sit amet blandit sed, mattis eu ligula. '
            . 'Duis laoreet dui non felis maximus fringilla. Maecenas tempor magna id urna dapibus, in elementum mauris consequat. '
            . 'Praesent in urna non felis fringilla ullamcorper interdum eu risus. '
            . 'Vestibulum id erat ultrices, varius est sed, dignissim dui. Vestibulum a dapibus nisl. '
            . 'Maecenas vestibulum nibh a aliquet mollis. Donec ac justo eget justo interdum faucibus. '
            . 'Aenean sit amet finibus turpis.');
        $this->assertNodeSummaryTokenReplacement($node, $expected_trimmed_to_600);

    This should also trims the string, no? I mean, the text_summary_or_trimmed just extends thetext_trimmed formatter:

    class TextSummaryOrTrimmedFormatter extends TextTrimmedFormatter { }
    

    So for this specific formatter the trim should work as well, at least for these two should work.

    Also the $expected_trimmed_to_600 is an invalid markup there is a </p> missing at the end of the variable.

    We still need to test that the value is trimmed correctly if the formater is text_summary_or_trimmed or text_trimmed and test if the trim_length is ignored if a different formated is used.

  6. -    foreach ($tests as $input => $expected) {
    -      $output = $this->tokenService->replace($input, array('node' => $node), array('language' => $this->interfaceLanguage));
    -      $this->assertEqual($output, $expected, new FormattableMarkup('Node token %token replaced for node without a summary.', ['%token' => $input]));
    -    }
    

    Why did you deleted this part? this is where actually all the tokens are tested, now we are just testing the summary. can we please revert this part?

Great work!

Thanks.

Taran2L’s picture

Hi @gnuget,

Thanks for the review.

However I can't agree with couple items.

1 and 3 - this is minor refactoring. I don't think spamming drupal issue queue is a good thing. Reviewing multiple tickets instead of a single one takes less time
2 - test method description should include what is being tested, not how we do. Also check a new test method, this naming has a lot of sense IMO
4 - ok
5 - please take a look how [node:summary] token is being generated. It uses summary or trimmed version of body
6 - please apply patch and check how it works or pay more attention reviewing it in browser. It does test all the tokens and node summary

Thanks

gnuget’s picture

1,2,3 I just wanted to help here, I've been asked to revert that types of changes before in other core issues (especially 3), if you don't want to it's ok, in the end, who decide if this is or not in the scope is the core commiter, as I said I just want to help :-)

5. I can see now that the text_summary_or_trimmed is being tested thanks, but I have doubts about this:

// Token [node:summary] should not pickup trim length setting of any other
  // formatter rather than "Summary or trimmed", even if setting name matches.
  // Fallbacks to "Summary or trimmed" default trim length setting (600).
  $view_display->setComponent('body', [
  'type' => 'text_trimmed',
  'settings' => ['trim_length' => 42],
  ]);
  $view_display->save();
  $expected_trimmed_to_600 = Html::escape('...');
  $this->assertNodeSummaryTokenReplacement($node, $expected_trimmed_to_600);

Not sure if I'm not understanding something but here you are using the text_trimmed formatter? because Drupal\text\Plugin\Field\FieldFormatter\TextSummaryOrTrimmedFormatter is empty and just extends TextTrimmedFormatter so that is why I was wondering if this formatter should behave as TextSummaryOrTrimmedFormatter and it should take in account the `trim_length` value (42) and trim the summary because right now you are testing to it's length should be 600.

So basically what I'm saying is that we might want to include text_trimmed in the node.tokens.inc file:

if ($display_options && $display_options['type'] === 'text_summary_or_trimmed') {
  $length = $display_options['settings']['trim_length'];
}

What do you think?

6. My bad, sorry!

Thanks!

Taran2L’s picture

Status: Needs work » Needs review
FileSize
10.12 KB
1.95 KB

Hi @gnuget,

I might have been a little bit too sharp in the previous comment . Sorry.

I can revert 1,2,3 - but let's have some other opinion on them

5 - At the moment trim length defaults to setting of `text_summary_or_trimmed formatter` (not text_trimmed). The values are both 600 now, nut could change in the future. Allowing both formatters creates an inconsistency with a fallback value. What do you think?

$display_options = entity_get_display('node', $node->getType(), 'teaser')->getComponent('body');
if (isset($display_options['settings']['trim_length'])) {
  $length = $display_options['settings']['trim_length'];
}
else {
  $settings = \Drupal::service('plugin.manager.field.formatter')->getDefaultSettings('text_summary_or_trimmed');
  $length = $settings['trim_length'];
}

New patch addressing 4 attached

Status: Needs review » Needs work

The last submitted patch, 15: drupal-node_summary_token-2854930-15.patch, failed testing.

gnuget’s picture

Status: Needs work » Needs review
FileSize
10.06 KB

Because of: #2776975: March 3, 2017: Convert core to array syntax coding standards for Drupal 8.3.x RC phase #15 doesn't apply anymore.

Here a straight reroll.

gnuget’s picture

5 - At the moment trim length defaults to setting of `text_summary_or_trimmed formatter` (not text_trimmed). The values are both 600 now, nut could change in the future. Allowing both formatters creates an inconsistency with a fallback value. What do you think?

The trim_length used on text_summary_or_trimmed and in text_trimmed is the same (literally both use the same variable) If you change one the other is changed as well because is the same.

So right now if the user is using the formatted "trimmed" in the teaser view mode and set the "trimmed limit" to 250 the summary token will use this value and I think that is the expected behavior.

With the suggested fix on #4 this won't work in this way anymore, the summary token won't use the trim_length if the user is using the "trimmed" formatted and will use the default value (600), and the only way to set a different value will be forcing the user to use the "text_summary_or_trimmed" formatted in the body in the teaser view mode.

So I think we should update node.tokens.inc with:

if (isset($display_options['type']) && isset($display_options['settings']['trim_length']) && in_array($display_options['type'], ['text_summary_or_trimmed', 'trimmed'])) {
  $length = $display_options['settings']['trim_length'];
}

An alternative (not sure how easy would be to do it or even if it is a good idea) is making the [node:summary] token use the same formatter and not just the trim_length value, in this way we can at least guarantee that the token will contain exactly the same value as the body in the teaser view mode, and the expected behaviour using the Smart trim would be having a teaser with a specific number of words.

Another alternative would be make the Smart trim module stop using the trim_lenght and use an a different setting variable.

At this point not sure what is the best thing to do. :-/

Taran2L’s picture

Thanks for the reroll.

Add Trimmed as a second option for [node:summary] token.

An alternative (not sure how easy would be to do it or even if it is a good idea) is making the [node:summary] token use the same formatter and not just the trim_length value, in this way we can at least guarantee that the token will contain exactly the same value as the body in the teaser view mode, and the expected behaviour using the Smart trim would be having a teaser with a specific number of words.

Another alternative would be make the Smart trim module stop using the trim_lenght and use an a different setting variable.

This might be a good idea. Could be a follow-up issue.

gnuget’s picture

Looks great, just i have two doubts.

  1. +                if ($display_options && ($display_options['type'] === 'text_trimmed'|| $display_options['type'] === 'text_summary_or_trimmed')) {
                       $length = $display_options['settings']['trim_length'];
                     }

    is there a case when $display_options exists but $display_options['settings']['trim_length']; doesn't? I mean this is never going to fail? maybe using a custom formatter which doesn't rely on trim_lenght will make it fail?

  2. Html::escape('<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi diam dui, finibus et purus ac, elementum pretium augue.');
    Before trim the output shouldn't remove tags or do something to avoid having an empty

    tag? even if it is escaped it will looks weird in the summary token no?

Thanks!

Taran2L’s picture

maybe using a custom formatter which doesn't rely on trim_lenght will make it fail?

We explicitly expect text_trimmed or text_summary_or_trimmed formatter only. Both have trim_length. I think extra check is unnecessary.

Before trim the output shouldn't remove tags or do something to avoid having an empty tag? even if it is escaped it will looks weird in the summary token no?

This is interesting question. I believe this test runs in a very limited environment with only a few modules enabled, which makes the output not valid html (seems like html corrector filter is not being invoked)

Taran2L’s picture

In text.module:

// If the htmlcorrector filter is present, apply it to the generated summary.
if (isset($format) && $filters->has('filter_htmlcorrector') && $filters->get('filter_htmlcorrector')->status) {
  $summary = Html::normalize($summary);
}

And by default plain_text filter format does not have html corrector. See filter.format.plain_text.yml

gnuget’s picture

We explicitly expect `text_trimmed` or `text_summary_or_trimmed` formatter only. Both have `trim_length`. I think extra check is unnecessary.

It is sometimes hard to me see this type of things. Thanks for your explanation.

#22 agree as well.

I haven't any other doubt, to me this is RTBC, we just need more opinions about 12.1, 12.2 and 12.3.

Thanks!

Taran2L’s picture

This is quite interesting comment to be honest.

[node:summary] uses this, when no summary is provided:

  $output = $item->processed;

and processed value contains already processed text, and then text_summary() applies filters for the second time!

Will update patch soon!

Taran2L’s picture

New patch that addresses issue with double escaping.

Taran2L’s picture

The last submitted patch, 25: drupal-node_summary_token-2854930-25.patch, failed testing.

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.

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.

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.

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.

Henry Tran’s picture

Status: Needs review » Needs work

The last submitted patch, 33: drupal-node_summary_token-2854930-27.patch, failed testing. View results

MrPaulDriver’s picture

Priority: Normal » Major

Unfortunately the latest patch does not appear compatible with 8.8.x. Any chance of a re-roll?

Given that Smart Trim has over 50,000 installs and that [node:summary] is used for meta descriptions by the Metatag module, might I suggest this core bug could be adversely affecting the SEO of many thousands of Drupal sites.

ravi.shankar’s picture

Status: Needs work » Needs review
FileSize
12.03 KB
984 bytes

I have done the patch on Drupal 8.9.x

I have also tried to fix the failed tests.

Status: Needs review » Needs work

The last submitted patch, 36: 2854930-36.patch, failed testing. View results

ravi.shankar’s picture

Status: Needs work » Needs review
FileSize
12.04 KB

I have again uploaded a patch.

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.

Henry Tran’s picture

Status: Needs review » Needs work

The last submitted patch, 40: 2854930-39.patch, failed testing. View results

naresh_bavaskar’s picture

Assigned: Unassigned » naresh_bavaskar
naresh_bavaskar’s picture

Assigned: naresh_bavaskar » Unassigned
Status: Needs work » Needs review
FileSize
12.04 KB
673 bytes

Fixed the failed test cases and re-rolled in 9.1.x

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.

greggles’s picture

Issue tags: -Needs tests

Just tested this out on Drupal 8.9 and it solved a bug I was running into.

I'm going to remove the "needs tests" tag here since there seem to be tests now, but if the tests are insufficient in some way perhaps that tag should come back.

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.

darvanen’s picture

Status: Needs review » Needs work

Needs work for failed patch.

Will prioritise this with assistance.

Suresh Prabhu Parkala’s picture

Status: Needs work » Needs review
FileSize
12.06 KB

A re-rolled patch against 9.3.x. Please review.

darvanen’s picture

Status: Needs review » Needs work

This patch is doing way more than outlined in the IS.

All of the feedback in #12 needs to be addressed, and the "Lorem Ipsum" text which is causing CSpell failure must be replaced with something else (make sure not to use anything under copyright).

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.

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.

JSchref’s picture

#48 appears to work for 9.4.3

ravi.shankar’s picture

FileSize
12.05 KB
1.63 KB

Addressed Drupal CS issues of patch #48.

There are lots of unknown words being used in core/modules/node/tests/src/Kernel/NodeTokenReplaceTest.php file.
So can we use cspell:ignore words or we will add these in the dictionary?

darvanen’s picture

Per #49, those aren't English words and shouldn't be added to the dictionary, we need a piece of text other than Lorem Ipsum in there.

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.