|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* +********************************************************************************** |
|
4
|
|
|
* The contents of this file are subject to the vtiger CRM Public License Version 1.0 |
|
5
|
|
|
* ("License"); You may not use this file except in compliance with the License |
|
6
|
|
|
* The Original Code is: vtiger CRM Open Source |
|
7
|
|
|
* The Initial Developer of the Original Code is vtiger. |
|
8
|
|
|
* Portions created by vtiger are Copyright (C) vtiger. |
|
9
|
|
|
* All Rights Reserved. |
|
10
|
|
|
* Contributor(s): YetiForce S.A. |
|
11
|
|
|
* ********************************************************************************** */ |
|
12
|
|
|
|
|
13
|
|
|
namespace vtlib; |
|
14
|
|
|
|
|
15
|
|
|
class Functions |
|
16
|
21 |
|
{ |
|
17
|
|
|
public static function getAllModules($isEntityType = true, $showRestricted = false, $presence = false, $colorActive = false, $ownedby = false) |
|
18
|
21 |
|
{ |
|
19
|
15 |
|
if (\App\Cache::has('moduleTabs', 'all')) { |
|
20
|
|
|
$moduleList = \App\Cache::get('moduleTabs', 'all'); |
|
21
|
14 |
|
} else { |
|
22
|
14 |
|
$moduleList = []; |
|
23
|
14 |
|
$rows = (new \App\Db\Query())->from('vtiger_tab')->all(); |
|
24
|
14 |
|
foreach ($rows as $row) { |
|
25
|
11 |
|
if (!\App\Cache::has('moduleTabById', $row['tabid'])) { |
|
26
|
|
|
\App\Cache::save('moduleTabById', $row['tabid'], $row); |
|
27
|
14 |
|
} |
|
28
|
11 |
|
if (!\App\Cache::has('moduleTabByName', $row['name'])) { |
|
29
|
|
|
\App\Cache::save('moduleTabByName', $row['name'], $row); |
|
30
|
14 |
|
} |
|
31
|
14 |
|
$row['tabid'] = (int) $row['tabid']; |
|
32
|
14 |
|
$row['presence'] = (int) $row['presence']; |
|
33
|
14 |
|
$row['tabsequence'] = (int) $row['tabsequence']; |
|
34
|
14 |
|
$row['customized'] = (int) $row['customized']; |
|
35
|
14 |
|
$row['ownedby'] = (int) $row['ownedby']; |
|
36
|
14 |
|
$row['isentitytype'] = (int) $row['isentitytype']; |
|
37
|
14 |
|
$row['coloractive'] = (int) $row['coloractive']; |
|
38
|
14 |
|
$row['type'] = (int) $row['type']; |
|
39
|
14 |
|
$row['premium'] = (int) $row['premium']; |
|
40
|
|
|
$moduleList[$row['tabid']] = $row; |
|
41
|
14 |
|
} |
|
42
|
|
|
\App\Cache::save('moduleTabs', 'all', $moduleList); |
|
43
|
21 |
|
} |
|
44
|
21 |
|
$restrictedModules = ['Dashboard', 'ModComments']; |
|
45
|
21 |
|
foreach ($moduleList as $id => $module) { |
|
46
|
14 |
|
if (!$showRestricted && \in_array($module['name'], $restrictedModules)) { |
|
47
|
|
|
unset($moduleList[$id]); |
|
48
|
21 |
|
} |
|
49
|
13 |
|
if ($isEntityType && 0 === (int) $module['isentitytype']) { |
|
50
|
|
|
unset($moduleList[$id]); |
|
51
|
21 |
|
} |
|
52
|
2 |
|
if (false !== $presence && (int) $module['presence'] !== $presence) { |
|
53
|
|
|
unset($moduleList[$id]); |
|
54
|
21 |
|
} |
|
55
|
|
|
if (false !== $colorActive && 1 !== (int) $module['coloractive']) { |
|
56
|
|
|
unset($moduleList[$id]); |
|
57
|
21 |
|
} |
|
58
|
2 |
|
if (false !== $ownedby && (int) $module['ownedby'] !== $ownedby) { |
|
59
|
|
|
unset($moduleList[$id]); |
|
60
|
|
|
} |
|
61
|
21 |
|
} |
|
62
|
|
|
return $moduleList; |
|
63
|
|
|
} |
|
64
|
84 |
|
|
|
65
|
|
|
public static function getModuleData($mixed) |
|
66
|
84 |
|
{ |
|
67
|
|
|
if (empty($mixed)) { |
|
68
|
|
|
\App\Log::error(__METHOD__ . ' - Required parameter missing'); |
|
69
|
|
|
|
|
70
|
|
|
return false; |
|
71
|
84 |
|
} |
|
72
|
84 |
|
$id = $name = null; |
|
73
|
69 |
|
if (is_numeric($mixed)) { |
|
74
|
69 |
|
$id = $mixed; |
|
75
|
47 |
|
if (\App\Cache::has('moduleTabById', $mixed)) { |
|
76
|
|
|
return \App\Cache::get('moduleTabById', $mixed); |
|
77
|
|
|
} |
|
78
|
58 |
|
} else { |
|
79
|
58 |
|
$name = (string) $mixed; |
|
80
|
32 |
|
if (\App\Cache::has('moduleTabByName', $name)) { |
|
81
|
|
|
return \App\Cache::get('moduleTabByName', $name); |
|
82
|
|
|
} |
|
83
|
59 |
|
} |
|
84
|
59 |
|
$moduleList = []; |
|
85
|
59 |
|
$rows = (new \App\Db\Query())->from('vtiger_tab')->all(); |
|
86
|
59 |
|
foreach ($rows as $row) { |
|
87
|
59 |
|
\App\Cache::save('moduleTabById', $row['tabid'], $row); |
|
88
|
59 |
|
\App\Cache::save('moduleTabByName', $row['name'], $row); |
|
89
|
|
|
$moduleList[$row['tabid']] = $row; |
|
90
|
59 |
|
} |
|
91
|
59 |
|
\App\Cache::save('moduleTabs', 'all', $moduleList); |
|
92
|
34 |
|
if ($name && \App\Cache::has('moduleTabByName', $name)) { |
|
93
|
|
|
return \App\Cache::get('moduleTabByName', $name); |
|
94
|
26 |
|
} |
|
95
|
|
|
return $id ? \App\Cache::get('moduleTabById', $id) : null; |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
// MODULE RECORD |
|
99
|
|
|
protected static $crmRecordIdMetadataCache = []; |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* Clear cache meta data for records. |
|
103
|
|
|
* |
|
104
|
|
|
* @param int $id |
|
105
|
1 |
|
*/ |
|
106
|
|
|
public static function clearCacheMetaDataRecord($id) |
|
107
|
1 |
|
{ |
|
108
|
1 |
|
if (isset(static::$crmRecordIdMetadataCache[$id])) { |
|
109
|
|
|
unset(static::$crmRecordIdMetadataCache[$id]); |
|
110
|
1 |
|
} |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* Function gets record metadata. |
|
115
|
|
|
* |
|
116
|
|
|
* @param array|int $mixedid |
|
117
|
|
|
* |
|
118
|
|
|
* @return array |
|
119
|
26 |
|
*/ |
|
120
|
|
|
public static function getCRMRecordMetadata($mixedid) |
|
121
|
26 |
|
{ |
|
122
|
|
|
$multimode = \is_array($mixedid); |
|
123
|
26 |
|
|
|
124
|
26 |
|
$ids = $multimode ? $mixedid : [$mixedid]; |
|
125
|
26 |
|
$missing = []; |
|
126
|
26 |
|
foreach ($ids as $id) { |
|
127
|
9 |
|
if ($id && !isset(self::$crmRecordIdMetadataCache[$id])) { |
|
128
|
|
|
$missing[] = $id; |
|
129
|
|
|
} |
|
130
|
26 |
|
} |
|
131
|
9 |
|
if ($missing) { |
|
132
|
9 |
|
$query = (new \App\Db\Query()) |
|
133
|
9 |
|
->select(['crmid', 'setype', 'deleted', 'smcreatorid', 'smownerid', 'createdtime', 'private']) |
|
134
|
9 |
|
->from('vtiger_crmentity') |
|
135
|
9 |
|
->where(['in', 'crmid', $missing]); |
|
136
|
9 |
|
$dataReader = $query->createCommand()->query(); |
|
137
|
8 |
|
while ($row = $dataReader->read()) { |
|
138
|
8 |
|
$row['deleted'] = (int) $row['deleted']; |
|
139
|
8 |
|
$row['smownerid'] = (int) $row['smownerid']; |
|
140
|
8 |
|
$row['smcreatorid'] = (int) $row['smcreatorid']; |
|
141
|
8 |
|
$row['crmid'] = (int) $row['crmid']; |
|
142
|
8 |
|
$row['private'] = (int) $row['private']; |
|
143
|
|
|
self::$crmRecordIdMetadataCache[$row['crmid']] = $row; |
|
144
|
|
|
} |
|
145
|
26 |
|
} |
|
146
|
26 |
|
$result = []; |
|
147
|
26 |
|
foreach ($ids as $id) { |
|
148
|
19 |
|
if (isset(self::$crmRecordIdMetadataCache[$id])) { |
|
149
|
|
|
$result[$id] = self::$crmRecordIdMetadataCache[$id]; |
|
150
|
8 |
|
} else { |
|
151
|
|
|
$result[$id] = null; |
|
152
|
|
|
} |
|
153
|
26 |
|
} |
|
154
|
|
|
return $multimode ? $result : array_shift($result); |
|
155
|
|
|
} |
|
156
|
1 |
|
|
|
157
|
|
|
public static function getCRMRecordLabel($id, $default = '') |
|
158
|
1 |
|
{ |
|
159
|
|
|
$label = \App\Record::getLabel($id); |
|
160
|
1 |
|
|
|
161
|
|
|
return empty($label) ? $default : $label; |
|
162
|
|
|
} |
|
163
|
|
|
|
|
164
|
|
|
/** |
|
165
|
|
|
* Function to gets mudule field ID. |
|
166
|
|
|
* |
|
167
|
|
|
* @param int|string $moduleId |
|
168
|
|
|
* @param int|string $mixed |
|
169
|
|
|
* @param bool $onlyactive |
|
170
|
|
|
* |
|
171
|
5821 |
|
* @return bool|int |
|
172
|
|
|
*/ |
|
173
|
5821 |
|
public static function getModuleFieldId($moduleId, $mixed, $onlyactive = true) |
|
174
|
2 |
|
{ |
|
175
|
|
|
$field = \App\Field::getFieldInfo($mixed, $moduleId); |
|
176
|
5821 |
|
|
|
177
|
5821 |
|
if ($field && $onlyactive && ('0' !== $field['presence'] && '2' !== $field['presence'])) { |
|
178
|
49 |
|
$field = null; |
|
179
|
49 |
|
} |
|
180
|
49 |
|
return $field ? $field['fieldid'] : false; |
|
181
|
49 |
|
} |
|
182
|
49 |
|
|
|
183
|
49 |
|
// Utility |
|
184
|
49 |
|
public static function formatDecimal($value) |
|
185
|
49 |
|
{ |
|
186
|
|
|
$fld_value = explode('.', $value); |
|
187
|
49 |
|
if (!empty($fld_value[1])) { |
|
188
|
49 |
|
$fld_value = rtrim($value, '0'); |
|
189
|
|
|
$value = rtrim($fld_value, '.'); |
|
190
|
5821 |
|
} |
|
191
|
1 |
|
return $value; |
|
192
|
|
|
} |
|
193
|
5821 |
|
|
|
194
|
|
|
public static function fromHtmlPopup($string, $encode = true) |
|
195
|
|
|
{ |
|
196
|
|
|
$popup_toHtml = [ |
|
197
|
|
|
'"' => '"', |
|
198
|
|
|
"'" => ''', |
|
199
|
|
|
]; |
|
200
|
|
|
if ($encode && \is_string($string)) { |
|
201
|
|
|
$string = addslashes(str_replace(array_values($popup_toHtml), array_keys($popup_toHtml), $string)); |
|
202
|
|
|
} |
|
203
|
|
|
return $string; |
|
204
|
|
|
} |
|
205
|
|
|
|
|
206
|
|
|
public static function br2nl($str) |
|
207
|
|
|
{ |
|
208
|
|
|
$str = preg_replace("/(\r\n)/", '\\r\\n', $str); |
|
209
|
|
|
$str = preg_replace("/'/", ' ', $str); |
|
210
|
|
|
return preg_replace('/"/', ' ', $str); |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
public static function suppressHTMLTags($string) |
|
214
|
|
|
{ |
|
215
|
|
|
return preg_replace(['/</', '/>/', '/"/'], ['<', '>', '"'], $string); |
|
216
|
1 |
|
} |
|
217
|
|
|
|
|
218
|
1 |
|
/** Function used to retrieve a single field value from database. |
|
219
|
1 |
|
* @param string $tableName - tablename from which we will retrieve the field value |
|
220
|
1 |
|
* @param string $fieldName - fieldname to which we want to get the value from database |
|
221
|
1 |
|
* @param string $idName - idname which is the name of the entity id in the table like, inoviceid, etc., |
|
222
|
|
|
* @param int $id - entity id |
|
223
|
1 |
|
* return mixed $fieldval - field value of the needed fieldname from database will be returned |
|
224
|
|
|
*/ |
|
225
|
|
|
public static function getSingleFieldValue($tableName, $fieldName, $idName, $id) |
|
226
|
|
|
{ |
|
227
|
|
|
return (new \App\Db\Query())->select([$fieldName])->from($tableName)->where([$idName => $id])->scalar(); |
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
|
|
/** function used to change the Type of Data for advanced filters in custom view and Reports. |
|
231
|
|
|
* * @param string $table_name - tablename value from field table |
|
232
|
|
|
* * @param string $column_nametable_name - columnname value from field table |
|
233
|
|
|
* * @param string $type_of_data - current type of data of the field. It is to return the same TypeofData |
|
234
|
|
|
* * if the field is not matched with the $new_field_details array. |
|
235
|
|
|
* * return string $type_of_data - If the string matched with the $new_field_details array then the Changed |
|
236
|
|
|
* * typeofdata will return, else the same typeofdata will return. |
|
237
|
|
|
* * |
|
238
|
|
|
* * EXAMPLE: If you have a field entry like this: |
|
239
|
|
|
* * |
|
240
|
|
|
* * fieldlabel | typeofdata | tablename | columnname | |
|
241
|
|
|
* * -------------------+------------+----------------------+------------------+ |
|
242
|
|
|
* * Potential Name | I~O | vtiger_quotes | potentialid | |
|
243
|
|
|
* * |
|
244
|
|
|
* * Then put an entry in $new_field_details like this: |
|
245
|
|
|
* * |
|
246
|
|
|
* * "vtiger_quotes:potentialid"=>"V", |
|
247
|
|
|
* * |
|
248
|
|
|
* * Now in customview and report's advance filter this field's criteria will be show like string. |
|
249
|
|
|
* @param mixed $column_name |
|
250
|
|
|
* */ |
|
251
|
|
|
public static function transformFieldTypeOfData($table_name, $column_name, $type_of_data) |
|
252
|
|
|
{ |
|
253
|
|
|
$field = $table_name . ':' . $column_name; |
|
254
|
|
|
//Add the field details in this array if you want to change the advance filter field details |
|
255
|
|
|
|
|
256
|
|
|
static $new_field_details = [ |
|
257
|
|
|
//Contacts Related Fields |
|
258
|
|
|
'vtiger_contactdetails:parentid' => 'V', |
|
259
|
|
|
'vtiger_contactsubdetails:birthday' => 'D', |
|
260
|
|
|
'vtiger_contactdetails:email' => 'V', |
|
261
|
|
|
'vtiger_contactdetails:secondaryemail' => 'V', |
|
262
|
|
|
//Account Related Fields |
|
263
|
|
|
'vtiger_account:parentid' => 'V', |
|
264
|
|
|
'vtiger_account:email1' => 'V', |
|
265
|
|
|
'vtiger_account:email2' => 'V', |
|
266
|
|
|
//Lead Related Fields |
|
267
|
|
|
'vtiger_leaddetails:email' => 'V', |
|
268
|
|
|
'vtiger_leaddetails:secondaryemail' => 'V', |
|
269
|
|
|
//Documents Related Fields |
|
270
|
|
|
'vtiger_senotesrel:crmid' => 'V', |
|
271
|
|
|
//HelpDesk Related Fields |
|
272
|
|
|
'vtiger_troubletickets:parent_id' => 'V', |
|
273
|
|
|
'vtiger_troubletickets:product_id' => 'V', |
|
274
|
|
|
//Product Related Fields |
|
275
|
|
|
'vtiger_products:discontinued' => 'C', |
|
276
|
|
|
'vtiger_products:vendor_id' => 'V', |
|
277
|
|
|
'vtiger_products:parentid' => 'V', |
|
278
|
|
|
//Faq Related Fields |
|
279
|
|
|
'vtiger_faq:product_id' => 'V', |
|
280
|
|
|
//Vendor Related Fields |
|
281
|
|
|
'vtiger_vendor:email' => 'V', |
|
282
|
|
|
//Campaign Related Fields |
|
283
|
|
|
'vtiger_campaign:product_id' => 'V', |
|
284
|
14 |
|
//Related List Entries(For Report Module) |
|
285
|
|
|
'vtiger_activityproductrel:activityid' => 'V', |
|
286
|
14 |
|
'vtiger_activityproductrel:productid' => 'V', |
|
287
|
|
|
'vtiger_campaign_records:campaignid' => 'V', |
|
288
|
|
|
'vtiger_campaign_records:crmid' => 'V', |
|
289
|
14 |
|
'vtiger_pricebookproductrel:pricebookid' => 'V', |
|
290
|
|
|
'vtiger_pricebookproductrel:productid' => 'V', |
|
291
|
|
|
'vtiger_senotesrel:crmid' => 'V', |
|
292
|
|
|
'vtiger_senotesrel:notesid' => 'V', |
|
293
|
|
|
'vtiger_seproductsrel:crmid' => 'V', |
|
294
|
|
|
'vtiger_seproductsrel:productid' => 'V', |
|
295
|
|
|
'vtiger_pricebook:currency_id' => 'V', |
|
296
|
|
|
]; |
|
297
|
|
|
|
|
298
|
|
|
//If the Fields details does not match with the array, then we return the same typeofdata |
|
299
|
|
|
if (isset($new_field_details[$field])) { |
|
300
|
|
|
$type_of_data = $new_field_details[$field]; |
|
301
|
|
|
} |
|
302
|
|
|
return $type_of_data; |
|
303
|
|
|
} |
|
304
|
|
|
|
|
305
|
|
|
public static function getArrayFromValue($values) |
|
306
|
|
|
{ |
|
307
|
|
|
if (\is_array($values)) { |
|
308
|
|
|
return $values; |
|
309
|
|
|
} |
|
310
|
|
|
if ('' === $values) { |
|
311
|
|
|
return []; |
|
312
|
|
|
} |
|
313
|
|
|
if (false === strpos($values, ',')) { |
|
314
|
|
|
$array[] = $values; |
|
|
|
|
|
|
315
|
|
|
} else { |
|
316
|
|
|
$array = explode(',', $values); |
|
317
|
|
|
} |
|
318
|
|
|
return $array; |
|
319
|
|
|
} |
|
320
|
|
|
|
|
321
|
|
|
public static function throwNewException($e, $die = true, $messageHeader = 'LBL_ERROR') |
|
322
|
|
|
{ |
|
323
|
|
|
if (!headers_sent() && \App\Config::security('cspHeaderActive')) { |
|
324
|
|
|
header("content-security-policy: default-src 'self' 'nonce-" . \App\Session::get('CSP_TOKEN') . "'; object-src 'none';base-uri 'self'; frame-ancestors 'self';"); |
|
|
|
|
|
|
325
|
|
|
} |
|
326
|
|
|
$message = \is_object($e) ? $e->getMessage() : $e; |
|
327
|
|
|
$code = 500; |
|
328
|
|
|
if (!\is_array($message)) { |
|
329
|
|
|
if (false === strpos($message, '||')) { |
|
330
|
|
|
$message = \App\Language::translateSingleMod($message, 'Other.Exceptions'); |
|
331
|
|
|
} else { |
|
332
|
14 |
|
$params = explode('||', $message); |
|
333
|
6 |
|
$label = \App\Language::translateSingleMod(array_shift($params), 'Other.Exceptions'); |
|
334
|
|
|
$params = array_pad($params, substr_count($label, '%'), ''); |
|
335
|
14 |
|
$message = \call_user_func_array('vsprintf', [$label, $params]); |
|
336
|
|
|
} |
|
337
|
|
|
} |
|
338
|
|
|
if ('API' === \App\Process::$requestMode) { |
|
339
|
|
|
throw new \App\Exceptions\ApiException($message, 401); |
|
340
|
|
|
} |
|
341
|
|
|
if (\App\Request::_isAjax() && \App\Request::_isJSON()) { |
|
|
|
|
|
|
342
|
|
|
$response = new \Vtiger_Response(); |
|
343
|
|
|
$response->setEmitType(\Vtiger_Response::$EMIT_JSON); |
|
344
|
|
|
|
|
345
|
|
|
if (\is_object($e)) { |
|
346
|
|
|
$response->setException($e); |
|
347
|
|
|
} else { |
|
348
|
|
|
$trace = ''; |
|
349
|
|
|
if (\App\Config::debug('DISPLAY_EXCEPTION_BACKTRACE') && \is_object($e)) { |
|
350
|
|
|
$trace = str_replace(ROOT_DIRECTORY . \DIRECTORY_SEPARATOR, '', "->{$e->getFile()}:{$e->getLine()}\n{$e->getTraceAsString()}"); |
|
351
|
|
|
} |
|
352
|
|
|
$response->setError($code, $message, $trace); |
|
353
|
|
|
} |
|
354
|
|
|
$response->emit(); |
|
355
|
|
|
} else { |
|
356
|
|
|
if (\PHP_SAPI !== 'cli') { |
|
357
|
|
|
if (\App\Config::debug('DISPLAY_EXCEPTION_BACKTRACE') && \is_object($e)) { |
|
358
|
|
|
$message = [ |
|
359
|
|
|
'message' => $message, |
|
360
|
|
|
'trace' => str_replace(ROOT_DIRECTORY . \DIRECTORY_SEPARATOR, '', "-> {$e->getFile()}:{$e->getLine()}\n{$e->getTraceAsString()}"), |
|
361
|
|
|
]; |
|
362
|
|
|
$code = $e->getCode(); |
|
363
|
|
|
} |
|
364
|
|
|
if (is_numeric($code)) { |
|
365
|
|
|
http_response_code($code); |
|
366
|
|
|
} |
|
367
|
|
|
$viewer = new \Vtiger_Viewer(); |
|
368
|
|
|
$viewer->assign('MESSAGE', \Config\Debug::$EXCEPTION_ERROR_TO_SHOW ? $message : \App\Language::translate('ERR_OCCURRED_ERROR')); |
|
369
|
|
|
$viewer->assign('MESSAGE_EXPANDED', \Config\Debug::$EXCEPTION_ERROR_TO_SHOW ? \is_array($message) : false); |
|
370
|
|
|
$viewer->assign('HEADER_MESSAGE', \App\Language::translate($messageHeader)); |
|
371
|
|
|
$viewer->view('Exceptions/ExceptionError.tpl', 'Vtiger'); |
|
372
|
|
|
} else { |
|
373
|
|
|
echo(\Config\Debug::$EXCEPTION_ERROR_TO_SHOW ? $message : \App\Language::translate('ERR_OCCURRED_ERROR')) . PHP_EOL; |
|
|
|
|
|
|
374
|
|
|
} |
|
375
|
|
|
} |
|
376
|
|
|
if ($die) { |
|
377
|
|
|
trigger_error(print_r($message, true), E_USER_ERROR); |
|
378
|
|
|
if (\is_object($message)) { |
|
379
|
|
|
throw new $message(); |
|
380
|
|
|
} |
|
381
|
|
|
if (\is_array($message)) { |
|
382
|
|
|
throw new \App\Exceptions\AppException($message['message']); |
|
383
|
|
|
} |
|
384
|
|
|
throw new \App\Exceptions\AppException($message); |
|
385
|
|
|
} |
|
386
|
|
|
} |
|
387
|
|
|
|
|
388
|
|
|
/** |
|
389
|
|
|
* Get html rr plain text. |
|
390
|
|
|
* |
|
391
|
|
|
* @param string $content |
|
392
|
|
|
* |
|
393
|
|
|
* @return string |
|
394
|
|
|
*/ |
|
395
|
|
|
public static function getHtmlOrPlainText(string $content) |
|
396
|
|
|
{ |
|
397
|
|
|
if (\App\Utils::isHtml($content)) { |
|
398
|
|
|
$content = \App\Purifier::decodeHtml($content); |
|
399
|
|
|
} else { |
|
400
|
|
|
$content = nl2br($content); |
|
401
|
|
|
} |
|
402
|
|
|
return $content; |
|
403
|
|
|
} |
|
404
|
|
|
|
|
405
|
|
|
/** |
|
406
|
|
|
* Function to delete files and dirs. |
|
407
|
|
|
* |
|
408
|
|
|
* @param string $src |
|
409
|
|
|
* @param bool $outsideRoot |
|
410
|
|
|
*/ |
|
411
|
|
|
public static function recurseDelete($src, $outsideRoot = false): int |
|
412
|
|
|
{ |
|
413
|
|
|
$rootDir = ($outsideRoot || 0 === strpos($src, ROOT_DIRECTORY)) ? '' : ROOT_DIRECTORY . \DIRECTORY_SEPARATOR; |
|
414
|
|
|
if (!file_exists($rootDir . $src)) { |
|
415
|
|
|
return 0; |
|
416
|
|
|
} |
|
417
|
|
|
$i = 0; |
|
418
|
|
|
if (is_dir($rootDir . $src)) { |
|
419
|
|
|
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($rootDir . $src, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST) as $filename => $file) { |
|
420
|
|
|
if ($file->isFile()) { |
|
421
|
|
|
unlink($filename); |
|
422
|
|
|
++$i; |
|
423
|
|
|
} else { |
|
424
|
|
|
rmdir($filename); |
|
425
|
|
|
} |
|
426
|
|
|
} |
|
427
|
|
|
rmdir($rootDir . $src); |
|
428
|
|
|
} else { |
|
429
|
|
|
unlink($rootDir . $src); |
|
430
|
|
|
++$i; |
|
431
|
|
|
} |
|
432
|
|
|
return $i; |
|
433
|
|
|
} |
|
434
|
|
|
|
|
435
|
|
|
/** |
|
436
|
|
|
* The function copies files. |
|
437
|
|
|
* |
|
438
|
|
|
* @param string $src |
|
439
|
|
|
* @param string $dest |
|
440
|
7 |
|
* |
|
441
|
|
|
* @return int |
|
442
|
7 |
|
*/ |
|
443
|
7 |
|
public static function recurseCopy($src, $dest) |
|
444
|
2 |
|
{ |
|
445
|
|
|
$rootDir = ROOT_DIRECTORY . \DIRECTORY_SEPARATOR; |
|
446
|
6 |
|
if (!file_exists($rootDir . $src)) { |
|
447
|
6 |
|
return 0; |
|
448
|
6 |
|
} |
|
449
|
6 |
|
if ($dest && '/' !== substr($dest, -1) && '\\' !== substr($dest, -1)) { |
|
450
|
|
|
$dest = $dest . \DIRECTORY_SEPARATOR; |
|
451
|
4 |
|
} |
|
452
|
|
|
$i = 0; |
|
453
|
|
|
$dest = $rootDir . $dest; |
|
454
|
6 |
|
foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($src, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) { |
|
455
|
|
|
if ($item->isDir() && !file_exists($dest . $iterator->getSubPathName())) { |
|
|
|
|
|
|
456
|
|
|
mkdir($dest . $iterator->getSubPathName(), 0755); |
|
457
|
|
|
} elseif (!$item->isDir()) { |
|
458
|
6 |
|
copy($item->getRealPath(), $dest . $iterator->getSubPathName()); |
|
459
|
|
|
++$i; |
|
460
|
|
|
} |
|
461
|
|
|
} |
|
462
|
|
|
return $i; |
|
463
|
|
|
} |
|
464
|
|
|
|
|
465
|
|
|
/** |
|
466
|
|
|
* Parse bytes. |
|
467
|
|
|
* |
|
468
|
|
|
* @param mixed $str |
|
469
|
|
|
* |
|
470
|
|
|
* @return float |
|
471
|
|
|
*/ |
|
472
|
|
|
public static function parseBytes($str): float |
|
473
|
|
|
{ |
|
474
|
|
|
if (is_numeric($str)) { |
|
475
|
|
|
return (float) $str; |
|
476
|
|
|
} |
|
477
|
|
|
$bytes = 0; |
|
478
|
|
|
if (preg_match('/([0-9\.]+)\s*([a-z]*)/i', $str, $regs)) { |
|
479
|
|
|
$bytes = (float) ($regs[1]); |
|
480
|
|
|
switch (strtolower($regs[2])) { |
|
481
|
|
|
case 'g': |
|
482
|
|
|
case 'gb': |
|
483
|
|
|
$bytes *= 1073741824; |
|
484
|
|
|
break; |
|
485
|
|
|
case 'm': |
|
486
|
|
|
case 'mb': |
|
487
|
|
|
$bytes *= 1048576; |
|
488
|
|
|
break; |
|
489
|
|
|
case 'k': |
|
490
|
13 |
|
case 'kb': |
|
491
|
|
|
$bytes *= 1024; |
|
492
|
13 |
|
break; |
|
493
|
13 |
|
default: |
|
494
|
|
|
break; |
|
495
|
|
|
} |
|
496
|
|
|
} |
|
497
|
|
|
return (float) $bytes; |
|
498
|
|
|
} |
|
499
|
|
|
|
|
500
|
|
|
/** |
|
501
|
|
|
* Show bytes. |
|
502
|
|
|
* |
|
503
|
|
|
* @param mixed $bytes |
|
504
|
|
|
* @param string|null $unit |
|
505
|
|
|
* |
|
506
|
|
|
* @return string |
|
507
|
|
|
*/ |
|
508
|
|
|
public static function showBytes($bytes, &$unit = null): string |
|
509
|
|
|
{ |
|
510
|
|
|
$bytes = self::parseBytes($bytes); |
|
511
|
|
|
if ($bytes >= 1073741824) { |
|
512
|
|
|
$unit = 'GB'; |
|
513
|
|
|
$gb = $bytes / 1073741824; |
|
514
|
|
|
$str = sprintf($gb >= 10 ? '%d ' : '%.2f ', $gb) . $unit; |
|
515
|
|
|
} elseif ($bytes >= 1048576) { |
|
516
|
|
|
$unit = 'MB'; |
|
517
|
|
|
$mb = $bytes / 1048576; |
|
518
|
13 |
|
$str = sprintf($mb >= 10 ? '%d ' : '%.2f ', $mb) . $unit; |
|
519
|
|
|
} elseif ($bytes >= 1024) { |
|
520
|
13 |
|
$unit = 'KB'; |
|
521
|
13 |
|
$str = sprintf('%d ', round($bytes / 1024)) . $unit; |
|
522
|
|
|
} else { |
|
523
|
|
|
$unit = 'B'; |
|
524
|
|
|
$str = sprintf('%d ', $bytes) . $unit; |
|
525
|
13 |
|
} |
|
526
|
|
|
return $str; |
|
527
|
|
|
} |
|
528
|
|
|
|
|
529
|
13 |
|
public static function getMinimizationOptions($type = 'js') |
|
530
|
7 |
|
{ |
|
531
|
7 |
|
switch ($type) { |
|
532
|
|
|
case 'js': |
|
533
|
7 |
|
$return = \App\Config::developer('MINIMIZE_JS'); |
|
534
|
7 |
|
break; |
|
535
|
|
|
case 'css': |
|
536
|
13 |
|
$return = \App\Config::developer('MINIMIZE_CSS'); |
|
537
|
|
|
break; |
|
538
|
|
|
default: |
|
539
|
|
|
break; |
|
540
|
|
|
} |
|
541
|
|
|
return $return; |
|
|
|
|
|
|
542
|
|
|
} |
|
543
|
|
|
|
|
544
|
|
|
/** |
|
545
|
|
|
* Checks if given date is working day, if not returns last working day. |
|
546
|
|
|
* |
|
547
|
|
|
* @param <Date> $date |
|
|
|
|
|
|
548
|
|
|
* |
|
549
|
|
|
* @return <Date> - last working y |
|
|
|
|
|
|
550
|
|
|
*/ |
|
551
|
|
|
public static function getLastWorkingDay($date) |
|
552
|
|
|
{ |
|
553
|
|
|
if (empty($date)) { |
|
554
|
|
|
$date = date('Y-m-d'); |
|
555
|
|
|
} |
|
556
|
|
|
$date = strtotime($date); |
|
557
|
|
|
if ('Sat' === date('D', $date)) { // switch to friday the day before |
|
558
|
|
|
$lastWorkingDay = date('Y-m-d', strtotime('-1 day', $date)); |
|
559
|
|
|
} elseif ('Sun' === date('D', $date)) { // switch to friday two days before |
|
560
|
|
|
$lastWorkingDay = date('Y-m-d', strtotime('-2 day', $date)); |
|
561
|
|
|
} else { |
|
562
|
|
|
$lastWorkingDay = date('Y-m-d', $date); |
|
563
|
|
|
} |
|
564
|
|
|
return $lastWorkingDay; |
|
565
|
|
|
} |
|
566
|
|
|
|
|
567
|
|
|
/** |
|
568
|
|
|
* Function that returns conversion info from default system currency to chosen one. |
|
569
|
|
|
* |
|
570
|
|
|
* @param <Integer> $currencyId - id of currency for which we want to retrieve conversion rate to default currency |
|
|
|
|
|
|
571
|
|
|
* @param <Date> $date - date of exchange rates, if empty then rate from yesterday |
|
572
|
|
|
* |
|
573
|
1 |
|
* @return <Array> - array containing: |
|
|
|
|
|
|
574
|
|
|
* date - date of rate |
|
575
|
1 |
|
* value - conversion 1 default currency -> $currencyId |
|
576
|
|
|
* conversion - 1 $currencyId -> default currency |
|
577
|
|
|
*/ |
|
578
|
1 |
|
public static function getConversionRateInfo($currencyId, $date = '') |
|
579
|
1 |
|
{ |
|
580
|
|
|
$defaultCurrencyId = \App\Fields\Currency::getDefault()['id']; |
|
581
|
1 |
|
$info = []; |
|
582
|
|
|
if (empty($date)) { |
|
583
|
|
|
$date = date('Y-m-d', strtotime('-1 day')); |
|
584
|
1 |
|
} |
|
585
|
|
|
$date = self::getLastWorkingDay($date); |
|
586
|
1 |
|
|
|
587
|
|
|
$info['date'] = $date; |
|
588
|
|
|
if ($currencyId == $defaultCurrencyId || !\App\Fields\Currency::getActiveBankForExchangeRateUpdate()) { |
|
589
|
2 |
|
$info['value'] = 1.0; |
|
590
|
|
|
$info['conversion'] = 1.0; |
|
591
|
|
|
} else { |
|
592
|
2 |
|
$exchangeDate = $date; |
|
593
|
|
|
$i = 5; |
|
594
|
|
|
// Loop to skip holidays |
|
595
|
2 |
|
while ($i-- && !($value = \Settings_CurrencyUpdate_Module_Model::getCleanInstance()->getCRMConversionRate($currencyId, $defaultCurrencyId, $exchangeDate))) { |
|
596
|
|
|
$exchangeDate = date('Y-m-d', strtotime('-1 day', strtotime($exchangeDate))); |
|
597
|
|
|
} |
|
598
|
|
|
$info['date'] = $value ? $exchangeDate : $date; |
|
|
|
|
|
|
599
|
|
|
$info['value'] = empty($value) ? 1.0 : round($value, 5); |
|
600
|
|
|
$info['conversion'] = empty($value) ? 1.0 : round(1 / $value, 5); |
|
601
|
|
|
} |
|
602
|
|
|
|
|
603
|
|
|
return $info; |
|
604
|
|
|
} |
|
605
|
|
|
|
|
606
|
|
|
/** |
|
607
|
|
|
* Getting parameters from URL. |
|
608
|
|
|
* |
|
609
|
|
|
* @param string|null $url |
|
610
|
|
|
* |
|
611
|
|
|
* @return array |
|
612
|
|
|
*/ |
|
613
|
|
|
public static function getQueryParams($url): array |
|
614
|
|
|
{ |
|
615
|
|
|
$queryParams = []; |
|
616
|
|
|
if (!empty($url) && $queryStr = parse_url(htmlspecialchars_decode($url), PHP_URL_QUERY)) { |
|
617
|
|
|
parse_str($queryStr, $queryParams); |
|
618
|
|
|
} |
|
619
|
|
|
|
|
620
|
|
|
return $queryParams; |
|
621
|
|
|
} |
|
622
|
|
|
|
|
623
|
|
|
public static function arrayDiffAssocRecursive($array1, $array2) |
|
624
|
|
|
{ |
|
625
|
|
|
$difference = []; |
|
626
|
|
|
foreach ($array1 as $key => $value) { |
|
627
|
|
|
if (\is_array($value)) { |
|
628
|
|
|
if (!isset($array2[$key]) || !\is_array($array2[$key])) { |
|
629
|
|
|
$difference[$key] = $value; |
|
630
|
|
|
} else { |
|
631
|
|
|
$newDiff = self::arrayDiffAssocRecursive($value, $array2[$key]); |
|
632
|
|
|
if (!empty($newDiff)) { |
|
633
|
|
|
$difference[$key] = $newDiff; |
|
634
|
|
|
} |
|
635
|
|
|
} |
|
636
|
|
|
} elseif (!\array_key_exists($key, $array2) || $array2[$key] !== $value) { |
|
637
|
|
|
$difference[$key] = $value; |
|
638
|
|
|
} |
|
639
|
|
|
} |
|
640
|
|
|
return $difference; |
|
641
|
|
|
} |
|
642
|
|
|
} |
|
643
|
|
|
|