2
2
3
3
namespace Statamic \StaticSite ;
4
4
5
+ use Spatie \Fork \Fork ;
5
6
use Facades \Statamic \View \Cascade ;
6
7
use Statamic \Facades \URL ;
7
8
use Statamic \Support \Str ;
@@ -26,6 +27,7 @@ class Generator
26
27
protected $ app ;
27
28
protected $ files ;
28
29
protected $ router ;
30
+ protected $ tasks ;
29
31
protected $ config ;
30
32
protected $ request ;
31
33
protected $ after ;
@@ -34,12 +36,14 @@ class Generator
34
36
protected $ warnings = 0 ;
35
37
protected $ viewPaths ;
36
38
protected $ extraUrls ;
39
+ protected $ workers = 1 ;
37
40
38
- public function __construct (Application $ app , Filesystem $ files , Router $ router )
41
+ public function __construct (Application $ app , Filesystem $ files , Router $ router, Tasks $ tasks )
39
42
{
40
43
$ this ->app = $ app ;
41
44
$ this ->files = $ files ;
42
45
$ this ->router = $ router ;
46
+ $ this ->tasks = $ tasks ;
43
47
$ this ->extraUrls = collect ();
44
48
$ this ->config = $ this ->initializeConfig ();
45
49
}
@@ -55,6 +59,13 @@ private function initializeConfig()
55
59
return $ config ;
56
60
}
57
61
62
+ public function workers (int $ workers )
63
+ {
64
+ $ this ->workers = $ workers ;
65
+
66
+ return $ this ;
67
+ }
68
+
58
69
public function after ($ after )
59
70
{
60
71
$ this ->after = $ after ;
@@ -69,6 +80,8 @@ public function addUrls($closure)
69
80
70
81
public function generate ()
71
82
{
83
+ $ this ->checkConcurrencySupport ();
84
+
72
85
Site::setCurrent (Site::default ()->handle ());
73
86
74
87
$ this
@@ -134,7 +147,7 @@ public function createSymlinks()
134
147
Partyline::line ("Symlink not created. $ dest already exists. " );
135
148
} else {
136
149
$ this ->files ->link ($ source , $ dest );
137
- Partyline::line ("$ source symlinked to $ dest " );
150
+ Partyline::line ("<info>[✔]</info> $ source symlinked to $ dest " );
138
151
}
139
152
}
140
153
@@ -152,7 +165,7 @@ public function copyFiles()
152
165
$ this ->files ->copyDirectory ($ source , $ dest );
153
166
}
154
167
155
- Partyline::line ("$ source copied to to $ dest " );
168
+ Partyline::line ("<info>[✔]</info> $ source copied to $ dest " );
156
169
}
157
170
}
158
171
@@ -163,33 +176,28 @@ protected function createContentFiles()
163
176
$ this ->app ->instance ('request ' , $ request );
164
177
});
165
178
166
- $ this ->pages ()->each (function ($ page ) use ($ request ) {
167
- $ this ->updateCurrentSite ($ page ->site ());
179
+ $ pages = $ this ->gatherContent ();
168
180
169
- view ()-> getFinder ()-> setPaths ( $ this -> viewPaths );
181
+ Partyline:: line ( " Generating { $ pages -> count ()} content files... " );
170
182
171
- $ this ->count ++ ;
183
+ $ closures = $ this ->makeContentGenerationClosures ( $ pages , $ request ) ;
172
184
173
- $ request -> setPage ( $ page );
185
+ $ results = $ this -> tasks -> run (... $ closures );
174
186
175
- Partyline:: comment ( " Generating { $ page -> url ()} ... " );
187
+ $ this -> outputResults ( $ results );
176
188
177
- try {
178
- $ generated = $ page ->generate ($ request );
179
- } catch (NotGeneratedException $ e ) {
180
- $ this ->skips ++;
181
- Partyline::line ($ e ->consoleMessage ());
182
- return ;
183
- }
189
+ return $ this ;
190
+ }
184
191
185
- if ( $ generated -> hasWarning ()) {
186
- $ this -> warnings ++;
187
- }
192
+ protected function gatherContent ()
193
+ {
194
+ Partyline:: line ( ' Gathering content to be generated... ' );
188
195
189
- Partyline::line ($ generated ->consoleMessage ());
190
- });
196
+ $ pages = $ this ->pages ();
191
197
192
- return $ this ;
198
+ Partyline::line ("\x1B[1A \x1B[2K<info>[✔]</info> Gathered content to be generated " );
199
+
200
+ return $ pages ;
193
201
}
194
202
195
203
protected function pages ()
@@ -215,6 +223,57 @@ protected function pages()
215
223
});
216
224
}
217
225
226
+ protected function makeContentGenerationClosures ($ pages , $ request )
227
+ {
228
+ return $ pages ->split ($ this ->workers )->map (function ($ pages ) use ($ request ) {
229
+ return function () use ($ pages , $ request ) {
230
+ $ count = $ skips = $ warnings = 0 ;
231
+ $ errors = [];
232
+
233
+ foreach ($ pages as $ page ) {
234
+ $ this ->updateCurrentSite ($ page ->site ());
235
+
236
+ view ()->getFinder ()->setPaths ($ this ->viewPaths );
237
+
238
+ $ count ++;
239
+
240
+ $ request ->setPage ($ page );
241
+
242
+ Partyline::line ("\x1B[1A \x1B[2KGenerating " .$ page ->url ());
243
+
244
+ try {
245
+ $ generated = $ page ->generate ($ request );
246
+ } catch (NotGeneratedException $ e ) {
247
+ $ skips ++;
248
+ $ errors [] = $ e ->consoleMessage ();
249
+ continue ;
250
+ }
251
+
252
+ if ($ generated ->hasWarning ()) {
253
+ $ warnings ++;
254
+ }
255
+ }
256
+
257
+ return compact ('count ' , 'skips ' , 'warnings ' , 'errors ' );
258
+ };
259
+ })->all ();
260
+ }
261
+
262
+ protected function outputResults ($ results )
263
+ {
264
+ $ results = collect ($ results );
265
+
266
+ Partyline::line ("\x1B[1A \x1B[2K<info>[✔]</info> Generated {$ results ->sum ('count ' )} content files " );
267
+
268
+ if ($ results ->sum ('skips ' )) {
269
+ $ results ->reduce (function ($ carry , $ item ) {
270
+ return $ carry ->merge ($ item ['errors ' ]);
271
+ }, collect ())->each (function ($ error ) {
272
+ Partyline::line ($ error );
273
+ });
274
+ }
275
+ }
276
+
218
277
protected function entries ()
219
278
{
220
279
return Entry::all ()
@@ -301,4 +360,13 @@ protected function updateCurrentSite($site)
301
360
setlocale (LC_TIME , $ site ->locale ());
302
361
app ()->setLocale ($ site ->shortLocale ());
303
362
}
363
+
364
+ protected function checkConcurrencySupport ()
365
+ {
366
+ if ($ this ->workers === 1 || class_exists (Fork::class)) {
367
+ return ;
368
+ }
369
+
370
+ throw new \RuntimeException ('To use multiple workers, you must install PHP 8 and spatie/fork. ' );
371
+ }
304
372
}
0 commit comments