Completed
Pull Request — master (#8095)
by Julius
16:50
created
lib/public/INavigationManager.php 2 patches
Doc Comments   -1 removed lines patch added patch discarded remove patch
@@ -61,7 +61,6 @@
 block discarded – undo
61 61
 	/**
62 62
 	 * Get a list of navigation entries
63 63
 	 *
64
-	 * @param bool $absolute set to true if links to navigation entries should be converted to absolute urls
65 64
 	 * @return array
66 65
 	 * @since 14.0.0
67 66
 	 */
Please login to merge, or discard this patch.
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -39,31 +39,31 @@
 block discarded – undo
39 39
  * @since 6.0.0
40 40
  */
41 41
 interface INavigationManager {
42
-	/**
43
-	 * Creates a new navigation entry
44
-	 *
45
-	 * @param array|\Closure $entry Array containing: id, name, order, icon and href key
46
-	 *					The use of a closure is preferred, because it will avoid
47
-	 * 					loading the routing of your app, unless required.
48
-	 * @return void
49
-	 * @since 6.0.0
50
-	 */
51
-	public function add($entry);
42
+    /**
43
+     * Creates a new navigation entry
44
+     *
45
+     * @param array|\Closure $entry Array containing: id, name, order, icon and href key
46
+     *					The use of a closure is preferred, because it will avoid
47
+     * 					loading the routing of your app, unless required.
48
+     * @return void
49
+     * @since 6.0.0
50
+     */
51
+    public function add($entry);
52 52
 
53
-	/**
54
-	 * Sets the current navigation entry of the currently running app
55
-	 * @param string $appId id of the app entry to activate (from added $entry)
56
-	 * @return void
57
-	 * @since 6.0.0
58
-	 */
59
-	public function setActiveEntry($appId);
53
+    /**
54
+     * Sets the current navigation entry of the currently running app
55
+     * @param string $appId id of the app entry to activate (from added $entry)
56
+     * @return void
57
+     * @since 6.0.0
58
+     */
59
+    public function setActiveEntry($appId);
60 60
 
61
-	/**
62
-	 * Get a list of navigation entries
63
-	 *
64
-	 * @param bool $absolute set to true if links to navigation entries should be converted to absolute urls
65
-	 * @return array
66
-	 * @since 14.0.0
67
-	 */
68
-	public function getAll(string $type = 'link'): array;
61
+    /**
62
+     * Get a list of navigation entries
63
+     *
64
+     * @param bool $absolute set to true if links to navigation entries should be converted to absolute urls
65
+     * @return array
66
+     * @since 14.0.0
67
+     */
68
+    public function getAll(string $type = 'link'): array;
69 69
 }
Please login to merge, or discard this patch.
lib/private/NavigationManager.php 1 patch
Indentation   +259 added lines, -259 removed lines patch added patch discarded remove patch
@@ -44,289 +44,289 @@
 block discarded – undo
44 44
  */
45 45
 
46 46
 class NavigationManager implements INavigationManager {
47
-	protected $entries = [];
48
-	protected $closureEntries = [];
49
-	protected $activeEntry;
50
-	/** @var bool */
51
-	protected $init = false;
52
-	/** @var IAppManager|AppManager */
53
-	protected $appManager;
54
-	/** @var IURLGenerator */
55
-	private $urlGenerator;
56
-	/** @var IFactory */
57
-	private $l10nFac;
58
-	/** @var IUserSession */
59
-	private $userSession;
60
-	/** @var IGroupManager|Manager */
61
-	private $groupManager;
62
-	/** @var IConfig */
63
-	private $config;
47
+    protected $entries = [];
48
+    protected $closureEntries = [];
49
+    protected $activeEntry;
50
+    /** @var bool */
51
+    protected $init = false;
52
+    /** @var IAppManager|AppManager */
53
+    protected $appManager;
54
+    /** @var IURLGenerator */
55
+    private $urlGenerator;
56
+    /** @var IFactory */
57
+    private $l10nFac;
58
+    /** @var IUserSession */
59
+    private $userSession;
60
+    /** @var IGroupManager|Manager */
61
+    private $groupManager;
62
+    /** @var IConfig */
63
+    private $config;
64 64
 
65
-	public function __construct(IAppManager $appManager,
66
-						 IURLGenerator $urlGenerator,
67
-						 IFactory $l10nFac,
68
-						 IUserSession $userSession,
69
-						 IGroupManager $groupManager,
70
-						 IConfig $config) {
71
-		$this->appManager = $appManager;
72
-		$this->urlGenerator = $urlGenerator;
73
-		$this->l10nFac = $l10nFac;
74
-		$this->userSession = $userSession;
75
-		$this->groupManager = $groupManager;
76
-		$this->config = $config;
77
-	}
65
+    public function __construct(IAppManager $appManager,
66
+                            IURLGenerator $urlGenerator,
67
+                            IFactory $l10nFac,
68
+                            IUserSession $userSession,
69
+                            IGroupManager $groupManager,
70
+                            IConfig $config) {
71
+        $this->appManager = $appManager;
72
+        $this->urlGenerator = $urlGenerator;
73
+        $this->l10nFac = $l10nFac;
74
+        $this->userSession = $userSession;
75
+        $this->groupManager = $groupManager;
76
+        $this->config = $config;
77
+    }
78 78
 
79
-	/**
80
-	 * Creates a new navigation entry
81
-	 *
82
-	 * @param array|\Closure $entry Array containing: id, name, order, icon and href key
83
-	 *					The use of a closure is preferred, because it will avoid
84
-	 * 					loading the routing of your app, unless required.
85
-	 * @return void
86
-	 */
87
-	public function add($entry) {
88
-		if ($entry instanceof \Closure) {
89
-			$this->closureEntries[] = $entry;
90
-			return;
91
-		}
79
+    /**
80
+     * Creates a new navigation entry
81
+     *
82
+     * @param array|\Closure $entry Array containing: id, name, order, icon and href key
83
+     *					The use of a closure is preferred, because it will avoid
84
+     * 					loading the routing of your app, unless required.
85
+     * @return void
86
+     */
87
+    public function add($entry) {
88
+        if ($entry instanceof \Closure) {
89
+            $this->closureEntries[] = $entry;
90
+            return;
91
+        }
92 92
 
93
-		$entry['active'] = false;
94
-		if(!isset($entry['icon'])) {
95
-			$entry['icon'] = '';
96
-		}
97
-		if(!isset($entry['classes'])) {
98
-			$entry['classes'] = '';
99
-		}
100
-		if(!isset($entry['type'])) {
101
-			$entry['type'] = 'link';
102
-		}
103
-		$this->entries[] = $entry;
104
-	}
93
+        $entry['active'] = false;
94
+        if(!isset($entry['icon'])) {
95
+            $entry['icon'] = '';
96
+        }
97
+        if(!isset($entry['classes'])) {
98
+            $entry['classes'] = '';
99
+        }
100
+        if(!isset($entry['type'])) {
101
+            $entry['type'] = 'link';
102
+        }
103
+        $this->entries[] = $entry;
104
+    }
105 105
 
106
-	/**
107
-	 * returns all the added Menu entries
108
-	 * @param string $type
109
-	 * @return array an array of the added entries
110
-	 */
111
-	public function getAll(string $type = 'link'): array {
112
-		$this->init();
113
-		foreach ($this->closureEntries as $c) {
114
-			$this->add($c());
115
-		}
116
-		$this->closureEntries = array();
106
+    /**
107
+     * returns all the added Menu entries
108
+     * @param string $type
109
+     * @return array an array of the added entries
110
+     */
111
+    public function getAll(string $type = 'link'): array {
112
+        $this->init();
113
+        foreach ($this->closureEntries as $c) {
114
+            $this->add($c());
115
+        }
116
+        $this->closureEntries = array();
117 117
 
118
-		$result = $this->entries;
119
-		if ($type !== 'all') {
120
-			$result = array_filter($this->entries, function($entry) use ($type) {
121
-				return $entry['type'] === $type;
122
-			});
123
-		}
118
+        $result = $this->entries;
119
+        if ($type !== 'all') {
120
+            $result = array_filter($this->entries, function($entry) use ($type) {
121
+                return $entry['type'] === $type;
122
+            });
123
+        }
124 124
 
125
-		return $this->proceedNavigation($result);
126
-	}
125
+        return $this->proceedNavigation($result);
126
+    }
127 127
 
128
-	/**
129
-	 * Sort navigation entries by order, name and set active flag
130
-	 *
131
-	 * @param $list
132
-	 * @return mixed
133
-	 */
134
-	private function proceedNavigation($list) {
135
-		usort($list, function($a, $b) {
136
-			if (isset($a['order']) && isset($b['order'])) {
137
-				return ($a['order'] < $b['order']) ? -1 : 1;
138
-			} else if (isset($a['order']) || isset($b['order'])) {
139
-				return isset($a['order']) ? -1 : 1;
140
-			} else {
141
-				return ($a['name'] < $b['name']) ? -1 : 1;
142
-			}
143
-		});
128
+    /**
129
+     * Sort navigation entries by order, name and set active flag
130
+     *
131
+     * @param $list
132
+     * @return mixed
133
+     */
134
+    private function proceedNavigation($list) {
135
+        usort($list, function($a, $b) {
136
+            if (isset($a['order']) && isset($b['order'])) {
137
+                return ($a['order'] < $b['order']) ? -1 : 1;
138
+            } else if (isset($a['order']) || isset($b['order'])) {
139
+                return isset($a['order']) ? -1 : 1;
140
+            } else {
141
+                return ($a['name'] < $b['name']) ? -1 : 1;
142
+            }
143
+        });
144 144
 
145
-		$activeApp = $this->getActiveEntry();
146
-		if ($activeApp !== null) {
147
-			foreach ($list as $index => &$navEntry) {
148
-				if ($navEntry['id'] == $activeApp) {
149
-					$navEntry['active'] = true;
150
-				} else {
151
-					$navEntry['active'] = false;
152
-				}
153
-			}
154
-			unset($navEntry);
155
-		}
145
+        $activeApp = $this->getActiveEntry();
146
+        if ($activeApp !== null) {
147
+            foreach ($list as $index => &$navEntry) {
148
+                if ($navEntry['id'] == $activeApp) {
149
+                    $navEntry['active'] = true;
150
+                } else {
151
+                    $navEntry['active'] = false;
152
+                }
153
+            }
154
+            unset($navEntry);
155
+        }
156 156
 
157
-		return $list;
158
-	}
157
+        return $list;
158
+    }
159 159
 
160 160
 
161
-	/**
162
-	 * removes all the entries
163
-	 */
164
-	public function clear($loadDefaultLinks = true) {
165
-		$this->entries = [];
166
-		$this->closureEntries = [];
167
-		$this->init = !$loadDefaultLinks;
168
-	}
161
+    /**
162
+     * removes all the entries
163
+     */
164
+    public function clear($loadDefaultLinks = true) {
165
+        $this->entries = [];
166
+        $this->closureEntries = [];
167
+        $this->init = !$loadDefaultLinks;
168
+    }
169 169
 
170
-	/**
171
-	 * Sets the current navigation entry of the currently running app
172
-	 * @param string $id of the app entry to activate (from added $entry)
173
-	 */
174
-	public function setActiveEntry($id) {
175
-		$this->activeEntry = $id;
176
-	}
170
+    /**
171
+     * Sets the current navigation entry of the currently running app
172
+     * @param string $id of the app entry to activate (from added $entry)
173
+     */
174
+    public function setActiveEntry($id) {
175
+        $this->activeEntry = $id;
176
+    }
177 177
 
178
-	/**
179
-	 * gets the active Menu entry
180
-	 * @return string id or empty string
181
-	 *
182
-	 * This function returns the id of the active navigation entry (set by
183
-	 * setActiveEntry
184
-	 */
185
-	public function getActiveEntry() {
186
-		return $this->activeEntry;
187
-	}
178
+    /**
179
+     * gets the active Menu entry
180
+     * @return string id or empty string
181
+     *
182
+     * This function returns the id of the active navigation entry (set by
183
+     * setActiveEntry
184
+     */
185
+    public function getActiveEntry() {
186
+        return $this->activeEntry;
187
+    }
188 188
 
189
-	private function init() {
190
-		if ($this->init) {
191
-			return;
192
-		}
193
-		$this->init = true;
189
+    private function init() {
190
+        if ($this->init) {
191
+            return;
192
+        }
193
+        $this->init = true;
194 194
 
195
-		$l = $this->l10nFac->get('lib');
196
-		if ($this->config->getSystemValue('knowledgebaseenabled', true)) {
197
-			$this->add([
198
-				'type' => 'settings',
199
-				'id' => 'help',
200
-				'order' => 5,
201
-				'href' => $this->urlGenerator->linkToRoute('settings_help'),
202
-				'name' => $l->t('Help'),
203
-				'icon' => $this->urlGenerator->imagePath('settings', 'help.svg'),
204
-			]);
205
-		}
195
+        $l = $this->l10nFac->get('lib');
196
+        if ($this->config->getSystemValue('knowledgebaseenabled', true)) {
197
+            $this->add([
198
+                'type' => 'settings',
199
+                'id' => 'help',
200
+                'order' => 5,
201
+                'href' => $this->urlGenerator->linkToRoute('settings_help'),
202
+                'name' => $l->t('Help'),
203
+                'icon' => $this->urlGenerator->imagePath('settings', 'help.svg'),
204
+            ]);
205
+        }
206 206
 
207
-		if ($this->userSession->isLoggedIn()) {
208
-			if ($this->isAdmin()) {
209
-				// App management
210
-				$this->add([
211
-					'type' => 'settings',
212
-					'id' => 'core_apps',
213
-					'order' => 3,
214
-					'href' => $this->urlGenerator->linkToRoute('settings.AppSettings.viewApps'),
215
-					'icon' => $this->urlGenerator->imagePath('settings', 'apps.svg'),
216
-					'name' => $l->t('Apps'),
217
-				]);
218
-			}
207
+        if ($this->userSession->isLoggedIn()) {
208
+            if ($this->isAdmin()) {
209
+                // App management
210
+                $this->add([
211
+                    'type' => 'settings',
212
+                    'id' => 'core_apps',
213
+                    'order' => 3,
214
+                    'href' => $this->urlGenerator->linkToRoute('settings.AppSettings.viewApps'),
215
+                    'icon' => $this->urlGenerator->imagePath('settings', 'apps.svg'),
216
+                    'name' => $l->t('Apps'),
217
+                ]);
218
+            }
219 219
 
220
-			// Personal and (if applicable) admin settings
221
-			$this->add([
222
-				'type' => 'settings',
223
-				'id' => 'settings',
224
-				'order' => 1,
225
-				'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index'),
226
-				'name' => $l->t('Settings'),
227
-				'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
228
-			]);
220
+            // Personal and (if applicable) admin settings
221
+            $this->add([
222
+                'type' => 'settings',
223
+                'id' => 'settings',
224
+                'order' => 1,
225
+                'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index'),
226
+                'name' => $l->t('Settings'),
227
+                'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
228
+            ]);
229 229
 
230
-			$logoutUrl = \OC_User::getLogoutUrl($this->urlGenerator);
231
-			if($logoutUrl !== '') {
232
-				// Logout
233
-				$this->add([
234
-					'type' => 'settings',
235
-					'id' => 'logout',
236
-					'order' => 99999,
237
-					'href' => $logoutUrl,
238
-					'name' => $l->t('Log out'),
239
-					'icon' => $this->urlGenerator->imagePath('core', 'actions/logout.svg'),
240
-				]);
241
-			}
230
+            $logoutUrl = \OC_User::getLogoutUrl($this->urlGenerator);
231
+            if($logoutUrl !== '') {
232
+                // Logout
233
+                $this->add([
234
+                    'type' => 'settings',
235
+                    'id' => 'logout',
236
+                    'order' => 99999,
237
+                    'href' => $logoutUrl,
238
+                    'name' => $l->t('Log out'),
239
+                    'icon' => $this->urlGenerator->imagePath('core', 'actions/logout.svg'),
240
+                ]);
241
+            }
242 242
 
243
-			if ($this->isSubadmin()) {
244
-				// User management
245
-				$this->add([
246
-					'type' => 'settings',
247
-					'id' => 'core_users',
248
-					'order' => 4,
249
-					'href' => $this->urlGenerator->linkToRoute('settings_users'),
250
-					'name' => $l->t('Users'),
251
-					'icon' => $this->urlGenerator->imagePath('settings', 'users.svg'),
252
-				]);
253
-			}
254
-		}
243
+            if ($this->isSubadmin()) {
244
+                // User management
245
+                $this->add([
246
+                    'type' => 'settings',
247
+                    'id' => 'core_users',
248
+                    'order' => 4,
249
+                    'href' => $this->urlGenerator->linkToRoute('settings_users'),
250
+                    'name' => $l->t('Users'),
251
+                    'icon' => $this->urlGenerator->imagePath('settings', 'users.svg'),
252
+                ]);
253
+            }
254
+        }
255 255
 
256
-		if ($this->appManager === 'null') {
257
-			return;
258
-		}
256
+        if ($this->appManager === 'null') {
257
+            return;
258
+        }
259 259
 
260
-		if ($this->userSession->isLoggedIn()) {
261
-			$apps = $this->appManager->getEnabledAppsForUser($this->userSession->getUser());
262
-		} else {
263
-			$apps = $this->appManager->getInstalledApps();
264
-		}
260
+        if ($this->userSession->isLoggedIn()) {
261
+            $apps = $this->appManager->getEnabledAppsForUser($this->userSession->getUser());
262
+        } else {
263
+            $apps = $this->appManager->getInstalledApps();
264
+        }
265 265
 
266
-		foreach ($apps as $app) {
267
-			if (!$this->userSession->isLoggedIn() && !$this->appManager->isEnabledForUser($app, $this->userSession->getUser())) {
268
-				continue;
269
-			}
266
+        foreach ($apps as $app) {
267
+            if (!$this->userSession->isLoggedIn() && !$this->appManager->isEnabledForUser($app, $this->userSession->getUser())) {
268
+                continue;
269
+            }
270 270
 
271
-			// load plugins and collections from info.xml
272
-			$info = $this->appManager->getAppInfo($app);
273
-			if (empty($info['navigations'])) {
274
-				continue;
275
-			}
276
-			foreach ($info['navigations'] as $nav) {
277
-				if (!isset($nav['name'])) {
278
-					continue;
279
-				}
280
-				if (!isset($nav['route'])) {
281
-					continue;
282
-				}
283
-				$role = isset($nav['@attributes']['role']) ? $nav['@attributes']['role'] : 'all';
284
-				if ($role === 'admin' && !$this->isAdmin()) {
285
-					continue;
286
-				}
287
-				$l = $this->l10nFac->get($app);
288
-				$id = isset($nav['id']) ? $nav['id'] : $app;
289
-				$order = isset($nav['order']) ? $nav['order'] : 100;
290
-				$type = isset($nav['type']) ? $nav['type'] : 'link';
291
-				$route = $this->urlGenerator->linkToRoute($nav['route']);
292
-				$icon = isset($nav['icon']) ? $nav['icon'] : 'app.svg';
293
-				foreach ([$icon, "$app.svg"] as $i) {
294
-					try {
295
-						$icon = $this->urlGenerator->imagePath($app, $i);
296
-						break;
297
-					} catch (\RuntimeException $ex) {
298
-						// no icon? - ignore it then
299
-					}
300
-				}
301
-				if ($icon === null) {
302
-					$icon = $this->urlGenerator->imagePath('core', 'default-app-icon');
303
-				}
271
+            // load plugins and collections from info.xml
272
+            $info = $this->appManager->getAppInfo($app);
273
+            if (empty($info['navigations'])) {
274
+                continue;
275
+            }
276
+            foreach ($info['navigations'] as $nav) {
277
+                if (!isset($nav['name'])) {
278
+                    continue;
279
+                }
280
+                if (!isset($nav['route'])) {
281
+                    continue;
282
+                }
283
+                $role = isset($nav['@attributes']['role']) ? $nav['@attributes']['role'] : 'all';
284
+                if ($role === 'admin' && !$this->isAdmin()) {
285
+                    continue;
286
+                }
287
+                $l = $this->l10nFac->get($app);
288
+                $id = isset($nav['id']) ? $nav['id'] : $app;
289
+                $order = isset($nav['order']) ? $nav['order'] : 100;
290
+                $type = isset($nav['type']) ? $nav['type'] : 'link';
291
+                $route = $this->urlGenerator->linkToRoute($nav['route']);
292
+                $icon = isset($nav['icon']) ? $nav['icon'] : 'app.svg';
293
+                foreach ([$icon, "$app.svg"] as $i) {
294
+                    try {
295
+                        $icon = $this->urlGenerator->imagePath($app, $i);
296
+                        break;
297
+                    } catch (\RuntimeException $ex) {
298
+                        // no icon? - ignore it then
299
+                    }
300
+                }
301
+                if ($icon === null) {
302
+                    $icon = $this->urlGenerator->imagePath('core', 'default-app-icon');
303
+                }
304 304
 
305
-				$this->add([
306
-					'id' => $id,
307
-					'order' => $order,
308
-					'href' => $route,
309
-					'icon' => $icon,
310
-					'type' => $type,
311
-					'name' => $l->t($nav['name']),
312
-				]);
313
-			}
314
-		}
315
-	}
305
+                $this->add([
306
+                    'id' => $id,
307
+                    'order' => $order,
308
+                    'href' => $route,
309
+                    'icon' => $icon,
310
+                    'type' => $type,
311
+                    'name' => $l->t($nav['name']),
312
+                ]);
313
+            }
314
+        }
315
+    }
316 316
 
