1 | <?php |
||||||
2 | |||||||
3 | namespace Elgg; |
||||||
4 | |||||||
5 | use Elgg\Database\SiteSecret; |
||||||
6 | use Elgg\Di\ServiceProvider; |
||||||
7 | use Elgg\Project\Paths; |
||||||
8 | use ElggCache; |
||||||
9 | use Stash\Invalidation; |
||||||
10 | |||||||
11 | /** |
||||||
12 | * Boots Elgg and manages a cache of data needed during boot |
||||||
13 | * |
||||||
14 | * @access private |
||||||
15 | * @since 2.1 |
||||||
16 | */ |
||||||
17 | class BootService { |
||||||
18 | use Profilable; |
||||||
19 | |||||||
20 | /** |
||||||
21 | * Under load, a short TTL gives nearly all of the benefits of a longer TTL, but it also ensures |
||||||
22 | * that, should cache invalidation fail for some reason, it'll be rebuilt quickly anyway. |
||||||
23 | * |
||||||
24 | * In 2.x we do not cache by default. This will likely change to 10 in 3.0. |
||||||
25 | */ |
||||||
26 | const DEFAULT_BOOT_CACHE_TTL = 0; |
||||||
27 | |||||||
28 | /** |
||||||
29 | * Has the cache already been invalidated this request? Avoids thrashing |
||||||
30 | * |
||||||
31 | * @var bool |
||||||
32 | */ |
||||||
33 | private $was_cleared = false; |
||||||
34 | |||||||
35 | /** |
||||||
36 | * @var ElggCache |
||||||
37 | */ |
||||||
38 | protected $cache; |
||||||
39 | |||||||
40 | /** |
||||||
41 | * Cache |
||||||
42 | * |
||||||
43 | * @param ElggCache $cache Cache |
||||||
44 | */ |
||||||
45 | 4417 | public function __construct(ElggCache $cache) { |
|||||
46 | 4417 | $this->cache = $cache; |
|||||
47 | 4417 | } |
|||||
48 | |||||||
49 | /** |
||||||
50 | * Boots the engine |
||||||
51 | * |
||||||
52 | * @param ServiceProvider $services Services |
||||||
53 | * |
||||||
54 | * @return void |
||||||
55 | * @throws \ClassException |
||||||
56 | * @throws \DatabaseException |
||||||
57 | * @throws \InstallationException |
||||||
58 | * @throws \InvalidParameterException |
||||||
59 | * @throws \SecurityException |
||||||
60 | */ |
||||||
61 | 4786 | public function boot(ServiceProvider $services) { |
|||||
62 | 4777 | $db = $services->db; |
|||||
63 | 4777 | $config = $services->config; |
|||||
64 | |||||||
65 | // set cookie values for session and remember me |
||||||
66 | 4777 | $config->getCookieConfig(); |
|||||
67 | |||||||
68 | // defaults in case these aren't in config table |
||||||
69 | 4777 | if ($config->boot_cache_ttl === null) { |
|||||
70 | 5 | $config->boot_cache_ttl = self::DEFAULT_BOOT_CACHE_TTL; |
|||||
71 | } |
||||||
72 | 4777 | if ($config->simplecache_enabled === null) { |
|||||
73 | 5 | $config->simplecache_enabled = 0; |
|||||
74 | } |
||||||
75 | 4777 | if ($config->system_cache_enabled === null) { |
|||||
76 | 5 | $config->system_cache_enabled = false; |
|||||
77 | } |
||||||
78 | 4777 | if ($config->simplecache_lastupdate === null) { |
|||||
79 | 4417 | $config->simplecache_lastupdate = 0; |
|||||
80 | } |
||||||
81 | |||||||
82 | // we were using NOTICE temporarily so we can't just check for null |
||||||
83 | 4777 | if (!$config->hasInitialValue('debug') && !$config->debug) { |
|||||
84 | 5 | $config->debug = ''; |
|||||
85 | } |
||||||
86 | |||||||
87 | // copy all table values into config |
||||||
88 | 4777 | $config->mergeValues($services->configTable->getAll()); |
|||||
89 | |||||||
90 | // needs to be set before [init, system] for links in html head |
||||||
91 | 4777 | $config->lastcache = (int) $config->simplecache_lastupdate; |
|||||
92 | |||||||
93 | 4777 | if (!$config->elgg_config_set_secret) { |
|||||
94 | 4777 | $site_secret = SiteSecret::fromConfig($config); |
|||||
95 | 4777 | if (!$site_secret) { |
|||||
96 | // The 2.3 installer doesn't create a site key (it's created on-demand on the first request) |
||||||
97 | // so for our Travis upgrade testing we need to check for this and create one on the spot. |
||||||
98 | if (defined('UPGRADING')) { |
||||||
99 | $site_secret = SiteSecret::regenerate($services->crypto, $services->configTable); |
||||||
100 | } |
||||||
101 | } |
||||||
102 | 4777 | if ($site_secret) { |
|||||
103 | 4777 | $services->setValue('siteSecret', $site_secret); |
|||||
104 | } else { |
||||||
105 | throw new \RuntimeException('The site secret is not set.'); |
||||||
106 | } |
||||||
107 | } |
||||||
108 | |||||||
109 | 4777 | $installed = isset($config->installed); |
|||||
110 | |||||||
111 | 4777 | if ($this->timer) { |
|||||
112 | $this->timer->begin([__CLASS__ . '::getBootData']); |
||||||
113 | } |
||||||
114 | |||||||
115 | // early config is done, now get the core boot data |
||||||
116 | 4777 | $data = $this->getBootData($config, $db, $installed); |
|||||
117 | |||||||
118 | 4777 | $site = $data->getSite(); |
|||||
119 | 4777 | if (!$site) { |
|||||
120 | // must be set in config |
||||||
121 | $site = $config->site; |
||||||
122 | if (!$site instanceof \ElggSite) { |
||||||
123 | throw new \RuntimeException('Before installation, config->site must have an unsaved ElggSite.'); |
||||||
124 | } |
||||||
125 | } |
||||||
126 | 4777 | $config->site = $site; |
|||||
127 | 4777 | $config->sitename = $site->name; |
|||||
128 | 4777 | $config->sitedescription = $site->description; |
|||||
129 | |||||||
130 | 4777 | $services->plugins->setBootPlugins($data->getActivePlugins()); |
|||||
131 | |||||||
132 | 4777 | $settings = $data->getPluginSettings(); |
|||||
133 | 4777 | foreach ($settings as $guid => $entity_settings) { |
|||||
134 | 13 | $services->privateSettingsCache->save($guid, $entity_settings); |
|||||
135 | } |
||||||
136 | |||||||
137 | 4777 | foreach ($data->getPluginMetadata() as $guid => $metadata) { |
|||||
138 | 13 | $services->dataCache->metadata->save($guid, $metadata); |
|||||
139 | } |
||||||
140 | |||||||
141 | // use value in settings.php if available |
||||||
142 | 4777 | $debug = $config->hasInitialValue('debug') ? $config->getInitialValue('debug') : $config->debug; |
|||||
143 | 4777 | $services->logger->setLevel($debug); |
|||||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||||
144 | |||||||
145 | // finish boot sequence |
||||||
146 | 4777 | _elgg_session_boot($services); |
|||||
147 | |||||||
148 | 4777 | if ($config->system_cache_enabled) { |
|||||
149 | 13 | $config->system_cache_loaded = false; |
|||||
150 | |||||||
151 | 13 | if ($services->views->configureFromCache($services->systemCache)) { |
|||||
152 | 12 | $config->system_cache_loaded = true; |
|||||
153 | } |
||||||
154 | } |
||||||
155 | |||||||
156 | // we don't store langs in boot data because it varies by user |
||||||
157 | 4777 | $services->translator->loadTranslations(); |
|||||
158 | |||||||
159 | // invalidate on some actions just in case other invalidation triggers miss something |
||||||
160 | 4786 | $services->hooks->registerHandler('action', 'all', function ($action) { |
|||||
161 | 17 | if (0 === strpos($action, 'admin/' || $action === 'plugins/settings/save')) { |
|||||
162 | $this->invalidateCache(); |
||||||
163 | } |
||||||
164 | 4786 | }, 1); |
|||||
165 | 4777 | } |
|||||
166 | |||||||
167 | /** |
||||||
168 | * Invalidate the cache item |
||||||
169 | * |
||||||
170 | * @return void |
||||||
171 | */ |
||||||
172 | 1081 | public function invalidateCache() { |
|||||
173 | 1081 | if (!$this->was_cleared) { |
|||||
174 | 417 | $this->cache->clear(); |
|||||
175 | 417 | $this->was_cleared = true; |
|||||
176 | } |
||||||
177 | 1081 | } |
|||||
178 | |||||||
179 | /** |
||||||
180 | * Get the boot data |
||||||
181 | * |
||||||
182 | * @param Config $config Elgg config object |
||||||
183 | * @param Database $db Elgg database |
||||||
184 | * @param bool $installed Is the site installed? |
||||||
185 | * |
||||||
186 | * @return BootData |
||||||
187 | * |
||||||
188 | * @throws \ClassException |
||||||
189 | * @throws \DatabaseException |
||||||
190 | * @throws \InstallationException |
||||||
191 | * @throws \InvalidParameterException |
||||||
192 | */ |
||||||
193 | 4777 | private function getBootData(Config $config, Database $db, $installed) { |
|||||
194 | 4777 | $config->_boot_cache_hit = false; |
|||||
195 | |||||||
196 | 4777 | $data = $this->cache->load('boot_data'); |
|||||
197 | 4777 | if (!isset($data)) { |
|||||
198 | 4777 | $data = new BootData(); |
|||||
199 | 4777 | $data->populate($db, _elgg_services()->entityTable, _elgg_services()->plugins, $installed); |
|||||
200 | 4777 | if ($config->boot_cache_ttl) { |
|||||
201 | 4777 | $this->cache->save('boot_data', $data, $config->boot_cache_ttl, [Invalidation::NONE]); |
|||||
0 ignored issues
–
show
The call to
ElggCache::save() has too many arguments starting with array(Stash\Invalidation::NONE) .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.
Loading history...
|
|||||||
202 | } |
||||||
203 | } else { |
||||||
204 | $config->_boot_cache_hit = true; |
||||||
205 | } |
||||||
206 | |||||||
207 | 4777 | return $data; |
|||||
208 | } |
||||||
209 | |||||||
210 | } |
||||||
211 |