Passed
Push — developer ( da84bd...1c16bf )
by Radosław
16:05 queued 01:18
created

Picklist::getValuesName()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 16
ccs 12
cts 12
cp 1
rs 9.8666
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
namespace App\Fields;
4
5
/**
6
 * Picklist class.
7
 *
8
 * @package App
9
 *
10
 * @copyright YetiForce S.A.
11
 * @license   YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com)
12
 * @author    Radosław Skrzypczak <[email protected]>
13
 * @author    Mariusz Krzaczkowski <[email protected]>
14
 */
15
class Picklist
16
{
17
	/**
18
	 * Function to get role based picklist values.
19
	 *
20
	 * @param string $fieldName
21
	 * @param string $roleId
22
	 *
23 3
	 * @return array list of role based picklist values
24
	 */
25 3
	public static function getRoleBasedValues(string $fieldName, string $roleId)
26 1
	{
27
		if (\App\Cache::has('Picklist::getRoleBasedValues', $fieldName)) {
28 3
			$allValues = \App\Cache::get('Picklist::getRoleBasedValues', $fieldName);
29 3
		} else {
30 3
			$allValues = (new \App\Db\Query())->select([$fieldName, 'roleid'])
31 3
				->from("vtiger_$fieldName")
32 3
				->innerJoin('vtiger_role2picklist', "vtiger_role2picklist.picklistvalueid = vtiger_$fieldName.picklist_valueid")
33 3
				->innerJoin('vtiger_picklist', 'vtiger_picklist.picklistid = vtiger_role2picklist.picklistid')
34 3
				->orderBy("vtiger_{$fieldName}.sortorderid")
35
				->all();
36 3
			\App\Cache::save('Picklist::getRoleBasedValues', $fieldName, $allValues);
37 3
		}
38 1
		$fldVal = [];
39 1
		foreach ($allValues as $row) {
40
			if ($row['roleid'] === $roleId) {
41
				$fldVal[] = \App\Purifier::decodeHtml($row[$fieldName]);
42
			}
43 3
		}
44
		return $fldVal;
45
	}
46
47
	/**
48
	 * Function which will give the picklist values for a field.
49
	 *
50
	 * @param string $fieldName -- string
51
	 *
52
	 * @return array -- array of values
53 6
	 */
54
	public static function getValuesName($fieldName)
55 6
	{
56 1
		if (\App\Cache::has('Picklist::getValuesName', $fieldName)) {
57
			return \App\Cache::get('Picklist::getValuesName', $fieldName);
58 6
		}
59 6
		$primaryKey = static::getPickListId($fieldName);
60 6
		$dataReader = (new \App\Db\Query())->select([$primaryKey, $fieldName])
61 6
			->from("vtiger_$fieldName")
62 6
			->orderBy('sortorderid')
63 6
			->createCommand()->query();
64 6
		$values = [];
65 5
		while ($row = $dataReader->read()) {
66
			$values[$row[$primaryKey]] = \App\Purifier::decodeHtml(\App\Purifier::decodeHtml($row[$fieldName]));
67 6
		}
68 6
		\App\Cache::save('Picklist::getValuesName', $fieldName, $values);
69
		return $values;
70
	}
71
72
	/**
73
	 * Check if the value exists in the picklist.
74
	 *
75
	 * @param string $fieldName
76
	 * @param string $value
77
	 *
78
	 * @return bool
79 1
	 */
80
	public static function isExists(string $fieldName, string $value): bool
81 1
	{
82
		return \in_array($value, static::getValuesName($fieldName));
83
	}
84
85
	/**
86
	 * Check if picklist exist.
87
	 *
88
	 * @param string $fieldName
89
	 *
90
	 * @return bool
91
	 */
92
	public static function isPicklistExist(string $fieldName): bool
93
	{
94
		return \App\Db::getInstance()->isTableExists("vtiger_{$fieldName}");
95
	}
96
97
	/**
98
	 * Function which will give the editable picklist values for a field.
99
	 *
100
	 * @param string $fieldName -- string
101
	 *
102
	 * @return array -- array of values
103
	 */
104
	public static function getEditableValues($fieldName)
105
	{
106
		$values = static::getValuesName($fieldName);
107
		$nonEditableValues = static::getNonEditableValues($fieldName);
108
		foreach ($values as $key => &$value) {
109
			if ('--None--' === $value || isset($nonEditableValues[$key])) {
110
				unset($values[$key]);
111
			}
112
		}
113
		return $values;
114
	}
115
116
	/**
117
	 * Function which will give the non editable picklist values for a field.
118
	 *
119
	 * @param string $fieldName -- string
120
	 *
121
	 * @return array -- array of values
122
	 */
123
	public static function getNonEditableValues($fieldName)
124
	{
125
		if (\App\Cache::has('Picklist::getNonEditableValues', $fieldName)) {
126
			return \App\Cache::get('Picklist::getNonEditableValues', $fieldName);
127
		}
128
		$primaryKey = static::getPickListId($fieldName);
129
		$dataReader = (new \App\Db\Query())->select([$primaryKey, $fieldName])
130
			->from("vtiger_$fieldName")
131
			->where(['presence' => 0])
132
			->createCommand()->query();
133
		$values = [];
134
		while ($row = $dataReader->read()) {
135
			$values[$row[$primaryKey]] = \App\Purifier::decodeHtml(\App\Purifier::decodeHtml($row[$fieldName]));
136 9
		}
137
		\App\Cache::save('Picklist::getNonEditableValues', $fieldName, $values);
138
139 9
		return $values;
140
	}
141
142
	/**
143
	 * Function to get picklist key for a picklist.
144
	 *
145
	 * @param string $fieldName
146
	 *
147
	 * @return string
148
	 */
149
	public static function getPickListId($fieldName)
150
	{
151
		$pickListIds = [
152 9
			'opportunity_type' => 'opptypeid',
153 3
			'sales_stage' => 'sales_stage_id',
154
			'rating' => 'rating_id',
155 9
			'ticketpriorities' => 'ticketpriorities_id',
156
			'ticketseverities' => 'ticketseverities_id',
157
			'ticketstatus' => 'ticketstatus_id',
158
			'salutationtype' => 'salutationtypeid',
159
			'faqstatus' => 'faqstatus_id',
160
			'recurring_frequency' => 'recurring_frequency_id',
161
			'payment_duration' => 'payment_duration_id',
162
			'language' => 'id',
163 2
			'duration_minutes' => 'minutesid',
164
		];
165 2
		if (isset($pickListIds[$fieldName])) {
166 2
			return $pickListIds[$fieldName];
167 2
		}
168
		return $fieldName . 'id';
169
	}
170
171
	/**
172
	 * Function to get modules which has picklist values.
173
	 *
174
	 * @return array
175
	 */
176
	public static function getModules()
177
	{
178
		return (new \App\Db\Query())->select(['vtiger_tab.tabid', 'vtiger_tab.tablabel', 'tabname' => 'vtiger_tab.name'])->from('vtiger_field')
179
			->innerJoin('vtiger_tab', 'vtiger_field.tabid = vtiger_tab.tabid')->where(['uitype' => [15, 16, 33, 115], 'vtiger_field.presence' => [0, 2], 'vtiger_tab.presence' => 0])
180
			->distinct('vtiger_tab.tabid')->orderBy(['vtiger_tab.tabid' => SORT_ASC])->createCommand()->queryAllByGroup(1);
0 ignored issues
show
Bug introduced by
'vtiger_tab.tabid' of type string is incompatible with the type boolean expected by parameter $value of yii\db\Query::distinct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

180
			->distinct(/** @scrutinizer ignore-type */ 'vtiger_tab.tabid')->orderBy(['vtiger_tab.tabid' => SORT_ASC])->createCommand()->queryAllByGroup(1);
Loading history...
181
	}
182
183
	/**
184
	 * Get modules with field names which are picklists.
185
	 *
186
	 * @param string $moduleName if you want only one module picklist fieldnames
187
	 *
188
	 * @return array associative array [$moduleName=>[...$fieldNames]]
189
	 */
190
	public static function getModulesByName(string $moduleName = '')
191
	{
192
		if (\App\Cache::has('Picklist::getPicklistModulesByName', $moduleName)) {
193
			return \App\Cache::get('Picklist::getPicklistModulesByName', $moduleName);
194
		}
195
		$query = (new \App\Db\Query())->select(['vtiger_tab.name', 'vtiger_field.fieldname'])
196
			->from('vtiger_field')
197
			->innerJoin('vtiger_tab', 'vtiger_field.tabid = vtiger_tab.tabid')
198
			->where(['uitype' => [15, 16, 33, 115]]);
199
		if ($moduleName) {
200
			$modules = $query->andWhere(['vtiger_tab.name' => $moduleName])->createCommand()->queryAllByGroup(2);
201
			$result = $modules[$moduleName] ?? [];
202
		} else {
203
			$result = $query->orderBy(['vtiger_tab.tabid' => SORT_ASC])->createCommand()->queryAllByGroup(2);
204
		}
205
		\App\Cache::save('Picklist::getPicklistModulesByName', $moduleName, $result);
206
		return $result;
207
	}
208
209
	/**
210
	 * Function to get picklist dependency data source.
211
	 *
212
	 * @param string $module
213
	 *
214
	 * @return array
215
	 */
216
	public static function getPicklistDependencyDatasource($module)
217
	{
218
		if (\App\Cache::has('getPicklistDependencyDatasource', $module) && \App\Cache::has('picklistDependencyFields', $module)) {
219
			return \App\Cache::get('getPicklistDependencyDatasource', $module);
220
		}
221
		$query = (new \App\Db\Query())->from('vtiger_picklist_dependency')->where(['tabid' => \App\Module::getModuleId($module)]);
222
		$dataReader = $query->createCommand()->query();
223
		$picklistDependencyDatasource = [];
224
		$picklistDependencyFields = [];
225
		$isEmptyDefaultValue = \App\Config::performance('PICKLIST_DEPENDENCY_DEFAULT_EMPTY');
226
		while ($row = $dataReader->read()) {
227
			$pickArray = [];
228
			$sourceField = $row['sourcefield'];
229
			$targetField = $row['targetfield'];
230
			$picklistDependencyFields[$sourceField] = true;
231
			$picklistDependencyFields[$targetField] = true;
232
			$sourceValue = \App\Purifier::decodeHtml($row['sourcevalue']);
233
			$targetValues = \App\Purifier::decodeHtml($row['targetvalues']);
234
			$unserializedTargetValues = \App\Json::decode(html_entity_decode($targetValues));
235
			$criteria = \App\Purifier::decodeHtml($row['criteria'] ?? '');
236
			$unserializedCriteria = \App\Json::decode(html_entity_decode($criteria));
237
238
			if (!empty($unserializedCriteria) && null !== $unserializedCriteria['fieldname']) {
239
				$picklistDependencyDatasource[$sourceField][$sourceValue][$targetField][] = [
240
					'condition' => [$unserializedCriteria['fieldname'] => $unserializedCriteria['fieldvalues']],
241
					'values' => $unserializedTargetValues,
242
				];
243
			} else {
244
				$picklistDependencyDatasource[$sourceField][$sourceValue][$targetField] = $unserializedTargetValues;
245
			}
246
			if (!isset($picklistDependencyDatasource[$sourceField]['__DEFAULT__'][$targetField])) {
247
				if (!$isEmptyDefaultValue) {
248
					foreach (self::getValuesName($targetField) as $picklistValue) {
249
						$pickArray[] = \App\Purifier::decodeHtml($picklistValue);
250
					}
251
					$picklistDependencyDatasource[$sourceField]['__DEFAULT__'][$targetField] = $pickArray;
252
				} else {
253
					$picklistDependencyDatasource[$sourceField]['__DEFAULT__'][$targetField] = [];
254
				}
255
			}
256
		}
257
		\App\Cache::save('picklistDependencyFields', $module, $picklistDependencyFields);
258
		\App\Cache::save('getPicklistDependencyDatasource', $module, $picklistDependencyDatasource);
259
		return $picklistDependencyDatasource;
260
	}
261
262
	/**
263
	 * Check if field is dependent.
264 4
	 *
265
	 * @param string $moduleName
266 4
	 * @param string $fieldName
267 3
	 *
268
	 * @return bool
269 4
	 */
270 4
	public static function isDependentField(string $moduleName, string $fieldName): bool
271 4
	{
272 4
		if (!\App\Cache::has('picklistDependencyFields', $moduleName)) {
273 4
			self::getPicklistDependencyDatasource($moduleName);
274 4
		}
275 4
		return isset(\App\Cache::get('picklistDependencyFields', $moduleName)[$fieldName]);
276 4
	}
277 4
278 4
	/**
279
	 * Gets dependent source field.
280 4
	 *
281 4
	 * @param string $moduleName
282
	 * @param string $fieldName
283
	 */
284
	public static function getDependentSourceField(string $moduleName, string $fieldName): string
285
	{
286
		foreach (self::getPicklistDependencyDatasource($moduleName) as $source => $values) {
287
			if (isset($values['__DEFAULT__'][$fieldName])) {
288
				return $source;
289
			}
290
		}
291
		return '';
292
	}
293
294
	/**
295
	 * Function which will give the picklist values rows for a field.
296
	 *
297
	 * @param string $fieldName -- string
298
	 *
299
	 * @return array -- array of values
300
	 */
301
	public static function getValues($fieldName)
302
	{
303
		if (\App\Cache::has('Picklist::getValues', $fieldName)) {
304
			return \App\Cache::get('Picklist::getValues', $fieldName);
305
		}
306
		$primaryKey = static::getPickListId($fieldName);
307
		$dataReader = (new \App\Db\Query())
308
			->from("vtiger_$fieldName")
309
			->orderBy('sortorderid')
310
			->createCommand()->query();
311
		$values = [];
312
		while ($row = $dataReader->read()) {
313
			$row['picklistValue'] = \App\Purifier::decodeHtml(\App\Purifier::decodeHtml($row[$fieldName]));
314
			$row['picklistValueId'] = $row[static::getPickListId($fieldName)];
315
			$values[$row[$primaryKey]] = $row;
316
		}
317
		\App\Cache::save('Picklist::getValues', $fieldName, $values);
318
		return $values;
319
	}
320
321
	/**
322
	 * Get value data by field.
323
	 *
324
	 * @param string $fieldName
325
	 * @param string $value
326
	 *
327 3
	 * @return array
328
	 */
329 3
	public static function getValueInfo(string $fieldName, string $value): array
330 3
	{
331 3
		$info = [];
332 3
		if (self::isPicklistExist($fieldName)) {
333 3
			foreach (self::getValues($fieldName) as $data) {
334 3
				if ($value === $data[$fieldName]) {
335 3
					$info = $data;
336 3
					break;
337 3
				}
338 3
			}
339
		}
340 3
341
		return $info;
342
	}
343
344
	/**
345
	 * Get colors for all fields or generate it if not exists.
346
	 *
347
	 * @param mixed $fieldName
348
	 * @param bool  $numericKey
349
	 *
350
	 * @return array [$id=>'#FF00FF']
351
	 */
352
	public static function getColors($fieldName, bool $numericKey = true)
353
	{
354
		$colors = [];
355
		foreach (static::getValues($fieldName) as $id => &$value) {
0 ignored issues
show
Bug introduced by
The expression static::getValues($fieldName) cannot be used as a reference.

Let?s assume that you have the following foreach statement:

foreach ($array as &$itemValue) { }

$itemValue is assigned by reference. This is possible because the expression (in the example $array) can be used as a reference target.

However, if we were to replace $array with something different like the result of a function call as in

foreach (getArray() as &$itemValue) { }

then assigning by reference is not possible anymore as there is no target that could be modified.

Available Fixes

1. Do not assign by reference
foreach (getArray() as $itemValue) { }
2. Assign to a local variable first
$array = getArray();
foreach ($array as &$itemValue) {}
3. Return a reference
function &getArray() { $array = array(); return $array; }

foreach (getArray() as &$itemValue) { }
Loading history...
356
			$value['color'] = trim($value['color'] ?? '', " #\\s\t\n\r");
357
			if (empty($value['color'])) {
358
				$color = \App\Colors::getRandomColor($id);
359
			} else {
360
				$color = '#' . $value['color'];
361
			}
362
			$colors[$numericKey ? $id : $value[$fieldName]] = $color;
363
		}
364
		return $colors;
365
	}
366
367
	/**
368
	 * Get picklist table name.
369
	 *
370
	 * @param string $fieldName
371
	 *
372
	 * @return string
373
	 */
374
	public static function getPickListTableName(string $fieldName)
375
	{
376
		if (empty($fieldName) || !preg_match('/^[_a-zA-Z0-9]+$/', $fieldName)) {
377
			throw new \App\Exceptions\AppException('Incorrect picklist name');
378
		}
379
		return 'vtiger_' . $fieldName;
380
	}
381
382
	/**
383
	 * Check if the prefix exists in given picklist name.
384
	 *
385
	 * @param string $fieldName
386
	 *
387
	 * @return bool
388
	 */
389
	public static function prefixExist(string $fieldName): bool
390
	{
391
		return !empty(array_filter(array_column(static::getValues($fieldName), 'prefix')));
392
	}
393
394
	/**
395
	 * Get picklist ID number.
396
	 *
397
	 * @param string $fieldName
398
	 *
399
	 * @return int
400
	 */
401
	public static function getPicklistIdNr(string $fieldName): int
402
	{
403
		return (int) (new \App\Db\Query())->select(['picklistid'])
404
			->from('vtiger_picklist')
405
			->where(['name' => $fieldName])
406
			->scalar();
407
	}
408
409
	/**
410
	 * Clear cache.
411
	 *
412
	 * @param string $fieldName
413
	 * @param string $moduleName
414
	 */
415
	public static function clearCache(string $fieldName, string $moduleName)
416
	{
417
		\App\Cache::delete('picklistDependencyFields', $moduleName);
418
		\App\Cache::delete('getPicklistDependencyDatasource', $moduleName);
419
		\App\Cache::delete('Picklist::getValuesName', $fieldName);
420
		\App\Cache::delete('Picklist::getNonEditableValues', $fieldName);
421
		\App\Cache::delete('Picklist::getRoleBasedValues', $fieldName);
422
		\App\Cache::delete('Picklist::getValues', $fieldName);
423
		\App\Cache::delete("RecordStatus::getLockStatus::$moduleName", true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $key of App\Cache::delete(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

423
		\App\Cache::delete("RecordStatus::getLockStatus::$moduleName", /** @scrutinizer ignore-type */ true);
Loading history...
424
		\App\Cache::delete("RecordStatus::getLockStatus::$moduleName", false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $key of App\Cache::delete(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

424
		\App\Cache::delete("RecordStatus::getLockStatus::$moduleName", /** @scrutinizer ignore-type */ false);
Loading history...
425
	}
426
}
427