Completed
Push — master ( 96d4e1...12c5c3 )
by Morris
31:41 queued 21:00
created

NavigationManager::init()   D

Complexity

Conditions 23
Paths 73

Size

Total Lines 128
Code Lines 88

Duplication

Lines 43
Ratio 33.59 %

Importance

Changes 0
Metric Value
cc 23
eloc 88
nc 73
nop 0
dl 43
loc 128
rs 4.6303
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud GmbH
4
 *
5
 * @author Bart Visscher <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Robin McCorkell <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 *
11
 * @license AGPL-3.0
12
 *
13
 * This code is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License, version 3,
15
 * as published by the Free Software Foundation.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License, version 3,
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
24
 *
25
 */
26
27
namespace OC;
28
29
use OC\App\AppManager;
30
use OC\Group\Manager;
31
use OCP\App\IAppManager;
32
use OCP\IConfig;
33
use OCP\IGroupManager;
34
use OCP\INavigationManager;
35
use OCP\IURLGenerator;
36
use OCP\IUserSession;
37
use OCP\L10N\IFactory;
38
39
/**
40
 * Manages the ownCloud navigation
41
 */
42
43
class NavigationManager implements INavigationManager {
44
	protected $entries = [];
45
	protected $closureEntries = [];
46
	protected $activeEntry;
47
	/** @var bool */
48
	protected $init = false;
49
	/** @var IAppManager|AppManager */
50
	protected $appManager;
51
	/** @var IURLGenerator */
52
	private $urlGenerator;
53
	/** @var IFactory */
54
	private $l10nFac;
55
	/** @var IUserSession */
56
	private $userSession;
57
	/** @var IGroupManager|Manager */
58
	private $groupManager;
59
	/** @var IConfig */
60
	private $config;
61
62 View Code Duplication
	public function __construct(IAppManager $appManager,
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
63
						 IURLGenerator $urlGenerator,
64
						 IFactory $l10nFac,
65
						 IUserSession $userSession,
66
						 IGroupManager $groupManager,
67
						 IConfig $config) {
68
		$this->appManager = $appManager;
69
		$this->urlGenerator = $urlGenerator;
70
		$this->l10nFac = $l10nFac;
71
		$this->userSession = $userSession;
72
		$this->groupManager = $groupManager;
73
		$this->config = $config;
74
	}
75
76
	/**
77
	 * Creates a new navigation entry
78
	 *
79
	 * @param array|\Closure $entry Array containing: id, name, order, icon and href key
80
	 *					The use of a closure is preferred, because it will avoid
81
	 * 					loading the routing of your app, unless required.
82
	 * @return void
83
	 */
84
	public function add($entry) {
85
		if ($entry instanceof \Closure) {
86
			$this->closureEntries[] = $entry;
87
			return;
88
		}
89
90
		$entry['active'] = false;
91
		if(!isset($entry['icon'])) {
92
			$entry['icon'] = '';
93
		}
94
		if(!isset($entry['type'])) {
95
			$entry['type'] = 'link';
96
		}
97
		$this->entries[] = $entry;
98
	}
99
100
	/**
101
	 * returns all the added Menu entries
102
	 * @param string $type
103
	 * @return array an array of the added entries
104
	 */
105
	public function getAll($type = 'link') {
106
		$this->init();
107
		foreach ($this->closureEntries as $c) {
108
			$this->add($c());
109
		}
110
		$this->closureEntries = array();
111
112
		if ($type === 'all') {
113
			return $this->entries;
114
		}
115
116
		return array_filter($this->entries, function($entry) use ($type) {
117
			return $entry['type'] === $type;
118
		});
119
	}
120
121
	/**
122
	 * removes all the entries
123
	 */
124
	public function clear($loadDefaultLinks = true) {
125
		$this->entries = [];
126
		$this->closureEntries = [];
127
		$this->init = !$loadDefaultLinks;
128
	}
129
130
	/**
131
	 * Sets the current navigation entry of the currently running app
132
	 * @param string $id of the app entry to activate (from added $entry)
133
	 */
134
	public function setActiveEntry($id) {
135
		$this->activeEntry = $id;
136
	}
137
138
	/**
139
	 * gets the active Menu entry
140
	 * @return string id or empty string
141
	 *
142
	 * This function returns the id of the active navigation entry (set by
143
	 * setActiveEntry
144
	 */
145
	public function getActiveEntry() {
146
		return $this->activeEntry;
147
	}
148
149
	private function init() {
150
		if ($this->init) {
151
			return;
152
		}
153
		$this->init = true;
154
155
		$l = $this->l10nFac->get('lib');
156 View Code Duplication
		if ($this->config->getSystemValue('knowledgebaseenabled', true)) {
157
			$this->add([
158
				'type' => 'settings',
159
				'id' => 'help',
160
				'order' => 5,
161
				'href' => $this->urlGenerator->linkToRoute('settings_help'),
162
				'name' => $l->t('Help'),
163
				'icon' => $this->urlGenerator->imagePath('settings', 'help.svg'),
164
			]);
165
		}
166
167
		if ($this->userSession->isLoggedIn()) {
168 View Code Duplication
			if ($this->isAdmin()) {
169
				// App management
170
				$this->add([
171
					'type' => 'settings',
172
					'id' => 'core_apps',
173
					'order' => 3,
174
					'href' => $this->urlGenerator->linkToRoute('settings.AppSettings.viewApps'),
175
					'icon' => $this->urlGenerator->imagePath('settings', 'apps.svg'),
176
					'name' => $l->t('Apps'),
177
				]);
178
			}
179
180
			// Personal settings
181
			$this->add([
182
				'type' => 'settings',
183
				'id' => 'personal',
184
				'order' => 1,
185
				'href' => $this->urlGenerator->linkToRoute('settings_personal'),
186
				'name' => $l->t('Personal'),
187
				'icon' => $this->urlGenerator->imagePath('settings', 'personal.svg'),
188
			]);
189
190
			// Logout
191
			$this->add([
192
				'type' => 'settings',
193
				'id' => 'logout',
194
				'order' => 99999,
195
				'href' => $this->urlGenerator->linkToRouteAbsolute(
196
					'core.login.logout',
197
					['requesttoken' => \OCP\Util::callRegister()]
198
				),
199
				'name' => $l->t('Log out'),
200
				'icon' => $this->urlGenerator->imagePath('core', 'actions/logout.svg'),
201
			]);
202
203 View Code Duplication
			if ($this->isSubadmin()) {
204
				// User management
205
				$this->add([
206
					'type' => 'settings',
207
					'id' => 'core_users',
208
					'order' => 4,
209
					'href' => $this->urlGenerator->linkToRoute('settings_users'),
210
					'name' => $l->t('Users'),
211
					'icon' => $this->urlGenerator->imagePath('settings', 'users.svg'),
212
				]);
213
			}
214
215 View Code Duplication
			if ($this->isAdmin()) {
216
				// Admin settings
217
				$this->add([
218
					'type' => 'settings',
219
					'id' => 'admin',
220
					'order' => 2,
221
					'href' => $this->urlGenerator->linkToRoute('settings.AdminSettings.index'),
222
					'name' => $l->t('Admin'),
223
					'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
224
				]);
225
			}
226
		}
227
228
		if ($this->appManager === 'null') {
229
			return;
230
		}
231
		foreach ($this->appManager->getInstalledApps() as $app) {
232
			// load plugins and collections from info.xml
233
			$info = $this->appManager->getAppInfo($app);
234
			if (empty($info['navigations'])) {
235
				continue;
236
			}
237
			foreach ($info['navigations'] as $nav) {
238
				if (!isset($nav['name'])) {
239
					continue;
240
				}
241
				if (!isset($nav['route'])) {
242
					continue;
243
				}
244
				$role = isset($nav['@attributes']['role']) ? $nav['@attributes']['role'] : 'all';
245
				if ($role === 'admin' && !$this->isAdmin()) {
246
					continue;
247
				}
248
				$l = $this->l10nFac->get($app);
249
				$id = isset($nav['id']) ? $nav['id'] : $app;
250
				$order = isset($nav['order']) ? $nav['order'] : 100;
251
				$type = isset($nav['type']) ? $nav['type'] : 'link';
252
				$route = $this->urlGenerator->linkToRoute($nav['route']);
253
				$icon = isset($nav['icon']) ? $nav['icon'] : 'app.svg';
254
				foreach ([$icon, "$app.svg"] as $i) {
255
					try {
256
						$icon = $this->urlGenerator->imagePath($app, $i);
257
						break;
258
					} catch (\RuntimeException $ex) {
259
						// no icon? - ignore it then
260
					}
261
				}
262
				if ($icon === null) {
263
					$icon = $this->urlGenerator->imagePath('core', 'default-app-icon');
264
				}
265
266
				$this->add([
267
					'id' => $id,
268
					'order' => $order,
269
					'href' => $route,
270
					'icon' => $icon,
271
					'type' => $type,
272
					'name' => $l->t($nav['name']),
273
				]);
274
			}
275
		}
276
	}
277
278 View Code Duplication
	private function isAdmin() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
279
		$user = $this->userSession->getUser();
280
		if ($user !== null) {
281
			return $this->groupManager->isAdmin($user->getUID());
282
		}
283
		return false;
284
	}
285
286
	private function isSubadmin() {
287
		$user = $this->userSession->getUser();
288
		if ($user !== null) {
289
			return $this->groupManager->getSubAdmin()->isSubAdmin($user);
0 ignored issues
show
Bug introduced by
The method getSubAdmin does only exist in OC\Group\Manager, but not in OCP\IGroupManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
290
		}
291
		return false;
292
	}
293
}
294