Passed
Push — master ( e16666...667470 )
by Filipe
01:49 queued 13s
created

IpsumLorenGenerator::paragraphsArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
/**
4
 * This file is part of template
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Slick\Template\Extension;
13
14
/**
15
 * IpsumLorenGenerator
16
 *
17
 * @package Slick\Template\Extension
18
 */
19
final class IpsumLorenGenerator
20
{
21
    /**
22
     * Whether we should be starting the string with "Lorem ipsum..."
23
     *
24
     * @access private
25
     * @var    mixed
26
     */
27
    private mixed $first = true;
28
29
    /**
30
     * A lorem ipsum vocabulary of sorts. Not a complete list as I'm unsure if
31
     * a complete list exists and if so, where to get it.
32
     *
33
     * @access private
34
     * @var    array<string>
35
     */
36
    private array $words = [
37
        // Lorem ipsum...
38
        'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit',
39
40
        // and the rest of the vocabulary
41
        'a', 'ac', 'accumsan', 'ad', 'aenean', 'aliquam', 'aliquet', 'ante',
42
        'aptent', 'arcu', 'at', 'auctor', 'augue', 'bibendum', 'blandit',
43
        'class', 'commodo', 'condimentum', 'congue', 'consequat', 'conubia',
44
        'convallis', 'cras', 'cubilia', 'curabitur', 'curae', 'cursus',
45
        'dapibus', 'diam', 'dictum', 'dictumst', 'dignissim', 'dis', 'donec',
46
        'dui', 'duis', 'efficitur', 'egestas', 'eget', 'eleifend', 'elementum',
47
        'enim', 'erat', 'eros', 'est', 'et', 'etiam', 'eu', 'euismod', 'ex',
48
        'facilisi', 'facilisis', 'fames', 'faucibus', 'felis', 'fermentum',
49
        'feugiat', 'finibus', 'fringilla', 'fusce', 'gravida', 'habitant',
50
        'habitasse', 'hac', 'hendrerit', 'himenaeos', 'iaculis', 'id',
51
        'imperdiet', 'in', 'inceptos', 'integer', 'interdum', 'justo',
52
        'lacinia', 'lacus', 'laoreet', 'lectus', 'leo', 'libero', 'ligula',
53
        'litora', 'lobortis', 'luctus', 'maecenas', 'magna', 'magnis',
54
        'malesuada', 'massa', 'mattis', 'mauris', 'maximus', 'metus', 'mi',
55
        'molestie', 'mollis', 'montes', 'morbi', 'mus', 'nam', 'nascetur',
56
        'natoque', 'nec', 'neque', 'netus', 'nibh', 'nisi', 'nisl', 'non',
57
        'nostra', 'nulla', 'nullam', 'nunc', 'odio', 'orci', 'ornare',
58
        'parturient', 'pellentesque', 'penatibus', 'per', 'pharetra',
59
        'phasellus', 'placerat', 'platea', 'porta', 'porttitor', 'posuere',
60
        'potenti', 'praesent', 'pretium', 'primis', 'proin', 'pulvinar',
61
        'purus', 'quam', 'quis', 'quisque', 'rhoncus', 'ridiculus', 'risus',
62
        'rutrum', 'sagittis', 'sapien', 'scelerisque', 'sed', 'sem', 'semper',
63
        'senectus', 'sociosqu', 'sodales', 'sollicitudin', 'suscipit', 'slick',
64
        'suspendisse', 'taciti', 'tellus', 'tempor', 'tempus', 'tincidunt',
65
        'torquent', 'tortor', 'tristique', 'turpis', 'ullamcorper', 'ultrices',
66
        'ultricies', 'urna', 'ut', 'varius', 'vehicula', 'vel', 'velit',
67
        'venenatis', 'vestibulum', 'vitae', 'vivamus', 'viverra', 'volutpat',
68
        'vulputate',
69
    ];
70
71
    /**
72
     * Generates a single word of lorem ipsum.
73
     *
74
     * @access public
75
     * @return string generated lorem ipsum word
76
     */
77
    public function word(): string
78
    {
79
        return $this->words();
80
    }
81
82
    /**
83
     * Generates words of lorem ipsum.
84
     *
85
     * @access public
86
     * @param  integer $count how many words to generate
87
     * @return array<string>   array of generated lorem ipsum words
88
     */
89
    public function wordsArray(int $count = 1): array
90
    {
91
        $wordCount = 0;
92
        $words = [];
93
94
        // Shuffles and appends the word list to compensate for count
95
        // arguments that exceed the size of our vocabulary list
96
        while ($wordCount < $count) {
97
            $shuffle = true;
98
99
            while ($shuffle) {
100
                $this->shuffle();
101
102
                // Checks that the last word of the list and the first word of
103
                // the list that's about to be appended are not the same
104
                if (!$wordCount || $words[$wordCount - 1] != $this->words[0]) {
105
                    $words      = array_merge($words, $this->words);
106
                    $wordCount  = count($words);
107
                    $shuffle    = false;
108
                }
109
            }
110
        }
111
112
        return array_slice($words, 0, $count);
113
    }
114
115
    /**
116
     * Sentences Array
117
     *
118
     * Generates an array of lorem ipsum sentences.
119
     *
120
     * @access public
121
     * @param integer $count how many sentences to generate
122
     * @return array<string> generated lorem ipsum sentences
123
     */
124
    public function sentencesArray(int $count = 1): array
125
    {
126
        $sentences = array();
127
128
        for ($i = 0; $i < $count; $i++) {
129
            $sentences[] = $this->wordsArray($this->gauss(24.46, 5.08));
130
        }
131
132
        $this->punctuate($sentences);
133
        return $sentences;
134
    }
135
136
    /**
137
     * Generates sentences of lorem ipsum.
138
     *
139
     * @access public
140
     * @param  int $count how many sentences to generate
141
     * @return string  string of generated lorem ipsum sentences
142
     */
143
    public function sentences(int $count = 1): string
144
    {
145
        return implode(" ", $this->sentencesArray($count));
146
    }
147
148
    /**
149
     * Generates a full sentence of lorem ipsum.
150
     *
151
     * @access public
152
     * @return string generated lorem ipsum sentence
153
     */
154
    public function sentence(): string
155
    {
156
        return $this->sentences();
157
    }
158
159
160
    /**
161
     * Generates words of lorem ipsum.
162
     *
163
     * @access public
164
     * @param  integer $count how many words to generate
165
     * @return string A string containing the given number of words
166
     */
167
    public function words(int $count = 1): string
168
    {
169
        return implode(" ", $this->wordsArray($count));
170
    }
171
172
    /**
173
     * Generates an array of lorem ipsum paragraphs.
174
     *
175
     * @access public
176
     * @param  int $count how many paragraphs to generate
177
     * @return array<string>   generated lorem ipsum paragraphs
178
     */
179
    public function paragraphsArray(int $count = 1): array
180
    {
181
        $paragraphs = array();
182
183
        for ($i = 0; $i < $count; $i++) {
184
            $paragraphs[] = $this->sentences($this->gauss(5.8, 1.93));
185
        }
186
187
        return $paragraphs;
188
    }
189
190
    /**
191
     * Generates paragraphs of lorem ipsum.
192
     *
193
     * @access public
194
     * @param  integer $count how many paragraphs to generate
195
     * @return string   string of generated lorem ipsum paragraphs
196
     */
197
    public function paragraphs(int $count = 1): string
198
    {
199
        return implode("\n", $this->paragraphsArray($count));
200
    }
201
202
    /**
203
     * Generates a full paragraph of lorem ipsum.
204
     *
205
     * @access public
206
     * @return string generated lorem ipsum paragraph
207
     */
208
    public function paragraph(): string
209
    {
210
        return $this->paragraphs();
211
    }
212
213
    /**
214
     * Shuffle
215
     *
216
     * Shuffles the words, forcing "Lorem ipsum..." at the beginning if it is
217
     * the first time we are generating the text.
218
     *
219
     * @access private
220
     * @return void
221
     */
222
    private function shuffle(): void
223
    {
224
        if ($this->first) {
225
            $this->first = array_slice($this->words, 0, 8);
226
            $this->words = array_slice($this->words, 8);
227
228
            shuffle($this->words);
229
230
            $this->words = $this->first + $this->words;
231
232
            $this->first = false;
233
            return;
234
        }
235
        shuffle($this->words);
236
    }
237
238
    /**
239
     * Calculate the number of words in a sentence, the number of sentences in a paragraph
240
     * and the distribution of commas in a sentence.
241
     *
242
     * @access private
243
     * @param double $mean average value
244
     * @param double $stdDev standard deviation
245
     * @return int  calculated distribution
246
     */
247
    private function gauss(float $mean, float $stdDev): int
248
    {
249
        $x = mt_rand() / mt_getrandmax();
250
        $y = mt_rand() / mt_getrandmax();
251
        $z = sqrt(-2 * log($x)) * cos(2 * pi() * $y);
252
253
        return intval($z * $stdDev + $mean);
254
    }
255
256
    /**
257
     * Punctuate
258
     *
259
     * Applies punctuation to a sentence. This includes a period at the end,
260
     * the injection of commas as well as capitalizing the first letter of the
261
     * first word of the sentence.
262
     *
263
     * @access private
264
     * @param array<array<string>> $sentences the sentences we would like to punctuate
265
     * @return void
266
     */
267
    private function punctuate(array &$sentences): void
268
    {
269
        foreach ($sentences as $key => $sentence) {
270
            $words = count($sentence);
271
            // Only worry about commas on sentences longer than 4 words
272
            if ($words > 4) {
273
                $mean    = log($words, 6);
274
                $std_dev = $mean / 6;
275
                $commas  = $this->gauss($mean, $std_dev);
276
277
                for ($i = 1; $i <= $commas; $i++) {
278
                    $word = round($i * $words / ($commas + 1));
279
280
                    if ($word < ($words - 1) && $word > 0) {
281
                        $sentence[$word] .= ',';
282
                    }
283
                }
284
            }
285
286
            $sentences[$key] = ucfirst(implode(' ', $sentence) . '.');
287
        }
288
    }
289
}
290