This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||||||
2 | /** |
||||||
3 | * Text parser file. |
||||||
4 | * |
||||||
5 | * @package App |
||||||
6 | * |
||||||
7 | * @copyright YetiForce S.A. |
||||||
8 | * @license YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com) |
||||||
9 | * @author Mariusz Krzaczkowski <[email protected]> |
||||||
10 | * @author Radosław Skrzypczak <[email protected]> |
||||||
11 | */ |
||||||
12 | |||||||
13 | namespace App; |
||||||
14 | |||||||
15 | /** |
||||||
16 | * Text parser class. |
||||||
17 | */ |
||||||
18 | class TextParser |
||||||
19 | { |
||||||
20 | /** |
||||||
21 | * Examples of supported variables. |
||||||
22 | * |
||||||
23 | * @var array |
||||||
24 | */ |
||||||
25 | public static $variableExamples = [ |
||||||
26 | 'LBL_ORGANIZATION_NAME' => '$(organization : company_name)$', |
||||||
27 | 'LBL_ORGANIZATION_LOGO' => '$(organization : logo)$', |
||||||
28 | 'LBL_EMPLOYEE_NAME' => '$(employee : last_name)$', |
||||||
29 | 'LBL_CRM_DETAIL_VIEW_URL' => '$(record : CrmDetailViewURL)$', |
||||||
30 | 'LBL_PORTAL_DETAIL_VIEW_URL' => '$(record : PortalDetailViewURL)$', |
||||||
31 | 'LBL_RECORD_ID' => '$(record : RecordId)$', |
||||||
32 | 'LBL_RECORD_LABEL' => '$(record : RecordLabel)$', |
||||||
33 | 'LBL_LIST_OF_CHANGES_IN_RECORD' => '$(record : ChangesListChanges)$', |
||||||
34 | 'LBL_LIST_OF_NEW_VALUES_IN_RECORD' => '$(record : ChangesListValues)$', |
||||||
35 | 'LBL_RECORD_COMMENT' => '$(record : Comments 5)$, $(record : Comments)$', |
||||||
36 | 'LBL_RELATED_RECORD_LABEL' => '$(relatedRecord : parent_id|email1|Accounts)$, $(relatedRecord : parent_id|email1)$', |
||||||
37 | 'LBL_RELATED_NEXT_LEVEL_RECORD_LABEL' => '$(relatedRecordLevel : projectid|Project|linktoaccountscontacts|email1|Accounts)$', |
||||||
38 | 'LBL_OWNER_EMAIL' => '$(relatedRecord : assigned_user_id|email1|Users)$', |
||||||
39 | 'LBL_SOURCE_RECORD_LABEL' => '$(sourceRecord : RecordLabel)$', |
||||||
40 | 'LBL_CUSTOM_FUNCTION' => '$(custom : ContactsPortalPass)$', |
||||||
41 | 'LBL_RELATED_RECORDS_LIST' => '$(relatedRecordsList : Contacts|firstname,lastname,email|[[["firstname","a","Tom"]]]||5)$', |
||||||
42 | 'LBL_RECORDS_LIST' => '$(recordsList : Contacts|firstname,lastname,email|[[["firstname","a","Tom"]]]||5)$', |
||||||
43 | 'LBL_INVENTORY_TABLE' => '$(inventory : type=table columns=seq,name,qty,unit,price,total,net href=no)$', |
||||||
44 | 'LBL_DYNAMIC_INVENTORY_TABLE' => '$(custom : dynamicInventoryColumnsTable)$', |
||||||
45 | 'LBL_BARCODE' => '$(barcode : type=EAN13 class=DNS1D , value=12345678)$', |
||||||
46 | ]; |
||||||
47 | |||||||
48 | /** |
||||||
49 | * Default date list. |
||||||
50 | * |
||||||
51 | * @var string[] |
||||||
52 | */ |
||||||
53 | public static $variableDates = [ |
||||||
54 | 'LBL_DATE_TODAY' => '$(date : now)$', |
||||||
55 | 'LBL_DATE_TOMORROW' => '$(date : tomorrow)$', |
||||||
56 | 'LBL_DATE_YESTERDAY' => '$(date : yesterday)$', |
||||||
57 | 'LBL_DATE_FIRST_DAY_OF_THIS_WEEK' => '$(date : monday this week)$', |
||||||
58 | 'LBL_DATE_MONDAY_NEXT_WEEK' => '$(date : monday next week)$', |
||||||
59 | 'LBL_DATE_FIRST_DAY_OF_THIS_MONTH' => '$(date : first day of this month)$', |
||||||
60 | 'LBL_DATE_LAST_DAY_OF_THIS_MONTH' => '$(date : last day of this month)$', |
||||||
61 | 'LBL_DATE_FIRST_DAY_OF_NEXT_MONTH' => '$(date : first day of next month)$', |
||||||
62 | ]; |
||||||
63 | |||||||
64 | /** |
||||||
65 | * Variables for entity modules. |
||||||
66 | * |
||||||
67 | * @var array |
||||||
68 | */ |
||||||
69 | public static $variableGeneral = [ |
||||||
70 | 'LBL_CURRENT_DATE' => '$(general : CurrentDate)$', |
||||||
71 | 'LBL_CURRENT_TIME' => '$(general : CurrentTime)$', |
||||||
72 | 'LBL_BASE_TIMEZONE' => '$(general : BaseTimeZone)$', |
||||||
73 | 'LBL_USER_TIMEZONE' => '$(general : UserTimeZone)$', |
||||||
74 | 'LBL_SITE_URL' => '$(general : SiteUrl)$', |
||||||
75 | 'LBL_PORTAL_URL' => '$(general : PortalUrl)$', |
||||||
76 | 'LBL_TRANSLATE' => '$(translate : Accounts|LBL_COPY_BILLING_ADDRESS)$, $(translate : LBL_SECONDS)$', |
||||||
77 | ]; |
||||||
78 | |||||||
79 | /** |
||||||
80 | * Variables for entity modules. |
||||||
81 | * |
||||||
82 | * @var array |
||||||
83 | */ |
||||||
84 | public static $variableEntity = [ |
||||||
85 | 'CrmDetailViewURL' => 'LBL_CRM_DETAIL_VIEW_URL', |
||||||
86 | 'PortalDetailViewURL' => 'LBL_PORTAL_DETAIL_VIEW_URL', |
||||||
87 | 'RecordId' => 'LBL_RECORD_ID', |
||||||
88 | 'RecordLabel' => 'LBL_RECORD_LABEL', |
||||||
89 | 'ChangesListChanges' => 'LBL_LIST_OF_CHANGES_IN_RECORD', |
||||||
90 | 'ChangesListValues' => 'LBL_LIST_OF_NEW_VALUES_IN_RECORD', |
||||||
91 | 'Comments' => 'LBL_RECORD_COMMENT', |
||||||
92 | 'SummaryFields' => 'LBL_SUMMARY_FIELDS', |
||||||
93 | ]; |
||||||
94 | |||||||
95 | /** |
||||||
96 | * List of available functions. |
||||||
97 | * |
||||||
98 | * @var string[] |
||||||
99 | */ |
||||||
100 | protected static $baseFunctions = ['general', 'translate', 'record', 'relatedRecord', 'relatedRecordLevel', 'sourceRecord', 'organization', 'employee', 'params', 'custom', 'relatedRecordsList', 'recordsList', 'date', 'inventory', 'userVariable', 'barcode']; |
||||||
101 | |||||||
102 | /** |
||||||
103 | * List of source modules. |
||||||
104 | * |
||||||
105 | * @var array |
||||||
106 | */ |
||||||
107 | public static $sourceModules = [ |
||||||
108 | 'Campaigns' => ['Leads', 'Accounts', 'Contacts', 'Vendors', 'Partners', 'Competition'], |
||||||
109 | ]; |
||||||
110 | /** |
||||||
111 | * Record variables. |
||||||
112 | * |
||||||
113 | * @var array |
||||||
114 | */ |
||||||
115 | protected static $recordVariable = []; |
||||||
116 | /** |
||||||
117 | * Related variables. |
||||||
118 | * |
||||||
119 | * @var array |
||||||
120 | */ |
||||||
121 | protected static $relatedVariable = []; |
||||||
122 | /** |
||||||
123 | * Next level related variables. |
||||||
124 | * |
||||||
125 | * @var array |
||||||
126 | */ |
||||||
127 | protected static $relatedVariableLevel = []; |
||||||
128 | |||||||
129 | /** |
||||||
130 | * Record id. |
||||||
131 | * |
||||||
132 | * @var int |
||||||
133 | */ |
||||||
134 | public $record; |
||||||
135 | |||||||
136 | /** |
||||||
137 | * Module name. |
||||||
138 | * |
||||||
139 | * @var string |
||||||
140 | */ |
||||||
141 | public $moduleName; |
||||||
142 | |||||||
143 | /** |
||||||
144 | * Record model. |
||||||
145 | * |
||||||
146 | * @var \Vtiger_Record_Model |
||||||
147 | */ |
||||||
148 | public $recordModel; |
||||||
149 | |||||||
150 | /** |
||||||
151 | * Parser type. |
||||||
152 | * |
||||||
153 | * @var string|null |
||||||
154 | */ |
||||||
155 | public $type; |
||||||
156 | |||||||
157 | /** |
||||||
158 | * Source record model. |
||||||
159 | * |
||||||
160 | * @var \Vtiger_Record_Model |
||||||
161 | */ |
||||||
162 | protected $sourceRecordModel; |
||||||
163 | |||||||
164 | /** |
||||||
165 | * Content. |
||||||
166 | * |
||||||
167 | * @var string |
||||||
168 | */ |
||||||
169 | protected $content = ''; |
||||||
170 | |||||||
171 | /** |
||||||
172 | * Rwa content. |
||||||
173 | * |
||||||
174 | * @var string |
||||||
175 | */ |
||||||
176 | protected $rawContent; |
||||||
177 | |||||||
178 | /** |
||||||
179 | * without translations. |
||||||
180 | * |
||||||
181 | * @var bool |
||||||
182 | */ |
||||||
183 | protected $withoutTranslations = false; |
||||||
184 | |||||||
185 | /** |
||||||
186 | * Language content. |
||||||
187 | * |
||||||
188 | * @var string |
||||||
189 | */ |
||||||
190 | protected $language; |
||||||
191 | |||||||
192 | /** |
||||||
193 | * Additional params. |
||||||
194 | * |
||||||
195 | * @var array |
||||||
196 | */ |
||||||
197 | protected $params; |
||||||
198 | |||||||
199 | /** |
||||||
200 | * Separator to display data when there are several values. |
||||||
201 | * |
||||||
202 | * @var string |
||||||
203 | */ |
||||||
204 | 4 | public $relatedRecordSeparator = ','; |
|||||
205 | |||||||
206 | 4 | /** |
|||||
207 | 4 | * Is the parsing text content html? |
|||||
208 | 4 | * |
|||||
209 | 4 | * @var bool |
|||||
210 | 4 | */ |
|||||
211 | 4 | public $isHtml = true; |
|||||
212 | |||||||
213 | /** |
||||||
214 | * Use extended parsing. |
||||||
215 | * |
||||||
216 | * @var bool |
||||||
217 | */ |
||||||
218 | public $useExtension = false; |
||||||
219 | |||||||
220 | /** |
||||||
221 | 7 | * Variable parser regex. |
|||||
222 | * |
||||||
223 | 7 | * @var string |
|||||
224 | 7 | */ |
|||||
225 | 7 | public const VARIABLE_REGEX = '/\$\((\w+) : ([,"\+\#\%\.\:\;\=\-\[\]\&\w\s\|\)\(\:]+)\)\$/u'; |
|||||
226 | 7 | ||||||
227 | 7 | /** @var bool Permissions condition */ |
|||||
228 | 7 | protected $permissions = true; |
|||||
229 | |||||||
230 | /** @var string[] Uitypes with large data */ |
||||||
231 | protected $largeDataUiTypes = ['multiImage', 'image']; |
||||||
232 | |||||||
233 | /** |
||||||
234 | * Get instanace by record id. |
||||||
235 | * |
||||||
236 | * @param int $record Record id |
||||||
237 | * @param string $moduleName Module name |
||||||
238 | 8 | * |
|||||
239 | * @return \self |
||||||
0 ignored issues
–
show
|
|||||||
240 | 8 | */ |
|||||
241 | 8 | public static function getInstanceById(int $record, ?string $moduleName = null) |
|||||
242 | 8 | { |
|||||
243 | 4 | $class = static::class; |
|||||
244 | $instance = new $class(); |
||||||
245 | 8 | $instance->record = $record; |
|||||
246 | $instance->recordModel = \Vtiger_Record_Model::getInstanceById($record, $moduleName); |
||||||
247 | $instance->moduleName = $instance->recordModel->getModuleName(); |
||||||
248 | return $instance; |
||||||
0 ignored issues
–
show
|
|||||||
249 | } |
||||||
250 | |||||||
251 | /** |
||||||
252 | * Get instanace by record model. |
||||||
253 | * |
||||||
254 | * @param \Vtiger_Record_Model $recordModel |
||||||
255 | 4 | * |
|||||
256 | * @return \self |
||||||
257 | 4 | */ |
|||||
258 | 4 | public static function getInstanceByModel(\Vtiger_Record_Model $recordModel) |
|||||
259 | { |
||||||
260 | $class = static::class; |
||||||
261 | $instance = new $class(); |
||||||
262 | $instance->record = $recordModel->getId(); |
||||||
263 | $instance->moduleName = $recordModel->getModuleName(); |
||||||
264 | $instance->recordModel = $recordModel; |
||||||
265 | return $instance; |
||||||
0 ignored issues
–
show
|
|||||||
266 | } |
||||||
267 | |||||||
268 | 2 | /** |
|||||
269 | * Get clean instanace. |
||||||
270 | 2 | * |
|||||
271 | 2 | * @param string $moduleName Module name |
|||||
272 | * |
||||||
273 | * @return \self |
||||||
274 | */ |
||||||
275 | public static function getInstance($moduleName = '') |
||||||
276 | { |
||||||
277 | $class = static::class; |
||||||
278 | $instance = new $class(); |
||||||
279 | if ($moduleName) { |
||||||
280 | $instance->moduleName = $moduleName; |
||||||
281 | 1 | } |
|||||
282 | return $instance; |
||||||
0 ignored issues
–
show
|
|||||||
283 | 1 | } |
|||||
284 | 1 | ||||||
285 | /** |
||||||
286 | * Set the active state of extended parsing functionality. |
||||||
287 | * |
||||||
288 | * @param bool $state |
||||||
289 | * |
||||||
290 | * @return $this |
||||||
291 | */ |
||||||
292 | public function setExtensionState(bool $state) |
||||||
293 | { |
||||||
294 | 3 | $this->useExtension = $state; |
|||||
295 | return $this; |
||||||
296 | 3 | } |
|||||
297 | 3 | ||||||
298 | /** |
||||||
299 | * Set without translations. |
||||||
300 | * |
||||||
301 | * @param string $type |
||||||
302 | * |
||||||
303 | * @return $this |
||||||
304 | */ |
||||||
305 | public function withoutTranslations($type = true) |
||||||
306 | { |
||||||
307 | 1 | $this->withoutTranslations = $type; |
|||||
0 ignored issues
–
show
It seems like
$type can also be of type string . However, the property $withoutTranslations is declared as type boolean . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||||||
308 | return $this; |
||||||
309 | 1 | } |
|||||
310 | |||||||
311 | /** |
||||||
312 | * Set language. |
||||||
313 | * |
||||||
314 | * @param string $name |
||||||
315 | * |
||||||
316 | * @return $this |
||||||
317 | */ |
||||||
318 | public function setLanguage($name = true) |
||||||
319 | { |
||||||
320 | $this->language = $name; |
||||||
0 ignored issues
–
show
It seems like
$name can also be of type true . However, the property $language is declared as type string . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||||||
321 | 2 | return $this; |
|||||
322 | } |
||||||
323 | 2 | ||||||
324 | 2 | /** |
|||||
325 | * Set parser type. |
||||||
326 | * |
||||||
327 | * @param string $type |
||||||
328 | * |
||||||
329 | * @return $this |
||||||
330 | */ |
||||||
331 | public function setType($type) |
||||||
332 | { |
||||||
333 | $this->type = $type; |
||||||
334 | 19 | return $this; |
|||||
335 | } |
||||||
336 | 19 | ||||||
337 | 19 | /** |
|||||
338 | * Set additional params. |
||||||
339 | * |
||||||
340 | * @param array $params |
||||||
341 | * |
||||||
342 | * @return $this |
||||||
343 | */ |
||||||
344 | public function setParams($params) |
||||||
345 | 16 | { |
|||||
346 | $this->params = $params; |
||||||
347 | 16 | return $this; |
|||||
348 | } |
||||||
349 | |||||||
350 | /** |
||||||
351 | * Set param value. |
||||||
352 | * |
||||||
353 | * @param string $key |
||||||
354 | * @param mixed $value |
||||||
355 | * |
||||||
356 | * @return $this |
||||||
357 | 22 | */ |
|||||
358 | public function setParam(string $key, $value) |
||||||
359 | 22 | { |
|||||
360 | $this->params[$key] = $value; |
||||||
361 | return $this; |
||||||
362 | } |
||||||
363 | |||||||
364 | /** |
||||||
365 | * Get additional params. |
||||||
366 | * |
||||||
367 | 19 | * @param string $key |
|||||
368 | * |
||||||
369 | 19 | * @return mixed |
|||||
370 | 2 | */ |
|||||
371 | public function getParam(string $key) |
||||||
372 | 17 | { |
|||||
373 | 3 | return $this->params[$key] ?? null; |
|||||
374 | } |
||||||
375 | |||||||
376 | 15 | /** |
|||||
377 | 15 | * Set source record. |
|||||
378 | 14 | * |
|||||
379 | * @param int $record |
||||||
380 | 1 | * @param bool|string $moduleName |
|||||
381 | 17 | * @param mixed $recordModel |
|||||
382 | 17 | * |
|||||
383 | 17 | * @return $this |
|||||
384 | */ |
||||||
385 | public function setSourceRecord($record, $moduleName = false, $recordModel = false) |
||||||
386 | { |
||||||
387 | $this->sourceRecordModel = $recordModel ?: \Vtiger_Record_Model::getInstanceById($record, $moduleName ?: Record::getType($record)); |
||||||
388 | return $this; |
||||||
389 | } |
||||||
390 | |||||||
391 | 2 | /** |
|||||
392 | * Set content. |
||||||
393 | 2 | * |
|||||
394 | 1 | * @param string $content |
|||||
395 | * |
||||||
396 | * @return $this |
||||||
397 | 1 | */ |
|||||
398 | 1 | public function setContent($content) |
|||||
399 | 2 | { |
|||||
400 | 2 | $this->rawContent = $this->content = str_replace(['%20%3A%20', '%20:%20'], ' : ', $content); |
|||||
401 | 2 | return $this; |
|||||
402 | } |
||||||
403 | |||||||
404 | /** |
||||||
405 | * Get content. |
||||||
406 | * |
||||||
407 | * @param mixed $trim |
||||||
408 | */ |
||||||
409 | public function getContent($trim = false) |
||||||
410 | { |
||||||
411 | 1 | return $trim ? trim($this->content) : $this->content; |
|||||
412 | } |
||||||
413 | 1 | ||||||
414 | 1 | /** |
|||||
415 | * Function checks if its TextParser type. |
||||||
416 | * |
||||||
417 | * @param string $text |
||||||
418 | * |
||||||
419 | * @return int |
||||||
420 | */ |
||||||
421 | public static function isVaribleToParse($text) |
||||||
422 | { |
||||||
423 | return (int) preg_match(static::VARIABLE_REGEX, $text); |
||||||
424 | 1 | } |
|||||
425 | |||||||
426 | 1 | /** |
|||||
427 | 1 | * Set permissions condition. |
|||||
428 | * |
||||||
429 | 1 | * @param bool $permitted |
|||||
430 | 1 | * |
|||||
431 | * @return $this |
||||||
432 | 1 | */ |
|||||
433 | 1 | public function setGlobalPermissions(bool $permitted) |
|||||
434 | 1 | { |
|||||
435 | $this->permissions = $permitted; |
||||||
436 | return $this; |
||||||
437 | } |
||||||
438 | |||||||
439 | /** |
||||||
440 | * All text parse function. |
||||||
441 | * |
||||||
442 | * @return $this |
||||||
443 | */ |
||||||
444 | public function parse() |
||||||
445 | { |
||||||
446 | if (empty($this->content)) { |
||||||
447 | return $this; |
||||||
448 | } |
||||||
449 | if (isset($this->language)) { |
||||||
450 | Language::setTemporaryLanguage($this->language); |
||||||
451 | } |
||||||
452 | $this->content = $this->parseData($this->content); |
||||||
453 | Language::clearTemporaryLanguage(); |
||||||
454 | return $this; |
||||||
455 | } |
||||||
456 | |||||||
457 | /** |
||||||
458 | * Text parse function. |
||||||
459 | * |
||||||
460 | * @param string $content |
||||||
461 | * |
||||||
462 | * @return string |
||||||
463 | */ |
||||||
464 | public function parseData(string $content) |
||||||
465 | { |
||||||
466 | if ($this->useExtension) { |
||||||
467 | $content = preg_replace_callback('/<!--[\s]+({% [\s\S]+? %})[\s]+-->/u', fn ($matches) => $matches[1] ?? '', $content); |
||||||
468 | $twig = new \Twig\Environment(new \Twig\Loader\ArrayLoader(['index' => $content])); |
||||||
469 | $sandbox = new \Twig\Extension\SandboxExtension(\App\Extension\Twig\SecurityPolicy::getPolicy(), true); |
||||||
470 | $twig->addExtension($sandbox); |
||||||
471 | $twig->addFunction(new \Twig\TwigFunction('YFParser', function ($text) { |
||||||
472 | $value = ''; |
||||||
473 | preg_match(static::VARIABLE_REGEX, $text, $matches); |
||||||
474 | 2 | if ($matches) { |
|||||
475 | [, $function, $params] = array_pad($matches, 3, ''); |
||||||
476 | 2 | $value = \in_array($function, static::$baseFunctions) ? $this->{$function}($params) : ''; |
|||||
477 | 2 | } |
|||||
478 | 2 | return $value; |
|||||
479 | })); |
||||||
480 | 2 | $content = $twig->render('index'); |
|||||
481 | } |
||||||
482 | return preg_replace_callback(static::VARIABLE_REGEX, function ($matches) { |
||||||
483 | 2 | [, $function, $params] = array_pad($matches, 3, ''); |
|||||
484 | 2 | return \in_array($function, static::$baseFunctions) ? $this->{$function}($params) : ''; |
|||||
485 | 2 | }, $content); |
|||||
486 | } |
||||||
487 | 2 | ||||||
488 | 2 | /** |
|||||
489 | 1 | * Text parse function. |
|||||
490 | 1 | * |
|||||
491 | 1 | * @return $this |
|||||
492 | 1 | */ |
|||||
493 | 1 | public function parseTranslations() |
|||||
494 | { |
||||||
495 | if (isset($this->language)) { |
||||||
496 | 1 | Language::setTemporaryLanguage($this->language); |
|||||
497 | } |
||||||
498 | 2 | $this->content = preg_replace_callback('/\$\(translate : ([,"\+\%\.\=\-\[\]\&\w\s\|]+)\)\$/u', function ($matches) { |
|||||
499 | 2 | [, $params] = array_pad($matches, 2, ''); |
|||||
500 | return $this->translate($params); |
||||||
501 | }, $this->content); |
||||||
502 | Language::clearTemporaryLanguage(); |
||||||
503 | return $this; |
||||||
504 | } |
||||||
505 | |||||||
506 | /** |
||||||
507 | * Function parse date. |
||||||
508 | * |
||||||
509 | 1 | * @param string $param |
|||||
510 | * |
||||||
511 | 1 | * @return string |
|||||
512 | 1 | */ |
|||||
513 | 1 | public function date($param) |
|||||
514 | 1 | { |
|||||
515 | 1 | if (isset(\App\Condition::DATE_OPERATORS[$param])) { |
|||||
516 | 1 | $date = implode(' - ', array_unique(\DateTimeRange::getDateRangeByType($param))); |
|||||
517 | } else { |
||||||
518 | 1 | $date = date('Y-m-d', strtotime($param)); |
|||||
519 | 1 | } |
|||||
520 | 1 | return $date; |
|||||
521 | 1 | } |
|||||
522 | 1 | ||||||
523 | 1 | /** |
|||||
524 | 1 | * Parsing translations. |
|||||
525 | 1 | * |
|||||
526 | 1 | * @param string $params |
|||||
527 | * |
||||||
528 | 1 | * @return string |
|||||
529 | */ |
||||||
530 | protected function translate($params) |
||||||
531 | { |
||||||
532 | if ($this->withoutTranslations) { |
||||||
533 | return "$(translate : $params)$"; |
||||||
534 | } |
||||||
535 | if (false === strpos($params, '|')) { |
||||||
536 | return Language::translate($params); |
||||||
537 | } |
||||||
538 | $splitParams = explode('|', $params); |
||||||
539 | $module = array_shift($splitParams); |
||||||
540 | 5 | $key = array_shift($splitParams); |
|||||
541 | return Language::translate($key, $module, $splitParams[0] ?? $this->language); |
||||||
542 | 5 | } |
|||||
543 | 1 | ||||||
544 | /** |
||||||
545 | 5 | * Parsing organization detail. |
|||||
546 | 5 | * |
|||||
547 | 5 | * @param string $params |
|||||
548 | 5 | * |
|||||
549 | 1 | * @return string |
|||||
550 | */ |
||||||
551 | 5 | protected function organization(string $params): string |
|||||
552 | { |
||||||
553 | 1 | if (!$params) { |
|||||
554 | 1 | return ''; |
|||||
555 | 1 | } |
|||||
556 | 1 | $returnVal = ''; |
|||||
557 | 1 | if (false === strpos($params, '|')) { |
|||||
558 | 1 | $id = User::getCurrentUserModel()->get('multiCompanyId'); |
|||||
559 | $fieldName = $params; |
||||||
560 | 1 | $params = false; |
|||||
561 | } else { |
||||||
562 | 1 | [$id, $fieldName, $params] = array_pad(explode('|', $params, 3), 3, false); |
|||||
563 | } |
||||||
564 | if (Record::isExists($id, 'MultiCompany')) { |
||||||
565 | 1 | $companyRecordModel = \Vtiger_Record_Model::getInstanceById($id, 'MultiCompany'); |
|||||
566 | 1 | if ($companyRecordModel->has($fieldName)) { |
|||||
567 | 1 | $value = $companyRecordModel->get($fieldName); |
|||||
568 | 1 | $fieldModel = $companyRecordModel->getModule()->getFieldByName($fieldName); |
|||||
569 | 1 | if ('' === $value || !$fieldModel || !$this->useValue($fieldModel, 'MultiCompany')) { |
|||||
570 | 1 | return ''; |
|||||
571 | 1 | } |
|||||
572 | 1 | if ($this->withoutTranslations) { |
|||||
573 | 1 | $returnVal = $this->getDisplayValueByType($value, $companyRecordModel, $fieldModel, $params); |
|||||
574 | 1 | } else { |
|||||
575 | 1 | $returnVal = $fieldModel->getUITypeModel()->getTextParserDisplayValue($value, $companyRecordModel, $params); |
|||||
576 | 1 | } |
|||||
577 | } |
||||||
578 | } |
||||||
579 | 1 | return $returnVal; |
|||||
580 | 1 | } |
|||||
581 | 1 | ||||||
582 | 1 | /** |
|||||
583 | * Parsing employee detail. |
||||||
584 | 1 | * |
|||||
585 | 1 | * @param string $fieldName |
|||||
586 | * |
||||||
587 | * @return mixed |
||||||
588 | 1 | */ |
|||||
589 | 1 | protected function employee($fieldName) |
|||||
590 | 1 | { |
|||||
591 | 1 | $userId = User::getCurrentUserId(); |
|||||
592 | 1 | if (Cache::has('TextParserEmployeeDetail', $userId . $fieldName)) { |
|||||
593 | 1 | return Cache::get('TextParserEmployeeDetail', $userId . $fieldName); |
|||||
594 | 1 | } |
|||||
595 | if (Cache::has('TextParserEmployeeDetailRows', $userId)) { |
||||||
596 | 1 | $employee = Cache::get('TextParserEmployeeDetailRows', $userId); |
|||||
597 | 1 | } else { |
|||||
598 | 1 | $employee = (new Db\Query())->select(['crmid'])->from('vtiger_crmentity')->where(['deleted' => 0, 'setype' => 'OSSEmployees', 'smownerid' => $userId]) |
|||||
599 | ->scalar(); |
||||||
600 | Cache::save('TextParserEmployeeDetailRows', $userId, $employee, Cache::LONG); |
||||||
601 | 1 | } |
|||||
602 | 1 | $value = ''; |
|||||
603 | 1 | if ($employee && Record::isExists($employee, 'OSSEmployees')) { |
|||||
604 | $relatedRecordModel = \Vtiger_Record_Model::getInstanceById($employee, 'OSSEmployees'); |
||||||
605 | 1 | $instance = static::getInstanceByModel($relatedRecordModel); |
|||||
606 | foreach (['withoutTranslations', 'language', 'emailoptout'] as $key) { |
||||||
607 | if (isset($this->{$key})) { |
||||||
608 | 1 | $instance->{$key} = $this->{$key}; |
|||||
609 | } |
||||||
610 | 1 | } |
|||||
611 | 1 | $value = $instance->record($fieldName); |
|||||
612 | } |
||||||
613 | 1 | Cache::save('TextParserEmployeeDetail', $userId . $fieldName, $value, Cache::LONG); |
|||||
614 | 1 | return $value; |
|||||
615 | } |
||||||
616 | 1 | ||||||
617 | /** |
||||||
618 | 1 | * Parsing general data. |
|||||
619 | * |
||||||
620 | * @param string $key |
||||||
621 | * |
||||||
622 | * @return mixed |
||||||
623 | */ |
||||||
624 | protected function general($key) |
||||||
625 | { |
||||||
626 | switch ($key) { |
||||||
627 | case 'CurrentDate': |
||||||
628 | 1 | return (new \DateTimeField(null))->getDisplayDate(); |
|||||
629 | case 'CurrentTime': |
||||||
630 | 1 | return \Vtiger_Util_Helper::convertTimeIntoUsersDisplayFormat(date('H:i:s')); |
|||||
631 | case 'CurrentDateTime': |
||||||
632 | 1 | return Fields\DateTime::formatToDisplay('now'); |
|||||
633 | 1 | case 'SiteUrl': |
|||||
634 | 1 | return Config::main('site_URL'); |
|||||
635 | case 'PortalUrl': |
||||||
636 | return Config::main('PORTAL_URL'); |
||||||
637 | case 'BaseTimeZone': |
||||||
638 | 1 | return Fields\DateTime::getTimeZone(); |
|||||
639 | 1 | case 'UserTimeZone': |
|||||
640 | $userModel = User::getCurrentUserModel(); |
||||||
641 | return ($userModel && $userModel->getDetail('time_zone')) ? $userModel->getDetail('time_zone') : Config::main('default_timezone'); |
||||||
642 | 1 | default: |
|||||
643 | return $key; |
||||||
644 | } |
||||||
645 | 1 | } |
|||||
646 | 1 | ||||||
647 | 1 | /** |
|||||
648 | 1 | * Parsing record data. |
|||||
649 | 1 | * |
|||||
650 | 1 | * @param string $params |
|||||
651 | 1 | * @param mixed $isPermitted |
|||||
652 | 1 | * |
|||||
653 | 1 | * @return string |
|||||
654 | */ |
||||||
655 | protected function record($params, $isPermitted = true) |
||||||
656 | { |
||||||
657 | 1 | if (!isset($this->recordModel) || ($isPermitted && !Privilege::isPermitted($this->moduleName, 'DetailView', $this->record))) { |
|||||
658 | return ''; |
||||||
659 | } |
||||||
660 | [$key, $params] = array_pad(explode('|', $params, 2), 2, false); |
||||||
661 | if ($this->recordModel->has($key)) { |
||||||
662 | $fieldModel = $this->recordModel->getModule()->getFieldByName($key); |
||||||
663 | if (!$fieldModel || !$this->useValue($fieldModel, $this->moduleName)) { |
||||||
664 | return ''; |
||||||
665 | } |
||||||
666 | return $this->getDisplayValueByField($fieldModel, false, $params); |
||||||
0 ignored issues
–
show
|
|||||||
667 | } |
||||||
668 | switch ($key) { |
||||||
669 | case 'CrmDetailViewURL': |
||||||
670 | return Config::main('site_URL') . 'index.php?module=' . $this->moduleName . '&view=Detail&record=' . $this->record; |
||||||
671 | case 'PortalDetailViewURL': |
||||||
672 | $recorIdName = 'id'; |
||||||
673 | if ('HelpDesk' === $this->moduleName) { |
||||||
674 | $recorIdName = 'ticketid'; |
||||||
675 | } elseif ('Faq' === $this->moduleName) { |
||||||
676 | $recorIdName = 'faqid'; |
||||||
677 | 1 | } elseif ('Products' === $this->moduleName) { |
|||||
678 | 1 | $recorIdName = 'productid'; |
|||||
679 | } |
||||||
680 | return Config::main('PORTAL_URL') . '/index.php?module=' . $this->moduleName . '&action=index&' . $recorIdName . '=' . $this->record; |
||||||
681 | 1 | case 'ModuleName': |
|||||
682 | 1 | return $this->moduleName; |
|||||
683 | 1 | case 'RecordId': |
|||||
684 | 1 | return $this->record; |
|||||
685 | 1 | case 'RecordLabel': |
|||||
686 | return $this->recordModel->getName(); |
||||||
687 | case 'ChangesListChanges': |
||||||
688 | 1 | $value = ''; |
|||||
689 | foreach ($this->recordModel->getPreviousValue() as $fieldName => $oldValue) { |
||||||
690 | $fieldModel = $this->recordModel->getModule()->getFieldByName($fieldName); |
||||||
691 | if (!$fieldModel) { |
||||||
692 | continue; |
||||||
693 | } |
||||||
694 | $oldValue = $this->getDisplayValueByField($fieldModel, $oldValue); |
||||||
695 | $currentValue = $this->getDisplayValueByField($fieldModel); |
||||||
696 | if ($this->withoutTranslations) { |
||||||
697 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
698 | 1 | $value .= "\$(translate : {$this->moduleName}|{$label})\$ \$(translate : LBL_FROM)\$ $oldValue \$(translate : LBL_TO)\$ " . $currentValue . ($this->isHtml ? '<br>' : PHP_EOL); |
|||||
0 ignored issues
–
show
Are you sure
$currentValue of type array|string can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
699 | } else { |
||||||
700 | 1 | $value .= Language::translate($fieldModel->getFieldLabel(), $this->moduleName, $this->language) . ' '; |
|||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
701 | 1 | $value .= Language::translate('LBL_FROM') . " $oldValue " . Language::translate('LBL_TO') . " $currentValue" . ($this->isHtml ? '<br>' : PHP_EOL); |
|||||
702 | } |
||||||
703 | 1 | } |
|||||
704 | 1 | return $value; |
|||||
705 | 1 | case 'ChangesListValues': |
|||||
706 | 1 | $value = ''; |
|||||
707 | $changes = $this->recordModel->getPreviousValue(); |
||||||
708 | if (empty($changes)) { |
||||||
709 | 1 | $changes = array_filter($this->recordModel->getData()); |
|||||
710 | unset($changes['createdtime'], $changes['modifiedtime'], $changes['id'], $changes['newRecord'], $changes['modifiedby']); |
||||||
711 | } |
||||||
712 | foreach ($changes as $fieldName => $oldValue) { |
||||||
713 | $fieldModel = $this->recordModel->getModule()->getFieldByName($fieldName); |
||||||
714 | if (!$fieldModel) { |
||||||
715 | continue; |
||||||
716 | } |
||||||
717 | $currentValue = \in_array($fieldModel->getFieldDataType(), $this->largeDataUiTypes) ? '' : $this->getDisplayValueByField($fieldModel); |
||||||
718 | if ($this->withoutTranslations) { |
||||||
719 | 1 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
|||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
720 | $value .= "\$(translate : {$this->moduleName}|{$label})\$: $currentValue" . ($this->isHtml ? '<br>' : PHP_EOL); |
||||||
721 | 1 | } else { |
|||||
722 | 1 | $value .= Language::translate($fieldModel->getFieldLabel(), $this->moduleName, $this->language) . ": $currentValue" . ($this->isHtml ? '<br>' : PHP_EOL); |
|||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
723 | 1 | } |
|||||
724 | 1 | } |
|||||
725 | return $value; |
||||||
726 | 1 | case 'SummaryFields': |
|||||
727 | 1 | $value = ''; |
|||||
728 | 1 | $recordStructure = \Vtiger_RecordStructure_Model::getInstanceFromRecordModel($this->recordModel, \Vtiger_RecordStructure_Model::RECORD_STRUCTURE_MODE_SUMMARY); |
|||||
729 | $fields = $recordStructure->getStructure()['SUMMARY_FIELDS'] ?? []; |
||||||
730 | 1 | foreach ($fields as $fieldName => $fieldModel) { |
|||||
731 | 1 | $currentValue = $this->getDisplayValueByField($fieldModel); |
|||||
732 | 1 | if ($this->withoutTranslations) { |
|||||
733 | 1 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
|||||
734 | 1 | $value .= "\$(translate : {$this->moduleName}|{$label})\$: $currentValue" . ($this->isHtml ? '<br>' : PHP_EOL); |
|||||
735 | } else { |
||||||
736 | 1 | $value .= Language::translate($fieldModel->getFieldLabel(), $this->moduleName, $this->language) . ": $currentValue" . ($this->isHtml ? '<br>' : PHP_EOL); |
|||||
737 | 1 | } |
|||||
738 | } |
||||||
739 | return $value; |
||||||
740 | 1 | default: |
|||||
741 | 1 | if (false !== strpos($key, ' ')) { |
|||||
742 | [$key, $params] = explode(' ', $key); |
||||||
743 | } |
||||||
744 | 1 | if ('Comments' === $key) { |
|||||
745 | 1 | return $this->getComments($params); |
|||||
746 | } |
||||||
747 | 1 | break; |
|||||
748 | 1 | } |
|||||
749 | 1 | return ''; |
|||||
750 | } |
||||||
751 | 1 | ||||||
752 | 1 | /** |
|||||
753 | 1 | * Parsing related record data. |
|||||
754 | 1 | * |
|||||
755 | 1 | * @param string $params |
|||||
756 | 1 | * |
|||||
757 | * @return mixed |
||||||
758 | */ |
||||||
759 | protected function relatedRecord($params) |
||||||
760 | { |
||||||
761 | $params = explode('|', $params); |
||||||
762 | 1 | $fieldName = array_shift($params); |
|||||
763 | 1 | $relatedField = array_shift($params); |
|||||
764 | 1 | $relatedModule = array_shift($params); |
|||||
765 | 1 | $value = $params ? $relatedField . '|' . implode('|', $params) : $relatedField; |
|||||
766 | 1 | if ( |
|||||
767 | 1 | !isset($this->recordModel) |
|||||
768 | 1 | || ($this->permissions && !Privilege::isPermitted($this->moduleName, 'DetailView', $this->record)) |
|||||
769 | 1 | || $this->recordModel->isEmpty($fieldName) |
|||||
770 | ) { |
||||||
771 | return ''; |
||||||
772 | 1 | } |
|||||
773 | $relatedId = $this->recordModel->get($fieldName); |
||||||
774 | if (empty($relatedId)) { |
||||||
775 | 1 | return ''; |
|||||
776 | } |
||||||
777 | 1 | if (empty($relatedModule) && \in_array($this->recordModel->getField($fieldName)->getFieldDataType(), ['owner', 'sharedOwner'])) { |
|||||
778 | $relatedModule = 'Users'; |
||||||
779 | } |
||||||
780 | if ('Users' === $relatedModule) { |
||||||
781 | $return = []; |
||||||
782 | foreach (explode(',', $relatedId) as $relatedValueId) { |
||||||
783 | if ('Users' === Fields\Owner::getType($relatedValueId)) { |
||||||
0 ignored issues
–
show
$relatedValueId of type string is incompatible with the type integer expected by parameter $id of App\Fields\Owner::getType() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
784 | $userRecordModel = \Vtiger_Record_Model::getInstanceById($relatedValueId, $relatedModule); |
||||||
0 ignored issues
–
show
$relatedValueId of type string is incompatible with the type integer expected by parameter $recordId of Vtiger_Record_Model::getInstanceById() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
785 | if ('Active' === $userRecordModel->get('status')) { |
||||||
786 | $instance = static::getInstanceByModel($userRecordModel); |
||||||
787 | 1 | foreach (['withoutTranslations', 'language', 'emailoptout'] as $key) { |
|||||
788 | if (isset($this->{$key})) { |
||||||
789 | 1 | $instance->{$key} = $this->{$key}; |
|||||
790 | 1 | } |
|||||
791 | 1 | } |
|||||
792 | 1 | $return[] = $instance->record($value, false); |
|||||
793 | 1 | } |
|||||
794 | 1 | continue; |
|||||
795 | 1 | } |
|||||
796 | foreach (PrivilegeUtil::getUsersByGroup($relatedValueId) as $userId) { |
||||||
0 ignored issues
–
show
$relatedValueId of type string is incompatible with the type integer expected by parameter $groupId of App\PrivilegeUtil::getUsersByGroup() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
797 | 1 | $userRecordModel = \Vtiger_Record_Model::getInstanceById($userId, $relatedModule); |
|||||
798 | 1 | if ('Active' === $userRecordModel->get('status')) { |
|||||
799 | $instance = static::getInstanceByModel($userRecordModel); |
||||||
800 | foreach (['withoutTranslations', 'language', 'emailoptout'] as $key) { |
||||||
801 | 1 | if (isset($this->{$key})) { |
|||||
802 | 1 | $instance->{$key} = $this->{$key}; |
|||||
803 | } |
||||||
804 | } |
||||||
805 | 1 | $return[] = $instance->record($value, false); |
|||||
806 | 1 | } |
|||||
807 | 1 | } |
|||||
808 | 1 | } |
|||||
809 | return implode($this->relatedRecordSeparator, $return); |
||||||
810 | 1 | } |
|||||
811 | 1 | $module = Record::getType($relatedId); |
|||||
812 | 1 | if (!Record::isExists($relatedId) || empty($module) || ($relatedModule && $relatedModule !== $module)) { |
|||||
813 | 1 | return ''; |
|||||
814 | 1 | } |
|||||
815 | 1 | $relatedRecordModel = \Vtiger_Record_Model::getInstanceById($relatedId, $module); |
|||||
816 | if ($this->permissions && !$relatedRecordModel->isViewable()) { |
||||||
817 | return ''; |
||||||
818 | 1 | } |
|||||
819 | 1 | $instance = static::getInstanceByModel($relatedRecordModel); |
|||||
820 | 1 | foreach (['withoutTranslations', 'language', 'emailoptout'] as $key) { |
|||||
821 | if (isset($this->{$key})) { |
||||||
822 | 1 | $instance->{$key} = $this->{$key}; |
|||||
823 | 1 | } |
|||||
824 | 1 | } |
|||||
825 | return $instance->record($value); |
||||||
826 | 1 | } |
|||||
827 | 1 | ||||||
828 | 1 | /** |
|||||
829 | 1 | * Parsing related record data. |
|||||
830 | 1 | * |
|||||
831 | * @param string $params |
||||||
832 | 1 | * |
|||||
833 | * @return mixed |
||||||
834 | */ |
||||||
835 | 1 | protected function relatedRecordLevel($params) |
|||||
836 | 1 | { |
|||||
837 | 1 | [$fieldName, $relatedModule, $relatedRecord] = array_pad(explode('|', $params, 3), 3, ''); |
|||||
838 | 1 | if ( |
|||||
839 | 1 | !isset($this->recordModel) |
|||||
840 | 1 | || !Privilege::isPermitted($this->moduleName, 'DetailView', $this->record) |
|||||
841 | 1 | || $this->recordModel->isEmpty($fieldName) |
|||||
842 | 1 | ) { |
|||||
843 | return ''; |
||||||
844 | } |
||||||
845 | 1 | $relatedId = $this->recordModel->get($fieldName); |
|||||
846 | if (empty($relatedId)) { |
||||||
847 | return ''; |
||||||
848 | 1 | } |
|||||
849 | $moduleName = Record::getType($relatedId); |
||||||
850 | 1 | if (!empty($moduleName) && ($relatedModule && $relatedModule !== $moduleName)) { |
|||||
851 | return ''; |
||||||
852 | } |
||||||
853 | if ('Users' === $relatedModule && 'Users' === Fields\Owner::getType($relatedId)) { |
||||||
0 ignored issues
–
show
|
|||||||
854 | $relatedRecordModel = \Users_Privileges_Model::getInstanceById($relatedId); |
||||||
855 | if ('Active' !== $relatedRecordModel->get('status')) { |
||||||
856 | return ''; |
||||||
857 | } |
||||||
858 | } else { |
||||||
859 | $relatedRecordModel = \Vtiger_Record_Model::getInstanceById($relatedId, $moduleName); |
||||||
860 | if (!$relatedRecordModel->isViewable()) { |
||||||
861 | return ''; |
||||||
862 | 7 | } |
|||||
863 | } |
||||||
864 | 7 | $instance = static::getInstanceByModel($relatedRecordModel); |
|||||
865 | 7 | foreach (['withoutTranslations', 'language', 'emailoptout'] as $key) { |
|||||
866 | 5 | if (isset($this->{$key})) { |
|||||
867 | 5 | $instance->{$key} = $this->{$key}; |
|||||
868 | } |
||||||
869 | } |
||||||
870 | 3 | return $instance->relatedRecord($relatedRecord); |
|||||
871 | 2 | } |
|||||
872 | 2 | ||||||
873 | 2 | /** |
|||||
874 | * Parsing source record data. |
||||||
875 | * |
||||||
876 | * @param string $fieldName |
||||||
877 | 7 | * |
|||||
878 | 1 | * @return mixed |
|||||
879 | */ |
||||||
880 | 7 | protected function sourceRecord($fieldName) |
|||||
881 | 3 | { |
|||||
882 | if (empty($this->sourceRecordModel) || !Privilege::isPermitted($this->sourceRecordModel->getModuleName(), 'DetailView', $this->sourceRecordModel->getId())) { |
||||||
883 | 6 | return ''; |
|||||
884 | } |
||||||
885 | $instance = static::getInstanceByModel($this->sourceRecordModel); |
||||||
886 | foreach (['withoutTranslations', 'language', 'emailoptout'] as $key) { |
||||||
887 | if (isset($this->{$key})) { |
||||||
888 | $instance->{$key} = $this->{$key}; |
||||||
889 | } |
||||||
890 | } |
||||||
891 | return $instance->record($fieldName); |
||||||
892 | } |
||||||
893 | |||||||
894 | /** |
||||||
895 | * Parsing related records list. |
||||||
896 | 3 | * |
|||||
897 | * @param string $params Parameter construction: RelatedModuleNameOrRelationId|Columns|Conditions|CustomViewIdOrName|Limit, Example: Contacts|firstname,lastname,modifiedtime|[[["firstname","a","Tom"]]]||2 |
||||||
898 | 3 | * |
|||||
899 | 3 | * @return string |
|||||
900 | 1 | */ |
|||||
901 | 1 | protected function relatedRecordsList($params) |
|||||
902 | 1 | { |
|||||
903 | 3 | [$relatedModuleName, $columns, $conditions, $viewIdOrName, $limit, $maxLength] = array_pad(explode('|', $params), 6, ''); |
|||||
904 | 1 | if (is_numeric($relatedModuleName)) { |
|||||
905 | 1 | if ($relationListView = \Vtiger_RelationListView_Model::getInstance($this->recordModel, '', $relatedModuleName)) { |
|||||
906 | 1 | $relatedModuleName = $relationListView->getRelatedModuleModel()->getName(); |
|||||
907 | 1 | } |
|||||
908 | 1 | } else { |
|||||
909 | $relationListView = \Vtiger_RelationListView_Model::getInstance($this->recordModel, $relatedModuleName); |
||||||
910 | 1 | } |
|||||
911 | 1 | if (!$relationListView || !Privilege::isPermitted($relatedModuleName)) { |
|||||
0 ignored issues
–
show
|
|||||||
912 | return ''; |
||||||
913 | 1 | } |
|||||
914 | 1 | $pagingModel = new \Vtiger_Paging_Model(); |
|||||
915 | 3 | $pagingModel->set('limit', (int) $limit); |
|||||
916 | 1 | if ($viewIdOrName) { |
|||||
917 | 1 | if (!is_numeric($viewIdOrName)) { |
|||||
918 | 3 | $customView = CustomView::getInstance($relatedModuleName); |
|||||
919 | if ($cvId = $customView->getViewIdByName($viewIdOrName)) { |
||||||
920 | $viewIdOrName = $cvId; |
||||||
921 | } else { |
||||||
922 | $viewIdOrName = false; |
||||||
923 | Log::warning("No view found. Module: $relatedModuleName, view name: $viewIdOrName", 'TextParser'); |
||||||
924 | } |
||||||
925 | } |
||||||
926 | if ($viewIdOrName) { |
||||||
927 | $relationListView->getQueryGenerator()->initForCustomViewById($viewIdOrName); |
||||||
928 | } |
||||||
929 | if ($cvId && ($customViewModel = \CustomView_Record_Model::getInstanceById($cvId)) && ($orderBy = $customViewModel->getSortOrderBy())) { |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
930 | $relationListView->set('orderby', $orderBy); |
||||||
931 | } |
||||||
932 | } |
||||||
933 | if ($columns) { |
||||||
934 | $relationListView->setFields($columns); |
||||||
935 | } else { |
||||||
936 | $fields = array_filter($relationListView->getHeaders(), fn ($fieldModel) => !$fieldModel->get('fromOutsideList')); |
||||||
937 | $relationListView->setFields(array_keys($fields)); |
||||||
938 | } |
||||||
939 | if ($conditions) { |
||||||
940 | $transformedSearchParams = $relationListView->getQueryGenerator()->parseBaseSearchParamsToCondition(Json::decode($conditions)); |
||||||
941 | 3 | $relationListView->set('search_params', $transformedSearchParams); |
|||||
942 | } |
||||||
943 | return $this->relatedRecordsListPrinter($relationListView, $pagingModel, (int) $maxLength); |
||||||
944 | } |
||||||
945 | |||||||
946 | /** |
||||||
947 | * Printer related records list. |
||||||
948 | * |
||||||
949 | * @param \Vtiger_RelationListView_Model $relationListView |
||||||
950 | * @param \Vtiger_Paging_Model $pagingModel |
||||||
951 | * @param int $maxLength |
||||||
952 | * |
||||||
953 | * @return string |
||||||
954 | */ |
||||||
955 | protected function relatedRecordsListPrinter(\Vtiger_RelationListView_Model $relationListView, \Vtiger_Paging_Model $pagingModel, int $maxLength): string |
||||||
956 | { |
||||||
957 | $relatedModuleName = $relationListView->getRelationModel()->getRelationModuleName(); |
||||||
958 | 3 | $rows = $headers = ''; |
|||||
959 | $fields = $relationListView->getRelationModel()->getQueryFields(); |
||||||
960 | 1 | foreach ($fields as $fieldModel) { |
|||||
961 | if ($fieldModel->isViewable() || $fieldModel->get('fromOutsideList')) { |
||||||
962 | if ($this->withoutTranslations) { |
||||||
963 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
964 | $headers .= "<th class=\"col-type-{$fieldModel->getFieldType()}\">$(translate : {$label}|$relatedModuleName)$</th>"; |
||||||
965 | } else { |
||||||
966 | $headers .= "<th class=\"col-type-{$fieldModel->getFieldType()}\">" . Language::translate($fieldModel->getFieldLabel(), $relatedModuleName) . '</th>'; |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
967 | } |
||||||
968 | } |
||||||
969 | } |
||||||
970 | 1 | $counter = 0; |
|||||
971 | foreach ($relationListView->getEntries($pagingModel) as $relatedRecordModel) { |
||||||
972 | 1 | ++$counter; |
|||||
973 | 1 | $rows .= '<tr class="row-' . $counter . '">'; |
|||||
974 | 1 | foreach ($fields as $fieldModel) { |
|||||
975 | 1 | $value = $this->getDisplayValueByField($fieldModel, $relatedRecordModel); |
|||||
976 | if (false !== $value) { |
||||||
977 | 1 | if ($maxLength) { |
|||||
978 | 1 | $value = TextUtils::textTruncate($value, $maxLength); |
|||||
979 | 1 | } |
|||||
980 | 1 | $rows .= "<td class=\"col-type-{$fieldModel->getFieldType()}\">{$value}</td>"; |
|||||
981 | 1 | } |
|||||
982 | } |
||||||
983 | $rows .= '</tr>'; |
||||||
984 | 1 | } |
|||||
985 | return empty($rows) ? '' : "<table style=\"border-collapse:collapse;width:100%\" class=\"related-records-list\"><thead><tr>{$headers}</tr></thead><tbody>{$rows}</tbody></table>"; |
||||||
986 | } |
||||||
987 | 1 | ||||||
988 | /** |
||||||
989 | * Parsing records list. |
||||||
990 | * |
||||||
991 | * @param string $params Parameter construction: ModuleName|Columns|Conditions|CustomViewIdOrName|Limit, Example: Contacts|firstname,lastname,modifiedtime|[[["firstname","a","Tom"]]]||2 |
||||||
992 | * |
||||||
993 | * @return string |
||||||
994 | */ |
||||||
995 | protected function recordsList($params) |
||||||
996 | { |
||||||
997 | [$moduleName, $columns, $conditions, $viewIdOrName, $limit, $maxLength, $params] = array_pad(explode('|', $params, 7), 7, ''); |
||||||
998 | 4 | $paramsArray = $params ? self::parseFieldParam($params) : []; |
|||||
999 | $cvId = 0; |
||||||
1000 | 4 | if ($viewIdOrName) { |
|||||
1001 | if (!is_numeric($viewIdOrName)) { |
||||||
1002 | $customView = CustomView::getInstance($moduleName); |
||||||
1003 | if ($cvIdByName = $customView->getViewIdByName($viewIdOrName)) { |
||||||
1004 | $viewIdOrName = $cvIdByName; |
||||||
1005 | } else { |
||||||
1006 | $viewIdOrName = false; |
||||||
1007 | Log::warning("No view found. Module: $moduleName, view name: $viewIdOrName", 'TextParser'); |
||||||
1008 | } |
||||||
1009 | } |
||||||
1010 | 2 | if ($viewIdOrName) { |
|||||
1011 | $cvId = $viewIdOrName; |
||||||
1012 | 2 | } |
|||||
1013 | 2 | } |
|||||
1014 | $listView = \Vtiger_ListView_Model::getInstance($moduleName, $cvId); |
||||||
1015 | 1 | if ($cvId && ($customViewModel = \CustomView_Record_Model::getInstanceById($cvId)) && ($orderBy = $customViewModel->getSortOrderBy())) { |
|||||
1016 | $listView->set('orderby', $orderBy); |
||||||
1017 | } |
||||||
1018 | $limit = (int) $limit; |
||||||
1019 | $listView->getQueryGenerator()->setLimit((int) ($limit ?: \App\Config::main('list_max_entries_per_page', 20))); |
||||||
1020 | if ($columns) { |
||||||
1021 | $headerFields = []; |
||||||
1022 | foreach (explode(',', $columns) as $fieldName) { |
||||||
1023 | $headerFields[] = [ |
||||||
1024 | 'field_name' => $fieldName, |
||||||
1025 | 1 | 'module_name' => $moduleName, |
|||||
1026 | ]; |
||||||
1027 | 1 | } |
|||||
1028 | $listView->set('header_fields', $headerFields); |
||||||
1029 | $listView->getQueryGenerator()->setFields(explode(',', $columns)); |
||||||
1030 | $listView->getQueryGenerator()->setField('id'); |
||||||
1031 | } |
||||||
1032 | if ($conditions) { |
||||||
1033 | 1 | $transformedSearchParams = $listView->getQueryGenerator()->parseBaseSearchParamsToCondition(Json::decode($conditions)); |
|||||
1034 | 1 | $listView->set('search_params', $transformedSearchParams); |
|||||
1035 | 1 | } |
|||||
1036 | if (($pdf = $this->getParam('pdf')) && $pdf->get('module_name') === $moduleName && ($ids = $pdf->getVariable('recordsId'))) { |
||||||
1037 | 1 | $listView->getQueryGenerator()->addCondition('id', $ids, 'e', 1); |
|||||
1038 | 1 | } |
|||||
1039 | 1 | $rows = $headers = $headerStyle = $borderStyle = ''; |
|||||
1040 | 1 | $fields = $listView->getListViewHeaders(); |
|||||
1041 | 1 | if (isset($paramsArray['headerStyle']) && 'background' === $paramsArray['headerStyle']) { |
|||||
1042 | $headerStyle = 'background-color:#ddd;'; |
||||||
1043 | } |
||||||
1044 | 1 | if (isset($paramsArray['table']) && 'border' === $paramsArray['table']) { |
|||||
1045 | 1 | $borderStyle = 'border:1px solid #ddd;'; |
|||||
1046 | 1 | } |
|||||
1047 | 1 | foreach ($fields as $fieldModel) { |
|||||
1048 | 1 | if ($this->withoutTranslations) { |
|||||
1049 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1050 | $headers .= "<th class=\"col-type-{$fieldModel->getFieldType()}\" style=\"{$headerStyle}\">$(translate : {$label}|$moduleName)$</th>"; |
||||||
1051 | } else { |
||||||
1052 | 1 | $headers .= "<th class=\"col-type-{$fieldModel->getFieldType()}\" style=\"{$headerStyle}\">" . Language::translate($fieldModel->getFieldLabel(), $moduleName) . '</th>'; |
|||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1053 | 1 | } |
|||||
1054 | 1 | } |
|||||
1055 | 1 | $counter = 0; |
|||||
1056 | foreach ($listView->getAllEntries() as $relatedRecordModel) { |
||||||
1057 | 1 | ++$counter; |
|||||
1058 | $rows .= '<tr class="row-' . $counter . '">'; |
||||||
1059 | 1 | foreach ($fields as $fieldModel) { |
|||||
1060 | 1 | $value = $this->getDisplayValueByField($fieldModel, $relatedRecordModel, $params); |
|||||
1061 | if (false !== $value) { |
||||||
1062 | if ((int) $maxLength) { |
||||||
1063 | $value = TextUtils::textTruncate($value, (int) $maxLength); |
||||||
1064 | } |
||||||
1065 | $rows .= "<td class=\"col-type-{$fieldModel->getFieldType()}\" style=\"{$borderStyle}\">{$value}</td>"; |
||||||
1066 | } |
||||||
1067 | } |
||||||
1068 | $rows .= '</tr>'; |
||||||
1069 | } |
||||||
1070 | if (empty($rows)) { |
||||||
1071 | return ''; |
||||||
1072 | 1 | } |
|||||
1073 | $headers = "<tr>{$headers}</tr>"; |
||||||
1074 | 1 | $table = "class=\"records-list\" style=\"border-collapse:collapse;width:100%;{$borderStyle}\""; |
|||||
1075 | 1 | if (isset($paramsArray['addCounter']) && '1' === $paramsArray['addCounter']) { |
|||||
1076 | 1 | $headers = '<tr><th colspan="' . \count($fields) . '">' . Language::translate('LBL_NUMBER_OF_ALL_ENTRIES') . ": $counter</th></th></tr>$headers"; |
|||||
1077 | } |
||||||
1078 | 1 | return "<table {$table}><thead>{$headers}</thead><tbody>{$rows}</tbody></table>"; |
|||||
1079 | 1 | } |
|||||
1080 | 1 | ||||||
1081 | 1 | /** |
|||||
1082 | 1 | * Get record display value. |
|||||
1083 | 1 | * |
|||||
1084 | 1 | * @param \Vtiger_Field_Model $fieldModel |
|||||
1085 | * @param bool|mixed|\Vtiger_Record_Model $value |
||||||
1086 | * @param string $params |
||||||
1087 | * |
||||||
1088 | 1 | * @return array|bool|mixed|string |
|||||
1089 | 1 | */ |
|||||
1090 | 1 | protected function getDisplayValueByField(\Vtiger_Field_Model $fieldModel, $value = false, $params = null) |
|||||
1091 | 1 | { |
|||||
1092 | 1 | $model = $this->recordModel; |
|||||
1093 | 1 | if (false === $value) { |
|||||
1094 | 1 | $value = \App\Utils\Completions::decode($this->recordModel->get($fieldModel->getName()), \App\Utils\Completions::FORMAT_TEXT); |
|||||
1095 | 1 | if (!$fieldModel->isViewEnabled() && !$fieldModel->get('fromOutsideList')) { |
|||||
1096 | return ''; |
||||||
1097 | } |
||||||
1098 | } elseif (\is_object($value)) { |
||||||
1099 | $model = $value; |
||||||
1100 | 1 | $value = $value->get($fieldModel->getName()); |
|||||
1101 | 1 | if (!$fieldModel->isViewEnabled() && !$fieldModel->get('fromOutsideList')) { |
|||||
1102 | return false; |
||||||
1103 | } |
||||||
1104 | } |
||||||
1105 | if ('' === $value) { |
||||||
1106 | return ''; |
||||||
1107 | } |
||||||
1108 | if ($this->withoutTranslations) { |
||||||
1109 | 1 | return $this->getDisplayValueByType($value, $model, $fieldModel, $params); |
|||||
1110 | } |
||||||
1111 | 1 | return $fieldModel->getUITypeModel()->getTextParserDisplayValue($value, $model, $params); |
|||||
1112 | 1 | } |
|||||
1113 | |||||||
1114 | 1 | /** |
|||||
1115 | 1 | * Get record display value by type. |
|||||
1116 | 1 | * |
|||||
1117 | 1 | * @param mixed $value |
|||||
1118 | 1 | * @param \Vtiger_Record_Model $recordModel |
|||||
1119 | 1 | * @param \Vtiger_Field_Model $fieldModel |
|||||
1120 | * @param string $params |
||||||
1121 | * |
||||||
1122 | 1 | * @return array|mixed|string |
|||||
1123 | 1 | */ |
|||||
1124 | 1 | protected function getDisplayValueByType($value, \Vtiger_Record_Model $recordModel, \Vtiger_Field_Model $fieldModel, $params) |
|||||
1125 | 1 | { |
|||||
1126 | 1 | switch ($fieldModel->getFieldDataType()) { |
|||||
1127 | 1 | case 'boolean': |
|||||
1128 | 1 | $value = (1 === $value) ? 'LBL_YES' : 'LBL_NO'; |
|||||
1129 | 1 | $value = "$(translate : $value)$"; |
|||||
1130 | 1 | break; |
|||||
1131 | case 'multipicklist': |
||||||
1132 | $value = explode(' |##| ', $value); |
||||||
1133 | $trValue = []; |
||||||
1134 | $countValue = \count($value); |
||||||
1135 | for ($i = 0; $i < $countValue; ++$i) { |
||||||
1136 | 1 | $trValue[] = "$(translate : {$recordModel->getModuleName()}|{$value[$i]})$"; |
|||||
1137 | } |
||||||
1138 | if (\is_array($trValue)) { |
||||||
0 ignored issues
–
show
|
|||||||
1139 | $trValue = implode(' |##| ', $trValue); |
||||||
1140 | } |
||||||
1141 | $value = str_ireplace(' |##| ', ', ', $trValue); |
||||||
1142 | break; |
||||||
1143 | case 'picklist': |
||||||
1144 | $value = "$(translate : {$recordModel->getModuleName()}|$value)$"; |
||||||
1145 | break; |
||||||
1146 | 1 | case 'time': |
|||||
1147 | $userModel = \Users_Privileges_Model::getCurrentUserModel(); |
||||||
1148 | 1 | $value = \DateTimeField::convertToUserTimeZone(date('Y-m-d') . ' ' . $value)->format('H:i:s'); |
|||||
1149 | 1 | if (12 === (int) $userModel->get('hour_format')) { |
|||||
1150 | 1 | if ($value) { |
|||||
1151 | [$hours, $minutes] = array_pad(explode(':', $value), 2, ''); |
||||||
1152 | 1 | $format = '$(translate : PM)$'; |
|||||
1153 | 1 | if ($hours > 12) { |
|||||
1154 | 1 | $hours = (int) $hours - 12; |
|||||
1155 | 1 | } elseif ($hours < 12) { |
|||||
1156 | 1 | $format = '$(translate : AM)$'; |
|||||
1157 | 1 | } |
|||||
1158 | //If hours zero then we need to make it as 12 AM |
||||||
1159 | 1 | if ('00' == $hours) { |
|||||
1160 | $hours = '12'; |
||||||
1161 | 1 | $format = '$(translate : AM)$'; |
|||||
1162 | 1 | } |
|||||
1163 | 1 | $value = "$hours:$minutes $format"; |
|||||
1164 | 1 | } else { |
|||||
1165 | 1 | $value = ''; |
|||||
1166 | 1 | } |
|||||
1167 | 1 | } |
|||||
1168 | break; |
||||||
1169 | case 'tree': |
||||||
1170 | $template = $fieldModel->getFieldParams(); |
||||||
1171 | 1 | $value = $parentName = ''; |
|||||
1172 | 1 | if ($row = Fields\Tree::getValueByTreeId($template, $value)) { |
|||||
0 ignored issues
–
show
$template of type array is incompatible with the type integer expected by parameter $templateId of App\Fields\Tree::getValueByTreeId() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1173 | 1 | if ($row['depth'] > 0) { |
|||||
1174 | 1 | $pieces = explode('::', $row['parentTree']); |
|||||
1175 | 1 | end($pieces); |
|||||
1176 | 1 | $parent = prev($pieces); |
|||||
1177 | 1 | $parentRow = Fields\Tree::getValueByTreeId($template, $parent); |
|||||
1178 | 1 | $parentName = "($(translate : {$recordModel->getModuleName()}|{$parentRow['name']})$) "; |
|||||
1179 | 1 | } |
|||||
1180 | 1 | $value = $parentName . "$(translate : {$recordModel->getModuleName()}|{$row['name']})$"; |
|||||
1181 | 1 | } |
|||||
1182 | break; |
||||||
1183 | default: |
||||||
1184 | return $fieldModel->getUITypeModel()->getTextParserDisplayValue($value, $recordModel, $params); |
||||||
1185 | } |
||||||
1186 | return $value; |
||||||
1187 | } |
||||||
1188 | 1 | ||||||
1189 | /** |
||||||
1190 | 1 | * Get last comments. |
|||||
1191 | * |
||||||
1192 | * @param mixed $params |
||||||
1193 | * |
||||||
1194 | * @return string |
||||||
1195 | */ |
||||||
1196 | protected function getComments($params = false) |
||||||
1197 | { |
||||||
1198 | 1 | [$limit, $showAuthor] = array_pad(explode('|', $params, 2), 2, false); |
|||||
1199 | $query = (new \App\Db\Query())->select(['commentcontent', 'userid'])->from('vtiger_modcomments')->where(['related_to' => $this->record])->orderBy(['modcommentsid' => SORT_DESC]); |
||||||
1200 | if ($limit) { |
||||||
1201 | $query->limit($limit); |
||||||
1202 | 1 | } |
|||||
1203 | 1 | $commentsList = ''; |
|||||
1204 | foreach ($query->all() as $comment) { |
||||||
1205 | 1 | if ('' != $comment['commentcontent']) { |
|||||
1206 | 1 | $commentsList .= '<br><br>'; |
|||||
1207 | if ('true' === $showAuthor) { |
||||||
1208 | $commentsList .= Purifier::encodeHtml(\App\Fields\Owner::getUserLabel($comment['userid'])) . ': '; |
||||||
1209 | } |
||||||
1210 | $commentsList .= nl2br($comment['commentcontent']); |
||||||
1211 | } |
||||||
1212 | } |
||||||
1213 | return ltrim($commentsList, '<br><br>'); |
||||||
1214 | 1 | } |
|||||
1215 | |||||||
1216 | 1 | /** |
|||||
1217 | 1 | * Check if this content can be used. |
|||||
1218 | 1 | * |
|||||
1219 | 1 | * @param \Vtiger_Field_Model $fieldModel |
|||||
1220 | 1 | * @param string $moduleName |
|||||
1221 | 1 | * |
|||||
1222 | * @return bool |
||||||
1223 | */ |
||||||
1224 | protected function useValue($fieldModel, $moduleName) |
||||||
1225 | 1 | { |
|||||
1226 | 1 | return true; |
|||||
1227 | } |
||||||
1228 | |||||||
1229 | 1 | /** |
|||||
1230 | * Parsing params. |
||||||
1231 | * |
||||||
1232 | 1 | * @param string $key |
|||||
1233 | * |
||||||
1234 | * @return string |
||||||
1235 | */ |
||||||
1236 | protected function params(string $key) |
||||||
1237 | { |
||||||
1238 | return isset($this->params[$key]) ? \App\Purifier::purifyHtml($this->params[$key]) : ''; |
||||||
1239 | } |
||||||
1240 | 1 | ||||||
1241 | /** |
||||||
1242 | 1 | * Parsing custom. |
|||||
1243 | 1 | * |
|||||
1244 | 1 | * @param string $params |
|||||
1245 | 1 | * |
|||||
1246 | 1 | * @return string |
|||||
1247 | 1 | */ |
|||||
1248 | 1 | protected function custom($params) |
|||||
1249 | 1 | { |
|||||
1250 | $instance = null; |
||||||
1251 | if (false !== strpos($params, '||')) { |
||||||
1252 | 1 | $params = explode('||', $params); |
|||||
1253 | $parserName = array_shift($params); |
||||||
1254 | $baseParams = $params; |
||||||
1255 | $params = []; |
||||||
1256 | 1 | } else { |
|||||
1257 | $params = explode('|', $params); |
||||||
1258 | $parserName = array_shift($params); |
||||||
1259 | $baseParams = $params; |
||||||
1260 | } |
||||||
1261 | $module = false; |
||||||
1262 | if (!empty($params)) { |
||||||
1263 | $module = array_shift($params); |
||||||
1264 | 1 | if (!Module::getModuleId($module)) { |
|||||
1265 | $module = $this->moduleName; |
||||||
1266 | 1 | } |
|||||
1267 | 1 | } |
|||||
1268 | 1 | $className = "\\App\\TextParser\\$parserName"; |
|||||
1269 | 1 | if ($module && $handlerClass = \Vtiger_Loader::getComponentClassName('TextParser', $parserName, $module, false)) { |
|||||
1270 | 1 | $className = $handlerClass; |
|||||
1271 | 1 | } |
|||||
1272 | 1 | if (!class_exists($className)) { |
|||||
1273 | Log::error("Not found custom class: $parserName|{$module}"); |
||||||
1274 | } else { |
||||||
1275 | 1 | $instance = new $className($this, $baseParams); |
|||||
1276 | } |
||||||
1277 | return $instance && $instance->isActive() ? $instance->process() : ''; |
||||||
1278 | } |
||||||
1279 | |||||||
1280 | /** |
||||||
1281 | * Get record variables. |
||||||
1282 | * |
||||||
1283 | 1 | * @param bool|string $fieldType |
|||||
1284 | * |
||||||
1285 | 1 | * @return array |
|||||
1286 | 1 | */ |
|||||
1287 | 1 | public function getRecordVariable($fieldType = false) |
|||||
1288 | 1 | { |
|||||
1289 | 1 | $cacheKey = "{$this->moduleName}|$fieldType"; |
|||||
1290 | if (isset(static::$recordVariable[$cacheKey])) { |
||||||
1291 | return static::$recordVariable[$cacheKey]; |
||||||
1292 | 1 | } |
|||||
1293 | $variables = []; |
||||||
1294 | if (!$fieldType) { |
||||||
1295 | foreach (static::$variableEntity as $key => $name) { |
||||||
1296 | $variables[Language::translate('LBL_ENTITY_VARIABLES', 'Other.TextParser')][] = [ |
||||||
1297 | 'var_value' => "$(record : $key)$", |
||||||
1298 | 'var_label' => "$(translate : Other.TextParser|$name)$", |
||||||
1299 | 'label' => Language::translate($name, 'Other.TextParser'), |
||||||
1300 | ]; |
||||||
1301 | } |
||||||
1302 | } |
||||||
1303 | $moduleModel = \Vtiger_Module_Model::getInstance($this->moduleName); |
||||||
1304 | foreach ($moduleModel->getBlocks() as $blockModel) { |
||||||
1305 | foreach ($blockModel->getFields() as $fieldModel) { |
||||||
1306 | if ($fieldModel->isViewable() && !($fieldType && $fieldModel->getFieldDataType() !== $fieldType)) { |
||||||
1307 | 2 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
|||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1308 | $variables[Language::translate($blockModel->get('label'), $this->moduleName)][] = [ |
||||||
1309 | 2 | 'var_value' => "$(record : {$fieldModel->getName()})$", |
|||||
1310 | 1 | 'var_label' => "$(translate : {$this->moduleName}|{$label})$", |
|||||
1311 | 'label' => Language::translate($fieldModel->getFieldLabel(), $this->moduleName), |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1312 | 2 | ]; |
|||||
1313 | 2 | } |
|||||
1314 | 2 | } |
|||||
1315 | 2 | } |
|||||
1316 | 2 | static::$recordVariable[$cacheKey] = $variables; |
|||||
1317 | 2 | return $variables; |
|||||
1318 | 2 | } |
|||||
1319 | 2 | ||||||
1320 | 2 | /** |
|||||
1321 | 2 | * Get source variables. |
|||||
1322 | 2 | * |
|||||
1323 | 2 | * @return array |
|||||
1324 | 2 | */ |
|||||
1325 | 2 | public function getSourceVariable() |
|||||
1326 | { |
||||||
1327 | if (empty(self::$sourceModules[$this->moduleName])) { |
||||||
1328 | return false; |
||||||
0 ignored issues
–
show
|
|||||||
1329 | } |
||||||
1330 | 2 | $variables = []; |
|||||
1331 | 1 | foreach (static::$variableEntity as $key => $name) { |
|||||
1332 | $variables['LBL_ENTITY_VARIABLES'][] = [ |
||||||
1333 | 2 | 'var_value' => "$(sourceRecord : $key)$", |
|||||
1334 | 'var_label' => "$(translate : Other.TextParser|$name)$", |
||||||
1335 | 2 | 'label' => Language::translate($name, 'Other.TextParser'), |
|||||
1336 | 2 | ]; |
|||||
1337 | 2 | } |
|||||
1338 | 2 | foreach (self::$sourceModules[$this->moduleName] as $moduleName) { |
|||||
1339 | 2 | $moduleModel = \Vtiger_Module_Model::getInstance($moduleName); |
|||||
1340 | 2 | foreach ($moduleModel->getBlocks() as $blockModel) { |
|||||
1341 | 2 | foreach ($blockModel->getFields() as $fieldModel) { |
|||||
1342 | if ($fieldModel->isViewable()) { |
||||||
1343 | 2 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
|||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1344 | 2 | $variables[$moduleName][$blockModel->get('label')][] = [ |
|||||
1345 | 'var_value' => "$(sourceRecord : {$fieldModel->getName()})$", |
||||||
1346 | 2 | 'var_label' => "$(translate : $moduleName|{$label})$", |
|||||
1347 | 1 | 'label' => Language::translate($fieldModel->getFieldLabel(), $moduleName), |
|||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1348 | 1 | ]; |
|||||
1349 | 1 | } |
|||||
1350 | 1 | } |
|||||
1351 | } |
||||||
1352 | } |
||||||
1353 | 1 | return $variables; |
|||||
1354 | } |
||||||
1355 | |||||||
1356 | 2 | /** |
|||||
1357 | * Get related variables. |
||||||
1358 | 2 | * |
|||||
1359 | 1 | * @param bool|string $fieldType |
|||||
1360 | * @param bool $skipEmpty |
||||||
1361 | 2 | * |
|||||
1362 | 2 | * @return array |
|||||
1363 | 2 | */ |
|||||
1364 | 2 | public function getRelatedVariable($fieldType = false, $skipEmpty = false) |
|||||
1365 | { |
||||||
1366 | $cacheKey = "{$this->moduleName}|$fieldType|{$skipEmpty}"; |
||||||
1367 | if (isset(static::$relatedVariable[$cacheKey])) { |
||||||
1368 | return static::$relatedVariable[$cacheKey]; |
||||||
1369 | } |
||||||
1370 | $moduleModel = \Vtiger_Module_Model::getInstance($this->moduleName); |
||||||
1371 | $variables = []; |
||||||
1372 | $entityVariables = Language::translate('LBL_ENTITY_VARIABLES', 'Other.TextParser'); |
||||||
1373 | foreach ($moduleModel->getFieldsByType(array_merge(\Vtiger_Field_Model::$referenceTypes, ['userCreator', 'owner', 'sharedOwner'])) as $parentFieldName => $field) { |
||||||
1374 | if ('owner' === $field->getFieldDataType() || 'sharedOwner' === $field->getFieldDataType()) { |
||||||
1375 | $relatedModules = ['Users']; |
||||||
1376 | 27 | } else { |
|||||
1377 | $relatedModules = $field->getReferenceList(); |
||||||
1378 | 27 | } |
|||||
1379 | 3 | $parentFieldNameLabel = Language::translate($field->getFieldLabel(), $this->moduleName); |
|||||
1380 | if (!$fieldType) { |
||||||
1381 | 27 | foreach (static::$variableEntity as $key => $name) { |
|||||
1382 | 27 | $variables[$parentFieldName]["$parentFieldNameLabel - $entityVariables"][] = [ |
|||||
1383 | 1 | 'var_value' => "$(relatedRecord : $parentFieldName|$key)$", |
|||||
1384 | 1 | 'var_label' => "$(translate : Other.TextParser|$key)$", |
|||||
1385 | 1 | 'label' => $parentFieldNameLabel . ': ' . Language::translate($name, 'Other.TextParser'), |
|||||
1386 | ]; |
||||||
1387 | } |
||||||
1388 | } |
||||||
1389 | $relRecord = false; |
||||||
1390 | if ($skipEmpty && $this->recordModel && !(($relId = $this->recordModel->get($field->getName())) |
||||||
1391 | && ( |
||||||
1392 | \in_array($field->getFieldDataType(), ['userCreator', 'owner', 'sharedOwner']) |
||||||
1393 | || ((Record::isExists($relId)) && ($relRecord = \Vtiger_Record_Model::getInstanceById($relId))->isViewable() && ($relatedModules = [Record::getType($relId)])) |
||||||
1394 | 27 | ) |
|||||
1395 | )) { |
||||||
1396 | continue; |
||||||
1397 | } |
||||||
1398 | |||||||
1399 | foreach ($relatedModules as $relatedModule) { |
||||||
1400 | $relatedModuleLang = Language::translate($relatedModule, $relatedModule); |
||||||
1401 | foreach (\Vtiger_Module_Model::getInstance($relatedModule)->getBlocks() as $blockModel) { |
||||||
1402 | foreach ($blockModel->getFields() as $fieldName => $fieldModel) { |
||||||
1403 | if ( |
||||||
1404 | 5783 | $fieldModel->isViewable() |
|||||
1405 | && !($fieldType && $fieldModel->getFieldDataType() !== $fieldType) |
||||||
1406 | 5783 | && (!$relRecord || ($relRecord && !$relRecord->isEmpty($fieldModel->getName()))) |
|||||
1407 | 5783 | ) { |
|||||
1408 | $labelGroup = "$parentFieldNameLabel: ($relatedModuleLang) " . Language::translate($blockModel->get('label'), $relatedModule); |
||||||
1409 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1410 | $variables[$parentFieldName][$labelGroup][] = [ |
||||||
1411 | 'var_value' => "$(relatedRecord : $parentFieldName|$fieldName|$relatedModule)$", |
||||||
1412 | 'var_label' => "$(translate : $relatedModule|{$label})$", |
||||||
1413 | 'label' => "$parentFieldNameLabel: ($relatedModuleLang) " . Language::translate($fieldModel->getFieldLabel(), $relatedModule), |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1414 | ]; |
||||||
1415 | } |
||||||
1416 | } |
||||||
1417 | } |
||||||
1418 | } |
||||||
1419 | } |
||||||
1420 | static::$relatedVariable[$cacheKey] = $variables; |
||||||
1421 | return $variables; |
||||||
1422 | } |
||||||
1423 | |||||||
1424 | /** |
||||||
1425 | * Get related variables. |
||||||
1426 | * |
||||||
1427 | * @param bool|string $fieldType |
||||||
1428 | * |
||||||
1429 | * @return array |
||||||
1430 | */ |
||||||
1431 | public function getRelatedLevelVariable($fieldType = false) |
||||||
1432 | { |
||||||
1433 | $cacheKey = "{$this->moduleName}|$fieldType"; |
||||||
1434 | if (isset(static::$relatedVariableLevel[$cacheKey])) { |
||||||
1435 | return static::$relatedVariableLevel[$cacheKey]; |
||||||
1436 | } |
||||||
1437 | $moduleModel = \Vtiger_Module_Model::getInstance($this->moduleName); |
||||||
1438 | $variables = []; |
||||||
1439 | foreach ($moduleModel->getFieldsByType(array_merge(\Vtiger_Field_Model::$referenceTypes, ['userCreator', 'owner'])) as $parentFieldName => $fieldModel) { |
||||||
1440 | if ('owner' === $fieldModel->getFieldDataType()) { |
||||||
1441 | $relatedModules = ['Users']; |
||||||
1442 | } else { |
||||||
1443 | $relatedModules = $fieldModel->getReferenceList(); |
||||||
1444 | } |
||||||
1445 | $parentFieldNameLabel = Language::translate($fieldModel->getFieldLabel(), $this->moduleName); |
||||||
1446 | foreach ($relatedModules as $relatedModule) { |
||||||
1447 | $relatedModuleLang = Language::translate($relatedModule, $relatedModule); |
||||||
1448 | foreach (\Vtiger_Module_Model::getInstance($relatedModule)->getFieldsByType(array_merge(\Vtiger_Field_Model::$referenceTypes, ['userCreator', 'owner', 'sharedOwner'])) as $parentFieldNameNextLevel => $fieldModelNextLevel) { |
||||||
1449 | if ('owner' === $fieldModelNextLevel->getFieldDataType() || 'sharedOwner' === $fieldModelNextLevel->getFieldDataType()) { |
||||||
1450 | $relatedModulesNextLevel = ['Users']; |
||||||
1451 | } else { |
||||||
1452 | $relatedModulesNextLevel = $fieldModelNextLevel->getReferenceList(); |
||||||
1453 | } |
||||||
1454 | $parentFieldNameLabelNextLevel = Language::translate($fieldModelNextLevel->getFieldLabel(), $relatedModule); |
||||||
1455 | foreach ($relatedModulesNextLevel as $relatedModuleNextLevel) { |
||||||
1456 | $relatedModuleLangNextLevel = Language::translate($relatedModuleNextLevel, $relatedModuleNextLevel); |
||||||
1457 | foreach (\Vtiger_Module_Model::getInstance($relatedModuleNextLevel)->getBlocks() as $blockModel) { |
||||||
1458 | foreach ($blockModel->getFields() as $fieldName => $fieldModel) { |
||||||
0 ignored issues
–
show
|
|||||||
1459 | if ($fieldModel->isViewable() && !($fieldType && $fieldModel->getFieldDataType() !== $fieldType)) { |
||||||
1460 | $labelGroup = "{$parentFieldNameLabel}($relatedModuleLang) -> {$parentFieldNameLabelNextLevel}($relatedModuleLangNextLevel) " . Language::translate($blockModel->get('label'), $relatedModuleNextLevel); |
||||||
1461 | $label = \App\Purifier::encodeHtml($fieldModel->getFieldLabel()); |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1462 | $variables[$labelGroup][] = [ |
||||||
1463 | 'var_value' => "$(relatedRecordLevel : $parentFieldName|$relatedModule|$parentFieldNameNextLevel|$fieldName|$relatedModuleNextLevel)$", |
||||||
1464 | 'var_label' => "$(translate : $relatedModuleNextLevel|{$label})$", |
||||||
1465 | 'label' => "{$parentFieldNameLabel}($relatedModuleLang) -> {$parentFieldNameLabelNextLevel}($relatedModuleLangNextLevel) " . Language::translate($fieldModel->getFieldLabel(), $relatedModuleNextLevel), |
||||||
0 ignored issues
–
show
The function
Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel()
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1466 | ]; |
||||||
1467 | } |
||||||
1468 | } |
||||||
1469 | } |
||||||
1470 | } |
||||||
1471 | } |
||||||
1472 | } |
||||||
1473 | } |
||||||
1474 | static::$relatedVariableLevel[$cacheKey] = $variables; |
||||||
1475 | return $variables; |
||||||
1476 | } |
||||||
1477 | |||||||
1478 | /** |
||||||
1479 | * Get general variables. |
||||||
1480 | * |
||||||
1481 | * @return array |
||||||
1482 | */ |
||||||
1483 | public function getGeneralVariable() |
||||||
1484 | { |
||||||
1485 | $variables = [ |
||||||
1486 | 'LBL_ENTITY_VARIABLES' => array_map(fn ($value) => Language::translate($value, 'Other.TextParser'), array_flip(static::$variableGeneral)), |
||||||
1487 | ]; |
||||||
1488 | $variables['LBL_CUSTOM_VARIABLES'] = array_merge($this->getBaseGeneralVariable(), $this->getModuleGeneralVariable()); |
||||||
1489 | return $variables; |
||||||
1490 | } |
||||||
1491 | |||||||
1492 | /** |
||||||
1493 | * Get general variables base function. |
||||||
1494 | * |
||||||
1495 | * @return array |
||||||
1496 | */ |
||||||
1497 | protected function getBaseGeneralVariable() |
||||||
1498 | { |
||||||
1499 | $variables = []; |
||||||
1500 | foreach ((new \DirectoryIterator(__DIR__ . \DIRECTORY_SEPARATOR . 'TextParser')) as $fileInfo) { |
||||||
1501 | $fileName = $fileInfo->getBasename('.php'); |
||||||
1502 | if ('dir' !== $fileInfo->getType() && 'Base' !== $fileName && 'php' === $fileInfo->getExtension()) { |
||||||
1503 | $className = '\App\TextParser\\' . $fileName; |
||||||
1504 | if (!class_exists($className)) { |
||||||
1505 | Log::warning('Not found custom class'); |
||||||
1506 | continue; |
||||||
1507 | } |
||||||
1508 | $instance = new $className($this); |
||||||
1509 | if (isset($this->type) && $this->type !== $instance->type) { |
||||||
1510 | continue; |
||||||
1511 | } |
||||||
1512 | $key = $instance->default ?? "$(custom : $fileName)$"; |
||||||
1513 | $variables[$key] = Language::translate($instance->name, 'Other.TextParser'); |
||||||
1514 | } |
||||||
1515 | } |
||||||
1516 | return $variables; |
||||||
1517 | } |
||||||
1518 | |||||||
1519 | /** |
||||||
1520 | * Get general variables module function. |
||||||
1521 | * |
||||||
1522 | * @return array |
||||||
1523 | */ |
||||||
1524 | protected function getModuleGeneralVariable() |
||||||
1525 | { |
||||||
1526 | $variables = []; |
||||||
1527 | if ($this->moduleName && is_dir(("modules/{$this->moduleName}/textparsers/"))) { |
||||||
1528 | foreach ((new \DirectoryIterator("modules/{$this->moduleName}/textparsers/")) as $fileInfo) { |
||||||
1529 | $fileName = $fileInfo->getBasename('.php'); |
||||||
1530 | if ('dir' !== $fileInfo->getType() && 'php' === $fileInfo->getExtension()) { |
||||||
1531 | $handlerClass = \Vtiger_Loader::getComponentClassName('TextParser', $fileName, $this->moduleName); |
||||||
1532 | $instanceClass = new $handlerClass($this); |
||||||
1533 | if (isset($this->type) && $this->type !== $instanceClass->type) { |
||||||
1534 | continue; |
||||||
1535 | } |
||||||
1536 | $variables["$(custom : $fileName|{$this->moduleName})$"] = Language::translate($instanceClass->name, $this->moduleName); |
||||||
1537 | } |
||||||
1538 | } |
||||||
1539 | } |
||||||
1540 | return $variables; |
||||||
1541 | } |
||||||
1542 | |||||||
1543 | /** |
||||||
1544 | * Get related modules list. |
||||||
1545 | * |
||||||
1546 | * @return array |
||||||
1547 | */ |
||||||
1548 | public function getRelatedListVariable() |
||||||
1549 | { |
||||||
1550 | $moduleModel = \Vtiger_Module_Model::getInstance($this->moduleName); |
||||||
1551 | $variables = []; |
||||||
1552 | foreach ($moduleModel->getRelations() as $relation) { |
||||||
1553 | $var = $relation->get('relatedModuleName'); |
||||||
1554 | if ($relation->get('field_name')) { |
||||||
1555 | $var = $relation->get('relation_id'); |
||||||
1556 | } |
||||||
1557 | $variables[] = [ |
||||||
1558 | 'key' => "$(relatedRecordsList : $var|__FIELDS_NAME__|__CONDITIONS__|__VIEW_ID_OR_NAME__|__LIMIT__|__MAX_LENGTH__)$", |
||||||
1559 | 'label' => Language::translate($relation->get('label'), $relation->get('relatedModuleName')), |
||||||
1560 | ]; |
||||||
1561 | } |
||||||
1562 | return $variables; |
||||||
1563 | } |
||||||
1564 | |||||||
1565 | /** |
||||||
1566 | * Get base modules list. |
||||||
1567 | * |
||||||
1568 | * @return array |
||||||
1569 | */ |
||||||
1570 | public function getBaseListVariable() |
||||||
1571 | { |
||||||
1572 | $variables = []; |
||||||
1573 | foreach (\vtlib\Functions::getAllModules() as $module) { |
||||||
1574 | $variables[] = [ |
||||||
1575 | 'key' => "$(recordsList : {$module['name']})$", |
||||||
1576 | 'label' => Language::translate($module['name'], $module['name']), |
||||||
1577 | ]; |
||||||
1578 | } |
||||||
1579 | return $variables; |
||||||
1580 | } |
||||||
1581 | |||||||
1582 | /** |
||||||
1583 | * Gets user variables. |
||||||
1584 | * |
||||||
1585 | * @param string $text |
||||||
1586 | * @param bool $useRegex |
||||||
1587 | * |
||||||
1588 | * @return array |
||||||
1589 | */ |
||||||
1590 | public function getUserVariables(string $text, bool $useRegex = true) |
||||||
1591 | { |
||||||
1592 | $data = []; |
||||||
1593 | if ($useRegex) { |
||||||
1594 | preg_match_all('/\$\(userVariable : ([,"\+\%\.\=\-\[\]\&\w\s\|\)\(\:]+)\)\$/u', str_replace(['%20%3A%20', '%20:%20'], ' : ', $text), $matches); |
||||||
1595 | $matches = $matches[1] ?? []; |
||||||
1596 | } else { |
||||||
1597 | $matches = [$text]; |
||||||
1598 | } |
||||||
1599 | foreach ($matches as $param) { |
||||||
1600 | $part = self::parseFieldParam($param); |
||||||
1601 | if (!empty($part['name']) && !(isset($data[$part['name']]))) { |
||||||
1602 | $data[$part['name']] = $part; |
||||||
1603 | } |
||||||
1604 | } |
||||||
1605 | return $data; |
||||||
1606 | } |
||||||
1607 | |||||||
1608 | /** |
||||||
1609 | * Parsing user variable. |
||||||
1610 | * |
||||||
1611 | * @param string $params |
||||||
1612 | * |
||||||
1613 | * @return string |
||||||
1614 | */ |
||||||
1615 | protected function userVariable($params) |
||||||
1616 | { |
||||||
1617 | $instance = null; |
||||||
1618 | $className = '\\App\\TextParser\\' . ucfirst(__FUNCTION__); |
||||||
1619 | if (!class_exists($className)) { |
||||||
1620 | Log::error("Not found custom class: $className"); |
||||||
1621 | } else { |
||||||
1622 | $instance = new $className($this, $params); |
||||||
1623 | } |
||||||
1624 | return $instance && $instance->isActive() ? $instance->process() : ''; |
||||||
1625 | } |
||||||
1626 | |||||||
1627 | /** |
||||||
1628 | * Parsing inventory. |
||||||
1629 | * |
||||||
1630 | * @param string $params |
||||||
1631 | * |
||||||
1632 | * @return string |
||||||
1633 | */ |
||||||
1634 | protected function inventory($params) |
||||||
1635 | { |
||||||
1636 | if (!$this->recordModel->getModule()->isInventory()) { |
||||||
1637 | return ''; |
||||||
1638 | } |
||||||
1639 | $config = $this->parseParams($params); |
||||||
1640 | if ('table' === $config['type']) { |
||||||
1641 | return $this->getInventoryTable($config); |
||||||
1642 | } |
||||||
1643 | return ''; |
||||||
1644 | } |
||||||
1645 | |||||||
1646 | /** |
||||||
1647 | * Get an instance of barcode text parser. |
||||||
1648 | * |
||||||
1649 | * @param string $params |
||||||
1650 | * |
||||||
1651 | * @return string |
||||||
1652 | */ |
||||||
1653 | protected function barcode($params): string |
||||||
1654 | { |
||||||
1655 | $params = $this->parseParams($params); |
||||||
1656 | if (isset($params['value'])) { |
||||||
1657 | $valueForParse = $params['value']; |
||||||
1658 | } |
||||||
1659 | if (isset($params['fieldName'])) { |
||||||
1660 | $valueForParse = $this->recordModel->get($params['fieldName']); |
||||||
1661 | } |
||||||
1662 | if ($valueForParse) { |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
1663 | $className = '\Milon\Barcode\\' . $params['class']; |
||||||
1664 | if (!class_exists($className)) { |
||||||
1665 | throw new \App\Exceptions\AppException('ERR_CLASS_NOT_FOUND||' . $className); |
||||||
1666 | } |
||||||
1667 | $qrCodeGenerator = new $className(); |
||||||
1668 | $qrCodeGenerator->setStorPath(__DIR__ . Config::main('tmp_dir')); |
||||||
1669 | $barcodeHeight = $this->params['height'] ?? 2; |
||||||
1670 | $barcodeWidth = $this->params['width'] ?? 30; |
||||||
1671 | $barcodeType = $this->params['type'] ?? 'EAN13'; |
||||||
1672 | $showText = $this->params['showText'] ?? true; |
||||||
1673 | $png = $qrCodeGenerator->getBarcodePNG($valueForParse, $barcodeType, $barcodeHeight, $barcodeWidth, [0, 0, 0], $showText); |
||||||
1674 | return '<img src="data:image/png;base64,' . $png . '"/>'; |
||||||
1675 | } |
||||||
1676 | return ''; |
||||||
1677 | } |
||||||
1678 | |||||||
1679 | /** |
||||||
1680 | * Get inventory param. |
||||||
1681 | * |
||||||
1682 | * @param string $params |
||||||
1683 | * |
||||||
1684 | * @return array |
||||||
1685 | */ |
||||||
1686 | protected function parseParams(string $params): array |
||||||
1687 | { |
||||||
1688 | preg_match('/type=(\w+)/', $params, $matches); |
||||||
1689 | $config = [ |
||||||
1690 | 'type' => ($matches[1] ?? false), |
||||||
1691 | ]; |
||||||
1692 | $params = ltrim($params, $matches[0] . ' '); |
||||||
1693 | foreach (explode(' , ', $params) as $value) { |
||||||
1694 | parse_str($value, $row); |
||||||
1695 | $config += $row; |
||||||
1696 | } |
||||||
1697 | if (isset($config['columns'])) { |
||||||
1698 | $config['columns'] = explode(',', $config['columns']); |
||||||
1699 | } |
||||||
1700 | return $config; |
||||||
1701 | } |
||||||
1702 | |||||||
1703 | /** |
||||||
1704 | * Parsing inventory table. |
||||||
1705 | * |
||||||
1706 | * @param array $config |
||||||
1707 | * |
||||||
1708 | * @return string |
||||||
1709 | */ |
||||||
1710 | public function getInventoryTable(array $config): string |
||||||
1711 | { |
||||||
1712 | $rawText = empty($config['href']) || 'yes' !== $config['href']; |
||||||
1713 | $inventory = \Vtiger_Inventory_Model::getInstance($this->moduleName); |
||||||
1714 | $fields = $inventory->getFieldsByBlocks(); |
||||||
1715 | $inventoryRows = $this->recordModel->getInventoryData(); |
||||||
1716 | $baseCurrency = \Vtiger_Util_Helper::getBaseCurrency(); |
||||||
1717 | $firstRow = current($inventoryRows); |
||||||
1718 | if ($inventory->isField('currency')) { |
||||||
1719 | if (!empty($firstRow) && null !== $firstRow['currency']) { |
||||||
1720 | $currency = $firstRow['currency']; |
||||||
1721 | } else { |
||||||
1722 | $currency = $baseCurrency['id']; |
||||||
1723 | } |
||||||
1724 | $currencyData = \App\Fields\Currency::getById($currency); |
||||||
1725 | $currencySymbol = $currencyData['currency_symbol']; |
||||||
1726 | } |
||||||
1727 | $html = ''; |
||||||
1728 | if (!empty($fields[1])) { |
||||||
1729 | $fieldsTextAlignRight = ['Unit', 'TotalPrice', 'Tax', 'MarginP', 'Margin', 'Purchase', 'Discount', 'NetPrice', 'GrossPrice', 'UnitPrice', 'Quantity', 'TaxPercent']; |
||||||
1730 | $fieldsWithCurrency = ['TotalPrice', 'Purchase', 'NetPrice', 'GrossPrice', 'UnitPrice', 'Discount', 'Margin', 'Tax']; |
||||||
1731 | $html .= '<table class="inventory-table" style="border-collapse:collapse;width:100%"><thead><tr>'; |
||||||
1732 | $columns = []; |
||||||
1733 | $customFieldClassSeq = 0; |
||||||
1734 | $labels = isset($config['labels']) ? explode(',', $config['labels']) : []; |
||||||
1735 | $width = isset($config['width']) ? preg_replace('/[^[:alnum:]]/', '', explode(',', $config['width'])) : []; |
||||||
1736 | foreach ($config['columns'] as $key => $name) { |
||||||
1737 | if (false !== strpos($name, '||')) { |
||||||
1738 | [$title,$value] = explode('||', $name, 2); |
||||||
1739 | if ('(' === $title[0] && ')' === substr($title, -1)) { |
||||||
1740 | $title = $this->parseVariable("\${$title}\$"); |
||||||
1741 | } |
||||||
1742 | ++$customFieldClassSeq; |
||||||
1743 | $html .= '<th class="col-type-customField' . $customFieldClassSeq . '" style="border:1px solid #ddd">' . $title . '</th>'; |
||||||
1744 | $columns[$title] = $value; |
||||||
1745 | continue; |
||||||
1746 | } |
||||||
1747 | if ('seq' === $name) { |
||||||
1748 | $html .= '<th class="col-type-ItemNumber" style="border:1px solid #ddd">' . Language::translate('LBL_ITEM_NUMBER', $this->moduleName) . '</th>'; |
||||||
1749 | $columns[$name] = false; |
||||||
1750 | continue; |
||||||
1751 | } |
||||||
1752 | if (empty($fields[1][$name]) && empty($fields[2][$name])) { |
||||||
1753 | continue; |
||||||
1754 | } |
||||||
1755 | $field = $fields[1][$name] ?? $fields[2][$name]; |
||||||
1756 | if (!$field->isVisible()) { |
||||||
1757 | continue; |
||||||
1758 | } |
||||||
1759 | $html .= '<th class="col-type-' . $field->getType() . '" style="border:1px solid #ddd ' . (empty($width[$key]) ? '' : ";width: {$width[$key]}") . '">' . (empty($labels[$key]) ? Language::translate($field->get('label'), $this->moduleName) : Purifier::encodeHtml($labels[$key])) . '</th>'; |
||||||
1760 | $columns[$field->getColumnName()] = $field; |
||||||
1761 | } |
||||||
1762 | $html .= '</tr></thead><tbody>'; |
||||||
1763 | $counter = 0; |
||||||
1764 | foreach ($inventoryRows as $inventoryRow) { |
||||||
1765 | ++$counter; |
||||||
1766 | $html .= '<tr class="row-' . $counter . '">'; |
||||||
1767 | $customFieldClassSeq = 0; |
||||||
1768 | foreach ($columns as $name => $field) { |
||||||
1769 | if ('seq' === $name) { |
||||||
1770 | $html .= '<td class="col-type-ItemNumber" style="border:1px solid #ddd;font-weight:bold;">' . $counter . '</td>'; |
||||||
1771 | } elseif (!\is_object($field)) { |
||||||
1772 | if ('(' === $field[0] && ')' === substr($field, -1)) { |
||||||
1773 | $field = $this->parseVariable("\${$field}\$", $inventoryRow['name'] ?? 0); |
||||||
1774 | } |
||||||
1775 | ++$customFieldClassSeq; |
||||||
1776 | $html .= '<td class="col-type-customField' . $customFieldClassSeq . '" style="border:1px solid #ddd;font-weight:bold;">' . $field . '</td>'; |
||||||
1777 | } elseif ('ItemNumber' === $field->getType()) { |
||||||
1778 | $html .= '<td class="col-type-ItemNumber" style="border:1px solid #ddd;font-weight:bold;">' . $counter . '</td>'; |
||||||
1779 | } elseif ('ean' === $name) { |
||||||
1780 | $itemValue = $inventoryRow[$name]; |
||||||
1781 | $html .= '<td class="col-type-barcode" style="border:1px solid #ddd;padding:0px 4px;' . (\in_array($field->getType(), $fieldsTextAlignRight) ? 'text-align:right;' : '') . '"><div data-barcode="EAN13" data-code="' . $itemValue . '" data-size="1" data-height="16"></div></td>'; |
||||||
1782 | } else { |
||||||
1783 | $itemValue = $inventoryRow[$name]; |
||||||
1784 | $html .= '<td class="col-type-' . $field->getType() . '" style="border:1px solid #ddd;padding:0px 4px;' . (\in_array($field->getType(), $fieldsTextAlignRight) ? 'text-align:right;' : '') . '">'; |
||||||
1785 | if ('Name' === $field->getType()) { |
||||||
1786 | $html .= '<strong>' . $field->getDisplayValue($itemValue, $inventoryRow, $rawText) . '</strong>'; |
||||||
1787 | foreach ($inventory->getFieldsByType('Comment') as $commentField) { |
||||||
1788 | if ($commentField->isVisible() && ($value = $inventoryRow[$commentField->getColumnName()])) { |
||||||
1789 | $comment = $commentField->getDisplayValue($value, $inventoryRow, $rawText); |
||||||
1790 | if ($comment) { |
||||||
1791 | $html .= '<br>' . $comment; |
||||||
1792 | } |
||||||
1793 | } |
||||||
1794 | } |
||||||
1795 | } elseif (\in_array($field->getType(), $fieldsWithCurrency, true)) { |
||||||
1796 | $html .= \CurrencyField::appendCurrencySymbol($field->getDisplayValue($itemValue, $inventoryRow, $rawText), $currencySymbol); |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
1797 | } else { |
||||||
1798 | $html .= $field->getDisplayValue($itemValue, $inventoryRow, $rawText); |
||||||
1799 | } |
||||||
1800 | $html .= '</td>'; |
||||||
1801 | } |
||||||
1802 | } |
||||||
1803 | $html .= '</tr>'; |
||||||
1804 | } |
||||||
1805 | |||||||
1806 | $html .= '</tbody><tfoot><tr>'; |
||||||
1807 | foreach ($columns as $name => $field) { |
||||||
1808 | $tb = $style = ''; |
||||||
1809 | if (\is_object($field) && $field->isSummary()) { |
||||||
1810 | $style = 'border:1px solid #ddd;'; |
||||||
1811 | $sum = 0; |
||||||
1812 | foreach ($inventoryRows as $inventoryRow) { |
||||||
1813 | $sum += $inventoryRow[$name]; |
||||||
1814 | } |
||||||
1815 | $tb = \CurrencyField::appendCurrencySymbol(\CurrencyField::convertToUserFormat($sum, null, true), $currencySymbol); |
||||||
0 ignored issues
–
show
CurrencyField::convertTo...ormat($sum, null, true) of type string is incompatible with the type double|integer expected by parameter $currencyValue of CurrencyField::appendCurrencySymbol() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() The function
CurrencyField::convertToUserFormat() has been deprecated: Recommend using function \App\Fields\Currency::formatToDisplay
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
1816 | } |
||||||
1817 | $html .= '<th class="col-type-' . (\is_object($field) ? $field->getType() : $name) . '" style="padding:0px 4px;text-align:right;' . $style . '">' . $tb . '</th>'; |
||||||
1818 | } |
||||||
1819 | $html .= '</tr></tfoot></table>'; |
||||||
1820 | } |
||||||
1821 | return $html; |
||||||
1822 | } |
||||||
1823 | |||||||
1824 | /** |
||||||
1825 | * Parse variable. |
||||||
1826 | * |
||||||
1827 | * @param string $variable |
||||||
1828 | * @param int $id |
||||||
1829 | * |
||||||
1830 | * @return string |
||||||
1831 | */ |
||||||
1832 | protected function parseVariable(string $variable, int $id = 0): string |
||||||
1833 | { |
||||||
1834 | if ($id && Record::isExists($id)) { |
||||||
1835 | $recordModel = \Vtiger_Record_Model::getInstanceById($id); |
||||||
1836 | if (!$recordModel->isViewable()) { |
||||||
1837 | return ''; |
||||||
1838 | } |
||||||
1839 | $instance = static::getInstanceByModel($recordModel); |
||||||
1840 | } else { |
||||||
1841 | $instance = static::getInstance(); |
||||||
1842 | } |
||||||
1843 | foreach (['withoutTranslations', 'language', 'emailoptout'] as $key) { |
||||||
1844 | if (isset($this->{$key})) { |
||||||
1845 | $instance->{$key} = $this->{$key}; |
||||||
1846 | } |
||||||
1847 | } |
||||||
1848 | $instance->setContent($variable)->parse(); |
||||||
1849 | return $instance->getContent(); |
||||||
1850 | } |
||||||
1851 | |||||||
1852 | /** |
||||||
1853 | * Parse custom params. |
||||||
1854 | * |
||||||
1855 | * @param string $param |
||||||
1856 | * |
||||||
1857 | * @return array |
||||||
1858 | */ |
||||||
1859 | public static function parseFieldParam(string $param): array |
||||||
1860 | { |
||||||
1861 | $part = []; |
||||||
1862 | if ($param) { |
||||||
1863 | foreach (explode('|', $param) as $type) { |
||||||
1864 | [$name, $value] = array_pad(explode('=', $type, 2), 2, ''); |
||||||
1865 | $part[$name] = $value; |
||||||
1866 | } |
||||||
1867 | } |
||||||
1868 | return $part; |
||||||
1869 | } |
||||||
1870 | } |
||||||
1871 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths