1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Initialize the ElkArte environment. |
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
|
|
|
use BBC\ParserWrapper; |
17
|
|
|
use ElkArte\Cache\Cache; |
18
|
|
|
use ElkArte\Controller\Auth; |
19
|
|
|
use ElkArte\Debug; |
20
|
|
|
use ElkArte\Errors\Errors; |
|
|
|
|
21
|
|
|
use ElkArte\EventManager; |
22
|
|
|
use ElkArte\ext\Composer\Autoload\ClassLoader; |
23
|
|
|
use ElkArte\Helper\TokenHash; |
24
|
|
|
use ElkArte\Hooks; |
25
|
|
|
use ElkArte\MembersList; |
26
|
|
|
use ElkArte\Request; |
27
|
|
|
use ElkArte\Server; |
28
|
|
|
use ElkArte\Themes\ThemeLoader; |
29
|
|
|
use ElkArte\User; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Class Bootstrap |
33
|
|
|
* |
34
|
|
|
* Takes care of the initial loading and feeding of Elkarte from |
35
|
|
|
* either SSI or Index |
36
|
|
|
*/ |
37
|
|
|
class Bootstrap |
38
|
|
|
{ |
39
|
|
|
/** @var array What is returned by the function getrusage. */ |
40
|
|
|
protected $rusage_start = []; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Bootstrap constructor. |
44
|
|
|
* |
45
|
|
|
* @param bool $standalone |
46
|
|
|
* - true to boot outside elkarte |
47
|
|
|
* - false to bootstrap the main elkarte site. |
48
|
|
|
*/ |
49
|
|
|
public function __construct($standalone = true) |
50
|
|
|
{ |
51
|
|
|
// Bootstrap only once. |
52
|
|
|
if (!defined('ELKBOOT')) |
53
|
|
|
{ |
54
|
|
|
// We're going to set a few globals |
55
|
|
|
global $time_start, $ssi_error_reporting, $db_show_debug; |
56
|
|
|
|
57
|
|
|
// Your on the clock |
58
|
|
|
$time_start = microtime(true); |
59
|
|
|
|
60
|
|
|
// Unless settings.php tells us otherwise |
61
|
|
|
$db_show_debug = false; |
62
|
|
|
|
63
|
|
|
// Report errors but not depreciated ones |
64
|
|
|
$ssi_error_reporting = error_reporting(E_ALL & ~E_DEPRECATED); |
65
|
|
|
|
66
|
|
|
// Get the things needed for ALL modes |
67
|
|
|
$this->bringUpBasics(); |
68
|
|
|
|
69
|
|
|
// Going to run from the side entrance and not directly from inside elkarte |
70
|
|
|
if ($standalone) |
71
|
|
|
{ |
72
|
|
|
$this->ssi_main(); |
73
|
|
|
} |
74
|
|
|
} |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Calls the various initialization functions in the needed order |
79
|
|
|
*/ |
80
|
|
|
public function bringUpBasics() |
81
|
|
|
{ |
82
|
|
|
$this->setConstants(); |
83
|
|
|
$this->setRusage(); |
84
|
|
|
$this->clearGlobals(); |
85
|
|
|
$this->loadSettingsFile(); |
86
|
|
|
$this->validatePaths(); |
87
|
|
|
$this->loadDependants(); |
88
|
|
|
$this->loadAutoloader(); |
89
|
|
|
$this->checkMaintance(); |
90
|
|
|
$this->setDebug(); |
91
|
|
|
$this->bringUp(); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Set the core constants, you know the ones we often forget to |
96
|
|
|
* update on new releases. |
97
|
|
|
*/ |
98
|
|
|
private function setConstants() |
99
|
|
|
{ |
100
|
|
|
// First things first, but not necessarily in that order. |
101
|
|
|
if (!defined('ELK')) |
102
|
|
|
{ |
103
|
|
|
define('ELK', '1'); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
define('ELKBOOT', '1'); |
107
|
|
|
|
108
|
|
|
// The software version |
109
|
|
|
define('FORUM_VERSION', 'ElkArte 2.0 dev'); |
110
|
|
|
|
111
|
|
|
// Shortcut for the browser cache stale |
112
|
|
|
define('CACHE_STALE', '?20dev'); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Get initial resource usage |
117
|
|
|
*/ |
118
|
|
|
private function setRusage() |
119
|
|
|
{ |
120
|
|
|
$this->rusage_start = getrusage(); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* If they glo, they need to be cleaned. |
125
|
|
|
*/ |
126
|
|
|
private function clearGlobals() |
127
|
|
|
{ |
128
|
|
|
// We don't need no globals. (a bug in "old" versions of PHP) |
129
|
|
|
foreach (['db_character_set', 'cachedir'] as $variable) |
130
|
|
|
{ |
131
|
|
|
if (isset($GLOBALS[$variable])) |
132
|
|
|
{ |
133
|
|
|
unset($GLOBALS[$variable], $GLOBALS[$variable]); |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Loads the settings values into the global space |
140
|
|
|
*/ |
141
|
|
|
private function loadSettingsFile() |
142
|
|
|
{ |
143
|
|
|
// All those wonderful things found in settings |
144
|
|
|
global $maintenance, $mtitle, $msubject, $mmessage, $mbname, $language, $boardurl, $webmaster_email; |
145
|
|
|
global $cookiename, $db_type, $db_server, $db_port, $db_name, $db_user, $db_passwd; |
146
|
|
|
global $ssi_db_user, $ssi_db_passwd, $db_prefix, $db_persist, $db_error_send, $cache_accelerator; |
147
|
|
|
global $cache_uid, $cache_password, $cache_enable, $cache_memcached, $db_show_debug, $url_format; |
148
|
|
|
global $cachedir, $boarddir, $sourcedir, $extdir, $languagedir; |
149
|
|
|
|
150
|
|
|
// Where the Settings.php file is located |
151
|
|
|
$settings_loc = __DIR__ . '/Settings.php'; |
152
|
|
|
|
153
|
|
|
// First thing: if the installation dir exists, just send anybody there |
154
|
|
|
// The IGNORE_INSTALL_DIR constant is for developers only. Do not add it on production sites |
155
|
|
|
if (file_exists('install') && (file_exists('install/install.php') || file_exists('install/upgrade.php'))) |
156
|
|
|
{ |
157
|
|
|
if (file_exists($settings_loc)) |
158
|
|
|
{ |
159
|
|
|
require_once($settings_loc); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
if (!defined('IGNORE_INSTALL_DIR')) |
163
|
|
|
{ |
164
|
|
|
$redirec_file = file_exists($settings_loc) && empty($_SESSION['installing']) ? 'upgrade.php' : 'install.php'; |
165
|
|
|
|
166
|
|
|
// To early for constants or autoloader |
167
|
|
|
require_once($boarddir . '/sources/ElkArte/Server.php'); |
168
|
|
|
$server = new Server($_SERVER); |
169
|
|
|
|
170
|
|
|
$version_running = str_replace('ElkArte ', '', FORUM_VERSION); |
171
|
|
|
$location = $server->supportsSSL() ? 'https://' : 'http://'; |
172
|
|
|
$location .= $server->getHost(); |
173
|
|
|
$temp = preg_replace('~/' . preg_quote(basename($boardurl . '/index.php'), '~') . '(/.+)?$~', '', str_replace('\\', '/', dirname($_SERVER['PHP_SELF']))); |
174
|
|
|
$location .= ($temp !== '/') ? $temp : ''; |
175
|
|
|
|
176
|
|
|
// Too early to use Headers class etc. |
177
|
|
|
header('Location:' . $location . '/install/' . $redirec_file . '?v=' . $version_running); |
178
|
|
|
die(); |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
else |
182
|
|
|
{ |
183
|
|
|
require_once($settings_loc); |
184
|
|
|
} |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Validate the paths set in Settings.php, correct as needed and move them to constants. |
189
|
|
|
*/ |
190
|
|
|
private function validatePaths() |
191
|
|
|
{ |
192
|
|
|
global $boarddir, $sourcedir, $cachedir, $extdir, $languagedir; |
193
|
|
|
|
194
|
|
|
// Make sure the paths are correct... at least try to fix them. |
195
|
|
|
if (!file_exists($boarddir) && file_exists(__DIR__ . '/bootstrap.php')) |
196
|
|
|
{ |
197
|
|
|
$boarddir = __DIR__; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
if (!file_exists($sourcedir . '/SiteDispatcher.class.php') && file_exists($boarddir . '/sources')) |
201
|
|
|
{ |
202
|
|
|
$sourcedir = $boarddir . '/sources'; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
// Check that directories which didn't exist in past releases are initialized. |
206
|
|
|
if ((empty($cachedir) || !file_exists($cachedir)) && file_exists($boarddir . '/cache')) |
207
|
|
|
{ |
208
|
|
|
$cachedir = $boarddir . '/cache'; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
if ((empty($extdir) || !file_exists($extdir)) && file_exists($sourcedir . '/ext')) |
212
|
|
|
{ |
213
|
|
|
$extdir = $sourcedir . '/ext'; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
if ((empty($languagedir) || !file_exists($languagedir)) && file_exists($sourcedir . '/Languages/Index')) |
217
|
|
|
{ |
218
|
|
|
$languagedir = $sourcedir . '/ElkArte/Languages'; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
// Time to forget about variables and go with constants! |
222
|
|
|
define('BOARDDIR', $boarddir); |
223
|
|
|
define('CACHEDIR', $cachedir); |
224
|
|
|
define('EXTDIR', $extdir); |
225
|
|
|
define('LANGUAGEDIR', $languagedir); |
226
|
|
|
define('SOURCEDIR', $sourcedir); |
227
|
|
|
define('ADMINDIR', $sourcedir . '/ElkArte/AdminController'); |
228
|
|
|
define('CONTROLLERDIR', $sourcedir . '/ElkArte/Controller'); |
229
|
|
|
define('SUBSDIR', $sourcedir . '/subs'); |
230
|
|
|
define('ADDONSDIR', $boarddir . '/addons'); |
231
|
|
|
unset($boarddir, $cachedir, $sourcedir, $languagedir, $extdir); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* We require access to several important files, so load them upfront |
236
|
|
|
*/ |
237
|
|
|
private function loadDependants() |
238
|
|
|
{ |
239
|
|
|
// Files we cannot live without. |
240
|
|
|
require_once(SOURCEDIR . '/QueryString.php'); |
241
|
|
|
require_once(SOURCEDIR . '/Session.php'); |
242
|
|
|
require_once(SOURCEDIR . '/Subs.php'); |
243
|
|
|
require_once(SOURCEDIR . '/Logging.php'); |
244
|
|
|
require_once(SOURCEDIR . '/Load.php'); |
245
|
|
|
require_once(SOURCEDIR . '/Security.php'); |
246
|
|
|
require_once(SUBSDIR . '/Cache.subs.php'); |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* The autoloader will take care most requests for files |
251
|
|
|
*/ |
252
|
|
|
private function loadAutoloader() |
253
|
|
|
{ |
254
|
|
|
require_once(EXTDIR . '/ClassLoader.php'); |
255
|
|
|
|
256
|
|
|
$loader = new ClassLoader(); |
257
|
|
|
$loader->setPsr4('ElkArte\\', SOURCEDIR . '/ElkArte'); |
258
|
|
|
$loader->setPsr4('BBC\\', SOURCEDIR . '/ElkArte/BBC'); |
259
|
|
|
$loader->register(); |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
/** |
263
|
|
|
* Check if we are in maintenance mode, if so end here. |
264
|
|
|
*/ |
265
|
|
|
private function checkMaintance() |
266
|
|
|
{ |
267
|
|
|
global $maintenance, $ssi_maintenance_off; |
268
|
|
|
|
269
|
|
|
// Don't do john didley if the forum's been shut down completely. |
270
|
|
|
if (empty($maintenance)) |
271
|
|
|
{ |
272
|
|
|
return; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
if ((int) $maintenance !== 2) |
276
|
|
|
{ |
277
|
|
|
return; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
if (isset($ssi_maintenance_off) && $ssi_maintenance_off === true) |
281
|
|
|
{ |
282
|
|
|
return; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
Errors::instance()->display_maintenance_message(); |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
/** |
289
|
|
|
* If you like lots of debug information in error messages and below the footer |
290
|
|
|
* then set $db_show_debug to true in settings. Don't do this on a production site. |
291
|
|
|
*/ |
292
|
|
|
private function setDebug() |
293
|
|
|
{ |
294
|
|
|
global $db_show_debug, $ssi_error_reporting; |
295
|
|
|
|
296
|
|
|
// Show lots of debug information below the page, not for production sites |
297
|
|
|
if ($db_show_debug === true) |
298
|
|
|
{ |
299
|
|
|
Debug::instance()->rusage('start', $this->rusage_start); |
300
|
|
|
$ssi_error_reporting = error_reporting(E_ALL | E_STRICT & ~8192); |
301
|
|
|
} |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* Time to see what has been requested, by whom and dispatch it to the proper handler |
306
|
|
|
*/ |
307
|
|
|
private function bringUp() |
308
|
|
|
{ |
309
|
|
|
global $context; |
310
|
|
|
|
311
|
|
|
// Initiate the database connection and define some database functions to use. |
312
|
|
|
loadDatabase(); |
313
|
|
|
|
314
|
|
|
// Let's set up our shiny new hooks handler. |
315
|
|
|
Hooks::init(database(), Debug::instance()); |
316
|
|
|
|
317
|
|
|
// It's time for settings loaded from the database. |
318
|
|
|
reloadSettings(); |
319
|
|
|
|
320
|
|
|
// Clean the request. |
321
|
|
|
cleanRequest(); |
322
|
|
|
|
323
|
|
|
// Make sure we have the list of members for populating it |
324
|
|
|
MembersList::init(database(), Cache::instance(), ParserWrapper::instance()); |
325
|
|
|
|
326
|
|
|
// Our good ole' contextual array, which will hold everything |
327
|
|
|
if (empty($context)) |
328
|
|
|
{ |
329
|
|
|
$context = []; |
330
|
|
|
} |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
/** |
334
|
|
|
* If you are running SSI standalone, you need to call this function after bootstrap is |
335
|
|
|
* initialized. |
336
|
|
|
*/ |
337
|
|
|
public function ssi_main() |
338
|
|
|
{ |
339
|
|
|
global $ssi_layers, $ssi_theme, $ssi_gzip, $ssi_ban, $ssi_guest_access; |
340
|
|
|
global $modSettings, $context, $board, $topic, $txt; |
341
|
|
|
|
342
|
|
|
// Check on any hacking attempts. |
343
|
|
|
$this->_validRequestCheck(); |
344
|
|
|
|
345
|
|
|
// Gzip output? (because it must be boolean and true, this can't be hacked.) |
346
|
|
|
if (isset($ssi_gzip) && $ssi_gzip === true && detectServer()->outPutCompressionEnabled()) |
347
|
|
|
{ |
348
|
|
|
ob_start('ob_gzhandler'); |
349
|
|
|
} |
350
|
|
|
else |
351
|
|
|
{ |
352
|
|
|
$modSettings['enableCompressedOutput'] = '0'; |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
// Primarily, this is to fix the URLs... |
356
|
|
|
ob_start('ob_sessrewrite'); |
357
|
|
|
|
358
|
|
|
// Start the session... known to scramble SSI includes in cases... |
359
|
|
|
if (!headers_sent()) |
360
|
|
|
{ |
361
|
|
|
loadSession(); |
362
|
|
|
} |
363
|
|
|
else |
364
|
|
|
{ |
365
|
|
|
if (isset($_COOKIE[session_name()]) || isset($_REQUEST[session_name()])) |
366
|
|
|
{ |
367
|
|
|
// Make a stab at it, but ignore the E_WARNINGs generated because we can't send headers. |
368
|
|
|
$temp = error_reporting(error_reporting() & !E_WARNING); |
369
|
|
|
loadSession(); |
370
|
|
|
error_reporting($temp); |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
if (!isset($_SESSION['session_value'])) |
374
|
|
|
{ |
375
|
|
|
$tokenizer = new TokenHash(); |
376
|
|
|
$_SESSION['session_value'] = $tokenizer->generate_hash(32, session_id()); |
377
|
|
|
$_SESSION['session_var'] = substr(preg_replace('~^\d+~', '', $tokenizer->generate_hash(16, session_id())), 0, rand(7, 12)); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
// This is here only to avoid session errors in PHP7 |
381
|
|
|
// microtime effectively forces the replacing of the session in the db each |
382
|
|
|
// time the page is loaded |
383
|
|
|
$_SESSION['mictrotime'] = microtime(); |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
// Get rid of $board and $topic... do stuff loadBoard would do. |
387
|
|
|
unset($board, $topic); |
388
|
|
|
$context['linktree'] = array(); |
389
|
|
|
|
390
|
|
|
// Load the user and their cookie, as well as their settings. |
391
|
|
|
User::load(true); |
392
|
|
|
$context['user']['is_mod'] = User::$info->is_mod ?? false; |
393
|
|
|
|
394
|
|
|
// Load the current user's permissions.... |
395
|
|
|
loadPermissions(); |
396
|
|
|
|
397
|
|
|
// Load the current or SSI theme. (just use $ssi_theme = id_theme;) |
398
|
|
|
new ThemeLoader(isset($ssi_theme) ? (int) $ssi_theme : 0); |
399
|
|
|
|
400
|
|
|
// Load BadBehavior functions, but not when running from CLI |
401
|
|
|
if (!defined('STDIN') && runBadBehavior()) |
402
|
|
|
{ |
403
|
|
|
// 403 and gone |
404
|
|
|
Errors::instance()->display_403_error(true); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
// Take care of any banning that needs to be done. |
408
|
|
|
if (isset($_REQUEST['ssi_ban']) || (isset($ssi_ban) && $ssi_ban === true)) |
409
|
|
|
{ |
410
|
|
|
is_not_banned(); |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
// Do we allow guests in here? |
414
|
|
|
if (empty($ssi_guest_access) && empty($modSettings['allow_guestAccess']) && User::$info->is_guest && basename($_SERVER['PHP_SELF']) !== 'SSI.php') |
415
|
|
|
{ |
416
|
|
|
$controller = new Auth(new EventManager()); |
417
|
|
|
$controller->setUser(User::$info); |
418
|
|
|
$controller->action_kickguest(); |
419
|
|
|
obExit(null, true); |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
if (!empty($modSettings['front_page']) && class_exists($modSettings['front_page']) |
423
|
|
|
&& in_array('frontPageHook', get_class_methods($modSettings['front_page']))) |
424
|
|
|
{ |
425
|
|
|
$modSettings['default_forum_action'] = ['action' => 'forum']; |
426
|
|
|
} |
427
|
|
|
else |
428
|
|
|
{ |
429
|
|
|
$modSettings['default_forum_action'] = []; |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
// Load the stuff like the menu bar, etc. |
433
|
|
|
if (isset($ssi_layers)) |
434
|
|
|
{ |
435
|
|
|
$template_layers = theme()->getLayers(); |
436
|
|
|
$template_layers->removeAll(); |
437
|
|
|
foreach ($ssi_layers as $layer) |
438
|
|
|
{ |
439
|
|
|
$template_layers->addBegin($layer); |
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
template_header(); |
443
|
|
|
} |
444
|
|
|
else |
445
|
|
|
{ |
446
|
|
|
setupThemeContext(); |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
// We need to set up user agent, and make more checks on the request |
450
|
|
|
$req = Request::instance(); |
451
|
|
|
|
452
|
|
|
// Make sure they didn't muss around with the settings... but only if it's not cli. |
453
|
|
|
if (isset($_SERVER['REMOTE_ADDR']) && session_id() === '') |
454
|
|
|
{ |
455
|
|
|
trigger_error($txt['ssi_session_broken']); |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
// Without visiting the forum this session variable might not be set on submit. |
459
|
|
|
if (isset($_SESSION['USER_AGENT'])) |
460
|
|
|
{ |
461
|
|
|
return; |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
if (isset($_GET['ssi_function']) && $_GET['ssi_function'] === 'pollVote') |
465
|
|
|
{ |
466
|
|
|
return; |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
$_SESSION['USER_AGENT'] = $req->user_agent(); |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* Used to ensure SSI requests are valid and not a probing attempt |
474
|
|
|
*/ |
475
|
|
|
private function _validRequestCheck() |
476
|
|
|
{ |
477
|
|
|
global $ssi_theme, $ssi_layers; |
478
|
|
|
|
479
|
|
|
// Check on any hacking attempts. |
480
|
|
|
if ( |
481
|
|
|
isset($_REQUEST['GLOBALS']) || isset($_COOKIE['GLOBALS']) |
482
|
|
|
|| isset($_REQUEST['ssi_theme']) && (int) $_REQUEST['ssi_theme'] === (int) $ssi_theme |
483
|
|
|
|| isset($_COOKIE['ssi_theme']) && (int) $_COOKIE['ssi_theme'] === (int) $ssi_theme |
484
|
|
|
|| isset($_REQUEST['ssi_layers'], $ssi_layers) && $_REQUEST['ssi_layers'] == $ssi_layers |
485
|
|
|
|| isset($_REQUEST['context'])) |
486
|
|
|
{ |
487
|
|
|
die('No access...'); |
|
|
|
|
488
|
|
|
} |
489
|
|
|
} |
490
|
|
|
} |
491
|
|
|
|
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