Test Setup Failed
Push — developer ( 6d38be...55da17 )
by Radosław
18:02
created

Link   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 336
Duplicated Lines 0 %

Test Coverage

Coverage 12.14%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 58
eloc 167
dl 0
loc 336
ccs 17
cts 140
cp 0.1214
rs 4.5599
c 5
b 0
f 0

9 Methods

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

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
	// Ignore module while selection
22
	const IGNORE_MODULE = -1;
23
	/** @var int */
24
	public $tabid;
25
	/** @var int */
26
	public $linkid;
27
	/** @var string */
28
	public $linkclass;
29
	/** @var array */
30
	public $linkdata;
31
	/** @var string */
32
	public $linktype;
33
	/** @var string */
34
	public $linklabel;
35
	/** @var string */
36
	public $linkurl;
37
	/** @var string */
38
	public $linkicon;
39
	/** @var string */
40
	public $icon;
41 1
	/** @var int */
42
	public $sequence;
43 1
	/** @var bool */
44 1
	public $status = false;
45 1
	/** @var string */
46
	public $handler_path;
47 1
	/** @var string */
48
	public $handler_class;
49
	/** @var string */
50 1
	public $handler;
51
	/** @var array */
52
	public $params;
53
	/** @var string */
54
	public $dataUrl;
55
	/** @var string */
56
	public $linkhint;
57
	/** @var bool */
58
	public $active = true;
59
	/** @var string */
60
	public $relatedModuleName;
61
	/** @var string */
62
	public $modalView;
63
	/** @var bool|int|null */
64
	public $showLabel;
65
	/** @var bool */
66
	public $linkhref;
67
	/** @var string */
68
	public $style;
69
70
	/** Cache (Record) the schema changes to improve performance */
71
	public static $__cacheSchemaChanges = [];
72
73
	/** @var array Array for temporary data */
74
	protected array $values = [];
75
76
	/**
77
	 * Initialize this instance.
78
	 *
79
	 * @param array $valuemap
80
	 */
81
	public function initialize($valuemap)
82
	{
83
		foreach ($valuemap as $key => $value) {
84
			if (!empty($value) && ('linkurl' == $key || 'linkicon' == $key)) {
85
				$value = \App\Purifier::decodeHtml($value);
86
			}
87
			if (property_exists($this, $key)) {
88
				$this->{$key} = $value;
89
			} else {
90
				$this->values[$key] = $value;
91
			}
92
		}
93
	}
94
95
	/**
96
	 * Get module name.
97
	 */
98
	public function module()
99
	{
100
		if (!empty($this->tabid)) {
101
			return \App\Module::getModuleName($this->tabid);
102
		}
103
		return false;
104
	}
105
106
	/**
107
	 * Add link given module.
108
	 *
109
	 * @param int         $tabid       Module ID
110
	 * @param string      $type        Link Type (like DETAIL_VIEW_BASIC). Useful for grouping based on pages
111
	 * @param string      $label       Label to display
112
	 * @param string      $url         HREF value or URL to use for the link
113
	 * @param string      $iconpath    ICON to use on the display
114
	 * @param int         $sequence    Order or sequence of displaying the link
115
	 * @param array|null  $handlerInfo
116
	 * @param string|null $linkParams
117
	 */
118
	public static function addLink($tabid, $type, $label, $url, $iconpath = '', $sequence = 0, $handlerInfo = null, $linkParams = null)