317
-	private function isAdmin() {
318
-		$user = $this->userSession->getUser();
319
-		if ($user !== null) {
320
-			return $this->groupManager->isAdmin($user->getUID());
321
-		}
322
-		return false;
323
-	}
317
+    private function isAdmin() {
318
+        $user = $this->userSession->getUser();
319
+        if ($user !== null) {
320
+            return $this->groupManager->isAdmin($user->getUID());
321
+        }
322
+        return false;
323
+    }
324 324
 
325
-	private function isSubadmin() {
326
-		$user = $this->userSession->getUser();
327
-		if ($user !== null) {
328
-			return $this->groupManager->getSubAdmin()->isSubAdmin($user);
329
-		}
330
-		return false;
331
-	}
325
+    private function isSubadmin() {
326
+        $user = $this->userSession->getUser();
327
+        if ($user !== null) {
328
+            return $this->groupManager->getSubAdmin()->isSubAdmin($user);
329
+        }
330
+        return false;
331
+    }
332 332
 }
Please login to merge, or discard this patch.
lib/private/legacy/app.php 1 patch
Indentation   +1153 added lines, -1153 removed lines patch added patch discarded remove patch
@@ -63,1157 +63,1157 @@
 block discarded – undo
63 63
  * upgrading and removing apps.
64 64
  */
