Reading time is a module that provides an extra field for content types, which displays to the users the time it will take for them to read a node. This field takes into consideration all the textfields part of the content type, plus entity reference revision fields like Paragraphs, Custom blocks etc.
It also comes with a configuration page, where you can:
- activate the reading time field for specific content types;
- set the "words per minute" value, which is part of the calculation of the reading time;

Also, the module provides twig template, which can be easily modified in your custom theme.

Similar modules

Read Time

The main differences between the Read Time module and the Node read time module are:

  • Node read time provides a template for the extra field
  • Node read time gives the possibility to enable/disable the field per content type
  • Node read time doesn't have field formatter; it displays the result only in minutes
  • Node read time doesn't allow you to modify which fields will be included in the calculation
  • Node read time takes into the calculation not only basic text fields, but also advanced fields like Paragraphs and custom blocks

Project link

https://www.drupal.org/project/node_read_time

Git instructions

git clone --branch 8.x-1.x https://git.drupalcode.org/project/node_read_time.git

PAReview checklist

https://pareview.sh/pareview/https-git.drupal.org-project-node_read_time...

CommentFileSizeAuthor
#17 Screenshot 2020-03-05 at 4.16.15 PM.png618.89 KBrksyravi

Comments

yivanov created an issue. See original summary.

avpaderno’s picture

avpaderno’s picture

Issue summary: View changes
avpaderno’s picture

Status: Needs review » Needs work

Thank you for applying! May you also describe the difference between the Node read time and Read Time modules?

yivanov’s picture

Issue summary: View changes
Status: Needs work » Needs review
yivanov’s picture

Thank you for the feedback, @kiamlaluno ! I updated the description with the main differences between the two modules.

avpaderno’s picture

Issue summary: View changes
vernit’s picture

Status: Needs review » Needs work

Thanks for your contribution. Please take a look number of items below :

1. Core version key in module's .info.yml. See link for more details : https://www.drupal.org/node/3070687
2. There will be only and only one return statement into hook_help.

ankush_03’s picture

Fix below issue :
------ ----------------------------------------------------------------------------
Line node_read_time.module
------ ----------------------------------------------------------------------------
66 Call to an undefined method Drupal\Core\Entity\EntityInterface::getType().
------ ----------------------------------------------------------------------------

------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Line src/Calculate/ReadingTime.php
------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
45 Property Drupal\node_read_time\Calculate\ReadingTime::$entityTypeManager has unknown class Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface as its type.
53 PHPDoc tag @param for parameter $entityTypeManager with type Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface is not subtype of native type Drupal\Core\Entity\EntityTypeManagerInterface.
53 Parameter $entityTypeManager of method Drupal\node_read_time\Calculate\ReadingTime::__construct() has invalid typehint type Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface.
54 Property Drupal\node_read_time\Calculate\ReadingTime::$entityTypeManager (Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface) does not accept Drupal\Core\Entity\EntityTypeManagerInterface.
79 Property Drupal\node_read_time\Calculate\ReadingTime::$words (string) does not accept int.
166 Call to method getStorage() on an unknown class Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface.
------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

------ ------------------------------------------------------------------------
Line src/Form/ReadingTimeConfigForm.php
------ ------------------------------------------------------------------------
35 Unsafe usage of new static().
💡 Consider making the class or the constructor final.
72 Call to an undefined method Drupal\Core\Entity\EntityInterface::get().
------ ------------------------------------------------------------------------

------ -------------------------------------------------------------------------
Line tests/src/Functional/LoadTest.php
------ -------------------------------------------------------------------------
Class PHPUnit\Framework\TestCase not found and could not be autoloaded.
6 Class PHPUnit\Framework\TestCase not found and could not be autoloaded.
13 Class PHPUnit\Framework\TestCase not found and could not be autoloaded.
------ -------------------------------------------------------------------------

yivanov’s picture

@Vernit thank you, both issues are fixed and commited to the project.

@ankushgautam76 - thanks for your feedback. Are these warnings coming from a Code sniffer with Drupal coding standards? Because for me they don't make much sense. Especially things like - * Unsafe usage of new static().* I mean, this is how these things are implemented in the Drupal core itself. IMO these shouldn't be a requirement for applying for security advisory coverage.

yivanov’s picture

Status: Needs work » Needs review
rksyravi’s picture

Issue summary: View changes

Hi @yivanov,

Unable to take the clone from git clone --branch 8.x-1.x https://git.drupal.org:project/node_read_time.git so, updating git clone --branch 8.x-1.x https://git.drupalcode.org/project/node_read_time.git

rksyravi’s picture

Status: Needs review » Needs work

I found these below issues. Please look into it.

