Passed
Pull Request — developer (#16684)
by Arkadiusz
16:18
created

Module::getSharingModuleList()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 10
ccs 0
cts 8
cp 0
rs 10
c 0
b 0
f 0
cc 4
nc 3
nop 1
crap 20
1
<?php
2
3
namespace App;
4
5
/**
6
 * Modules basic 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    Mariusz Krzaczkowski <[email protected]>
13
 * @author    Radosław Skrzypczak <[email protected]>
14
 */
15
class Module
16
{
17
	/**
18
	 * Cache for tabdata.php.
19
	 *
20
	 * @var array
21
	 */
22
	protected static $tabdataCache;
23
24
	/**
25
	 * Init tabdata from file.
26
	 */
27
	public static function init()
28
	{
29
		static::$tabdataCache = require ROOT_DIRECTORY . '/user_privileges/tabdata.php';
30
		static::$tabdataCache['tabName'] = array_flip(static::$tabdataCache['tabId']);
31
	}
32
33
	/**
34
	 * Init tabdata form db.
35 7
	 */
36
	public static function initFromDb()
37 7
	{
38 7
		static::$tabdataCache = static::getModuleMeta();
39 7
		static::$tabdataCache['tabName'] = array_flip(static::$tabdataCache['tabId']);
40
	}
41 5868
42
	/**
43 5868
	 * Gets entity info.
44 5868
	 *
45 5868
	 * @param string $moduleName
46
	 *
47
	 * @return array|null
48
	 */
49
	public static function getEntityInfo(string $moduleName = null): ?array
50 5868
	{
51 5844
		return self::getEntitiesInfo()[$moduleName] ?? null;
52
	}
53
54
	/**
55 62
	 * Gets all entities data.
56 62
	 *
57 62
	 * @param array
58 62
	 */
59 62
	public static function getEntitiesInfo(): array
60 62
	{
61 62
		$cacheName = 'ModuleEntityInfo';
62 62
		if (!Cache::has($cacheName, '')) {
63 62
			$entityInfos = [];
64
			$dataReader = (new \App\Db\Query())->from('vtiger_entityname')->createCommand()->query();
65 62
			while ($row = $dataReader->read()) {
66 62
				$row['fieldnameArr'] = $row['fieldname'] ? explode(',', $row['fieldname']) : [];
67
				$row['searchcolumnArr'] = $row['searchcolumn'] ? explode(',', $row['searchcolumn']) : [];
68
				$entityInfos[$row['modulename']] = $row;
69 62
			}
70
			return Cache::save($cacheName, '', $entityInfos);
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Cache::save($...Name, '', $entityInfos) returns the type boolean which is incompatible with the type-hinted return array.
Loading history...
71
		}
72
		return Cache::get($cacheName, '');
73
	}
74
75
	public static function getAllEntityModuleInfo($sort = false)
76
	{
77
		$entity = static::getEntitiesInfo();
78
		if ($sort) {
79
			usort($entity, function ($a, $b) {
80
				return $a['sequence'] < $b['sequence'] ? -1 : 1;
81
			});
82
		}
83
		return $entity;
84
	}
85
86
	protected static $isModuleActiveCache = [];
87
88
	/**
89
	 * Function to check whether the module is active.
90
	 *
91
	 * @param string $moduleName
92
	 *
93
	 * @return bool
94 15
	 */
95
	public static function isModuleActive(string $moduleName): bool
96 15
	{
97 15
		if (isset(static::$isModuleActiveCache[$moduleName])) {
98
			return static::$isModuleActiveCache[$moduleName];
99 3
		}
100 1
		if (\in_array($moduleName, ['CustomView', 'Users', 'Import', 'com_vtiger_workflow', 'PickList'])) {
101
			static::$isModuleActiveCache[$moduleName] = true;
102 1
			return true;
103
		}
104 2
		$moduleId = static::getModuleId($moduleName);
105 2
		$isActive = (isset(static::$tabdataCache['tabPresence'][$moduleId]) && 0 == static::$tabdataCache['tabPresence'][$moduleId]);
106 2
		static::$isModuleActiveCache[$moduleName] = $isActive;
107
		return $isActive;
108 2
	}
109
110
	/**
111
	 * Get module id by module name.
112
	 *
113
	 * @param string $moduleName
114
	 *
115
	 * @return bool|int
116
	 */
117
	public static function getModuleId($moduleName)
118 127
	{
119
		return static::$tabdataCache['tabId'][$moduleName] ?? false;
120 127
	}
121
122
	/**
123
	 * Get module nane by module id.
124
	 *
125
	 * @param int $tabId
126
	 *
127
	 * @return bool|string
128
	 */
129
	public static function getModuleName($tabId)
130 446
	{
131
		return static::$tabdataCache['tabName'][$tabId] ?? false;
132 446
	}
133
134
	/**
135
	 * Get default module name.
136
	 *
137
	 * @return string
138
	 */
139
	public static function getDefaultModule(): string
140
	{
141
		$defaultModule = \App\Config::main('default_module');
142
		$moduleName = !empty($defaultModule) ? $defaultModule : 'Home';
143
		if (!empty($moduleName) && !\App\Privilege::isPermitted($moduleName)) {
144
			foreach (\vtlib\Functions::getAllModules() as $module) {
145
				if (\App\Privilege::isPermitted($module['name'])) {
146
					$moduleName = $module['name'];
147
					break;
148
				}
149
			}
150
		}
151
		return $moduleName;
152
	}
153
154
	/**
155
	 * Get module owner by module id.
156
	 *
157
	 * @param int $tabId
158
	 *
159
	 * @return int
160
	 */
161
	public static function getModuleOwner($tabId)
162
	{
163
		return static::$tabdataCache['tabOwnedby'][$tabId] ?? false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::tabdataCa...edby'][$tabId] ?? false could also return false which is incompatible with the documented return type integer. 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...
164 2
	}
165
166 2
	/**
167 2
	 * Get all module names.
168 2
	 *
169 2
	 * @return string[]
170 2
	 */
171
	public static function getAllModuleNames()
172
	{
173 2
		return static::$tabdataCache['tabName'];
174
	}
175
176
	/**
177
	 * Function to get the list of module for which the user defined sharing rules can be defined.
178
	 *
179
	 * @param array $eliminateModules
180
	 *
181
	 * @return array
182
	 */
183
	public static function getSharingModuleList($eliminateModules = false)
184
	{
185
		$modules = \vtlib\Functions::getAllModules(true, true, 0, false, 0);
186
		$sharingModules = [];
187
		foreach ($modules as $row) {
188
			if (!$eliminateModules || !\in_array($row['name'], $eliminateModules)) {
189
				$sharingModules[] = $row['name'];
190
			}
191
		}
192
		return $sharingModules;
193
	}
194
195
	/**
196
	 * Get sql for name in display format.
197
	 *
198
	 * @param string $moduleName
199
	 *
200
	 * @return string
201
	 */
202
	public static function getSqlForNameInDisplayFormat($moduleName)
203
	{
204
		$db = \App\Db::getInstance();
205
		$entityFieldInfo = static::getEntityInfo($moduleName);
206
		$fieldsName = $entityFieldInfo['fieldnameArr'];
207
		if (\count($fieldsName) > 1) {
208 16
			$sqlString = 'CONCAT(';
209
			foreach ($fieldsName as &$column) {
210 16
				$sqlString .= "{$db->quoteTableName($entityFieldInfo['tablename'])}.{$db->quoteColumnName($column)},' ',";
211 6
			}
212
			$formattedName = new \yii\db\Expression(rtrim($sqlString, ',\' \',') . ')');
213 12
		} else {
214 6
			$fieldsName = array_pop($fieldsName);
215
			$formattedName = "{$db->quoteTableName($entityFieldInfo['tablename'])}.{$db->quoteColumnName($fieldsName)}";
216 7
		}
217 7
		return $formattedName;
218 7
	}
219
220 7
	/**
221
	 * Function to get a action id for a given action name.
222
	 *
223 7
	 * @param string $action
224 7
	 *
225
	 * @return int|null
226 7
	 */
227 7
	public static function getActionId($action)
228
	{
229
		if (empty($action)) {
230
			return null;
231
		}
232
		if (Cache::has('getActionId', $action)) {
233
			return Cache::get('getActionId', $action);
234
		}
235 7
		$actionIds = static::$tabdataCache['actionId'];
236
		if (isset($actionIds[$action])) {
237 7
			$actionId = $actionIds[$action];
238 7
		}
239 7
		if (empty($actionId)) {
240 7
			$actionId = (new Db\Query())->select(['actionid'])->from('vtiger_actionmapping')->where(['actionname' => $action])->scalar();
241 7
		}
242 7
		if (is_numeric($actionId)) {
243
			$actionId = (int) $actionId;
244
		}
245 7
		Cache::save('getActionId', $action, $actionId, Cache::LONG);
246 7
		return $actionId;
247 7
	}
248 7
249 7
	/**
250 7
	 * Get module meta data.
251 7
	 *
252
	 * @return array
253
	 */
254
	public static function getModuleMeta()
255 7
	{
256 7
		$tabNames = $tabPresence = $tabOwned = [];
257 7
		$allModules = \vtlib\Functions::getAllModules(false, true);
258 7
		foreach ($allModules as $moduleInfo) {
259 7
			$tabNames[$moduleInfo['name']] = $tabId = (int) $moduleInfo['tabid'];
260
			$tabPresence[$tabId] = $moduleInfo['presence'];
261
			$tabOwned[$tabId] = $moduleInfo['ownedby'];
262
		}
263
		//Constructing the actionname=>actionid array
264
		$actionAll = [];
265
		$dataReader = (new Db\Query())->from(['vtiger_actionmapping'])->createCommand()->query();
266
		while ($row = $dataReader->read()) {
267
			$actionname = $row['actionname'];
268 7
			$actionAll[$actionname] = $actionid = (int) $row['actionid'];
269
			if (0 === (int) $row['securitycheck']) {
270 7
				$actionSecure[$actionid] = $actionname;
271 7
			}
272 7
		}
273 7
		return [
274 7
			'tabId' => $tabNames,
275 7
			'tabPresence' => $tabPresence,
276 7
			'tabOwnedby' => $tabOwned,
277 7
			'actionId' => $actionAll,
278
			'actionName' => $actionSecure,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $actionSecure does not seem to be defined for all execution paths leading up to this point.
Loading history...
279
		];
280
	}
281
282
	/**
283
	 * Function to create file about modules.
284
	 *
285
	 * @throws \App\Exceptions\NoPermitted
286 7
	 */
287
	public static function createModuleMetaFile()
288
	{
289 7
		Cache::delete('moduleTabs', 'all');
290 7
		Cache::delete('getTrackingModules', 'all');
291
		$filename = ROOT_DIRECTORY . '/user_privileges/tabdata.php';
292
		if (file_exists($filename)) {
293
			if (is_writable($filename)) {
294
				$moduleMeta = static::getModuleMeta();
295
				$content = '$tab_seq_array=' . Utils::varExport($moduleMeta['tabPresence']) . ";\n";
296
				$content .= 'return ' . Utils::varExport($moduleMeta) . ";\n";
297
				if (!Utils::saveToFile($filename, $content)) {
298
					throw new Exceptions\NoPermitted("Cannot write file ($filename)");
299
				}
300
			} else {
301
				Log::error("The file $filename is not writable");
302
			}
303
		} else {
304
			Log::error("The file $filename does not exist");
305
		}
306
		static::initFromDb();
307
		register_shutdown_function(function () {
308
			try {
309
				YetiForce\Shop::generateCache();
310
			} catch (\Throwable $e) {
311
				\App\Log::error($e->getMessage() . PHP_EOL . $e->__toString());
312
				throw $e;
313
			}
314
		});
315
	}
316
317
	/**
318
	 * Function changes the module type.
319
	 *
320
	 * @param string $moduleName
321
	 * @param int    $type
322
	 */
323
	public static function changeType(string $moduleName, int $type)
324
	{
325
		$moduleModel = \Vtiger_Module_Model::getInstance($moduleName);
326
		if ($moduleModel && $moduleModel->changeType($type) && PrivilegeUtil::modifyPermissions($moduleName, ['RecordPdfInventory'], \Vtiger_Module_Model::ADVANCED_TYPE === $type)) {
327
			UserPrivilegesFile::recalculateAll();
328
		}
329
	}
330
331
	/**
332
	 * Get all module names by filter.
333
	 *
334
	 * @param bool     $isEntityType
335
	 * @param bool     $showRestricted
336
	 * @param bool|int $presence
337
	 *
338
	 * @return string[]
339
	 */
340
	public static function getAllModuleNamesFilter($isEntityType = true, $showRestricted = false, $presence = false): array
341
	{
342
		$modules = [];
343
		foreach (\vtlib\Functions::getAllModules($isEntityType, $showRestricted, $presence) as $value) {
344
			$modules[$value['name']] = Language::translate($value['name'], $value['name']);
345
		}
346
		return $modules;
347
	}
348
349
	/**
350
	 * Function to get the list of all accessible modules for Quick Create.
351
	 *
352
	 * @param bool $restrictList
353
	 * @param bool $tree
354
	 *
355
	 * @return array List of Vtiger_Module_Model instances
356
	 */
357
	public static function getQuickCreateModules($restrictList = false, $tree = false): array
358
	{
359
		$restrictListString = $restrictList ? 1 : 0;
360
		if ($tree) {
361
			$userModel = \App\User::getCurrentUserModel();
362
			$quickCreateModulesTreeCache = \App\Cache::get('getQuickCreateModules', 'tree' . $restrictListString . $userModel->getDetail('roleid'));
363
			if (false !== $quickCreateModulesTreeCache) {
364
				return $quickCreateModulesTreeCache;
365
			}
366
		} else {
367
			$quickCreateModules = \App\Cache::get('getQuickCreateModules', $restrictListString);
368
			if (false !== $quickCreateModules) {
369
				return $quickCreateModules;
370
			}
371
		}
372
373
		$userPrivModel = \Users_Privileges_Model::getCurrentUserPrivilegesModel();
374
375
		$query = new \App\Db\Query();
376
		$query->select(['vtiger_tab.*'])->from('vtiger_field')
377
			->innerJoin('vtiger_tab', 'vtiger_tab.tabid = vtiger_field.tabid')
378
			->where(['<>', 'vtiger_tab.presence', 1]);
379
		if ($tree) {
380
			$query->andWhere(['<>', 'vtiger_tab.name', 'Users']);
381
		} else {
382
			$query->andWhere(['quickcreate' => [0, 2]])
383
				->andWhere(['<>', 'vtiger_tab.type', 1]);
384
		}
385
		if ($restrictList) {
386
			$query->andWhere(['not in', 'vtiger_tab.name', ['ModComments', 'PriceBooks', 'CallHistory', 'OSSMailView']]);
387
		}
388
		$quickCreateModules = [];
389
		$dataReader = $query->distinct()->createCommand()->query();
390
		while ($row = $dataReader->read()) {
391
			if ($userPrivModel->hasModuleActionPermission($row['tabid'], 'CreateView')) {
392
				$moduleModel = \Vtiger_Module_Model::getInstanceFromArray($row);
393
				$quickCreateModules[$row['name']] = $moduleModel;
394
			}
395
		}
396
		if ($tree) {
397
			$menu = \Vtiger_Menu_Model::getAll();
398
			$quickCreateModulesTree = [];
399
			foreach ($menu as $parent) {
400
				if (!empty($parent['childs'])) {
401
					$items = [];
402
					foreach ($parent['childs'] as $child) {
403
						if (isset($quickCreateModules[$child['mod']])) {
404
							$items[$quickCreateModules[$child['mod']]->name] = $quickCreateModules[$child['mod']];
405
							unset($quickCreateModules[$child['mod']]);
406
						}
407
					}
408
					if (!empty($items)) {
409
						$quickCreateModulesTree[] = ['name' => $parent['name'], 'icon' => $parent['icon'], 'modules' => $items];
410
					}
411
				}
412
			}
413
			if (!empty($quickCreateModules)) {
414
				$quickCreateModulesTree[] = ['name' => 'LBL_OTHER', 'icon' => 'yfm-Other', 'modules' => $quickCreateModules];
415
			}
416
			\App\Cache::save('getQuickCreateModules', 'tree' . $restrictListString . $userPrivModel->get('roleid'), $quickCreateModulesTree);
417
			return $quickCreateModulesTree;
418
		}
419
		\App\Cache::save('getQuickCreateModules', $restrictListString, $quickCreateModules);
420
		return $quickCreateModules;
421
	}
422
}
423
424
Module::init();
425