65 65
 class OC_App {
66
-	static private $appVersion = [];
67
-	static private $adminForms = array();
68
-	static private $personalForms = array();
69
-	static private $appInfo = array();
70
-	static private $appTypes = array();
71
-	static private $loadedApps = array();
72
-	static private $altLogin = array();
73
-	static private $alreadyRegistered = [];
74
-	const officialApp = 200;
75
-
76
-	/**
77
-	 * clean the appId
78
-	 *
79
-	 * @param string|boolean $app AppId that needs to be cleaned
80
-	 * @return string
81
-	 */
82
-	public static function cleanAppId($app) {
83
-		return str_replace(array('\0', '/', '\\', '..'), '', $app);
84
-	}
85
-
86
-	/**
87
-	 * Check if an app is loaded
88
-	 *
89
-	 * @param string $app
90
-	 * @return bool
91
-	 */
92
-	public static function isAppLoaded($app) {
93
-		return in_array($app, self::$loadedApps, true);
94
-	}
95
-
96
-	/**
97
-	 * loads all apps
98
-	 *
99
-	 * @param string[] | string | null $types
100
-	 * @return bool
101
-	 *
102
-	 * This function walks through the ownCloud directory and loads all apps
103
-	 * it can find. A directory contains an app if the file /appinfo/info.xml
104
-	 * exists.
105
-	 *
106
-	 * if $types is set, only apps of those types will be loaded
107
-	 */
108
-	public static function loadApps($types = null) {
109
-		if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
110
-			return false;
111
-		}
112
-		// Load the enabled apps here
113
-		$apps = self::getEnabledApps();
114
-
115
-		// Add each apps' folder as allowed class path
116
-		foreach($apps as $app) {
117
-			$path = self::getAppPath($app);
118
-			if($path !== false) {
119
-				self::registerAutoloading($app, $path);
120
-			}
121
-		}
122
-
123
-		// prevent app.php from printing output
124
-		ob_start();
125
-		foreach ($apps as $app) {
126
-			if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
127
-				self::loadApp($app);
128
-			}
129
-		}
130
-		ob_end_clean();
131
-
132
-		return true;
133
-	}
134
-
135
-	/**
136
-	 * load a single app
137
-	 *
138
-	 * @param string $app
139
-	 */
140
-	public static function loadApp($app) {
141
-		self::$loadedApps[] = $app;
142
-		$appPath = self::getAppPath($app);
143
-		if($appPath === false) {
144
-			return;
145
-		}
146
-
147
-		// in case someone calls loadApp() directly
148
-		self::registerAutoloading($app, $appPath);
149
-
150
-		if (is_file($appPath . '/appinfo/app.php')) {
151
-			\OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
152
-			self::requireAppFile($app);
153
-			if (self::isType($app, array('authentication'))) {
154
-				// since authentication apps affect the "is app enabled for group" check,
155
-				// the enabled apps cache needs to be cleared to make sure that the
156
-				// next time getEnableApps() is called it will also include apps that were
157
-				// enabled for groups
158
-				self::$enabledAppsCache = array();
159
-			}
160
-			\OC::$server->getEventLogger()->end('load_app_' . $app);
161
-		}
162
-
163
-		$info = self::getAppInfo($app);
164
-		if (!empty($info['activity']['filters'])) {
165
-			foreach ($info['activity']['filters'] as $filter) {
166
-				\OC::$server->getActivityManager()->registerFilter($filter);
167
-			}
168
-		}
169
-		if (!empty($info['activity']['settings'])) {
170
-			foreach ($info['activity']['settings'] as $setting) {
171
-				\OC::$server->getActivityManager()->registerSetting($setting);
172
-			}
173
-		}
174
-		if (!empty($info['activity']['providers'])) {
175
-			foreach ($info['activity']['providers'] as $provider) {
176
-				\OC::$server->getActivityManager()->registerProvider($provider);
177
-			}
178
-		}
179
-		if (!empty($info['collaboration']['plugins'])) {
180
-			// deal with one or many plugin entries
181
-			$plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
182
-				[$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
183
-			foreach ($plugins as $plugin) {
184
-				if($plugin['@attributes']['type'] === 'collaborator-search') {
185
-					$pluginInfo = [
186
-						'shareType' => $plugin['@attributes']['share-type'],
187
-						'class' => $plugin['@value'],
188
-					];
189
-					\OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
190
-				} else if ($plugin['@attributes']['type'] === 'autocomplete-sort') {
191
-					\OC::$server->getAutoCompleteManager()->registerSorter($plugin['@value']);
192
-				}
193
-			}
194
-		}
195
-	}
196
-
197
-	/**
198
-	 * @internal
199
-	 * @param string $app
200
-	 * @param string $path
201
-	 */
202
-	public static function registerAutoloading($app, $path) {
203
-		$key = $app . '-' . $path;
204
-		if(isset(self::$alreadyRegistered[$key])) {
205
-			return;
206
-		}
207
-
208
-		self::$alreadyRegistered[$key] = true;
209
-
210
-		// Register on PSR-4 composer autoloader
211
-		$appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
212
-		\OC::$server->registerNamespace($app, $appNamespace);
213
-
214
-		if (file_exists($path . '/composer/autoload.php')) {
215
-			require_once $path . '/composer/autoload.php';
216
-		} else {
217
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
218
-			// Register on legacy autoloader
219
-			\OC::$loader->addValidRoot($path);
220
-		}
221
-
222
-		// Register Test namespace only when testing
223
-		if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
224
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
225
-		}
226
-	}
227
-
228
-	/**
229
-	 * Load app.php from the given app
230
-	 *
231
-	 * @param string $app app name
232
-	 */
233
-	private static function requireAppFile($app) {
234
-		try {
235
-			// encapsulated here to avoid variable scope conflicts
236
-			require_once $app . '/appinfo/app.php';
237
-		} catch (Error $ex) {
238
-			\OC::$server->getLogger()->logException($ex);
239
-			if (!\OC::$server->getAppManager()->isShipped($app)) {
240
-				// Only disable apps which are not shipped
241
-				self::disable($app);
242
-			}
243
-		}
244
-	}
245
-
246
-	/**
247
-	 * check if an app is of a specific type
248
-	 *
249
-	 * @param string $app
250
-	 * @param string|array $types
251
-	 * @return bool
252
-	 */
253
-	public static function isType($app, $types) {
254
-		if (is_string($types)) {
255
-			$types = array($types);
256
-		}
257
-		$appTypes = self::getAppTypes($app);
258
-		foreach ($types as $type) {
259
-			if (array_search($type, $appTypes) !== false) {
260
-				return true;
261
-			}
262
-		}
263
-		return false;
264
-	}
265
-
266
-	/**
267
-	 * get the types of an app
268
-	 *
269
-	 * @param string $app
270
-	 * @return array
271
-	 */
272
-	private static function getAppTypes($app) {
273
-		//load the cache
274
-		if (count(self::$appTypes) == 0) {
275
-			self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
276
-		}
277
-
278
-		if (isset(self::$appTypes[$app])) {
279
-			return explode(',', self::$appTypes[$app]);
280
-		} else {
281
-			return array();
282
-		}
283
-	}
284
-
285
-	/**
286
-	 * read app types from info.xml and cache them in the database
287
-	 */
288
-	public static function setAppTypes($app) {
289
-		$appData = self::getAppInfo($app);
290
-		if(!is_array($appData)) {
291
-			return;
292
-		}
293
-
294
-		if (isset($appData['types'])) {
295
-			$appTypes = implode(',', $appData['types']);
296
-		} else {
297
-			$appTypes = '';
298
-			$appData['types'] = [];
299
-		}
300
-
301
-		\OC::$server->getConfig()->setAppValue($app, 'types', $appTypes);
302
-
303
-		if (\OC::$server->getAppManager()->hasProtectedAppType($appData['types'])) {
304
-			$enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'yes');
305
-			if ($enabled !== 'yes' && $enabled !== 'no') {
306
-				\OC::$server->getConfig()->setAppValue($app, 'enabled', 'yes');
307
-			}
308
-		}
309
-	}
310
-
311
-	/**
312
-	 * get all enabled apps
313
-	 */
314
-	protected static $enabledAppsCache = array();
315
-
316
-	/**
317
-	 * Returns apps enabled for the current user.
318
-	 *
319
-	 * @param bool $forceRefresh whether to refresh the cache
320
-	 * @param bool $all whether to return apps for all users, not only the
321
-	 * currently logged in one
322
-	 * @return string[]
323
-	 */
324
-	public static function getEnabledApps($forceRefresh = false, $all = false) {
325
-		if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
326
-			return array();
327
-		}
328
-		// in incognito mode or when logged out, $user will be false,
329
-		// which is also the case during an upgrade
330
-		$appManager = \OC::$server->getAppManager();
331
-		if ($all) {
332
-			$user = null;
333
-		} else {
334
-			$user = \OC::$server->getUserSession()->getUser();
335
-		}
336
-
337
-		if (is_null($user)) {
338
-			$apps = $appManager->getInstalledApps();
339
-		} else {
340
-			$apps = $appManager->getEnabledAppsForUser($user);
341
-		}
342
-		$apps = array_filter($apps, function ($app) {
343
-			return $app !== 'files';//we add this manually
344
-		});
345
-		sort($apps);
346
-		array_unshift($apps, 'files');
347
-		return $apps;
348
-	}
349
-
350
-	/**
351
-	 * checks whether or not an app is enabled
352
-	 *
353
-	 * @param string $app app
354
-	 * @return bool
355
-	 * @deprecated 13.0.0 use \OC::$server->getAppManager()->isEnabledForUser($appId)
356
-	 *
357
-	 * This function checks whether or not an app is enabled.
358
-	 */
359
-	public static function isEnabled($app) {
360
-		return \OC::$server->getAppManager()->isEnabledForUser($app);
361
-	}
362
-
363
-	/**
364
-	 * enables an app
365
-	 *
366
-	 * @param string $appId
367
-	 * @param array $groups (optional) when set, only these groups will have access to the app
368
-	 * @throws \Exception
369
-	 * @return void
370
-	 *
371
-	 * This function set an app as enabled in appconfig.
372
-	 */
373
-	public function enable($appId,
374
-						   $groups = null) {
375
-		self::$enabledAppsCache = []; // flush
376
-
377
-		// Check if app is already downloaded
378
-		$installer = \OC::$server->query(Installer::class);
379
-		$isDownloaded = $installer->isDownloaded($appId);
380
-
381
-		if(!$isDownloaded) {
382
-			$installer->downloadApp($appId);
383
-		}
384
-
385
-		$installer->installApp($appId);
386
-
387
-		$appManager = \OC::$server->getAppManager();
388
-		if (!is_null($groups)) {
389
-			$groupManager = \OC::$server->getGroupManager();
390
-			$groupsList = [];
391
-			foreach ($groups as $group) {
392
-				$groupItem = $groupManager->get($group);
393
-				if ($groupItem instanceof \OCP\IGroup) {
394
-					$groupsList[] = $groupManager->get($group);
395
-				}
396
-			}
397
-			$appManager->enableAppForGroups($appId, $groupsList);
398
-		} else {
399
-			$appManager->enableApp($appId);
400
-		}
401
-	}
402
-
403
-	/**
404
-	 * @param string $app
405
-	 * @return bool
406
-	 */
407
-	public static function removeApp($app) {
408
-		if (\OC::$server->getAppManager()->isShipped($app)) {
409
-			return false;
410
-		}
411
-
412
-		$installer = \OC::$server->query(Installer::class);
413
-		return $installer->removeApp($app);
414
-	}
415
-
416
-	/**
417
-	 * This function set an app as disabled in appconfig.
418
-	 *
419
-	 * @param string $app app
420
-	 * @throws Exception
421
-	 */
422
-	public static function disable($app) {
423
-		// flush
424
-		self::$enabledAppsCache = array();
425
-
426
-		// run uninstall steps
427
-		$appData = OC_App::getAppInfo($app);
428
-		if (!is_null($appData)) {
429
-			OC_App::executeRepairSteps($app, $appData['repair-steps']['uninstall']);
430
-		}
431
-
432
-		// emit disable hook - needed anymore ?
433
-		\OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
434
-
435
-		// finally disable it
436
-		$appManager = \OC::$server->getAppManager();
437
-		$appManager->disableApp($app);
438
-	}
439
-
440
-	/**
441
-	 * Get the path where to install apps
442
-	 *
443
-	 * @return string|false
444
-	 */
445
-	public static function getInstallPath() {
446
-		if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
447
-			return false;
448
-		}
449
-
450
-		foreach (OC::$APPSROOTS as $dir) {
451
-			if (isset($dir['writable']) && $dir['writable'] === true) {
452
-				return $dir['path'];
453
-			}
454
-		}
455
-
456
-		\OCP\Util::writeLog('core', 'No application directories are marked as writable.', \OCP\Util::ERROR);
457
-		return null;
458
-	}
459
-
460
-
461
-	/**
462
-	 * search for an app in all app-directories
463
-	 *
464
-	 * @param string $appId
465
-	 * @return false|string
466
-	 */
467
-	public static function findAppInDirectories($appId) {
468
-		$sanitizedAppId = self::cleanAppId($appId);
469
-		if($sanitizedAppId !== $appId) {
470
-			return false;
471
-		}
472
-		static $app_dir = array();
473
-
474
-		if (isset($app_dir[$appId])) {
475
-			return $app_dir[$appId];
476
-		}
477
-
478
-		$possibleApps = array();
479
-		foreach (OC::$APPSROOTS as $dir) {
480
-			if (file_exists($dir['path'] . '/' . $appId)) {
481
-				$possibleApps[] = $dir;
482
-			}
483
-		}
484
-
485
-		if (empty($possibleApps)) {
486
-			return false;
487
-		} elseif (count($possibleApps) === 1) {
488
-			$dir = array_shift($possibleApps);
489
-			$app_dir[$appId] = $dir;
490
-			return $dir;
491
-		} else {
492
-			$versionToLoad = array();
493
-			foreach ($possibleApps as $possibleApp) {
494
-				$version = self::getAppVersionByPath($possibleApp['path']);
495
-				if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
496
-					$versionToLoad = array(
497
-						'dir' => $possibleApp,
498
-						'version' => $version,
499
-					);
500
-				}
501
-			}
502
-			$app_dir[$appId] = $versionToLoad['dir'];
503
-			return $versionToLoad['dir'];
504
-			//TODO - write test
505
-		}
506
-	}
507
-
508
-	/**
509
-	 * Get the directory for the given app.
510
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
511
-	 *
512
-	 * @param string $appId
513
-	 * @return string|false
514
-	 */
515
-	public static function getAppPath($appId) {
516
-		if ($appId === null || trim($appId) === '') {
517
-			return false;
518
-		}
519
-
520
-		if (($dir = self::findAppInDirectories($appId)) != false) {
521
-			return $dir['path'] . '/' . $appId;
522
-		}
523
-		return false;
524
-	}
525
-
526
-	/**
527
-	 * Get the path for the given app on the access
528
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
529
-	 *
530
-	 * @param string $appId
531
-	 * @return string|false
532
-	 */
533
-	public static function getAppWebPath($appId) {
534
-		if (($dir = self::findAppInDirectories($appId)) != false) {
535
-			return OC::$WEBROOT . $dir['url'] . '/' . $appId;
536
-		}
537
-		return false;
538
-	}
539
-
540
-	/**
541
-	 * get the last version of the app from appinfo/info.xml
542
-	 *
543
-	 * @param string $appId
544
-	 * @param bool $useCache
545
-	 * @return string
546
-	 */
547
-	public static function getAppVersion($appId, $useCache = true) {
548
-		if($useCache && isset(self::$appVersion[$appId])) {
549
-			return self::$appVersion[$appId];
550
-		}
551
-
552
-		$file = self::getAppPath($appId);
553
-		self::$appVersion[$appId] = ($file !== false) ? self::getAppVersionByPath($file) : '0';
554
-		return self::$appVersion[$appId];
555
-	}
556
-
557
-	/**
558
-	 * get app's version based on it's path
559
-	 *
560
-	 * @param string $path
561
-	 * @return string
562
-	 */
563
-	public static function getAppVersionByPath($path) {
564
-		$infoFile = $path . '/appinfo/info.xml';
565
-		$appData = self::getAppInfo($infoFile, true);
566
-		return isset($appData['version']) ? $appData['version'] : '';
567
-	}
568
-
569
-
570
-	/**
571
-	 * Read all app metadata from the info.xml file
572
-	 *
573
-	 * @param string $appId id of the app or the path of the info.xml file
574
-	 * @param bool $path
575
-	 * @param string $lang
576
-	 * @return array|null
577
-	 * @note all data is read from info.xml, not just pre-defined fields
578
-	 */
579
-	public static function getAppInfo($appId, $path = false, $lang = null) {
580
-		if ($path) {
581
-			$file = $appId;
582
-		} else {
583
-			if ($lang === null && isset(self::$appInfo[$appId])) {
584
-				return self::$appInfo[$appId];
585
-			}
586
-			$appPath = self::getAppPath($appId);
587
-			if($appPath === false) {
588
-				return null;
589
-			}
590
-			$file = $appPath . '/appinfo/info.xml';
591
-		}
592
-
593
-		$parser = new InfoParser(\OC::$server->getMemCacheFactory()->createLocal('core.appinfo'));
594
-		$data = $parser->parse($file);
595
-
596
-		if (is_array($data)) {
597
-			$data = OC_App::parseAppInfo($data, $lang);
598
-		}
599
-		if(isset($data['ocsid'])) {
600
-			$storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
601
-			if($storedId !== '' && $storedId !== $data['ocsid']) {
602
-				$data['ocsid'] = $storedId;
603
-			}
604
-		}
605
-
606
-		if ($lang === null) {
607
-			self::$appInfo[$appId] = $data;
608
-		}
609
-
610
-		return $data;
611
-	}
612
-
613
-	/**
614
-	 * Returns the navigation
615
-	 *
616
-	 * @return array
617
-	 *
618
-	 * This function returns an array containing all entries added. The
619
-	 * entries are sorted by the key 'order' ascending. Additional to the keys
620
-	 * given for each app the following keys exist:
621
-	 *   - active: boolean, signals if the user is on this navigation entry
622
-	 */
623
-	public static function getNavigation() {
624
-		return OC::$server->getNavigationManager()->getAll();
625
-	}
626
-
627
-	/**
628
-	 * Returns the Settings Navigation
629
-	 *
630
-	 * @return string[]
631
-	 *
632
-	 * This function returns an array containing all settings pages added. The
633
-	 * entries are sorted by the key 'order' ascending.
634
-	 */
635
-	public static function getSettingsNavigation() {
636
-		return OC::$server->getNavigationManager()->getAll('settings');
637
-	}
638
-
639
-	/**
640
-	 * get the id of loaded app
641
-	 *
642
-	 * @return string
643
-	 */
644
-	public static function getCurrentApp() {
645
-		$request = \OC::$server->getRequest();
646
-		$script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
647
-		$topFolder = substr($script, 0, strpos($script, '/') ?: 0);
648
-		if (empty($topFolder)) {
649
-			$path_info = $request->getPathInfo();
650
-			if ($path_info) {
651
-				$topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
652
-			}
653
-		}
654
-		if ($topFolder == 'apps') {
655
-			$length = strlen($topFolder);
656
-			return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1);
657
-		} else {
658
-			return $topFolder;
659
-		}
660
-	}
661
-
662
-	/**
663
-	 * @param string $type
664
-	 * @return array
665
-	 */
666
-	public static function getForms($type) {
667
-		$forms = array();
668
-		switch ($type) {
669
-			case 'admin':
670
-				$source = self::$adminForms;
671
-				break;
672
-			case 'personal':
673
-				$source = self::$personalForms;
674
-				break;
675
-			default:
676
-				return array();
677
-		}
678
-		foreach ($source as $form) {
679
-			$forms[] = include $form;
680
-		}
681
-		return $forms;
682
-	}
683
-
684
-	/**
685
-	 * register an admin form to be shown
686
-	 *
687
-	 * @param string $app
688
-	 * @param string $page
689
-	 */
690
-	public static function registerAdmin($app, $page) {
691
-		self::$adminForms[] = $app . '/' . $page . '.php';
692
-	}
693
-
694
-	/**
695
-	 * register a personal form to be shown
696
-	 * @param string $app
697
-	 * @param string $page
698
-	 */
699
-	public static function registerPersonal($app, $page) {
700
-		self::$personalForms[] = $app . '/' . $page . '.php';
701
-	}
702
-
703
-	/**
704
-	 * @param array $entry
705
-	 */
706
-	public static function registerLogIn(array $entry) {
707
-		self::$altLogin[] = $entry;
708
-	}
709
-
710
-	/**
711
-	 * @return array
712
-	 */
713
-	public static function getAlternativeLogIns() {
714
-		return self::$altLogin;
715
-	}
716
-
717
-	/**
718
-	 * get a list of all apps in the apps folder
719
-	 *
720
-	 * @return array an array of app names (string IDs)
721
-	 * @todo: change the name of this method to getInstalledApps, which is more accurate
722
-	 */
723
-	public static function getAllApps() {
724
-
725
-		$apps = array();
726
-
727
-		foreach (OC::$APPSROOTS as $apps_dir) {
728
-			if (!is_readable($apps_dir['path'])) {
729
-				\OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
730
-				continue;
731
-			}
732
-			$dh = opendir($apps_dir['path']);
733
-
734
-			if (is_resource($dh)) {
735
-				while (($file = readdir($dh)) !== false) {
736
-
737
-					if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
738
-
739
-						$apps[] = $file;
740
-					}
741
-				}
742
-			}
743
-		}
744
-
745
-		$apps = array_unique($apps);
746
-
747
-		return $apps;
748
-	}
749
-
750
-	/**
751
-	 * List all apps, this is used in apps.php
752
-	 *
753
-	 * @return array
754
-	 */
755
-	public function listAllApps() {
756
-		$installedApps = OC_App::getAllApps();
757
-
758
-		$appManager = \OC::$server->getAppManager();
759
-		//we don't want to show configuration for these
760
-		$blacklist = $appManager->getAlwaysEnabledApps();
761
-		$appList = array();
762
-		$langCode = \OC::$server->getL10N('core')->getLanguageCode();
763
-		$urlGenerator = \OC::$server->getURLGenerator();
764
-
765
-		foreach ($installedApps as $app) {
766
-			if (array_search($app, $blacklist) === false) {
767
-
768
-				$info = OC_App::getAppInfo($app, false, $langCode);
769
-				if (!is_array($info)) {
770
-					\OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
771
-					continue;
772
-				}
773
-
774
-				if (!isset($info['name'])) {
775
-					\OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
776
-					continue;
777
-				}
778
-
779
-				$enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'no');
780
-				$info['groups'] = null;
781
-				if ($enabled === 'yes') {
782
-					$active = true;
783
-				} else if ($enabled === 'no') {
784
-					$active = false;
785
-				} else {
786
-					$active = true;
787
-					$info['groups'] = $enabled;
788
-				}
789
-
790
-				$info['active'] = $active;
791
-
792
-				if ($appManager->isShipped($app)) {
793
-					$info['internal'] = true;
794
-					$info['level'] = self::officialApp;
795
-					$info['removable'] = false;
796
-				} else {
797
-					$info['internal'] = false;
798
-					$info['removable'] = true;
799
-				}
800
-
801
-				$appPath = self::getAppPath($app);
802
-				if($appPath !== false) {
803
-					$appIcon = $appPath . '/img/' . $app . '.svg';
804
-					if (file_exists($appIcon)) {
805
-						$info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
806
-						$info['previewAsIcon'] = true;
807
-					} else {
808
-						$appIcon = $appPath . '/img/app.svg';
809
-						if (file_exists($appIcon)) {
810
-							$info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
811
-							$info['previewAsIcon'] = true;
812
-						}
813
-					}
814
-				}
815
-				// fix documentation
816
-				if (isset($info['documentation']) && is_array($info['documentation'])) {
817
-					foreach ($info['documentation'] as $key => $url) {
818
-						// If it is not an absolute URL we assume it is a key
819
-						// i.e. admin-ldap will get converted to go.php?to=admin-ldap
820
-						if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
821
-							$url = $urlGenerator->linkToDocs($url);
822
-						}
823
-
824
-						$info['documentation'][$key] = $url;
825
-					}
826
-				}
827
-
828
-				$info['version'] = OC_App::getAppVersion($app);
829
-				$appList[] = $info;
830
-			}
831
-		}
832
-
833
-		return $appList;
834
-	}
835
-
836
-	public static function shouldUpgrade($app) {
837
-		$versions = self::getAppVersions();
838
-		$currentVersion = OC_App::getAppVersion($app);
839
-		if ($currentVersion && isset($versions[$app])) {
840
-			$installedVersion = $versions[$app];
841
-			if (!version_compare($currentVersion, $installedVersion, '=')) {
842
-				return true;
843
-			}
844
-		}
845
-		return false;
846
-	}
847
-
848
-	/**
849
-	 * Adjust the number of version parts of $version1 to match
850
-	 * the number of version parts of $version2.
851
-	 *
852
-	 * @param string $version1 version to adjust
853
-	 * @param string $version2 version to take the number of parts from
854
-	 * @return string shortened $version1
855
-	 */
856
-	private static function adjustVersionParts($version1, $version2) {
857
-		$version1 = explode('.', $version1);
858
-		$version2 = explode('.', $version2);
859
-		// reduce $version1 to match the number of parts in $version2
860
-		while (count($version1) > count($version2)) {
861
-			array_pop($version1);
862
-		}
863
-		// if $version1 does not have enough parts, add some
864
-		while (count($version1) < count($version2)) {
865
-			$version1[] = '0';
866
-		}
867
-		return implode('.', $version1);
868
-	}
869
-
870
-	/**
871
-	 * Check whether the current ownCloud version matches the given
872
-	 * application's version requirements.
873
-	 *
874
-	 * The comparison is made based on the number of parts that the
875
-	 * app info version has. For example for ownCloud 6.0.3 if the
876
-	 * app info version is expecting version 6.0, the comparison is
877
-	 * made on the first two parts of the ownCloud version.
878
-	 * This means that it's possible to specify "requiremin" => 6
879
-	 * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
880
-	 *
881
-	 * @param string $ocVersion ownCloud version to check against
882
-	 * @param array $appInfo app info (from xml)
883
-	 *
884
-	 * @return boolean true if compatible, otherwise false
885
-	 */
886
-	public static function isAppCompatible($ocVersion, $appInfo) {
887
-		$requireMin = '';
888
-		$requireMax = '';
889
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
890
-			$requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
891
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
892
-			$requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
893
-		} else if (isset($appInfo['requiremin'])) {
894
-			$requireMin = $appInfo['requiremin'];
895
-		} else if (isset($appInfo['require'])) {
896
-			$requireMin = $appInfo['require'];
897
-		}
898
-
899
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
900
-			$requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
901
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
902
-			$requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
903
-		} else if (isset($appInfo['requiremax'])) {
904
-			$requireMax = $appInfo['requiremax'];
905
-		}
906
-
907
-		if (is_array($ocVersion)) {
908
-			$ocVersion = implode('.', $ocVersion);
909
-		}
910
-
911
-		if (!empty($requireMin)
912
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
913
-		) {
914
-
915
-			return false;
916
-		}
917
-
918
-		if (!empty($requireMax)
919
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
920
-		) {
921
-			return false;
922
-		}
923
-
924
-		return true;
925
-	}
926
-
927
-	/**
928
-	 * get the installed version of all apps
929
-	 */
930
-	public static function getAppVersions() {
931
-		static $versions;
932
-
933
-		if(!$versions) {
934
-			$appConfig = \OC::$server->getAppConfig();
935
-			$versions = $appConfig->getValues(false, 'installed_version');
936
-		}
937
-		return $versions;
938
-	}
939
-
940
-	/**
941
-	 * @param string $app
942
-	 * @param \OCP\IConfig $config
943
-	 * @param \OCP\IL10N $l
944
-	 * @return bool
945
-	 *
946
-	 * @throws Exception if app is not compatible with this version of ownCloud
947
-	 * @throws Exception if no app-name was specified
948
-	 */
949
-	public function installApp($app,
950
-							   \OCP\IConfig $config,
951
-							   \OCP\IL10N $l) {
952
-		if ($app !== false) {
953
-			// check if the app is compatible with this version of ownCloud
954
-			$info = self::getAppInfo($app);
955
-			if(!is_array($info)) {
956
-				throw new \Exception(
957
-					$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
958
-						[$info['name']]
959
-					)
960
-				);
961
-			}
962
-
963
-			$version = \OCP\Util::getVersion();
964
-			if (!self::isAppCompatible($version, $info)) {
965
-				throw new \Exception(
966
-					$l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
967
-						array($info['name'])
968
-					)
969
-				);
970
-			}
971
-
972
-			// check for required dependencies
973
-			self::checkAppDependencies($config, $l, $info);
974
-
975
-			$config->setAppValue($app, 'enabled', 'yes');
976
-			if (isset($appData['id'])) {
977
-				$config->setAppValue($app, 'ocsid', $appData['id']);
978
-			}
979
-
980
-			if(isset($info['settings']) && is_array($info['settings'])) {
981
-				$appPath = self::getAppPath($app);
982
-				self::registerAutoloading($app, $appPath);
983
-				\OC::$server->getSettingsManager()->setupSettings($info['settings']);
984
-			}
985
-
986
-			\OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
987
-		} else {
988
-			if(empty($appName) ) {
989
-				throw new \Exception($l->t("No app name specified"));
990
-			} else {
991
-				throw new \Exception($l->t("App '%s' could not be installed!", $appName));
992
-			}
993
-		}
994
-
995
-		return $app;
996
-	}
997
-
998
-	/**
999
-	 * update the database for the app and call the update script
1000
-	 *
1001
-	 * @param string $appId
1002
-	 * @return bool
1003
-	 */
1004
-	public static function updateApp($appId) {
1005
-		$appPath = self::getAppPath($appId);
1006
-		if($appPath === false) {
1007
-			return false;
1008
-		}
1009
-		self::registerAutoloading($appId, $appPath);
1010
-
1011
-		$appData = self::getAppInfo($appId);
1012
-		self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
1013
-
1014
-		if (file_exists($appPath . '/appinfo/database.xml')) {
1015
-			OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
1016
-		} else {
1017
-			$ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
1018
-			$ms->migrate();
1019
-		}
1020
-
1021
-		self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
1022
-		self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
1023
-		unset(self::$appVersion[$appId]);
1024
-
1025
-		// run upgrade code
1026
-		if (file_exists($appPath . '/appinfo/update.php')) {
1027
-			self::loadApp($appId);
1028
-			include $appPath . '/appinfo/update.php';
1029
-		}
1030
-		self::setupBackgroundJobs($appData['background-jobs']);
1031
-		if(isset($appData['settings']) && is_array($appData['settings'])) {
1032
-			\OC::$server->getSettingsManager()->setupSettings($appData['settings']);
1033
-		}
1034
-
1035
-		//set remote/public handlers
1036
-		if (array_key_exists('ocsid', $appData)) {
1037
-			\OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
1038
-		} elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1039
-			\OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
1040
-		}
1041
-		foreach ($appData['remote'] as $name => $path) {
1042
-			\OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
1043
-		}
1044
-		foreach ($appData['public'] as $name => $path) {
1045
-			\OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
1046
-		}
1047
-
1048
-		self::setAppTypes($appId);
1049
-
1050
-		$version = \OC_App::getAppVersion($appId);
1051
-		\OC::$server->getConfig()->setAppValue($appId, 'installed_version', $version);
1052
-
1053
-		\OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
1054
-			ManagerEvent::EVENT_APP_UPDATE, $appId
1055
-		));
1056
-
1057
-		return true;
1058
-	}
1059
-
1060
-	/**
1061
-	 * @param string $appId
1062
-	 * @param string[] $steps
1063
-	 * @throws \OC\NeedsUpdateException
1064
-	 */
1065
-	public static function executeRepairSteps($appId, array $steps) {
1066
-		if (empty($steps)) {
1067
-			return;
1068
-		}
1069
-		// load the app
1070
-		self::loadApp($appId);
1071
-
1072
-		$dispatcher = OC::$server->getEventDispatcher();
1073
-
1074
-		// load the steps
1075
-		$r = new Repair([], $dispatcher);
1076
-		foreach ($steps as $step) {
1077
-			try {
1078
-				$r->addStep($step);
1079
-			} catch (Exception $ex) {
1080
-				$r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
1081
-				\OC::$server->getLogger()->logException($ex);
1082
-			}
1083
-		}
1084
-		// run the steps
1085
-		$r->run();
1086
-	}
1087
-
1088
-	public static function setupBackgroundJobs(array $jobs) {
1089
-		$queue = \OC::$server->getJobList();
1090
-		foreach ($jobs as $job) {
1091
-			$queue->add($job);
1092
-		}
1093
-	}
1094
-
1095
-	/**
1096
-	 * @param string $appId
1097
-	 * @param string[] $steps
1098
-	 */
1099
-	private static function setupLiveMigrations($appId, array $steps) {
1100
-		$queue = \OC::$server->getJobList();
1101
-		foreach ($steps as $step) {
1102
-			$queue->add('OC\Migration\BackgroundRepair', [
1103
-				'app' => $appId,
1104
-				'step' => $step]);
1105
-		}
1106
-	}
1107
-
1108
-	/**
1109
-	 * @param string $appId
1110
-	 * @return \OC\Files\View|false
1111
-	 */
1112
-	public static function getStorage($appId) {
1113
-		if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check
1114
-			if (\OC::$server->getUserSession()->isLoggedIn()) {
1115
-				$view = new \OC\Files\View('/' . OC_User::getUser());
1116
-				if (!$view->file_exists($appId)) {
1117
-					$view->mkdir($appId);
1118
-				}
1119
-				return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1120
-			} else {
1121
-				\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
1122
-				return false;
1123
-			}
1124
-		} else {
1125
-			\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
1126
-			return false;
1127
-		}
1128
-	}
1129
-
1130
-	protected static function findBestL10NOption($options, $lang) {
1131
-		$fallback = $similarLangFallback = $englishFallback = false;
1132
-
1133
-		$lang = strtolower($lang);
1134
-		$similarLang = $lang;
1135
-		if (strpos($similarLang, '_')) {
1136
-			// For "de_DE" we want to find "de" and the other way around
1137
-			$similarLang = substr($lang, 0, strpos($lang, '_'));
1138
-		}
1139
-
1140
-		foreach ($options as $option) {
1141
-			if (is_array($option)) {
1142
-				if ($fallback === false) {
1143
-					$fallback = $option['@value'];
1144
-				}
1145
-
1146
-				if (!isset($option['@attributes']['lang'])) {
1147
-					continue;
1148
-				}
1149
-
1150
-				$attributeLang = strtolower($option['@attributes']['lang']);
1151
-				if ($attributeLang === $lang) {
1152
-					return $option['@value'];
1153
-				}
1154
-
1155
-				if ($attributeLang === $similarLang) {
1156
-					$similarLangFallback = $option['@value'];
1157
-				} else if (strpos($attributeLang, $similarLang . '_') === 0) {
1158
-					if ($similarLangFallback === false) {
1159
-						$similarLangFallback =  $option['@value'];
1160
-					}
1161
-				}
1162
-			} else {
1163
-				$englishFallback = $option;
1164
-			}
1165
-		}
1166
-
1167
-		if ($similarLangFallback !== false) {
1168
-			return $similarLangFallback;
1169
-		} else if ($englishFallback !== false) {
1170
-			return $englishFallback;
1171
-		}
1172
-		return (string) $fallback;
1173
-	}
1174
-
1175
-	/**
1176
-	 * parses the app data array and enhanced the 'description' value
1177
-	 *
1178
-	 * @param array $data the app data
1179
-	 * @param string $lang
1180
-	 * @return array improved app data
1181
-	 */
1182
-	public static function parseAppInfo(array $data, $lang = null) {
1183
-
1184
-		if ($lang && isset($data['name']) && is_array($data['name'])) {
1185
-			$data['name'] = self::findBestL10NOption($data['name'], $lang);
1186
-		}
1187
-		if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1188
-			$data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1189
-		}
1190
-		if ($lang && isset($data['description']) && is_array($data['description'])) {
1191
-			$data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1192
-		} else if (isset($data['description']) && is_string($data['description'])) {
1193
-			$data['description'] = trim($data['description']);
1194
-		} else  {
1195
-			$data['description'] = '';
1196
-		}
1197
-
1198
-		return $data;
1199
-	}
1200
-
1201
-	/**
1202
-	 * @param \OCP\IConfig $config
1203
-	 * @param \OCP\IL10N $l
1204
-	 * @param array $info
1205
-	 * @throws \Exception
1206
-	 */
1207
-	public static function checkAppDependencies($config, $l, $info) {
1208
-		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1209
-		$missing = $dependencyAnalyzer->analyze($info);
1210
-		if (!empty($missing)) {
1211
-			$missingMsg = implode(PHP_EOL, $missing);
1212
-			throw new \Exception(
1213
-				$l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
1214
-					[$info['name'], $missingMsg]
1215
-				)
1216
-			);
1217
-		}
1218
-	}
66
+    static private $appVersion = [];
67
+    static private $adminForms = array();
68
+    static private $personalForms = array();
69
+    static private $appInfo = array();
70
+    static private $appTypes = array();
71
+    static private $loadedApps = array();
72
+    static private $altLogin = array();
73
+    static private $alreadyRegistered = [];
74
+    const officialApp = 200;
75
+
76
+    /**
77
+     * clean the appId
78
+     *
79
+     * @param string|boolean $app AppId that needs to be cleaned
80
+     * @return string
81
+     */
82
+    public static function cleanAppId($app) {
83
+        return str_replace(array('\0', '/', '\\', '..'), '', $app);
84
+    }
85
+
86
+    /**
87
+     * Check if an app is loaded
88
+     *
89
+     * @param string $app
90
+     * @return bool
91
+     */
92
+    public static function isAppLoaded($app) {
93
+        return in_array($app, self::$loadedApps, true);
94
+    }
95
+
96
+    /**
97
+     * loads all apps
98
+     *
99
+     * @param string[] | string | null $types
100
+     * @return bool
101
+     *
102
+     * This function walks through the ownCloud directory and loads all apps
103
+     * it can find. A directory contains an app if the file /appinfo/info.xml
104
+     * exists.
105
+     *
106
+     * if $types is set, only apps of those types will be loaded
107
+     */
108
+    public static function loadApps($types = null) {
109
+        if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
110
+            return false;
111
+        }
112
+        // Load the enabled apps here
113
+        $apps = self::getEnabledApps();
114
+
115
+        // Add each apps' folder as allowed class path
116
+        foreach($apps as $app) {
117
+            $path = self::getAppPath($app);
118
+            if($path !== false) {
119
+                self::registerAutoloading($app, $path);
120
+            }
121
+        }
122
+
123
+        // prevent app.php from printing output
124
+        ob_start();
125
+        foreach ($apps as $app) {
126
+            if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
127
+                self::loadApp($app);
128
+            }
129
+        }
130
+        ob_end_clean();
131
+
132
+        return true;
133
+    }
134
+
135
+    /**
136
+     * load a single app
137
+     *
138
+     * @param string $app
139
+     */
140
+    public static function loadApp($app) {
141
+        self::$loadedApps[] = $app;
142
+        $appPath = self::getAppPath($app);
143
+        if($appPath === false) {
144
+            return;
145
+        }
146
+
147
+        // in case someone calls loadApp() directly
148
+        self::registerAutoloading($app, $appPath);
149
+
150
+        if (is_file($appPath . '/appinfo/app.php')) {
151
+            \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
152
+            self::requireAppFile($app);
153
+            if (self::isType($app, array('authentication'))) {
154
+                // since authentication apps affect the "is app enabled for group" check,
155
+                // the enabled apps cache needs to be cleared to make sure that the
156
+                // next time getEnableApps() is called it will also include apps that were
157
+                // enabled for groups
158
+                self::$enabledAppsCache = array();
159
+            }
160
+            \OC::$server->getEventLogger()->end('load_app_' . $app);
161
+        }
162
+
163
+        $info = self::getAppInfo($app);
164
+        if (!empty($info['activity']['filters'])) {
165
+            foreach ($info['activity']['filters'] as $filter) {
166
+                \OC::$server->getActivityManager()->registerFilter($filter);
167
+            }
168
+        }
169
+        if (!empty($info['activity']['settings'])) {
170
+            foreach ($info['activity']['settings'] as $setting) {
171
+                \OC::$server->getActivityManager()->registerSetting($setting);
172
+            }
173
+        }
174
+        if (!empty($info['activity']['providers'])) {
175
+            foreach ($info['activity']['providers'] as $provider) {
176
+                \OC::$server->getActivityManager()->registerProvider($provider);
177
+            }
178
+        }
179
+        if (!empty($info['collaboration']['plugins'])) {
180
+            // deal with one or many plugin entries
181
+            $plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
182
+                [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
183
+            foreach ($plugins as $plugin) {
184
+                if($plugin['@attributes']['type'] === 'collaborator-search') {
185
+                    $pluginInfo = [
186
+                        'shareType' => $plugin['@attributes']['share-type'],
187
+                        'class' => $plugin['@value'],
188
+                    ];
189
+                    \OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
190
+                } else if ($plugin['@attributes']['type'] === 'autocomplete-sort') {
191
+                    \OC::$server->getAutoCompleteManager()->registerSorter($plugin['@value']);
192
+                }
193
+            }
194
+        }
195
+    }
196
+
197
+    /**
198
+     * @internal
199
+     * @param string $app
200
+     * @param string $path
201
+     */
202
+    public static function registerAutoloading($app, $path) {
203
+        $key = $app . '-' . $path;
204
+        if(isset(self::$alreadyRegistered[$key])) {
205
+            return;
206
+        }
207
+
208
+        self::$alreadyRegistered[$key] = true;
209
+
210
+        // Register on PSR-4 composer autoloader
211
+        $appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
212
+        \OC::$server->registerNamespace($app, $appNamespace);
213
+
214
+        if (file_exists($path . '/composer/autoload.php')) {
215
+            require_once $path . '/composer/autoload.php';
216
+        } else {
217
+            \OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
218
+            // Register on legacy autoloader
219
+            \OC::$loader->addValidRoot($path);
220
+        }
221
+
222
+        // Register Test namespace only when testing
223
+        if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
224
+            \OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
225
+        }
226
+    }
227
+
228
+    /**
229
+     * Load app.php from the given app
230
+     *
231
+     * @param string $app app name
232
+     */
233
+    private static function requireAppFile($app) {
234
+        try {
235
+            // encapsulated here to avoid variable scope conflicts
236
+            require_once $app . '/appinfo/app.php';
237
+        } catch (Error $ex) {
238
+            \OC::$server->getLogger()->logException($ex);
239
+            if (!\OC::$server->getAppManager()->isShipped($app)) {
240
+                // Only disable apps which are not shipped
241
+                self::disable($app);
242
+            }
243
+        }
244
+    }
245
+
246
+    /**
247
+     * check if an app is of a specific type
248
+     *
249
+     * @param string $app
250
+     * @param string|array $types
251
+     * @return bool
252
+     */
253
+    public static function isType($app, $types) {
254
+        if (is_string($types)) {
255
+            $types = array($types);
256
+        }
257
+        $appTypes = self::getAppTypes($app);
258
+        foreach ($types as $type) {
259
+            if (array_search($type, $appTypes) !== false) {
260
+                return true;
261
+            }
262
+        }
263
+        return false;
264
+    }
265
+
266
+    /**
267
+     * get the types of an app
268
+     *
269
+     * @param string $app
270
+     * @return array
271
+     */
272
+    private static function getAppTypes($app) {
273
+        //load the cache
274
+        if (count(self::$appTypes) == 0) {
275
+            self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
276
+        }
277
+
278
+        if (isset(self::$appTypes[$app])) {
279
+            return explode(',', self::$appTypes[$app]);
280
+        } else {
281
+            return array();
282
+        }
283
+    }
284
+
285
+    /**
286
+     * read app types from info.xml and cache them in the database
287
+     */
288
+    public static function setAppTypes($app) {
289
+        $appData = self::getAppInfo($app);
290
+        if(!is_array($appData)) {
291
+            return;
292
+        }
293
+
294
+        if (isset($appData['types'])) {
295
+            $appTypes = implode(',', $appData['types']);
296
+        } else {
297
+            $appTypes = '';
298
+            $appData['types'] = [];
299
+        }
300
+
301
+        \OC::$server->getConfig()->setAppValue($app, 'types', $appTypes);
302
+
303
+        if (\OC::$server->getAppManager()->hasProtectedAppType($appData['types'])) {
304
+            $enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'yes');
305
+            if ($enabled !== 'yes' && $enabled !== 'no') {
306
+                \OC::$server->getConfig()->setAppValue($app, 'enabled', 'yes');
307
+            }
308
+        }
309
+    }
310
+
311
+    /**
312
+     * get all enabled apps
313
+     */
314
+    protected static $enabledAppsCache = array();
315
+
316
+    /**
317
+     * Returns apps enabled for the current user.
318
+     *
319
+     * @param bool $forceRefresh whether to refresh the cache
320
+     * @param bool $all whether to return apps for all users, not only the
321
+     * currently logged in one
322
+     * @return string[]
323
+     */
324
+    public static function getEnabledApps($forceRefresh = false, $all = false) {
325
+        if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
326
+            return array();
327
+        }
328
+        // in incognito mode or when logged out, $user will be false,
329
+        // which is also the case during an upgrade
330
+        $appManager = \OC::$server->getAppManager();
331
+        if ($all) {
332
+            $user = null;
333
+        } else {
334
+            $user = \OC::$server->getUserSession()->getUser();
335
+        }
336
+
337
+        if (is_null($user)) {
338
+            $apps = $appManager->getInstalledApps();
339
+        } else {
340
+            $apps = $appManager->getEnabledAppsForUser($user);
341
+        }
342
+        $apps = array_filter($apps, function ($app) {
343
+            return $app !== 'files';//we add this manually
344
+        });
345
+        sort($apps);
346
+        array_unshift($apps, 'files');
347
+        return $apps;
348
+    }
349
+
350
+    /**
351
+     * checks whether or not an app is enabled
352
+     *
353
+     * @param string $app app
354
+     * @return bool
355
+     * @deprecated 13.0.0 use \OC::$server->getAppManager()->isEnabledForUser($appId)
356
+     *
357
+     * This function checks whether or not an app is enabled.
358
+     */
359
+    public static function isEnabled($app) {
360
+        return \OC::$server->getAppManager()->isEnabledForUser($app);
361
+    }
362
+
363
+    /**
364
+     * enables an app
365
+     *
366
+     * @param string $appId
367
+     * @param array $groups (optional) when set, only these groups will have access to the app
368
+     * @throws \Exception
369
+     * @return void
370
+     *
371
+     * This function set an app as enabled in appconfig.
372
+     */
373
+    public function enable($appId,
374
+                            $groups = null) {
375
+        self::$enabledAppsCache = []; // flush
376
+
377
+        // Check if app is already downloaded
378
+        $installer = \OC::$server->query(Installer::class);
379
+        $isDownloaded = $installer->isDownloaded($appId);
380
+
381
+        if(!$isDownloaded) {
382
+            $installer->downloadApp($appId);
383
+        }
384
+
385
+        $installer->installApp($appId);
386
+
387
+        $appManager = \OC::$server->getAppManager();
388
+        if (!is_null($groups)) {
389
+            $groupManager = \OC::$server->getGroupManager();
390
+            $groupsList = [];
391
+            foreach ($groups as $group) {
392
+                $groupItem = $groupManager->get($group);
393
+                if ($groupItem instanceof \OCP\IGroup) {
394
+                    $groupsList[] = $groupManager->get($group);
395
+                }
396
+            }
397
+            $appManager->enableAppForGroups($appId, $groupsList);
398
+        } else {
399
+            $appManager->enableApp($appId);
400
+        }
401
+    }
402
+
403
+    /**
404
+     * @param string $app
405
+     * @return bool
406
+     */
407
+    public static function removeApp($app) {
408
+        if (\OC::$server->getAppManager()->isShipped($app)) {
409
+            return false;
410
+        }
411
+
412
+        $installer = \OC::$server->query(Installer::class);
413
+        return $installer->removeApp($app);
414
+    }
415
+
416
+    /**
417
+     * This function set an app as disabled in appconfig.
418
+     *
419
+     * @param string $app app
420
+     * @throws Exception
421
+     */
422
+    public static function disable($app) {
423
+        // flush
424
+        self::$enabledAppsCache = array();
425
+
426
+        // run uninstall steps
427
+        $appData = OC_App::getAppInfo($app);
428
+        if (!is_null($appData)) {
429
+            OC_App::executeRepairSteps($app, $appData['repair-steps']['uninstall']);
430
+        }
431
+
432
+        // emit disable hook - needed anymore ?
433
+        \OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
434
+
435
+        // finally disable it
436
+        $appManager = \OC::$server->getAppManager();
437
+        $appManager->disableApp($app);
438
+    }
439
+
440
+    /**
441
+     * Get the path where to install apps
442
+     *
443
+     * @return string|false
444
+     */
445
+    public static function getInstallPath() {
446
+        if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
447
+            return false;
448
+        }
449
+
450
+        foreach (OC::$APPSROOTS as $dir) {
451
+            if (isset($dir['writable']) && $dir['writable'] === true) {
452
+                return $dir['path'];
453
+            }
454
+        }
455
+
456
+        \OCP\Util::writeLog('core', 'No application directories are marked as writable.', \OCP\Util::ERROR);
457
+        return null;
458
+    }
459
+
460
+
461
+    /**
462
+     * search for an app in all app-directories
463
+     *
464
+     * @param string $appId
465
+     * @return false|string
466
+     */
467
+    public static function findAppInDirectories($appId) {
468
+        $sanitizedAppId = self::cleanAppId($appId);
469
+        if($sanitizedAppId !== $appId) {
470
+            return false;
471
+        }
472
+        static $app_dir = array();
473
+
474
+        if (isset($app_dir[$appId])) {
475
+            return $app_dir[$appId];
476
+        }
477
+
478
+        $possibleApps = array();
479
+        foreach (OC::$APPSROOTS as $dir) {
480
+            if (file_exists($dir['path'] . '/' . $appId)) {
481
+                $possibleApps[] = $dir;
482
+            }
483
+        }
484
+
485
+        if (empty($possibleApps)) {
486
+            return false;
487
+        } elseif (count($possibleApps) === 1) {
488
+            $dir = array_shift($possibleApps);
489
+            $app_dir[$appId] = $dir;
490
+            return $dir;
491
+        } else {
492
+            $versionToLoad = array();
493
+            foreach ($possibleApps as $possibleApp) {
494
+                $version = self::getAppVersionByPath($possibleApp['path']);
495
+                if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
496
+                    $versionToLoad = array(
497
+                        'dir' => $possibleApp,
498
+                        'version' => $version,
499
+                    );
500
+                }
501
+            }
502
+            $app_dir[$appId] = $versionToLoad['dir'];
503
+            return $versionToLoad['dir'];
504
+            //TODO - write test
505
+        }
506
+    }
507
+
508
+    /**
509
+     * Get the directory for the given app.
510
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
511
+     *
512
+     * @param string $appId
513
+     * @return string|false
514
+     */
515
+    public static function getAppPath($appId) {
516
+        if ($appId === null || trim($appId) === '') {
517
+            return false;
518
+        }
519
+
520
+        if (($dir = self::findAppInDirectories($appId)) != false) {
521
+            return $dir['path'] . '/' . $appId;
522
+        }
523
+        return false;
524
+    }
525
+
526
+    /**
527
+     * Get the path for the given app on the access
528
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
529
+     *
530
+     * @param string $appId
531
+     * @return string|false
532
+     */
533
+    public static function getAppWebPath($appId) {
534
+        if (($dir = self::findAppInDirectories($appId)) != false) {
535
+            return OC::$WEBROOT . $dir['url'] . '/' . $appId;
536
+        }
537
+        return false;
538
+    }
539
+
540
+    /**
541
+     * get the last version of the app from appinfo/info.xml
542
+     *
543
+     * @param string $appId
544
+     * @param bool $useCache
545
+     * @return string
546
+     */
547
+    public static function getAppVersion($appId, $useCache = true) {
548
+        if($useCache && isset(self::$appVersion[$appId])) {
549
+            return self::$appVersion[$appId];
550
+        }
551
+
552
+        $file = self::getAppPath($appId);
553
+        self::$appVersion[$appId] = ($file !== false) ? self::getAppVersionByPath($file) : '0';
554
+        return self::$appVersion[$appId];
555
+    }
556
+
557
+    /**
558
+     * get app's version based on it's path
559
+     *
560
+     * @param string $path
561
+     * @return string
562
+     */
563
+    public static function getAppVersionByPath($path) {
564
+        $infoFile = $path . '/appinfo/info.xml';
565
+        $appData = self::getAppInfo($infoFile, true);
566
+        return isset($appData['version']) ? $appData['version'] : '';
567
+    }
568
+
569
+
570
+    /**
571
+     * Read all app metadata from the info.xml file
572
+     *
573
+     * @param string $appId id of the app or the path of the info.xml file
574
+     * @param bool $path
575
+     * @param string $lang
576
+     * @return array|null
577
+     * @note all data is read from info.xml, not just pre-defined fields
578
+     */
579
+    public static function getAppInfo($appId, $path = false, $lang = null) {
580
+        if ($path) {
581
+            $file = $appId;
582
+        } else {
583
+            if ($lang === null && isset(self::$appInfo[$appId])) {
584
+                return self::$appInfo[$appId];
585
+            }
586
+            $appPath = self::getAppPath($appId);
587
+            if($appPath === false) {
588
+                return null;
589
+            }
590
+            $file = $appPath . '/appinfo/info.xml';
591
+        }
592
+
593
+        $parser = new InfoParser(\OC::$server->getMemCacheFactory()->createLocal('core.appinfo'));
594
+        $data = $parser->parse($file);
595
+
596
+        if (is_array($data)) {
597
+            $data = OC_App::parseAppInfo($data, $lang);
598
+        }
599
+        if(isset($data['ocsid'])) {
600
+            $storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
601
+            if($storedId !== '' && $storedId !== $data['ocsid']) {
602
+                $data['ocsid'] = $storedId;
603
+            }
604
+        }
605
+
606
+        if ($lang === null) {
607
+            self::$appInfo[$appId] = $data;
608
+        }
609
+
610
+        return $data;
611
+    }
612
+
613
+    /**
614
+     * Returns the navigation
615
+     *
616
+     * @return array
617
+     *
618
+     * This function returns an array containing all entries added. The
619
+     * entries are sorted by the key 'order' ascending. Additional to the keys
620
+     * given for each app the following keys exist:
621
+     *   - active: boolean, signals if the user is on this navigation entry
622
+     */
623
+    public static function getNavigation() {
624
+        return OC::$server->getNavigationManager()->getAll();
625
+    }
626
+
627
+    /**
628
+     * Returns the Settings Navigation
629
+     *
630
+     * @return string[]
631
+     *
632
+     * This function returns an array containing all settings pages added. The
633
+     * entries are sorted by the key 'order' ascending.
634
+     */
635
+    public static function getSettingsNavigation() {
636
+        return OC::$server->getNavigationManager()->getAll('settings');
637
+    }
638
+
639
+    /**
640
+     * get the id of loaded app
641
+     *
642
+     * @return string
643
+     */
644
+    public static function getCurrentApp() {
645
+        $request = \OC::$server->getRequest();
646
+        $script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
647
+        $topFolder = substr($script, 0, strpos($script, '/') ?: 0);
648
+        if (empty($topFolder)) {
649
+            $path_info = $request->getPathInfo();
650
+            if ($path_info) {
651
+                $topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
652
+            }
653
+        }
654
+        if ($topFolder == 'apps') {
655
+            $length = strlen($topFolder);
656
+            return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1);
657
+        } else {
658
+            return $topFolder;
659
+        }
660
+    }
661
+
662
+    /**
663
+     * @param string $type
664
+     * @return array
665
+     */
666
+    public static function getForms($type) {
667
+        $forms = array();
668
+        switch ($type) {
669
+            case 'admin':
670
+                $source = self::$adminForms;
671
+                break;
672
+            case 'personal':
673
+                $source = self::$personalForms;
674
+                break;
675
+            default:
676
+                return array();
677
+        }
678
+        foreach ($source as $form) {
679
+            $forms[] = include $form;
680
+        }
681
+        return $forms;
682
+    }
683
+
684
+    /**
685
+     * register an admin form to be shown
686
+     *
687
+     * @param string $app
688
+     * @param string $page
689
+     */
690
+    public static function registerAdmin($app, $page) {
691
+        self::$adminForms[] = $app . '/' . $page . '.php';
692
+    }
693
+
694
+    /**
695
+     * register a personal form to be shown
696
+     * @param string $app
697
+     * @param string $page
698
+     */
699
+    public static function registerPersonal($app, $page) {
700
+        self::$personalForms[] = $app . '/' . $page . '.php';
701
+    }
702
+
703
+    /**
704
+     * @param array $entry
705
+     */
706
+    public static function registerLogIn(array $entry) {
707
+        self::$altLogin[] = $entry;
708
+    }
709
+
710
+    /**
711
+     * @return array
712
+     */
713
+    public static function getAlternativeLogIns() {
714
+        return self::$altLogin;
715
+    }
716
+
717
+    /**
718
+     * get a list of all apps in the apps folder
719
+     *
720
+     * @return array an array of app names (string IDs)
721
+     * @todo: change the name of this method to getInstalledApps, which is more accurate
722
+     */
723
+    public static function getAllApps() {
724
+
725
+        $apps = array();
726
+
727
+        foreach (OC::$APPSROOTS as $apps_dir) {
728
+            if (!is_readable($apps_dir['path'])) {
729
+                \OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
730
+                continue;
731
+            }
732
+            $dh = opendir($apps_dir['path']);
733
+
734
+            if (is_resource($dh)) {
735
+                while (($file = readdir($dh)) !== false) {
736
+
737
+                    if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
738
+
739
+                        $apps[] = $file;
740
+                    }
741
+                }
742
+            }
743
+        }
744
+
745
+        $apps = array_unique($apps);
746
+
747
+        return $apps;
748
+    }
749
+
750
+    /**
751
+     * List all apps, this is used in apps.php
752
+     *
753
+     * @return array
754
+     */
755
+    public function listAllApps() {
756
+        $installedApps = OC_App::getAllApps();
757
+
758
+        $appManager = \OC::$server->getAppManager();
759
+        //we don't want to show configuration for these
760
+        $blacklist = $appManager->getAlwaysEnabledApps();
761
+        $appList = array();
762
+        $langCode = \OC::$server->getL10N('core')->getLanguageCode();
763
+        $urlGenerator = \OC::$server->getURLGenerator();
764
+
765
+        foreach ($installedApps as $app) {
766
+            if (array_search($app, $blacklist) === false) {
767
+
768
+                $info = OC_App::getAppInfo($app, false, $langCode);
769
+                if (!is_array($info)) {
770
+                    \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
771
+                    continue;
772
+                }
773
+
774
+                if (!isset($info['name'])) {
775
+                    \OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
776
+                    continue;
777
+                }
778
+
779
+                $enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'no');
780
+                $info['groups'] = null;
781
+                if ($enabled === 'yes') {
782
+                    $active = true;
783
+                } else if ($enabled === 'no') {
784
+                    $active = false;
785
+                } else {
786
+                    $active = true;
787
+                    $info['groups'] = $enabled;
788
+                }
789
+
790
+                $info['active'] = $active;
791
+
792
+                if ($appManager->isShipped($app)) {
793
+                    $info['internal'] = true;
794
+                    $info['level'] = self::officialApp;
795
+                    $info['removable'] = false;
796
+                } else {
797
+                    $info['internal'] = false;
798
+                    $info['removable'] = true;
799
+                }
800
+
801
+                $appPath = self::getAppPath($app);
802
+                if($appPath !== false) {
803
+                    $appIcon = $appPath . '/img/' . $app . '.svg';
804
+                    if (file_exists($appIcon)) {
805
+                        $info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
806
+                        $info['previewAsIcon'] = true;
807
+                    } else {
808
+                        $appIcon = $appPath . '/img/app.svg';
809
+                        if (file_exists($appIcon)) {
810
+                            $info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
811
+                            $info['previewAsIcon'] = true;
812
+                        }
813
+                    }
814
+                }
815
+                // fix documentation
816
+                if (isset($info['documentation']) && is_array($info['documentation'])) {
817
+                    foreach ($info['documentation'] as $key => $url) {
818
+                        // If it is not an absolute URL we assume it is a key
819
+                        // i.e. admin-ldap will get converted to go.php?to=admin-ldap
820
+                        if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
821
+                            $url = $urlGenerator->linkToDocs($url);
822
+                        }
823
+
824
+                        $info['documentation'][$key] = $url;
825
+                    }
826
+                }
827
+
828
+                $info['version'] = OC_App::getAppVersion($app);
829
+                $appList[] = $info;
830
+            }
831
+        }
832
+
833
+        return $appList;
834
+    }
835
+
836
+    public static function shouldUpgrade($app) {
837
+        $versions = self::getAppVersions();
838
+        $currentVersion = OC_App::getAppVersion($app);
839
+        if ($currentVersion && isset($versions[$app])) {
840
+            $installedVersion = $versions[$app];
841
+            if (!version_compare($currentVersion, $installedVersion, '=')) {
842
+                return true;
843
+            }
844
+        }
845
+        return false;
846
+    }
847
+
848
+    /**
849
+     * Adjust the number of version parts of $version1 to match
850
+     * the number of version parts of $version2.
851
+     *
852
+     * @param string $version1 version to adjust
853
+     * @param string $version2 version to take the number of parts from
854
+     * @return string shortened $version1
855
+     */
856
+    private static function adjustVersionParts($version1, $version2) {
857
+        $version1 = explode('.', $version1);
858
+        $version2 = explode('.', $version2);
859
+        // reduce $version1 to match the number of parts in $version2
860
+        while (count($version1) > count($version2)) {
861
+            array_pop($version1);
862
+        }
863
+        // if $version1 does not have enough parts, add some
864
+        while (count($version1) < count($version2)) {
865
+            $version1[] = '0';
866
+        }
867
+        return implode('.', $version1);
868
+    }
869
+
870
+    /**
871
+     * Check whether the current ownCloud version matches the given
872
+     * application's version requirements.
873
+     *
874
+     * The comparison is made based on the number of parts that the
875
+     * app info version has. For example for ownCloud 6.0.3 if the
876
+     * app info version is expecting version 6.0, the comparison is
877
+     * made on the first two parts of the ownCloud version.
878
+     * This means that it's possible to specify "requiremin" => 6
879
+     * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
880
+     *
881
+     * @param string $ocVersion ownCloud version to check against
882
+     * @param array $appInfo app info (from xml)
883
+     *
884
+     * @return boolean true if compatible, otherwise false
885
+     */
886
+    public static function isAppCompatible($ocVersion, $appInfo) {
887
+        $requireMin = '';
888
+        $requireMax = '';
889
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
890
+            $requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
891
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
892
+            $requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
893
+        } else if (isset($appInfo['requiremin'])) {
894
+            $requireMin = $appInfo['requiremin'];
895
+        } else if (isset($appInfo['require'])) {
896
+            $requireMin = $appInfo['require'];
897
+        }
898
+
899
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
900
+            $requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
901
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
902
+            $requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
903
+        } else if (isset($appInfo['requiremax'])) {
904
+            $requireMax = $appInfo['requiremax'];
905
+        }
906
+
907
+        if (is_array($ocVersion)) {
908
+            $ocVersion = implode('.', $ocVersion);
909
+        }
910
+
911
+        if (!empty($requireMin)
912
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
913
+        ) {
914
+
915
+            return false;
916
+        }
917
+
918
+        if (!empty($requireMax)
919
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
920
+        ) {
921
+            return false;
922
+        }
923
+
924
+        return true;
925
+    }
926
+
927
+    /**
928
+     * get the installed version of all apps
929
+     */
930
+    public static function getAppVersions() {
931
+        static $versions;
932
+
933
+        if(!$versions) {
934
+            $appConfig = \OC::$server->getAppConfig();
935
+            $versions = $appConfig->getValues(false, 'installed_version');
936
+        }
937
+        return $versions;
938
+    }
939
+
940
+    /**
941
+     * @param string $app
942
+     * @param \OCP\IConfig $config
943
+     * @param \OCP\IL10N $l
944
+     * @return bool
945
+     *
946
+     * @throws Exception if app is not compatible with this version of ownCloud
947
+     * @throws Exception if no app-name was specified
948
+     */
949
+    public function installApp($app,
950
+                                \OCP\IConfig $config,
951
+                                \OCP\IL10N $l) {
952
+        if ($app !== false) {
953
+            // check if the app is compatible with this version of ownCloud
954
+            $info = self::getAppInfo($app);
955
+            if(!is_array($info)) {
956
+                throw new \Exception(
957
+                    $l->t('App "%s" cannot be installed because appinfo file cannot be read.',
958
+                        [$info['name']]
959
+                    )
960
+                );
961
+            }
962
+
963
+            $version = \OCP\Util::getVersion();
964
+            if (!self::isAppCompatible($version, $info)) {
965
+                throw new \Exception(
966
+                    $l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
967
+                        array($info['name'])
968
+                    )
969
+                );
970
+            }
971
+
972
+            // check for required dependencies
973
+            self::checkAppDependencies($config, $l, $info);
974
+
975
+            $config->setAppValue($app, 'enabled', 'yes');
976
+            if (isset($appData['id'])) {
977
+                $config->setAppValue($app, 'ocsid', $appData['id']);
978
+            }
979
+
980
+            if(isset($info['settings']) && is_array($info['settings'])) {
981
+                $appPath = self::getAppPath($app);
982
+                self::registerAutoloading($app, $appPath);
983
+                \OC::$server->getSettingsManager()->setupSettings($info['settings']);
984
+            }
985
+
986
+            \OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
987
+        } else {
988
+            if(empty($appName) ) {
989
+                throw new \Exception($l->t("No app name specified"));
990
+            } else {
991
+                throw new \Exception($l->t("App '%s' could not be installed!", $appName));
992
+            }
993
+        }
994
+
995
+        return $app;
996
+    }
997
+
998
+    /**
999
+     * update the database for the app and call the update script
1000
+     *
1001
+     * @param string $appId
1002
+     * @return bool
1003
+     */
1004
+    public static function updateApp($appId) {
1005
+        $appPath = self::getAppPath($appId);
1006
+        if($appPath === false) {
1007
+            return false;
1008
+        }
1009
+        self::registerAutoloading($appId, $appPath);
1010
+
1011
+        $appData = self::getAppInfo($appId);
1012
+        self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
1013
+
1014
+        if (file_exists($appPath . '/appinfo/database.xml')) {
1015
+            OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
1016
+        } else {
1017
+            $ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
1018
+            $ms->migrate();
1019
+        }
1020
+
1021
+        self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
1022
+        self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
1023
+        unset(self::$appVersion[$appId]);
1024
+
1025
+        // run upgrade code
1026
+        if (file_exists($appPath . '/appinfo/update.php')) {
1027
+            self::loadApp($appId);
1028
+            include $appPath . '/appinfo/update.php';
1029
+        }
1030
+        self::setupBackgroundJobs($appData['background-jobs']);
1031
+        if(isset($appData['settings']) && is_array($appData['settings'])) {
1032
+            \OC::$server->getSettingsManager()->setupSettings($appData['settings']);
1033
+        }
1034
+
1035
+        //set remote/public handlers
1036
+        if (array_key_exists('ocsid', $appData)) {
1037
+            \OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
1038
+        } elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1039
+            \OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
1040
+        }
1041
+        foreach ($appData['remote'] as $name => $path) {
1042
+            \OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
1043
+        }
1044
+        foreach ($appData['public'] as $name => $path) {
1045
+            \OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
1046
+        }
1047
+
1048
+        self::setAppTypes($appId);
1049
+
1050
+        $version = \OC_App::getAppVersion($appId);
1051
+        \OC::$server->getConfig()->setAppValue($appId, 'installed_version', $version);
1052
+
1053
+        \OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
1054
+            ManagerEvent::EVENT_APP_UPDATE, $appId
1055
+        ));
1056
+
1057
+        return true;
1058
+    }
1059
+
1060
+    /**
1061
+     * @param string $appId
1062
+     * @param string[] $steps
1063
+     * @throws \OC\NeedsUpdateException
1064
+     */
1065
+    public static function executeRepairSteps($appId, array $steps) {
1066
+        if (empty($steps)) {
1067
+            return;
1068
+        }
1069
+        // load the app
1070
+        self::loadApp($appId);
1071
+
1072
+        $dispatcher = OC::$server->getEventDispatcher();
1073
+
1074
+        // load the steps
1075
+        $r = new Repair([], $dispatcher);
1076
+        foreach ($steps as $step) {
1077
+            try {
1078
+                $r->addStep($step);
1079
+            } catch (Exception $ex) {
1080
+                $r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
1081
+                \OC::$server->getLogger()->logException($ex);
1082
+            }
1083
+        }
1084
+        // run the steps
1085
+        $r->run();
1086
+    }
1087
+
1088
+    public static function setupBackgroundJobs(array $jobs) {
1089
+        $queue = \OC::$server->getJobList();
1090
+        foreach ($jobs as $job) {
1091
+            $queue->add($job);
1092
+        }
1093
+    }
1094
+
1095
+    /**
1096
+     * @param string $appId
1097
+     * @param string[] $steps
1098
+     */
1099
+    private static function setupLiveMigrations($appId, array $steps) {
1100
+        $queue = \OC::$server->getJobList();
1101
+        foreach ($steps as $step) {
1102
+            $queue->add('OC\Migration\BackgroundRepair', [
1103
+                'app' => $appId,
1104
+                'step' => $step]);
1105
+        }
1106
+    }
1107
+
1108
+    /**
1109
+     * @param string $appId
1110
+     * @return \OC\Files\View|false
1111
+     */
1112
+    public static function getStorage($appId) {
1113
+        if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check
1114
+            if (\OC::$server->getUserSession()->isLoggedIn()) {
1115
+                $view = new \OC\Files\View('/' . OC_User::getUser());
1116
+                if (!$view->file_exists($appId)) {
1117
+                    $view->mkdir($appId);
1118
+                }
1119
+                return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1120
+            } else {
1121
+                \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
1122
+                return false;
1123
+            }
1124
+        } else {
1125
+            \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
1126
+            return false;
1127
+        }
1128
+    }
1129
+
1130
+    protected static function findBestL10NOption($options, $lang) {
1131
+        $fallback = $similarLangFallback = $englishFallback = false;
1132
+
1133
+        $lang = strtolower($lang);
1134
+        $similarLang = $lang;
1135
+        if (strpos($similarLang, '_')) {
1136
+            // For "de_DE" we want to find "de" and the other way around
1137
+            $similarLang = substr($lang, 0, strpos($lang, '_'));
1138
+        }
1139
+
1140
+        foreach ($options as $option) {
1141
+            if (is_array($option)) {
1142
+                if ($fallback === false) {
1143
+                    $fallback = $option['@value'];
1144
+                }
1145
+
1146
+                if (!isset($option['@attributes']['lang'])) {
1147
+                    continue;
1148
+                }
1149
+
1150
+                $attributeLang = strtolower($option['@attributes']['lang']);
1151
+                if ($attributeLang === $lang) {
1152
+                    return $option['@value'];
1153
+                }
1154
+
1155
+                if ($attributeLang === $similarLang) {
1156
+                    $similarLangFallback = $option['@value'];
1157
+                } else if (strpos($attributeLang, $similarLang . '_') === 0) {
1158
+                    if ($similarLangFallback === false) {
1159
+                        $similarLangFallback =  $option['@value'];
1160
+                    }
1161
+                }
1162
+            } else {
1163
+                $englishFallback = $option;
1164
+            }
1165
+        }
1166
+
1167
+        if ($similarLangFallback !== false) {
1168
+            return $similarLangFallback;
1169
+        } else if ($englishFallback !== false) {
1170
+            return $englishFallback;
1171
+        }
1172
+        return (string) $fallback;
1173
+    }
1174
+
1175
+    /**
1176
+     * parses the app data array and enhanced the 'description' value
1177
+     *
1178
+     * @param array $data the app data
1179
+     * @param string $lang
1180
+     * @return array improved app data
1181
+     */
1182
+    public static function parseAppInfo(array $data, $lang = null) {
1183
+
1184
+        if ($lang && isset($data['name']) && is_array($data['name'])) {
1185
+            $data['name'] = self::findBestL10NOption($data['name'], $lang);
1186
+        }
1187
+        if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1188
+            $data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1189
+        }
1190
+        if ($lang && isset($data['description']) && is_array($data['description'])) {
1191
+            $data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1192
+        } else if (isset($data['description']) && is_string($data['description'])) {
1193
+            $data['description'] = trim($data['description']);
1194
+        } else  {
1195
+            $data['description'] = '';
1196
+        }
1197
+
1198
+        return $data;
1199
+    }
1200
+
1201
+    /**
1202
+     * @param \OCP\IConfig $config
1203
+     * @param \OCP\IL10N $l
1204
+     * @param array $info
1205
+     * @throws \Exception
1206
+     */
1207
+    public static function checkAppDependencies($config, $l, $info) {
1208
+        $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1209
+        $missing = $dependencyAnalyzer->analyze($info);
1210
+        if (!empty($missing)) {
1211
+            $missingMsg = implode(PHP_EOL, $missing);
1212
+            throw new \Exception(
1213
+                $l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
1214
+                    [$info['name'], $missingMsg]
1215
+                )
1216
+            );
1217
+        }
1218
+    }
1219 1219
 }
