dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxContactList.class.php
Go to the documentation of this file.
1<?php
2namespace dbx\dbxContact;
3
4require_once __DIR__ . '/dbxContactTicket.class.php';
5
7
8 private function db() {
9 return dbx()->get_system_obj('dbxDB');
10 }
11
12 private function tpl() {
13 return dbx()->get_system_obj('dbxTPL');
14 }
15
16 private function h($value): string {
17 return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
18 }
19
20 private function denied(): string {
21 $form = dbx()->get_system_obj('dbxForm');
22 $form->init('contact-list-messages', 'dbx|form');
23 $form->load_fd_messages('dbxContact|contact-list');
24 return $this->tpl()->get_tpl('dbx|alert-warning', array(
25 'msg' => $form->get_fd_message('login_required'),
26 ));
27 }
28
29 private function statusClass(string $status): string {
30 return array(
31 'open' => 'text-bg-primary',
32 'in_progress' => 'text-bg-info',
33 'waiting_customer' => 'text-bg-warning',
34 'answered' => 'text-bg-success',
35 'closed' => 'text-bg-secondary',
36 )[$status] ?? 'text-bg-light';
37 }
38
39 private function ticketForUser(int $rid, int $uid): array {
40 $ticket = dbxContactTicket::ticket($this->db(), $rid);
41 if (!$ticket || !dbxContactTicket::userOwns($ticket, $uid) || (int) ($ticket['user_hidden'] ?? 0) === 1) {
42 return array();
43 }
44 return $ticket;
45 }
46
47 private function excerpt($value, int $max = 120): string {
48 $value = trim((string) preg_replace('/\s+/', ' ', (string) $value));
49 if (strlen($value) > $max) {
50 $value = substr($value, 0, $max - 3) . '...';
51 }
52 return $this->h($value);
53 }
54
55 private function decorateRows(array $rows, $report): array {
56 $out = array();
57 foreach ($rows as $row) {
58 $status = dbxContactTicket::normalizeStatus((string) ($row['status'] ?? 'open'));
59 $statusLabel = $report->get_fd_message(
60 'status_' . $status,
61 $status
62 );
63 $row['status_view'] = '<span class="badge ' . $this->statusClass($status) . '">' . $this->h($statusLabel) . '</span>';
64 $row['subject_view'] = $this->excerpt($row['subject'] ?? '', 90);
65 $row['action'] = $this->tpl()->get_tpl('dbxContact|contact-ticket-row-action', array(
66 'rid' => (int) ($row['id'] ?? 0),
67 ));
68 $out[] = $row;
69 }
70 return $out;
71 }
72
73 public function contactListReportRowActionData($report, $data): array {
74 if (!is_array($data) || (string) ($data['type'] ?? '') !== 'delete') {
75 return $data;
76 }
77
78 $rid = (int) ($data['record']['id'] ?? $data['data']['rid'] ?? 0);
79 $data['data']['action'] = '?dbx_modul=dbxContact&dbx_run1=my&dbx_run2=delete&rid=' . $rid;
80 $data['data']['tooltip'] = $report->get_fd_message(
81 'delete_tooltip'
82 );
83
84 return $data;
85 }
86
87 private function listTickets(int $uid): string {
88 $db = $this->db();
89 $report = dbx()->get_system_obj('dbxReport');
90 $where = 'uid = ' . $uid . ' AND user_hidden = 0';
91
92 $report->init('contact-list', 'dbxContact|contact-list');
93 $report->_fd = 'dbxContact|contact-list';
94 $report->load_fd_messages();
95 $report->add_rep(
96 'bar_title',
97 $report->get_fd_message('bar_title')
98 );
99 $report->add_rep('bar_icon', 'bi-life-preserver');
100 $report->add_rep(
101 'bar_subtitle',
102 $report->get_fd_message('bar_subtitle')
103 );
104 $report->add_rep(
105 'bar_actions',
106 $this->tpl()->get_tpl('dbxContact|contact-new-request-button')
107 );
109 $report->_action = '?dbx_modul=dbxContact&dbx_run1=my';
110 $report->_pages = true;
111 $report->_create_row_select = false;
112 $report->_create_row_edit = false;
113 $report->_create_row_delete = true;
114 $report->_table_buttons = 'left';
115 $report->_msg_confirm_delete = $report->get_fd_message(
116 'delete_confirm'
117 );
118 $report->set_callback_owner($this);
119 $report->set_callback('row_action_data', 'contactListReportRowActionData');
120 $report->set_tabel_tpl('tpl_row_delete', 'modul|contact-ticket-row-delete');
121 $report->_rflds = array(
122 'id' => $report->get_fd_message('column_ticket'),
123 'last_activity_date' => $report->get_fd_message(
124 'column_activity'
125 ),
126 'status_view' => $report->get_fd_message('column_status'),
127 'subject_view' => $report->get_fd_message('column_subject'),
128 'action' => '&nbsp;',
129 );
130 $report->_rpt_format = array(
131 'last_activity_date' => 'php-datetime-usr',
132 'status_view' => 'html',
133 'subject_view' => 'html',
134 'action' => 'html',
135 );
136 $report->_rrows = 30;
137 $report->_rpos = 0;
138 $report->_count_all = $db->count(dbxContactTicket::DD_TICKET, $where);
139 $report->_rcount = $report->_count_all;
140 $rows = $db->select(
142 $where,
143 array('id', 'last_activity_date', 'create_date', 'status', 'subject'),
144 'last_activity_date,id',
145 'DESC',
146 '',
147 30,
148 0,
149 0
150 );
151 $report->_rdata = $this->decorateRows(
152 is_array($rows) ? $rows : array(),
153 $report
154 );
155
156 return $report->run();
157 }
158
159 private function timeline(array $ticket, array $messages): string {
160 $db = $this->db();
161 dbxContactTicket::ensureInitialMessage($db, $ticket);
162 $html = '';
163
164 foreach (dbxContactTicket::messages($db, (int) $ticket['id'], false) as $message) {
165 $authorType = (string) ($message['author_type'] ?? 'system');
166 $statusTo = trim((string) ($message['status_to'] ?? ''));
167 $html .= $this->tpl()->get_tpl('dbxContact|contact-ticket-message', array(
168 'message_class' => $authorType === 'admin' ? 'border-primary bg-primary-subtle' : 'bg-body-tertiary',
169 'message_icon' => $authorType === 'admin' ? 'bi-headset' : ($authorType === 'requester' ? 'bi-person' : 'bi-gear'),
170 'author_label' => $messages[
171 $authorType === 'admin'
172 ? 'author_admin'
173 : ($authorType === 'requester'
174 ? 'author_requester'
175 : 'author_system')
176 ] ?? $authorType,
177 'create_date' => $this->h($message['create_date'] ?? ''),
178 'body' => nl2br($this->h($message['body'] ?? '')),
179 'status_badge' => $statusTo !== ''
180 ? '<span class="badge ' . $this->statusClass($statusTo) . '">'
181 . $this->h($messages['status_prefix'] ?? 'Status:')
182 . ' '
183 . $this->h(
184 $messages['status_' . $statusTo] ?? $statusTo
185 )
186 . '</span>'
187 : '',
188 ));
189 }
190
191 return $html !== ''
192 ? $html
193 : '<div class="text-muted">'
194 . $this->h($messages['no_timeline'] ?? '')
195 . '</div>';
196 }
197
198 private function messageForm(array $ticket): string {
199 $rid = (int) $ticket['id'];
200 $form = dbx()->get_system_obj('dbxForm');
201 $form->init('contact-user-message', 'contact-user-message-form');
202 $form->_dd = dbxContactTicket::DD_MESSAGE;
203 $form->_fd = 'dbxContact|contact-user-message';
204 $form->load_fd_messages();
205 $form->prepare_form_shell(array(
206 'form_attrs' => 'data-target="dbx_contact_ticket_' . $rid . '"',
207 ));
208 if ((string) ($ticket['status'] ?? '') === 'closed') {
209 return '<div class="alert alert-secondary mb-0">'
210 . $this->h($form->get_fd_message('ticket_closed'))
211 . '</div>';
212 }
213
214 $form->_action = '?dbx_modul=dbxContact&dbx_run1=my&dbx_run2=ticket&rid=' . $rid;
215 $form->_data = array('body' => '');
216 $form->add_module_bar(
217 $form->get_fd_message('bar_title'),
218 'bi-chat-dots',
219 $form->get_fd_message('bar_subtitle')
220 );
221 $form->add_rep('bar_title_pre', '');
222 $form->add_rep('bar_title_heading_attrs', '');
223 $form->add_rep('bar_middle', '');
224 $form->add_rep('bar_actions', '');
225 $form->add_rep('bar_extra', '');
226 $form->add_rep('rid', $rid);
227 $form->_msg_info = $form->get_fd_message('form_info');
228 $form->_msg_error = $form->get_fd_message('validation_error');
229 $form->add_fld('body');
230
231 if ($form->submit() && !$form->errors()) {
232 $body = trim((string) $form->get_post_data('body', '', '*'));
233 $oldStatus = dbxContactTicket::normalizeStatus((string) ($ticket['status'] ?? 'open'));
234 $messageId = dbxContactTicket::addMessage($this->db(), $rid, array(
235 'author_uid' => (int) dbx()->user(),
236 'author_type' => 'requester',
237 'message_type' => 'message',
238 'visibility' => 'public',
239 'body' => $body,
240 'status_from' => $oldStatus,
241 'status_to' => 'open',
242 ));
243 if ($messageId > 0) {
244 dbxContactTicket::touch($this->db(), $rid, array('status' => 'open', 'closed_date' => ''));
245 $form->_msg_success = $form->get_fd_message(
246 'message_success'
247 );
248 $form->_data['body'] = '';
249 } else {
250 $form->_msg_error = $form->get_fd_message('message_error');
251 }
252 }
253
254 return $form->run();
255 }
256
257 private function ticket(int $uid): string {
258 $rid = (int) dbx()->get_modul_var('rid', 0, 'int');
259 $view = dbx()->get_system_obj('dbxForm');
260 $view->init('contact-ticket-messages', 'dbx|form');
261 $messages = $view->load_fd_messages('dbxContact|contact-list');
262 $ticket = $this->ticketForUser($rid, $uid);
263 if (!$ticket) {
264 return $this->tpl()->get_tpl('dbx|alert-warning', array(
265 'msg' => $view->get_fd_message('ticket_not_found'),
266 ));
267 }
268
269 $messageForm = $this->messageForm($ticket);
270 $ticket = $this->ticketForUser($rid, $uid);
271 $status = dbxContactTicket::normalizeStatus((string) ($ticket['status'] ?? 'open'));
272
273 return $this->tpl()->get_tpl('dbxContact|contact-ticket-detail', array(
274 'bar_class' => 'dbx-module-bar',
275 'bar_title_class' => 'dbx-module-bar-titleblock',
276 'bar_actions_class' => 'dbx-module-bar-actions',
277 'bar_title_pre' => '',
278 'bar_title_heading_attrs' => '',
279 'bar_icon' => 'bi-life-preserver',
280 'bar_title' => $view->format_fd_message(
281 'ticket_title',
282 array('rid' => $rid)
283 ),
284 'bar_subtitle' => $view->get_fd_message('ticket_subtitle'),
285 'bar_middle' => '',
286 'bar_actions' => $this->tpl()->get_tpl(
287 'dbxContact|contact-my-requests-button'
288 ),
289 'bar_extra' => '',
290 'rid' => $rid,
291 'delete_url' => dbx()->action_url(
292 '?dbx_modul=dbxContact&dbx_run1=my&dbx_run2=delete&rid=' . $rid
293 ),
294 'subject' => $this->h($ticket['subject'] ?? ''),
295 'status_label' => $this->h(
296 $messages['status_' . $status] ?? $status
297 ),
298 'status_class' => $this->statusClass($status),
299 'create_date' => $this->h($ticket['create_date'] ?? ''),
300 'timeline' => $this->timeline($ticket, $messages),
301 'message_form' => $messageForm,
302 ));
303 }
304
305 private function deleteTicket(int $uid): string {
306 $rid = (int) dbx()->get_modul_var('rid', 0, 'int');
307 $ticket = $this->ticketForUser($rid, $uid);
308 if (!$ticket) {
309 $view = dbx()->get_system_obj('dbxForm');
310 $view->init('contact-delete-messages', 'dbx|form');
311 $view->load_fd_messages('dbxContact|contact-list');
312 return $this->tpl()->get_tpl('dbx|alert-warning', array(
313 'msg' => $view->get_fd_message('ticket_not_found'),
314 ));
315 }
316
317 $form = dbx()->get_system_obj('dbxForm');
318 $form->init('contact-user-delete', 'contact-user-delete-form');
319 $form->_fd = 'dbxContact|contact-user-delete';
320 $form->load_fd_messages();
321 $form->_action = '?dbx_modul=dbxContact&dbx_run1=my&dbx_run2=delete&rid=' . $rid;
322 $form->_data = array('confirm_delete' => 0);
323 $form->add_module_bar(
324 $form->get_fd_message('bar_title'),
325 'bi-trash'
326 );
327 $form->add_rep('bar_title_pre', '');
328 $form->add_rep('bar_title_heading_attrs', '');
329 $form->add_rep('bar_middle', '');
330 $form->add_rep('bar_actions', '');
331 $form->add_rep('bar_extra', '');
332 $form->add_rep('rid', $rid);
333 $form->_msg_info = '';
334 $form->_msg_error = $form->get_fd_message('validation_error');
335 $form->add_fld('confirm_delete');
336
337 if ($form->submit() && !$form->errors()) {
338 $ok = $this->db()->update(dbxContactTicket::DD_TICKET, array(
339 'user_hidden' => 1,
340 'user_hidden_date' => date('Y-m-d H:i:s'),
341 ), 'id = ' . $rid . ' AND uid = ' . $uid, 0, 1, 1, 1);
342 if ($ok === 1) {
343 return $this->tpl()->get_tpl('dbx|alert-success', array(
344 'msg' => $form->get_fd_message('delete_success'),
345 )) . $this->tpl()->get_tpl(
346 'dbxContact|contact-delete-back-button'
347 );
348 }
349 $form->_msg_error = $form->get_fd_message('delete_error');
350 }
351
352 return $form->run();
353 }
354
355 public function run() {
356 $uid = (int) dbx()->user();
357 if ($uid <= 0) {
358 return $this->denied();
359 }
360
361 $run2 = dbx()->get_modul_var('dbx_run2', 'list', 'parameter');
362 if ($run2 === 'ticket') {
363 return $this->ticket($uid);
364 }
365 if ($run2 === 'delete') {
366 return $this->deleteTicket($uid);
367 }
368 return $this->listTickets($uid);
369 }
370}
static userOwns(array $ticket, int $uid)
static normalizeStatus(string $status, string $fallback='open')
$messages
Definition config.fd.php:2
if((string)($formActionPolicy['action'] ?? '') !=='dbxAction.save'||!dbx() ->check_action_token((string)($formActionPolicy['scope'] ?? ''),(string)($formActionRoute['params']['dbx_token'] ?? ''))) $report
action_url(string $url, string $action='', array $bindings=array())
Tokenisiert eine automatisch erkannte zustandsaendernde Route.
Definition dbxApi.php:1270
user($key='id')
Liest einen Wert des aktuellen Benutzers.
Definition dbxApi.php:1305
if(!defined( 'IMG_WEBP')) define( 'IMG_WEBP'
DBX schema administration.