8 private function db() {
9 return dbx()->get_system_obj(
'dbxDB');
12 private function tpl() {
13 return dbx()->get_system_obj(
'dbxTPL');
16 private function h(
$value):
string {
17 return htmlspecialchars((
string)
$value, ENT_QUOTES,
'UTF-8');
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'),
29 private function statusClass(
string $status):
string {
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';
39 private function ticketForUser(
int $rid,
int $uid): array {
47 private function excerpt(
$value,
int $max = 120):
string {
48 $value = trim((
string) preg_replace(
'/\s+/',
' ', (
string)
$value));
49 if (strlen(
$value) > $max) {
55 private function decorateRows(array
$rows,
$report): array {
57 foreach (
$rows as $row) {
59 $statusLabel =
$report->get_fd_message(
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),
74 if (!is_array($data) || (string) ($data[
'type'] ??
'') !==
'delete') {
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(
87 private function listTickets(
int $uid): string {
90 $where =
'uid = ' . $uid .
' AND user_hidden = 0';
92 $report->init(
'contact-list',
'dbxContact|contact-list');
93 $report->_fd =
'dbxContact|contact-list';
97 $report->get_fd_message(
'bar_title')
99 $report->add_rep(
'bar_icon',
'bi-life-preserver');
102 $report->get_fd_message(
'bar_subtitle')
106 $this->tpl()->get_tpl(
'dbxContact|contact-new-request-button')
109 $report->_action =
'?dbx_modul=dbxContact&dbx_run1=my';
111 $report->_create_row_select =
false;
112 $report->_create_row_edit =
false;
113 $report->_create_row_delete =
true;
114 $report->_table_buttons =
'left';
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');
122 'id' =>
$report->get_fd_message(
'column_ticket'),
123 'last_activity_date' =>
$report->get_fd_message(
126 'status_view' =>
$report->get_fd_message(
'column_status'),
127 'subject_view' =>
$report->get_fd_message(
'column_subject'),
128 'action' =>
' ',
131 'last_activity_date' =>
'php-datetime-usr',
132 'status_view' =>
'html',
133 'subject_view' =>
'html',
143 array(
'id',
'last_activity_date',
'create_date',
'status',
'subject'),
144 'last_activity_date,id',
151 $report->_rdata = $this->decorateRows(
159 private function timeline(array $ticket, array
$messages): string {
161 dbxContactTicket::ensureInitialMessage(
$db, $ticket);
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'),
171 $authorType ===
'admin'
173 : ($authorType ===
'requester'
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:')
184 $messages[
'status_' . $statusTo] ?? $statusTo
193 :
'<div class="text-muted">'
194 . $this->h(
$messages[
'no_timeline'] ??
'')
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 .
'"',
208 if ((
string) ($ticket[
'status'] ??
'') ===
'closed') {
209 return '<div class="alert alert-secondary mb-0">'
210 . $this->h(
$form->get_fd_message(
'ticket_closed'))
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'),
219 $form->get_fd_message(
'bar_subtitle')
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');
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',
240 'status_from' => $oldStatus,
241 'status_to' =>
'open',
243 if ($messageId > 0) {
244 dbxContactTicket::touch($this->db(), $rid, array(
'status' =>
'open',
'closed_date' =>
''));
248 $form->_data[
'body'] =
'';
250 $form->_msg_error =
$form->get_fd_message(
'message_error');
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);
264 return $this->tpl()->get_tpl(
'dbx|alert-warning', array(
265 'msg' => $view->get_fd_message(
'ticket_not_found'),
269 $messageForm = $this->messageForm($ticket);
270 $ticket = $this->ticketForUser($rid, $uid);
271 $status = dbxContactTicket::normalizeStatus((
string) ($ticket[
'status'] ??
'open'));
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(
284 'bar_subtitle' => $view->get_fd_message(
'ticket_subtitle'),
286 'bar_actions' => $this->tpl()->get_tpl(
287 'dbxContact|contact-my-requests-button'
292 '?dbx_modul=dbxContact&dbx_run1=my&dbx_run2=delete&rid=' . $rid
294 'subject' => $this->h($ticket[
'subject'] ??
''),
295 'status_label' => $this->h(
296 $messages[
'status_' . $status] ?? $status
298 'status_class' => $this->statusClass($status),
299 'create_date' => $this->h($ticket[
'create_date'] ??
''),
300 'timeline' => $this->timeline($ticket,
$messages),
301 'message_form' => $messageForm,
305 private function deleteTicket(
int $uid): string {
306 $rid = (int)
dbx()->get_modul_var(
'rid', 0,
'int');
307 $ticket = $this->ticketForUser($rid, $uid);
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'),
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'),
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');
338 $ok = $this->db()->update(dbxContactTicket::DD_TICKET, array(
340 'user_hidden_date' => date(
'Y-m-d H:i:s'),
341 ),
'id = ' . $rid .
' AND uid = ' . $uid, 0, 1, 1, 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'
349 $form->_msg_error =
$form->get_fd_message(
'delete_error');
356 $uid = (int)
dbx()->user();
358 return $this->denied();
361 $run2 =
dbx()->get_modul_var(
'dbx_run2',
'list',
'parameter');
362 if ($run2 ===
'ticket') {
363 return $this->ticket($uid);
365 if ($run2 ===
'delete') {
366 return $this->deleteTicket($uid);
368 return $this->listTickets($uid);
action_url(string $url, string $action='', array $bindings=array())
Tokenisiert eine automatisch erkannte zustandsaendernde Route.