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 declare(strict_types=1); |
||||
2 | |||||
3 | namespace XoopsModules\Xhelp; |
||||
4 | |||||
5 | /* |
||||
6 | * You may not change or alter any portion of this comment or credits |
||||
7 | * of supporting developers from this source code or any supporting source code |
||||
8 | * which is considered copyrighted (c) material of the original comment or credit authors. |
||||
9 | * |
||||
10 | * This program is distributed in the hope that it will be useful, |
||||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
13 | */ |
||||
14 | |||||
15 | /** |
||||
16 | * @copyright {@link https://xoops.org/ XOOPS Project} |
||||
17 | * @license {@link https://www.gnu.org/licenses/gpl-2.0.html GNU GPL 2 or later} |
||||
18 | * @author Eric Juden <[email protected]> |
||||
19 | * @author XOOPS Development Team |
||||
20 | */ |
||||
21 | |||||
22 | use function md5; |
||||
23 | |||||
24 | if (!\defined('XHELP_CLASS_PATH')) { |
||||
25 | exit(); |
||||
26 | } |
||||
27 | // require_once XHELP_CLASS_PATH . '/BaseObjectHandler.php'; |
||||
28 | $path = \dirname(__DIR__, 3); |
||||
29 | require_once $path . '/mainfile.php'; |
||||
30 | //require_once $path . '/include/cp_functions.php'; |
||||
31 | //require_once $path . '/include/cp_header.php'; |
||||
32 | |||||
33 | global $xoopsUser; |
||||
34 | |||||
35 | /** |
||||
36 | * Ticket class |
||||
37 | * |
||||
38 | * Information about an individual ticket |
||||
39 | * |
||||
40 | * <code> |
||||
41 | * $ticketHandler = $this->helper->getHandler('Ticket'); |
||||
42 | * $ticket = $ticketHandler->get(1); |
||||
43 | * $ticket_id = $ticket->getVar('id'); |
||||
44 | * $responses = $ticket->getResponses(); |
||||
45 | * echo $ticket->lastUpdated(); |
||||
46 | * </code> |
||||
47 | * |
||||
48 | * @author Eric Juden <[email protected]> |
||||
49 | */ |
||||
50 | class Ticket extends \XoopsObject |
||||
51 | { |
||||
52 | private $helper; |
||||
53 | |||||
54 | /** |
||||
55 | * Ticket constructor. |
||||
56 | * @param int|array|null $id |
||||
57 | */ |
||||
58 | public function __construct($id = null) |
||||
59 | { |
||||
60 | $this->initVar('id', \XOBJ_DTYPE_INT, null, false); |
||||
61 | $this->initVar('uid', \XOBJ_DTYPE_INT, null, false); // will store Xoops user id |
||||
62 | $this->initVar('subject', \XOBJ_DTYPE_TXTBOX, null, true, 100); |
||||
63 | $this->initVar('description', \XOBJ_DTYPE_TXTAREA, null, false, 1000000); |
||||
64 | $this->initVar('department', \XOBJ_DTYPE_INT, null, false); |
||||
65 | $this->initVar('priority', \XOBJ_DTYPE_INT, null, false); |
||||
66 | $this->initVar('status', \XOBJ_DTYPE_INT, null, false); |
||||
67 | $this->initVar('lastUpdated', \XOBJ_DTYPE_INT, null, false); |
||||
68 | $this->initVar('posted', \XOBJ_DTYPE_INT, null, false); |
||||
69 | $this->initVar('ownership', \XOBJ_DTYPE_INT, null, false); // will store Xoops user id |
||||
70 | $this->initVar('closedBy', \XOBJ_DTYPE_INT, null, false); // will store Xoops user id |
||||
71 | $this->initVar('totalTimeSpent', \XOBJ_DTYPE_INT, null, false); |
||||
72 | $this->initVar('userIP', \XOBJ_DTYPE_TXTBOX, null, false, 25); |
||||
73 | $this->initVar('elapsed', \XOBJ_DTYPE_INT, null, false); |
||||
74 | $this->initVar('lastUpdate', \XOBJ_DTYPE_INT, null, false); |
||||
75 | $this->initVar('emailHash', \XOBJ_DTYPE_TXTBOX, '', true, 100); |
||||
76 | $this->initVar('email', \XOBJ_DTYPE_TXTBOX, '', true, 100); |
||||
77 | $this->initVar('serverid', \XOBJ_DTYPE_INT, null, false); //will store email server this was picked up from |
||||
78 | $this->initVar('overdueTime', \XOBJ_DTYPE_INT, null, false); |
||||
79 | |||||
80 | $this->helper = Helper::getInstance(); |
||||
81 | |||||
82 | if (null !== $id) { |
||||
83 | if (\is_array($id)) { |
||||
84 | $this->assignVars($id); |
||||
85 | } |
||||
86 | } else { |
||||
87 | $this->setNew(); |
||||
88 | } |
||||
89 | } |
||||
90 | |||||
91 | /** |
||||
92 | * retrieve the department object associated with this ticket |
||||
93 | * |
||||
94 | * @return Department|bool {@link Department} |
||||
95 | */ |
||||
96 | public function getDepartment() |
||||
97 | { |
||||
98 | $departmentHandler = $this->helper->getHandler('Department'); |
||||
99 | |||||
100 | return $departmentHandler->get($this->getVar('department')); |
||||
101 | } |
||||
102 | |||||
103 | /** |
||||
104 | * create an md5 hash based on the ID and emailaddress. Use this as a lookup key when trying to find a ticket. |
||||
105 | * |
||||
106 | * @param string $email |
||||
107 | */ |
||||
108 | public function createEmailHash(string $email): void |
||||
109 | { |
||||
110 | if ('' === $this->getVar('posted')) { |
||||
111 | $this->setVar('posted', \time()); |
||||
112 | } |
||||
113 | $hash = $this->getVar('posted') . '-' . $email; |
||||
114 | $hash = md5($hash); |
||||
115 | |||||
116 | $this->setVar('email', $email); |
||||
117 | $this->setVar('emailHash', $hash); |
||||
118 | } |
||||
119 | |||||
120 | /** |
||||
121 | * retrieve all emails attached to this ticket object |
||||
122 | * @param bool $activeOnly |
||||
123 | * @return array of <a href='psi_element://TicketEmail'>TicketEmail</a> objects |
||||
124 | * objects |
||||
125 | */ |
||||
126 | public function getEmails(bool $activeOnly = false): array |
||||
127 | { |
||||
128 | $arr = []; |
||||
129 | $id = (int)$this->getVar('id'); |
||||
130 | if (!$id) { |
||||
131 | return $arr; |
||||
132 | } |
||||
133 | |||||
134 | $hEmails = $this->helper->getHandler('TicketEmails'); |
||||
135 | $criteria = new \CriteriaCompo(new \Criteria('ticketid', $id)); |
||||
136 | if ($activeOnly) { |
||||
137 | $criteria->add(new \Criteria('suppress', 0)); |
||||
138 | } |
||||
139 | $arr = $hEmails->getObjects($criteria); |
||||
140 | |||||
141 | return $arr; |
||||
142 | } |
||||
143 | |||||
144 | /** |
||||
145 | * retrieve all files attached to this ticket object |
||||
146 | * |
||||
147 | * @return array of {@link File} objects |
||||
148 | */ |
||||
149 | public function getFiles(): array |
||||
150 | { |
||||
151 | $arr = []; |
||||
152 | $id = (int)$this->getVar('id'); |
||||
153 | if (!$id) { |
||||
154 | return $arr; |
||||
155 | } |
||||
156 | |||||
157 | $fileHandler = $this->helper->getHandler('File'); |
||||
158 | $criteria = new \CriteriaCompo(new \Criteria('ticketid', $id)); |
||||
159 | $criteria->setSort('responseid'); |
||||
160 | $arr = $fileHandler->getObjects($criteria); |
||||
161 | |||||
162 | return $arr; |
||||
163 | } |
||||
164 | |||||
165 | /** |
||||
166 | * retrieve all responses attached to this ticket object |
||||
167 | * |
||||
168 | * @param int $limit |
||||
169 | * @param int $start |
||||
170 | * @return array of <a href='psi_element://Response'>Response</a> objects |
||||
171 | * objects |
||||
172 | */ |
||||
173 | public function getResponses(int $limit = 0, int $start = 0): array |
||||
174 | { |
||||
175 | $arr = []; |
||||
176 | $id = (int)$this->getVar('id'); |
||||
177 | if (!$id) { |
||||
178 | return $arr; |
||||
179 | } |
||||
180 | $responseHandler = $this->helper->getHandler('Response'); |
||||
181 | $criteria = new \CriteriaCompo(new \Criteria('ticketid', $id)); |
||||
182 | $criteria->setSort('updateTime'); |
||||
183 | $criteria->setOrder('DESC'); |
||||
184 | $criteria->setLimit($limit); |
||||
185 | $criteria->setStart($start); |
||||
186 | |||||
187 | $arr = $responseHandler->getObjects($criteria); |
||||
188 | |||||
189 | return $arr; |
||||
190 | } |
||||
191 | |||||
192 | /** |
||||
193 | * Retrieve number of responses for this ticket object |
||||
194 | * @return int Number of Responses |
||||
195 | */ |
||||
196 | public function getResponseCount(): int |
||||
197 | { |
||||
198 | $responseHandler = $this->helper->getHandler('Response'); |
||||
199 | $criteria = new \Criteria('ticketid', $this->getVar('id')); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
200 | |||||
201 | return $responseHandler->getCount($criteria); |
||||
202 | } |
||||
203 | |||||
204 | /** |
||||
205 | * Get all reviews for the current ticket |
||||
206 | * @param int $limit |
||||
207 | * @param int $start |
||||
208 | * @return array of <a href='psi_element://StaffReview'>StaffReview</a> |
||||
209 | */ |
||||
210 | public function getReviews(int $limit = 0, int $start = 0): array |
||||
211 | { |
||||
212 | $helper = Helper::getInstance(); |
||||
213 | $arr = []; |
||||
214 | $id = (int)$this->getVar('id'); |
||||
215 | if (!$id) { |
||||
216 | return $arr; |
||||
217 | } |
||||
218 | /** @var \XoopsModules\Xhelp\StaffReviewHandler $staffReviewHandler */ |
||||
219 | $staffReviewHandler = $helper->getHandler('StaffReview'); |
||||
220 | $criteria = new \CriteriaCompo(new \Criteria('ticketid', $id)); |
||||
221 | $criteria->setSort('responseid'); |
||||
222 | $criteria->setOrder('DESC'); |
||||
223 | $criteria->setLimit($limit); |
||||
224 | $criteria->setStart($start); |
||||
225 | |||||
226 | $arr = $staffReviewHandler->getObjects($criteria); |
||||
227 | |||||
228 | return $arr; |
||||
229 | } |
||||
230 | |||||
231 | /** |
||||
232 | * retrieve all log messages attached to this ticket object |
||||
233 | * |
||||
234 | * @param int $limit |
||||
235 | * @param int $start |
||||
236 | * @return array of <a href='psi_element://LogMessages'>LogMessages</a> objects |
||||
237 | * objects |
||||
238 | */ |
||||
239 | public function getLogs(int $limit = 0, int $start = 0): array |
||||
240 | { |
||||
241 | $arr = []; |
||||
242 | $id = (int)$this->getVar('id'); |
||||
243 | if (!$id) { |
||||
244 | return $arr; |
||||
245 | } |
||||
246 | /** @var \XoopsModules\Xhelp\LogMessageHandler $this- >logmessageHandler */ |
||||
247 | $logMessageHandler = $this->helper->getHandler('LogMessage'); |
||||
248 | $criteria = new \CriteriaCompo(new \Criteria('ticketid', $id)); |
||||
249 | $criteria->setSort('lastUpdated'); |
||||
250 | $criteria->setOrder('DESC'); |
||||
251 | $criteria->setLimit($limit); |
||||
252 | $criteria->setStart($start); |
||||
253 | |||||
254 | $arr = $logMessageHandler->getObjects($criteria); |
||||
255 | |||||
256 | return $arr; |
||||
257 | } |
||||
258 | |||||
259 | /** |
||||
260 | * @param string $post_field |
||||
261 | * @param \XoopsModules\Xhelp\Response|string|null $response |
||||
262 | * @param array|string|null $allowed_mimetypes |
||||
263 | * @return \XoopsModules\Xhelp\File|array|false|string|void |
||||
264 | */ |
||||
265 | public function storeUpload(string $post_field, $response = null, $allowed_mimetypes = null) |
||||
266 | { |
||||
267 | global $xoopsUser, $xoopsDB, $xoopsModule; |
||||
268 | // require_once XHELP_CLASS_PATH . '/uploader.php'; |
||||
269 | |||||
270 | $config = Utility::getModuleConfig(); |
||||
271 | |||||
272 | $ticketid = $this->getVar('id'); |
||||
273 | |||||
274 | if (null === $allowed_mimetypes) { |
||||
275 | $mimetypeHandler = $this->helper->getHandler('Mimetype'); |
||||
276 | $allowed_mimetypes = $mimetypeHandler->checkMimeTypes($post_field); |
||||
277 | if (!$allowed_mimetypes) { |
||||
278 | return false; |
||||
279 | } |
||||
280 | } |
||||
281 | |||||
282 | $maxfilesize = (int)$config['xhelp_uploadSize']; |
||||
283 | $maxfilewidth = (int)$config['xhelp_uploadWidth']; |
||||
284 | $maxfileheight = (int)$config['xhelp_uploadHeight']; |
||||
285 | if (!\is_dir(XHELP_UPLOAD_PATH)) { |
||||
0 ignored issues
–
show
|
|||||
286 | if (!\mkdir($concurrentDirectory = XHELP_UPLOAD_PATH, 0757) && !\is_dir($concurrentDirectory)) { |
||||
287 | throw new \RuntimeException(\sprintf('Directory "%s" was not created', $concurrentDirectory)); |
||||
288 | } |
||||
289 | } |
||||
290 | |||||
291 | $uploader = new MediaUploader(XHELP_UPLOAD_PATH . '/', $allowed_mimetypes, $maxfilesize, $maxfilewidth, $maxfileheight); |
||||
0 ignored issues
–
show
It seems like
$allowed_mimetypes can also be of type string ; however, parameter $allowedMimeTypes of XoopsModules\Xhelp\MediaUploader::__construct() does only seem to accept array|integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
292 | if ($uploader->fetchMedia($post_field)) { |
||||
293 | if (null === $response) { |
||||
294 | $uploader->setTargetFileName($ticketid . '_' . $uploader->getMediaName()); |
||||
295 | } else { |
||||
296 | if ($response > 0) { |
||||
297 | $uploader->setTargetFileName($ticketid . '_' . $response . '_' . $uploader->getMediaName()); |
||||
0 ignored issues
–
show
Are you sure
$response of type XoopsModules\Xhelp\Response|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
![]() |
|||||
298 | } else { |
||||
299 | $uploader->setTargetFileName($ticketid . '_' . $uploader->getMediaName()); |
||||
300 | } |
||||
301 | } |
||||
302 | if ($uploader->upload()) { |
||||
303 | $fileHandler = $this->helper->getHandler('File'); |
||||
304 | $file = $fileHandler->create(); |
||||
305 | $file->setVar('filename', $uploader->getSavedFileName()); |
||||
306 | $file->setVar('ticketid', $ticketid); |
||||
307 | $file->setVar('mimetype', $allowed_mimetypes); |
||||
308 | $file->setVar('responseid', (null !== $response ? (int)$response : 0)); |
||||
309 | |||||
310 | if ($fileHandler->insert($file)) { |
||||
311 | return $file; |
||||
312 | } |
||||
313 | |||||
314 | return $uploader->getErrors(); |
||||
315 | } |
||||
316 | |||||
317 | return $uploader->getErrors(); |
||||
318 | } |
||||
319 | } |
||||
320 | |||||
321 | /** |
||||
322 | * @param string $post_field |
||||
323 | * @param array|null $allowed_mimetypes |
||||
324 | * @param array $errors |
||||
325 | * @return bool |
||||
326 | */ |
||||
327 | public function checkUpload(string $post_field, ?array &$allowed_mimetypes, array &$errors): bool |
||||
328 | { |
||||
329 | // require_once XHELP_CLASS_PATH . '/uploader.php'; |
||||
330 | $config = Utility::getModuleConfig(); |
||||
331 | |||||
332 | $maxfilesize = (int)$config['xhelp_uploadSize']; |
||||
333 | $maxfilewidth = (int)$config['xhelp_uploadWidth']; |
||||
334 | $maxfileheight = (int)$config['xhelp_uploadHeight']; |
||||
335 | $errors = []; |
||||
336 | |||||
337 | if (null === $allowed_mimetypes) { |
||||
338 | $mimetypeHandler = $this->helper->getHandler('Mimetype'); |
||||
339 | $allowed_mimetypes = $mimetypeHandler->checkMimeTypes($post_field); |
||||
340 | if (!$allowed_mimetypes) { |
||||
341 | $errors[] = \_XHELP_MESSAGE_WRONG_MIMETYPE; |
||||
342 | |||||
343 | return false; |
||||
344 | } |
||||
345 | } |
||||
346 | $uploader = new MediaUploader(XHELP_UPLOAD_PATH . '/', $allowed_mimetypes, $maxfilesize, $maxfilewidth, $maxfileheight); |
||||
0 ignored issues
–
show
|
|||||
347 | |||||
348 | if ($uploader->fetchMedia($post_field)) { |
||||
349 | return true; |
||||
350 | } |
||||
351 | |||||
352 | $errors = \array_merge($errors, $uploader->getErrors(false)); |
||||
353 | |||||
354 | return false; |
||||
355 | } |
||||
356 | |||||
357 | /** |
||||
358 | * determine last time the ticket was updated relative to the current user |
||||
359 | * |
||||
360 | * @param string $format |
||||
361 | * @return int Timestamp of last update |
||||
362 | */ |
||||
363 | public function lastUpdated(string $format = 'l'): int |
||||
364 | { |
||||
365 | return (int)\formatTimestamp($this->getVar('lastUpdated'), $format); |
||||
366 | } |
||||
367 | |||||
368 | /** |
||||
369 | * @param string $format |
||||
370 | * @return string |
||||
371 | */ |
||||
372 | public function posted(string $format = 'l'): string |
||||
373 | { |
||||
374 | return \formatTimestamp($this->getVar('posted'), $format); |
||||
375 | } |
||||
376 | |||||
377 | /** |
||||
378 | * return a simplified measurement of elapsed ticket time |
||||
379 | * |
||||
380 | * @return string Elapsed time |
||||
381 | */ |
||||
382 | public function elapsed(): string |
||||
383 | { |
||||
384 | $tmp = Utility::getElapsedTime($this->getVar('elapsed')); |
||||
385 | |||||
386 | return $this->prettyElapsed($tmp); |
||||
0 ignored issues
–
show
|
|||||
387 | } |
||||
388 | |||||
389 | /** |
||||
390 | * @return string |
||||
391 | */ |
||||
392 | public function lastUpdate(): string |
||||
393 | { |
||||
394 | $tmp = Utility::getElapsedTime($this->getVar('lastUpdate')); |
||||
395 | |||||
396 | return $this->prettyElapsed($tmp); |
||||
0 ignored issues
–
show
|
|||||
397 | } |
||||
398 | |||||
399 | /** |
||||
400 | * @param array $time |
||||
401 | * @return string |
||||
402 | */ |
||||
403 | private function prettyElapsed(array $time): ?string |
||||
404 | { |
||||
405 | $useSingle = false; |
||||
406 | |||||
407 | foreach ($time as $unit => $value) { |
||||
408 | if ($value) { |
||||
409 | if (1 == $value) { |
||||
410 | $useSingle = true; |
||||
411 | } |
||||
412 | switch ($unit) { |
||||
413 | case 'years': |
||||
414 | $unit_dsc = ($useSingle ? \_XHELP_TIME_YEAR : \_XHELP_TIME_YEARS); |
||||
415 | break; |
||||
416 | case 'weeks': |
||||
417 | $unit_dsc = ($useSingle ? \_XHELP_TIME_WEEK : \_XHELP_TIME_WEEKS); |
||||
418 | break; |
||||
419 | case 'days': |
||||
420 | $unit_dsc = ($useSingle ? \_XHELP_TIME_DAY : \_XHELP_TIME_DAYS); |
||||
421 | break; |
||||
422 | case 'hours': |
||||
423 | $unit_dsc = ($useSingle ? \_XHELP_TIME_HOUR : \_XHELP_TIME_HOURS); |
||||
424 | break; |
||||
425 | case 'minutes': |
||||
426 | $unit_dsc = ($useSingle ? \_XHELP_TIME_MIN : \_XHELP_TIME_MINS); |
||||
427 | break; |
||||
428 | case 'seconds': |
||||
429 | $unit_dsc = ($useSingle ? \_XHELP_TIME_SEC : \_XHELP_TIME_SECS); |
||||
430 | break; |
||||
431 | default: |
||||
432 | $unit_dsc = $unit; |
||||
433 | break; |
||||
434 | } |
||||
435 | |||||
436 | return "$value $unit_dsc"; |
||||
437 | } |
||||
438 | } |
||||
439 | } |
||||
440 | |||||
441 | /** |
||||
442 | * Determine if ticket is overdue |
||||
443 | * |
||||
444 | * @return bool |
||||
445 | */ |
||||
446 | public function isOverdue(): bool |
||||
447 | { |
||||
448 | $config = Utility::getModuleConfig(); |
||||
449 | $statusHandler = $this->helper->getHandler('Status'); |
||||
450 | if (isset($config['xhelp_overdueTime'])) { |
||||
451 | $overdueTime = $config['xhelp_overdueTime']; |
||||
452 | |||||
453 | if ($overdueTime) { |
||||
454 | $status = $statusHandler->get($this->getVar('status')); |
||||
455 | if (1 == $status->getVar('state')) { |
||||
456 | if (\time() > $this->getVar('overdueTime')) { |
||||
457 | return true; |
||||
458 | } |
||||
459 | } |
||||
460 | } |
||||
461 | } |
||||
462 | |||||
463 | return false; |
||||
464 | } |
||||
465 | |||||
466 | /** |
||||
467 | * @param string $email |
||||
468 | * @param int $uid |
||||
469 | * @param int $suppress |
||||
470 | * @return bool |
||||
471 | */ |
||||
472 | public function addSubmitter(string $email, int $uid, int $suppress = 0): bool |
||||
473 | { |
||||
474 | $uid = $uid; |
||||
475 | |||||
476 | if ('' != $email) { |
||||
477 | $ticketEmailsHandler = $this->helper->getHandler('TicketEmails'); |
||||
478 | $tEmail = $ticketEmailsHandler->create(); |
||||
479 | |||||
480 | $tEmail->setVar('ticketid', $this->getVar('id')); |
||||
481 | $tEmail->setVar('email', $email); |
||||
482 | $tEmail->setVar('uid', $uid); |
||||
483 | $tEmail->setVar('suppress', $suppress); |
||||
484 | |||||
485 | if ($ticketEmailsHandler->insert($tEmail)) { |
||||
486 | return true; |
||||
487 | } |
||||
488 | } |
||||
489 | |||||
490 | return false; |
||||
491 | } |
||||
492 | |||||
493 | /** |
||||
494 | * @param int $ticket2_id |
||||
495 | * @return bool|mixed |
||||
496 | */ |
||||
497 | public function merge(int $ticket2_id) |
||||
498 | { |
||||
499 | global $xoopsDB; |
||||
500 | $ticket2_id = $ticket2_id; |
||||
501 | |||||
502 | // Retrieve $ticket2 |
||||
503 | $ticketHandler = $this->helper->getHandler('Ticket'); |
||||
504 | $mergeTicket = $ticketHandler->get($ticket2_id); |
||||
505 | |||||
506 | // Figure out which ticket is older |
||||
507 | if ($this->getVar('posted') < $mergeTicket->getVar('posted')) { // If this ticket is older than the 2nd ticket |
||||
508 | $keepTicket = $this; |
||||
509 | $loseTicket = $mergeTicket; |
||||
510 | } else { |
||||
511 | $keepTicket = $mergeTicket; |
||||
512 | $loseTicket = $this; |
||||
513 | } |
||||
514 | |||||
515 | $keep_id = $keepTicket->getVar('id'); |
||||
516 | $lose_id = $loseTicket->getVar('id'); |
||||
517 | |||||
518 | // Copy ticket subject and description of 2nd ticket as response to $this ticket |
||||
519 | $responseid = $keepTicket->addResponse($loseTicket->getVar('uid'), $keep_id, $loseTicket->getVar('subject', 'e') . ' - ' . $loseTicket->getVar('description', 'e'), $loseTicket->getVar('posted'), $loseTicket->getVar('userIP')); |
||||
520 | |||||
521 | // Copy 2nd ticket file attachments to $this ticket |
||||
522 | $fileHandler = $this->helper->getHandler('File'); |
||||
523 | $criteria = new \Criteria('ticketid', $lose_id); |
||||
0 ignored issues
–
show
It seems like
$lose_id can also be of type array and array ; however, parameter $value of Criteria::__construct() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
524 | $files = $fileHandler->getObjects($criteria); |
||||
525 | foreach ($files as $file) { |
||||
526 | $file->rename($keep_id, $responseid); |
||||
527 | } |
||||
528 | $success = $fileHandler->updateAll('ticketid', $keep_id, $criteria); |
||||
529 | |||||
530 | // Copy 2nd ticket responses as responses to $this ticket |
||||
531 | $responseHandler = $this->helper->getHandler('Response'); |
||||
532 | $criteria = new \Criteria('ticketid', $lose_id); |
||||
533 | $success = $responseHandler->updateAll('ticketid', $keep_id, $criteria); |
||||
534 | |||||
535 | // Change file responseid to match the response added to merged ticket |
||||
536 | $criteria = new \CriteriaCompo(new \Criteria('ticketid', $lose_id)); |
||||
537 | $criteria->add(new \Criteria('responseid', 0)); |
||||
538 | $success = $fileHandler->updateAll('responseid', $responseid, $criteria); |
||||
539 | |||||
540 | // Add 2nd ticket submitter to $this ticket via ticketEmails table |
||||
541 | $ticketEmailsHandler = $this->helper->getHandler('TicketEmails'); |
||||
542 | $criteria = new \Criteria('ticketid', $lose_id); |
||||
543 | $success = $ticketEmailsHandler->updateAll('ticketid', $keep_id, $criteria); |
||||
544 | |||||
545 | // Remove $loseTicket |
||||
546 | $criteria = new \Criteria('id', $lose_id); |
||||
547 | if (!$ticketHandler->deleteAll($criteria)) { |
||||
548 | return false; |
||||
549 | } |
||||
550 | |||||
551 | return $keep_id; |
||||
552 | } |
||||
553 | |||||
554 | /** |
||||
555 | * Check if the supplied user can add a response to the ticket |
||||
556 | * @param \XoopsUser $xoopsUser The user to check |
||||
557 | * @return bool |
||||
558 | */ |
||||
559 | public function canAddResponse(\XoopsUser $xoopsUser): bool |
||||
560 | { |
||||
561 | //1. If the $xoopsUser a valid \XoopsUser Object |
||||
562 | if (!$xoopsUser instanceof \XoopsUser) { |
||||
563 | return false; |
||||
564 | } |
||||
565 | |||||
566 | //2. Is the user one of the "ticket submitters" |
||||
567 | $ticketEmailsHandler = $this->helper->getHandler('TicketEmails'); |
||||
568 | $criteria = new \CriteriaCompo(new \Criteria('ticketid', $this->getVar('id'))); |
||||
0 ignored issues
–
show
It seems like
$this->getVar('id') can also be of type array and array ; however, parameter $value of Criteria::__construct() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
569 | $criteria->add(new \Criteria('uid', $xoopsUser->getVar('uid'))); |
||||
570 | $count = $ticketEmailsHandler->getCount($criteria); |
||||
571 | |||||
572 | if ($count > 0) { |
||||
573 | return true; |
||||
574 | } |
||||
575 | |||||
576 | //3. Is the user a staff member? |
||||
577 | global $xhelp_isStaff, $staff; |
||||
578 | if ($xhelp_isStaff) { |
||||
579 | if ($staff->checkRoleRights(\XHELP_SEC_RESPONSE_ADD, $this->getVar('department'))) { |
||||
580 | return true; |
||||
581 | } |
||||
582 | } |
||||
583 | |||||
584 | //4. If neither option is true, user cannot add response. |
||||
585 | return false; |
||||
586 | } |
||||
587 | |||||
588 | /** |
||||
589 | * @param int $uid |
||||
590 | * @param int $ticketid |
||||
591 | * @param string $message |
||||
592 | * @param int $updateTime |
||||
593 | * @param string $userIP |
||||
594 | * @param int $private |
||||
595 | * @param int $timeSpent |
||||
596 | * @param bool $ret_obj |
||||
597 | * @return bool|mixed|\XoopsObject |
||||
598 | */ |
||||
599 | public function addResponse( |
||||
600 | int $uid, int $ticketid, string $message, int $updateTime, string $userIP, int $private = 0, int $timeSpent = 0, bool $ret_obj = false |
||||
601 | ) { |
||||
602 | $uid = $uid; |
||||
603 | $ticketid = $ticketid; |
||||
604 | $updateTime = $updateTime; |
||||
605 | $private = $private; |
||||
606 | $timeSpent = $timeSpent; |
||||
607 | |||||
608 | $responseHandler = $this->helper->getHandler('Response'); |
||||
609 | $newResponse = $responseHandler->create(); |
||||
610 | $newResponse->setVar('uid', $uid); |
||||
611 | $newResponse->setVar('ticketid', $ticketid); |
||||
612 | $newResponse->setVar('message', $message); |
||||
613 | $newResponse->setVar('timeSpent', $timeSpent); |
||||
614 | $newResponse->setVar('updateTime', $updateTime); |
||||
615 | $newResponse->setVar('userIP', $userIP); |
||||
616 | $newResponse->setVar('private', $private); |
||||
617 | if ($responseHandler->insert($newResponse)) { |
||||
618 | if ($ret_obj) { |
||||
619 | return $newResponse; |
||||
620 | } |
||||
621 | |||||
622 | return $newResponse->getVar('id'); |
||||
623 | } |
||||
624 | |||||
625 | return false; |
||||
626 | } |
||||
627 | |||||
628 | /** |
||||
629 | * @param bool $includeEmptyValues |
||||
630 | * @return array |
||||
631 | */ |
||||
632 | public function &getCustFieldValues(bool $includeEmptyValues = false): array |
||||
633 | { |
||||
634 | $ticketid = $this->getVar('id'); |
||||
635 | |||||
636 | /** @var \XoopsModules\Xhelp\TicketFieldHandler $ticketFieldHandler */ |
||||
637 | $ticketFieldHandler = $this->helper->getHandler('TicketField'); |
||||
638 | $fields = $ticketFieldHandler->getObjects(null); // Retrieve custom fields |
||||
639 | |||||
640 | $ticketValuesHandler = $this->helper->getHandler('TicketValues'); |
||||
641 | $values = $ticketValuesHandler->get($ticketid); // Retrieve custom field values |
||||
642 | $aCustFields = []; |
||||
643 | foreach ($fields as $field) { |
||||
644 | $fileid = ''; |
||||
645 | $filename = ''; |
||||
646 | $value = ''; |
||||
647 | $key = ''; |
||||
648 | $hasValue = false; |
||||
649 | $_arr = $field->toArray(); |
||||
650 | |||||
651 | if (false !== $values |
||||
652 | && '' != $values->getVar($field->getVar('fieldname'))) { // If values for this field has something |
||||
653 | $fieldvalues = $field->getVar('fieldvalues'); // Set fieldvalues |
||||
654 | $value = $key = $values->getVar($field->getVar('fieldname')); // Value of current field |
||||
655 | |||||
656 | if (\XHELP_CONTROL_YESNO == $field->getVar('controltype')) { |
||||
657 | $value = ((1 == $value) ? _YES : _NO); |
||||
658 | } |
||||
659 | |||||
660 | if (\XHELP_CONTROL_FILE == $field->getVar('controltype')) { |
||||
661 | $file = \explode('_', $value); |
||||
662 | $fileid = $file[0]; |
||||
663 | $filename = $file[1]; |
||||
664 | } |
||||
665 | |||||
666 | if (\is_array($fieldvalues)) { |
||||
667 | foreach ($fieldvalues as $fkey => $fvalue) { |
||||
668 | if ($fkey == $value) { |
||||
669 | $value = $fvalue; |
||||
670 | break; |
||||
671 | } |
||||
672 | } |
||||
673 | } |
||||
674 | |||||
675 | $hasValue = true; |
||||
676 | } |
||||
677 | $_arr['value'] = $value; |
||||
678 | $_arr['fileid'] = $fileid; |
||||
679 | $_arr['filename'] = $filename; |
||||
680 | $_arr['key'] = $key; |
||||
681 | |||||
682 | if ($includeEmptyValues || $hasValue) { |
||||
683 | $aCustFields[$field->getVar('fieldname')] = $_arr; |
||||
684 | } |
||||
685 | } |
||||
686 | |||||
687 | return $aCustFields; |
||||
688 | } |
||||
689 | } // end of class |
||||
690 |