Please login to merge, or discard this patch.
core/routes.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -36,44 +36,44 @@  discard block
 block discarded – undo
36 36
 
37 37
 $application = new Application();
38 38
 $application->registerRoutes($this, [
39
-	'routes' => [
40
-		['name' => 'lost#email', 'url' => '/lostpassword/email', 'verb' => 'POST'],
41
-		['name' => 'lost#resetform', 'url' => '/lostpassword/reset/form/{token}/{userId}', 'verb' => 'GET'],
42
-		['name' => 'lost#setPassword', 'url' => '/lostpassword/set/{token}/{userId}', 'verb' => 'POST'],
43
-		['name' => 'user#getDisplayNames', 'url' => '/displaynames', 'verb' => 'POST'],
44
-		['name' => 'avatar#getAvatar', 'url' => '/avatar/{userId}/{size}', 'verb' => 'GET'],
45
-		['name' => 'avatar#deleteAvatar', 'url' => '/avatar/', 'verb' => 'DELETE'],
46
-		['name' => 'avatar#postCroppedAvatar', 'url' => '/avatar/cropped', 'verb' => 'POST'],
47
-		['name' => 'avatar#getTmpAvatar', 'url' => '/avatar/tmp', 'verb' => 'GET'],
48
-		['name' => 'avatar#postAvatar', 'url' => '/avatar/', 'verb' => 'POST'],
49
-		['name' => 'login#tryLogin', 'url' => '/login', 'verb' => 'POST'],
50
-		['name' => 'login#confirmPassword', 'url' => '/login/confirm', 'verb' => 'POST'],
51
-		['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'],
52
-		['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'],
53
-		['name' => 'ClientFlowLogin#showAuthPickerPage', 'url' => '/login/flow', 'verb' => 'GET'],
54
-		['name' => 'ClientFlowLogin#redirectPage', 'url' => '/login/flow/redirect', 'verb' => 'GET'],
55
-		['name' => 'ClientFlowLogin#generateAppPassword', 'url' => '/login/flow', 'verb' => 'POST'],
56
-		['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'],
57
-		['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'],
58
-		['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'],
59
-		['name' => 'OCJS#getConfig', 'url' => '/core/js/oc.js', 'verb' => 'GET'],
60
-		['name' => 'Preview#getPreviewByFileId', 'url' => '/core/preview', 'verb' => 'GET'],
61
-		['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'],
62
-		['name' => 'Navigation#getAppsNavigation', 'url' => '/core/navigation/apps', 'verb' => 'GET'],
63
-		['name' => 'Navigation#getSettingsNavigation', 'url' => '/core/navigation/settings', 'verb' => 'GET'],
64
-		['name' => 'Css#getCss', 'url' => '/css/{appName}/{fileName}', 'verb' => 'GET'],
65
-		['name' => 'Js#getJs', 'url' => '/js/{appName}/{fileName}', 'verb' => 'GET'],
66
-		['name' => 'contactsMenu#index', 'url' => '/contactsmenu/contacts', 'verb' => 'POST'],
67
-		['name' => 'contactsMenu#findOne', 'url' => '/contactsmenu/findOne', 'verb' => 'POST'],
68
-		['name' => 'AutoComplete#get', 'url' => 'autocomplete/get', 'verb' => 'GET'],
69
-		['name' => 'WalledGarden#get', 'url' => '/204', 'verb' => 'GET'],
70
-	],
71
-	'ocs' => [
72
-		['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
73
-		['root' => '', 'name' => 'OCS#getConfig', 'url' => '/config', 'verb' => 'GET'],
74
-		['root' => '/person', 'name' => 'OCS#personCheck', 'url' => '/check', 'verb' => 'POST'],
75
-		['root' => '/identityproof', 'name' => 'OCS#getIdentityProof', 'url' => '/key/{cloudId}', 'verb' => 'GET'],
76
-	],
39
+    'routes' => [
40
+        ['name' => 'lost#email', 'url' => '/lostpassword/email', 'verb' => 'POST'],
41
+        ['name' => 'lost#resetform', 'url' => '/lostpassword/reset/form/{token}/{userId}', 'verb' => 'GET'],
42
+        ['name' => 'lost#setPassword', 'url' => '/lostpassword/set/{token}/{userId}', 'verb' => 'POST'],
43
+        ['name' => 'user#getDisplayNames', 'url' => '/displaynames', 'verb' => 'POST'],
44
+        ['name' => 'avatar#getAvatar', 'url' => '/avatar/{userId}/{size}', 'verb' => 'GET'],
45
+        ['name' => 'avatar#deleteAvatar', 'url' => '/avatar/', 'verb' => 'DELETE'],
46
+        ['name' => 'avatar#postCroppedAvatar', 'url' => '/avatar/cropped', 'verb' => 'POST'],
47
+        ['name' => 'avatar#getTmpAvatar', 'url' => '/avatar/tmp', 'verb' => 'GET'],
48
+        ['name' => 'avatar#postAvatar', 'url' => '/avatar/', 'verb' => 'POST'],
49
+        ['name' => 'login#tryLogin', 'url' => '/login', 'verb' => 'POST'],
50
+        ['name' => 'login#confirmPassword', 'url' => '/login/confirm', 'verb' => 'POST'],
51
+        ['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'],
52
+        ['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'],
53
+        ['name' => 'ClientFlowLogin#showAuthPickerPage', 'url' => '/login/flow', 'verb' => 'GET'],
54
+        ['name' => 'ClientFlowLogin#redirectPage', 'url' => '/login/flow/redirect', 'verb' => 'GET'],
55
+        ['name' => 'ClientFlowLogin#generateAppPassword', 'url' => '/login/flow', 'verb' => 'POST'],
56
+        ['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'],
57
+        ['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'],
58
+        ['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'],
59
+        ['name' => 'OCJS#getConfig', 'url' => '/core/js/oc.js', 'verb' => 'GET'],
60
+        ['name' => 'Preview#getPreviewByFileId', 'url' => '/core/preview', 'verb' => 'GET'],
61
+        ['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'],
62
+        ['name' => 'Navigation#getAppsNavigation', 'url' => '/core/navigation/apps', 'verb' => 'GET'],
63
+        ['name' => 'Navigation#getSettingsNavigation', 'url' => '/core/navigation/settings', 'verb' => 'GET'],
64
+        ['name' => 'Css#getCss', 'url' => '/css/{appName}/{fileName}', 'verb' => 'GET'],
65
+        ['name' => 'Js#getJs', 'url' => '/js/{appName}/{fileName}', 'verb' => 'GET'],
66
+        ['name' => 'contactsMenu#index', 'url' => '/contactsmenu/contacts', 'verb' => 'POST'],
67
+        ['name' => 'contactsMenu#findOne', 'url' => '/contactsmenu/findOne', 'verb' => 'POST'],
68
+        ['name' => 'AutoComplete#get', 'url' => 'autocomplete/get', 'verb' => 'GET'],
69
+        ['name' => 'WalledGarden#get', 'url' => '/204', 'verb' => 'GET'],
70
+    ],
71
+    'ocs' => [
72
+        ['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
73
+        ['root' => '', 'name' => 'OCS#getConfig', 'url' => '/config', 'verb' => 'GET'],
74
+        ['root' => '/person', 'name' => 'OCS#personCheck', 'url' => '/check', 'verb' => 'POST'],
75
+        ['root' => '/identityproof', 'name' => 'OCS#getIdentityProof', 'url' => '/key/{cloudId}', 'verb' => 'GET'],
76
+    ],
77 77
 ]);
78 78
 
79 79
 // Post installation check
@@ -82,15 +82,15 @@  discard block
 block discarded – undo
82 82
 // Core ajax actions
83 83
 // Search
84 84
 $this->create('search_ajax_search', '/core/search')
85
-	->actionInclude('core/search/ajax/search.php');
85
+    ->actionInclude('core/search/ajax/search.php');
86 86
 // Routing
87 87
 $this->create('core_ajax_update', '/core/ajax/update.php')
88
-	->actionInclude('core/ajax/update.php');
88
+    ->actionInclude('core/ajax/update.php');
89 89
 
90 90
 // File routes
91 91
 $this->create('files.viewcontroller.showFile', '/f/{fileid}')->action(function($urlParams) {
92
-	$app = new \OCA\Files\AppInfo\Application($urlParams);
93
-	$app->dispatch('ViewController', 'index');
92
+    $app = new \OCA\Files\AppInfo\Application($urlParams);
93
+    $app->dispatch('ViewController', 'index');
94 94
 });
95 95
 
96 96
 // Call routes
@@ -99,57 +99,57 @@  discard block
 block discarded – undo
99 99
  * @suppress PhanUndeclaredClassMethod
100 100
  */
101 101
 $this->create('spreed.pagecontroller.showCall', '/call/{token}')->action(function($urlParams) {
102
-	if (class_exists(\OCA\Spreed\AppInfo\Application::class, false)) {
103
-		$app = new \OCA\Spreed\AppInfo\Application($urlParams);
104
-		$app->dispatch('PageController', 'index');
105
-	} else {
106
-		throw new \OC\HintException('App spreed is not enabled');
107
-	}
102
+    if (class_exists(\OCA\Spreed\AppInfo\Application::class, false)) {
103
+        $app = new \OCA\Spreed\AppInfo\Application($urlParams);
104
+        $app->dispatch('PageController', 'index');
105
+    } else {
106
+        throw new \OC\HintException('App spreed is not enabled');
107
+    }
108 108
 });
109 109
 
110 110
 // Sharing routes
111 111
 $this->create('files_sharing.sharecontroller.showShare', '/s/{token}')->action(function($urlParams) {
112
-	if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
113
-		$app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
114
-		$app->dispatch('ShareController', 'showShare');
115
-	} else {
116
-		throw new \OC\HintException('App file sharing is not enabled');
117
-	}
112
+    if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
113
+        $app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
114
+        $app->dispatch('ShareController', 'showShare');
115
+    } else {
116
+        throw new \OC\HintException('App file sharing is not enabled');
117
+    }
118 118
 });
