dbXapp 2.0
RAD, CMS, Module und Runtime-IDE fuer dbXapp
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 return $this->tpl()->get_tpl('dbx|alert-warning', array(
22 'msg' => 'Bitte melden Sie sich an, um Ihre Kontaktanfragen zu sehen.',
23 ));
24 }
25
26 private function statusClass(string $status): string {
27 return array(
28 'open' => 'text-bg-primary',
29 'in_progress' => 'text-bg-info',
30 'waiting_customer' => 'text-bg-warning',
31 'answered' => 'text-bg-success',
32 'closed' => 'text-bg-secondary',
33 )[$status] ?? 'text-bg-light';
34 }
35
36 private function ticketForUser(int $rid, int $uid): array {
37 $ticket = dbxContactTicket::ticket($this->db(), $rid);
38 if (!$ticket || !dbxContactTicket::userOwns($ticket, $uid) || (int) ($ticket['user_hidden'] ?? 0) === 1) {
39 return array();
40 }
41 return $ticket;
42 }
43
44 private function excerpt($value, int $max = 120): string {
45 $value = trim((string) preg_replace('/\s+/', ' ', (string) $value));
46 if (strlen($value) > $max) {
47 $value = substr($value, 0, $max - 3) . '...';
48 }
49 return $this->h($value);
50 }
51
52 private function decorateRows(array $rows): array {
53 $out = array();
54 foreach ($rows as $row) {
55 $status = dbxContactTicket::normalizeStatus((string) ($row['status'] ?? 'open'));
56 $row['status_view'] = '<span class="badge ' . $this->statusClass($status) . '">' . $this->h(dbxContactTicket::statusLabel($status)) . '</span>';
57 $row['subject_view'] = $this->excerpt($row['subject'] ?? '', 90);
58 $row['action'] = $this->tpl()->get_tpl('dbxContact|contact-ticket-row-action', array(
59 'rid' => (int) ($row['id'] ?? 0),
60 ));
61 $out[] = $row;
62 }
63 return $out;
64 }
65
66 public function contactListReportRowActionData($report, $data): array {
67 if (!is_array($data) || (string) ($data['type'] ?? '') !== 'delete') {
68 return $data;
69 }
70
71 $rid = (int) ($data['record']['id'] ?? $data['data']['rid'] ?? 0);
72 $data['data']['action'] = '?dbx_modul=dbxContact&dbx_run1=my&dbx_run2=delete&rid=' . $rid;
73 $data['data']['tooltip'] = 'Anfrage entfernen';
74
75 return $data;
76 }
77
78 private function listTickets(int $uid): string {
79 $db = $this->db();
80 $report = dbx()->get_system_obj('dbxReport');
81 $where = 'uid = ' . $uid . ' AND user_hidden = 0';
82
83 $report->init('contact-list', 'dbxContact|contact-list');
84 $report->add_rep('bar_title', 'Meine Anfragen');
85 $report->add_rep('bar_icon', 'bi-life-preserver');
86 $report->add_rep('bar_subtitle', 'Status, Antworten und Verlauf Ihrer Tickets');
87 $report->add_rep('bar_actions',
88 '<a class="btn btn-primary btn-sm" href="?dbx_modul=dbxContact&dbx_run1=form"><i class="bi bi-plus-circle"></i> Neue Anfrage</a>'
89 );
90 $report->_dd = dbxContactTicket::DD_TICKET;
91 $report->_action = '?dbx_modul=dbxContact&dbx_run1=my';
92 $report->_pages = true;
93 $report->_create_row_select = false;
94 $report->_create_row_edit = false;
95 $report->_create_row_delete = true;
96 $report->_table_buttons = 'left';
97 $report->_msg_confirm_delete = 'Anfrage entfernen?';
98 $report->set_callback_owner($this);
99 $report->set_callback('row_action_data', 'contactListReportRowActionData');
100 $report->set_tabel_tpl('tpl_row_delete', 'modul|contact-ticket-row-delete');
101 $report->_rflds = array(
102 'id' => 'Ticket',
103 'last_activity_date' => 'Letzte Aktivitaet',
104 'status_view' => 'Status',
105 'subject_view' => 'Betreff',
106 'action' => '&nbsp;',
107 );
108 $report->_rpt_format = array(
109 'last_activity_date' => 'php-datetime-usr',
110 'status_view' => 'html',
111 'subject_view' => 'html',
112 'action' => 'html',
113 );
114 $report->_rrows = 30;
115 $report->_rpos = 0;
116 $report->_count_all = $db->count(dbxContactTicket::DD_TICKET, $where);
117 $report->_rcount = $report->_count_all;
118 $rows = $db->select(
120 $where,
121 array('id', 'last_activity_date', 'create_date', 'status', 'subject'),
122 'last_activity_date,id',
123 'DESC',
124 '',
125 30,
126 0,
127 0
128 );
129 $report->_rdata = $this->decorateRows(is_array($rows) ? $rows : array());
130
131 return $report->run();
132 }
133
134 private function timeline(array $ticket): string {
135 $db = $this->db();
136 dbxContactTicket::ensureInitialMessage($db, $ticket);
137 $html = '';
138
139 foreach (dbxContactTicket::messages($db, (int) $ticket['id'], false) as $message) {
140 $authorType = (string) ($message['author_type'] ?? 'system');
141 $statusTo = trim((string) ($message['status_to'] ?? ''));
142 $html .= $this->tpl()->get_tpl('dbxContact|contact-ticket-message', array(
143 'message_class' => $authorType === 'admin' ? 'border-primary bg-primary-subtle' : 'bg-body-tertiary',
144 'message_icon' => $authorType === 'admin' ? 'bi-headset' : ($authorType === 'requester' ? 'bi-person' : 'bi-gear'),
145 'author_label' => $authorType === 'admin' ? 'Support' : ($authorType === 'requester' ? 'Sie' : 'System'),
146 'create_date' => $this->h($message['create_date'] ?? ''),
147 'body' => nl2br($this->h($message['body'] ?? '')),
148 'status_badge' => $statusTo !== ''
149 ? '<span class="badge ' . $this->statusClass($statusTo) . '">Status: ' . $this->h(dbxContactTicket::statusLabel($statusTo)) . '</span>'
150 : '',
151 ));
152 }
153
154 return $html !== '' ? $html : '<div class="text-muted">Noch kein Verlauf vorhanden.</div>';
155 }
156
157 private function messageForm(array $ticket): string {
158 $rid = (int) $ticket['id'];
159 if ((string) ($ticket['status'] ?? '') === 'closed') {
160 return '<div class="alert alert-secondary mb-0">Dieses Ticket ist geschlossen. Fuer ein neues Anliegen legen Sie bitte eine neue Anfrage an.</div>';
161 }
162
163 $form = dbx()->get_system_obj('dbxForm');
164 $form->init('contact-user-message', 'contact-user-message-form');
165 $form->_dd = dbxContactTicket::DD_MESSAGE;
166 $form->_fd = 'dbxContact|contact-user-message';
167 $form->_action = '?dbx_modul=dbxContact&dbx_run1=my&dbx_run2=ticket&rid=' . $rid;
168 $form->_data = array('body' => '');
169 $form->add_module_bar('Nachricht hinzufuegen', 'bi-chat-dots', 'Ihre Nachricht wird dem Support angezeigt');
170 $form->add_rep('bar_title_pre', '');
171 $form->add_rep('bar_title_heading_attrs', '');
172 $form->add_rep('bar_middle', '');
173 $form->add_rep('bar_actions', '');
174 $form->add_rep('bar_extra', '');
175 $form->add_rep('rid', $rid);
176 $form->_msg_info = 'Ergaenzen Sie Informationen oder beantworten Sie eine Rueckfrage des Supports.';
177 $form->add_fld('body');
178
179 if ($form->submit() && !$form->errors()) {
180 $body = trim((string) $form->get_post_data('body', '', '*'));
181 $oldStatus = dbxContactTicket::normalizeStatus((string) ($ticket['status'] ?? 'open'));
182 $messageId = dbxContactTicket::addMessage($this->db(), $rid, array(
183 'author_uid' => (int) dbx()->user(),
184 'author_type' => 'requester',
185 'message_type' => 'message',
186 'visibility' => 'public',
187 'body' => $body,
188 'status_from' => $oldStatus,
189 'status_to' => 'open',
190 ));
191 if ($messageId > 0) {
192 dbxContactTicket::touch($this->db(), $rid, array('status' => 'open', 'closed_date' => ''));
193 $form->_msg_success = 'Ihre Nachricht wurde dem Ticket hinzugefuegt.';
194 $form->_data['body'] = '';
195 } else {
196 $form->_msg_error = 'Die Nachricht konnte nicht gespeichert werden.';
197 }
198 }
199
200 return $form->run();
201 }
202
203 private function ticket(int $uid): string {
204 $rid = (int) dbx()->get_modul_var('rid', 0, 'int');
205 $ticket = $this->ticketForUser($rid, $uid);
206 if (!$ticket) {
207 return $this->tpl()->get_tpl('dbx|alert-warning', array('msg' => 'Anfrage nicht gefunden.'));
208 }
209
210 $messageForm = $this->messageForm($ticket);
211 $ticket = $this->ticketForUser($rid, $uid);
212 $status = dbxContactTicket::normalizeStatus((string) ($ticket['status'] ?? 'open'));
213
214 return $this->tpl()->get_tpl('dbxContact|contact-ticket-detail', array(
215 'bar_class' => 'dbx-module-bar',
216 'bar_title_class' => 'dbx-module-bar-titleblock',
217 'bar_actions_class' => 'dbx-module-bar-actions',
218 'bar_title_pre' => '',
219 'bar_title_heading_attrs' => '',
220 'bar_icon' => 'bi-life-preserver',
221 'bar_title' => 'Ticket #' . $rid,
222 'bar_subtitle' => 'Kontaktanfrage und Verlauf',
223 'bar_middle' => '',
224 'bar_actions' => '<a class="btn btn-outline-secondary btn-sm" href="?dbx_modul=dbxContact&amp;dbx_run1=my"><i class="bi bi-arrow-left"></i> Meine Anfragen</a>',
225 'bar_extra' => '',
226 'rid' => $rid,
227 'subject' => $this->h($ticket['subject'] ?? ''),
228 'status_label' => $this->h(dbxContactTicket::statusLabel($status)),
229 'status_class' => $this->statusClass($status),
230 'create_date' => $this->h($ticket['create_date'] ?? ''),
231 'timeline' => $this->timeline($ticket),
232 'message_form' => $messageForm,
233 ));
234 }
235
236 private function deleteTicket(int $uid): string {
237 $rid = (int) dbx()->get_modul_var('rid', 0, 'int');
238 $ticket = $this->ticketForUser($rid, $uid);
239 if (!$ticket) {
240 return $this->tpl()->get_tpl('dbx|alert-warning', array('msg' => 'Anfrage nicht gefunden.'));
241 }
242
243 $form = dbx()->get_system_obj('dbxForm');
244 $form->init('contact-user-delete', 'contact-user-delete-form');
245 $form->_fd = 'dbxContact|contact-user-delete';
246 $form->_action = '?dbx_modul=dbxContact&dbx_run1=my&dbx_run2=delete&rid=' . $rid;
247 $form->_data = array('confirm_delete' => 0);
248 $form->add_module_bar('Anfrage ausblenden', 'bi-trash');
249 $form->add_rep('bar_title_pre', '');
250 $form->add_rep('bar_title_heading_attrs', '');
251 $form->add_rep('bar_middle', '');
252 $form->add_rep('bar_actions', '');
253 $form->add_rep('bar_extra', '');
254 $form->add_rep('rid', $rid);
255 $form->_msg_info = '';
256 $form->add_fld('confirm_delete');
257
258 if ($form->submit() && !$form->errors()) {
259 $ok = $this->db()->update(dbxContactTicket::DD_TICKET, array(
260 'user_hidden' => 1,
261 'user_hidden_date' => date('Y-m-d H:i:s'),
262 ), 'id = ' . $rid . ' AND uid = ' . $uid, 0, 1, 1, 1);
263 if ($ok === 1) {
264 return $this->tpl()->get_tpl('dbx|alert-success', array(
265 'msg' => 'Die Anfrage wurde aus Ihrer Ansicht entfernt. Der Supportverlauf bleibt erhalten.',
266 )) . '<div class="p-3"><a class="btn btn-primary" href="?dbx_modul=dbxContact&dbx_run1=my">Zu meinen Anfragen</a></div>';
267 }
268 $form->_msg_error = 'Die Anfrage konnte nicht ausgeblendet werden.';
269 }
270
271 return $form->run();
272 }
273
274 public function run() {
275 $uid = (int) dbx()->user();
276 if ($uid <= 0) {
277 return $this->denied();
278 }
279
280 $run2 = dbx()->get_modul_var('dbx_run2', 'list', 'parameter');
281 if ($run2 === 'ticket') {
282 return $this->ticket($uid);
283 }
284 if ($run2 === 'delete') {
285 return $this->deleteTicket($uid);
286 }
287 return $this->listTickets($uid);
288 }
289}
static userOwns(array $ticket, int $uid)
static normalizeStatus(string $status, string $fallback='open')
if( $syncRequest)
Definition index.php:520
DBX schema administration.