|
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); |
|
|
|
|
|
|
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; |
|
|
|
|
|
|
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, |
|
|
|
|
|
|
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
|
|
|
|