119
	{
120
		$db = \App\Db::getInstance();
121
		if (0 != $tabid) {
122
			$exists = (new \App\Db\Query())->from('vtiger_links')
123
				->where(['tabid' => $tabid, 'linktype' => $type, 'linkurl' => $url, 'linkicon' => $iconpath, 'linklabel' => $label])
124
				->exists();
125
		}
126
		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...
127
			$params = [
128
				'tabid' => $tabid,
129
				'linktype' => $type,
130
				'linklabel' => $label,
131
				'linkurl' => $url,
132
				'linkicon' => $iconpath,
133
				'sequence' => (int) $sequence,
134
			];
135
			if (!empty($handlerInfo)) {
136
				$params['handler_path'] = $handlerInfo['path'] ?? null;
137
				$params['handler_class'] = $handlerInfo['class'] ?? null;
138
				$params['handler'] = $handlerInfo['method'] ?? null;
139
			}
140 1
			if (!empty($linkParams)) {
141
				$params['params'] = $linkParams;
142 1
			}
143 1
			$db->createCommand()->insert('vtiger_links', $params)->execute();
144 1
			\App\Log::trace("Adding Link ($type - $label) ... DONE");
145
			\App\Cache::delete('AllLinks', 'ByType');
146
		}
147
	}
148
149
	/**
150
	 * Delete link of the module.
151
	 *
152
	 * @param int    $tabid Module ID
153
	 * @param string $type  Link Type (like DETAIL_VIEW_BASIC). Useful for grouping based on pages
154
	 * @param string $label Display label
155
	 * @param string $url   URL of link to lookup while deleting
156
	 */
157
	public static function deleteLink($tabid, $type, $label, $url = false)
158
	{
159
		$db = \App\Db::getInstance();
160
		if ($url) {
161
			$db->createCommand()->delete('vtiger_links', [
162
				'tabid' => $tabid,
163
				'linktype' => $type,
164
				'linklabel' => $label,
165
				'linkurl' => $url,
166
			])->execute();
167
			\App\Log::trace("Deleting Link ($type - $label - $url) ... DONE");
168
		} else {
169
			$db->createCommand()->delete('vtiger_links', [
170
				'tabid' => $tabid,
171
				'linktype' => $type,
172
				'linklabel' => $label,
173
			])->execute();
174
			\App\Log::trace("Deleting Link ($type - $label) ... DONE");
175
		}
176
		\App\Cache::delete('AllLinks', 'ByType');
177
	}
178
179
	/**
180
	 * Delete all links related to module.
181
	 *
182
	 * @param int $tabid Module ID
183
	 */
184
	public static function deleteAll($tabid)
185
	{
186
		\App\Db::getInstance()->createCommand()->delete('vtiger_links', ['tabid' => $tabid])->execute();
187
		\App\Log::trace('Deleting Links ... DONE');
188
		\App\Cache::delete('AllLinks', 'ByType');
189
	}
190
191
	/**
192
	 * Get all the links related to module.
193
	 *
194
	 * @param int $tabid Module ID
195
	 */
196
	public static function getAll($tabid)
197
	{
198
		return self::getAllByType($tabid);
199
	}
200
201
	/**
202
	 * Get all the link related to module based on type.
203
	 *
204
	 * @param int   $tabid      Module ID
205
	 * @param mixed $type       String or List of types to select
206
	 * @param array $parameters Map Key-Value pair to use for formating the link url
207
	 */
208
	public static function getAllByType($tabid, $type = false, $parameters = false)