119 119
 $this->create('files_sharing.sharecontroller.authenticate', '/s/{token}/authenticate')->post()->action(function($urlParams) {
120
-	if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
121
-		$app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
122
-		$app->dispatch('ShareController', 'authenticate');
123
-	} else {
124
-		throw new \OC\HintException('App file sharing is not enabled');
125
-	}
120
+    if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
121
+        $app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
122
+        $app->dispatch('ShareController', 'authenticate');
123
+    } else {
124
+        throw new \OC\HintException('App file sharing is not enabled');
125
+    }
126 126
 });
127 127
 $this->create('files_sharing.sharecontroller.showAuthenticate', '/s/{token}/authenticate')->get()->action(function($urlParams) {
128
-	if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
129
-		$app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
130
-		$app->dispatch('ShareController', 'showAuthenticate');
131
-	} else {
132
-		throw new \OC\HintException('App file sharing is not enabled');
133
-	}
128
+    if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
129
+        $app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
130
+        $app->dispatch('ShareController', 'showAuthenticate');
131
+    } else {
132
+        throw new \OC\HintException('App file sharing is not enabled');
133
+    }
134 134
 });
135 135
 $this->create('files_sharing.sharecontroller.downloadShare', '/s/{token}/download')->get()->action(function($urlParams) {
136
-	if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
137
-		$app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
138
-		$app->dispatch('ShareController', 'downloadShare');
139
-	} else {
140
-		throw new \OC\HintException('App file sharing is not enabled');
141
-	}
136
+    if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
137
+        $app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
138
+        $app->dispatch('ShareController', 'downloadShare');
139
+    } else {
140
+        throw new \OC\HintException('App file sharing is not enabled');
141
+    }
142 142
 });
