Test Failed
Push — master ( 8c47c2...3acf9f )
by Steve
12:37
created

engine/classes/Elgg/BootService.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Elgg;
4
5
use Elgg\Filesystem\Directory\Local;
6
use Stash\Driver\BlackHole;
7
use Stash\Driver\FileSystem;
8
use Stash\Driver\Memcache;
9
use Stash\Invalidation;
10
use Stash\Pool;
11
12
/**
13
 * Boots Elgg and manages a cache of data needed during boot
14
 *
15
 * @access private
16
 * @since 2.1
17
 */
18
class BootService {
19
	use Profilable;
20
21
	/**
22
	 * Under load, a short TTL gives nearly all of the benefits of a longer TTL, but it also ensures
23
	 * that, should cache invalidation fail for some reason, it'll be rebuilt quickly anyway.
24
	 *
25
	 * In 2.x we do not cache by default. This will likely change to 10 in 3.0.
26
	 */
27
	const DEFAULT_BOOT_CACHE_TTL = 0;
28
29
	/**
30
	 * Boots the engine
31
	 *
32
	 * @return void
33
	 */
34
	public function boot() {
0 ignored issues
show
boot uses the super-global variable $GLOBALS which is generally not recommended.

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:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
35
		// Register the error handlers
36
		set_error_handler('_elgg_php_error_handler');
37
		set_exception_handler('_elgg_php_exception_handler');
38
39
		$db = _elgg_services()->db;
40
41
		// we inject the logger here to allow use of DB without loading core
42
		$db->setLogger(_elgg_services()->logger);
43
44
		$db->setupConnections();
45
		$db->assertInstalled();
46
47
		$CONFIG = _elgg_services()->config->getStorageObject();
48
		$local_path = Local::root()->getPath();
49
50
		// setup stuff available without any DB info
51
		$CONFIG->path = $local_path;
52
		$CONFIG->plugins_path = "{$local_path}mod/";
53
		$CONFIG->pluginspath = "{$local_path}mod/";
54
		$CONFIG->entity_types = ['group', 'object', 'site', 'user'];
55
		$CONFIG->language = 'en';
56
57
		// set cookie values for session and remember me
58
		_elgg_services()->config->getCookieConfig();
59
60
		$CONFIG->site_guid = 1;
61
		if (!isset($CONFIG->boot_cache_ttl)) {
62
			$CONFIG->boot_cache_ttl = self::DEFAULT_BOOT_CACHE_TTL;
63
		}
64
65
		if ($this->timer) {
66
			$this->timer->begin([__CLASS__ . '::getBootData']);
67
		}
68
69
		// early config is done, now get the core boot data
70
		$data = $this->getBootData($CONFIG, $db);
71
72
		if ($this->timer) {
73
			$this->timer->begin([__CLASS__ . '::getBootData']);
74
		}
75
76
		$configs_cache = $data->getConfigValues();
77
78
		$CONFIG->site = $data->getSite();
79
		$CONFIG->sitename = $CONFIG->site->name;
80
		$CONFIG->sitedescription = $CONFIG->site->description;
81
		$CONFIG->url = $CONFIG->wwwroot;
82
83
		_elgg_services()->subtypeTable->setCachedValues($data->getSubtypeData());
84
85
		foreach ($data->getConfigValues() as $key => $value) {
86
			$CONFIG->$key = $value;
87
		}
88
89
		_elgg_services()->plugins->setBootPlugins($data->getActivePlugins());
90
91
		_elgg_services()->pluginSettingsCache->setCachedValues($data->getPluginSettings());
92
93
		if (!$GLOBALS['_ELGG']->simplecache_enabled_in_settings) {
94
			$simplecache_enabled = $configs_cache['simplecache_enabled'];
95
			$CONFIG->simplecache_enabled = ($simplecache_enabled === false) ? 1 : $simplecache_enabled;
96
		}
97
98
		$system_cache_enabled = $configs_cache['system_cache_enabled'];
99
		$CONFIG->system_cache_enabled = ($system_cache_enabled === false) ? 1 : $system_cache_enabled;
100
101
		// needs to be set before [init, system] for links in html head
102
		$CONFIG->lastcache = (int) $configs_cache['simplecache_lastupdate'];
103
104
		$GLOBALS['_ELGG']->i18n_loaded_from_cache = false;
105
106
		if (!empty($CONFIG->debug)) {
107
			_elgg_services()->logger->setLevel($CONFIG->debug);
108
			_elgg_services()->logger->setDisplay(true);
109
		}
110
111
		_elgg_services()->views->view_path = \Elgg\Application::elggDir()->getPath("/views/");
112
113
		// finish boot sequence
114
		_elgg_session_boot();
115
		if ($CONFIG->system_cache_enabled) {
116
			_elgg_services()->systemCache->loadAll();
117
		}
118
119
		// we don't store langs in boot data because it varies by user
120
		_elgg_services()->translator->loadTranslations();
121
122
		// we always need site->email and user->icontime, so load them together
123
		$user_guid = _elgg_services()->session->getLoggedInUserGuid();
124
		if ($user_guid) {
125
			_elgg_services()->metadataCache->populateFromEntities([$user_guid]);
126
		}
127
128
		// gives hint to get() how to approach missing values
129
		$CONFIG->site_config_loaded = true;
130
131
		// invalidate on some actions just in case other invalidation triggers miss something
132
		_elgg_services()->hooks->registerHandler('action', 'all', function ($action) {
133
			if (0 === strpos($action, 'admin/' || $action === 'plugins/settings/save')) {
134
				$this->invalidateCache();
135
			}
136
		}, 1);
137
	}
138
139
	/**
140
	 * Invalidate the cache item
141
	 *
142
	 * @return void
143
	 */
144 10
	public function invalidateCache() {
145 10
		$CONFIG = _elgg_services()->config->getStorageObject();
146
		
147
		// this gets called a lot on plugins page, avoid thrashing cache
148 10
		static $cleared = false;
149 10
		if (!$cleared) {
150 1
			$this->getStashItem($CONFIG)->clear();
151 1
			$cleared = true;
152
		}
153 10
	}
154
155
	/**
156
	 * Get the boot data
157
	 *
158
	 * @param \stdClass $CONFIG Elgg config object
159
	 * @param Database  $db     Elgg database
160
	 *
161
	 * @return BootData
162
	 *
163
	 * @throws \InstallationException
164
	 */
165
	private function getBootData(\stdClass $CONFIG, Database $db) {
166
		$CONFIG->_boot_cache_hit = false;
167
168
		if (!$CONFIG->boot_cache_ttl) {
169
			$data = new BootData();
170
			$data->populate($CONFIG, $db, _elgg_services()->entityTable, _elgg_services()->plugins);
171
			return $data;
172
		}
173
174
		$item = $this->getStashItem($CONFIG);
175
		$item->setInvalidationMethod(Invalidation::NONE);
176
		$data = $item->get();
177
		if ($item->isMiss()) {
178
			$data = new BootData();
179
			$data->populate($CONFIG, $db, _elgg_services()->entityTable, _elgg_services()->plugins);
180
			$item->set($data);
181
			$item->expiresAfter($CONFIG->boot_cache_ttl);
182
			$item->save();
183
		} else {
184
			$CONFIG->_boot_cache_hit = true;
185
		}
186
187
		return $data;
188
	}
189
190
	/**
191
	 * Get a Stash cache item
192
	 *
193
	 * @param \stdClass $CONFIG Elgg config object
194
	 *
195
	 * @return \Stash\Interfaces\ItemInterface
196
	 */
197 1
	private function getStashItem(\stdClass $CONFIG) {
198 1
		if (!empty($CONFIG->memcache) && class_exists('Memcache')) {
199
			$options = [];
200
			if (!empty($CONFIG->memcache_servers)) {
201
				$options['servers'] = $CONFIG->memcache_servers;
202
			}
203
			$driver = new Memcache($options);
204
		} else {
205 1
			if (!$CONFIG->dataroot) {
206
				// we're in the installer
207
				$driver = new BlackHole();
208
			} else {
209 1
				$driver = new FileSystem([
210 1
					'path' => $CONFIG->dataroot,
211
				]);
212
			}
213
		}
214 1
		return (new Pool($driver))->getItem("boot_data");
215
	}
216
}
217