209
	{
210
		if (\App\Cache::has('AllLinks', 'ByType')) {
211
			$rows = \App\Cache::get('AllLinks', 'ByType');
212
		} else {
213
			$linksFromDb = (new \App\Db\Query())->from('vtiger_links')->all();
214
			$rows = [];
215
			foreach ($linksFromDb as $row) {
216
				$rows[$row['tabid']][$row['linktype']][] = $row;
217
			}
218
			\App\Cache::save('AllLinks', 'ByType', $rows);
219
		}
220
221
		$multitype = false;
222
		$links = [];
223
		if (false !== $type) {
224
			if (\is_array($type)) {
225
				$multitype = true;
226
				if (self::IGNORE_MODULE === $tabid) {
227
					$permittedTabIdList = \App\User::getCurrentUserId() ? \vtlib\Deprecated::getPermittedModuleIdList() : [];
228
					$permittedTabIdList[] = 0;  // Added to support one link for all modules
229
					foreach ($permittedTabIdList as $moduleId) {
230
						foreach ($type as $typ) {
231
							if (isset($rows[$moduleId][$typ])) {
232
								foreach ($rows[$moduleId][$typ] as $data) {
233
									$links[] = $data;
234
								}
235
							}
236
						}
237
					}
238
				} else {
239
					foreach ($type as $typeLink) {
240
						if (isset($rows[0][$typeLink])) {
241
							foreach ($rows[0][$typeLink] as $data) {
242
								$links[] = $data;
243
							}
244
						}
245
						if (isset($rows[$tabid][$typeLink])) {
246
							foreach ($rows[$tabid][$typeLink] as $data) {
247
								$links[] = $data;
248
							}
249
						}
250
					}
251
				}
252
			} else {
253
				if (self::IGNORE_MODULE === $tabid) {
254
					foreach ($rows as $row) {
255
						if (isset($row[$type])) {
256
							foreach ($row[$type] as $data) {
257
								$links[] = $data;
258
							}
259
						}
260
					}
261
				} else {
262
					if (isset($rows[0][$type])) {
263
						foreach ($rows[0][$type] as $data) {
264
							$links[] = $data;
265
						}
266
					}
267
					if (isset($rows[$tabid][$type])) {
268
						foreach ($rows[$tabid][$type] as $data) {
269
							$links[] = $data;
270
						}
271
					}
272
				}
273
			}
274
		} else {
275
			foreach ($rows[$tabid] as $linkType) {
276
				foreach ($linkType as $data) {
277
					$links[] = $data;
278
				}
279
			}
280
		}
281 1
282
		$strtemplate = new \Vtiger_StringTemplate();
283 1
		if ($parameters) {
284 1
			foreach ($parameters as $key => $value) {
285 1
				$strtemplate->assign($key, $value);
286 1
			}
287 1
		}
288
289
		$instances = [];
290
		if ($multitype) {
291
			foreach ($type as $t) {
292 1
				$instances[$t] = [];
293
			}
294
		}
295
		foreach ($links as $row) {
296
			$instance = new self();
297
			$instance->initialize($row);
298
			if (!empty($row['handler_path']) && \vtlib\Deprecated::isFileAccessible($row['handler_path'])) {
299
				\vtlib\Deprecated::checkFileAccessForInclusion($row['handler_path']);
300
				require_once $row['handler_path'];
301
				$linkData = new LinkData($instance);
302
				$ignore = \call_user_func([$row['handler_class'], $row['handler']], $linkData);
303
				if (!$ignore) {
304
					\App\Log::trace('Ignoring Link ... ' . var_export($row, true));
305
					continue;
306
				}
307
			}
308
			if ($parameters) {
309
				$instance->linkurl = $strtemplate->merge($instance->linkurl);
310
				$instance->linkicon = $strtemplate->merge($instance->linkicon);
311
			}
312
			if ($multitype) {
313
				$instances[$instance->linktype][] = $instance;
314
			} else {
315
				$instances[$instance->linktype] = $instance;
316
			}
317
		}
318
		return $instances;
319
	}
320
321
	/**
322
	 * Extract the links of module for export.
323
	 *
324
	 * @param mixed $tabid
325
	 */
326
	public static function getAllForExport($tabid)
327
	{
328
		$dataReader = (new \App\Db\Query())->from('vtiger_links')
329
			->where(['tabid' => $tabid])
330
			->createCommand()->query();
331
		$links = [];
332
		while ($row = $dataReader->read()) {
333
			$instance = new self();
334
			$instance->initialize($row);
335
			$links[] = $instance;
336
		}
337
		return $links;
338
	}
339
340
	/**
341
	 * Link data.
342
	 *
343
	 * @param int $linkId
344
	 *
345
	 * @return array
346
	 */
347
	public static function getLinkData($linkId)
348
	{
349
		if (\App\Cache::has('Link', $linkId)) {
350
			return \App\Cache::get('Link', $linkId);
351
		}
352
		$linkData = (new \App\Db\Query())->from('vtiger_links')->where(['linkid' => $linkId])->one();
353
		\App\Cache::save('Link', $linkId, $linkData);
354
		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...
355
	}
356
}
357