Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
12 / 12
CRAP
100.00% covered (success)
100.00%
1 / 1
ReadingTime
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
12 / 12
14
100.00% covered (success)
100.00%
1 / 1
 fromString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fromFile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWordCount
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMinutes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSeconds
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMinutesAsFloat
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSecondsOver
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFormatted
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 formatUsingClosure
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 generate
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Hyde\Support;
6
7use Closure;
8use Hyde\Facades\Filesystem;
9use Stringable;
10
11use function floor;
12use function round;
13use function sprintf;
14use function str_word_count;
15
16/**
17 * Calculate the estimated reading time for a text.
18 */
19class ReadingTime implements Stringable
20{
21    /** @var int How many words per minute is read. Inversely proportional. Increase for a shorter reading time. */
22    protected static int $wordsPerMinute = 240;
23
24    /** @var string The text to calculate the reading time for. */
25    protected readonly string $text;
26
27    /** @var int The number of words in the text. */
28    protected int $wordCount;
29
30    /** @var int The number of seconds it takes to read the text. */
31    protected int $seconds;
32
33    public static function fromString(string $text): static
34    {
35        return new static($text);
36    }
37
38    public static function fromFile(string $path): static
39    {
40        return static::fromString(Filesystem::getContents($path));
41    }
42
43    public function __construct(string $text)
44    {
45        $this->text = $text;
46
47        $this->generate();
48    }
49
50    public function __toString()
51    {
52        return $this->getFormatted();
53    }
54
55    public function getWordCount(): int
56    {
57        return $this->wordCount;
58    }
59
60    public function getMinutes(): int
61    {
62        return (int) floor($this->getMinutesAsFloat());
63    }
64
65    public function getSeconds(): int
66    {
67        return $this->seconds;
68    }
69
70    protected function getMinutesAsFloat(): float
71    {
72        return $this->seconds / 60;
73    }
74
75    public function getSecondsOver(): int
76    {
77        return (int) round(($this->getMinutesAsFloat() - $this->getMinutes()) * 60);
78    }
79
80    public function getFormatted(string $format = '%dmin, %dsec'): string
81    {
82        return sprintf($format, $this->getMinutes() ?: 1, $this->getMinutes() >= 1 ? $this->getSecondsOver() : 0);
83    }
84
85    /** @param  \Closure(int, int): string $closure The closure will receive the minutes and seconds as integers and should return a string. */
86    public function formatUsingClosure(Closure $closure): string
87    {
88        return $closure($this->getMinutes(), $this->getSecondsOver());
89    }
90
91    protected function generate(): void
92    {
93        $wordCount = str_word_count($this->text);
94
95        $minutes = $wordCount / static::$wordsPerMinute;
96        $seconds = (int) floor($minutes * 60);
97
98        $this->wordCount = $wordCount;
99        $this->seconds = $seconds;
100    }
101}