------ ---------------------------------------------------------------------------- 
  Line   node_read_time.module                                                       
 ------ ---------------------------------------------------------------------------- 
  66     Call to an undefined method Drupal\Core\Entity\EntityInterface::getType().  
 ------ ---------------------------------------------------------------------------- 

 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   src/Calculate/ReadingTime.php                                                                                                                                                                                            
 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  45     Property Drupal\node_read_time\Calculate\ReadingTime::$entityTypeManager has unknown class Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface as its type.                                    
  53     PHPDoc tag @param for parameter $entityTypeManager with type Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface is not subtype of native type Drupal\Core\Entity\EntityTypeManagerInterface.  
  53     Parameter $entityTypeManager of method Drupal\node_read_time\Calculate\ReadingTime::__construct() has invalid typehint type Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface.               
  54     Property Drupal\node_read_time\Calculate\ReadingTime::$entityTypeManager (Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface) does not accept Drupal\Core\Entity\EntityTypeManagerInterface.  
  79     Property Drupal\node_read_time\Calculate\ReadingTime::$words (string) does not accept int.                                                                                                                               
  166    Call to method getStorage() on an unknown class Drupal\node_read_time\Calculate\Drupal\Core\Entity\EntityTypeManagerInterface.                                                                                           
 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ ------------------------------------------------------------------------ 
  Line   src/Form/ReadingTimeConfigForm.php                                      
 ------ ------------------------------------------------------------------------                
  72     Call to an undefined method Drupal\Core\Entity\EntityInterface::get().  
 ------ ------------------------------------------------------------------------
rksyravi’s picture

StatusFileSize
new618.89 KB

Hi again,
Also, make sure to set the default value to Words per minute. field other than 0. Because it gives errors, see the attachment.

yivanov’s picture

Hi @rksyravi, thanks for your input. You definitely have a point and I've just set a default value of 225 words per minute (This is an average reading speed for adult, according to most of the researches on this topic). You can check my latest commit.

About the code sniffer errors - I think here the situation is the same as @ankushgautam76 mentioned. According to the Drupal coding standards everything is ok. Are you running this code sniffer without context (outside Drupal project structure) ?

yivanov’s picture

Status: Needs work » Needs review
crafter’s picture

Thanks for your contribution. Please take a look number of items below :

1. You have to change the parent in node_read_time.links.menu.yml file because it doesn't appear "Reading time" link in menu config.

diff --git a/node_read_time.links.menu.yml b/node_read_time.links.menu.yml
index b0afcad..980ba1a 100644
--- a/node_read_time.links.menu.yml
+++ b/node_read_time.links.menu.yml
@@ -1,5 +1,5 @@
 reading_time.settings:
   title: 'Reading time'
-  parent: system.admin_config
+  parent: system.admin_config_system
   description: 'Manage the Read time field settings.'
   route_name: system.admin_config_reading_time

2. getStorage on entityManager is depraceted use \Drupal\Core\Entity\EntityTypeManagerInterface::getStorage() instead here

3. You have to add your config install and config schema for your config storage it's not necessary but it should be here.

yivanov’s picture

Thanks for your time for reviewing the module, @crafter ! The following commit is addressing the points you have mentioned - https://git.drupalcode.org/project/node_read_time/commit/ec72bb4

klausi’s picture

Status: Needs review » Needs work
Issue tags: +PAreview: security

Thanks for your contribution!

  1. ReadingTime::collectWords(): this looks vulnerable to denial of service attacks. It seems there is no recursion prevention, so if a node has a reference field to the same node type then this method could go in circles when 2 nodes reference each other. An attacker could reference such a circle and then your site goes down whenever the node is displayed. You need to prevent that by checking if the same entity was already scanned and stop in that case. This is a bit of a fringe case and might be unlikely for most sites, but you should fix that potential security issue first just to be sure.
  2. LoadTest: this test is useless and does not test anything? Please make it a useful test, for example testing the recursion prevention. Otherwise I think useless tests should be removed as they they don't provide any value?
yivanov’s picture

Thank you for the review, @klausi !

1. You are right that I don't have recursion prevention in the case you have mentioned. It is indeed a fringe case and I can reproduce this vulnerability with Drupal core itself - just create reference field in a node and in the display settings specify as Rendered entity - the default display. Then create node and reference the same node in the entity reference field - infinite recursion will happen, trying to render the same entity again and again.
I will prepare a check for this for sure and I am glad that people pay attention to security in the Drupal community. Thanks :)

2. Generally, the test is useless in terms that it doesn't test the functionality of the module, but I've encountered many times a situation, when I enable a module and then the website cannot be accessed :) IMO it's better to add more test cases on top of that, but this test at least makes sure that no major regressions are happening after enable of the module.

Thanks again for your feedback and I will prepare a commit to address these two points.
Cheers!

rohitrajputsahab’s picture

Please fix this one also.
FILE: node_read_time/README.md
------------------------------------------------------------------------
FOUND 1 ERROR AND 1 WARNING AFFECTING 1 LINE
------------------------------------------------------------------------
33 | WARNING | [ ] Line exceeds 80 characters; contains 113 characters
33 | ERROR | [x] Expected 1 newline at end of file; 0 found
------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------

FILE: node_read_time/node_read_time.info.yml
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
6 | ERROR | [x] Expected 1 newline at end of file; 2 found
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

klausi’s picture

Status: Needs work » Fixed
Issue tags: -PAreview: security

@yivanov right, that is good into. If core does not consider the recursion a security issue then I think we can proceed right away here :-)

Thanks for your contribution, Yasen!

I updated your account so you can opt into security advisory coverage now.

Here are some recommended readings to help with excellent maintainership:

You can find lots more contributors chatting on Slack or IRC in #drupal-contribute. So, come hang out and stay involved!

Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

Thanks to the dedicated reviewer(s) as well.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.