1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Elgg; |
4
|
|
|
|
5
|
|
|
use Elgg\Di\ServiceProvider; |
6
|
|
|
use Elgg\Filesystem\Directory; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Load, boot, and implement a front controller for an Elgg application |
10
|
|
|
* |
11
|
|
|
* To run as PHP CLI server: |
12
|
|
|
* <code>php -S localhost:8888 /full/path/to/elgg/index.php</code> |
13
|
|
|
* |
14
|
|
|
* The full path is necessary to work around this: https://bugs.php.net/bug.php?id=55726 |
15
|
|
|
* |
16
|
|
|
* @since 2.0.0 |
17
|
|
|
* |
18
|
|
|
* @property-read \Elgg\Menu\Service $menus |
19
|
|
|
* @property-read \Elgg\Views\TableColumn\ColumnFactory $table_columns |
20
|
|
|
*/ |
21
|
|
|
class Application { |
22
|
|
|
|
23
|
|
|
const GET_PATH_KEY = '__elgg_uri'; |
24
|
|
|
const REWRITE_TEST_TOKEN = '__testing_rewrite'; |
25
|
|
|
const REWRITE_TEST_OUTPUT = 'success'; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var ServiceProvider |
29
|
|
|
*/ |
30
|
|
|
private $services; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var string |
34
|
|
|
*/ |
35
|
|
|
private $engine_dir; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var bool |
39
|
|
|
*/ |
40
|
|
|
private static $testing_app; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Property names of the service provider to be exposed via __get() |
44
|
|
|
* |
45
|
|
|
* E.g. the presence of `'foo' => true` in the list would allow _elgg_services()->foo to |
46
|
|
|
* be accessed via elgg()->foo. |
47
|
|
|
* |
48
|
|
|
* @var string[] |
49
|
|
|
*/ |
50
|
|
|
private static $public_services = [ |
51
|
|
|
//'config' => true, |
52
|
|
|
'menus' => true, |
53
|
|
|
'table_columns' => true, |
54
|
|
|
]; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Reference to the loaded Application returned by elgg() |
58
|
|
|
* |
59
|
|
|
* @internal Do not use this. use elgg() to access the application |
60
|
|
|
* @access private |
61
|
|
|
* @var Application |
62
|
|
|
*/ |
63
|
|
|
public static $_instance; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Constructor |
67
|
|
|
* |
68
|
|
|
* Upon construction, no actions are taken to load or boot Elgg. |
69
|
|
|
* |
70
|
|
|
* @param ServiceProvider $services Elgg services provider |
71
|
|
|
*/ |
72
|
182 |
|
public function __construct(ServiceProvider $services) { |
|
|
|
|
73
|
182 |
|
$this->services = $services; |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* The time with microseconds when the Elgg engine was started. |
77
|
|
|
* |
78
|
|
|
* @global float |
79
|
|
|
*/ |
80
|
182 |
|
if (!isset($GLOBALS['START_MICROTIME'])) { |
81
|
1 |
|
$GLOBALS['START_MICROTIME'] = microtime(true); |
82
|
1 |
|
} |
83
|
|
|
|
84
|
182 |
|
$services->timer->begin([]); |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* This was introduced in 2.0 in order to remove all internal non-API state from $CONFIG. This will |
88
|
|
|
* be a breaking change, but frees us to refactor in 2.x without fear of plugins depending on |
89
|
|
|
* $CONFIG. |
90
|
|
|
* |
91
|
|
|
* @access private |
92
|
|
|
*/ |
93
|
182 |
|
if (!isset($GLOBALS['_ELGG'])) { |
94
|
|
|
$GLOBALS['_ELGG'] = new \stdClass(); |
95
|
|
|
} |
96
|
|
|
|
97
|
182 |
|
$this->engine_dir = __DIR__ . '/../..'; |
98
|
182 |
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Load settings.php |
102
|
|
|
* |
103
|
|
|
* This is done automatically during the boot process or before requesting a database object |
104
|
|
|
* |
105
|
|
|
* @see Config::loadSettingsFile |
106
|
|
|
* @return void |
107
|
|
|
*/ |
108
|
|
|
public function loadSettings() { |
109
|
|
|
$this->services->config->loadSettingsFile(); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Load all Elgg procedural code and wire up boot events, but don't boot |
114
|
|
|
* |
115
|
|
|
* This is used for internal testing purposes |
116
|
|
|
* |
117
|
|
|
* @return void |
118
|
|
|
* @access private |
119
|
|
|
* @internal |
120
|
|
|
*/ |
121
|
180 |
|
public function loadCore() { |
122
|
180 |
|
if (function_exists('elgg')) { |
123
|
180 |
|
return; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
$lib_dir = self::elggDir()->chroot("engine/lib"); |
127
|
|
|
|
128
|
|
|
// load the rest of the library files from engine/lib/ |
129
|
|
|
// All on separate lines to make diffs easy to read + make it apparent how much |
130
|
|
|
// we're actually loading on every page (Hint: it's too much). |
131
|
|
|
$lib_files = array( |
132
|
|
|
// Needs to be loaded first to correctly bootstrap |
133
|
|
|
'autoloader.php', |
134
|
|
|
'elgglib.php', |
135
|
|
|
|
136
|
|
|
// The order of these doesn't matter, so keep them alphabetical |
137
|
|
|
'access.php', |
138
|
|
|
'actions.php', |
139
|
|
|
'admin.php', |
140
|
|
|
'annotations.php', |
141
|
|
|
'cache.php', |
142
|
|
|
'comments.php', |
143
|
|
|
'configuration.php', |
144
|
|
|
'cron.php', |
145
|
|
|
'database.php', |
146
|
|
|
'entities.php', |
147
|
|
|
'extender.php', |
148
|
|
|
'filestore.php', |
149
|
|
|
'friends.php', |
150
|
|
|
'group.php', |
151
|
|
|
'input.php', |
152
|
|
|
'languages.php', |
153
|
|
|
'mb_wrapper.php', |
154
|
|
|
'memcache.php', |
155
|
|
|
'metadata.php', |
156
|
|
|
'metastrings.php', |
157
|
|
|
'navigation.php', |
158
|
|
|
'notification.php', |
159
|
|
|
'objects.php', |
160
|
|
|
'output.php', |
161
|
|
|
'pagehandler.php', |
162
|
|
|
'pageowner.php', |
163
|
|
|
'pam.php', |
164
|
|
|
'plugins.php', |
165
|
|
|
'private_settings.php', |
166
|
|
|
'relationships.php', |
167
|
|
|
'river.php', |
168
|
|
|
'sessions.php', |
169
|
|
|
'sites.php', |
170
|
|
|
'statistics.php', |
171
|
|
|
'system_log.php', |
172
|
|
|
'tags.php', |
173
|
|
|
'user_settings.php', |
174
|
|
|
'users.php', |
175
|
|
|
'upgrade.php', |
176
|
|
|
'views.php', |
177
|
|
|
'widgets.php', |
178
|
|
|
|
179
|
|
|
// backward compatibility |
180
|
|
|
'deprecated-1.9.php', |
181
|
|
|
'deprecated-1.10.php', |
182
|
|
|
'deprecated-1.11.php', |
183
|
|
|
'deprecated-1.12.php', |
184
|
|
|
'deprecated-2.1.php', |
185
|
|
|
); |
186
|
|
|
|
187
|
|
|
// isolate global scope |
188
|
|
|
call_user_func(function () use ($lib_dir, $lib_files) { |
189
|
|
|
|
190
|
|
|
$setups = array(); |
191
|
|
|
|
192
|
|
|
// include library files, capturing setup functions |
193
|
|
|
foreach ($lib_files as $file) { |
194
|
|
|
$setup = (require_once $lib_dir->getPath($file)); |
195
|
|
|
|
196
|
|
|
if ($setup instanceof \Closure) { |
197
|
|
|
$setups[$file] = $setup; |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
// store instance to be returned by elgg() |
202
|
|
|
self::$_instance = $this; |
203
|
|
|
|
204
|
|
|
// set up autoloading and DIC |
205
|
|
|
_elgg_services($this->services); |
|
|
|
|
206
|
|
|
|
207
|
|
|
$events = $this->services->events; |
208
|
|
|
$hooks = $this->services->hooks; |
209
|
|
|
|
210
|
|
|
// run setups |
211
|
|
|
foreach ($setups as $func) { |
212
|
|
|
$func($events, $hooks); |
213
|
|
|
} |
214
|
|
|
}); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* Replacement for loading engine/start.php |
219
|
|
|
* |
220
|
|
|
* @return self |
221
|
|
|
*/ |
222
|
|
|
public static function start() { |
223
|
|
|
$app = self::create(); |
224
|
|
|
$app->bootCore(); |
225
|
|
|
return $app; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Bootstrap the Elgg engine, loads plugins, and calls initial system events |
230
|
|
|
* |
231
|
|
|
* This method loads the full Elgg engine, checks the installation |
232
|
|
|
* state, and triggers a series of events to finish booting Elgg: |
233
|
|
|
* - {@elgg_event boot system} |
234
|
|
|
* - {@elgg_event init system} |
235
|
|
|
* - {@elgg_event ready system} |
236
|
|
|
* |
237
|
|
|
* If Elgg is not fully installed, the browser will be redirected to an installation page. |
238
|
|
|
* |
239
|
|
|
* @return void |
240
|
|
|
*/ |
241
|
|
|
public function bootCore() { |
242
|
|
|
|
243
|
|
|
$config = $this->services->config; |
244
|
|
|
|
245
|
|
|
if ($this->isTestingApplication()) { |
246
|
|
|
throw new \RuntimeException('Unit tests should not call ' . __METHOD__); |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
if ($config->getVolatile('boot_complete')) { |
250
|
|
|
return; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
$this->loadSettings(); |
254
|
|
|
|
255
|
|
|
$config->set('boot_complete', false); |
256
|
|
|
|
257
|
|
|
// This will be overridden by the DB value but may be needed before the upgrade script can be run. |
258
|
|
|
$config->set('default_limit', 10); |
259
|
|
|
|
260
|
|
|
// in case not loaded already |
261
|
|
|
$this->loadCore(); |
262
|
|
|
|
263
|
|
|
$events = $this->services->events; |
264
|
|
|
|
265
|
|
|
// Connect to database, load language files, load configuration, init session |
266
|
|
|
// Plugins can't use this event because they haven't been loaded yet. |
267
|
|
|
$events->trigger('boot', 'system'); |
268
|
|
|
|
269
|
|
|
// Load the plugins that are active |
270
|
|
|
$this->services->plugins->load(); |
271
|
|
|
|
272
|
|
|
$root = Directory\Local::root(); |
273
|
|
|
if ($root->getPath() != self::elggDir()->getPath()) { |
274
|
|
|
// Elgg is installed as a composer dep, so try to treat the root directory |
275
|
|
|
// as a custom plugin that is always loaded last and can't be disabled... |
276
|
|
|
if (!elgg_get_config('system_cache_loaded')) { |
277
|
|
|
// configure view locations for the custom plugin (not Elgg core) |
278
|
|
|
$viewsFile = $root->getFile('views.php'); |
279
|
|
|
if ($viewsFile->exists()) { |
280
|
|
|
$viewsSpec = $viewsFile->includeFile(); |
281
|
|
|
if (is_array($viewsSpec)) { |
282
|
|
|
_elgg_services()->views->mergeViewsSpec($viewsSpec); |
283
|
|
|
} |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
// find views for the custom plugin (not Elgg core) |
287
|
|
|
_elgg_services()->views->registerPluginViews($root->getPath()); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
if (!elgg_get_config('i18n_loaded_from_cache')) { |
291
|
|
|
_elgg_services()->translator->registerPluginTranslations($root->getPath()); |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
// This is root directory start.php, not elgg/engine/start.php |
295
|
|
|
$root_start = $root->getPath("start.php"); |
296
|
|
|
if (is_file($root_start)) { |
297
|
|
|
require $root_start; |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
|
302
|
|
|
// @todo move loading plugins into a single boot function that replaces 'boot', 'system' event |
303
|
|
|
// and then move this code in there. |
304
|
|
|
// This validates the view type - first opportunity to do it is after plugins load. |
305
|
|
|
$viewtype = elgg_get_viewtype(); |
306
|
|
|
if (!elgg_is_registered_viewtype($viewtype)) { |
307
|
|
|
elgg_set_viewtype('default'); |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
$this->allowPathRewrite(); |
311
|
|
|
|
312
|
|
|
// Allows registering handlers strictly before all init, system handlers |
313
|
|
|
$events->trigger('plugins_boot', 'system'); |
314
|
|
|
|
315
|
|
|
// Complete the boot process for both engine and plugins |
316
|
|
|
$events->trigger('init', 'system'); |
317
|
|
|
|
318
|
|
|
$config->set('boot_complete', true); |
319
|
|
|
|
320
|
|
|
// System loaded and ready |
321
|
|
|
$events->trigger('ready', 'system'); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Get a Database wrapper for performing queries without booting Elgg |
326
|
|
|
* |
327
|
|
|
* If settings.php has not been loaded, it will be loaded to configure the DB connection. |
328
|
|
|
* |
329
|
|
|
* @note Do not type hint on \Elgg\Database, as this will fail in 3.0. If you must type hint, |
330
|
|
|
* expect an \Elgg\Application\Database. |
331
|
|
|
* |
332
|
|
|
* @note Before boot, the Database instance will not yet be bound to a Logger. |
333
|
|
|
* |
334
|
|
|
* @return \Elgg\Application\Database |
335
|
|
|
*/ |
336
|
|
|
public function getDb() { |
337
|
|
|
$this->loadSettings(); |
338
|
|
|
return $this->services->publicDb; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* Get an undefined property |
343
|
|
|
* |
344
|
|
|
* @param string $name The property name accessed |
345
|
|
|
* |
346
|
|
|
* @return mixed |
347
|
|
|
*/ |
348
|
|
|
public function __get($name) { |
349
|
|
|
if (isset(self::$public_services[$name])) { |
350
|
|
|
return $this->services->{$name}; |
351
|
|
|
} |
352
|
|
|
trigger_error("Undefined property: " . __CLASS__ . ":\${$name}"); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* Creates a new, trivial instance of Elgg\Application and set it as the singleton instance. |
357
|
|
|
* If the singleton is already set, it's returned. |
358
|
|
|
* |
359
|
|
|
* @return self |
360
|
|
|
*/ |
361
|
|
|
private static function create() { |
362
|
|
|
if (self::$_instance === null) { |
363
|
|
|
// we need to register for shutdown before Symfony registers the |
364
|
|
|
// session_write_close() function. https://github.com/Elgg/Elgg/issues/9243 |
365
|
|
|
register_shutdown_function(function () { |
366
|
|
|
// There are cases where we may exit before this function is defined |
367
|
|
|
if (function_exists('_elgg_shutdown_hook')) { |
368
|
|
|
_elgg_shutdown_hook(); |
369
|
|
|
} |
370
|
|
|
}); |
371
|
|
|
|
372
|
|
|
self::$_instance = new self(new Di\ServiceProvider(new Config())); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
return self::$_instance; |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
/** |
379
|
|
|
* Elgg's front controller. Handles basically all incoming URL requests. |
380
|
|
|
* |
381
|
|
|
* @return bool True if Elgg will handle the request, false if the server should (PHP-CLI server) |
382
|
|
|
*/ |
383
|
|
|
public static function index() { |
384
|
|
|
return self::create()->run(); |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* Routes the request, booting core if not yet booted |
389
|
|
|
* |
390
|
|
|
* @return bool False if Elgg wants the PHP CLI server to handle the request |
391
|
|
|
*/ |
392
|
|
|
public function run() { |
|
|
|
|
393
|
|
|
$path = $this->setupPath(); |
394
|
|
|
|
395
|
|
|
// allow testing from the upgrade page before the site is upgraded. |
396
|
|
|
if (isset($_GET[self::REWRITE_TEST_TOKEN])) { |
397
|
|
|
if (false !== strpos($path, self::REWRITE_TEST_TOKEN)) { |
398
|
|
|
echo self::REWRITE_TEST_OUTPUT; |
399
|
|
|
} |
400
|
|
|
return true; |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
if (php_sapi_name() === 'cli-server') { |
404
|
|
|
$www_root = "http://{$_SERVER['SERVER_NAME']}:{$_SERVER['SERVER_PORT']}/"; |
405
|
|
|
$this->services->config->set('wwwroot', $www_root); |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
if (0 === strpos($path, '/cache/')) { |
409
|
|
|
(new Application\CacheHandler($this, $this->services->config, $_SERVER))->handleRequest($path); |
|
|
|
|
410
|
|
|
return true; |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
if (0 === strpos($path, '/serve-file/')) { |
414
|
|
|
$this->services->serveFileHandler->getResponse($this->services->request)->send(); |
415
|
|
|
return true; |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
if ($path === '/rewrite.php') { |
419
|
|
|
require Directory\Local::root()->getPath("install.php"); |
420
|
|
|
return true; |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
if (php_sapi_name() === 'cli-server') { |
424
|
|
|
// The CLI server routes ALL requests here (even existing files), so we have to check for these. |
425
|
|
|
if ($path !== '/' && Directory\Local::root()->isFile($path)) { |
426
|
|
|
// serve the requested resource as-is. |
427
|
|
|
return false; |
428
|
|
|
} |
429
|
|
|
} |
430
|
|
|
|
431
|
|
|
$this->bootCore(); |
432
|
|
|
|
433
|
|
|
// TODO use formal Response object instead |
434
|
|
|
header("Content-Type: text/html;charset=utf-8"); |
435
|
|
|
|
436
|
|
|
if (!$this->services->router->route($this->services->request)) { |
437
|
|
|
forward('', '404'); |
438
|
|
|
} |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
/** |
442
|
|
|
* Determine the Elgg data directory with trailing slash, save it to config, and return it |
443
|
|
|
* |
444
|
|
|
* @todo Consider a better place for this logic? We need it before boot |
445
|
|
|
* |
446
|
|
|
* @return string |
447
|
|
|
* @throws \InstallationException |
448
|
|
|
*/ |
449
|
|
|
public static function getDataPath() { |
|
|
|
|
450
|
|
|
$app = self::create(); |
451
|
|
|
$app->services->config->loadSettingsFile(); |
452
|
|
|
|
453
|
|
|
if ($GLOBALS['_ELGG']->dataroot_in_settings) { |
454
|
|
|
return $app->services->config->getVolatile('dataroot'); |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
$dataroot = $app->services->datalist->get('dataroot'); |
458
|
|
|
if (!$dataroot) { |
459
|
|
|
throw new \InstallationException('The datalists table lacks a value for "dataroot".'); |
460
|
|
|
} |
461
|
|
|
$dataroot = rtrim($dataroot, '/\\') . DIRECTORY_SEPARATOR; |
462
|
|
|
$app->services->config->set('dataroot', $dataroot); |
463
|
|
|
return $dataroot; |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
/** |
467
|
|
|
* Returns a directory that points to the root of Elgg, but not necessarily |
468
|
|
|
* the install root. See `self::root()` for that. |
469
|
|
|
* |
470
|
|
|
* @return Directory |
471
|
|
|
*/ |
472
|
|
|
public static function elggDir() /*: Directory*/ { |
473
|
|
|
return Directory\Local::fromPath(realpath(__DIR__ . '/../../..')); |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
/** |
477
|
|
|
* Renders a web UI for installing Elgg. |
478
|
|
|
* |
479
|
|
|
* @return void |
480
|
|
|
*/ |
481
|
|
|
public static function install() { |
482
|
|
|
ini_set('display_errors', 1); |
483
|
|
|
$installer = new \ElggInstaller(); |
484
|
|
|
$step = get_input('step', 'welcome'); |
485
|
|
|
$installer->run($step); |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
/** |
489
|
|
|
* Elgg upgrade script. |
490
|
|
|
* |
491
|
|
|
* This script triggers any necessary upgrades. If the site has been upgraded |
492
|
|
|
* to the most recent version of the code, no upgrades are run but the caches |
493
|
|
|
* are flushed. |
494
|
|
|
* |
495
|
|
|
* Upgrades use a table {db_prefix}upgrade_lock as a mutex to prevent concurrent upgrades. |
496
|
|
|
* |
497
|
|
|
* The URL to forward to after upgrades are complete can be specified by setting $_GET['forward'] |
498
|
|
|
* to a relative URL. |
499
|
|
|
* |
500
|
|
|
* @return void |
501
|
|
|
*/ |
502
|
|
|
public static function upgrade() { |
503
|
|
|
// we want to know if an error occurs |
504
|
|
|
ini_set('display_errors', 1); |
505
|
|
|
|
506
|
|
|
define('UPGRADING', 'upgrading'); |
507
|
|
|
|
508
|
|
|
self::start(); |
509
|
|
|
|
510
|
|
|
$site_url = elgg_get_config('url'); |
511
|
|
|
$site_host = parse_url($site_url, PHP_URL_HOST) . '/'; |
512
|
|
|
|
513
|
|
|
// turn any full in-site URLs into absolute paths |
514
|
|
|
$forward_url = get_input('forward', '/admin', false); |
515
|
|
|
$forward_url = str_replace(array($site_url, $site_host), '/', $forward_url); |
516
|
|
|
|
517
|
|
|
if (strpos($forward_url, '/') !== 0) { |
518
|
|
|
$forward_url = '/' . $forward_url; |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
if (get_input('upgrade') == 'upgrade') { |
522
|
|
|
|
523
|
|
|
$upgrader = _elgg_services()->upgrades; |
524
|
|
|
$result = $upgrader->run(); |
525
|
|
|
if ($result['failure'] == true) { |
526
|
|
|
register_error($result['reason']); |
527
|
|
|
forward($forward_url); |
528
|
|
|
} |
529
|
|
|
} else { |
530
|
|
|
$rewriteTester = new \ElggRewriteTester(); |
531
|
|
|
$url = elgg_get_site_url() . "__testing_rewrite?__testing_rewrite=1"; |
532
|
|
|
if (!$rewriteTester->runRewriteTest($url)) { |
533
|
|
|
// see if there is a problem accessing the site at all |
534
|
|
|
// due to ip restrictions for example |
535
|
|
|
if (!$rewriteTester->runLocalhostAccessTest()) { |
536
|
|
|
// note: translation may not be available until after upgrade |
537
|
|
|
$msg = elgg_echo("installation:htaccess:localhost:connectionfailed"); |
538
|
|
|
if ($msg === "installation:htaccess:localhost:connectionfailed") { |
539
|
|
|
$msg = "Elgg cannot connect to itself to test rewrite rules properly. Check " |
540
|
|
|
. "that curl is working and there are no IP restrictions preventing " |
541
|
|
|
. "localhost connections."; |
542
|
|
|
} |
543
|
|
|
echo $msg; |
544
|
|
|
exit; |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
// note: translation may not be available until after upgrade |
548
|
|
|
$msg = elgg_echo("installation:htaccess:needs_upgrade"); |
549
|
|
|
if ($msg === "installation:htaccess:needs_upgrade") { |
550
|
|
|
$msg = "You must update your .htaccess file so that the path is injected " |
551
|
|
|
. "into the GET parameter __elgg_uri (you can use install/config/htaccess.dist as a guide)."; |
552
|
|
|
} |
553
|
|
|
echo $msg; |
554
|
|
|
exit; |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
$vars = array( |
558
|
|
|
'forward' => $forward_url |
559
|
|
|
); |
560
|
|
|
|
561
|
|
|
// reset cache to have latest translations available during upgrade |
562
|
|
|
elgg_reset_system_cache(); |
563
|
|
|
|
564
|
|
|
echo elgg_view_page(elgg_echo('upgrading'), '', 'upgrade', $vars); |
565
|
|
|
exit; |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
forward($forward_url); |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
/** |
572
|
|
|
* Get the request URI and store it in $_GET['__elgg_uri'] |
573
|
|
|
* |
574
|
|
|
* @return string e.g. "cache/123..." |
575
|
|
|
*/ |
576
|
|
|
private function setupPath() { |
|
|
|
|
577
|
|
|
if (!isset($_GET[self::GET_PATH_KEY]) || is_array($_GET[self::GET_PATH_KEY])) { |
578
|
|
|
if (php_sapi_name() === 'cli-server') { |
579
|
|
|
$_GET[self::GET_PATH_KEY] = (string)parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); |
580
|
|
|
} else { |
581
|
|
|
$_GET[self::GET_PATH_KEY] = '/'; |
582
|
|
|
} |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
// normalize |
586
|
|
|
$_GET[self::GET_PATH_KEY] = '/' . trim($_GET[self::GET_PATH_KEY], '/'); |
587
|
|
|
|
588
|
|
|
return $_GET[self::GET_PATH_KEY]; |
589
|
|
|
} |
590
|
|
|
|
591
|
|
|
/** |
592
|
|
|
* Allow plugins to rewrite the path. |
593
|
|
|
* |
594
|
|
|
* @return void |
595
|
|
|
*/ |
596
|
|
|
private function allowPathRewrite() { |
597
|
|
|
$request = $this->services->request; |
598
|
|
|
$new = $this->services->router->allowRewrite($request); |
599
|
|
|
if ($new === $request) { |
600
|
|
|
return; |
601
|
|
|
} |
602
|
|
|
|
603
|
|
|
$this->services->setValue('request', $new); |
604
|
|
|
_elgg_set_initial_context($new); |
605
|
|
|
} |
606
|
|
|
|
607
|
|
|
/** |
608
|
|
|
* Flag this application as running for testing (PHPUnit) |
609
|
|
|
* |
610
|
|
|
* @param bool $testing Is testing application |
611
|
|
|
* @return void |
612
|
|
|
*/ |
613
|
180 |
|
public static function setTestingApplication($testing = true) { |
614
|
180 |
|
self::$testing_app = $testing; |
615
|
180 |
|
} |
616
|
|
|
|
617
|
|
|
/** |
618
|
|
|
* Checks if the application is running in PHPUnit |
619
|
|
|
* @return bool |
620
|
|
|
*/ |
621
|
1 |
|
public static function isTestingApplication() { |
622
|
1 |
|
return (bool) self::$testing_app; |
623
|
|
|
} |
624
|
|
|
} |
625
|
|
|
|
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: