1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file has functions dealing with loading and precessing template files. |
5
|
|
|
* |
6
|
|
|
* @package ElkArte Forum |
7
|
|
|
* @copyright ElkArte Forum contributors |
8
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
9
|
|
|
* |
10
|
|
|
* This file contains code covered by: |
11
|
|
|
* copyright: 2011 Simple Machines (http://www.simplemachines.org) |
12
|
|
|
* |
13
|
|
|
* @version 2.0 dev |
14
|
|
|
* |
15
|
|
|
*/ |
16
|
|
|
|
17
|
|
|
namespace ElkArte\Themes; |
18
|
|
|
|
19
|
|
|
use BadFunctionCallException; |
20
|
|
|
use ElkArte\Debug; |
21
|
|
|
use ElkArte\Errors\Errors; |
|
|
|
|
22
|
|
|
use ElkArte\Exceptions\Exception; |
23
|
|
|
use ElkArte\Helper\FileFunctions; |
24
|
|
|
use ElkArte\Helper\HttpReq; |
25
|
|
|
use ElkArte\Http\Headers; |
26
|
|
|
use ElkArte\Languages\Txt; |
27
|
|
|
use Error; |
28
|
|
|
use Generator; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Class Templates |
32
|
|
|
* |
33
|
|
|
* This class loads and processes template files and sheets. |
34
|
|
|
*/ |
35
|
|
|
class Templates |
36
|
|
|
{ |
37
|
|
|
/** @var Directories Template directory's that we will be searching for the sheets */ |
38
|
|
|
public $dirs; |
39
|
|
|
|
40
|
|
|
/** @var array Template sheets that have not loaded */ |
41
|
|
|
protected $delayed = []; |
42
|
|
|
|
43
|
|
|
/** @var bool Tracks if the default index.css has been loaded */ |
44
|
|
|
protected $default_loaded = false; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Templates constructor. |
48
|
|
|
*/ |
49
|
|
|
public function __construct(Directories $dirs) |
50
|
|
|
{ |
51
|
|
|
$this->dirs = $dirs; |
52
|
|
|
|
53
|
|
|
// We want to be able to figure out any errors... |
54
|
|
|
error_clear_last(); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Load a template - if the theme doesn't include it, use the default. |
59
|
|
|
* |
60
|
|
|
* What it does: |
61
|
|
|
* - Loads a template file with the name template_name from the current, default, or base theme. |
62
|
|
|
* - Detects a wrong default theme directory and tries to work around it. |
63
|
|
|
* - Can be used to only load style sheets by using false as the template name |
64
|
|
|
* loading of style sheets with this function is deprecated, use loadCSSFile instead |
65
|
|
|
* - If $this->dirs is empty, it delays the loading of the template |
66
|
229 |
|
* |
67
|
|
|
* @param string|false $template_name |
68
|
|
|
* @param string[]|string $style_sheets any style sheets to load with the template |
69
|
229 |
|
* @param bool $fatal = true if fatal is true, dies with an error message if the |
70
|
229 |
|
* template cannot be found |
71
|
|
|
* |
72
|
|
|
* @uses $this->requireTemplate() to actually load the file. |
73
|
|
|
* |
74
|
|
|
*/ |
75
|
|
|
public function load($template_name, $style_sheets = [], $fatal = true): ?bool |
76
|
|
|
{ |
77
|
|
|
// If we don't know yet the default theme directory, let's wait a bit. |
78
|
|
|
if ($this->dirs->hasDirectories() === false) |
79
|
|
|
{ |
80
|
|
|
$this->delayed[] = [ |
81
|
|
|
$template_name, |
82
|
|
|
$style_sheets, |
83
|
|
|
$fatal, |
84
|
|
|
]; |
85
|
|
|
|
86
|
|
|
return null; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
// If instead we know the default theme directory, and we have delayed something, it's time to process |
90
|
|
|
if (!empty($this->delayed)) |
91
|
|
|
{ |
92
|
|
|
foreach ($this->delayed as $val) |
93
|
|
|
{ |
94
|
287 |
|
$this->requireTemplate($val[0], $val[1], $val[2]); |
95
|
|
|
} |
96
|
|
|
|
97
|
287 |
|
// Forget about them (load them only once) |
98
|
|
|
$this->delayed = []; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
return $this->requireTemplate($template_name, $style_sheets, $fatal); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* <b>Internal function! Do not use it, use theme()->getTemplates()->load instead</b> |
106
|
|
|
* |
107
|
|
|
* What it does: |
108
|
287 |
|
* - Loads a template file with the name template_name from the current, default, or |
109
|
|
|
* base theme. |
110
|
|
|
* - Detects a wrong default theme directory and tries to work around it. |
111
|
|
|
* - Can be used to only load style sheets by using false as the template name |
112
|
|
|
* loading of style sheets with this function is deprecated, use loadCSSFile instead |
113
|
|
|
* |
114
|
|
|
* @param string|false $template_name |
115
|
|
|
* @param string[]|string $style_sheets any style sheets to load with the template |
116
|
|
|
* @param bool $fatal = true if fatal is true, dies with an error message if the |
117
|
|
|
* template cannot be found |
118
|
|
|
* |
119
|
287 |
|
* @uses $this->dirs->fileInclude() to include the file. |
120
|
|
|
* |
121
|
|
|
*/ |
122
|
|
|
protected function requireTemplate($template_name, $style_sheets, $fatal): bool |
123
|
|
|
{ |
124
|
|
|
global $context, $settings, $txt, $db_show_debug; |
125
|
|
|
|
126
|
|
|
if (!is_array($style_sheets)) |
127
|
|
|
{ |
128
|
|
|
$style_sheets = [$style_sheets]; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
if (!$this->default_loaded) |
132
|
|
|
{ |
133
|
|
|
loadCSSFile('index.css'); |
134
|
|
|
$this->default_loaded = true; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
// Any specific template style sheets to load? |
138
|
|
|
if (!empty($style_sheets)) |
139
|
|
|
{ |
140
|
|
|
trigger_error( |
141
|
|
|
'Use of theme()->getTemplates()->load to add style sheets to the head is deprecated.', |
142
|
287 |
|
E_USER_DEPRECATED |
143
|
|
|
); |
144
|
287 |
|
$sheets = []; |
145
|
|
|
foreach ($style_sheets as $sheet) |
146
|
287 |
|
{ |
147
|
|
|
$sheets[] = stripos('.css', $sheet) !== false ? $sheet : $sheet . '.css'; |
148
|
|
|
if ($sheet !== 'admin') |
149
|
|
|
{ |
150
|
|
|
continue; |
151
|
287 |
|
} |
152
|
|
|
|
153
|
229 |
|
if (empty($context['theme_variant'])) |
154
|
229 |
|
{ |
155
|
|
|
continue; |
156
|
|
|
} |
157
|
|
|
|
158
|
287 |
|
$sheets[] = $context['theme_variant'] . '/admin' . $context['theme_variant'] . '.css'; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
loadCSSFile($sheets); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
// No template to load? |
165
|
|
|
if ($template_name === false) |
166
|
|
|
{ |
167
|
|
|
return true; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
$loaded = false; |
171
|
|
|
$template_dir = ''; |
172
|
|
|
$file_functions = FileFunctions::instance(); |
173
|
|
|
foreach ($this->dirs->getDirectories() as $template_dir) |
174
|
|
|
{ |
175
|
|
|
if ($file_functions->fileExists($template_dir . '/' . $template_name . '.template.php')) |
176
|
|
|
{ |
177
|
|
|
$loaded = true; |
178
|
|
|
try |
179
|
287 |
|
{ |
180
|
|
|
$this->dirs->fileInclude( |
181
|
|
|
$template_dir . '/' . $template_name . '.template.php', |
182
|
|
|
true |
183
|
|
|
); |
184
|
287 |
|
} |
185
|
287 |
|
catch (Error $e) |
186
|
287 |
|
{ |
187
|
|
|
$this->templateNotFound($e); |
188
|
287 |
|
} |
189
|
|
|
|
190
|
287 |
|
break; |
191
|
287 |
|
} |
192
|
287 |
|
} |
193
|
287 |
|
|
194
|
|
|
if ($loaded) |
195
|
287 |
|
{ |
196
|
|
|
if ($db_show_debug === true) |
197
|
|
|
{ |
198
|
|
|
Debug::instance()->add( |
199
|
287 |
|
'templates', |
200
|
|
|
$template_name . ' (' . basename($template_dir) . ')' |
201
|
287 |
|
); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
// If they have specified an initialization function for this template, go ahead and call it now. |
205
|
|
|
if (function_exists('template_' . $template_name . '_init')) |
206
|
|
|
{ |
207
|
|
|
call_user_func('template_' . $template_name . '_init'); |
208
|
|
|
} |
209
|
|
|
} |
210
|
287 |
|
// Hmmm... doesn't exist?! I don't suppose the directory is wrong, is it? |
211
|
|
|
elseif (!$file_functions->fileExists($settings['default_theme_dir']) |
212
|
287 |
|
&& $file_functions->fileExists(BOARDDIR . '/themes/default')) |
213
|
|
|
{ |
214
|
|
|
$settings['default_theme_dir'] = BOARDDIR . '/themes/default'; |
215
|
|
|
$this->dirs->addDirectory($settings['default_theme_dir']); |
216
|
|
|
|
217
|
|
|
if (!empty($context['user']['is_admin']) && !isset($_GET['th'])) |
218
|
|
|
{ |
219
|
|
|
Txt::load('Errors'); |
220
|
|
|
|
221
|
|
|
if (!isset($context['security_controls_files']['title'])) |
222
|
|
|
{ |
223
|
|
|
$context['security_controls_files']['title'] = $txt['generic_warning']; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
$context['security_controls_files']['errors']['theme_dir'] = |
227
|
|
|
'<a href="' . getUrl('admin', ['action' => 'admin', 'area' => 'theme', 'sa' => 'list', 'th' => 1, '{session_data}']) . '">' . $txt['theme_dir_wrong'] . '</a>'; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
$this->load($template_name); |
231
|
|
|
} |
232
|
|
|
// Cause an error otherwise. |
233
|
|
|
elseif ($template_name !== 'Errors' && $template_name !== 'index' && $fatal) |
234
|
|
|
{ |
235
|
|
|
throw new Exception( |
236
|
|
|
'theme_template_error', |
237
|
|
|
'template', |
238
|
|
|
[(string) $template_name] |
239
|
|
|
); |
240
|
|
|
} |
241
|
|
|
elseif ($fatal) |
242
|
|
|
{ |
243
|
|
|
throw new Exception( |
244
|
|
|
sprintf( |
245
|
|
|
$txt['theme_template_error'] ?? 'Unable to load themes/default/%s.template.php!', |
246
|
|
|
(string) $template_name |
247
|
|
|
), 'template' |
248
|
|
|
); |
249
|
|
|
} |
250
|
|
|
else |
251
|
|
|
{ |
252
|
|
|
return false; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
return true; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Displays an error when a template is not found or has syntax errors preventing its |
260
|
|
|
* loading |
261
|
|
|
* |
262
|
287 |
|
* @param Error $e |
263
|
|
|
*/ |
264
|
|
|
protected function templateNotFound(Error $e) |
265
|
|
|
{ |
266
|
|
|
global $context, $txt, $scripturl, $boardurl; |
267
|
|
|
|
268
|
|
|
obStart(); |
269
|
|
|
|
270
|
|
|
// Don't cache error pages!! |
271
|
|
|
Headers::instance() |
272
|
|
|
->removeHeader('all') |
273
|
|
|
->header('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT') |
274
|
|
|
->header('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT') |
275
|
|
|
->header('Cache-Control', 'no-cache') |
276
|
|
|
->contentType('text/html', 'UTF-8') |
277
|
|
|
->sendHeaders(); |
278
|
341 |
|
|
279
|
|
|
if (!isset($txt['template_parse_error'])) |
280
|
|
|
{ |
281
|
|
|
$txt['template_parse_error'] = 'Template Parse Error!'; |
282
|
|
|
$txt['template_parse_error_message'] = |
283
|
|
|
'It seems something has gone sour on the forum with the template system. This problem should only be temporary, so please come back later and try again. If you continue to see this message, please contact the administrator.<br /><br />You can also try <a href="javascript:location.reload();">refreshing this page</a>.'; |
284
|
|
|
$txt['template_parse_error_details'] = |
285
|
341 |
|
'There was a problem loading the <span style="font-family: monospace;"><strong>%1$s</strong></span> template or language file. Please check the syntax and try again - remember, single quotes (<span style="font-family: monospace;">\'</span>) often have to be escaped with a slash (<span style="font-family: monospace;">\\</span>). To see more specific error information from PHP, try <a href="%2$s%1$s" class="extern">accessing the file directly</a>.<br /><br />You may want to try to <a href="javascript:location.reload();">refresh this page</a> or <a href="%3$s">use the default theme</a>.'; |
286
|
|
|
$txt['template_parse_undefined'] = |
287
|
|
|
'An undefined error occurred during the parsing of this template'; |
288
|
341 |
|
} |
289
|
|
|
|
290
|
64 |
|
// First, let's get the doctype and language information out of the way. |
291
|
|
|
echo '<!DOCTYPE html> |
292
|
|
|
<html ', empty($context['right_to_left']) ? '' : 'dir="rtl"', '> |
293
|
|
|
<head> |
294
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
295
|
295 |
|
<style> |
296
|
|
|
body { |
297
|
|
|
color: #222; |
298
|
|
|
background-color: #FAFAFA; |
299
|
295 |
|
font-family: Verdana, arial, helvetica, serif; |
300
|
|
|
font-size: small; |
301
|
|
|
} |
302
|
|
|
a {color: #49643D;} |
303
|
295 |
|
.curline {background: #ffe; display: inline-block;} |
304
|
|
|
.lineno {color:#222; -webkit-user-select: none;-moz-user-select: none; -ms-user-select: none;user-select: none;} |
305
|
239 |
|
</style>'; |
306
|
|
|
|
307
|
261 |
|
if (!allowedTo('admin_forum')) |
308
|
|
|
{ |
309
|
295 |
|
echo ' |
310
|
|
|
<title>', $txt['template_parse_error'], '</title> |
311
|
|
|
</head> |
312
|
|
|
<body> |
313
|
|
|
<h3>', $txt['template_parse_error'], '</h3> |
314
|
|
|
', $txt['template_parse_error_message'], ' |
315
|
|
|
</body> |
316
|
295 |
|
</html>'; |
317
|
|
|
} |
318
|
|
|
else |
319
|
|
|
{ |
320
|
|
|
$error = $e->getMessage(); |
321
|
|
|
|
322
|
|
|
echo ' |
323
|
|
|
<title>', $txt['template_parse_error'], '</title> |
324
|
|
|
</head> |
325
|
|
|
<body> |
326
|
|
|
<h3>', $txt['template_parse_error'], '</h3> |
327
|
|
|
', sprintf( |
328
|
|
|
$txt['template_parse_error_details'], |
329
|
|
|
strtr( |
330
|
|
|
$e->getFile(), |
331
|
|
|
[ |
332
|
|
|
BOARDDIR => '', |
333
|
|
|
strtr(BOARDDIR, '\\', '/') => '', |
334
|
|
|
] |
335
|
|
|
), |
336
|
|
|
$boardurl, |
337
|
|
|
$scripturl . '?theme=1' |
338
|
|
|
); |
339
|
|
|
|
340
|
|
|
echo ' |
341
|
|
|
<hr /> |
342
|
|
|
|
343
|
|
|
<div style="margin: 0 20px;"><span style="font-family: monospace;">', str_replace('\\', '/', strtr( |
344
|
|
|
$error, |
345
|
|
|
[ |
346
|
|
|
'<strong>' . BOARDDIR => '<strong>...', |
347
|
|
|
'<strong>' . strtr(BOARDDIR, '\\', '/') => '<strong>...', |
348
|
|
|
] |
349
|
|
|
)), '</span></div>'; |
350
|
|
|
|
351
|
|
|
$this->printLines($e); |
352
|
|
|
|
353
|
|
|
echo ' |
354
|
|
|
</body> |
355
|
|
|
</html>'; |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
die; |
|
|
|
|
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* Print lines from the file with the error. |
363
|
|
|
* |
364
|
|
|
* @param Error $e |
365
|
|
|
* @uses getHighlightedLinesFromFile() Highlights syntax. |
366
|
|
|
* |
367
|
|
|
*/ |
368
|
|
|
private function printLines(Error $e): void |
369
|
|
|
{ |
370
|
|
|
if (allowedTo('admin_forum')) |
371
|
|
|
{ |
372
|
|
|
$data = iterator_to_array( |
373
|
|
|
$this->getHighlightedLinesFromFile( |
374
|
|
|
$e->getFile(), |
375
|
|
|
max($e->getLine() - 9, 1), |
376
|
|
|
min($e->getLine() + 4, count(file($e->getFile())) + 1) |
377
|
|
|
) |
378
|
|
|
); |
379
|
|
|
|
380
|
|
|
// Mark the offending line. |
381
|
|
|
$data[$e->getLine()] = sprintf( |
382
|
|
|
'<div class="curline">%s</div>', |
383
|
|
|
$data[$e->getLine()] |
384
|
|
|
); |
385
|
|
|
|
386
|
|
|
echo ' |
387
|
|
|
<div style="margin: 2ex 20px; width: 96%; overflow: auto;"><pre style="margin: 0;">'; |
388
|
|
|
|
389
|
|
|
// Show the relevant lines... |
390
|
|
|
foreach ($data as $line => $content) |
391
|
|
|
{ |
392
|
|
|
printf( |
393
|
|
|
'<span class="lineno">%d:</span> ', |
394
|
|
|
$line |
395
|
|
|
); |
396
|
|
|
|
397
|
|
|
echo $content, "\n"; |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
echo '</pre></div>'; |
401
|
|
|
} |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* Highlights PHP syntax. |
406
|
|
|
* |
407
|
|
|
* @param string $file Name of file to highlight. |
408
|
|
|
* @param int $min Minimum line number to return. |
409
|
|
|
* @param int $max Maximum line number to return. |
410
|
|
|
* |
411
|
|
|
* @used-by printLines() Prints syntax for template files with errors. |
412
|
|
|
* @return Generator Highlighted lines ranging from $min to $max. |
413
|
|
|
* @uses highlight_file() Highlights syntax. |
414
|
|
|
* |
415
|
|
|
*/ |
416
|
|
|
public function getHighlightedLinesFromFile(string $file, int $min, int $max): Generator |
417
|
|
|
{ |
418
|
|
|
foreach (preg_split('~<br( /)?>~', highlight_file($file, true)) as $line => $content) |
|
|
|
|
419
|
|
|
{ |
420
|
|
|
if ($line < $min) |
421
|
|
|
{ |
422
|
|
|
continue; |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
if ($line > $max) |
426
|
|
|
{ |
427
|
|
|
continue; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
yield $line + 1 => $content; |
431
|
|
|
} |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* Load a sub-template. |
436
|
|
|
* |
437
|
|
|
* What it does: |
438
|
|
|
* - loads the sub template specified by sub_template_name, which must be in an |
439
|
|
|
* already-loaded template. |
440
|
|
|
* - if ?debug is in the query string, shows administrators a marker after every sub |
441
|
|
|
* template for debugging purposes. |
442
|
|
|
* |
443
|
|
|
* @param string $sub_template_name |
444
|
|
|
* @param bool|string $fatal = false, $fatal = true is for templates that |
445
|
|
|
* shouldn't get a 'pretty' error screen 'ignore' to skip |
446
|
|
|
* |
447
|
|
|
* @throws Exception theme_template_error |
448
|
|
|
* |
449
|
|
|
*/ |
450
|
|
|
public function loadSubTemplate($sub_template_name, $fatal = false) |
451
|
|
|
{ |
452
|
|
|
global $txt, $db_show_debug; |
453
|
|
|
|
454
|
|
|
if (!empty($sub_template_name)) |
455
|
|
|
{ |
456
|
|
|
if ($db_show_debug === true) |
457
|
|
|
{ |
458
|
|
|
Debug::instance()->add('sub_templates', $sub_template_name); |
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
// Figure out what the template function is named. |
462
|
|
|
$theme_function = 'template_' . $sub_template_name; |
463
|
|
|
|
464
|
|
|
if (function_exists($theme_function)) |
465
|
|
|
{ |
466
|
|
|
try |
467
|
|
|
{ |
468
|
|
|
$this->_templateDebug($sub_template_name, true); |
469
|
|
|
$theme_function(); |
470
|
|
|
} |
471
|
|
|
catch (Error $e) |
472
|
|
|
{ |
473
|
|
|
$this->templateNotFound($e); |
474
|
|
|
} |
475
|
|
|
} |
476
|
|
|
elseif ($fatal === false) |
477
|
|
|
{ |
478
|
|
|
throw new Exception( |
479
|
|
|
'theme_template_error', |
480
|
|
|
'template', |
481
|
|
|
[(string) $sub_template_name] |
482
|
|
|
); |
483
|
|
|
} |
484
|
|
|
elseif ($fatal !== 'ignore') |
485
|
|
|
{ |
486
|
|
|
throw new BadFunctionCallException( |
487
|
|
|
Errors::instance()->log_error( |
488
|
|
|
sprintf( |
489
|
|
|
$txt['theme_template_error'] ?? 'Unable to load the %s sub template!', |
490
|
|
|
(string) $sub_template_name |
491
|
|
|
), |
492
|
|
|
'template' |
493
|
|
|
) |
494
|
|
|
); |
495
|
|
|
} |
496
|
|
|
} |
497
|
|
|
|
498
|
|
|
$this->_templateDebug($sub_template_name); |
499
|
|
|
} |
500
|
229 |
|
|
501
|
|
|
/** |
502
|
229 |
|
* Are we showing debugging for templates? Just make sure not to do it before the doctype... |
503
|
|
|
* |
504
|
229 |
|
* @param bool $start |
505
|
|
|
* @param string $sub_template_name |
506
|
|
|
*/ |
507
|
|
|
private function _templateDebug($sub_template_name, $start = false) |
508
|
|
|
{ |
509
|
|
|
$req = HttpReq::instance(); |
510
|
|
|
|
511
|
|
|
if ($req->isSet('debug') |
512
|
|
|
&& $sub_template_name !== 'init' |
513
|
|
|
&& ob_get_length() > 0 |
514
|
|
|
&& empty($req->getRequest('xml')) |
515
|
|
|
&& empty($req->getRequest('api')) |
516
|
|
|
&& allowedTo('admin_forum')) |
517
|
|
|
{ |
518
|
|
|
echo ' |
519
|
283 |
|
<div class="warningbox">---- ', $sub_template_name, ' ', ($start ? 'starts' : 'ends'), ' ----</div>'; |
520
|
|
|
} |
521
|
|
|
} |
522
|
|
|
|
523
|
|
|
/** |
524
|
|
|
* @return Directories |
525
|
283 |
|
*/ |
526
|
283 |
|
public function getDirectory() |
527
|
140 |
|
{ |
528
|
140 |
|
return $this->dirs; |
529
|
140 |
|
} |
530
|
|
|
} |
531
|
|
|
|
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths