Passed
Push — developer ( 6b5868...bed0f9 )
by Radosław
22:42 queued 03:39
created

Link   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 298
Duplicated Lines 0 %

Test Coverage

Coverage 12.14%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 57
eloc 154
c 5
b 0
f 0
dl 0
loc 298
ccs 17
cts 140
cp 0.1214
rs 5.04

9 Methods

Rating   Name   Duplication   Size   Complexity  
A module() 0 6 2
A getAll() 0 3 1
A deleteAll() 0 5 1
A deleteLink() 0 20 2
B addLink() 0 28 6
A getAllForExport() 0 12 2
F getAllByType() 0 111 36
A getLinkData() 0 8 2
A initialize() 0 7 5

How to fix   Complexity   

Complex Class

Complex classes like Link often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Link, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* +**********************************************************************************
3
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
4
 * ("License"); You may not use this file except in compliance with the License
5
 * The Original Code is:  vtiger CRM Open Source
6
 * The Initial Developer of the Original Code is vtiger.
7
 * Portions created by vtiger are Copyright (C) vtiger.
8
 * All Rights Reserved.
9
 * Contributor(s): YetiForce S.A.
10
 * ********************************************************************************** */
11
12
namespace vtlib;
13
14
include_once 'vtlib/Vtiger/Utils/StringTemplate.php';
15
16
/**
17
 * Provides API to handle custom links.
18
 */
19
class Link
20
{
21
	public $tabid;
22
	public $linkid;
23
	public $linktype;
24
	public $linklabel;
25
	public $linkurl;
26
	public $linkicon;
27
	public $icon;
28
	public $sequence;
29
	public $status = false;
30
	public $handler_path;
31
	public $handler_class;
32
	public $handler;
33
	public $params;
34
35
	// Ignore module while selection
36
	const IGNORE_MODULE = -1;
37
38
	/**
39
	 * Initialize this instance.
40
	 *
41 1
	 * @param array $valuemap
42
	 */
43 1
	public function initialize($valuemap)
44 1
	{
45 1
		foreach ($valuemap as $key => $value) {
46
			if (!empty($value) && ('linkurl' == $key || 'linkicon' == $key)) {
47 1
				$this->{$key} = \App\Purifier::decodeHtml($value);
48
			} else {
49
				$this->{$key} = $value;
50 1
			}
51
		}
52
	}
53
54
	/**
55
	 * Get module name.
56
	 */
57
	public function module()
58
	{
59
		if (!empty($this->tabid)) {
60
			return \App\Module::getModuleName($this->tabid);
61
		}
62
		return false;
63
	}
64
65
	/** Cache (Record) the schema changes to improve performance */
66
	public static $__cacheSchemaChanges = [];
67
68
	/**
69
	 * Add link given module.
70
	 *
71
	 * @param int         $tabid       Module ID
72
	 * @param string      $type        Link Type (like DETAIL_VIEW_BASIC). Useful for grouping based on pages
73
	 * @param string      $label       Label to display
74
	 * @param string      $url         HREF value or URL to use for the link
75
	 * @param string      $iconpath    ICON to use on the display
76
	 * @param int         $sequence    Order or sequence of displaying the link
77
	 * @param array|null  $handlerInfo
78
	 * @param string|null $linkParams
79
	 */
80
	public static function addLink($tabid, $type, $label, $url, $iconpath = '', $sequence = 0, $handlerInfo = null, $linkParams = null)
81
	{
82
		$db = \App\Db::getInstance();
83
		if (0 != $tabid) {
84
			$exists = (new \App\Db\Query())->from('vtiger_links')
85
				->where(['tabid' => $tabid, 'linktype' => $type, 'linkurl' => $url, 'linkicon' => $iconpath, 'linklabel' => $label])
86
				->exists();
87
		}
88
		if (0 == $tabid || !$exists) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $exists does not seem to be defined for all execution paths leading up to this point.
Loading history...
89
			$params = [
90
				'tabid' => $tabid,
91
				'linktype' => $type,
92
				'linklabel' => $label,
93
				'linkurl' => $url,
94
				'linkicon' => $iconpath,
95
				'sequence' => (int) $sequence,
96
			];
97
			if (!empty($handlerInfo)) {
98
				$params['handler_path'] = $handlerInfo['path'] ?? null;
99
				$params['handler_class'] = $handlerInfo['class'] ?? null;
100
				$params['handler'] = $handlerInfo['method'] ?? null;
101
			}
102
			if (!empty($linkParams)) {
103
				$params['params'] = $linkParams;
104
			}
105
			$db->createCommand()->insert('vtiger_links', $params)->execute();
106
			\App\Log::trace("Adding Link ($type - $label) ... DONE");
107
			\App\Cache::delete('AllLinks', 'ByType');
108
		}
109
	}
110
111
	/**
112
	 * Delete link of the module.
113
	 *
114
	 * @param int    $tabid Module ID
115
	 * @param string $type  Link Type (like DETAIL_VIEW_BASIC). Useful for grouping based on pages
116
	 * @param string $label Display label
117
	 * @param string $url   URL of link to lookup while deleting
118
	 */
119
	public static function deleteLink($tabid, $type, $label, $url = false)
120
	{
121
		$db = \App\Db::getInstance();
122
		if ($url) {
123
			$db->createCommand()->delete('vtiger_links', [
124
				'tabid' => $tabid,
125
				'linktype' => $type,
126
				'linklabel' => $label,
127
				'linkurl' => $url,
128
			])->execute();
129
			\App\Log::trace("Deleting Link ($type - $label - $url) ... DONE");
130
		} else {
131
			$db->createCommand()->delete('vtiger_links', [
132
				'tabid' => $tabid,
133
				'linktype' => $type,
134
				'linklabel' => $label,
135
			])->execute();
136
			\App\Log::trace("Deleting Link ($type - $label) ... DONE");
137
		}
138
		\App\Cache::delete('AllLinks', 'ByType');
139
	}
140 1
141
	/**
142 1
	 * Delete all links related to module.
143 1
	 *
144 1
	 * @param int $tabid Module ID
145
	 */
146
	public static function deleteAll($tabid)
147
	{
148
		\App\Db::getInstance()->createCommand()->delete('vtiger_links', ['tabid' => $tabid])->execute();
149
		\App\Log::trace('Deleting Links ... DONE');
150
		\App\Cache::delete('AllLinks', 'ByType');
151
	}
152
153
	/**
154
	 * Get all the links related to module.
155
	 *
156
	 * @param int $tabid Module ID
157
	 */
158
	public static function getAll($tabid)
159
	{
160
		return self::getAllByType($tabid);
161
	}
162
163
	/**
164
	 * Get all the link related to module based on type.
165
	 *
166
	 * @param int   $tabid      Module ID
167
	 * @param mixed $type       String or List of types to select
168
	 * @param array $parameters Map Key-Value pair to use for formating the link url
169
	 */
170
	public static function getAllByType($tabid, $type = false, $parameters = false)