143 143
 $this->create('files_sharing.publicpreview.directLink', '/s/{token}/preview')->get()->action(function($urlParams) {
144
-	if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
145
-		$app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
146
-		$app->dispatch('PublicPreviewController', 'directLink');
147
-	} else {
148
-		throw new \OC\HintException('App file sharing is not enabled');
149
-	}
144
+    if (class_exists(\OCA\Files_Sharing\AppInfo\Application::class, false)) {
145
+        $app = new \OCA\Files_Sharing\AppInfo\Application($urlParams);
146
+        $app->dispatch('PublicPreviewController', 'directLink');
147
+    } else {
148
+        throw new \OC\HintException('App file sharing is not enabled');
149
+    }
150 150
 });
151 151
 
152 152
 // used for heartbeat
153 153
 $this->create('heartbeat', '/heartbeat')->action(function(){
154
-	// do nothing
154
+    // do nothing
155 155
 });
Please login to merge, or discard this patch.
core/Controller/NavigationController.php 1 patch
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -30,58 +30,58 @@
 block discarded – undo
30 30
 
31 31
 class NavigationController extends Controller {
32 32
 
33
-	/** @var INavigationManager */
34
-	private $navigationManager;
33
+    /** @var INavigationManager */
34
+    private $navigationManager;
35 35
 
36
-	/** @var IURLGenerator */
37
-	private $urlGenerator;
36
+    /** @var IURLGenerator */
37
+    private $urlGenerator;
38 38
 
39
-	public function __construct(string $appName, IRequest $request, INavigationManager $navigationManager, IURLGenerator $urlGenerator) {
40
-		parent::__construct($appName, $request);
41
-		$this->navigationManager = $navigationManager;
42
-		$this->urlGenerator = $urlGenerator;
43
-	}
39
+    public function __construct(string $appName, IRequest $request, INavigationManager $navigationManager, IURLGenerator $urlGenerator) {
40
+        parent::__construct($appName, $request);
41
+        $this->navigationManager = $navigationManager;
42
+        $this->urlGenerator = $urlGenerator;
43
+    }
44 44
 
45
-	/**
46
-	 * @NoAdminRequired
47
-	 * @NoCSRFRequired
48
-	 *
49
-	 * @param bool $absolute
50
-	 * @return JSONResponse
51
-	 */
52
-	public function getAppsNavigation(bool $absolute = false) {
53
-		$navigation = $this->navigationManager->getAll('link');
54
-		if ($absolute) {
55
-			$this->rewriteToAbsoluteUrls($navigation);
56
-		}
57
-		return new JSONResponse($navigation);
58
-	}
45
+    /**
46
+     * @NoAdminRequired
47
+     * @NoCSRFRequired
48
+     *
49
+     * @param bool $absolute
50
+     * @return JSONResponse
51
+     */
52
+    public function getAppsNavigation(bool $absolute = false) {
53
+        $navigation = $this->navigationManager->getAll('link');
54
+        if ($absolute) {
55
+            $this->rewriteToAbsoluteUrls($navigation);
56
+        }
57
+        return new JSONResponse($navigation);
58
+    }
59 59
 
60
-	/**
61
-	 * @NoAdminRequired
62
-	 * @NoCSRFRequired
63
-	 *
64
-	 * @param bool $absolute
65
-	 * @return JSONResponse
66
-	 */
67
-	public function getSettingsNavigation(bool $absolute = false) {
68
-		$navigation = $this->navigationManager->getAll('settings');
69
-		if ($absolute) {
70
-			$this->rewriteToAbsoluteUrls($navigation);
71
-		}
72
-		return new JSONResponse($navigation);
73
-	}
60
+    /**
61
+     * @NoAdminRequired
62
+     * @NoCSRFRequired
63
+     *
64
+     * @param bool $absolute
65
+     * @return JSONResponse
66
+     */
67
+    public function getSettingsNavigation(bool $absolute = false) {
68
+        $navigation = $this->navigationManager->getAll('settings');
69
+        if ($absolute) {
70
+            $this->rewriteToAbsoluteUrls($navigation);
71
+        }
72
+        return new JSONResponse($navigation);
73
+    }
74 74
 
75
-	/**
76
-	 * Rewrite href attribute of navigation entries to an absolute URL
77
-	 *
78
-	 * @param array $navigation
79
-	 */
80
-	private function rewriteToAbsoluteUrls(array &$navigation) {
81
-		foreach ($navigation as &$entry) {
82
-			if (substr($entry['href'], 0, strlen($this->urlGenerator->getBaseUrl())) !== $this->urlGenerator->getBaseUrl()) {
83
-				$entry['href'] = $this->urlGenerator->getAbsoluteURL($entry['href']);
84
-			}
85
-		}
86
-	}
75
+    /**
76
+     * Rewrite href attribute of navigation entries to an absolute URL
77
+     *
78
+     * @param array $navigation
79
+     */
80
+    private function rewriteToAbsoluteUrls(array &$navigation) {
81
+        foreach ($navigation as &$entry) {
82
+            if (substr($entry['href'], 0, strlen($this->urlGenerator->getBaseUrl())) !== $this->urlGenerator->getBaseUrl()) {
83
+                $entry['href'] = $this->urlGenerator->getAbsoluteURL($entry['href']);
84
+            }
85
+        }
86
+    }
87 87
 }
Please login to merge, or discard this patch.