171
	{
172
		if (\App\Cache::has('AllLinks', 'ByType')) {
173
			$rows = \App\Cache::get('AllLinks', 'ByType');
174
		} else {
175
			$linksFromDb = (new \App\Db\Query())->from('vtiger_links')->all();
176
			$rows = [];
177
			foreach ($linksFromDb as $row) {
178
				$rows[$row['tabid']][$row['linktype']][] = $row;
179
			}
180
			\App\Cache::save('AllLinks', 'ByType', $rows);
181
		}
182
183
		$multitype = false;
184
		$links = [];
185
		if (false !== $type) {
186
			if (\is_array($type)) {
187
				$multitype = true;
188
				if (self::IGNORE_MODULE === $tabid) {
189
					$permittedTabIdList = \App\User::getCurrentUserId() ? \vtlib\Deprecated::getPermittedModuleIdList() : [];
190
					$permittedTabIdList[] = 0;  // Added to support one link for all modules
191
					foreach ($permittedTabIdList as $moduleId) {
192
						foreach ($type as $typ) {
193
							if (isset($rows[$moduleId][$typ])) {
194
								foreach ($rows[$moduleId][$typ] as $data) {
195
									$links[] = $data;
196
								}
197
							}
198
						}
199
					}
200
				} else {
201
					foreach ($type as $typeLink) {
202
						if (isset($rows[0][$typeLink])) {
203
							foreach ($rows[0][$typeLink] as $data) {
204
								$links[] = $data;
205
							}
206
						}
207
						if (isset($rows[$tabid][$typeLink])) {
208
							foreach ($rows[$tabid][$typeLink] as $data) {
209
								$links[] = $data;
210
							}
211
						}
212
					}
213
				}
214
			} else {
215
				if (self::IGNORE_MODULE === $tabid) {
216
					foreach ($rows as $row) {
217
						if (isset($row[$type])) {
218
							foreach ($row[$type] as $data) {
219
								$links[] = $data;
220
							}
221
						}
222
					}
223
				} else {
224
					if (isset($rows[0][$type])) {
225
						foreach ($rows[0][$type] as $data) {
226
							$links[] = $data;
227
						}
228
					}
229
					if (isset($rows[$tabid][$type])) {
230
						foreach ($rows[$tabid][$type] as $data) {
231
							$links[] = $data;
232
						}
233
					}
234
				}
235
			}
236
		} else {
237
			foreach ($rows[$tabid] as $linkType) {
238
				foreach ($linkType as $data) {
239
					$links[] = $data;
240
				}
241
			}
242
		}
243
244
		$strtemplate = new \Vtiger_StringTemplate();
245
		if ($parameters) {
246
			foreach ($parameters as $key => $value) {
247
				$strtemplate->assign($key, $value);
248
			}
249
		}
250
251
		$instances = [];
252
		if ($multitype) {
253
			foreach ($type as $t) {
254
				$instances[$t] = [];
255
			}
256
		}
257
		foreach ($links as $row) {
258
			$instance = new self();
259
			$instance->initialize($row);
260
			if (!empty($row['handler_path']) && \vtlib\Deprecated::isFileAccessible($row['handler_path'])) {
261
				\vtlib\Deprecated::checkFileAccessForInclusion($row['handler_path']);
262
				require_once $row['handler_path'];
263
				$linkData = new LinkData($instance);
264
				$ignore = \call_user_func([$row['handler_class'], $row['handler']], $linkData);
265
				if (!$ignore) {
266
					\App\Log::trace('Ignoring Link ... ' . var_export($row, true));
267
					continue;
268
				}
269
			}
270
			if ($parameters) {
271
				$instance->linkurl = $strtemplate->merge($instance->linkurl);
272
				$instance->linkicon = $strtemplate->merge($instance->linkicon);
273
			}
274
			if ($multitype) {
275
				$instances[$instance->linktype][] = $instance;
276
			} else {
277
				$instances[$instance->linktype] = $instance;
278
			}
279
		}
280
		return $instances;
281 1
	}
282
283 1
	/**
284 1
	 * Extract the links of module for export.
285 1
	 *
286 1
	 * @param mixed $tabid
287 1
	 */
288
	public static function getAllForExport($tabid)
289
	{
290
		$dataReader = (new \App\Db\Query())->from('vtiger_links')
291
			->where(['tabid' => $tabid])
292 1
			->createCommand()->query();
293
		$links = [];
294
		while ($row = $dataReader->read()) {
295
			$instance = new self();
296
			$instance->initialize($row);
297
			$links[] = $instance;
298
		}
299
		return $links;
300
	}
301
302
	/**
303
	 * Link data.
304
	 *
305
	 * @param int $linkId
306
	 *
307
	 * @return array
308
	 */
309
	public static function getLinkData($linkId)
310
	{
311
		if (\App\Cache::has('Link', $linkId)) {
312
			return \App\Cache::get('Link', $linkId);
313
		}
314
		$linkData = (new \App\Db\Query())->from('vtiger_links')->where(['linkid' => $linkId])->one();
315
		\App\Cache::save('Link', $linkId, $linkData);
316
		return $linkData;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $linkData could also return false which is incompatible with the documented return type array. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
317
	}
318
}
319