nas commited on 2010-11-29 05:20:37
Showing 250 changed files, with 21371 additions and 0 deletions.
... | ... |
@@ -0,0 +1,470 @@ |
1 |
+/********************************** |
|
2 |
+* General stuff used all around the helpdesk * |
|
3 |
+***********************************/ |
|
4 |
+ |
|
5 |
+/* Half rounded headers and footers */ |
|
6 |
+h3.grid_header |
|
7 |
+{ |
|
8 |
+ height: 25px; |
|
9 |
+} |
|
10 |
+ |
|
11 |
+/* You no left float, Core! */ |
|
12 |
+h3.grid_header img |
|
13 |
+{ |
|
14 |
+ float: none; |
|
15 |
+} |
|
16 |
+ |
|
17 |
+/* Smaller icons */ |
|
18 |
+.shd_smallicon |
|
19 |
+{ |
|
20 |
+ width: 13px; |
|
21 |
+ height: 13px; |
|
22 |
+ margin-right: 4px; |
|
23 |
+} |
|
24 |
+.shd_icon_minihead |
|
25 |
+{ |
|
26 |
+ position: relative; |
|
27 |
+ top: 3px; |
|
28 |
+} |
|
29 |
+.shd_icon_fullhead |
|
30 |
+{ |
|
31 |
+ position: relative; |
|
32 |
+ top: 9px; |
|
33 |
+} |
|
34 |
+.shd_tinyicon |
|
35 |
+{ |
|
36 |
+ width: 9px; |
|
37 |
+ height: 9px; |
|
38 |
+} |
|
39 |
+ |
|
40 |
+.shd_main_hd |
|
41 |
+{ |
|
42 |
+ margin-top: -3px; |
|
43 |
+} |
|
44 |
+ |
|
45 |
+.shd_nowrap |
|
46 |
+{ |
|
47 |
+ white-space: nowrap; |
|
48 |
+} |
|
49 |
+ |
|
50 |
+/********************************** |
|
51 |
+* The ticket listings * |
|
52 |
+***********************************/ |
|
53 |
+.shd_ticketlist |
|
54 |
+{ |
|
55 |
+ width: 100%; |
|
56 |
+ border: solid #BBBBBB; |
|
57 |
+ border-width: 1px 1px 0; |
|
58 |
+} |
|
59 |
+.shd_ticketlist td |
|
60 |
+{ |
|
61 |
+ padding: 5px; |
|
62 |
+ border-bottom: 1px solid #AFAFAF; |
|
63 |
+} |
|
64 |
+.shd_noticket |
|
65 |
+{ |
|
66 |
+ text-align: center; |
|
67 |
+} |
|
68 |
+.shd_staffresources ul |
|
69 |
+{ |
|
70 |
+ list-style-type: none; |
|
71 |
+ padding: 0; |
|
72 |
+ margin: 0; |
|
73 |
+} |
|
74 |
+.shd_staffresources li |
|
75 |
+{ |
|
76 |
+ margin-bottom: 3px; |
|
77 |
+} |
|
78 |
+ |
|
79 |
+.shd_gototicket |
|
80 |
+{ |
|
81 |
+ display: block; |
|
82 |
+ float: right; |
|
83 |
+ margin-left: 1em; |
|
84 |
+ white-space: nowrap; |
|
85 |
+} |
|
86 |
+ |
|
87 |
+/********************************** |
|
88 |
+* Stuff used within the actual tickets * |
|
89 |
+***********************************/ |
|
90 |
+ |
|
91 |
+/* This is done to position icons perfectly in the ticket header (i.e the navigation)*/ |
|
92 |
+h3.ticketheader img |
|
93 |
+{ |
|
94 |
+ top: 2px; |
|
95 |
+ position: relative; |
|
96 |
+ margin-right: 2px; |
|
97 |
+} |
|
98 |
+ |
|
99 |
+/* Ticket details (Left-floated box) */ |
|
100 |
+.shd_ticketdetails |
|
101 |
+{ |
|
102 |
+ float: left; |
|
103 |
+ width: 215px; |
|
104 |
+ min-height: 280px; |
|
105 |
+ overflow: auto; |
|
106 |
+ margin-right: 20px; |
|
107 |
+} |
|
108 |
+.shd_ticketdetails ul |
|
109 |
+{ |
|
110 |
+ list-style-type: none; |
|
111 |
+ padding-left: 0; |
|
112 |
+ margin: 0; |
|
113 |
+} |
|
114 |
+ |
|
115 |
+/* The ticket container */ |
|
116 |
+.shd_ticket |
|
117 |
+{ |
|
118 |
+ min-height: 340px; |
|
119 |
+} |
|
120 |
+.shd_ticket_description |
|
121 |
+{ |
|
122 |
+ padding-top: 9px; |
|
123 |
+ padding-bottom: 45px; |
|
124 |
+ margin-left: 260px; |
|
125 |
+ min-height: 200px; |
|
126 |
+} |
|
127 |
+ |
|
128 |
+#shd_ticket_text |
|
129 |
+{ |
|
130 |
+ min-height: 100px; |
|
131 |
+} |
|
132 |
+ |
|
133 |
+/* The left column in the ticket display */ |
|
134 |
+.shd_ticket_leftcolumn |
|
135 |
+{ |
|
136 |
+ width: 25%; |
|
137 |
+} |
|
138 |
+/* The right column in the ticket display */ |
|
139 |
+.shd_ticket_rightcolumn |
|
140 |
+{ |
|
141 |
+ width: 75%; |
|
142 |
+} |
|
143 |
+ |
|
144 |
+/* The Respond, Edit, Delete etc links */ |
|
145 |
+.shd_ticketlinks a |
|
146 |
+{ |
|
147 |
+ margin-right: 10px; |
|
148 |
+} |
|
149 |
+.shd_ticketlinks a#last |
|
150 |
+{ |
|
151 |
+ margin-right: 0px; |
|
152 |
+} |
|
153 |
+ |
|
154 |
+.shd_ticket_avatar |
|
155 |
+{ |
|
156 |
+ margin: 1em auto; |
|
157 |
+ text-align: center; |
|
158 |
+} |
|
159 |
+ |
|
160 |
+.shd_modified |
|
161 |
+{ |
|
162 |
+ margin-top: 20px; |
|
163 |
+} |
|
164 |
+ |
|
165 |
+.postreply |
|
166 |
+{ |
|
167 |
+ margin: 0; |
|
168 |
+} |
|
169 |
+ |
|
170 |
+.postmodify |
|
171 |
+{ |
|
172 |
+ margin: 0; |
|
173 |
+} |
|
174 |
+ |
|
175 |
+/* The 'Go to the main log' link in ticket logs */ |
|
176 |
+.shd_main_log |
|
177 |
+{ |
|
178 |
+ font-size: 80%; |
|
179 |
+} |
|
180 |
+.shd_main_log img |
|
181 |
+{ |
|
182 |
+ position: relative; |
|
183 |
+ top: 3px; |
|
184 |
+ margin-right: 2px; |
|
185 |
+} |
|
186 |
+#shd_ticket_log_expand |
|
187 |
+{ |
|
188 |
+ margin-top: 8px; |
|
189 |
+} |
|
190 |
+.shd_ticket_log_expand_container |
|
191 |
+{ |
|
192 |
+ margin-right: 3px; |
|
193 |
+} |
|
194 |
+ |
|
195 |
+#quickReplyExpand |
|
196 |
+{ |
|
197 |
+ margin-top: 8px; |
|
198 |
+} |
|
199 |
+ |
|
200 |
+/* Override editor margins */ |
|
201 |
+#quickReplyOptions form textarea |
|
202 |
+{ |
|
203 |
+ margin-bottom: 0!important; |
|
204 |
+} |
|
205 |
+ |
|
206 |
+/********************************** |
|
207 |
+ * Huge buttons :D * |
|
208 |
+***********************************/ |
|
209 |
+ |
|
210 |
+/* The big reply button */ |
|
211 |
+.shd_replybutton |
|
212 |
+{ |
|
213 |
+ margin-top: 10px; |
|
214 |
+ height: 15px; |
|
215 |
+ background: url(../images/simpledesk/respond.png) no-repeat left; |
|
216 |
+ background-position: 10px; |
|
217 |
+ padding: 10px; |
|
218 |
+ padding-left: 40px; |
|
219 |
+ padding-top: 8px; |
|
220 |
+ font-weight: bold; |
|
221 |
+ font-size: 100%; |
|
222 |
+ margin-bottom: 10px; |
|
223 |
+} |
|
224 |
+/* The big quote button */ |
|
225 |
+.shd_quotebutton |
|
226 |
+{ |
|
227 |
+ margin-top: 10px; |
|
228 |
+ height: 15px; |
|
229 |
+ background: url(../images/simpledesk/quote.png) no-repeat left; |
|
230 |
+ background-position: 10px; |
|
231 |
+ padding: 10px; |
|
232 |
+ padding-left: 40px; |
|
233 |
+ padding-top: 8px; |
|
234 |
+ font-weight: bold; |
|
235 |
+ font-size: 100%; |
|
236 |
+ margin-right: 10px; |
|
237 |
+} |
|
238 |
+/* Go advanced! */ |
|
239 |
+.shd_advancedbutton |
|
240 |
+{ |
|
241 |
+ margin-top: 10px; |
|
242 |
+ height: 15px; |
|
243 |
+ background: url(../images/simpledesk/advanced.png) no-repeat left; |
|
244 |
+ background-position: 10px; |
|
245 |
+ padding: 10px; |
|
246 |
+ padding-left: 40px; |
|
247 |
+ padding-top: 8px; |
|
248 |
+ font-weight: bold; |
|
249 |
+ font-size: 100%; |
|
250 |
+ margin-right: 10px; |
|
251 |
+} |
|
252 |
+ |
|
253 |
+/* Edit settings*/ |
|
254 |
+.shd_editpreferences |
|
255 |
+{ |
|
256 |
+ height: 15px; |
|
257 |
+ background: url(../images/simpledesk/edit.png) no-repeat left; |
|
258 |
+ background-position: 10px; |
|
259 |
+ padding: 10px; |
|
260 |
+ padding-left: 40px; |
|
261 |
+ padding-top: 8px; |
|
262 |
+ font-weight: bold; |
|
263 |
+ font-size: 100%; |
|
264 |
+ margin-right: 10px; |
|
265 |
+} |
|
266 |
+ |
|
267 |
+/* Show tickets */ |
|
268 |
+.shd_showtickets |
|
269 |
+{ |
|
270 |
+ height: 15px; |
|
271 |
+ padding: 10px; |
|
272 |
+ padding-left: 40px; |
|
273 |
+ padding-top: 8px; |
|
274 |
+ font-weight: bold; |
|
275 |
+ font-size: 100%; |
|
276 |
+ margin-right: 10px; |
|
277 |
+} |
|
278 |
+#shd_showtickets |
|
279 |
+{ |
|
280 |
+ background: url(../images/simpledesk/details.png) no-repeat left; |
|
281 |
+ background-position: 10px; |
|
282 |
+} |
|
283 |
+#shd_post_proxy |
|
284 |
+{ |
|
285 |
+ background: url(../images/simpledesk/proxy.png) no-repeat left; |
|
286 |
+ background-position: 10px; |
|
287 |
+} |
|
288 |
+ |
|
289 |
+/********************************** |
|
290 |
+* Ticket replies * |
|
291 |
+***********************************/ |
|
292 |
+.shd_reply |
|
293 |
+{ |
|
294 |
+ padding-bottom: 32px; |
|
295 |
+ padding-top: 12px; |
|
296 |
+} |
|
297 |
+.shd_posterinfo |
|
298 |
+{ |
|
299 |
+ width: 11em; |
|
300 |
+ text-align: center; |
|
301 |
+ margin-left: 3px; |
|
302 |
+} |
|
303 |
+.shd_postername |
|
304 |
+{ |
|
305 |
+ font-size: 120%; |
|
306 |
+} |
|
307 |
+.shd_groupmargin |
|
308 |
+{ |
|
309 |
+ margin-bottom: 10px; |
|
310 |
+} |
|
311 |
+.shd_posteravatar img |
|
312 |
+{ |
|
313 |
+ padding: 0px; |
|
314 |
+ max-width: 10.5em; |
|
315 |
+} |
|
316 |
+.shd_replyarea |
|
317 |
+{ |
|
318 |
+ padding-left: 11em; |
|
319 |
+ margin-left: 10px; |
|
320 |
+} |
|
321 |
+ |
|
322 |
+.shd_reply .avatar |
|
323 |
+{ |
|
324 |
+ margin-bottom: 10px; |
|
325 |
+} |
|
326 |
+ |
|
327 |
+/********************************** |
|
328 |
+* Attachment stuff * |
|
329 |
+***********************************/ |
|
330 |
+.shd_reply_attachments |
|
331 |
+{ |
|
332 |
+ width: 68%; |
|
333 |
+ margin-bottom: 0; |
|
334 |
+ float: left; |
|
335 |
+ margin-top: 5px; |
|
336 |
+} |
|
337 |
+.shd_replyattachments ul, .shd_replyattachments li |
|
338 |
+{ |
|
339 |
+ display: block; |
|
340 |
+ list-style-type: none; |
|
341 |
+} |
|
342 |
+ |
|
343 |
+.shd_replyattachments li |
|
344 |
+{ |
|
345 |
+ float: left; |
|
346 |
+ width: 30%; |
|
347 |
+} |
|
348 |
+ |
|
349 |
+.shd_attachment |
|
350 |
+{ |
|
351 |
+ padding-bottom: 5px; |
|
352 |
+ font-size: 85%; |
|
353 |
+} |
|
354 |
+.shd_attachmentpreview |
|
355 |
+{ |
|
356 |
+ text-align: center; |
|
357 |
+} |
|
358 |
+.shd_attachmentpreview img |
|
359 |
+{ |
|
360 |
+ max-width: 75px; |
|
361 |
+ margin: 3px; |
|
362 |
+ margin-top: 6px; |
|
363 |
+} |
|
364 |
+.shd_attachmentpreview .description |
|
365 |
+{ |
|
366 |
+ padding: 0; |
|
367 |
+} |
|
368 |
+.shd_removeattachment |
|
369 |
+{ |
|
370 |
+ margin-left: -8px; |
|
371 |
+ margin-right: 3px; |
|
372 |
+} |
|
373 |
+.shd_attachmentbox |
|
374 |
+{ |
|
375 |
+ padding: 10px; |
|
376 |
+} |
|
377 |
+.shd_attachmentcolumn |
|
378 |
+{ |
|
379 |
+ margin-right: 20px; |
|
380 |
+} |
|
381 |
+.shd_thumb |
|
382 |
+{ |
|
383 |
+ border: 0; |
|
384 |
+ display: block; |
|
385 |
+ margin-left: auto; |
|
386 |
+ margin-right: auto; |
|
387 |
+} |
|
388 |
+ |
|
389 |
+/********************************** |
|
390 |
+* Posting and editing tickets/replies * |
|
391 |
+***********************************/ |
|
392 |
+#shd_bbcbox |
|
393 |
+{ |
|
394 |
+ margin: 0 0 0.5em 0; |
|
395 |
+} |
|
396 |
+#shd_bbcbox div |
|
397 |
+{ |
|
398 |
+ margin: 0.2em 0; |
|
399 |
+ vertical-align: top; |
|
400 |
+} |
|
401 |
+#shd_bbcbox div img |
|
402 |
+{ |
|
403 |
+ margin: 0 1px 0 0; |
|
404 |
+ vertical-align: top; |
|
405 |
+} |
|
406 |
+#shd_bbcbox select |
|
407 |
+{ |
|
408 |
+ margin: 0 2px; |
|
409 |
+} |
|
410 |
+/* The smiley strip */ |
|
411 |
+#shd_smileybox |
|
412 |
+{ |
|
413 |
+ margin: 0.75em 0 0.5em 0; |
|
414 |
+} |
|
415 |
+ |
|
416 |
+/********************************** |
|
417 |
+* General actions * |
|
418 |
+***********************************/ |
|
419 |
+.pm_message |
|
420 |
+{ |
|
421 |
+ margin-top: 1ex; |
|
422 |
+} |
|
423 |
+ |
|
424 |
+/* The 'Empty log' link in the action log */ |
|
425 |
+.shd_empty_log |
|
426 |
+{ |
|
427 |
+ font-size: 80%; |
|
428 |
+} |
|
429 |
+.shd_empty_log img |
|
430 |
+{ |
|
431 |
+ position: relative; |
|
432 |
+ top: 3px; |
|
433 |
+ margin-right: 2px; |
|
434 |
+} |
|
435 |
+ |
|
436 |
+/********************************** |
|
437 |
+* The profile * |
|
438 |
+***********************************/ |
|
439 |
+.shd_profile_navigation |
|
440 |
+{ |
|
441 |
+ margin-right: 20px; |
|
442 |
+} |
|
443 |
+.shd_profile_nav_list, .shd_profile_nav_list ul, .shd_profile_nav_list li |
|
444 |
+{ |
|
445 |
+ margin: 0; |
|
446 |
+ padding: 0; |
|
447 |
+ list-style-type: none; |
|
448 |
+} |
|
449 |
+.shd_profile_nav_inline, .shd_profile_nav_inline ul, .shd_profile_nav_inline li |
|
450 |
+{ |
|
451 |
+ margin: 0; |
|
452 |
+ padding: 0; |
|
453 |
+ list-style-type: none; |
|
454 |
+ float: left; |
|
455 |
+} |
|
456 |
+.shd_profile_nav_inline li |
|
457 |
+{ |
|
458 |
+ margin-right: 10px; |
|
459 |
+ border-right: 1px solid #cccccc; |
|
460 |
+ padding-right: 10px; |
|
461 |
+} |
|
462 |
+.shd_profile_nav_inline img |
|
463 |
+{ |
|
464 |
+ margin-left: 4px; |
|
465 |
+} |
|
466 |
+ |
|
467 |
+.shd_profile_nav_inline li.shd_inline_last |
|
468 |
+{ |
|
469 |
+ border-right: none; |
|
470 |
+} |
|
0 | 471 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,232 @@ |
1 |
+#sd_live_news |
|
2 |
+{ |
|
3 |
+ width: 64%; |
|
4 |
+ font-size: 0.85em; |
|
5 |
+} |
|
6 |
+#sd_live_news div.content |
|
7 |
+{ |
|
8 |
+ padding: 0; |
|
9 |
+} |
|
10 |
+#sd_live_news div.content dl |
|
11 |
+{ |
|
12 |
+ padding: 0.5em 0 0 0.5em; |
|
13 |
+} |
|
14 |
+ |
|
15 |
+#sd_supportVersionsTable |
|
16 |
+{ |
|
17 |
+ width: 34%; |
|
18 |
+} |
|
19 |
+#sd_version_details |
|
20 |
+{ |
|
21 |
+ overflow: auto; |
|
22 |
+ height: 16.4em; |
|
23 |
+} |
|
24 |
+#sdAnnouncements |
|
25 |
+{ |
|
26 |
+ height: 21.6em; |
|
27 |
+ overflow: auto; |
|
28 |
+} |
|
29 |
+#sdAnnouncements dt |
|
30 |
+{ |
|
31 |
+ border-bottom: 1px dashed #000; |
|
32 |
+} |
|
33 |
+#sdAnnouncements dd |
|
34 |
+{ |
|
35 |
+ padding: 0; |
|
36 |
+ margin: 0 0 1em 1.5em; |
|
37 |
+} |
|
38 |
+#sd_update_section |
|
39 |
+{ |
|
40 |
+ margin-top: 10px; |
|
41 |
+ margin-bottom: 10px; |
|
42 |
+} |
|
43 |
+#sd_credits |
|
44 |
+{ |
|
45 |
+} |
|
46 |
+.sd_group_name |
|
47 |
+{ |
|
48 |
+} |
|
49 |
+.sd_group_name hr |
|
50 |
+{ |
|
51 |
+ margin-top: 2px; |
|
52 |
+} |
|
53 |
+.shd_help |
|
54 |
+{ |
|
55 |
+ float: right; |
|
56 |
+ margin-top: 8px; |
|
57 |
+} |
|
58 |
+.shd_actionloginfo |
|
59 |
+{ |
|
60 |
+ margin-bottom: 0; |
|
61 |
+ border-bottom: 0; |
|
62 |
+} |
|
63 |
+.shd_admin_leftcolumn |
|
64 |
+{ |
|
65 |
+ width: 74%; |
|
66 |
+ margin-right: 10px; |
|
67 |
+} |
|
68 |
+.shd_admin_rightcolumn |
|
69 |
+{ |
|
70 |
+ width: 24%; |
|
71 |
+} |
|
72 |
+.shd_credits_break |
|
73 |
+{ |
|
74 |
+ margin-bottom: 0; |
|
75 |
+ |
|
76 |
+} |
|
77 |
+.shd_bbc_list |
|
78 |
+{ |
|
79 |
+ width: 33%; |
|
80 |
+} |
|
81 |
+.shd_info_box |
|
82 |
+{ |
|
83 |
+ margin-bottom: 0; |
|
84 |
+} |
|
85 |
+h3.sd_no_margin |
|
86 |
+{ |
|
87 |
+ margin-bottom: 0px; |
|
88 |
+ padding-bottom: 3px; |
|
89 |
+} |
|
90 |
+ |
|
91 |
+.disabled |
|
92 |
+{ |
|
93 |
+ color: #777777; |
|
94 |
+} |
|
95 |
+ |
|
96 |
+.shd_credits_names |
|
97 |
+{ |
|
98 |
+ margin-left: 57px; |
|
99 |
+} |
|
100 |
+ |
|
101 |
+.shd_valign_top |
|
102 |
+{ |
|
103 |
+ vertical-align: top; |
|
104 |
+} |
|
105 |
+ |
|
106 |
+.shd_yes, .shd_no, .shd_own, .shd_any |
|
107 |
+{ |
|
108 |
+ padding-left:19px; |
|
109 |
+ padding-bottom:3px; |
|
110 |
+} |
|
111 |
+ |
|
112 |
+.shd_yes |
|
113 |
+{ |
|
114 |
+ background:url(../images/simpledesk/perm_yes.png) no-repeat; |
|
115 |
+} |
|
116 |
+ |
|
117 |
+.shd_no |
|
118 |
+{ |
|
119 |
+ background:url(../images/simpledesk/perm_no.png) no-repeat; |
|
120 |
+} |
|
121 |
+ |
|
122 |
+.shd_own |
|
123 |
+{ |
|
124 |
+ background:url(../images/simpledesk/perm_own.png) no-repeat; |
|
125 |
+} |
|
126 |
+ |
|
127 |
+.shd_any |
|
128 |
+{ |
|
129 |
+ background:url(../images/simpledesk/perm_any.png) no-repeat; |
|
130 |
+} |
|
131 |
+ |
|
132 |
+dl.permsettings |
|
133 |
+{ |
|
134 |
+ clear: right; |
|
135 |
+ overflow: auto; |
|
136 |
+ margin: 0 0 10px 0; |
|
137 |
+ padding: 0; |
|
138 |
+} |
|
139 |
+ |
|
140 |
+dl.permsettings dt |
|
141 |
+{ |
|
142 |
+ width: 58%; |
|
143 |
+ float: left; |
|
144 |
+ margin: 0 0 10px 0; |
|
145 |
+ padding: 0; |
|
146 |
+ clear: both; |
|
147 |
+} |
|
148 |
+ |
|
149 |
+dl.permsettings dt.settings_title |
|
150 |
+{ |
|
151 |
+ width: 100%; |
|
152 |
+ float: none; |
|
153 |
+ margin: 0 0 10px 0; |
|
154 |
+ padding: 5px 0 0 0; |
|
155 |
+ font-weight: bold; |
|
156 |
+ clear: both; |
|
157 |
+} |
|
158 |
+ |
|
159 |
+dl.permsettings dt.windowbg |
|
160 |
+{ |
|
161 |
+ width: 98%; |
|
162 |
+ float: left; |
|
163 |
+ margin: 0 0 3px 0; |
|
164 |
+ padding: 0 0 5px 0; |
|
165 |
+ clear: both; |
|
166 |
+} |
|
167 |
+ |
|
168 |
+dl.permsettings dd |
|
169 |
+{ |
|
170 |
+ width: 38%; |
|
171 |
+ float: left; |
|
172 |
+ margin: 0 0 3px 0; |
|
173 |
+ padding: 0; |
|
174 |
+} |
|
175 |
+ |
|
176 |
+dl.permsettings img |
|
177 |
+{ |
|
178 |
+ margin: 0 10px 0 0; |
|
179 |
+} |
|
180 |
+ |
|
181 |
+h3 a.permcollapse img |
|
182 |
+{ |
|
183 |
+ margin-top:8px; |
|
184 |
+} |
|
185 |
+ |
|
186 |
+#cf_fieldicon_icon |
|
187 |
+{ |
|
188 |
+ padding-left:19px; |
|
189 |
+ padding-bottom:3px; |
|
190 |
+} |
|
191 |
+ |
|
192 |
+.cf_ui_text, .cf_ui_largetext, .cf_ui_int, .cf_ui_float, .cf_ui_select, .cf_ui_checkbox, .cf_ui_radio |
|
193 |
+{ |
|
194 |
+ padding-left:19px; |
|
195 |
+ padding-bottom:3px; |
|
196 |
+} |
|
197 |
+ |
|
198 |
+.cf_ui_text |
|
199 |
+{ |
|
200 |
+ background:url(../images/simpledesk/cf_ui_text.png) no-repeat; |
|
201 |
+} |
|
202 |
+.cf_ui_largetext |
|
203 |
+{ |
|
204 |
+ background:url(../images/simpledesk/cf_ui_largetext.png) no-repeat; |
|
205 |
+} |
|
206 |
+.cf_ui_int |
|
207 |
+{ |
|
208 |
+ background:url(../images/simpledesk/cf_ui_int.png) no-repeat; |
|
209 |
+} |
|
210 |
+.cf_ui_float |
|
211 |
+{ |
|
212 |
+ background:url(../images/simpledesk/cf_ui_float.png) no-repeat; |
|
213 |
+} |
|
214 |
+.cf_ui_select |
|
215 |
+{ |
|
216 |
+ background:url(../images/simpledesk/cf_ui_select.png) no-repeat; |
|
217 |
+} |
|
218 |
+.cf_ui_checkbox |
|
219 |
+{ |
|
220 |
+ background:url(../images/simpledesk/cf_ui_checkbox.png) no-repeat; |
|
221 |
+} |
|
222 |
+.cf_ui_radio |
|
223 |
+{ |
|
224 |
+ background:url(../images/simpledesk/cf_ui_radio.png) no-repeat; |
|
225 |
+} |
|
226 |
+ |
|
227 |
+.langblock |
|
228 |
+{ |
|
229 |
+ width:30%; |
|
230 |
+ float:right; |
|
231 |
+ display:block; |
|
232 |
+} |
|
0 | 233 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,31 @@ |
1 |
+/* IE6, IE6, how do I hate thee, let me count the ways. */ |
|
2 |
+ |
|
3 |
+/* IE6 needs a height fix here */ |
|
4 |
+.shd_ticketdetails |
|
5 |
+{ |
|
6 |
+ min-height: 280px; |
|
7 |
+ height: auto !important; |
|
8 |
+ height: 280px; |
|
9 |
+} |
|
10 |
+.shd_ticket |
|
11 |
+{ |
|
12 |
+ min-height: 340px; |
|
13 |
+ height: auto !important; |
|
14 |
+ height: 340px; |
|
15 |
+} |
|
16 |
+ |
|
17 |
+/* For whatever odd reason this have to 0.8% or so smaller in IE6 to look good. */ |
|
18 |
+h3.grid_header |
|
19 |
+{ |
|
20 |
+ width: 99.2%; |
|
21 |
+} |
|
22 |
+ |
|
23 |
+.shd_reply .shd_ticketlinks |
|
24 |
+{ |
|
25 |
+ margin-top: -15px; |
|
26 |
+} |
|
27 |
+ |
|
28 |
+h3.ticketheader .shd_ticketlinks |
|
29 |
+{ |
|
30 |
+ margin-top: 3px; |
|
31 |
+} |
|
0 | 32 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,324 @@ |
1 |
+<?xml version="1.0"?> |
|
2 |
+<!DOCTYPE modification SYSTEM "http://www.simplemachines.org/xml/modification"> |
|
3 |
+<modification xmlns="http://www.simplemachines.org/xml/modification" xmlns:smf="http://www.simplemachines.org/"> |
|
4 |
+ <id>SimpleDeskTeam:SimpleDesk</id> |
|
5 |
+ <version>1.1 rev753</version> |
|
6 |
+ |
|
7 |
+ <file name="$sourcedir/Display.php"> |
|
8 |
+ <operation><!-- add the option to the download system to ensure it handles SD attachments --> |
|
9 |
+ <search position="after"><![CDATA[ |
|
10 |
+ // This is just a regular attachment... |
|
11 |
+ else]]></search> |
|
12 |
+ <add><![CDATA[ |
|
13 |
+ elseif (!empty($_REQUEST['ticket'])) |
|
14 |
+ { |
|
15 |
+ // Make sure the attachment is on this ticket, note right now we're forcing it to be "approved" |
|
16 |
+ $request = shd_db_query('', ' |
|
17 |
+ SELECT a.id_folder, a.filename, a.file_hash, a.fileext, a.id_attach, a.attachment_type, a.mime_type, 1 AS approved |
|
18 |
+ FROM {db_prefix}attachments AS a |
|
19 |
+ INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (a.id_attach = hda.id_attach) |
|
20 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hda.id_msg = hdtr.id_msg) |
|
21 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket) |
|
22 |
+ WHERE {query_see_ticket} |
|
23 |
+ AND a.id_attach = {int:attach} |
|
24 |
+ AND hdt.id_ticket = {int:ticket} |
|
25 |
+ LIMIT 1', |
|
26 |
+ array( |
|
27 |
+ 'attach' => $_REQUEST['attach'], |
|
28 |
+ 'ticket' => (int) $_REQUEST['ticket'], |
|
29 |
+ ) |
|
30 |
+ ); |
|
31 |
+ }]]></add> |
|
32 |
+ </operation> |
|
33 |
+ </file> |
|
34 |
+ |
|
35 |
+ <file name="$sourcedir/ManageAttachments.php"> |
|
36 |
+ <operation><!-- extend removeAttachments to cover SD's table items since it's doing the rest of the work anyway --> |
|
37 |
+ <search position="after"><![CDATA[ if ($return_affected_messages)]]></search> |
|
38 |
+ <add><![CDATA[ // And now lastly to remove SimpleDesk attachments |
|
39 |
+ if (!empty($attach)) |
|
40 |
+ $smcFunc['db_query']('', ' |
|
41 |
+ DELETE FROM {db_prefix}helpdesk_attachments |
|
42 |
+ WHERE id_attach IN ({array_int:attachment_list})', |
|
43 |
+ array( |
|
44 |
+ 'attachment_list' => $attach, |
|
45 |
+ ) |
|
46 |
+ ); |
|
47 |
+ |
|
48 |
+]]></add> |
|
49 |
+ </operation> |
|
50 |
+ <operation><!-- prevent attachment maintenance killing our attachments! unconventionally, this is an atomic query for good reason, it MUST be put in place fully --> |
|
51 |
+ <search position="replace"><![CDATA[SELECT a.id_attach, a.id_folder, a.filename, a.file_hash |
|
52 |
+ FROM {db_prefix}attachments AS a |
|
53 |
+ LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) |
|
54 |
+ WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499 |
|
55 |
+ AND a.id_member = {int:no_member} |
|
56 |
+ AND a.id_msg != {int:no_msg} |
|
57 |
+ AND m.id_msg IS NULL]]></search> |
|
58 |
+ <add><![CDATA[SELECT a.id_attach, a.id_folder, a.filename, a.file_hash |
|
59 |
+ FROM {db_prefix}attachments AS a |
|
60 |
+ LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) |
|
61 |
+ LEFT JOIN {db_prefix}helpdesk_attachments AS hda ON (hda.id_attach = a.id_attach) |
|
62 |
+ LEFT JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdtr.id_msg = hda.id_msg) |
|
63 |
+ WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499 |
|
64 |
+ AND a.id_member = {int:no_member} |
|
65 |
+ AND a.id_msg != {int:no_msg} |
|
66 |
+ AND m.id_msg IS NULL |
|
67 |
+ AND hdtr.id_msg IS NULL]]></add> |
|
68 |
+ </operation> |
|
69 |
+ <operation><!-- override the master attachments code if it's HD only stuff requested --> |
|
70 |
+ <search position="before"><![CDATA[$context['browse_type'] = isset($_REQUEST['avatars']) ? 'avatars' : (isset($_REQUEST['thumbs']) ? 'thumbs' : 'attachments');]]></search> |
|
71 |
+ <add><![CDATA[ |
|
72 |
+ |
|
73 |
+ if (!empty($modSettings['helpdesk_active']) && (isset($_REQUEST['shd_attach']) || isset($_REQUEST['shd_thumb']))) |
|
74 |
+ { |
|
75 |
+ // We're actually wanting helpdesk only stuff, so do it and bail |
|
76 |
+ return shd_admin_browse_attachments(); |
|
77 |
+ } |
|
78 |
+ |
|
79 |
+]]></add> |
|
80 |
+ </operation> |
|
81 |
+ <operation><!-- add the code to deal with deleting our attachments from ACP --> |
|
82 |
+ <search position="after"><![CDATA[if ($_REQUEST['type'] == 'avatars' && !empty($attachments))]]></search> |
|
83 |
+ <add><![CDATA[if (in_array($_REQUEST['type'], array('shd_attach', 'shd_thumb')) && !empty($attachments)) |
|
84 |
+ $messages = removeAttachments(array('id_attach' => $attachments), '', true); |
|
85 |
+ else]]></add> |
|
86 |
+ </operation> |
|
87 |
+ <operation><!-- add our handling for attachments --> |
|
88 |
+ <search position="end" /> |
|
89 |
+ <add><![CDATA[ |
|
90 |
+ |
|
91 |
+function shd_admin_browse_attachments() |
|
92 |
+{ |
|
93 |
+ global $context, $txt, $scripturl, $options, $modSettings; |
|
94 |
+ global $smcFunc, $sourcedir; |
|
95 |
+ |
|
96 |
+ $context['browse_type'] = isset($_REQUEST['shd_attach']) ? 'shd_attach' : 'shd_thumb'; |
|
97 |
+ |
|
98 |
+ // Set the options for the list component. |
|
99 |
+ $listOptions = array( |
|
100 |
+ 'id' => 'file_list', |
|
101 |
+ 'title' => $txt['attachment_manager_' . $context['browse_type']], |
|
102 |
+ 'items_per_page' => $modSettings['defaultMaxMessages'], |
|
103 |
+ 'base_href' => $scripturl . '?action=admin;area=manageattachments;sa=browse;' . $context['browse_type'], |
|
104 |
+ 'default_sort_col' => 'name', |
|
105 |
+ 'no_items_label' => $txt['attachment_manager_' . $context['browse_type'] . '_no_entries'], |
|
106 |
+ 'get_items' => array( |
|
107 |
+ 'function' => 'shd_list_get_files', |
|
108 |
+ 'params' => array( |
|
109 |
+ $context['browse_type'], |
|
110 |
+ ), |
|
111 |
+ ), |
|
112 |
+ 'get_count' => array( |
|
113 |
+ 'function' => 'shd_list_get_num_files', |
|
114 |
+ 'params' => array( |
|
115 |
+ $context['browse_type'], |
|
116 |
+ ), |
|
117 |
+ ), |
|
118 |
+ 'columns' => array( |
|
119 |
+ 'name' => array( |
|
120 |
+ 'header' => array( |
|
121 |
+ 'value' => $txt['attachment_name'], |
|
122 |
+ ), |
|
123 |
+ 'data' => array( |
|
124 |
+ 'function' => create_function('$rowData', ' |
|
125 |
+ global $modSettings, $context, $scripturl; |
|
126 |
+ |
|
127 |
+ $link = \'<a href="\'; |
|
128 |
+ |
|
129 |
+ $link .= sprintf(\'%1$s?action=dlattach;ticket=%2$d.0;id=%3$d\', $scripturl, $rowData[\'id_ticket\'], $rowData[\'id_attach\']); |
|
130 |
+ |
|
131 |
+ $link .= \'"\'; |
|
132 |
+ |
|
133 |
+ // Show a popup on click if it\'s a picture and we know its dimensions. |
|
134 |
+ if (!empty($rowData[\'width\']) && !empty($rowData[\'height\'])) |
|
135 |
+ $link .= sprintf(\' onclick="return reqWin(this.href + \\\';image\\\', %1$d, %2$d, true);"\', $rowData[\'width\'] + 20, $rowData[\'height\'] + 20); |
|
136 |
+ |
|
137 |
+ $link .= sprintf(\'>%1$s</a>\', preg_replace(\'~&#(\\\\d{1,7}|x[0-9a-fA-F]{1,6});~\', \'&#\\\\1;\', htmlspecialchars($rowData[\'filename\']))); |
|
138 |
+ |
|
139 |
+ // Show the dimensions. |
|
140 |
+ if (!empty($rowData[\'width\']) && !empty($rowData[\'height\'])) |
|
141 |
+ $link .= sprintf(\' <span class="smalltext">%1$dx%2$d</span>\', $rowData[\'width\'], $rowData[\'height\']); |
|
142 |
+ |
|
143 |
+ return $link; |
|
144 |
+ '), |
|
145 |
+ ), |
|
146 |
+ 'sort' => array( |
|
147 |
+ 'default' => 'a.filename', |
|
148 |
+ 'reverse' => 'a.filename DESC', |
|
149 |
+ ), |
|
150 |
+ ), |
|
151 |
+ 'filesize' => array( |
|
152 |
+ 'header' => array( |
|
153 |
+ 'value' => $txt['attachment_file_size'], |
|
154 |
+ ), |
|
155 |
+ 'data' => array( |
|
156 |
+ 'function' => create_function('$rowData',' |
|
157 |
+ global $txt; |
|
158 |
+ |
|
159 |
+ return sprintf(\'%1$s%2$s\', round($rowData[\'size\'] / 1024, 2), $txt[\'kilobyte\']); |
|
160 |
+ '), |
|
161 |
+ 'class' => 'windowbg', |
|
162 |
+ ), |
|
163 |
+ 'sort' => array( |
|
164 |
+ 'default' => 'a.size', |
|
165 |
+ 'reverse' => 'a.size DESC', |
|
166 |
+ ), |
|
167 |
+ ), |
|
168 |
+ 'member' => array( |
|
169 |
+ 'header' => array( |
|
170 |
+ 'value' => $txt['posted_by'], |
|
171 |
+ ), |
|
172 |
+ 'data' => array( |
|
173 |
+ 'function' => create_function('$rowData', ' |
|
174 |
+ global $scripturl; |
|
175 |
+ |
|
176 |
+ return htmlspecialchars($rowData[\'poster_name\']); |
|
177 |
+ '), |
|
178 |
+ ), |
|
179 |
+ 'sort' => array( |
|
180 |
+ 'default' => 'mem.real_name', |
|
181 |
+ 'reverse' => 'mem.real_name DESC', |
|
182 |
+ ), |
|
183 |
+ ), |
|
184 |
+ 'date' => array( |
|
185 |
+ 'header' => array( |
|
186 |
+ 'value' => $txt['date'], |
|
187 |
+ ), |
|
188 |
+ 'data' => array( |
|
189 |
+ 'function' => create_function('$rowData', ' |
|
190 |
+ global $txt, $context, $scripturl; |
|
191 |
+ |
|
192 |
+ return empty($rowData[\'poster_time\']) ? $txt[\'never\'] : timeformat($rowData[\'poster_time\']); |
|
193 |
+ '), |
|
194 |
+ 'class' => 'windowbg', |
|
195 |
+ ), |
|
196 |
+ 'sort' => array( |
|
197 |
+ 'default' => 'hdtr.id_msg', |
|
198 |
+ 'reverse' => 'hdtr.id_msg DESC', |
|
199 |
+ ), |
|
200 |
+ ), |
|
201 |
+ 'downloads' => array( |
|
202 |
+ 'header' => array( |
|
203 |
+ 'value' => $txt['downloads'], |
|
204 |
+ ), |
|
205 |
+ 'data' => array( |
|
206 |
+ 'function' => create_function('$rowData',' |
|
207 |
+ global $txt; |
|
208 |
+ |
|
209 |
+ return comma_format($rowData[\'downloads\']); |
|
210 |
+ '), |
|
211 |
+ 'class' => 'windowbg', |
|
212 |
+ ), |
|
213 |
+ 'sort' => array( |
|
214 |
+ 'default' => 'a.downloads', |
|
215 |
+ 'reverse' => 'a.downloads DESC', |
|
216 |
+ ), |
|
217 |
+ ), |
|
218 |
+ 'check' => array( |
|
219 |
+ 'header' => array( |
|
220 |
+ 'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check" />', |
|
221 |
+ ), |
|
222 |
+ 'data' => array( |
|
223 |
+ 'sprintf' => array( |
|
224 |
+ 'format' => '<input type="checkbox" name="remove[%1$d]" class="input_check" />', |
|
225 |
+ 'params' => array( |
|
226 |
+ 'id_attach' => false, |
|
227 |
+ ), |
|
228 |
+ ), |
|
229 |
+ 'style' => 'text-align: center', |
|
230 |
+ ), |
|
231 |
+ ), |
|
232 |
+ ), |
|
233 |
+ 'form' => array( |
|
234 |
+ 'href' => $scripturl . '?action=admin;area=manageattachments;sa=remove;' . $context['browse_type'], |
|
235 |
+ 'include_sort' => true, |
|
236 |
+ 'include_start' => true, |
|
237 |
+ 'hidden_fields' => array( |
|
238 |
+ 'type' => $context['browse_type'], |
|
239 |
+ ), |
|
240 |
+ ), |
|
241 |
+ 'additional_rows' => array( |
|
242 |
+ array( |
|
243 |
+ 'position' => 'below_table_data', |
|
244 |
+ 'value' => '<input type="submit" name="remove_submit" class="button_submit" value="' . $txt['quickmod_delete_selected'] . '" onclick="return confirm(\'' . $txt['confirm_delete_attachments'] . '\');" />', |
|
245 |
+ 'class' => 'titlebg', |
|
246 |
+ 'style' => 'text-align: right;', |
|
247 |
+ ), |
|
248 |
+ ), |
|
249 |
+ ); |
|
250 |
+ |
|
251 |
+ // Create the list. |
|
252 |
+ require_once($sourcedir . '/Subs-List.php'); |
|
253 |
+ createList($listOptions); |
|
254 |
+} |
|
255 |
+ |
|
256 |
+function shd_list_get_files($start, $items_per_page, $sort, $browse_type) |
|
257 |
+{ |
|
258 |
+ global $smcFunc, $txt; |
|
259 |
+ |
|
260 |
+ $request = $smcFunc['db_query']('', ' |
|
261 |
+ SELECT |
|
262 |
+ hdtr.id_msg, IFNULL(mem.real_name, hdtr.poster_name) AS poster_name, hdtr.poster_time, hdt.id_ticket, hdtr.id_member, |
|
263 |
+ a.id_attach, a.filename, a.file_hash, a.attachment_type, a.size, a.width, a.height, a.downloads, hdt.subject |
|
264 |
+ FROM {db_prefix}attachments AS a |
|
265 |
+ INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (a.id_attach = hda.id_attach) |
|
266 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hda.id_ticket = hdt.id_ticket) |
|
267 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hda.id_msg = hdtr.id_msg) |
|
268 |
+ LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = hdtr.id_member) |
|
269 |
+ WHERE a.attachment_type = {int:attachment_type} |
|
270 |
+ ORDER BY {raw:sort} |
|
271 |
+ LIMIT {int:start}, {int:per_page}', |
|
272 |
+ array( |
|
273 |
+ 'attachment_type' => $browse_type === 'shd_thumb' ? '3' : '0', |
|
274 |
+ 'sort' => $sort, |
|
275 |
+ 'start' => $start, |
|
276 |
+ 'per_page' => $items_per_page, |
|
277 |
+ ) |
|
278 |
+ ); |
|
279 |
+ $files = array(); |
|
280 |
+ while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
281 |
+ $files[] = $row; |
|
282 |
+ $smcFunc['db_free_result']($request); |
|
283 |
+ |
|
284 |
+ return $files; |
|
285 |
+} |
|
286 |
+ |
|
287 |
+function shd_list_get_num_files($browse_type) |
|
288 |
+{ |
|
289 |
+ global $smcFunc; |
|
290 |
+ |
|
291 |
+ $request = $smcFunc['db_query']('', ' |
|
292 |
+ SELECT COUNT(*) AS num_attach |
|
293 |
+ FROM {db_prefix}attachments AS a |
|
294 |
+ INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (a.id_attach = hda.id_attach) |
|
295 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hda.id_ticket = hdt.id_ticket) |
|
296 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hda.id_msg = hdtr.id_msg) |
|
297 |
+ WHERE a.attachment_type = {int:attachment_type} |
|
298 |
+ AND a.id_member = {int:guest_id_member}', |
|
299 |
+ array( |
|
300 |
+ 'attachment_type' => $browse_type === 'shd_thumb' ? '3' : '0', |
|
301 |
+ 'guest_id_member' => 0, |
|
302 |
+ ) |
|
303 |
+ ); |
|
304 |
+ |
|
305 |
+ list ($num_files) = $smcFunc['db_fetch_row']($request); |
|
306 |
+ $smcFunc['db_free_result']($request); |
|
307 |
+ |
|
308 |
+ return $num_files; |
|
309 |
+} |
|
310 |
+ |
|
311 |
+]]></add> |
|
312 |
+ </operation> |
|
313 |
+ </file> |
|
314 |
+ |
|
315 |
+ <file name="$themedir/ManageAttachments.template.php"> |
|
316 |
+ <operation> |
|
317 |
+ <search position="before"><![CDATA[$txt['attachment_manager_thumbs'], ']]></search> |
|
318 |
+ <add><![CDATA[', (empty($GLOBALS['modSettings']['helpdesk_active']) ? '' : '</a> | |
|
319 |
+ <a href="' . $scripturl . '?action=admin;area=manageattachments;sa=browse;shd_attach">' . ($context['browse_type'] == 'shd_attach' ? '<img src="' . $settings['images_url'] . '/selected.gif" alt=">" border="0" /> ' : '') . $txt['attachment_manager_shd_attach'] . '</a> | |
|
320 |
+ <a href="' . $scripturl . '?action=admin;area=manageattachments;sa=browse;shd_thumb">' . ($context['browse_type'] == 'shd_thumb' ? '<img src="' . $settings['images_url'] . '/selected.gif" alt=">" border="0" /> ' : '') . $txt['attachment_manager_shd_thumb']), ']]></add> |
|
321 |
+ </operation> |
|
322 |
+ </file> |
|
323 |
+ |
|
324 |
+</modification> |
|
0 | 325 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,177 @@ |
1 |
+<?xml version="1.0"?> |
|
2 |
+<!DOCTYPE modification SYSTEM "http://www.simplemachines.org/xml/modification"> |
|
3 |
+<modification xmlns="http://www.simplemachines.org/xml/modification" xmlns:smf="http://www.simplemachines.org/"> |
|
4 |
+ <id>SimpleDeskTeam:SimpleDesk</id> |
|
5 |
+ <version>1.1 rev753</version> |
|
6 |
+ |
|
7 |
+ <file name="$sourcedir/Profile-View.php"> |
|
8 |
+ <operation><!-- add the code to call for IP tracking --> |
|
9 |
+ <search position="after"><![CDATA[ $context['single_ip'] = strpos($context['ip'], '*') === false;]]></search> |
|
10 |
+ <add><![CDATA[ // Set the options for the helpdesk replies list. |
|
11 |
+ if (!empty($modSettings['helpdesk_active'])) |
|
12 |
+ { |
|
13 |
+ $listOptions = array( |
|
14 |
+ 'id' => 'track_helpdesk_list', |
|
15 |
+ 'title' => $txt['shd_replies_from_ip'] . ' ' . $context['ip'], |
|
16 |
+ 'start_var_name' => 'helpdeskStart', |
|
17 |
+ 'items_per_page' => $modSettings['defaultMaxMessages'], |
|
18 |
+ 'no_items_label' => $txt['shd_replies_from_ip'], |
|
19 |
+ 'base_href' => $context['base_url'] . ';searchip=' . $context['ip'], |
|
20 |
+ 'default_sort_col' => 'date2', |
|
21 |
+ 'get_items' => array( |
|
22 |
+ 'function' => 'shd_list_get_ip_messages', |
|
23 |
+ 'params' => array( |
|
24 |
+ 'hdtr.poster_ip ' . $ip_string, |
|
25 |
+ array('ip_address' => $ip_var), |
|
26 |
+ ), |
|
27 |
+ ), |
|
28 |
+ 'get_count' => array( |
|
29 |
+ 'function' => 'shd_list_get_ip_message_count', |
|
30 |
+ 'params' => array( |
|
31 |
+ 'hdtr.poster_ip ' . $ip_string, |
|
32 |
+ array('ip_address' => $ip_var), |
|
33 |
+ ), |
|
34 |
+ ), |
|
35 |
+ 'columns' => array( |
|
36 |
+ 'ip_address2' => array( |
|
37 |
+ 'header' => array( |
|
38 |
+ 'value' => $txt['ip_address'], |
|
39 |
+ ), |
|
40 |
+ 'data' => array( |
|
41 |
+ 'sprintf' => array( |
|
42 |
+ 'format' => '<a href="' . $context['base_url'] . ';searchip=%1$s">%1$s</a>', |
|
43 |
+ 'params' => array( |
|
44 |
+ 'ip' => false, |
|
45 |
+ ), |
|
46 |
+ ), |
|
47 |
+ ), |
|
48 |
+ 'sort' => array( |
|
49 |
+ 'default' => 'INET_ATON(hdtr.poster_ip)', |
|
50 |
+ 'reverse' => 'INET_ATON(hdtr.poster_ip) DESC', |
|
51 |
+ ), |
|
52 |
+ ), |
|
53 |
+ 'display_name' => array( |
|
54 |
+ 'header' => array( |
|
55 |
+ 'value' => $txt['display_name'], |
|
56 |
+ ), |
|
57 |
+ 'data' => array( |
|
58 |
+ 'db' => 'member_link', |
|
59 |
+ ), |
|
60 |
+ ), |
|
61 |
+ 'subject' => array( |
|
62 |
+ 'header' => array( |
|
63 |
+ 'value' => $txt['subject'], |
|
64 |
+ ), |
|
65 |
+ 'data' => array( |
|
66 |
+ 'sprintf' => array( |
|
67 |
+ 'format' => '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=%1$s.msg%2$s#msg%2$s" rel="nofollow">%3$s</a>%4$s', |
|
68 |
+ 'params' => array( |
|
69 |
+ 'ticket' => false, |
|
70 |
+ 'id' => false, |
|
71 |
+ 'subject' => false, |
|
72 |
+ 'additional' => false, |
|
73 |
+ ), |
|
74 |
+ ), |
|
75 |
+ ), |
|
76 |
+ ), |
|
77 |
+ 'date2' => array( |
|
78 |
+ 'header' => array( |
|
79 |
+ 'value' => $txt['date'], |
|
80 |
+ ), |
|
81 |
+ 'data' => array( |
|
82 |
+ 'db' => 'time', |
|
83 |
+ ), |
|
84 |
+ 'sort' => array( |
|
85 |
+ 'default' => 'hdtr.id_msg DESC', |
|
86 |
+ 'reverse' => 'hdtr.id_msg', |
|
87 |
+ ), |
|
88 |
+ ), |
|
89 |
+ ), |
|
90 |
+ 'additional_rows' => array( |
|
91 |
+ array( |
|
92 |
+ 'position' => 'after_title', |
|
93 |
+ 'value' => '<span class="smalltext">' . $txt['shd_replies_from_ip_desc'] . '</span>', |
|
94 |
+ 'class' => 'windowbg', |
|
95 |
+ 'style' => 'padding: 2ex;', |
|
96 |
+ ), |
|
97 |
+ ), |
|
98 |
+ ); |
|
99 |
+ |
|
100 |
+ // Create the helpdesk replies list. |
|
101 |
+ createList($listOptions); |
|
102 |
+ } |
|
103 |
+ |
|
104 |
+]]></add> |
|
105 |
+ </operation> |
|
106 |
+ <operation><!-- add the code to get IP tracking data --> |
|
107 |
+ <search position="end" /> |
|
108 |
+ <add><![CDATA[ |
|
109 |
+ |
|
110 |
+function shd_list_get_ip_messages($start, $items_per_page, $sort, $where, $where_vars = array()) |
|
111 |
+{ |
|
112 |
+ global $smcFunc, $txt, $scripturl; |
|
113 |
+ $query = shd_db_query('', ' |
|
114 |
+ SELECT |
|
115 |
+ hdtr.id_msg, hdtr.poster_ip, IFNULL(mem.real_name, hdtr.poster_name) AS display_name, mem.id_member, |
|
116 |
+ hdt.subject, hdtr.poster_time, hdt.id_ticket, hdt.id_first_msg |
|
117 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
118 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket) |
|
119 |
+ LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = hdtr.id_member) |
|
120 |
+ WHERE {query_see_ticket} AND ' . $where . ' |
|
121 |
+ ORDER BY ' . $sort . ' |
|
122 |
+ LIMIT ' . $start . ', ' . $items_per_page, |
|
123 |
+ array_merge($where_vars, array( |
|
124 |
+ )) |
|
125 |
+ ); |
|
126 |
+ $messages = array(); |
|
127 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
128 |
+ $messages[] = array( |
|
129 |
+ 'ip' => $row['poster_ip'], |
|
130 |
+ 'member_link' => shd_profile_link($row['display_name'], $row['id_member']), |
|
131 |
+ 'ticket' => $row['id_ticket'], |
|
132 |
+ 'id' => $row['id_msg'], |
|
133 |
+ 'subject' => $row['subject'], |
|
134 |
+ 'time' => timeformat($row['poster_time']), |
|
135 |
+ 'timestamp' => forum_time(true, $row['poster_time']), |
|
136 |
+ 'additional' => $row['id_first_msg'] == $row['id_msg'] ? $txt['shd_is_ticket_opener'] : '', |
|
137 |
+ ); |
|
138 |
+ $smcFunc['db_free_result']($query); |
|
139 |
+ |
|
140 |
+ return $messages; |
|
141 |
+} |
|
142 |
+ |
|
143 |
+function shd_list_get_ip_message_count($where, $where_vars = array()) |
|
144 |
+{ |
|
145 |
+ global $smcFunc; |
|
146 |
+ |
|
147 |
+ $request = shd_db_query('', ' |
|
148 |
+ SELECT COUNT(id_msg) AS message_count |
|
149 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
150 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket) |
|
151 |
+ WHERE {query_see_ticket} AND ' . $where, |
|
152 |
+ $where_vars |
|
153 |
+ ); |
|
154 |
+ list ($count) = $smcFunc['db_fetch_row']($request); |
|
155 |
+ $smcFunc['db_free_result']($request); |
|
156 |
+ |
|
157 |
+ return $count; |
|
158 |
+} |
|
159 |
+ |
|
160 |
+]]></add> |
|
161 |
+ </operation> |
|
162 |
+ </file> |
|
163 |
+ |
|
164 |
+ <file name="$themedir/Profile.template.php"><!-- add the display of tracked IPs to the profile view --> |
|
165 |
+ <operation> |
|
166 |
+ <search position="before"><![CDATA[template_show_list('track_message_list');]]></search> |
|
167 |
+ <add><![CDATA[ |
|
168 |
+ global $modSettings; |
|
169 |
+ if (!empty($modSettings['helpdesk_active'])) |
|
170 |
+ { |
|
171 |
+ echo '<br />'; |
|
172 |
+ |
|
173 |
+ template_show_list('track_helpdesk_list'); |
|
174 |
+ }]]></add> |
|
175 |
+ </operation> |
|
176 |
+ </file> |
|
177 |
+</modification> |
|
0 | 178 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,692 @@ |
1 |
+<?xml version="1.0"?> |
|
2 |
+<!DOCTYPE modification SYSTEM "http://www.simplemachines.org/xml/modification"> |
|
3 |
+<modification xmlns="http://www.simplemachines.org/xml/modification" xmlns:smf="http://www.simplemachines.org/"> |
|
4 |
+ <id>SimpleDeskTeam:SimpleDesk</id> |
|
5 |
+ <version>1.1 rev753</version> |
|
6 |
+ |
|
7 |
+ <file name="$sourcedir/Admin.php"><!-- adds the navbar links to the admin panel --> |
|
8 |
+ <operation><!-- main SHD menu --> |
|
9 |
+ <search position="after"><![CDATA[ // Make sure the administrator has a valid session...]]></search> |
|
10 |
+ <add><![CDATA[ // Add the SHD item to the menu |
|
11 |
+ if (!empty($modSettings['helpdesk_active'])) |
|
12 |
+ { |
|
13 |
+ $admin_areas['helpdesk_info'] = array( |
|
14 |
+ 'title' => $txt['shd_helpdesk'], |
|
15 |
+ 'enabled' => allowedTo('admin_forum') || shd_allowed_to('admin_helpdesk'), |
|
16 |
+ 'areas' => array( |
|
17 |
+ 'helpdesk_info' => array( |
|
18 |
+ 'label' => $txt['shd_admin_info'], |
|
19 |
+ 'file' => 'sd_source/SimpleDesk-Admin.php', |
|
20 |
+ 'icon' => 'shd/simpledesk.png', |
|
21 |
+ 'function' => 'shd_admin_main', |
|
22 |
+ 'subsections' => array( |
|
23 |
+ 'main' => array($txt['shd_admin_info']), |
|
24 |
+ 'actionlog' => array($txt['shd_admin_actionlog'], 'enabled' => empty($modSettings['shd_disable_action_log'])), |
|
25 |
+ 'support' => array($txt['shd_admin_support']), |
|
26 |
+ ), |
|
27 |
+ ), |
|
28 |
+ 'helpdesk_options' => array( |
|
29 |
+ 'label' => $txt['shd_admin_options'], |
|
30 |
+ 'file' => 'sd_source/SimpleDesk-Admin.php', |
|
31 |
+ 'icon' => 'shd/status.png', |
|
32 |
+ 'function' => 'shd_admin_main', |
|
33 |
+ 'subsections' => array( |
|
34 |
+ 'display' => array($txt['shd_admin_options_display']), |
|
35 |
+ 'posting' => array($txt['shd_admin_options_posting']), |
|
36 |
+ 'admin' => array($txt['shd_admin_options_admin']), |
|
37 |
+ 'standalone' => array($txt['shd_admin_options_standalone']), |
|
38 |
+ 'actionlog' => array($txt['shd_admin_options_actionlog']), |
|
39 |
+ ), |
|
40 |
+ ), |
|
41 |
+ 'helpdesk_customfield' => array( |
|
42 |
+ 'label' => $txt['shd_admin_custom_fields'], |
|
43 |
+ 'file' => 'sd_source/SimpleDesk-Admin.php', |
|
44 |
+ 'icon' => 'shd/custom_fields.png', |
|
45 |
+ 'function' => 'shd_admin_main', |
|
46 |
+ 'subsections' => array( |
|
47 |
+ ), |
|
48 |
+ ), |
|
49 |
+ 'helpdesk_permissions' => array( |
|
50 |
+ 'label' => $txt['shd_admin_permissions'], |
|
51 |
+ 'file' => 'sd_source/SimpleDesk-Admin.php', |
|
52 |
+ 'icon' => 'shd/permissions.png', |
|
53 |
+ 'function' => 'shd_admin_main', |
|
54 |
+ 'subsections' => array( |
|
55 |
+ ), |
|
56 |
+ ), |
|
57 |
+ 'helpdesk_plugins' => array( |
|
58 |
+ 'label' => $txt['shd_admin_plugins'], |
|
59 |
+ 'file' => 'sd_source/SimpleDesk-Admin.php', |
|
60 |
+ 'icon' => 'shd/plugins.png', |
|
61 |
+ 'function' => 'shd_admin_main', |
|
62 |
+ 'subsections' => array( |
|
63 |
+ ), |
|
64 |
+ ), |
|
65 |
+ ), |
|
66 |
+ ); |
|
67 |
+ |
|
68 |
+ // Now engage any hooks. |
|
69 |
+ if (!empty($modSettings['shd_hook_adminmenu'])) |
|
70 |
+ { |
|
71 |
+ $functions = explode(',', $modSettings['shd_hook_adminmenu']); |
|
72 |
+ foreach ($functions as $function) |
|
73 |
+ { |
|
74 |
+ if (is_callable($function)) |
|
75 |
+ $function($admin_areas); // this should be picked up by reference in the called function or it won't do anything! |
|
76 |
+ } |
|
77 |
+ } |
|
78 |
+ } |
|
79 |
+ |
|
80 |
+]]></add> |
|
81 |
+ </operation> |
|
82 |
+ <operation><!-- add the item to the logs menu --> |
|
83 |
+ <search position="before"><![CDATA['pruning' => array($txt['pruning_title'], 'admin_forum'),]]></search> |
|
84 |
+ <add><![CDATA[ |
|
85 |
+ 'helpdesklog' => array($txt['shd_admin_helpdesklog'], 'admin_forum', 'enabled' => $modSettings['helpdesk_active'] && empty($modSettings['shd_disable_action_log']), 'url' => $scripturl . '?action=admin;area=helpdesk_info;sa=actionlog'),]]></add> |
|
86 |
+ </operation> |
|
87 |
+ <operation><!-- load the SD admin language file --> |
|
88 |
+ <search position="before"><![CDATA[loadLanguage('Admin');]]></search> |
|
89 |
+ <add><![CDATA[ |
|
90 |
+ shd_load_language('SimpleDeskAdmin'); |
|
91 |
+ shd_load_plugin_files('hdadmin'); |
|
92 |
+ shd_load_plugin_langfiles('hdadmin');]]></add> |
|
93 |
+ </operation> |
|
94 |
+ <operation><!-- add SimpleDesk-Admin to the list of files to load when doing admin search --> |
|
95 |
+ <search position="after"><![CDATA[ foreach ($include_files as $file)]]></search> |
|
96 |
+ <add><![CDATA[ // Add SimpleDesk's files (including plugins) before we start anything |
|
97 |
+ $include_files[] = 'sd_source/SimpleDesk-Admin'; |
|
98 |
+ shd_load_plugin_files('hdadmin'); |
|
99 |
+ shd_load_plugin_langfiles('hdadmin'); |
|
100 |
+ |
|
101 |
+]]></add> |
|
102 |
+ </operation> |
|
103 |
+ <operation><!-- prepend SimpleDesk's ACP helper functions to the list of places to search --> |
|
104 |
+ <search position="replace"><![CDATA[// This is a special array of functions that contain setting data - we query all these to simply pull all setting bits! |
|
105 |
+ $settings_search = array(]]></search> |
|
106 |
+ <add><![CDATA[// Add SimpleDesk functions |
|
107 |
+ $settings_search = array(); |
|
108 |
+ $settings_search[] = array('shd_modify_display_options', 'area=helpdesk_options;sa=display'); |
|
109 |
+ $settings_search[] = array('shd_modify_posting_options', 'area=helpdesk_options;sa=posting'); |
|
110 |
+ $settings_search[] = array('shd_modify_admin_options', 'area=helpdesk_options;sa=admin'); |
|
111 |
+ $settings_search[] = array('shd_modify_standalone_options', 'area=helpdesk_options;sa=standalone'); |
|
112 |
+ $settings_search[] = array('shd_modify_actionlog_options', 'area=helpdesk_options;sa=actionlog'); |
|
113 |
+ |
|
114 |
+ if (!empty($modSettings['shd_hook_hdadminoptssrch'])) |
|
115 |
+ { |
|
116 |
+ $functions = explode(',', $modSettings['shd_hook_hdadminoptssrch']); |
|
117 |
+ foreach ($functions as $function) |
|
118 |
+ { |
|
119 |
+ if (is_callable($function)) |
|
120 |
+ $function($settings_search); // by reference! |
|
121 |
+ } |
|
122 |
+ } |
|
123 |
+ |
|
124 |
+ $search_entries = count($settings_search); |
|
125 |
+ |
|
126 |
+ // This is a special array of functions that contain setting data - we query all these to simply pull all setting bits! |
|
127 |
+ $settings_search += array( |
|
128 |
+ $search_entries =>]]></add> |
|
129 |
+ </operation> |
|
130 |
+ </file> |
|
131 |
+ |
|
132 |
+ <file name="$sourcedir/Load.php"><!-- globally figure out if Helpdesk is enabled; note this doesn't get pushed into settings table :) --> |
|
133 |
+ <operation> |
|
134 |
+ <search position="after"><![CDATA[ // Build the list of boards they WANT to see.]]></search> |
|
135 |
+ <add><![CDATA[ // Are we helping people today? If so, bootstrap SimpleDesk. |
|
136 |
+ shd_init(); |
|
137 |
+ |
|
138 |
+]]></add> |
|
139 |
+ </operation> |
|
140 |
+ </file> |
|
141 |
+ |
|
142 |
+ <file name="$sourcedir/Profile.php"><!-- Add the profile section --> |
|
143 |
+ <operation><!-- Add the SimpleDesk section to the Profile menu --> |
|
144 |
+ <search position="after"><![CDATA[ // Is there an updated message to show?]]></search> |
|
145 |
+ <add><![CDATA[ // SimpleDesk sections. Added here after the initial cleaning is done, so that we can do our own permission checks without arguing with SMF's system (so much) |
|
146 |
+ if (!empty($modSettings['helpdesk_active'])) |
|
147 |
+ { |
|
148 |
+ shd_load_language('SimpleDeskProfile'); |
|
149 |
+ |
|
150 |
+ // Put it here so we can reuse it for the left menu a bit |
|
151 |
+ $context['helpdesk_menu'] = array( |
|
152 |
+ 'title' => $txt['shd_profile_area'], |
|
153 |
+ 'areas' => array( |
|
154 |
+ 'helpdesk' => array( |
|
155 |
+ 'label' => $txt['shd_profile_main'], |
|
156 |
+ 'file' => 'sd_source/SimpleDesk-Profile.php', |
|
157 |
+ 'function' => 'shd_profile_main', |
|
158 |
+ 'enabled' => shd_allowed_to('shd_view_profile_any') || ($context['user']['is_owner'] && shd_allowed_to('shd_view_profile_own')), |
|
159 |
+ ), |
|
160 |
+ 'hd_prefs' => array( |
|
161 |
+ 'label' => $txt['shd_profile_preferences'], |
|
162 |
+ 'file' => 'sd_source/SimpleDesk-Profile.php', |
|
163 |
+ 'function' => 'shd_profile_main', |
|
164 |
+ 'enabled' => shd_allowed_to('shd_view_preferences_any') || ($context['user']['is_owner'] && shd_allowed_to('shd_view_preferences_own')), |
|
165 |
+ ), |
|
166 |
+ 'hd_showtickets' => array( |
|
167 |
+ 'label' => $txt['shd_profile_show_tickets'], |
|
168 |
+ 'file' => 'sd_source/SimpleDesk-Profile.php', |
|
169 |
+ 'function' => 'shd_profile_main', |
|
170 |
+ 'enabled' => ($context['user']['is_owner'] && shd_allowed_to('shd_view_ticket_own')) || shd_allowed_to('shd_view_ticket_any'), |
|
171 |
+ ), |
|
172 |
+ 'hd_permissions' => array( |
|
173 |
+ 'label' => $txt['shd_profile_permissions'], |
|
174 |
+ 'file' => 'sd_source/SimpleDesk-Profile.php', |
|
175 |
+ 'function' => 'shd_profile_main', |
|
176 |
+ 'enabled' => shd_allowed_to('admin_helpdesk'), |
|
177 |
+ ), |
|
178 |
+ 'hd_actionlog' => array( |
|
179 |
+ 'label' => $txt['shd_profile_actionlog'], |
|
180 |
+ 'file' => 'sd_source/SimpleDesk-Profile.php', |
|
181 |
+ 'function' => 'shd_profile_main', |
|
182 |
+ 'enabled' => empty($modSettings['shd_disable_action_log']) && (shd_allowed_to('shd_view_profile_log_any') || ($context['user']['is_owner'] && shd_allowed_to('shd_view_profile_log_own'))), |
|
183 |
+ ), |
|
184 |
+ ), |
|
185 |
+ ); |
|
186 |
+ |
|
187 |
+ // Kill the existing profile menu but save it in a temporary place first. |
|
188 |
+ $old_profile_areas = $profile_areas; |
|
189 |
+ $profile_areas = array(); |
|
190 |
+ |
|
191 |
+ // Now, where we add this depends very much on what mode we're in. In HD only mode, we want our menu first before anything else. |
|
192 |
+ if (!empty($modSettings['shd_helpdesk_only'])) |
|
193 |
+ { |
|
194 |
+ $profile_areas['helpdesk'] = $context['helpdesk_menu']; |
|
195 |
+ $profile_areas += $old_profile_areas; |
|
196 |
+ } |
|
197 |
+ else |
|
198 |
+ // In non HD only, put it before the editing stuff menu |
|
199 |
+ { |
|
200 |
+ foreach ($old_profile_areas as $area => $details) |
|
201 |
+ { |
|
202 |
+ if ($area == 'edit_profile') |
|
203 |
+ $profile_areas['helpdesk'] = $context['helpdesk_menu']; |
|
204 |
+ $profile_areas[$area] = $details; |
|
205 |
+ } |
|
206 |
+ } |
|
207 |
+ |
|
208 |
+ // Now engage any hooks. |
|
209 |
+ if (!empty($modSettings['shd_hook_profilemenu'])) |
|
210 |
+ { |
|
211 |
+ $functions = explode(',', $modSettings['shd_hook_profilemenu']); |
|
212 |
+ foreach ($functions as $function) |
|
213 |
+ { |
|
214 |
+ if (is_callable($function)) |
|
215 |
+ $function($profile_areas); // this should be picked up by reference in the called function or it won't do anything! |
|
216 |
+ } |
|
217 |
+ } |
|
218 |
+ } |
|
219 |
+ |
|
220 |
+]]></add> |
|
221 |
+ </operation> |
|
222 |
+ </file> |
|
223 |
+ |
|
224 |
+ <file name="$sourcedir/Subs.php"><!-- reconfigure the main menu somewhat --> |
|
225 |
+ <operation><!-- add a generic menu item --> |
|
226 |
+ <search position="replace"><![CDATA[ ), |
|
227 |
+ 'profile' => array(]]></search> |
|
228 |
+ <add><![CDATA[ ), |
|
229 |
+ 'helpdesk' => array( |
|
230 |
+ 'title' => $modSettings['helpdesk_active'] && SMF != 'SSI' ? shd_get_active_tickets() : $txt['shd_helpdesk'], |
|
231 |
+ 'href' => $scripturl . '?action=helpdesk;sa=main', |
|
232 |
+ 'show' => $modSettings['helpdesk_active'] && shd_allowed_to(array('access_helpdesk', 'admin_helpdesk')), |
|
233 |
+ 'sub_buttons' => array( |
|
234 |
+ 'newticket' => array( |
|
235 |
+ 'title' => $txt['shd_new_ticket'], |
|
236 |
+ 'href' => $scripturl . '?action=helpdesk;sa=newticket', |
|
237 |
+ 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_new_ticket'), |
|
238 |
+ ), |
|
239 |
+ 'newproxyticket' => array( |
|
240 |
+ 'title' => $txt['shd_new_ticket_proxy'], |
|
241 |
+ 'href' => $scripturl . '?action=helpdesk;sa=newticket;proxy', |
|
242 |
+ 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_new_ticket') && shd_allowed_to('shd_post_proxy'), |
|
243 |
+ ), |
|
244 |
+ 'closedtickets' => array( |
|
245 |
+ 'title' => $txt['shd_tickets_closed'], |
|
246 |
+ 'href' => $scripturl . '?action=helpdesk;sa=closedtickets', |
|
247 |
+ 'show' => SMF == 'SSI' ? false : (shd_allowed_to('shd_resolve_ticket_own') || shd_allowed_to('shd_resolve_ticket_any')), |
|
248 |
+ ), |
|
249 |
+ 'recyclebin' => array( |
|
250 |
+ 'title' => $txt['shd_recycle_bin'], |
|
251 |
+ 'href' => $scripturl . '?action=helpdesk;sa=recyclebin', |
|
252 |
+ 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_access_recyclebin'), |
|
253 |
+ 'is_last' => true, |
|
254 |
+ ), |
|
255 |
+ ), |
|
256 |
+ ), |
|
257 |
+ 'profile' => array(]]></add> |
|
258 |
+ </operation> |
|
259 |
+ <operation><!-- turn off PMs if they're disabled --> |
|
260 |
+ <search position="replace"><![CDATA[$context['allow_pm'] = allowedTo('pm_read');]]></search> |
|
261 |
+ <add><![CDATA[$context['allow_pm'] = allowedTo('pm_read') && (empty($modSettings['helpdesk_active']) || empty($modSettings['shd_helpdesk_only']) || empty($modSettings['shd_disable_pm']));]]></add> |
|
262 |
+ </operation> |
|
263 |
+ <operation><!-- expand the quote link= parameter --> |
|
264 |
+ <search position="before"><![CDATA[(?:topic|threadid)=[\dmsg#\./]{1,40}(?:;start=[\dmsg#\./]{1,40})?]]></search> |
|
265 |
+ <add><![CDATA[|action=helpdesk;sa=ticket;ticket=[\dmsg#\./]{1,40}(?:;start=[\dmsg#\./]{1,40})?]]></add> |
|
266 |
+ </operation> |
|
267 |
+ <operation><!-- mess with the main menu --> |
|
268 |
+ <search position="after"><![CDATA[ $context['menu_buttons'] = $menu_buttons;]]></search> |
|
269 |
+ <add><![CDATA[ // SD specific options |
|
270 |
+ if (!empty($modSettings['helpdesk_active'])) |
|
271 |
+ { |
|
272 |
+ // Stuff we'll always do in SD if active |
|
273 |
+ |
|
274 |
+ // Fix up the helpdesk menu's is_last item - if it exists (if insufficient permission, it'll have already been eaten) |
|
275 |
+ if (!empty($menu_buttons['helpdesk'])) |
|
276 |
+ { |
|
277 |
+ $item = false; |
|
278 |
+ foreach ($menu_buttons['helpdesk']['sub_buttons'] as $key => $value) |
|
279 |
+ { |
|
280 |
+ if (!empty($value['show'])) |
|
281 |
+ $item = $key; |
|
282 |
+ } |
|
283 |
+ if (!empty($item)) |
|
284 |
+ $menu_buttons['helpdesk']['sub_buttons'][$key]['is_last'] = true; |
|
285 |
+ } |
|
286 |
+ |
|
287 |
+ // Add the helpdesk admin option to the admin menu |
|
288 |
+ if (allowedTo('admin_forum') || shd_allowed_to('admin_helpdesk')) |
|
289 |
+ { |
|
290 |
+ // Make sure the button is visible if you can admin forum |
|
291 |
+ $menu_buttons['admin']['show'] = true; |
|
292 |
+ |
|
293 |
+ // Remove the is_last item |
|
294 |
+ foreach ($menu_buttons['admin']['sub_buttons'] as $key => $value) |
|
295 |
+ { |
|
296 |
+ if (!empty($value['is_last'])) |
|
297 |
+ unset($menu_buttons['admin']['sub_buttons'][$key]['is_last']); |
|
298 |
+ } |
|
299 |
+ |
|
300 |
+ // Add the new button |
|
301 |
+ $menu_buttons['admin']['sub_buttons']['helpdesk_admin'] = array( |
|
302 |
+ 'title' => $txt['shd_helpdesk'], |
|
303 |
+ 'href' => $scripturl . '?action=admin;area=helpdesk_info', |
|
304 |
+ 'show' => true, |
|
305 |
+ 'is_last' => true, |
|
306 |
+ ); |
|
307 |
+ } |
|
308 |
+ |
|
309 |
+ if (shd_allowed_to(array('shd_view_profile_own', 'shd_view_profile_any'))) |
|
310 |
+ { |
|
311 |
+ // Hmm, this could be tricky. It's possible the main menu has been eaten by permissions at this point, so just in case, reconstruct what's missing. |
|
312 |
+ if (empty($menu_buttons['profile'])) |
|
313 |
+ { |
|
314 |
+ $profile_menu = array( |
|
315 |
+ 'title' => $txt['profile'], |
|
316 |
+ 'href' => $scripturl . '?action=profile', |
|
317 |
+ 'active_button' => false, |
|
318 |
+ 'sub_buttons' => array( |
|
319 |
+ ), |
|
320 |
+ ); |
|
321 |
+ |
|
322 |
+ // Trouble is, now we've done that, it's in the wrong damn place. So step through and insert our menu into just after the SD menu |
|
323 |
+ $old_menu_buttons = $menu_buttons; |
|
324 |
+ $menu_buttons = array(); |
|
325 |
+ |
|
326 |
+ foreach ($old_menu_buttons as $area => $detail) |
|
327 |
+ { |
|
328 |
+ $menu_buttons[$area] = $detail; |
|
329 |
+ |
|
330 |
+ if ($area == 'helpdesk') |
|
331 |
+ $menu_buttons['profile'] = $profile_menu; |
|
332 |
+ } |
|
333 |
+ } |
|
334 |
+ |
|
335 |
+ // Remove the is_last item |
|
336 |
+ foreach ($menu_buttons['profile']['sub_buttons'] as $key => $value) |
|
337 |
+ { |
|
338 |
+ if (!empty($value['is_last'])) |
|
339 |
+ unset($menu_buttons['profile']['sub_buttons'][$key]['is_last']); |
|
340 |
+ } |
|
341 |
+ |
|
342 |
+ // Add the helpdesk profile to the profile menu (either the original or our reconstituted one) |
|
343 |
+ $menu_buttons['profile']['show'] = true; |
|
344 |
+ $menu_buttons['profile']['sub_buttons']['hd_profile'] = array( |
|
345 |
+ 'title' => $txt['shd_helpdesk_profile'], |
|
346 |
+ 'href' => $scripturl . '?action=profile;area=helpdesk', |
|
347 |
+ 'show' => true, |
|
348 |
+ 'is_last' => true, |
|
349 |
+ ); |
|
350 |
+ } |
|
351 |
+ |
|
352 |
+ // Stuff we'll only do if in standalone mode |
|
353 |
+ if (!empty($modSettings['shd_helpdesk_only'])) |
|
354 |
+ { |
|
355 |
+ $menu_buttons['home'] = array( |
|
356 |
+ 'title' => $modSettings['helpdesk_active'] && SMF != 'SSI' ? shd_get_active_tickets() : $txt['shd_helpdesk'], |
|
357 |
+ 'href' => $scripturl . '?action=helpdesk;sa=main', |
|
358 |
+ 'show' => $modSettings['helpdesk_active'] && shd_allowed_to(array('access_helpdesk', 'admin_helpdesk')), |
|
359 |
+ 'sub_buttons' => array( |
|
360 |
+ ), |
|
361 |
+ 'active_button' => false, |
|
362 |
+ ); |
|
363 |
+ unset($menu_buttons['helpdesk']); |
|
364 |
+ |
|
365 |
+ // Disable help, search, calendar, moderation center |
|
366 |
+ unset($menu_buttons['help'], $menu_buttons['search'], $menu_buttons['calendar'], $menu_buttons['moderate']); |
|
367 |
+ |
|
368 |
+ $context['allow_search'] = false; |
|
369 |
+ $context['allow_calendar'] = false; |
|
370 |
+ $context['allow_moderation_center'] = false; |
|
371 |
+ |
|
372 |
+ // Disable PMs |
|
373 |
+ if (!empty($modSettings['shd_disable_pm'])) |
|
374 |
+ { |
|
375 |
+ $context['allow_pm'] = false; |
|
376 |
+ unset($menu_buttons['pm']); |
|
377 |
+ $context['user']['unread_messages'] = 0; // to disable it trying to add to the menu item |
|
378 |
+ } |
|
379 |
+ |
|
380 |
+ // Disable memberlist |
|
381 |
+ if (!empty($modSettings['shd_disable_mlist'])) |
|
382 |
+ { |
|
383 |
+ $context['allow_memberlist'] = false; |
|
384 |
+ unset($menu_buttons['mlist']); |
|
385 |
+ } |
|
386 |
+ } |
|
387 |
+ |
|
388 |
+ // Now engage any hooks. |
|
389 |
+ if (!empty($modSettings['shd_hook_mainmenu'])) |
|
390 |
+ { |
|
391 |
+ $functions = explode(',', $modSettings['shd_hook_mainmenu']); |
|
392 |
+ foreach ($functions as $function) |
|
393 |
+ { |
|
394 |
+ if (is_callable($function)) |
|
395 |
+ $function($menu_buttons); // this should be picked up by reference in the called function or it won't do anything! |
|
396 |
+ } |
|
397 |
+ } |
|
398 |
+ } |
|
399 |
+ |
|
400 |
+]]></add> |
|
401 |
+ </operation> |
|
402 |
+ <operation><!-- Force the log of disabled tags to be reset if we're calling it in such a condition as it is being re-evaluated anyway --> |
|
403 |
+ <search position="before"><![CDATA[ if (!empty($modSettings['disabledBBC'])) |
|
404 |
+ {]]></search> |
|
405 |
+ <add><![CDATA[ |
|
406 |
+ $disabled = array(); // SimpleDesk added! Forces reset of $disabled if we're calling in an unusual way |
|
407 |
+]]></add> |
|
408 |
+ </operation> |
|
409 |
+ </file> |
|
410 |
+ |
|
411 |
+ <file name="$sourcedir/Profile-Modify.php"><!-- Ensure things get uncached if we change groups (which means permissions) --> |
|
412 |
+ <operation> |
|
413 |
+ <search position="after"><![CDATA[// The account page allows the change of your id_group - but not to a protected group!]]></search> |
|
414 |
+ <add><![CDATA[ // Ensure we uncache stuff that might change in the helpdesk |
|
415 |
+ shd_clear_active_tickets($context['id_member']); |
|
416 |
+ |
|
417 |
+]]></add> |
|
418 |
+ </operation> |
|
419 |
+ </file> |
|
420 |
+ |
|
421 |
+ <file name="$sourcedir/ManageSettings.php"><!-- add the helpdesk to Core Features in admin --> |
|
422 |
+ <operation> |
|
423 |
+ <search position="after"><![CDATA[ // k = karma.]]></search> |
|
424 |
+ <add><![CDATA[ // shd = Helpdesk - Simple(Help)Desk |
|
425 |
+ 'shd' => array( |
|
426 |
+ 'url' => 'action=admin;area=helpdesk_info', |
|
427 |
+ ), |
|
428 |
+]]></add> |
|
429 |
+ </operation> |
|
430 |
+ </file> |
|
431 |
+ |
|
432 |
+ <file name="$sourcedir/Display.php"><!-- add topic to ticket menu button --> |
|
433 |
+ <operation> |
|
434 |
+ <search position="after"><![CDATA[ // We don't want to show the poll icon in the topic class here, so pretend it's not one.]]></search> |
|
435 |
+ <add><![CDATA[// Simpledesk: Figure out if they can move this topic to the Helpdesk. |
|
436 |
+ $context['can_move_to_helpdesk'] = empty($modSettings['shd_disable_tickettotopic']) && empty($modSettings['shd_helpdesk_only']) && shd_allowed_to('shd_topic_to_ticket'); |
|
437 |
+ |
|
438 |
+]]></add> |
|
439 |
+ </operation> |
|
440 |
+ </file> |
|
441 |
+ |
|
442 |
+ <file name="$sourcedir/ManagePermissions.php"><!-- disable permissions that don't apply in SA mode --> |
|
443 |
+ <operation> |
|
444 |
+ <search position="after"><![CDATA[ // We need to know what permissions we can't give to guests.]]></search> |
|
445 |
+ <add><![CDATA[ // Are we in SD only mode? If so... hoo boy, we gots some purging to do. |
|
446 |
+ if ($modSettings['helpdesk_active'] && !empty($modSettings['shd_helpdesk_only'])) |
|
447 |
+ { |
|
448 |
+ $perms_disable = array( |
|
449 |
+ 'membergroup' => array( |
|
450 |
+ 'view_stats', |
|
451 |
+ 'who_view', |
|
452 |
+ 'search_posts', |
|
453 |
+ 'karma_edit', |
|
454 |
+ 'calendar_view', |
|
455 |
+ 'calendar_post', |
|
456 |
+ 'calendar_edit', |
|
457 |
+ 'manage_boards', |
|
458 |
+ 'manage_attachments', |
|
459 |
+ 'manage_smileys', |
|
460 |
+ 'edit_news', |
|
461 |
+ 'access_mod_center', |
|
462 |
+ 'moderate_forum', |
|
463 |
+ 'send_mail', |
|
464 |
+ 'issue_warning', |
|
465 |
+ 'shd_ticket_to_topic', // yes, even our own, makes sense to reuse what we have here |
|
466 |
+ 'shd_topic_to_ticket', |
|
467 |
+ ), |
|
468 |
+ 'board' => array( |
|
469 |
+ 'moderate_board', |
|
470 |
+ 'approve_posts', |
|
471 |
+ 'post_new', |
|
472 |
+ 'post_unapproved_topics', |
|
473 |
+ 'post_unapproved_replies', |
|
474 |
+ 'post_reply', |
|
475 |
+ 'merge_any', |
|
476 |
+ 'split_any', |
|
477 |
+ 'send_topic', |
|
478 |
+ 'make_sticky', |
|
479 |
+ 'move', |
|
480 |
+ 'lock', |
|
481 |
+ 'remove', |
|
482 |
+ 'modify_replies', |
|
483 |
+ 'delete_replies', |
|
484 |
+ 'announce_topic', |
|
485 |
+ 'delete', |
|
486 |
+ 'modify', |
|
487 |
+ 'report_any', |
|
488 |
+ 'poll_view', |
|
489 |
+ 'poll_vote', |
|
490 |
+ 'poll_post', |
|
491 |
+ 'poll_add', |
|
492 |
+ 'poll_edit', |
|
493 |
+ 'poll_lock', |
|
494 |
+ 'poll_remove', |
|
495 |
+ 'mark_any_notify', |
|
496 |
+ 'mark_notify', |
|
497 |
+ 'view_attachments', |
|
498 |
+ 'post_unapproved_attachments', |
|
499 |
+ 'post_attachment', |
|
500 |
+ ), |
|
501 |
+ ); |
|
502 |
+ // that's the generic stuff, now for specific options |
|
503 |
+ if (!empty($modSettings['shd_disable_pm'])) |
|
504 |
+ { |
|
505 |
+ $perms_disable['membergroup'][] = 'pm_read'; |
|
506 |
+ $perms_disable['membergroup'][] = 'pm_send'; |
|
507 |
+ } |
|
508 |
+ |
|
509 |
+ foreach ($perms_disable as $group => $perm_list) |
|
510 |
+ foreach ($perm_list as $perm) |
|
511 |
+ if (isset($permissionList[$group][$perm])) |
|
512 |
+ unset($permissionList[$group][$perm]); |
|
513 |
+ } |
|
514 |
+ |
|
515 |
+]]></add> |
|
516 |
+ </operation> |
|
517 |
+ </file> |
|
518 |
+ |
|
519 |
+ <file name="$sourcedir/Help.php"><!-- load the admin help strings --> |
|
520 |
+ <operation> |
|
521 |
+ <search position="replace"><![CDATA[ loadLanguage('Help');]]></search> |
|
522 |
+ <add><![CDATA[ loadLanguage('Help'); |
|
523 |
+ shd_load_language('SimpleDeskAdmin');]]></add> |
|
524 |
+ </operation> |
|
525 |
+ </file> |
|
526 |
+ |
|
527 |
+ <file name="$sourcedir/ManagePosts.php"><!-- at the same time we modify the post settings, make sure we check and update SD's if necessary --> |
|
528 |
+ <operation> |
|
529 |
+ <search position="before"><![CDATA[$smcFunc['db_change_column']('{db_prefix}messages', 'body', array('type' => 'mediumtext'));]]></search> |
|
530 |
+ <add><![CDATA[ |
|
531 |
+ $smcFunc['db_change_column']('{db_prefix}helpdesk_ticket_replies', 'body', array('type' => 'mediumtext'));]]></add> |
|
532 |
+ </operation> |
|
533 |
+ <operation> |
|
534 |
+ <search position="before"><![CDATA[$smcFunc['db_change_column']('{db_prefix}messages', 'body', array('type' => 'text'));]]></search> |
|
535 |
+ <add><![CDATA[ |
|
536 |
+ $smcFunc['db_change_column']('{db_prefix}helpdesk_ticket_replies', 'body', array('type' => 'text'));]]></add> |
|
537 |
+ </operation> |
|
538 |
+ </file> |
|
539 |
+ |
|
540 |
+ <file name="$sourcedir/Who.php"><!-- load the who's online strings... we don't use it much now, but maybe later... --> |
|
541 |
+ <operation> |
|
542 |
+ <search position="before"><![CDATA[loadLanguage('Who');]]></search> |
|
543 |
+ <add><![CDATA[ |
|
544 |
+ shd_load_language('SimpleDeskWho'); |
|
545 |
+ shd_load_plugin_langfiles('who');]]></add> |
|
546 |
+ </operation> |
|
547 |
+ </file> |
|
548 |
+ |
|
549 |
+ <file name="$sourcedir/Errors.php"><!-- if an error occurs in an SD file, log it appropriately with the SD errortype --> |
|
550 |
+ <operation> |
|
551 |
+ <search position="after"><![CDATA[ // Make sure the category that was specified is a valid one]]></search> |
|
552 |
+ <add><![CDATA[ // Is this a SimpleDesk error? |
|
553 |
+ $known_error_types[] = 'simpledesk'; |
|
554 |
+ if (strpos($file, 'SimpleDesk') !== false || strpos($error_message, 'shd_') !== false || strpos($error_message, 'SimpleDesk') !== false) |
|
555 |
+ $error_type = 'simpledesk'; |
|
556 |
+ |
|
557 |
+]]></add> |
|
558 |
+ </operation> |
|
559 |
+ </file> |
|
560 |
+ |
|
561 |
+ <file name="$boarddir/index.php"><!-- set up the relevant action stuff --> |
|
562 |
+ <operation><!-- add/remove action without having to touch the master array - cleaner! --> |
|
563 |
+ <search position="after"><![CDATA[ // Get the function and file to include - if it's not there, do the board index.]]></search> |
|
564 |
+ <add><![CDATA[ // Deal with SimpleDesk. If we're enabling HD only mode, rebuild everything, otherwise just add it to the array. |
|
565 |
+ $actionArray['helpdesk'] = array('sd_source/SimpleDesk.php', 'shd_main'); |
|
566 |
+ // Now engage any hooks. |
|
567 |
+ if (!empty($modSettings['shd_hook_actions'])) |
|
568 |
+ { |
|
569 |
+ $functions = explode(',', $modSettings['shd_hook_actions']); |
|
570 |
+ foreach ($functions as $function) |
|
571 |
+ { |
|
572 |
+ if (is_callable($function)) |
|
573 |
+ $function($actionArray); // this should be picked up by reference in the called function or it won't do anything! |
|
574 |
+ } |
|
575 |
+ } |
|
576 |
+ |
|
577 |
+ if (!empty($modSettings['shd_helpdesk_only']) && $modSettings['helpdesk_active']) |
|
578 |
+ { |
|
579 |
+ // Firstly, remove all the standard actions we neither want nor need. |
|
580 |
+ // Note we did this to prevent breakage of other mods that may be installed, e.g. gallery or portal or something. |
|
581 |
+ $unwanted_actions = array('announce', 'attachapprove', 'buddy', 'calendar', 'clock', 'collapse', 'deletemsg', 'display', 'editpoll', 'editpoll2', |
|
582 |
+ 'emailuser', 'lock', 'lockvoting', 'markasread', 'mergetopics', 'moderate', 'modifycat', 'modifykarma', 'movetopic', 'movetopic2', |
|
583 |
+ 'notify', 'notifyboard', 'post', 'post2', 'printpage', 'quotefast', 'quickmod', 'quickmod2', 'recent', 'reminder', 'removepoll', 'removetopic2', |
|
584 |
+ 'reporttm', 'restoretopic', 'search', 'search2', 'sendtopic', 'smstats', 'splittopics', 'stats', 'sticky', 'theme', 'trackip', 'about:mozilla', 'about:unknown', |
|
585 |
+ 'unread', 'unreadreplies', 'vote', 'viewquery', 'who', '.xml', 'xmlhttp'); |
|
586 |
+ |
|
587 |
+ // that's the generic stuff, now for specific options |
|
588 |
+ if (!empty($modSettings['shd_disable_pm'])) |
|
589 |
+ $unwanted_actions[] = 'pm'; |
|
590 |
+ |
|
591 |
+ if (!empty($modSettings['shd_disable_mlist'])) |
|
592 |
+ $unwanted_actions[] = 'mlist'; |
|
593 |
+ |
|
594 |
+ foreach ($unwanted_actions as $unwanted) |
|
595 |
+ if (isset($actionArray[$unwanted])) |
|
596 |
+ unset($actionArray[$unwanted]); |
|
597 |
+ |
|
598 |
+ // Secondly, rewrite the defaults to point to helpdesk, for unknown actions. I'm doing this rather than munging the main code - easier to unbreak stuff |
|
599 |
+ if (empty($actionArray[$_GET['action']])) |
|
600 |
+ $_GET['action'] = 'helpdesk'; |
|
601 |
+ } |
|
602 |
+]]></add> |
|
603 |
+ </operation> |
|
604 |
+ <operation><!-- add a master override if we haven't declared an action --> |
|
605 |
+ <search position="after"><![CDATA[ // Action and board are both empty... BoardIndex!]]></search> |
|
606 |
+ <add><![CDATA[ // If we're in HD-only mode, let's run with that! |
|
607 |
+ if (!empty($modSettings['shd_helpdesk_only']) && $modSettings['helpdesk_active']) |
|
608 |
+ { |
|
609 |
+ require_once($sourcedir . '/sd_source/SimpleDesk.php'); |
|
610 |
+ return 'shd_main'; |
|
611 |
+ } |
|
612 |
+]]></add> |
|
613 |
+ </operation> |
|
614 |
+ <operation><!-- add a catcher in case it's a function we don't have --> |
|
615 |
+ <search position="after"><![CDATA[ // Fall through to the board index then... |
|
616 |
+ require_once($sourcedir . '/BoardIndex.php'); |
|
617 |
+ return 'BoardIndex';]]></search> |
|
618 |
+ <add><![CDATA[ // If we're in HD-only mode, we can't let them go anywhere useless |
|
619 |
+ if (!empty($modSettings['shd_helpdesk_only']) && $modSettings['helpdesk_active']) |
|
620 |
+ { |
|
621 |
+ require_once($sourcedir . '/sd_source/SimpleDesk.php'); |
|
622 |
+ return 'shd_main'; |
|
623 |
+ } |
|
624 |
+ |
|
625 |
+]]></add> |
|
626 |
+ </operation> |
|
627 |
+ <operation><!-- bootstrap the SimpleDesk functions a little --> |
|
628 |
+ <search position="before"><![CDATA[require_once($sourcedir . '/Security.php');]]></search> |
|
629 |
+ <add><![CDATA[ |
|
630 |
+require_once($sourcedir . '/sd_source/Subs-SimpleDesk.php');]]></add> |
|
631 |
+ </operation> |
|
632 |
+ </file> |
|
633 |
+ |
|
634 |
+ <file name="$boarddir/SSI.php"><!-- Load SimpleDesk SSI functions --> |
|
635 |
+ <operation> |
|
636 |
+ <search position="before"><![CDATA[require_once($sourcedir . '/Security.php');]]></search> |
|
637 |
+ <add><![CDATA[ |
|
638 |
+require_once($sourcedir . '/sd_source/Subs-SimpleDesk.php'); |
|
639 |
+require_once($sourcedir . '/sd_source/SimpleDesk-SSI.php');]]></add> |
|
640 |
+ </operation> |
|
641 |
+ </file> |
|
642 |
+ |
|
643 |
+ <file name="$sourcedir/QueryString.php"><!-- Remove those pesky unread/unreadreplies links in SA mode --> |
|
644 |
+ <operation> |
|
645 |
+ <search position="after"><![CDATA[ // If $scripturl is set to nothing]]></search> |
|
646 |
+ <add><![CDATA[ // Some last minute changes by SimpleDesk |
|
647 |
+ global $smcFunc; |
|
648 |
+ if (!empty($modSettings['helpdesk_active'])) |
|
649 |
+ { |
|
650 |
+ $shd_replacements = array(); |
|
651 |
+ $shd_preg_replacements = array(); |
|
652 |
+ |
|
653 |
+ // If we're in helpdesk standalone mode, purge unread type links |
|
654 |
+ if (!empty($modSettings['shd_helpdesk_only'])) |
|
655 |
+ { |
|
656 |
+ $shd_preg_replacements += array( |
|
657 |
+ '~<a(.+)action=unread(.+)</a>~iuU' => '', |
|
658 |
+ '~<form([^<]+)action=search2(.+)</form>~iuUs' => '', |
|
659 |
+ ); |
|
660 |
+ } |
|
661 |
+ |
|
662 |
+ if (!empty($shd_replacements)) // no sense doing preg when regular will do |
|
663 |
+ $buffer = str_replace(array_keys($shd_replacements), array_values($shd_replacements), $buffer); |
|
664 |
+ if (!empty($shd_preg_replacements)) |
|
665 |
+ $buffer = preg_replace(array_keys($shd_preg_replacements), array_values($shd_preg_replacements), $buffer); |
|
666 |
+ } |
|
667 |
+ |
|
668 |
+ if (!empty($modSettings['shd_hook_buffer'])) |
|
669 |
+ { |
|
670 |
+ $functions = explode(',', $modSettings['shd_hook_buffer']); |
|
671 |
+ foreach ($functions as $function) |
|
672 |
+ { |
|
673 |
+ if (is_callable($function)) |
|
674 |
+ $function($buffer); // BY REFERENCE! |
|
675 |
+ } |
|
676 |
+ } |
|
677 |
+ |
|
678 |
+]]></add> |
|
679 |
+ </operation> |
|
680 |
+ </file> |
|
681 |
+ |
|
682 |
+ <!-- theme edits boohoo --> |
|
683 |
+ <file name="$themedir/Display.template.php"><!-- add topic to ticket menu button --> |
|
684 |
+ <operation> |
|
685 |
+ <search position="after"><![CDATA[// Show the page index... "Pages: [1]".]]></search> |
|
686 |
+ <add><![CDATA[ // SimpleDesk: Add topic -> ticket button |
|
687 |
+ $normal_buttons = array_merge($normal_buttons,array('topictoticket' => array('test' => 'can_move_to_helpdesk', 'text' => 'shd_move_topic_to_ticket', 'lang' => true, 'url' => $scripturl . '?action=helpdesk;sa=topictoticket;topic='.$context['current_topic'].';' . $context['session_var'] . '=' . $context['session_id']))); |
|
688 |
+]]></add> |
|
689 |
+ </operation> |
|
690 |
+ </file> |
|
691 |
+ |
|
692 |
+</modification> |
|
0 | 693 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,375 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk.english.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+// Version: 1.0 Felidae; SimpleDesk main language file |
|
20 |
+ |
|
21 |
+// Important! Before editing these language files please read the text at the top of index.english.php. |
|
22 |
+ |
|
23 |
+/** |
|
24 |
+ * This file contains all of the principle language strings used by SimpleDesk and are loaded on every page. |
|
25 |
+ * |
|
26 |
+ * @package language |
|
27 |
+ * @todo Document the text groups in this file. |
|
28 |
+ * @since 1.0 |
|
29 |
+ */ |
|
30 |
+ |
|
31 |
+$txt['shd_helpdesk'] = 'Helpdesk'; |
|
32 |
+$txt['shd_helpdesk_maintenance'] = 'The helpdesk is currently in <strong>maintenance mode</strong>. Only forum and helpdesk administrators can see this.'; |
|
33 |
+ |
|
34 |
+//! @name Admininstration panel strings |
|
35 |
+//@{ |
|
36 |
+$txt['shd_admin_welcome'] = 'Welcome to the main helpdesk administration center!'; |
|
37 |
+$txt['shd_admin_title'] = 'Helpdesk Administration Center'; |
|
38 |
+$txt['shd_staff_list'] = 'Helpdesk staff'; |
|
39 |
+$txt['shd_update_available'] = 'New version available!'; |
|
40 |
+$txt['shd_update_message'] = 'A new version of SimpleDesk has been released. We recommened you to <a href="#" id="update-link">update to the latest version</a> in order to stay secure and enjoy all features our modification have to offer.' . "\n\n" . '<span style="display: none;" id="information-link-span"><br />For more information on what is new in this release, please visit <a href="#" id="information-link" target="_blank">our website</a>.</span><br />' . "\n\n" . '<strong>The SimpleDesk Team</strong>'; |
|
41 |
+//@} |
|
42 |
+ |
|
43 |
+//! @name Urgency levels, ties to helpdesk_tickets.urgency |
|
44 |
+//@{ |
|
45 |
+$txt['shd_urgency_0'] = 'Low'; |
|
46 |
+$txt['shd_urgency_1'] = 'Medium'; |
|
47 |
+$txt['shd_urgency_2'] = 'High'; |
|
48 |
+$txt['shd_urgency_3'] = 'Very High'; |
|
49 |
+$txt['shd_urgency_4'] = 'Severe'; |
|
50 |
+$txt['shd_urgency_5'] = 'Critical'; |
|
51 |
+$txt['shd_urgency_increase'] = 'Increase'; |
|
52 |
+$txt['shd_urgency_decrease'] = 'Decrease'; |
|
53 |
+//@} |
|
54 |
+ |
|
55 |
+//! @name Status, ties to helpdesk_tickets.status |
|
56 |
+//@{ |
|
57 |
+$txt['shd_status_0'] = 'New'; |
|
58 |
+$txt['shd_status_1'] = 'Pending Staff Comment'; |
|
59 |
+$txt['shd_status_2'] = 'Pending User Comment'; |
|
60 |
+$txt['shd_status_3'] = 'Resolved/Closed'; |
|
61 |
+$txt['shd_status_4'] = 'Referred to Supervisor'; |
|
62 |
+$txt['shd_status_5'] = 'Escalated - Urgent'; |
|
63 |
+$txt['shd_status_6'] = 'Deleted'; |
|
64 |
+//@} |
|
65 |
+ |
|
66 |
+//! @name Headings, for the helpdesk listing pages |
|
67 |
+//@{ |
|
68 |
+$txt['shd_status_0_heading'] = 'New Tickets'; |
|
69 |
+$txt['shd_status_1_heading'] = 'Tickets Awaiting Staff Response'; |
|
70 |
+$txt['shd_status_2_heading'] = 'Tickets Awaiting User Response'; |
|
71 |
+$txt['shd_status_3_heading'] = 'Closed Tickets'; |
|
72 |
+$txt['shd_status_4_heading'] = 'Tickets Referred to Supervisor'; |
|
73 |
+$txt['shd_status_5_heading'] = 'Urgent Tickets'; |
|
74 |
+$txt['shd_status_6_heading'] = 'Recycled Tickets'; |
|
75 |
+$txt['shd_status_assigned_heading'] = 'Assigned to Me'; |
|
76 |
+$txt['shd_status_withdeleted_heading'] = 'Tickets with Deleted Replies'; |
|
77 |
+//@} |
|
78 |
+ |
|
79 |
+$txt['shd_tickets_open'] = 'Open Tickets'; |
|
80 |
+$txt['shd_tickets_closed'] = 'Closed Tickets'; |
|
81 |
+$txt['shd_tickets_recycled'] = 'Recycled Tickets'; |
|
82 |
+ |
|
83 |
+$txt['shd_assigned'] = 'Assigned'; |
|
84 |
+$txt['shd_unassigned'] = 'Unassigned'; |
|
85 |
+ |
|
86 |
+$txt['shd_read_ticket'] = 'Read Ticket'; |
|
87 |
+$txt['shd_unread_ticket'] = 'Unread Ticket'; |
|
88 |
+ |
|
89 |
+$txt['shd_owned'] = 'Owned Ticket'; // aka Assigned to Me |
|
90 |
+ |
|
91 |
+$txt['shd_count_ticket_1'] = 'ticket'; |
|
92 |
+$txt['shd_count_tickets'] = 'tickets'; |
|
93 |
+ |
|
94 |
+// Errors |
|
95 |
+$txt['cannot_access_helpdesk'] = 'You are not permitted to access the helpdesk.'; |
|
96 |
+$txt['shd_no_ticket'] = 'The ticket you have requested does not appear to exist.'; |
|
97 |
+$txt['shd_no_reply'] = 'The ticket reply you have request does not appear to exist, or is not part of this ticket.'; |
|
98 |
+$txt['shd_no_topic'] = 'The topic you have requested does not appear to exist.'; |
|
99 |
+$txt['shd_ticket_no_perms'] = 'You do not have permission to view that ticket.'; |
|
100 |
+$txt['shd_error_no_tickets'] = 'No tickets were found.'; |
|
101 |
+$txt['shd_inactive'] = 'The helpdesk is currently deactivated.'; |
|
102 |
+$txt['shd_cannot_assign'] = 'You are not permitted to assign tickets.'; |
|
103 |
+$txt['shd_cannot_assign_other'] = 'This ticket is already assigned to another user. You cannot reassign it to yourself - please contact the administrator.'; |
|
104 |
+$txt['shd_no_staff_assign'] = 'There are no staff configured; it is not possible to assign a ticket. Please contact your administrator.'; |
|
105 |
+$txt['shd_assigned_not_permitted'] = 'The user you have requested to assign this ticket to does not have sufficient permissions to see it.'; |
|
106 |
+$txt['shd_cannot_resolve'] = 'You do not have permission to mark this ticket as resolved.'; |
|
107 |
+$txt['error_shd_cannot_resolve_children'] = 'This ticket cannot currently be closed; this ticket is the parent of one or more tickets that are currently open.'; |
|
108 |
+$txt['error_shd_proxy_unknown'] = 'The user this ticket is posted on behalf of does not exist.'; |
|
109 |
+$txt['shd_cannot_change_privacy'] = 'You do not have permission to alter the privacy on this ticket.'; |
|
110 |
+$txt['shd_cannot_change_urgency'] = 'You do not have permission to alter the urgency on this ticket.'; |
|
111 |
+$txt['shd_ajax_problem'] = 'There was a problem attempting to load the page. Would you like to try again?'; |
|
112 |
+$txt['shd_cannot_move_ticket'] = 'You do not have permission to move this ticket to a topic.'; |
|
113 |
+$txt['shd_cannot_move_topic'] = 'You do not have permission to move this topic to a ticket.'; |
|
114 |
+$txt['shd_moveticket_noboards'] = 'There are no boards to move this ticket to!'; |
|
115 |
+$txt['shd_move_no_pm'] = 'You must enter a reason for moving the ticket to send to the ticket owner, or uncheck the option to \'send a PM to the ticket owner\'.'; |
|
116 |
+$txt['shd_move_no_pm_topic'] = 'You must enter a reason for moving the topic to send to the topic starter, or uncheck the option to \'send a PM to the topic starter\'.'; |
|
117 |
+$txt['shd_move_topic_not_created'] = 'Failed to move the ticket to the board. Please try again.'; |
|
118 |
+$txt['shd_move_ticket_not_created'] = 'Failed to move the topic to the helpdesk. Please try again.'; |
|
119 |
+$txt['shd_no_replies'] = 'This ticket does not have any replies yet.'; |
|
120 |
+$txt['cannot_shd_new_ticket'] = 'You do not have permission to create a new ticket.'; |
|
121 |
+$txt['cannot_shd_edit_ticket'] = 'You do not have permission to edit this ticket.'; |
|
122 |
+$txt['shd_cannot_reply_any'] = 'You do not have permission to reply to any tickets.'; |
|
123 |
+$txt['shd_cannot_reply_any_but_own'] = 'You do not have permission to reply to any tickets other than your own.'; |
|
124 |
+$txt['shd_cannot_edit_reply_any'] = 'You do not have permission to edit any replies.'; |
|
125 |
+$txt['shd_cannot_edit_reply_any_but_own'] = 'You do not have permission to edit replies to any tickets other than your own replies.'; |
|
126 |
+$txt['shd_cannot_edit_closed'] = 'You cannot edit resolved tickets; you need to mark it unresolved first.'; |
|
127 |
+$txt['shd_cannot_edit_deleted'] = 'You cannot edit tickets in the recycle bin. They will need to be restored first.'; |
|
128 |
+$txt['shd_cannot_reply_closed'] = 'You cannot reply to resolved tickets; you need to mark them unresolved first.'; |
|
129 |
+$txt['shd_cannot_reply_deleted'] = 'You cannot reply to tickets in the recycle bin. They will need to be restored first.'; |
|
130 |
+$txt['shd_cannot_delete_ticket'] = 'You are not permitted to delete this ticket.'; |
|
131 |
+$txt['shd_cannot_delete_reply'] = 'You are not permitted to delete that reply.'; |
|
132 |
+$txt['shd_cannot_restore_ticket'] = 'You are not permitted to restore this ticket from the recycle bin.'; |
|
133 |
+$txt['shd_cannot_restore_reply'] = 'You are not permitted to restore that reply from the recycle bin.'; |
|
134 |
+$txt['shd_cannot_view_resolved'] = 'You are not permitted to access resolved tickets.'; |
|
135 |
+$txt['cannot_shd_access_recyclebin'] = 'You cannot access the recycle bin.'; |
|
136 |
+$txt['shd_cannot_move_ticket_with_deleted'] = 'You cannot move this ticket to the forum; there are one or more deleted replies, which your current permissions do not permit access to.'; |
|
137 |
+$txt['shd_cannot_attach_ext'] = 'The type of file you have tried to attach ({ext}) is not allowed here. The allowed types of file are: {attach_exts}'; |
|
138 |
+$txt['shd_cannot_merge'] = 'You do not have permission to merge this ticket.'; |
|
139 |
+$txt['shd_no_tickets_to_merge'] = 'There are no currently open tickets started by the same user; you cannot merge this ticket with any others at this time.'; |
|
140 |
+$txt['cannot_shd_split_ticket_own'] = 'You are not permitted to split your own tickets.'; |
|
141 |
+$txt['cannot_shd_split_ticket_any'] = 'You are not permitted to split any tickets.'; |
|
142 |
+$txt['shd_split_no_title'] = 'You must specify a title for the newly split ticket.'; |
|
143 |
+$txt['shd_split_invalid_type'] = 'That operation on splitting a ticket is not supported.'; |
|
144 |
+$txt['shd_ticket_unavailable'] = 'This ticket is currently not available for modification.'; |
|
145 |
+$txt['shd_invalid_relation'] = 'You must provide a valid type of relationship for these tickets.'; |
|
146 |
+$txt['shd_no_relation_delete'] = 'You cannot delete a relationship that does not exist.'; |
|
147 |
+$txt['shd_cannot_relate_self'] = 'You cannot make a ticket relate to itself.'; |
|
148 |
+$txt['shd_split_no_pm'] = 'You must enter a reason for splitting the ticket to send to the ticket owner, or uncheck the option to \'send a PM to the ticket owner\'.'; |
|
149 |
+ |
|
150 |
+// The main Helpdesk. |
|
151 |
+$txt['shd_home'] = 'Helpdesk'; // separate string in case someone wants to change it independently of the main menu |
|
152 |
+$txt['shd_new_ticket'] = 'Post New Ticket'; |
|
153 |
+$txt['shd_new_ticket_proxy'] = 'Post Proxy Ticket'; |
|
154 |
+$txt['shd_helpdesk_profile'] = 'Helpdesk Profile'; |
|
155 |
+$txt['shd_welcome'] = 'Welcome, %s!'; |
|
156 |
+$txt['shd_go'] = 'Go!'; |
|
157 |
+$txt['shd_go_to_ticket'] = 'Go to ticket'; |
|
158 |
+ |
|
159 |
+$txt['shd_user_greeting'] = 'Here you can file new tickets for the site staff to action, and check on current tickets already underway.'; |
|
160 |
+$txt['shd_staff_greeting'] = 'Here are all the tickets that require attention.'; |
|
161 |
+$txt['shd_shd_greeting'] = 'This is the Helpdesk. Here you waste your time to help newbies. Enjoy! ;D'; |
|
162 |
+$txt['shd_closed_user_greeting'] = 'These are all the closed/resolved tickets you have posted to the helpdesk.'; |
|
163 |
+$txt['shd_closed_staff_greeting'] = 'These are all closed/resolved tickets submitted to the helpdesk.'; |
|
164 |
+ |
|
165 |
+$txt['shd_ticket_posted_header'] = 'Your ticket has been created!'; |
|
166 |
+$txt['shd_ticket_posted_body'] = 'Thank you for posting your ticket, {membername}!' . "\n\n" . 'The helpdesk staff will review it and get back to you as soon as possible.' . "\n\n" . 'In the meantime, you can view your ticket, "[url={ticketurl}]{subject}[/url]" at the following URL:' . "\n" . '[iurl={ticketurl}]{ticketurl}[/iurl]' . "\n\n" .'[iurl={newticketlink}]Open another ticket[/iurl] | [iurl={helpdesklink}]Back to the main helpdesk[/iurl] | [iurl={forumlink}]Back to the forum[/iurl]' . "\n\n" . 'Regards,' . "\n" . 'The {forum_name} Team.'; |
|
167 |
+ |
|
168 |
+// The main ticket view. |
|
169 |
+$txt['shd_ticket_details'] = 'Ticket details'; |
|
170 |
+$txt['shd_ticket_updated'] = 'Updated'; |
|
171 |
+$txt['shd_ticket_id'] = 'Id'; |
|
172 |
+$txt['shd_ticket_name'] = 'Name'; |
|
173 |
+$txt['shd_ticket_user'] = 'User'; |
|
174 |
+$txt['shd_ticket_date'] = 'Posted'; |
|
175 |
+$txt['shd_ticket_urgency'] = 'Urgency'; |
|
176 |
+$txt['shd_ticket_assigned'] = 'Assigned'; |
|
177 |
+$txt['shd_ticket_assignedto'] = 'Assigned to'; |
|
178 |
+$txt['shd_ticket_started_by'] = 'Started by'; |
|
179 |
+$txt['shd_ticket_updated_by'] = 'Updated by'; |
|
180 |
+$txt['shd_ticket_status'] = 'Status'; |
|
181 |
+$txt['shd_ticket_num_replies'] = 'Replies'; |
|
182 |
+$txt['shd_ticket_replies'] = 'Replies'; |
|
183 |
+$txt['shd_ticket_staff'] = 'Staff member'; |
|
184 |
+$txt['shd_ticket_attachments'] = 'Attachments'; |
|
185 |
+$txt['shd_ticket_reply_number'] = 'Reply <strong>#%s</strong>'; // 'Reply #34' |
|
186 |
+$txt['shd_ticket'] = 'Ticket'; |
|
187 |
+$txt['shd_reply_written'] = 'Reply written %s'; // 'Reply written Today at 04:12:29 pm', 'Reply written January 5 2009 04:12:29 pm' |
|
188 |
+$txt['shd_never'] = 'Never'; |
|
189 |
+$txt['shd_linktree_tickets'] = 'Tickets'; |
|
190 |
+$txt['shd_ticket_privacy'] = 'Privacy'; |
|
191 |
+$txt['shd_ticket_notprivate'] = 'Not Private'; |
|
192 |
+$txt['shd_ticket_private'] = 'Private'; |
|
193 |
+$txt['shd_ticket_change'] = 'Change'; |
|
194 |
+$txt['shd_ticket_ip'] = 'IP address'; |
|
195 |
+$txt['shd_back_to_hd'] = 'Back to the helpdesk'; |
|
196 |
+ |
|
197 |
+$txt['shd_ticket_has_been_deleted'] = 'This ticket is currently in the recycle bin and cannot be altered without being returned to the helpdesk.'; |
|
198 |
+$txt['shd_ticket_replies_deleted'] = 'This ticket has had replies deleted from it previously.'; |
|
199 |
+$txt['shd_ticket_replies_deleted_view'] = 'These are displayed with a colored background. <a href="%1$s">View the ticket without deletions</a>.'; |
|
200 |
+$txt['shd_ticket_replies_deleted_link'] = 'Please <a href="%1$s">click here</a> to view them.'; |
|
201 |
+ |
|
202 |
+$txt['shd_ticket_notnew'] = 'You have already seen this'; |
|
203 |
+$txt['shd_ticket_new'] = 'New!'; |
|
204 |
+ |
|
205 |
+$txt['shd_linktree_move_ticket'] = 'Move ticket'; |
|
206 |
+$txt['shd_linktree_move_topic'] = 'Move topic to helpdesk'; |
|
207 |
+ |
|
208 |
+$txt['shd_cancel_ticket'] = 'Cancel and return to the ticket'; |
|
209 |
+$txt['shd_cancel_home'] = 'Cancel and return to the helpdesk home'; |
|
210 |
+$txt['shd_cancel_topic'] = 'Cancel and return to the topic'; |
|
211 |
+ |
|
212 |
+// Actions |
|
213 |
+$txt['shd_ticket_reply'] = 'Reply to ticket'; |
|
214 |
+$txt['shd_ticket_quote'] = 'Reply with quote'; |
|
215 |
+$txt['shd_go_advanced'] = 'Go advanced!'; |
|
216 |
+$txt['shd_ticket_edit_reply'] = 'Edit reply'; |
|
217 |
+$txt['shd_ticket_quote_short'] = 'Quote'; |
|
218 |
+$txt['shd_ticket_markunread'] = 'Mark as unread'; |
|
219 |
+$txt['shd_ticket_reply_short'] = 'Reply'; |
|
220 |
+$txt['shd_ticket_edit'] = 'Edit'; |
|
221 |
+$txt['shd_ticket_resolved'] = 'Mark resolved'; |
|
222 |
+$txt['shd_ticket_unresolved'] = 'Mark unresolved'; |
|
223 |
+$txt['shd_ticket_assign'] = 'Assign'; |
|
224 |
+$txt['shd_ticket_assign_self'] = 'Assign to me'; |
|
225 |
+$txt['shd_ticket_reassign'] = 'Re-Assign'; |
|
226 |
+$txt['shd_ticket_unassign'] = 'Un-Assign'; |
|
227 |
+$txt['shd_ticket_delete'] = 'Delete'; |
|
228 |
+$txt['shd_delete_confirm'] = 'Are you sure you want to delete this ticket? If deleted, this ticket will be moved to recycling bin.'; |
|
229 |
+$txt['shd_delete_reply_confirm'] = 'Are you sure you want to delete this reply? If deleted, this reply will be moved to the recycling bin.'; |
|
230 |
+$txt['shd_ticket_restore'] = 'Restore'; |
|
231 |
+$txt['shd_delete_permanently'] = 'Delete permanently'; |
|
232 |
+$txt['shd_delete_permanently_confirm'] = 'Are you sure you want to permanently delete this ticket? This CAN NOT be undone!'; |
|
233 |
+$txt['shd_ticket_move_to_topic'] = 'Move to topic'; |
|
234 |
+$txt['shd_actions'] = 'Actions'; |
|
235 |
+$txt['shd_back_to_ticket'] = 'Return to this ticket after posting'; |
|
236 |
+$txt['shd_disable_smileys_post'] = 'Turn off smileys in this post'; |
|
237 |
+$txt['shd_resolve_this_ticket'] = 'Mark this ticket as resolved'; |
|
238 |
+ |
|
239 |
+$txt['shd_ticket_assign_ticket'] = 'Assign Ticket'; |
|
240 |
+$txt['shd_ticket_assign_to'] = 'Assign ticket to'; |
|
241 |
+ |
|
242 |
+// Ticket to topic and back |
|
243 |
+$txt['shd_new_subject'] = 'New subject'; |
|
244 |
+$txt['shd_move_ticket_to_topic'] = 'Move ticket to topic'; |
|
245 |
+$txt['shd_move_ticket'] = 'Move ticket'; |
|
246 |
+$txt['shd_ticket_board'] = 'Board'; |
|
247 |
+$txt['shd_change_ticket_subject'] = 'Change the ticket subject'; |
|
248 |
+$txt['shd_move_send_pm'] = 'Send a PM to the ticket owner'; |
|
249 |
+$txt['shd_move_why'] = 'Please enter a brief description as to why this ticket is being moved to a forum topic. '; |
|
250 |
+$txt['shd_ticket_moved_subject'] = 'Your ticket has been moved.'; |
|
251 |
+$txt['shd_move_default'] = 'Hello {user},' . "\n\n" . 'Your ticket, {subject}, has been moved from the helpdesk to a topic in the forum.' . "\n" . 'You can find your ticket in the board {board} or via this link:' . "\n\n" . '{link}' . "\n\n" . 'Thanks'; |
|
252 |
+ |
|
253 |
+$txt['shd_move_topic_to_ticket'] = 'Move topic to helpdesk'; |
|
254 |
+$txt['shd_move_topic'] = 'Move topic'; |
|
255 |
+$txt['shd_change_topic_subject'] = 'Change the topic subject'; |
|
256 |
+$txt['shd_move_send_pm_topic'] = 'Send a PM to the topic starter'; |
|
257 |
+$txt['shd_move_why_topic'] = 'Please enter a brief description as to why this topic is being moved to the helpdesk. '; |
|
258 |
+$txt['shd_ticket_moved_subject_topic'] = 'Your topic has been moved.'; |
|
259 |
+$txt['shd_move_default_topic'] = 'Hello {user},' . "\n\n" . 'Your topic, {subject}, has been moved from the forum to the Helpdesk section.' . "\n" . 'You can find your topic via this link:' . "\n\n" . '{link}' . "\n\n" . 'Thanks'; |
|
260 |
+ |
|
261 |
+$txt['shd_ticket_move_deleted'] = 'This ticket has replies that are currently in the recycle bin. What do you wish to do?'; |
|
262 |
+$txt['shd_ticket_move_deleted_abort'] = 'Abort, take me to the recycle bin'; |
|
263 |
+$txt['shd_ticket_move_deleted_delete'] = 'Continue, abandon the deleted replies (do not move them into the new topic)'; |
|
264 |
+$txt['shd_ticket_move_deleted_undelete'] = 'Continue, undelete the replies (move them into the new topic)'; |
|
265 |
+ |
|
266 |
+// Merge ticket |
|
267 |
+$txt['shd_merge_ticket'] = 'Merge ticket'; |
|
268 |
+$txt['shd_ticket_to_merge'] = 'Ticket to merge'; |
|
269 |
+$txt['shd_ticket_merge_tickets'] = 'Merge Tickets'; |
|
270 |
+$txt['shd_merge_send_pm'] = 'Send a PM to the ticket starter'; |
|
271 |
+$txt['shd_merge_why'] = 'Please enter a brief description as to why this ticket has been merged with another.'; |
|
272 |
+$txt['shd_merge_default_msg'] = 'Hello {user},' . "\n\n" . 'Your tickets, {source} and {destination}, have been merged together to form a single ticket.' . "\n\n" . 'You can find your ticket here:' . "\n" . '{link}' . "\n\n" . 'Thanks'; |
|
273 |
+ |
|
274 |
+// Split ticket |
|
275 |
+$txt['shd_ticket_split_ticket'] = 'Split'; |
|
276 |
+$txt['shd_split_ticket'] = 'Split Ticket'; |
|
277 |
+$txt['shd_split_new_subject'] = 'Subject for newly split ticket'; |
|
278 |
+$txt['shd_split_type'] = 'What replies should make up the new ticket?'; |
|
279 |
+$txt['shd_split_only_this'] = 'The new ticket should only have this reply'; |
|
280 |
+$txt['shd_split_after_this'] = 'The new ticket should contain all replies from this message forward'; |
|
281 |
+$txt['shd_split_done'] = 'The ticket has been split into two tickets.'; |
|
282 |
+$txt['shd_split_origin_ticket'] = 'Go back to the original ticket'; |
|
283 |
+$txt['shd_split_new_ticket'] = 'Go to the new ticket'; |
|
284 |
+$txt['shd_split_send_pm'] = 'Send a PM to the ticket starter'; |
|
285 |
+$txt['shd_split_why'] = 'Please enter a brief description as to why this ticket has been split into two.'; |
|
286 |
+$txt['shd_split_why_note'] = 'It is possible the ticket starter will not be able to see the split ticket, depending on how the split is done.'; |
|
287 |
+$txt['shd_ticket_split_subject'] = 'Your ticket has been split.'; |
|
288 |
+$txt['shd_split_default_msg'] = 'Hello {user},' . "\n\n" . 'Your ticket, {source}, has been split into another ticket.' . "\n" . 'You can find your original ticket here:' . "\n\n" . '{link}' . "\n\n" . 'The new ticket is:' . "\n" . '{splitlink}' . "\n\n" . 'Thanks'; |
|
289 |
+ |
|
290 |
+// Recycling |
|
291 |
+$txt['shd_recycle_bin'] = 'Recycle Bin'; |
|
292 |
+$txt['shd_recycle_greeting'] = 'This is the recycling bin. All deleted tickets go here, but staff members with special permissions can remove tickets permanently from here.'; |
|
293 |
+ |
|
294 |
+// Posting |
|
295 |
+$txt['shd_create_ticket'] = 'Create ticket'; |
|
296 |
+$txt['shd_edit_ticket'] = 'Edit ticket'; |
|
297 |
+$txt['shd_edit_ticket_linktree'] = 'Edit ticket (%s)'; |
|
298 |
+$txt['shd_ticket_subject'] = 'Ticket subject'; |
|
299 |
+$txt['shd_ticket_proxy'] = 'Post on behalf of'; |
|
300 |
+$txt['shd_ticket_post_error'] = 'The following issue, or issues, occurred while trying to post this ticket'; |
|
301 |
+$txt['shd_reply_ticket'] = 'Reply to ticket'; |
|
302 |
+$txt['shd_reply_ticket_linktree'] = 'Reply to ticket (%s)'; |
|
303 |
+$txt['shd_edit_reply_linktree'] = 'Edit reply (%s)'; |
|
304 |
+$txt['shd_previewing_ticket'] = 'Previewing ticket'; |
|
305 |
+$txt['shd_previewing_reply'] = 'Previewing reply to'; |
|
306 |
+ |
|
307 |
+// Profile / trackip |
|
308 |
+$txt['shd_replies_from_ip'] = 'Helpdesk replies posted from IP (range)'; |
|
309 |
+$txt['shd_no_replies_from_ip'] = 'No helpdesk replies from the specified IP (range) found'; |
|
310 |
+$txt['shd_replies_from_ip_desc'] = 'Below is a list of all messages posted to the helpdesk from this IP (range).'; |
|
311 |
+$txt['shd_is_ticket_opener'] = ' (ticket starter)'; |
|
312 |
+ |
|
313 |
+ |
|
314 |
+// Attachment types |
|
315 |
+// Archive formats |
|
316 |
+$txt['shd_attachtype_bz2'] = 'BZip2 archive'; |
|
317 |
+$txt['shd_attachtype_gz'] = 'GZip archive'; |
|
318 |
+$txt['shd_attachtype_rar'] = 'Rar/WinRAR archive'; |
|
319 |
+$txt['shd_attachtype_zip'] = 'Zip archive'; |
|
320 |
+// Media: Audio formats |
|
321 |
+$txt['shd_attachtype_mp3'] = 'MP3 (MPEG Layer III) audio file'; |
|
322 |
+// Media: Image formats |
|
323 |
+$txt['shd_attachtype_bmp'] = 'Windows Bitmap image'; |
|
324 |
+$txt['shd_attachtype_gif'] = 'Graphics Interchange Format (GIF) image'; |
|
325 |
+$txt['shd_attachtype_jpeg'] = 'Joint Photographic Experts Group (JPEG) image'; |
|
326 |
+$txt['shd_attachtype_jpg'] = 'Joint Photographic Experts Group (JPEG) image'; |
|
327 |
+$txt['shd_attachtype_png'] = 'Portable Network Graphic (PNG) image'; |
|
328 |
+$txt['shd_attachtype_svg'] = 'Scalable Vector Graphic (SVG) image'; |
|
329 |
+// Media: Video formats |
|
330 |
+$txt['shd_attachtype_wmv'] = 'Windows Media Video movie'; |
|
331 |
+// Office formats |
|
332 |
+$txt['shd_attachtype_doc'] = 'Microsoft Word document'; |
|
333 |
+$txt['shd_attachtype_mdb'] = 'Microsoft Access database'; |
|
334 |
+$txt['shd_attachtype_ppt'] = 'Microsoft Powerpoint presentation'; |
|
335 |
+$txt['shd_attachtype_xls'] = 'Microsoft Excel spreadsheet'; |
|
336 |
+// Programming languages |
|
337 |
+$txt['shd_attachtype_cpp'] = 'C++ source file'; |
|
338 |
+$txt['shd_attachtype_php'] = 'PHP script'; |
|
339 |
+$txt['shd_attachtype_py'] = 'Python source file'; |
|
340 |
+$txt['shd_attachtype_rb'] = 'Ruby source file'; |
|
341 |
+$txt['shd_attachtype_sql'] = 'SQL script'; |
|
342 |
+// Proprietory formats |
|
343 |
+$txt['shd_attachtype_kml'] = 'Google Earth (KML)'; |
|
344 |
+$txt['shd_attachtype_kmz'] = 'Google Earth (KML archive)'; |
|
345 |
+$txt['shd_attachtype_pdf'] = 'Adobe Acrobat Portable Document File'; |
|
346 |
+$txt['shd_attachtype_psd'] = 'Adobe Photoshop document'; |
|
347 |
+$txt['shd_attachtype_swf'] = 'Adobe Flash file'; |
|
348 |
+// Miscellaneous |
|
349 |
+$txt['shd_attachtype_exe'] = 'Executable file (Windows)'; |
|
350 |
+$txt['shd_attachtype_htm'] = 'Hypertext Markup Document (HTML)'; |
|
351 |
+$txt['shd_attachtype_html'] = 'Hypertext Markup Document (HTML)'; |
|
352 |
+$txt['shd_attachtype_rtf'] = 'Rich Text Format (RTF)'; |
|
353 |
+$txt['shd_attachtype_txt'] = 'Plain text'; |
|
354 |
+ |
|
355 |
+// Ticket logs. |
|
356 |
+$txt['shd_ticket_log'] = 'Ticket action log'; |
|
357 |
+$txt['shd_ticket_log_count_one'] = '1 entry'; |
|
358 |
+$txt['shd_ticket_log_count_more'] = '%s entries'; |
|
359 |
+$txt['shd_ticket_log_none'] = 'This ticket has not had any changes.'; |
|
360 |
+$txt['shd_ticket_log_member'] = 'Member'; |
|
361 |
+$txt['shd_ticket_log_ip'] = 'Member IP:'; |
|
362 |
+$txt['shd_ticket_log_date'] = 'Date'; |
|
363 |
+$txt['shd_ticket_log_action'] = 'Action'; |
|
364 |
+$txt['shd_ticket_log_full'] = 'Go to the full action log (All tickets)'; |
|
365 |
+ |
|
366 |
+// Ticket relationships |
|
367 |
+$txt['shd_ticket_relationships'] = 'Related Tickets'; |
|
368 |
+$txt['shd_ticket_create_relationship'] = 'Create relationship'; |
|
369 |
+$txt['shd_ticket_delete_relationship'] = 'Delete relationship'; |
|
370 |
+$txt['shd_ticket_reltype'] = 'select type'; |
|
371 |
+$txt['shd_ticket_reltype_linked'] = 'Linked to'; |
|
372 |
+$txt['shd_ticket_reltype_duplicated'] = 'Duplicate of'; |
|
373 |
+$txt['shd_ticket_reltype_parent'] = 'Parent of'; |
|
374 |
+$txt['shd_ticket_reltype_child'] = 'Child of'; |
|
375 |
+?> |
|
0 | 376 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,335 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Admin.english.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+// Version: 1.0 Felidae; SimpleDesk administration options |
|
20 |
+ |
|
21 |
+// Important! Before editing these language files please read the text at the top of index.english.php. |
|
22 |
+ |
|
23 |
+/** |
|
24 |
+ * This file contains all of the language strings used in SimpleDesk's administration panel which is loaded throughout the SMF admin area. |
|
25 |
+ * |
|
26 |
+ * @package language |
|
27 |
+ * @todo Document the text groups in this file. |
|
28 |
+ * @since 1.0 |
|
29 |
+ */ |
|
30 |
+ |
|
31 |
+//! @name The 'Core Features' page item |
|
32 |
+//@{ |
|
33 |
+$txt['core_settings_item_shd'] = 'Helpdesk'; |
|
34 |
+$txt['core_settings_item_shd_desc'] = 'The helpdesk allows you to expand your forum into the service industry by providing a dedicated user-staff helpdesk area.'; |
|
35 |
+//@} |
|
36 |
+ |
|
37 |
+//! @name Items for general SMF/ACP integration |
|
38 |
+//@{ |
|
39 |
+$txt['errortype_simpledesk'] = 'SimpleDesk'; |
|
40 |
+$txt['errortype_simpledesk_desc'] = 'Errors most likely related to SimpleDesk. Please report any such errors on www.simpledesk.net.'; |
|
41 |
+//@} |
|
42 |
+ |
|
43 |
+//! @name Items for the administration menu structure |
|
44 |
+//@{ |
|
45 |
+// Admin menu items |
|
46 |
+$txt['shd_admin_info'] = 'Information'; |
|
47 |
+$txt['shd_admin_options'] = 'Options'; |
|
48 |
+$txt['shd_admin_standalone_options'] = 'Standalone Mode'; |
|
49 |
+$txt['shd_admin_actionlog'] = 'Action Log'; |
|
50 |
+$txt['shd_admin_support'] = 'Support'; |
|
51 |
+$txt['shd_admin_helpdesklog'] = 'Helpdesk Log'; |
|
52 |
+$txt['shd_admin_permissions'] = 'Permissions'; |
|
53 |
+ |
|
54 |
+$txt['shd_admin_options_display'] = 'Display Options'; |
|
55 |
+$txt['shd_admin_options_posting'] = 'Posting Options'; |
|
56 |
+$txt['shd_admin_options_admin'] = 'Administrative Options'; |
|
57 |
+$txt['shd_admin_options_standalone'] = 'Standalone Options'; |
|
58 |
+$txt['shd_admin_options_actionlog'] = 'Action Log Options'; |
|
59 |
+//@} |
|
60 |
+ |
|
61 |
+//! @name Descriptions for the page items. |
|
62 |
+//@{ |
|
63 |
+$txt['shd_admin_info_desc'] = 'This is the information center for the helpdesk, powered by SimpleDesk. Here you can get the latest news as well as version-specific support.'; |
|
64 |
+$txt['shd_admin_options_desc'] = 'This is the general configuration area for the helpdesk, where some basic options can be configured.'; |
|
65 |
+$txt['shd_admin_options_display_desc'] = 'In this area you can change some settings that will edit the display of your helpdesk.'; |
|
66 |
+$txt['shd_admin_options_posting_desc'] = 'Here you can edit posting settings, such as BBC, smileys, and attachments.'; |
|
67 |
+$txt['shd_admin_options_admin_desc'] = 'Here you can set some general administrative options for the helpdesk.'; |
|
68 |
+$txt['shd_admin_options_standalone_desc'] = 'This area manages the standalone mode for the helpdesk, that effectively disables the forum part of an SMF installation.'; |
|
69 |
+$txt['shd_admin_options_actionlog_desc'] = 'This area allows you to configure what items can be logged within the helpdesk action log.'; |
|
70 |
+$txt['shd_admin_actionlog_desc'] = 'This is a list of all actions, such as resolved tickets, edited tickets and more, carried out in the helpdesk.'; |
|
71 |
+$txt['shd_admin_support_desc'] = 'This area will help you get through to SimpleDesk.net quickly and effectively - the post will include some information helpful for our Support team, about your installation (like SMF version and SimpleDesk version).'; |
|
72 |
+$txt['shd_admin_help'] = 'This is the administration panel for the helpdesk. Here you can manage settings, get news and updates on this modification, and view helpdesk logs.'; |
|
73 |
+//@} |
|
74 |
+ |
|
75 |
+//! @name SimpleDesk info center |
|
76 |
+//@{ |
|
77 |
+$txt['shd_live_from'] = 'Live from SimpleDesk.net'; |
|
78 |
+$txt['shd_no_connect'] = 'Could not retrieve news file from simpledesk.net'; |
|
79 |
+$txt['shd_current_version'] = 'Current Version'; |
|
80 |
+$txt['shd_your_version'] = 'Your Version'; |
|
81 |
+$txt['shd_mod_information'] = 'Mod Information'; |
|
82 |
+$txt['shd_admin_readmore'] = 'Read more'; |
|
83 |
+$txt['shd_admin_help_live'] = 'This box displays the latest news and updates from www.simpledesk.net. Keep your eyes open for new releases and bug fixes. If a new version of this modification is released, you will also see a notification at the top of the helpdesk administration page.'; |
|
84 |
+$txt['shd_admin_help_modification'] = 'This box contains various information about your installation of SimpleDesk.'; |
|
85 |
+$txt['shd_admin_help_credits'] = 'This box lists all of the people that made SimpleDesk possible, from the developers of the actual code, to the support team and the beta testers.'; |
|
86 |
+$txt['shd_admin_help_update'] = 'If you can see this box, you are most likely using an outdated version of SimpleDesk. Follow the guidelines in the notification in order to upgrade to the new release.'; |
|
87 |
+$txt['shd_ticket_information'] = 'Ticket information'; |
|
88 |
+$txt['shd_total_tickets'] = 'Total number of tickets'; |
|
89 |
+$txt['shd_open_tickets'] = 'Open tickets'; |
|
90 |
+$txt['shd_closed_tickets'] = 'Closed tickets'; |
|
91 |
+$txt['shd_recycled_tickets'] = 'Recycled tickets'; |
|
92 |
+$txt['shd_need_support'] = 'Help with SimpleDesk?'; |
|
93 |
+$txt['shd_support_start_here'] = 'See our <a href="%1$s">Support Page</a>'; |
|
94 |
+//@} |
|
95 |
+ |
|
96 |
+//! @name Translatable strings for the credits |
|
97 |
+//@{ |
|
98 |
+$txt['shd_credits'] = 'SimpleDesk Credits'; |
|
99 |
+$txt['shd_credits_and'] = 'and'; |
|
100 |
+$txt['shd_credits_pretext'] = 'These are the persons that made SimpleDesk possible. Thank you!'; |
|
101 |
+$txt['shd_credits_devs'] = 'Developers'; |
|
102 |
+$txt['shd_credits_devs_desc'] = 'The developers of the actual SimpleDesk code.'; |
|
103 |
+$txt['shd_credits_projectsupport'] = 'Project Support'; |
|
104 |
+$txt['shd_credits_projectsupport_desc'] = 'Those managing and supporting the project in different ways.'; |
|
105 |
+$txt['shd_credits_marketing'] = 'Marketing'; |
|
106 |
+$txt['shd_credits_marketing_desc'] = 'Those spreading the word of SimpleDesk.'; |
|
107 |
+$txt['shd_credits_globalizer'] = 'Globalization'; |
|
108 |
+$txt['shd_credits_globalizer_desc'] = 'The people who makes SimpleDesk spread across the world.'; |
|
109 |
+$txt['shd_credits_support'] = 'Support'; |
|
110 |
+$txt['shd_credits_support_desc'] = 'The people providing all the helpless souls with the support they require.'; |
|
111 |
+$txt['shd_credits_qualityassurance'] = 'Quality Assurance'; |
|
112 |
+$txt['shd_credits_qualityassurance_desc'] = 'The leaders of the beta testing team.'; |
|
113 |
+$txt['shd_credits_beta'] = 'Beta Testers'; |
|
114 |
+$txt['shd_credits_beta_desc'] = 'These persons make sure SimpleDesk lives up to the expectations.'; |
|
115 |
+$txt['shd_credits_alltherest'] = 'Anyone else we might\'ve missed...'; |
|
116 |
+$txt['shd_credits_icons'] = '<a href="%1$s">LED</a>, <a href="%2$s">Function</a> and <a href="%3$s">FamFamFam Flags</a> icon sets - the pretty icons used by SimpleDesk'; |
|
117 |
+$txt['shd_credits_user'] = '<strong>YOU</strong>, the proud users of SimpleDesk. Thank you for choosing our software!'; |
|
118 |
+$txt['shd_credits_translators'] = 'Our translators - Thanks to you, people all around the world can use SimpleDesk'; |
|
119 |
+//@} |
|
120 |
+ |
|
121 |
+//! @name Configuration items on the Display Options page |
|
122 |
+//@{ |
|
123 |
+$txt['shd_staff_badge'] = 'What style of badges to use in ticket view?'; |
|
124 |
+$txt['shd_staff_badge_note'] = 'When looking at different replies, it may be helpful to display badges if you have different teams who may respond in the helpdesk. It may also be useful to display members\' own badges, or not; this option lets you select.'; |
|
125 |
+$txt['shd_staff_badge_nobadge'] = 'Display no badge, just a small icon for staff'; |
|
126 |
+$txt['shd_staff_badge_staffbadge'] = 'Display badges only of staff members'; |
|
127 |
+$txt['shd_staff_badge_userbadge'] = 'Display badges only of non-staff/regular users'; |
|
128 |
+$txt['shd_staff_badge_bothbadge'] = 'Display badges of both users and staff'; |
|
129 |
+$txt['shd_display_avatar'] = 'Display avatars in replies to a ticket?'; |
|
130 |
+$txt['shd_ticketnav_style'] = 'What type of navigation to use in the ticket view?'; |
|
131 |
+$txt['shd_ticketnav_style_note'] = 'When looking at tickets, there may be a number of options available to users, including edit, close, and delete. This option specifies the different ways this can look.'; |
|
132 |
+$txt['shd_ticketnav_style_sd'] = 'SimpleDesk style (icon with small text note)'; |
|
133 |
+$txt['shd_ticketnav_style_sdcompact'] = 'SimpleDesk style (icon only)'; |
|
134 |
+$txt['shd_ticketnav_style_smf'] = 'SMF style (text buttons, above the ticket)'; |
|
135 |
+//@} |
|
136 |
+ |
|
137 |
+//! @name Configuration items on the Posting Options page |
|
138 |
+//@{ |
|
139 |
+$txt['shd_thank_you_post'] = 'Display a message to users on posting a ticket'; |
|
140 |
+$txt['shd_thank_you_nonstaff'] = 'Display the message only to non-staff members'; |
|
141 |
+$txt['shd_allow_wikilinks'] = 'Allow use of [[ticket:123]] wiki-style links'; |
|
142 |
+$txt['shd_allow_ticket_bbc'] = 'Allow tickets and replies to use bbcode'; |
|
143 |
+$txt['shd_allow_ticket_smileys'] = 'Allow tickets and replies to use smileys'; |
|
144 |
+$txt['shd_attachments_mode'] = 'How should attachments to tickets be treated?'; |
|
145 |
+$txt['shd_attachments_mode_ticket'] = 'As attached to the ticket'; |
|
146 |
+$txt['shd_attachments_mode_reply'] = 'As attached to individual replies'; |
|
147 |
+$txt['shd_attachments_mode_note'] = 'If using "to ticket" mode, there is no limit on the number of attachments, while if using "to replies", the helpdesk will use the same settings as regular attachments, by default 4 to a post only. Both modes check the size per attachment and that it will not fill up your attachments folder based on the settings in your attachments panel.'; |
|
148 |
+$txt['shd_bbc'] = 'Enabled BBC tags in the helpdesk'; |
|
149 |
+$txt['shd_bbc_desc'] = 'What tags should be enabled for use in the helpdesk?'; |
|
150 |
+//@} |
|
151 |
+ |
|
152 |
+//! @name Configuration items on the Admin Options page |
|
153 |
+//@{ |
|
154 |
+$txt['shd_maintenance_mode'] = 'Put the helpdesk into maintenance mode'; |
|
155 |
+$txt['shd_staff_ticket_self'] = 'For tickets opened by staff, should it be possible to assign them the ticket?'; |
|
156 |
+$txt['shd_admins_not_assignable'] = 'Should admins be excluded from having tickets assigned to them?'; |
|
157 |
+$txt['shd_privacy_display'] = 'What method to use for displaying ticket privacy?'; |
|
158 |
+$txt['shd_privacy_display_smart'] = 'Display a ticket\'s privacy setting when appropriate'; |
|
159 |
+$txt['shd_privacy_display_always'] = 'Always display the ticket\'s privacy setting'; |
|
160 |
+$txt['shd_privacy_display_note'] = 'Normally tickets are limited to user seeing their own and staff seeing all users. There are times you might want staff to be able to create tickets only for senior staff to see - this is a "private" ticket. Since "non-private" might be confusing for regular users, this option allows you to hide the display of "non private" or "private" to only when it is appropriate on a ticket.'; |
|
161 |
+$txt['shd_disable_tickettotopic'] = 'Disable "ticket to topic" options'; |
|
162 |
+$txt['shd_disable_tickettotopic_note'] = 'Normally, it is possible to move tickets to topics and back again (except in Standalone mode), this option denies it for all users regardless of any permissions for it.'; |
|
163 |
+//@} |
|
164 |
+ |
|
165 |
+//! @name Configuration items on the Standalone Options page |
|
166 |
+//@{ |
|
167 |
+$txt['shd_helpdesk_only'] = 'Enable helpdesk only mode'; |
|
168 |
+$txt['shd_helpdesk_only_note'] = 'This will disable access to topics and boards, as well as optionally the features below. Note that none of the data is lost, merely rendered inactive. The following options ONLY apply when this mode is active (when the forum is basically disabled outside the helpdesk)'; |
|
169 |
+$txt['shd_disable_pm'] = 'Disable private messages entirely'; |
|
170 |
+$txt['shd_disable_mlist'] = 'Disable the memberlist entirely'; |
|
171 |
+//@} |
|
172 |
+ |
|
173 |
+//! @name Configuration items on the Action Log Options page |
|
174 |
+//@{ |
|
175 |
+$txt['shd_disable_action_log'] = 'Disable logging of helpdesk actions?'; |
|
176 |
+$txt['shd_display_ticket_logs'] = 'Display a mini action log in each ticket?'; |
|
177 |
+$txt['shd_logopt_newposts'] = 'Log new tickets and their replies'; |
|
178 |
+$txt['shd_logopt_editposts'] = 'Log edits to tickets and posts'; |
|
179 |
+$txt['shd_logopt_resolve'] = 'Log tickets being resolved/unresolved'; |
|
180 |
+$txt['shd_logopt_assign'] = 'Log tickets being assigned/reassigned/unassigned'; |
|
181 |
+$txt['shd_logopt_privacy'] = 'Log ticket privacy being changed'; |
|
182 |
+$txt['shd_logopt_urgency'] = 'Log ticket urgency being changed'; |
|
183 |
+$txt['shd_logopt_tickettopicmove'] = 'Log tickets being moved to topics and back'; |
|
184 |
+$txt['shd_logopt_delete'] = 'Log tickets and replies being deleted'; |
|
185 |
+$txt['shd_logopt_restore'] = 'Log tickets and replies being restored'; |
|
186 |
+$txt['shd_logopt_permadelete'] = 'Log tickets and replies being permadeleted'; |
|
187 |
+$txt['shd_logopt_relationships'] = 'Log any changes in ticket relationships'; |
|
188 |
+$txt['shd_logopt_split'] = 'Log splitting of a ticket into two tickets'; |
|
189 |
+//@} |
|
190 |
+ |
|
191 |
+//! @name General language strings for the action log (entries are contained in SimpleDesk-LogAction.english.php) |
|
192 |
+//@{ |
|
193 |
+$txt['shd_delete_item'] = 'Delete this log item'; |
|
194 |
+$txt['shd_admin_actionlog_title'] = 'Helpdesk action log'; |
|
195 |
+$txt['shd_admin_actionlog_action'] = 'Action'; |
|
196 |
+$txt['shd_admin_actionlog_date'] = 'Date'; |
|
197 |
+$txt['shd_admin_actionlog_member'] = 'Member'; |
|
198 |
+$txt['shd_admin_actionlog_position'] = 'Position'; |
|
199 |
+$txt['shd_admin_actionlog_ip'] = 'IP'; |
|
200 |
+$txt['shd_admin_actionlog_none'] = 'No entries were found.'; |
|
201 |
+$txt['shd_admin_actionlog_unknown'] = 'Unknown'; |
|
202 |
+$txt['shd_admin_actionlog_hidden'] = 'Hidden'; |
|
203 |
+$txt['shd_admin_actionlog_removeall'] = 'Empty out the entire log'; |
|
204 |
+$txt['shd_admin_actionlog_removeall_confirm'] = 'This will permanently delete all entries in the action log older than %s hours. Are you sure?'; |
|
205 |
+//@} |
|
206 |
+ |
|
207 |
+//! @name Strings for the post-to-SimpleDesk.net support page |
|
208 |
+//@{ |
|
209 |
+$txt['shd_admin_support_form_title'] = 'Support form'; |
|
210 |
+$txt['shd_admin_support_what_is_this'] = 'What is this?'; |
|
211 |
+$txt['shd_admin_support_explanation'] = 'This simple form will allow you to send a support request directly to the SimpleDesk website so that the support team there can help you solve any issue you run in to.<br /><br />Please note that you will need an account on our website in order to post as well as replying to your topic in the future. This form will simply speed up the posting process.'; |
|
212 |
+$txt['shd_admin_support_send'] = 'Send support request'; |
|
213 |
+//@} |
|
214 |
+ |
|
215 |
+//! @name The browse-attachments integration strings |
|
216 |
+//@{ |
|
217 |
+$txt['attachment_manager_shd_attach'] = 'Helpdesk attachments'; |
|
218 |
+$txt['attachment_manager_shd_thumb'] = 'Helpdesk thumbnails'; |
|
219 |
+$txt['attachment_manager_shd_attach_no_entries'] = 'There are currently no helpdesk attachments.'; |
|
220 |
+$txt['attachment_manager_shd_thumb_no_entries'] = 'There are currently no helpdesk thumbnails.'; |
|
221 |
+//@} |
|
222 |
+ |
|
223 |
+//! @name Custom fields stuff |
|
224 |
+//@{ |
|
225 |
+$txt['shd_admin_custom_fields'] = 'Custom Fields'; |
|
226 |
+$txt['shd_admin_custom_fields_long'] = 'Custom Fields for Tickets and Replies'; |
|
227 |
+$txt['shd_admin_custom_fields_desc'] = 'This section allows you to create extra fields that can be added to tickets and/or their replies, to gather additional information about the ticket or to help you manage your helpdesk.'; |
|
228 |
+$txt['shd_admin_custom_fields_general'] = 'General Details'; |
|
229 |
+ |
|
230 |
+ |
|
231 |
+$txt['shd_admin_custom_fields_fieldname'] = 'Field Name'; |
|
232 |
+$txt['shd_admin_custom_fields_fieldname_desc'] = 'The name displayed next to where the user will enter the information (required)'; |
|
233 |
+$txt['shd_admin_custom_fields_icon'] = 'Field Icon'; |
|
234 |
+$txt['shd_admin_custom_fields_icon_desc'] = 'An optional icon displayed next to the field name.'; |
|
235 |
+$txt['shd_admin_custom_fields_fieldtype'] = 'Field Type'; |
|
236 |
+$txt['shd_admin_custom_fields_fieldtype_desc'] = 'The type of field the user will complete with requested information.'; |
|
237 |
+$txt['shd_admin_custom_fields_active'] = 'Active'; |
|
238 |
+$txt['shd_admin_custom_fields_inactive'] = 'Not active'; |
|
239 |
+$txt['shd_admin_custom_fields_active_desc'] = 'This is a master toggle for this field; if it is not active, it will not be displayed or requested from the user when posting.'; |
|
240 |
+$txt['shd_admin_custom_fields_fielddesc'] = 'Field Description'; |
|
241 |
+$txt['shd_admin_custom_fields_fielddesc_desc'] = 'A short description of the field you are adding.'; |
|
242 |
+$txt['shd_admin_custom_fields_visible'] = 'Visible'; |
|
243 |
+$txt['shd_admin_custom_fields_visible_ticket'] = 'Visible/editable for a ticket'; |
|
244 |
+$txt['shd_admin_custom_fields_visible_field'] = 'Visible/editable in replies'; |
|
245 |
+$txt['shd_admin_custom_fields_visible_both'] = 'Visible/editable in both tickets and replies'; |
|
246 |
+$txt['shd_admin_custom_fields_visible_desc'] = 'This controls whether a given field applies to just tickets as a whole, to replies individually or both a ticket and its replies.'; |
|
247 |
+$txt['shd_admin_custom_fields_none'] = '(none)'; |
|
248 |
+$txt['shd_admin_no_custom_fields'] = 'There are no custom fields currently set up.'; |
|
249 |
+$txt['shd_admin_custom_fields_inticket'] = 'Visible on a ticket'; |
|
250 |
+$txt['shd_admin_custom_fields_inreply'] = 'Visible on a reply'; |
|
251 |
+$txt['shd_admin_custom_fields_move'] = 'Move'; |
|
252 |
+$txt['shd_admin_move_up'] = 'Move up'; |
|
253 |
+$txt['shd_admin_move_down'] = 'Move down'; |
|
254 |
+$txt['shd_admin_custom_fields_ui_text'] = 'Textbox'; |
|
255 |
+$txt['shd_admin_custom_fields_ui_largetext'] = 'Large textbox'; |
|
256 |
+$txt['shd_admin_custom_fields_ui_int'] = 'Integer (whole numbers)'; |
|
257 |
+$txt['shd_admin_custom_fields_ui_float'] = 'Floating (fractional) numbers'; |
|
258 |
+$txt['shd_admin_custom_fields_ui_select'] = 'Select from a dropdown'; |
|
259 |
+$txt['shd_admin_custom_fields_ui_checkbox'] = 'Tickbox (yes/no)'; |
|
260 |
+$txt['shd_admin_custom_fields_ui_radio'] = 'Select from radio buttons'; |
|
261 |
+$txt['shd_admin_cannot_edit_custom_field'] = 'You cannot edit that custom field.'; |
|
262 |
+$txt['shd_admin_cannot_move_custom_field'] = 'You cannot move that custom field.'; |
|
263 |
+$txt['shd_admin_cannot_move_custom_field_up'] = 'You cannot move that custom field up; it is the first item already.'; |
|
264 |
+$txt['shd_admin_cannot_move_custom_field_down'] = 'You cannot move that custom field down; it is the last item already.'; |
|
265 |
+$txt['shd_admin_new_custom_field'] = 'Add New Field'; |
|
266 |
+$txt['shd_admin_new_custom_field_desc'] = 'From this panel you can add a new custom field for your tickets and/or their replies, and specify how these should function for you.'; |
|
267 |
+$txt['shd_admin_edit_custom_field'] = 'Edit Existing Field'; |
|
268 |
+$txt['shd_admin_edit_custom_field_desc'] = 'From this panel you can edit an existing custom field, as set out below.'; |
|
269 |
+//@} |
|
270 |
+ |
|
271 |
+//! Plugins |
|
272 |
+//@{ |
|
273 |
+$txt['shd_admin_plugins'] = 'Plugins'; |
|
274 |
+$txt['shd_admin_plugins_homedesc'] = 'This area allows you to manage any additional components for SimpleDesk. They are installed through the Package Manager as regular mods, and configured from here.'; |
|
275 |
+$txt['shd_admin_plugins_none'] = 'No plugins are currently installed.'; |
|
276 |
+$txt['shd_admin_plugins_writtenby'] = 'Written by'; |
|
277 |
+$txt['shd_admin_plugins_website'] = 'Website'; |
|
278 |
+$txt['shd_admin_plugins_wrong_version'] = 'Not supported by this version!'; |
|
279 |
+$txt['shd_admin_plugins_versions_avail'] = 'Supported by the plugin'; |
|
280 |
+$txt['shd_admin_plugins_languages'] = 'Available languages'; |
|
281 |
+$txt['shd_admin_plugins_lang_albanian'] = 'Albanian'; |
|
282 |
+$txt['shd_admin_plugins_lang_arabic'] = 'Arabic'; |
|
283 |
+$txt['shd_admin_plugins_lang_bangla'] = 'Bangla'; |
|
284 |
+$txt['shd_admin_plugins_lang_bulgarian'] = 'Bulgarian'; |
|
285 |
+$txt['shd_admin_plugins_lang_catalan'] = 'Catalan'; |
|
286 |
+$txt['shd_admin_plugins_lang_chinese_simplified'] = 'Chinese (simplified)'; |
|
287 |
+$txt['shd_admin_plugins_lang_chinese_traditional'] = 'Chinese (traditional)'; |
|
288 |
+$txt['shd_admin_plugins_lang_croatian'] = 'Croatian'; |
|
289 |
+$txt['shd_admin_plugins_lang_czech'] = 'Czech'; |
|
290 |
+$txt['shd_admin_plugins_lang_danish'] = 'Danish'; |
|
291 |
+$txt['shd_admin_plugins_lang_dutch'] = 'Dutch'; |
|
292 |
+$txt['shd_admin_plugins_lang_english'] = 'English (US)'; |
|
293 |
+$txt['shd_admin_plugins_lang_english_british'] = 'English (UK)'; |
|
294 |
+$txt['shd_admin_plugins_lang_finnish'] = 'Finnish'; |
|
295 |
+$txt['shd_admin_plugins_lang_french'] = 'French'; |
|
296 |
+$txt['shd_admin_plugins_lang_galician'] = 'Galician'; |
|
297 |
+$txt['shd_admin_plugins_lang_german'] = 'German'; |
|
298 |
+$txt['shd_admin_plugins_lang_hebrew'] = 'Hebrew'; |
|
299 |
+$txt['shd_admin_plugins_lang_hindi'] = 'Hindi'; |
|
300 |
+$txt['shd_admin_plugins_lang_hungarian'] = 'Hungarian'; |
|
301 |
+$txt['shd_admin_plugins_lang_indonesian'] = 'Indonesian'; |
|
302 |
+$txt['shd_admin_plugins_lang_italian'] = 'Italian'; |
|
303 |
+$txt['shd_admin_plugins_lang_japanese'] = 'Japanese'; |
|
304 |
+$txt['shd_admin_plugins_lang_kurdish_kurmanji'] = 'Kurdish (Kurmanji)'; |
|
305 |
+$txt['shd_admin_plugins_lang_kurdish_sorani'] = 'Kurdish (Sorani)'; |
|
306 |
+$txt['shd_admin_plugins_lang_macedonian'] = 'Macedonian'; |
|
307 |
+$txt['shd_admin_plugins_lang_malay'] = 'Malay'; |
|
308 |
+$txt['shd_admin_plugins_lang_norwegian'] = 'Norwegian'; |
|
309 |
+$txt['shd_admin_plugins_lang_persian'] = 'Persian'; |
|
310 |
+$txt['shd_admin_plugins_lang_polish'] = 'Polish'; |
|
311 |
+$txt['shd_admin_plugins_lang_portuguese_brazilian'] = 'Portuguese (Brazilian)'; |
|
312 |
+$txt['shd_admin_plugins_lang_portuguese_pt'] = 'Portuguese'; |
|
313 |
+$txt['shd_admin_plugins_lang_romanian'] = 'Romanian'; |
|
314 |
+$txt['shd_admin_plugins_lang_russian'] = 'Russian'; |
|
315 |
+$txt['shd_admin_plugins_lang_serbian_cyrillic'] = 'Serbian (Cyrillic)'; |
|
316 |
+$txt['shd_admin_plugins_lang_serbian_latin'] = 'Serbian (Latin)'; |
|
317 |
+$txt['shd_admin_plugins_lang_slovak'] = 'Slovak'; |
|
318 |
+$txt['shd_admin_plugins_lang_spanish_es'] = 'Spanish (Spain)'; |
|
319 |
+$txt['shd_admin_plugins_lang_spanish_latin'] = 'Spanish (Latin)'; |
|
320 |
+$txt['shd_admin_plugins_lang_swedish'] = 'Swedish'; |
|
321 |
+$txt['shd_admin_plugins_lang_thai'] = 'Thai'; |
|
322 |
+$txt['shd_admin_plugins_lang_turkish'] = 'Turkish'; |
|
323 |
+$txt['shd_admin_plugins_lang_ukrainian'] = 'Ukrainian'; |
|
324 |
+$txt['shd_admin_plugins_lang_urdu'] = 'Urdu'; |
|
325 |
+$txt['shd_admin_plugins_lang_uzbek_latin'] = 'Uzbek (Latin)'; |
|
326 |
+$txt['shd_admin_plugins_lang_vietnamese'] = 'Vietnamese'; |
|
327 |
+//@} |
|
328 |
+ |
|
329 |
+/** |
|
330 |
+ * @ignore |
|
331 |
+ * Warning: He may bite. |
|
332 |
+*/ |
|
333 |
+$txt['shd_fluffy'] = 'Guardian of the <span %s>cookies</span>'; |
|
334 |
+ |
|
335 |
+?> |
|
0 | 336 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,108 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-LogAction.english.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+// Version: 1.0 Felidae; SimpleDesk action log |
|
20 |
+ |
|
21 |
+// Important! Before editing these language files please read the text at the top of index.english.php. |
|
22 |
+ |
|
23 |
+/** |
|
24 |
+ * This file contains all of the base language strings used by the helpdesk action log. |
|
25 |
+ * Unlike other language files, many of the strings here are parameterised, enabling them to be extended in the future. |
|
26 |
+ * @see shd_log_action() |
|
27 |
+ * |
|
28 |
+ * @package language |
|
29 |
+ * @todo Document the text groups in this file. |
|
30 |
+ * @since 1.0 |
|
31 |
+ */ |
|
32 |
+ |
|
33 |
+//! @name General strings |
|
34 |
+//@{ |
|
35 |
+$txt['shd_action_log_disabled'] = '<strong>Note:</strong> Logging of actions is currently <strong>disabled</strong>, so no new log entries will be added.'; |
|
36 |
+//@} |
|
37 |
+ |
|
38 |
+//! @name Ticket resolution |
|
39 |
+//@{ |
|
40 |
+$txt['shd_log_resolve'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" marked as <strong>resolved</strong>.'; |
|
41 |
+$txt['shd_log_unresolve'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" marked as <strong>not yet resolved</strong>.'; |
|
42 |
+//@} |
|
43 |
+ |
|
44 |
+//! @name Ticket assignation |
|
45 |
+//@{ |
|
46 |
+$txt['shd_log_assign'] = 'Assigned "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" to {profile_link}.'; |
|
47 |
+$txt['shd_log_unassign'] = 'Assigned "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" to no-one.'; |
|
48 |
+//@} |
|
49 |
+ |
|
50 |
+//! @name Ticket privacy |
|
51 |
+//@{ |
|
52 |
+$txt['shd_log_markprivate'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" marked as <strong>private</strong>.'; |
|
53 |
+$txt['shd_log_marknotprivate'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" marked as <strong>not private</strong>.'; |
|
54 |
+//@} |
|
55 |
+ |
|
56 |
+//! @name Ticket urgency |
|
57 |
+//@{ |
|
58 |
+$txt['shd_log_urgency_increase'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" increased to <strong>{urgency}</strong>.'; |
|
59 |
+$txt['shd_log_urgency_decrease'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" decreased to <strong>{urgency}</strong>.'; |
|
60 |
+//@} |
|
61 |
+ |
|
62 |
+//! @name Ticket/topic, topic/ticket moves |
|
63 |
+//@{ |
|
64 |
+$txt['shd_log_tickettotopic'] = 'Moved "<a href="{scripturl}?topic={ticket}.0">{subject}</a>" to "<strong><a href="{scripturl}?board={board_id}.0">{board_name}</a></strong>" in the forum.'; |
|
65 |
+$txt['shd_log_topictoticket'] = 'Moved the topic "<strong><a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a></strong>" from the forum to the helpdesk.'; |
|
66 |
+//@} |
|
67 |
+ |
|
68 |
+//! @name Ticket deletion, restoration, permadeletion |
|
69 |
+//@{ |
|
70 |
+$txt['shd_log_delete'] = 'Deleted "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" to the recycle bin.'; |
|
71 |
+$txt['shd_log_restore'] = 'Restored "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" from the recycle bin.'; |
|
72 |
+$txt['shd_log_permadelete'] = '<strong>Permanently</strong> deleted "{subject}" (ticket {ticket}).'; |
|
73 |
+$txt['shd_log_delete_reply'] = 'Deleted reply in "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.msg{msg}#msg{msg};recycle">{subject}</a>" to the recycle bin.'; |
|
74 |
+$txt['shd_log_restore_reply'] = 'Restored reply in "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.msg{msg}#msg{msg}">{subject}</a>" from the recycle bin.'; |
|
75 |
+$txt['shd_log_permadelete_reply'] = '<strong>Permanently</strong> deleted a reply from "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>".'; |
|
76 |
+//@} |
|
77 |
+ |
|
78 |
+//! @name Ticket relationships |
|
79 |
+//@{ |
|
80 |
+$txt['shd_log_rel_linked'] = 'Marked "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" as linked to "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
81 |
+$txt['shd_log_rel_duplicated'] = 'Marked "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" as duplicate of "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
82 |
+$txt['shd_log_rel_parent'] = 'Marked "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" as parent of "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
83 |
+$txt['shd_log_rel_child'] = 'Marked "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" as child of "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
84 |
+$txt['shd_log_rel_re_linked'] = 'Updated "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" as being linked to "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
85 |
+$txt['shd_log_rel_re_duplicated'] = 'Updated "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" as being a duplicate of "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
86 |
+$txt['shd_log_rel_re_parent'] = 'Updated "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" as being the parent of "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
87 |
+$txt['shd_log_rel_re_child'] = 'Updated "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" as being a child of "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
88 |
+$txt['shd_log_rel_delete'] = 'Removed relationship between "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" and "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
89 |
+//@} |
|
90 |
+ |
|
91 |
+//! @name Ticket merge/split |
|
92 |
+//@{ |
|
93 |
+$txt['shd_log_split_origin'] = 'Split "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" to create "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
94 |
+$txt['shd_log_split_new'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>" was split from "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={otherticket}.0">{othersubject}</a>".'; |
|
95 |
+//@} |
|
96 |
+ |
|
97 |
+//! @name Other ticket events |
|
98 |
+//@{ |
|
99 |
+$txt['shd_log_newticket'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" opened.'; |
|
100 |
+$txt['shd_log_editticket'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" was edited.'; |
|
101 |
+$txt['shd_log_newreply'] = '<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.msg{msg}#msg{msg}">New reply</a> to "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>".'; |
|
102 |
+$txt['shd_log_editreply'] = 'A <a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.msg{msg}#msg{msg}">reply</a> was edited in "<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}.0">{subject}</a>".'; |
|
103 |
+$txt['shd_log_newticketproxy'] = '"<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>" opened on behalf of {profile_link}.'; |
|
104 |
+ |
|
105 |
+$txt['shd_logpart_att_added'] = 'Files added'; |
|
106 |
+$txt['shd_logpart_att_removed'] = 'Files removed'; |
|
107 |
+//@} |
|
108 |
+?> |
|
0 | 109 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,325 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Permissions.english.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+// Version: 1.0 Felidae; SimpleDesk permissions |
|
20 |
+ |
|
21 |
+// Important! Before editing these language files please read the text at the top of index.english.php. |
|
22 |
+ |
|
23 |
+/** |
|
24 |
+ * This file contains all of the language strings (both main description and help text) for all permissions that SimpleDesk adds to the |
|
25 |
+ * permissions pages. Note that both classic and simple view are accounted for, explaining the large number of strings per permission. |
|
26 |
+ * |
|
27 |
+ * @package language |
|
28 |
+ * @todo Document the text groups in this file. |
|
29 |
+ * @since 1.0 |
|
30 |
+ */ |
|
31 |
+ |
|
32 |
+global $modSettings; |
|
33 |
+ |
|
34 |
+//! @name General permissions |
|
35 |
+//@{ |
|
36 |
+$txt['permissionname_access_helpdesk'] = 'Access the helpdesk'; |
|
37 |
+$txt['permissionhelp_access_helpdesk'] = 'This permission allows users to even see the helpdesk, and is required to do anything within the helpdesk; is available in the event of banning someone from the helpdesk.'; |
|
38 |
+$txt['permissionname_admin_helpdesk'] = 'Administrate the helpdesk (allows reconfiguration)'; |
|
39 |
+$txt['permissionhelp_admin_helpdesk'] = 'This permission controls whether administrative functions of the helpdesk can be passed on to users who are not administrators of the forum; typically senior associates/helpdesk agents would have this.'; |
|
40 |
+$txt['permissionname_shd_staff'] = 'Treat this user group as helpdesk staff'; |
|
41 |
+$txt['permissionhelp_shd_staff'] = 'Users with this permission will be treated as staff. Amongst other things, this grants the ability to reply to any ticket that is not owned by the starter.'; |
|
42 |
+//@} |
|
43 |
+ |
|
44 |
+//! @name Ticket visibility: general |
|
45 |
+//@{ |
|
46 |
+$txt['permissionname_shd_view_ticket'] = 'What tickets can users see?'; |
|
47 |
+$txt['permissionhelp_shd_view_ticket'] = 'This permission controls whether users can see tickets at all, and more importantly whether they have access to the standard user view or the staff level view; users with the ability to view any are generally considered to be staff.'; |
|
48 |
+$txt['permissionname_shd_view_ticket_no'] = 'None'; |
|
49 |
+$txt['permissionname_shd_view_ticket_own'] = 'Their own tickets'; |
|
50 |
+$txt['permissionname_shd_view_ticket_any'] = 'Any tickets'; |
|
51 |
+//@} |
|
52 |
+ |
|
53 |
+//! @name Ticket visibility: privacy |
|
54 |
+//@{ |
|
55 |
+$txt['permissionname_shd_view_ticket_private'] = 'What private tickets can users see?'; |
|
56 |
+$txt['permissionhelp_shd_view_ticket_private'] = 'This permission controls whether tickets that are marked private can be seen by users, for example, you could use this permission for staff members who want to post a ticket that concerns them, without it being visible to all staff - only senior staff.'; |
|
57 |
+$txt['permissionname_shd_view_ticket_private_no'] = 'None'; |
|
58 |
+$txt['permissionname_shd_view_ticket_private_own'] = 'Own private tickets'; |
|
59 |
+$txt['permissionname_shd_view_ticket_private_any'] = 'Any private tickets'; |
|
60 |
+//@} |
|
61 |
+ |
|
62 |
+//! @name Ticket modifications: privacy |
|
63 |
+//@{ |
|
64 |
+$txt['permissionname_shd_alter_privacy'] = 'Change ticket privacy'; |
|
65 |
+$txt['permissionhelp_shd_alter_privacy'] = 'This permission allows a user to change the privacy on a ticket, from public to private and back. Actual ticket editing permission is not required to use this.'; |
|
66 |
+$txt['permissionname_shd_alter_privacy_own'] = 'Own tickets'; |
|
67 |
+$txt['permissionname_shd_alter_privacy_any'] = 'Any tickets'; |
|
68 |
+//@} |
|
69 |
+ |
|
70 |
+//! @name Ticket modifications: urgency |
|
71 |
+//@{ |
|
72 |
+$txt['permissionname_shd_alter_urgency'] = 'Change ticket urgency'; |
|
73 |
+$txt['permissionhelp_shd_alter_urgency'] = 'Tickets are available in a range of \'urgency\' levels: Low, Medium, High, Very High, Severe, Critical. This permission allows users to raise and lower urgency up to the level of High (and lower from Very High back to High only)'; |
|
74 |
+$txt['permissionname_shd_alter_urgency_own'] = 'Own tickets'; |
|
75 |
+$txt['permissionname_shd_alter_urgency_any'] = 'Any tickets'; |
|
76 |
+$txt['permissionname_shd_alter_urgency_higher'] = 'Change to \'higher\' urgencies'; |
|
77 |
+$txt['permissionhelp_shd_alter_urgency_higher'] = 'This permission extends the above permission, and allows users to be able to select the highest levels of urgency for a ticket. Generally this would be assigned by staff only.'; |
|
78 |
+$txt['permissionname_shd_alter_urgency_higher_own'] = 'Own tickets'; |
|
79 |
+$txt['permissionname_shd_alter_urgency_higher_any'] = 'Any tickets'; |
|
80 |
+//@} |
|
81 |
+ |
|
82 |
+//! @name Ticket modification: assignment |
|
83 |
+//@{ |
|
84 |
+$txt['permissionname_shd_assign_ticket'] = 'Assign a ticket'; |
|
85 |
+$txt['permissionhelp_shd_assign_ticket'] = 'This permission allows users to assign tickets to staff to be dealt with; normally would be given to staff to assign tickets to themselves, or to managers to assign to other users'; |
|
86 |
+$txt['permissionname_shd_assign_ticket_own'] = 'To themselves'; |
|
87 |
+$txt['permissionname_shd_assign_ticket_any'] = 'Any staff member'; |
|
88 |
+//@} |
|
89 |
+ |
|
90 |
+//! @name Ticket modification: resolution |
|
91 |
+//@{ |
|
92 |
+$txt['permissionname_shd_resolve_ticket'] = 'Mark a ticket resolved'; |
|
93 |
+$txt['permissionhelp_shd_resolve_ticket'] = 'This permission allows users to mark tickets resolved, and mark completed tickets as unresolved if there is further business to attend to.'; |
|
94 |
+$txt['permissionname_shd_resolve_ticket_no'] = 'No tickets'; |
|
95 |
+$txt['permissionname_shd_resolve_ticket_own'] = 'Their own tickets'; |
|
96 |
+$txt['permissionname_shd_resolve_ticket_any'] = 'Any tickets'; |
|
97 |
+//@} |
|
98 |
+ |
|
99 |
+//! @name Ticket posting: new ticket |
|
100 |
+//@{ |
|
101 |
+$txt['permissionname_shd_new_ticket'] = 'Post new tickets'; |
|
102 |
+$txt['permissionhelp_shd_new_ticket'] = 'This permission allows users in this membergroup to file new tickets for themselves.'; |
|
103 |
+//@} |
|
104 |
+ |
|
105 |
+//! @name Ticket posting: replies |
|
106 |
+//@{ |
|
107 |
+$txt['permissionname_shd_reply_ticket'] = 'Reply to tickets'; |
|
108 |
+$txt['permissionhelp_shd_reply_ticket'] = 'This permission allows users to reply to tickets, either to provide further details, or to provide an answer.'; |
|
109 |
+$txt['permissionname_shd_reply_ticket_own'] = 'Own tickets'; |
|
110 |
+$txt['permissionname_shd_reply_ticket_any'] = 'Any tickets'; |
|
111 |
+//@} |
|
112 |
+ |
|
113 |
+//! @name Ticket posting: editing a ticket |
|
114 |
+//@{ |
|
115 |
+$txt['permissionname_shd_edit_ticket'] = 'Edit ticket details'; |
|
116 |
+$txt['permissionhelp_shd_edit_ticket'] = 'This permission allows a user to edit the core details of a ticket, such as the ticket\'s name and initial description.'; |
|
117 |
+$txt['permissionname_shd_edit_ticket_own'] = 'Own tickets'; |
|
118 |
+$txt['permissionname_shd_edit_ticket_any'] = 'Any tickets'; |
|
119 |
+//@} |
|
120 |
+ |
|
121 |
+//! @name Ticket posting: editing replies |
|
122 |
+//@{ |
|
123 |
+$txt['permissionname_shd_edit_reply'] = 'Edit ticket replies'; |
|
124 |
+$txt['permissionhelp_shd_edit_reply'] = 'This permission allows a user to edit replies in tickets, not the main ticket itself.'; |
|
125 |
+$txt['permissionname_shd_edit_reply_own'] = 'Own replies'; |
|
126 |
+$txt['permissionname_shd_edit_reply_any'] = 'Any replies'; |
|
127 |
+//@} |
|
128 |
+ |
|
129 |
+//! @name Ticket deletion: tickets |
|
130 |
+//@{ |
|
131 |
+$txt['permissionname_shd_delete_ticket'] = 'Delete a ticket'; |
|
132 |
+$txt['permissionhelp_shd_delete_ticket'] = 'This permission allows a user to delete a ticket.'; |
|
133 |
+$txt['permissionname_shd_delete_ticket_own'] = 'Own tickets'; |
|
134 |
+$txt['permissionname_shd_delete_ticket_any'] = 'Any tickets'; |
|
135 |
+//@} |
|
136 |
+ |
|
137 |
+//! @name Ticket deletion: replies |
|
138 |
+//@{ |
|
139 |
+$txt['permissionname_shd_delete_reply'] = 'Delete ticket replies'; |
|
140 |
+$txt['permissionhelp_shd_delete_reply'] = 'This permission allows a user to delete replies in tickets, not the main ticket itself.'; |
|
141 |
+$txt['permissionname_shd_delete_reply_own'] = 'Own replies'; |
|
142 |
+$txt['permissionname_shd_delete_reply_any'] = 'Any replies'; |
|
143 |
+//@} |
|
144 |
+ |
|
145 |
+//! @name Ticket deletion: permadelete |
|
146 |
+//@{ |
|
147 |
+$txt['permissionname_shd_delete_recycling'] = '<strong>Permanently</strong> delete items'; |
|
148 |
+$txt['permissionhelp_shd_delete_recycling'] = 'This permission allows users to remove tickets and posts from the recycling area. Note that once removed here, they are NOT recoverable, as such it is not recommended to grant this permission to all staff.'; |
|
149 |
+//@} |
|
150 |
+ |
|
151 |
+//! @name Ticket deletion: accessing recycle bin |
|
152 |
+//@{ |
|
153 |
+$txt['permissionname_shd_access_recyclebin'] = 'Access recycling bin'; |
|
154 |
+$txt['permissionhelp_shd_access_recyclebin'] = 'Users with this permission will be able to access the list of recycled tickets and read the tickets.'; |
|
155 |
+//@} |
|
156 |
+ |
|
157 |
+//! @name Ticket deletion: restoration of tickets |
|
158 |
+//@{ |
|
159 |
+$txt['permissionname_shd_restore_ticket'] = 'Restore deleted tickets'; |
|
160 |
+$txt['permissionhelp_shd_restore_ticket'] = 'This permission allows a user to restore deleted tickets from the recycling bin.'; |
|
161 |
+$txt['permissionname_shd_restore_ticket_own'] = 'Own tickets'; |
|
162 |
+$txt['permissionname_shd_restore_ticket_any'] = 'Any tickets'; |
|
163 |
+//@} |
|
164 |
+ |
|
165 |
+//! @name Ticket deletion: restoration of replies |
|
166 |
+//@{ |
|
167 |
+$txt['permissionname_shd_restore_reply'] = 'Restore deleted replies'; |
|
168 |
+$txt['permissionhelp_shd_restore_reply'] = 'This permission allows a user to restore deleted replies from the recycling bin.'; |
|
169 |
+$txt['permissionname_shd_restore_reply_own'] = 'Own replies'; |
|
170 |
+$txt['permissionname_shd_restore_reply_any'] = 'Any replies'; |
|
171 |
+//@} |
|
172 |
+ |
|
173 |
+//! @name Attachments |
|
174 |
+//@{ |
|
175 |
+$txt['permissionname_shd_post_attachment'] = 'Post attachments'; |
|
176 |
+$txt['permissionhelp_shd_post_attachment'] = 'This permission allows a user to post attachments to tickets.'; |
|
177 |
+//@} |
|
178 |
+ |
|
179 |
+//! @name Posting proxy tickets (i.e. posting new ticket on behalf of someone else) |
|
180 |
+//@{ |
|
181 |
+$txt['permissionname_shd_post_proxy'] = 'Post proxy tickets'; |
|
182 |
+$txt['permissionhelp_shd_post_proxy'] = 'This permission allows a user, typically staff, to create a ticket on behalf of another user (e.g. from a telephone call)'; |
|
183 |
+ |
|
184 |
+//! @name Ticket to topic, topic to ticket movement |
|
185 |
+//@{ |
|
186 |
+$txt['permissionname_shd_ticket_to_topic'] = 'Move tickets to topics'; |
|
187 |
+$txt['permissionhelp_shd_ticket_to_topic'] = 'This permission allows a user to transform tickets into topics in the forum. This should only be granted to staff members.'; |
|
188 |
+$txt['permissionname_shd_topic_to_ticket'] = 'Move topics to tickets'; |
|
189 |
+$txt['permissionhelp_shd_topic_to_ticket'] = 'This permission allows a user to transform topics in the forum into helpdesk tickets. This should only be granted to staff members.'; |
|
190 |
+//@} |
|
191 |
+ |
|
192 |
+//! @name Ticket action logs. |
|
193 |
+//@{ |
|
194 |
+$txt['permissionname_shd_view_ticket_logs'] = 'View ticket action logs'; |
|
195 |
+$txt['permissionhelp_shd_view_ticket_logs'] = 'This permission allows the user to view a log over all actions taken in the current ticket, such as urgency changes, assigning, ticket resolving etc.'; |
|
196 |
+$txt['permissionname_shd_view_ticket_logs_own'] = 'For own tickets'; |
|
197 |
+$txt['permissionname_shd_view_ticket_logs_any'] = 'For any ticket'; |
|
198 |
+//@} |
|
199 |
+ |
|
200 |
+//! @name Ticket merging |
|
201 |
+//@{ |
|
202 |
+$txt['permissionname_shd_merge_ticket'] = 'Merge two tickets together'; |
|
203 |
+$txt['permissionhelp_shd_merge_ticket'] = 'This allows a user to merge two tickets from the same creator together (to ensure the creator can still see the result ticket)'; |
|
204 |
+$txt['permissionname_shd_merge_ticket_own'] = 'Two of their own'; |
|
205 |
+$txt['permissionname_shd_merge_ticket_any'] = 'Two from any user'; |
|
206 |
+//@} |
|
207 |
+ |
|
208 |
+//! @name Ticket splitting |
|
209 |
+//@{ |
|
210 |
+$txt['permissionname_shd_split_ticket'] = 'Split a ticket into two'; |
|
211 |
+$txt['permissionhelp_shd_split_ticket'] = 'This allows a user to split a ticket they can see into two tickets, maybe if the ticket has started discussing a separate issue.'; |
|
212 |
+$txt['permissionname_shd_split_ticket_own'] = 'One of their own'; |
|
213 |
+$txt['permissionname_shd_split_ticket_any'] = 'One from any user'; |
|
214 |
+//@} |
|
215 |
+ |
|
216 |
+//! @name Ticket relationships |
|
217 |
+//@{ |
|
218 |
+$txt['permissionname_shd_view_relationships'] = 'View relationships'; |
|
219 |
+$txt['permissionhelp_shd_view_relationships'] = 'Tickets can be related to each other, as duplicates, linked together, or have dependencies (one requires another to be completed). Not all setups will want users to be able to see relationships, particularly if the relationships are between different users\'s tickets, so this permission blocks the links.'; |
|
220 |
+$txt['permissionname_shd_create_relationships'] = 'Create relationships'; |
|
221 |
+$txt['permissionhelp_shd_create_relationships'] = 'Tickets can have relationships, this permission allows a user the ability to mark a given ticket as having a given relationship between any two tickets they can see. This permission also gives the ability for a relationship to be changed, e.g. from parent/child to linked together.'; |
|
222 |
+$txt['permissionname_shd_delete_relationships'] = 'Remove relationships'; |
|
223 |
+$txt['permissionhelp_shd_delete_relationships'] = 'Sometimes a ticket relationship will no longer be appropriate; this allows the user to remove a relationship between two tickets (not the tickets themselves, note)'; |
|
224 |
+//@} |
|
225 |
+ |
|
226 |
+//! @name Viewing IP addresses |
|
227 |
+//@{ |
|
228 |
+$txt['permissionname_shd_view_ip'] = 'View IP addresses'; |
|
229 |
+$txt['permissionhelp_shd_view_ip'] = 'IP addresses are recorded on every new post/reply made in the helpdesk. This permission controls whether users can see them or not. If \'anyone\' is selected, this includes administrators.'; |
|
230 |
+$txt['permissionname_shd_view_ip_own'] = 'Only their own'; |
|
231 |
+$txt['permissionname_shd_view_ip_any'] = 'Anyone\'s'; |
|
232 |
+//@} |
|
233 |
+ |
|
234 |
+//! @name User profile access |
|
235 |
+//@{ |
|
236 |
+$txt['permissionname_shd_view_profile'] = 'View helpdesk profiles'; |
|
237 |
+$txt['permissionhelp_shd_view_profile'] = 'Users do have a profile within the helpdesk; it allows them to set user preferences, view their tickets, and stats.'; |
|
238 |
+$txt['permissionname_shd_view_profile_no'] = 'None'; |
|
239 |
+$txt['permissionname_shd_view_profile_own'] = 'Only their own'; |
|
240 |
+$txt['permissionname_shd_view_profile_any'] = 'Anyone\'s'; |
|
241 |
+//@} |
|
242 |
+ |
|
243 |
+//! @name User profile logs |
|
244 |
+//@{ |
|
245 |
+$txt['permissionname_shd_view_profile_log'] = 'View profile action logs'; |
|
246 |
+$txt['permissionhelp_shd_view_profile_log'] = 'Just as there is the master action log within the helpdesk, events made by a particular individual can be viewed from their profile.'; |
|
247 |
+$txt['permissionname_shd_view_profile_log_no'] = 'None'; |
|
248 |
+$txt['permissionname_shd_view_profile_log_own'] = 'Only their own'; |
|
249 |
+$txt['permissionname_shd_view_profile_log_any'] = 'Anyone\'s'; |
|
250 |
+//@} |
|
251 |
+ |
|
252 |
+//! @name User preferences |
|
253 |
+$txt['permissionname_shd_view_preferences'] = 'View user preferences'; |
|
254 |
+$txt['permissionhelp_shd_view_preferences'] = 'Users have some configurable options, such as when to receive email notifications. This allows them access to change their preferences.'; |
|
255 |
+$txt['permissionname_shd_view_preferences_no'] = 'None'; |
|
256 |
+$txt['permissionname_shd_view_preferences_own'] = 'Only their own'; |
|
257 |
+$txt['permissionname_shd_view_preferences_any'] = 'Anyone\'s'; |
|
258 |
+ |
|
259 |
+//////////////////////////////// |
|
260 |
+ |
|
261 |
+$txt['shd_admin_permissions'] = 'Helpdesk Permissions'; |
|
262 |
+$txt['shd_admin_permissions_homedesc'] = 'This area allows you to configure the permissions for SimpleDesk - from here you can create roles for your users based on templates, and assign those roles to your membergroups.'; |
|
263 |
+ |
|
264 |
+//! @name Permission categories |
|
265 |
+//@{ |
|
266 |
+$txt['shd_permgroup_general'] = 'General helpdesk permissions'; |
|
267 |
+$txt['shd_permgroup_posting'] = 'Ticket/reply posting'; |
|
268 |
+$txt['shd_permgroup_ticketactions'] = 'Ticket actions'; |
|
269 |
+$txt['shd_permgroup_relationships'] = 'Relationships between tickets'; |
|
270 |
+$txt['shd_permgroup_deletion'] = 'The recycle bin and ticket/reply deletion'; |
|
271 |
+$txt['shd_permgroup_moderation'] = 'Ticket moderation and management'; |
|
272 |
+$txt['shd_permgroup_profile'] = 'User profiles and options'; |
|
273 |
+ |
|
274 |
+$txt['shd_permgroup_short_general'] = 'General'; |
|
275 |
+$txt['shd_permgroup_short_posting'] = 'Posting'; |
|
276 |
+$txt['shd_permgroup_short_ticketactions'] = 'Actions'; |
|
277 |
+$txt['shd_permgroup_short_relationships'] = 'Relationships'; |
|
278 |
+$txt['shd_permgroup_short_deletion'] = 'Delete/Restore'; |
|
279 |
+$txt['shd_permgroup_short_moderation'] = 'Moderation'; |
|
280 |
+$txt['shd_permgroup_short_profile'] = 'Profile'; |
|
281 |
+ |
|
282 |
+$txt['shd_permgroup_denied'] = 'Denied'; |
|
283 |
+//@} |
|
284 |
+ |
|
285 |
+//! @name Permission roles |
|
286 |
+//@{ |
|
287 |
+$txt['shd_role_templates'] = 'Templates'; |
|
288 |
+$txt['shd_role_templates_desc'] = 'These are the templates for permissions, of the roles you may have in your helpdesk. You will use these as a base when creating your own roles.'; |
|
289 |
+$txt['shd_roles'] = 'Roles'; |
|
290 |
+$txt['shd_roles_desc'] = 'These are the roles in your helpdesk, listing what type of role (user/staff/admin) it is, what permissions the roles have and which roles are attached to which membergroups.'; |
|
291 |
+$txt['shd_role'] = 'Role'; |
|
292 |
+$txt['shd_permissions'] = 'Permissions'; |
|
293 |
+$txt['shd_membergroups'] = 'Membergroups'; |
|
294 |
+$txt['shd_permrole_user'] = 'Helpdesk Users'; |
|
295 |
+$txt['shd_permrole_staff'] = 'Helpdesk Staff'; |
|
296 |
+$txt['shd_permrole_admin'] = 'Helpdesk Administrators'; |
|
297 |
+$txt['shd_create_role'] = 'Create new role based on this'; |
|
298 |
+$txt['shd_no_defined_roles'] = 'You have not created any roles yet for your users!'; |
|
299 |
+$txt['shd_based_on'] = 'Based on \'%1$s\' template'; |
|
300 |
+$txt['shd_none'] = 'None'; |
|
301 |
+$txt['shd_edit_role'] = 'Edit this role'; |
|
302 |
+$txt['shd_create_role'] = 'Create New Role'; |
|
303 |
+$txt['shd_edit_role'] = 'Edit Role'; |
|
304 |
+$txt['shd_copy_role'] = 'Copy Role'; |
|
305 |
+$txt['shd_copy_role_groups'] = 'Copy this role\'s groups as well?'; |
|
306 |
+$txt['shd_delete_role'] = 'Delete Role'; |
|
307 |
+$txt['shd_delete_role_confirm'] = 'Do you really want to delete this role?'; |
|
308 |
+$txt['shd_create_based_on'] = 'The new role will be based on'; |
|
309 |
+$txt['shd_is_based_on'] = 'This role is based on the template'; |
|
310 |
+$txt['shd_create_name'] = 'What should the new role be called?'; |
|
311 |
+$txt['shd_role_name'] = 'This role is called'; |
|
312 |
+$txt['shd_role_membergroups'] = 'Membergroups This Role Applies To'; |
|
313 |
+$txt['shd_role_membergroups_desc'] = 'Each role may well apply to multiple groups. Here is where you set what groups this role applies to; note that all the groups below may have roles already attached to them, and permissions can be duplicated that way.'; |
|
314 |
+$txt['shd_badge_stars'] = 'Badge/Stars'; |
|
315 |
+$txt['shd_assign_group'] = 'Assign Role/Group'; |
|
316 |
+$txt['shd_roleperm_allow'] = 'Allowed'; |
|
317 |
+$txt['shd_roleperm_disallow'] = 'Not allowed'; |
|
318 |
+$txt['shd_roleperm_deny'] = 'Never allowed'; |
|
319 |
+ |
|
320 |
+$txt['shd_unknown_template'] = 'The specified template does not exist.'; |
|
321 |
+$txt['shd_no_role_name'] = 'You did not enter the name of your new role.'; |
|
322 |
+$txt['shd_could_not_create_role'] = 'There was an error creating the role, please contact SimpleDesk.net for further support.'; |
|
323 |
+$txt['shd_unknown_role'] = 'That role does not exist.'; |
|
324 |
+//@} |
|
325 |
+?> |
|
0 | 326 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,91 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.1 # |
|
17 |
+# File Info: SimpleDesk-Profile.english.php / 1.1 # |
|
18 |
+############################################################### |
|
19 |
+// Version: 1.0; SimpleDesk Profile language file |
|
20 |
+ |
|
21 |
+// Important! Before editing these language files please read the text at the top of index.english.php. |
|
22 |
+ |
|
23 |
+/** |
|
24 |
+ * This file contains all of the principle language strings used by the Profile page. |
|
25 |
+ * |
|
26 |
+ * @package language |
|
27 |
+ * @since 1.1 |
|
28 |
+ */ |
|
29 |
+ |
|
30 |
+$txt['shd_profile_area'] = 'Helpdesk'; |
|
31 |
+$txt['shd_profile_main'] = 'Profile'; |
|
32 |
+$txt['shd_profile_home'] = 'Profile Home'; |
|
33 |
+$txt['shd_profile_preferences'] = 'Preferences'; |
|
34 |
+$txt['shd_profile_show_tickets'] = 'Show Tickets'; |
|
35 |
+$txt['shd_profile_show_replies'] = 'Show Replies'; |
|
36 |
+$txt['shd_profile_permissions'] = 'Permissions'; |
|
37 |
+$txt['shd_profile_actionlog'] = 'Action Log'; |
|
38 |
+$txt['shd_profile_go_to_helpdesk'] = 'Go to the helpdesk'; |
|
39 |
+ |
|
40 |
+ |
|
41 |
+$txt['shd_profile_heading'] = 'Helpdesk Profile - %s'; |
|
42 |
+$txt['shd_profile_edit_settings'] = 'Edit my settings'; |
|
43 |
+$txt['shd_profile_view_tickets'] = 'View my tickets'; |
|
44 |
+$txt['shd_profile_proxy'] = 'Post proxy ticket'; |
|
45 |
+$txt['shd_profile_tickets'] = 'Ticket Information'; |
|
46 |
+$txt['shd_profile_tickets_created'] = 'Tickets created by this user'; |
|
47 |
+$txt['shd_profile_tickets_assigned'] = 'Tickets assigned to this user'; |
|
48 |
+ |
|
49 |
+$txt['shd_profile_currently_open'] = 'currently open'; |
|
50 |
+ |
|
51 |
+// Permissions |
|
52 |
+$txt['membergroups_members'] = 'Regular Members'; |
|
53 |
+$txt['shd_profile_permissions_header'] = 'Helpdesk Permissions - %s'; |
|
54 |
+$txt['shd_profile_permissions_description'] = 'This area displays all the permissions within the helpdesk for this user.'; |
|
55 |
+$txt['shd_profile_permissions_all_admin'] = 'This user is a full administrator within the forum, and as they have full permissions within the forum, they also have every possible permission within the helpdesk.'; |
|
56 |
+$txt['shd_profile_no_roles'] = 'No helpdesk roles are attached to this user.'; |
|
57 |
+$txt['shd_profile_no_permissions'] = 'No permissions'; |
|
58 |
+$txt['shd_profile_roles_assigned'] = 'These are the roles assigned to this user.'; |
|
59 |
+$txt['shd_profile_role_membergroups'] = 'Associated Membergroups'; |
|
60 |
+$txt['shd_profile_granted'] = 'Granted Permissions'; |
|
61 |
+$txt['shd_profile_denied'] = 'Denied Permissions'; |
|
62 |
+$txt['shd_profile_granted_desc'] = 'These are all the permissions this member has, and what role allows them to have that permission. Note that if one role would grant access to a user\'s own area but another role grants access to any area (e.g. a "users" role grants access to their own profile, but staff grants access to any profile), only the "any" one will be displayed because that takes priority over the "own" one.'; |
|
63 |
+$txt['shd_profile_denied_desc'] = 'These are permissions denied to this member through one or more of the roles they have, and what role is preventing it.'; |
|
64 |
+ |
|
65 |
+// Profile logs |
|
66 |
+$txt['shd_profile_log'] = 'Profile action log - %s'; |
|
67 |
+$txt['shd_profile_log_count_one'] = '1 entry'; |
|
68 |
+$txt['shd_profile_log_count_more'] = '%s entries'; |
|
69 |
+$txt['shd_profile_log_none'] = 'This member has not carried out any helpdesk activities.'; |
|
70 |
+$txt['shd_profile_log_member'] = 'Member'; |
|
71 |
+$txt['shd_profile_log_ip'] = 'Member IP:'; |
|
72 |
+$txt['shd_profile_log_date'] = 'Date'; |
|
73 |
+$txt['shd_profile_log_action'] = 'Action'; |
|
74 |
+$txt['shd_profile_log_full'] = 'Go to the full action log (All members)'; |
|
75 |
+ |
|
76 |
+// Preferences |
|
77 |
+$txt['shd_profile_preferences_header'] = 'Preferences - %s'; |
|
78 |
+$txt['shd_profile_preferences_none_header'] = 'No Preferences'; |
|
79 |
+$txt['shd_profile_preferences_none_desc'] = 'There are no available preferences that can be selected in this profile.'; |
|
80 |
+ |
|
81 |
+$txt['shd_profile_save_prefs'] = 'Save Preferences'; |
|
82 |
+$txt['shd_prefs_updated'] = 'Preferences have been updated.'; |
|
83 |
+ |
|
84 |
+// Show tickets |
|
85 |
+$txt['shd_profile_show_tickets_header'] = 'Tickets and replies posted by %s'; |
|
86 |
+$txt['shd_profile_show_tickets_description'] = 'This page displays all the tickets started by this user as well as all replies the user has posted to tickets.'; |
|
87 |
+$txt['shd_profile_view_full_ticket'] = 'View the full ticket'; |
|
88 |
+$txt['shd_profile_a_ticket'] = 'Ticket %s'; |
|
89 |
+$txt['shd_profile_reply_to_ticket'] = 'Reply to ticket %s'; |
|
90 |
+ |
|
91 |
+?> |
|
0 | 92 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,82 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Who.english.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+// Version: 1.0 Felidae; SimpleDesk who's online |
|
20 |
+ |
|
21 |
+// Important! Before editing these language files please read the text at the top of index.english.php. |
|
22 |
+ |
|
23 |
+/** |
|
24 |
+ * This file contains all of the language strings used by Who's Online for actions carried out within the helpdesk. |
|
25 |
+ * |
|
26 |
+ * @package language |
|
27 |
+ * @todo Document the text groups in this file. |
|
28 |
+ * @since 1.0 |
|
29 |
+ */ |
|
30 |
+ |
|
31 |
+//! @name General strings |
|
32 |
+//@{ |
|
33 |
+$txt['whoall_helpdesk'] = 'Viewing the helpdesk index.'; |
|
34 |
+$txt['whoall_helpdesk_main'] = 'Viewing the helpdesk index.'; |
|
35 |
+$txt['whoall_helpdesk_ticket'] = 'Viewing a helpdesk ticket.'; |
|
36 |
+//@} |
|
37 |
+ |
|
38 |
+//! @name Posting/editing |
|
39 |
+//@{ |
|
40 |
+$txt['whoall_helpdesk_newticket'] = 'Posting a new ticket in the helpdesk.'; |
|
41 |
+$txt['whoall_helpdesk_editticket'] = 'Editing a ticket in the helpdesk.'; |
|
42 |
+$txt['whoall_helpdesk_saveticket'] = 'Posting a ticket in the helpdesk.'; |
|
43 |
+$txt['whoall_helpdesk_reply'] = 'Replying to a helpdesk ticket.'; |
|
44 |
+$txt['whoall_helpdesk_savereply'] = 'Replying to a helpdesk ticket.'; |
|
45 |
+$txt['whoall_helpdesk_editreply'] = 'Editing a reply on a helpdesk ticket.'; |
|
46 |
+$txt['whoall_helpdesk_markunread'] = 'Marking a helpdesk ticket as unread.'; |
|
47 |
+//@} |
|
48 |
+ |
|
49 |
+//! @name Updating ticket details |
|
50 |
+//@{ |
|
51 |
+$txt['whoall_helpdesk_assign'] = 'Assigning a ticket to a user in the helpdesk.'; |
|
52 |
+$txt['whoall_helpdesk_assign2'] = 'Assigning a ticket to a user in the helpdesk.'; |
|
53 |
+$txt['whoall_helpdesk_ajax'] = 'Updating a ticket in the helpdesk.'; |
|
54 |
+$txt['whoall_helpdesk_privacychange'] = 'Updating a ticket\'s details in the helpdesk.'; |
|
55 |
+$txt['whoall_helpdesk_urgencychange'] = 'Updating a ticket\'s details in the helpdesk.'; |
|
56 |
+//@} |
|
57 |
+ |
|
58 |
+//! @name Deletion/recycling, restoration, permadeletion |
|
59 |
+//@{ |
|
60 |
+$txt['whoall_helpdesk_deletereply'] = 'Deleting a reply to a helpdesk ticket.'; |
|
61 |
+$txt['whoall_helpdesk_deleteticket'] = 'Deleting a ticket in the helpdesk.'; |
|
62 |
+$txt['whoall_helpdesk_restorereply'] = 'Restoring a post from the helpdesk recycle bin.'; |
|
63 |
+$txt['whoall_helpdesk_restoretopic'] = 'Restoring a ticket from the helpdesk recycle bin.'; |
|
64 |
+$txt['whoall_helpdesk_recyclebin'] = 'Viewing the deleted tickets in the helpdesk.'; |
|
65 |
+$txt['whoall_helpdesk_permadelete'] = 'Permanently deleting a ticket from the helpdesk.'; |
|
66 |
+//@} |
|
67 |
+ |
|
68 |
+//! @name Ticket resolution |
|
69 |
+//@{ |
|
70 |
+$txt['whoall_helpdesk_resolveticket'] = 'Marking a ticket as resolved, or reopening a resolved, ticket in the helpdesk.'; |
|
71 |
+$txt['whoall_helpdesk_closedtickets'] = 'Viewing the resolved tickets in the helpdesk.'; |
|
72 |
+//@} |
|
73 |
+ |
|
74 |
+//! @name Topic-to-ticket, ticket-to-topic movement |
|
75 |
+//@{ |
|
76 |
+$txt['whoall_helpdesk_tickettotopic'] = 'Moving a helpdesk ticket to a forum topic.'; |
|
77 |
+$txt['whoall_helpdesk_tickettotopic2'] = 'Moving a helpdesk ticket to a forum topic.'; |
|
78 |
+$txt['whoall_helpdesk_topictoticket'] = 'Moving a forum topic to a helpdesk ticket.'; |
|
79 |
+$txt['whoall_helpdesk_topictoticket2'] = 'Moving a forum topic to a helpdesk ticket.'; |
|
80 |
+//@} |
|
81 |
+ |
|
82 |
+?> |
|
0 | 83 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,52 @@ |
1 |
+[url=http://www.simpledesk.net/][img]http://www.simpledesk.net/promo/graphics/signatures/signature1.png[/img][/url] |
|
2 |
+ |
|
3 |
+Thank you for downloading SimpleDesk :) |
|
4 |
+ |
|
5 |
+[b]License[/b] |
|
6 |
+ |
|
7 |
+Yes, we know, you don't want the boring formality of a license, but to protect us - and you - we have a license in the code. Clicking the install button after this constitutes acceptance of the following terms. |
|
8 |
+ |
|
9 |
+[code]Copyright (c) 2010, SimpleDesk Team |
|
10 |
+All rights reserved. |
|
11 |
+ |
|
12 |
+Redistribution and use in source and binary forms, with or without |
|
13 |
+modification, are permitted provided that the following conditions are met: |
|
14 |
+ * Redistributions of source code must retain the above copyright |
|
15 |
+ notice, this list of conditions and the following disclaimer. |
|
16 |
+ * Redistributions in binary form must reproduce the above copyright |
|
17 |
+ notice, this list of conditions and the following disclaimer in the |
|
18 |
+ documentation and/or other materials provided with the distribution. |
|
19 |
+ * Neither the name of SimpleDesk nor the |
|
20 |
+ names of its contributors may be used to endorse or promote products |
|
21 |
+ derived from this software without specific prior written permission. |
|
22 |
+ |
|
23 |
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|
24 |
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
25 |
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
26 |
+DISCLAIMED. IN NO EVENT SHALL SIMPLEDESK TEAM BE LIABLE FOR ANY |
|
27 |
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
28 |
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
29 |
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
30 |
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
31 |
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
32 |
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.[/code] |
|
33 |
+ |
|
34 |
+Loosely translated (and this bit isn't the legal wording) |
|
35 |
+* You can pass it on to others but you have to leave the copyright in the files, including derived/modified versions |
|
36 |
+ |
|
37 |
+* You can't use the name of SimpleDesk to promote something without asking us first. |
|
38 |
+ |
|
39 |
+ |
|
40 |
+[b]So, what next?[/b] |
|
41 |
+ |
|
42 |
+Well, once you click the button and install this mod, the installer will take you to the Core Features page of the SMF admin panel, where you can enable SimpleDesk and begin working with it. |
|
43 |
+ |
|
44 |
+[b]What if I need help?[/b] |
|
45 |
+ |
|
46 |
+You can always get help on our forum, http://www.simpledesk.net/community/ |
|
47 |
+ |
|
48 |
+When SimpleDesk is installed, there will be an extra area for support in the SimpleDesk admin area, that will take you to our forum and help you make a post in the best place for your question - and provide us with some necessary information at the same time. |
|
49 |
+ |
|
50 |
+ |
|
51 |
+I think that's everything from us for now! Enjoy using SimpleDesk as much as we enjoyed creating it! |
|
52 |
+-- the SimpleDesk Development team |
|
0 | 53 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,359 @@ |
1 |
+/* Javascript for the main Helpdesk */ |
|
2 |
+ |
|
3 |
+/* The privacy toggle in AJAX */ |
|
4 |
+function shd_privacyControl(oOpts) |
|
5 |
+{ |
|
6 |
+ shd_privacyControl.prototype.opts = oOpts; // attaches to the link, but it doesn't exist until after DOM is loaded! |
|
7 |
+ if(window.addEventListener) |
|
8 |
+ window.addEventListener('load', shd_privacyControl.prototype.init, false); |
|
9 |
+ else if(window.attachEvent) |
|
10 |
+ window.attachEvent('onload', shd_privacyControl.prototype.init); |
|
11 |
+} |
|
12 |
+ |
|
13 |
+shd_privacyControl.prototype.init = function () |
|
14 |
+{ |
|
15 |
+ var oDiv = document.getElementById(shd_privacyControl.prototype.opts.sSrcA); |
|
16 |
+ if (oDiv != null) |
|
17 |
+ oDiv.onclick = shd_privacyControl.prototype.action; |
|
18 |
+} |
|
19 |
+ |
|
20 |
+shd_privacyControl.prototype.action = function () |
|
21 |
+{ |
|
22 |
+ ajax_indicator(true); |
|
23 |
+ getXMLDocument(shd_privacyControl.prototype.opts.sUrl + ';' + shd_privacyControl.prototype.opts.sSession, shd_privacyControl.prototype.callback); |
|
24 |
+ return false; |
|
25 |
+} |
|
26 |
+ |
|
27 |
+shd_privacyControl.prototype.callback = function (oRecvd) |
|
28 |
+{ |
|
29 |
+ ajax_indicator(false); |
|
30 |
+ if (oRecvd) |
|
31 |
+ { |
|
32 |
+ var errors = oRecvd.getElementsByTagName('error'); |
|
33 |
+ if (errors.length > 0) |
|
34 |
+ { |
|
35 |
+ var msg = ""; |
|
36 |
+ for (var i = 0; i < errors.length; i++) |
|
37 |
+ msg += errors[i].firstChild.nodeValue + "\n"; |
|
38 |
+ alert(msg); |
|
39 |
+ } |
|
40 |
+ else |
|
41 |
+ { |
|
42 |
+ var msg = oRecvd.getElementsByTagName('message'); |
|
43 |
+ if (msg.length > 0) |
|
44 |
+ { |
|
45 |
+ var oSpan = document.getElementById(shd_privacyControl.prototype.opts.sDestSpan); |
|
46 |
+ oSpan.firstChild.nodeValue = msg[0].firstChild.nodeValue; |
|
47 |
+ } |
|
48 |
+ } |
|
49 |
+ } |
|
50 |
+ else |
|
51 |
+ if (confirm(shd_ajax_problem)) |
|
52 |
+ window.location = smf_scripturl + '?action=helpdesk;sa=privacychange;ticket=' + shd_privacyControl.prototype.opts.ticket + ';' + shd_privacyControl.prototype.opts.sSession; |
|
53 |
+ |
|
54 |
+ return false; |
|
55 |
+} |
|
56 |
+ |
|
57 |
+/* The urgency doodad */ |
|
58 |
+function shd_urgencyControl(oOpts) |
|
59 |
+{ |
|
60 |
+ shd_urgencyControl.prototype.opts = oOpts; // attaches to the link, but it doesn't exist until after DOM is loaded! |
|
61 |
+ if(window.addEventListener) |
|
62 |
+ window.addEventListener('load', shd_urgencyControl.prototype.init, false); |
|
63 |
+ else if(window.attachEvent) |
|
64 |
+ window.attachEvent('onload', shd_urgencyControl.prototype.init); |
|
65 |
+} |
|
66 |
+ |
|
67 |
+shd_urgencyControl.prototype.init = function () |
|
68 |
+{ |
|
69 |
+ for (var i in shd_urgencyControl.prototype.opts.aButtonOps) |
|
70 |
+ { |
|
71 |
+ var oDiv = document.getElementById('urglink_' + shd_urgencyControl.prototype.opts.aButtonOps[i]); |
|
72 |
+ if (oDiv != null && i == 'up') |
|
73 |
+ oDiv.onclick = shd_urgencyControl.prototype.actionUp; |
|
74 |
+ else if(oDiv != null && i == 'down') |
|
75 |
+ oDiv.onclick = shd_urgencyControl.prototype.actionDown; // I *did* try to make this a single parameterised function but it always fired when it wasn't supposed to |
|
76 |
+ } |
|
77 |
+} |
|
78 |
+ |
|
79 |
+shd_urgencyControl.prototype.actionUp = function () |
|
80 |
+{ |
|
81 |
+ return shd_urgencyControl.prototype.action('up'); |
|
82 |
+} |
|
83 |
+ |
|
84 |
+shd_urgencyControl.prototype.actionDown = function () |
|
85 |
+{ |
|
86 |
+ return shd_urgencyControl.prototype.action('down'); |
|
87 |
+} |
|
88 |
+ |
|
89 |
+shd_urgencyControl.prototype.action = function (direction) |
|
90 |
+{ |
|
91 |
+ ajax_indicator(true); |
|
92 |
+ shd_urgencyControl.prototype.opts.direction = direction; |
|
93 |
+ getXMLDocument(shd_urgencyControl.prototype.opts.sUrl + shd_urgencyControl.prototype.opts.aButtonOps[direction] + ';' + shd_urgencyControl.prototype.opts.sSession, shd_urgencyControl.prototype.callback); |
|
94 |
+ return false; |
|
95 |
+} |
|
96 |
+ |
|
97 |
+shd_urgencyControl.prototype.callback = function (oRecvd) |
|
98 |
+{ |
|
99 |
+ ajax_indicator(false); |
|
100 |
+ if (oRecvd) |
|
101 |
+ { |
|
102 |
+ var errors = oRecvd.getElementsByTagName('error'); |
|
103 |
+ if (errors.length > 0) |
|
104 |
+ { |
|
105 |
+ var msg = ""; |
|
106 |
+ for (var i = 0; i < errors.length; i++) |
|
107 |
+ msg += errors[i].firstChild.nodeValue + "\n"; |
|
108 |
+ alert(msg); |
|
109 |
+ } |
|
110 |
+ else |
|
111 |
+ { |
|
112 |
+ var msg = oRecvd.getElementsByTagName('message'); |
|
113 |
+ if (msg.length > 0) |
|
114 |
+ { |
|
115 |
+ var oSpan = document.getElementById(shd_urgencyControl.prototype.opts.sDestSpan); |
|
116 |
+ setInnerHTML(oSpan, msg[0].firstChild.nodeValue); |
|
117 |
+ } |
|
118 |
+ // Now to reset the buttons |
|
119 |
+ var btn_set = [ "increase", "decrease" ]; |
|
120 |
+ |
|
121 |
+ for (var i in btn_set) |
|
122 |
+ { |
|
123 |
+ var oBtn = oRecvd.getElementsByTagName(btn_set[i]); |
|
124 |
+ var oSpan = document.getElementById('urgency_' + btn_set[i]); |
|
125 |
+ setInnerHTML(oSpan, (oBtn.length != 0 ? oBtn[0].firstChild.nodeValue : '')); |
|
126 |
+ } |
|
127 |
+ // Attach JS events to new links |
|
128 |
+ shd_urgencyControl.prototype.init(); |
|
129 |
+ } |
|
130 |
+ } |
|
131 |
+ else |
|
132 |
+ if (confirm(shd_ajax_problem)) |
|
133 |
+ window.location = smf_scripturl + '?action=helpdesk;sa=urgencychange;ticket=' + shd_urgencyControl.prototype.opts.ticket + ';change=' + shd_urgencyControl.prototype.opts.aButtonOps[shd_urgencyControl.prototype.opts.direction] + ';' + shd_urgencyControl.prototype.opts.sSession; |
|
134 |
+ |
|
135 |
+ return false; |
|
136 |
+} |
|
137 |
+ |
|
138 |
+/* Attachment selector, based on http://the-stickman.com/web-development/javascript/upload-multiple-files-with-a-single-file-element/ |
|
139 |
+* The code below is modified under the MIT licence, http://the-stickman.com/using-code-from-this-site-ie-licence/ not reproduced here for |
|
140 |
+* convenience of users using this software (as this is an active downloaded file) */ |
|
141 |
+function shd_attach_select(oOptions) |
|
142 |
+{ |
|
143 |
+ shd_attach_select.prototype.opts = oOptions; |
|
144 |
+ shd_attach_select.prototype.count = 0; |
|
145 |
+ shd_attach_select.prototype.id = 0; |
|
146 |
+ shd_attach_select.prototype.max = (oOptions.max) ? oOptions.max : -1; |
|
147 |
+ shd_attach_select.prototype.addElement(document.getElementById(shd_attach_select.prototype.opts.file_item)); |
|
148 |
+}; |
|
149 |
+ |
|
150 |
+shd_attach_select.prototype.addElement = function (element) |
|
151 |
+{ |
|
152 |
+ // Make sure it's a file input element, ignore it if not |
|
153 |
+ if (element.tagName == 'INPUT' && element.type == 'file') |
|
154 |
+ { |
|
155 |
+ element.name = 'file_' + this.id++; |
|
156 |
+ element.multi_selector = this; |
|
157 |
+ element.onchange = function() |
|
158 |
+ { |
|
159 |
+ if (element.value == '') |
|
160 |
+ return; |
|
161 |
+ |
|
162 |
+ // Check if it's a valid extension (if we're checking such things) |
|
163 |
+ if (!shd_attach_select.prototype.checkExtension(element.value)) |
|
164 |
+ { |
|
165 |
+ alert(shd_attach_select.prototype.opts.message_ext_error_final); |
|
166 |
+ element.value = ''; |
|
167 |
+ return; |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ var new_element = document.createElement('input'); |
|
171 |
+ new_element.type = 'file'; |
|
172 |
+ new_element.className = 'input_file'; |
|
173 |
+ new_element.setAttribute('size', '60'); |
|
174 |
+ |
|
175 |
+ // Add new element, update everything |
|
176 |
+ this.parentNode.insertBefore(new_element, this); |
|
177 |
+ this.multi_selector.addElement(new_element); |
|
178 |
+ this.multi_selector.addListRow(this); |
|
179 |
+ |
|
180 |
+ // Hide this: we can't use display:none because Safari doesn't like it |
|
181 |
+ this.style.position = 'absolute'; |
|
182 |
+ this.style.left = '-1000px'; |
|
183 |
+ }; |
|
184 |
+ |
|
185 |
+ this.count++; |
|
186 |
+ shd_attach_select.prototype.current_element = element; |
|
187 |
+ this.checkActive(); |
|
188 |
+ } |
|
189 |
+}; |
|
190 |
+ |
|
191 |
+shd_attach_select.prototype.checkExtension = function (filename) |
|
192 |
+{ |
|
193 |
+ if (!shd_attach_select.prototype.opts.attachment_ext) |
|
194 |
+ return true; // we're not checking |
|
195 |
+ |
|
196 |
+ if (!filename || filename.length == 0) |
|
197 |
+ { |
|
198 |
+ shd_attach_select.prototype.opts.message_ext_error_final = shd_attach_select.prototype.opts.message_ext_error.replace(' ({ext})', ''); |
|
199 |
+ return false; // pfft, didn't specify anything |
|
200 |
+ } |
|
201 |
+ |
|
202 |
+ var dot = filename.lastIndexOf("."); |
|
203 |
+ if (dot == -1) |
|
204 |
+ { |
|
205 |
+ shd_attach_select.prototype.opts.message_ext_error_final = shd_attach_select.prototype.opts.message_ext_error.replace(' ({ext})', ''); |
|
206 |
+ return false; // no extension |
|
207 |
+ } |
|
208 |
+ |
|
209 |
+ var ext = (filename.substr(dot + 1, filename.length)).toLowerCase(); |
|
210 |
+ var arr = shd_attach_select.prototype.opts.attachment_ext; |
|
211 |
+ var func = Array.prototype.indexOf ? |
|
212 |
+ function(arr, obj) { return arr.indexOf(obj) !== -1; } : |
|
213 |
+ function(arr, obj) { |
|
214 |
+ for(var i = -1, j = arr.length; ++i < j;) |
|
215 |
+ if(arr[i] === obj) return true; |
|
216 |
+ return false; |
|
217 |
+ }; |
|
218 |
+ var value = func(arr, ext); |
|
219 |
+ if (!value) |
|
220 |
+ shd_attach_select.prototype.opts.message_ext_error_final = shd_attach_select.prototype.opts.message_ext_error.replace('{ext}', ext); |
|
221 |
+ |
|
222 |
+ return value; |
|
223 |
+} |
|
224 |
+ |
|
225 |
+shd_attach_select.prototype.addListRow = function (element) |
|
226 |
+{ |
|
227 |
+ var new_row = document.createElement('div'); |
|
228 |
+ var new_row_button = document.createElement('input'); |
|
229 |
+ new_row_button.type = 'button'; |
|
230 |
+ new_row_button.value = this.opts.message_txt_delete; |
|
231 |
+ new_row_button.className = 'button_submit'; |
|
232 |
+ new_row.element = element; |
|
233 |
+ |
|
234 |
+ new_row_button.onclick = function () |
|
235 |
+ { |
|
236 |
+ // Remove element from form |
|
237 |
+ this.parentNode.element.parentNode.removeChild(this.parentNode.element); |
|
238 |
+ this.parentNode.parentNode.removeChild(this.parentNode); |
|
239 |
+ this.parentNode.element.multi_selector.count--; |
|
240 |
+ shd_attach_select.prototype.checkActive(); |
|
241 |
+ return false; |
|
242 |
+ }; |
|
243 |
+ |
|
244 |
+ new_row.innerHTML = element.value + ' '; |
|
245 |
+ new_row.appendChild(new_row_button); |
|
246 |
+ document.getElementById(this.opts.file_container).appendChild(new_row); |
|
247 |
+}; |
|
248 |
+ |
|
249 |
+shd_attach_select.prototype.checkActive = function() |
|
250 |
+{ |
|
251 |
+ var elements = document.getElementsByTagName('input'); |
|
252 |
+ var session_attach = 0; |
|
253 |
+ for (i in elements) |
|
254 |
+ { |
|
255 |
+ if (elements[i] && elements[i].type == 'checkbox' && elements[i].name == 'attach_del[]' && elements[i].checked == true) |
|
256 |
+ session_attach++; |
|
257 |
+ } |
|
258 |
+ |
|
259 |
+ var flag = !(shd_attach_select.prototype.max == -1 || (this.max >= (session_attach + shd_attach_select.prototype.count))); |
|
260 |
+ shd_attach_select.prototype.current_element.disabled = flag; |
|
261 |
+} |
|
262 |
+ |
|
263 |
+/* Quick reply stuff */ |
|
264 |
+ |
|
265 |
+function QuickReply(oOptions) |
|
266 |
+{ |
|
267 |
+ this.opt = oOptions; |
|
268 |
+ this.bCollapsed = this.opt.bDefaultCollapsed; |
|
269 |
+} |
|
270 |
+ |
|
271 |
+// When a user presses quote, put it in the quick reply box (if expanded). |
|
272 |
+QuickReply.prototype.quote = function (iMessageId, sSessionId, sSessionVar, bTemplateUpgraded) |
|
273 |
+{ |
|
274 |
+ // Add backwards compatibility with old themes. |
|
275 |
+ if (sSessionVar == true) |
|
276 |
+ { |
|
277 |
+ bTemplateUpgraded = true; |
|
278 |
+ sSessionVar = 'sesc'; |
|
279 |
+ } |
|
280 |
+ |
|
281 |
+ |
|
282 |
+ if (this.bCollapsed) |
|
283 |
+ { |
|
284 |
+ // This is for compatibility. |
|
285 |
+ if (bTemplateUpgraded) |
|
286 |
+ return true; |
|
287 |
+ else |
|
288 |
+ { |
|
289 |
+ window.location.href = smf_prepareScriptUrl(this.opt.sScriptUrl) + 'action=helpdesk;sa=reply;quote=' + iMessageId + ';ticket=' + this.opt.iTicketId + '.' + this.opt.iStart + ';' + sSessionVar + '=' + sSessionId; |
|
290 |
+ return false; |
|
291 |
+ } |
|
292 |
+ } |
|
293 |
+ else |
|
294 |
+ { |
|
295 |
+ // Doing it the XMLhttp way? |
|
296 |
+ if (window.XMLHttpRequest) |
|
297 |
+ { |
|
298 |
+ ajax_indicator(true); |
|
299 |
+ getXMLDocument(smf_prepareScriptUrl(this.opt.sScriptUrl) + 'action=helpdesk;sa=ajax;op=quote;quote=' + iMessageId + ';' + sSessionVar + '=' + sSessionId + ';xml' + ';mode=' + (oEditorHandle_shd_message.bRichTextEnabled ? 1 : 0), this.onQuoteReceived); |
|
300 |
+ } |
|
301 |
+ |
|
302 |
+ // Move the view to the quick reply box. |
|
303 |
+ if (navigator.appName == 'Microsoft Internet Explorer') |
|
304 |
+ window.location.hash = this.opt.sJumpAnchor; |
|
305 |
+ else |
|
306 |
+ window.location.hash = '#' + this.opt.sJumpAnchor; |
|
307 |
+ |
|
308 |
+ return false; |
|
309 |
+ } |
|
310 |
+} |
|
311 |
+ |
|
312 |
+// This is the callback function used after the XMLhttp request. |
|
313 |
+QuickReply.prototype.onQuoteReceived = function (oXMLDoc) |
|
314 |
+{ |
|
315 |
+ var sQuoteText = ''; |
|
316 |
+ |
|
317 |
+ for (var i = 0; i < oXMLDoc.getElementsByTagName('quote')[0].childNodes.length; i++) |
|
318 |
+ sQuoteText += oXMLDoc.getElementsByTagName('quote')[0].childNodes[i].nodeValue; |
|
319 |
+ |
|
320 |
+ oEditorHandle_shd_message.insertText(sQuoteText, false, true); |
|
321 |
+ |
|
322 |
+ ajax_indicator(false); |
|
323 |
+} |
|
324 |
+ |
|
325 |
+// The function handling the swapping of the quick reply. |
|
326 |
+QuickReply.prototype.swap = function () |
|
327 |
+{ |
|
328 |
+ document.getElementById(this.opt.sImageId).src = this.opt.sImagesUrl + "/" + (this.bCollapsed ? this.opt.sImageCollapsed : this.opt.sImageExpanded); |
|
329 |
+ document.getElementById(this.opt.sContainerId).style.display = this.bCollapsed ? '' : 'none'; |
|
330 |
+ document.getElementById(this.opt.sFooterId).style.display = this.bCollapsed ? '' : 'none'; |
|
331 |
+ document.getElementById(this.opt.sHeaderId).setAttribute('class', (this.bCollapsed ? 'titlebg grid_header' : 'titlebg')); |
|
332 |
+ |
|
333 |
+ this.bCollapsed = !this.bCollapsed; |
|
334 |
+} |
|
335 |
+ |
|
336 |
+// The quick jump function |
|
337 |
+function shd_quickTicketJump(id_ticket) |
|
338 |
+{ |
|
339 |
+ window.location.href = smf_prepareScriptUrl(smf_scripturl) + '?action=helpdesk;sa=ticket;ticket=' + id_ticket; |
|
340 |
+ return false; |
|
341 |
+} |
|
342 |
+ |
|
343 |
+/* The action log in tickets - Not much. */ |
|
344 |
+ |
|
345 |
+function ActionLog(oOptions) |
|
346 |
+{ |
|
347 |
+ this.opt = oOptions; |
|
348 |
+ this.bCollapsed = true; |
|
349 |
+} |
|
350 |
+ |
|
351 |
+// The function handling the swapping of the ticket log. |
|
352 |
+ActionLog.prototype.swap = function () |
|
353 |
+{ |
|
354 |
+ document.getElementById(this.opt.sImageId).src = this.opt.sImagesUrl + "/" + (this.bCollapsed ? this.opt.sImageCollapsed : this.opt.sImageExpanded); |
|
355 |
+ document.getElementById(this.opt.sContainerId).style.display = this.bCollapsed ? '' : 'none'; |
|
356 |
+ document.getElementById(this.opt.sHeaderId).setAttribute('class', (this.bCollapsed ? 'catbg grid_header' : 'catbg')); |
|
357 |
+ |
|
358 |
+ this.bCollapsed = !this.bCollapsed; |
|
359 |
+} |
... | ... |
@@ -0,0 +1,104 @@ |
1 |
+// Handle the JavaScript surrounding the admin center. |
|
2 |
+function sd_AdminIndex(oOptions) |
|
3 |
+{ |
|
4 |
+ this.opt = oOptions; |
|
5 |
+ this.init(); |
|
6 |
+} |
|
7 |
+ |
|
8 |
+sd_AdminIndex.prototype.init = function () |
|
9 |
+{ |
|
10 |
+ window.adminIndexInstanceRef = this; |
|
11 |
+ var fHandlePageLoaded = function () { |
|
12 |
+ window.adminIndexInstanceRef.loadAdminIndex(); |
|
13 |
+ } |
|
14 |
+ addLoadEvent(fHandlePageLoaded); |
|
15 |
+} |
|
16 |
+ |
|
17 |
+sd_AdminIndex.prototype.loadAdminIndex = function () |
|
18 |
+{ |
|
19 |
+ // Load the text box containing the latest news items. |
|
20 |
+ if (this.opt.bLoadAnnouncements) |
|
21 |
+ this.setAnnouncements(); |
|
22 |
+ |
|
23 |
+ // Load the current SMF and your SMF version numbers. |
|
24 |
+ if (this.opt.bLoadVersions) |
|
25 |
+ this.showCurrentVersion(); |
|
26 |
+ |
|
27 |
+ // Load the text box that sais there's a new version available. |
|
28 |
+ if (this.opt.bLoadUpdateNotification) |
|
29 |
+ this.checkUpdateAvailable(); |
|
30 |
+} |
|
31 |
+ |
|
32 |
+ |
|
33 |
+sd_AdminIndex.prototype.setAnnouncements = function () |
|
34 |
+{ |
|
35 |
+ if (!('sdAnnouncements' in window) || !('length' in window.sdAnnouncements)) |
|
36 |
+ return; |
|
37 |
+ |
|
38 |
+ var sMessages = ''; |
|
39 |
+ for (var i = 0; i < window.sdAnnouncements.length; i++) |
|
40 |
+ sMessages += this.opt.sAnnouncementMessageTemplate.replace('%href%', window.sdAnnouncements[i].href).replace('%subject%', window.sdAnnouncements[i].subject).replace('%time%', window.sdAnnouncements[i].time).replace('%message%', window.sdAnnouncements[i].message).replace('%author%', window.sdAnnouncements[i].author).replace('%readmore%', window.sdAnnouncements[i].href); |
|
41 |
+ |
|
42 |
+ setInnerHTML(document.getElementById(this.opt.sAnnouncementContainerId), this.opt.sAnnouncementTemplate.replace('%content%', sMessages)); |
|
43 |
+} |
|
44 |
+ |
|
45 |
+sd_AdminIndex.prototype.showCurrentVersion = function () |
|
46 |
+{ |
|
47 |
+ if (!('sdVersion' in window)) |
|
48 |
+ return; |
|
49 |
+ |
|
50 |
+ var oSdVersionContainer = document.getElementById(this.opt.sSdVersionContainerId); |
|
51 |
+ var oYourVersionContainer = document.getElementById(this.opt.sYourVersionContainerId); |
|
52 |
+ |
|
53 |
+ setInnerHTML(oSdVersionContainer, window.sdVersion); |
|
54 |
+ |
|
55 |
+ var sCurrentVersion = getInnerHTML(oYourVersionContainer); |
|
56 |
+ if (sCurrentVersion != window.sdVersion) |
|
57 |
+ setInnerHTML(oYourVersionContainer, this.opt.sVersionOutdatedTemplate.replace('%currentVersion%', sCurrentVersion)); |
|
58 |
+} |
|
59 |
+ |
|
60 |
+sd_AdminIndex.prototype.checkUpdateAvailable = function () |
|
61 |
+{ |
|
62 |
+ if (!('sdUpdatePackage' in window)) |
|
63 |
+ return; |
|
64 |
+ |
|
65 |
+ var oContainer = document.getElementById(this.opt.sUpdateNotificationContainerId); |
|
66 |
+ |
|
67 |
+ // Are we setting a custom title and message? |
|
68 |
+ var sTitle = 'sdUpdateTitle' in window ? window.sdUpdateTitle : this.opt.sUpdateNotificationDefaultTitle; |
|
69 |
+ var sMessage = 'sdUpdateNotice' in window ? window.sdUpdateNotice : this.opt.sUpdateNotificationDefaultMessage; |
|
70 |
+ |
|
71 |
+ setInnerHTML(oContainer, this.opt.sUpdateNotificationTemplate.replace('%title%', sTitle).replace('%message%', sMessage).replace('%criticaltitle%', sTitle)); |
|
72 |
+ |
|
73 |
+ // Parse in the package download URL if it exists in the string. |
|
74 |
+ document.getElementById('update-link').href = this.opt.sUpdateNotificationLink.replace('%package%', window.sdUpdatePackage); |
|
75 |
+ |
|
76 |
+ if ('sdUpdateInformation' in window) |
|
77 |
+ { |
|
78 |
+ document.getElementById('information-link-span').style.display = 'block'; |
|
79 |
+ document.getElementById('information-link').href = this.opt.sUpdateInformationLink.replace('%information%', window.sdUpdateInformation); |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ // If we decide to override life into "red" mode, do it. |
|
83 |
+ if ('sdUpdateCritical' in window && window.sdUpdateCritical == true) |
|
84 |
+ { |
|
85 |
+ document.getElementById('update_container').className = 'errorbox'; |
|
86 |
+ document.getElementById('update_critical_title').style.display = 'block'; |
|
87 |
+ document.getElementById('update_critical_alert').style.display = 'block'; |
|
88 |
+ document.getElementById('update_title').style.display = 'none'; |
|
89 |
+ document.getElementById('update_content').className = ''; |
|
90 |
+ } |
|
91 |
+ |
|
92 |
+ document.getElementById('sd_update_section').style.display = 'block'; |
|
93 |
+} |
|
94 |
+ |
|
95 |
+// Ticket number information... |
|
96 |
+function shd_ticket_total_information() |
|
97 |
+{ |
|
98 |
+ var infocontainer = document.getElementById('shd_ticket_total_information'); |
|
99 |
+ |
|
100 |
+ if (infocontainer.style.display == 'none') |
|
101 |
+ infocontainer.style.display = 'block'; |
|
102 |
+ else |
|
103 |
+ infocontainer.style.display = 'none'; |
|
104 |
+} |
|
0 | 105 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,81 @@ |
1 |
+<?php |
|
2 |
+################################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+# Email Notifications Plugin # |
|
5 |
+################################################################### |
|
6 |
+# An advanced help desk modifcation built on SMF # |
|
7 |
+################################################################### |
|
8 |
+# # |
|
9 |
+# * Copyright 2010 - SimpleDesk.net # |
|
10 |
+# # |
|
11 |
+# This file and its contents are subject to the license # |
|
12 |
+# included with this distribution, license.txt, which # |
|
13 |
+# states that this software is New BSD Licensed. # |
|
14 |
+# Any questions, please contact SimpleDesk.net # |
|
15 |
+# # |
|
16 |
+################################################################### |
|
17 |
+# SimpleDesk Version: 1.0 Felidae # |
|
18 |
+# File Info: SDPluginEmailNotifications.english.php / 1.0 Felidae # |
|
19 |
+################################################################### |
|
20 |
+// Version: 1.0 Felidae; SimpleDesk main language file |
|
21 |
+ |
|
22 |
+// Important! Before editing these language files please read the text at the top of index.english.php. |
|
23 |
+ |
|
24 |
+/** |
|
25 |
+ * @package plugin-emailnotifications |
|
26 |
+ * @since 1.1 |
|
27 |
+*/ |
|
28 |
+ |
|
29 |
+$txt['email_notifications'] = 'Email Notifications'; |
|
30 |
+$txt['email_notifications_desc'] = 'This plugin allows the helpdesk to notify users when tickets are updated.'; |
|
31 |
+ |
|
32 |
+$txt['shd_admin_options_notifications'] = 'Notifications'; |
|
33 |
+$txt['shd_admin_options_notifications_desc'] = 'This area allows you to configure email notifications being sent to users when their tickets change.'; |
|
34 |
+ |
|
35 |
+// Admin panel options |
|
36 |
+$txt['shd_notify_log'] = 'Log notifications being sent (what notification, when sent, user(s) involved)'; |
|
37 |
+$txt['shd_notify_new_ticket'] = 'Allow staff to receive notifications on new tickets'; |
|
38 |
+$txt['shd_notify_new_reply_own'] = 'Allow users to receive notifications when their tickets are replied to'; |
|
39 |
+$txt['shd_notify_new_reply_assigned'] = 'Allow staff to receive notifications when tickets assigned to them are replied to'; |
|
40 |
+$txt['shd_notify_new_reply_previous'] = 'Allow staff to receive notifications when tickets they have replied to, are replied to again'; |
|
41 |
+$txt['shd_notify_new_reply_any'] = 'Allow staff to receive notifications when any tickets are replied to'; |
|
42 |
+$txt['shd_notify_assign_me'] = 'Allow staff to receive notifications when a ticket is assigned to them'; |
|
43 |
+$txt['shd_notify_assign_own'] = 'Allow users to receive notifications when their tickets are assigned to staff'; |
|
44 |
+ |
|
45 |
+// User preferences |
|
46 |
+$txt['shd_pref_group_notify'] = 'Notifications By Email'; |
|
47 |
+$txt['shd_pref_notify_new_ticket'] = 'Email me when a new ticket is posted'; |
|
48 |
+$txt['shd_pref_notify_new_reply_own'] = 'Email me when one of my tickets is replied to'; |
|
49 |
+$txt['shd_pref_notify_new_reply_assigned'] = 'Email me when a ticket assigned to me is replied to'; |
|
50 |
+$txt['shd_pref_notify_new_reply_previous'] = 'Email me when a ticket I\'ve replied to before is replied to again'; |
|
51 |
+$txt['shd_pref_notify_new_reply_any'] = 'Email me when any ticket is replied to'; |
|
52 |
+$txt['shd_pref_notify_assign_me'] = 'Email me when a ticket is assigned to me'; |
|
53 |
+$txt['shd_pref_notify_assign_own'] = 'Email me when one of my tickets is assigned to staff'; |
|
54 |
+ |
|
55 |
+$txt['shd_notify_send_to'] = 'Will be sent to'; |
|
56 |
+$txt['shd_notify_ticket_starter'] = 'the user who started the ticket (if set in their preferences)'; |
|
57 |
+$txt['shd_notify_nobody'] = 'nobody'; |
|
58 |
+ |
|
59 |
+// Email subject and body contents |
|
60 |
+$txt['template_subject_notify_new_ticket'] = 'New helpdesk ticket: {subject}'; |
|
61 |
+$txt['template_body_notify_new_ticket'] = 'A new helpdesk ticket, "{subject}", has been created.' . "\n\n" . 'You can access it here:' . "\n" . '{ticketlink}'; |
|
62 |
+ |
|
63 |
+$txt['template_subject_notify_new_reply_own'] = 'Your helpdesk ticket updated: {subject}'; |
|
64 |
+$txt['template_body_notify_new_reply_own'] = 'Your ticket, "{subject}", has been replied to.' . "\n\n" . 'You can read the reply here:' . "\n" . '{ticketlink}'; |
|
65 |
+ |
|
66 |
+$txt['template_subject_notify_new_reply_assigned'] = 'Helpdesk - assigned ticket updated: {subject}'; |
|
67 |
+$txt['template_body_notify_new_reply_assigned'] = 'A ticket assigned to you, "{subject}", has been replied to.' . "\n\n" . 'You can read the reply here:' . "\n" . '{ticketlink}'; |
|
68 |
+ |
|
69 |
+$txt['template_subject_notify_new_reply_previous'] = 'Helpdesk ticket updated: {subject}'; |
|
70 |
+$txt['template_body_notify_new_reply_previous'] = 'A ticket you previously replied to, "{subject}", has been replied to again.' . "\n\n" . 'You can read the reply here:' . "\n" . '{ticketlink}'; |
|
71 |
+ |
|
72 |
+$txt['template_subject_notify_new_reply_any'] = 'Helpdesk ticket - new reply: {subject}'; |
|
73 |
+$txt['template_body_notify_new_reply_any'] = 'A helpdesk ticket, "{subject}", has been replied to.' . "\n\n" . 'You can read the reply here:' . "\n" . '{ticketlink}'; |
|
74 |
+ |
|
75 |
+$txt['template_subject_notify_assign_me'] = 'Helpdesk ticket assigned: {subject}'; |
|
76 |
+$txt['template_body_notify_assign_me'] = 'The helpdesk ticket, "{subject}", has been assigned to you.' . "\n\n" . 'You can access it here:' . "\n" . '{ticketlink}'; |
|
77 |
+ |
|
78 |
+$txt['template_subject_notify_assign_own'] = 'Helpdesk ticket assigned: {subject}'; |
|
79 |
+$txt['template_body_notify_assign_own'] = 'Your helpdesk ticket, "{subject}", has been assigned to a member of staff to be dealt with.' . "\n\n" . 'You can access your ticket here:' . "\n" . '{ticketlink}'; |
|
80 |
+ |
|
81 |
+?> |
|
0 | 82 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,530 @@ |
1 |
+<?php |
|
2 |
+################################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+# Email Notifications Plugin # |
|
5 |
+################################################################### |
|
6 |
+# An advanced help desk modifcation built on SMF # |
|
7 |
+################################################################### |
|
8 |
+# # |
|
9 |
+# * Copyright 2010 - SimpleDesk.net # |
|
10 |
+# # |
|
11 |
+# This file and its contents are subject to the license # |
|
12 |
+# included with this distribution, license.txt, which # |
|
13 |
+# states that this software is New BSD Licensed. # |
|
14 |
+# Any questions, please contact SimpleDesk.net # |
|
15 |
+# # |
|
16 |
+################################################################### |
|
17 |
+# SimpleDesk Version: 1.0 Felidae # |
|
18 |
+# File Info: SDPluginEmailNotifications.php / 1.0 Felidae # |
|
19 |
+################################################################### |
|
20 |
+ |
|
21 |
+/** |
|
22 |
+ * @package plugin-emailnotifications |
|
23 |
+ * @since 1.1 |
|
24 |
+*/ |
|
25 |
+ |
|
26 |
+if (!defined('SMF')) |
|
27 |
+ die('Hacking attempt...'); |
|
28 |
+ |
|
29 |
+function shd_notifications_notify_newticket(&$msgOptions, &$ticketOptions, &$posterOptions) |
|
30 |
+{ |
|
31 |
+ global $smcFunc, $context, $modSettings, $scripturl; |
|
32 |
+ |
|
33 |
+ // Enabled? |
|
34 |
+ if (empty($modSettings['shd_notify_new_ticket']) || !in_array('email_notifications', $context['shd_plugins'])) |
|
35 |
+ return; |
|
36 |
+ |
|
37 |
+ // So, we're getting the list of people that are being affected by this ticket being posted. Basically, that's a list of staff on new ticket, less people who've set preferences otherwise. |
|
38 |
+ $members = shd_members_allowed_to('shd_staff'); |
|
39 |
+ if (empty($members)) |
|
40 |
+ return; |
|
41 |
+ |
|
42 |
+ $members = array_diff($members, array($context['user']['id'])); |
|
43 |
+ |
|
44 |
+ // Get the default preference (since this is controlled by plugin, i.e. here, we could just hardcode it, but in case someone modifies the default, let's load it from here) |
|
45 |
+ $pref_groups = array(); |
|
46 |
+ $base_prefs = array(); |
|
47 |
+ shd_notifications_prefs($pref_groups, $base_prefs); |
|
48 |
+ |
|
49 |
+ // Apply the default preference |
|
50 |
+ $members = array_flip($members); |
|
51 |
+ foreach ($members as $member => $value) |
|
52 |
+ $members[$member] = $base_prefs['notify_new_ticket']['default']; |
|
53 |
+ |
|
54 |
+ // Grab from the database |
|
55 |
+ $query = $smcFunc['db_query']('', ' |
|
56 |
+ SELECT id_member, value |
|
57 |
+ FROM {db_prefix}helpdesk_preferences |
|
58 |
+ WHERE id_member IN ({array_int:members}) |
|
59 |
+ AND variable = {string:pref}', |
|
60 |
+ array( |
|
61 |
+ 'members' => array_keys($members), |
|
62 |
+ 'pref' => 'notify_new_ticket', |
|
63 |
+ ) |
|
64 |
+ ); |
|
65 |
+ |
|
66 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
67 |
+ { |
|
68 |
+ $row['id_member'] = (int) $row['id_member']; |
|
69 |
+ $members[$row['id_member']] = $row['value']; |
|
70 |
+ } |
|
71 |
+ $smcFunc['db_free_result']($query); |
|
72 |
+ |
|
73 |
+ // OK, now figure out who we're sending to, and discard any member id's we're not sending to |
|
74 |
+ foreach ($members as $member => $value) |
|
75 |
+ { |
|
76 |
+ if (!empty($value)) |
|
77 |
+ $members[$member] = 'new_ticket'; // for the type of message to send |
|
78 |
+ else |
|
79 |
+ unset($members[$member]); |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ // Build the big ol' data set |
|
83 |
+ $notify_data = array( |
|
84 |
+ 'members' => $members, |
|
85 |
+ 'ticketlink' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticketOptions['id'], |
|
86 |
+ 'subject' => $ticketOptions['subject'], |
|
87 |
+ ); |
|
88 |
+ |
|
89 |
+ shd_notify_users($notify_data); |
|
90 |
+} |
|
91 |
+ |
|
92 |
+function shd_notifications_notify_newreply(&$msgOptions, &$ticketOptions, &$posterOptions) |
|
93 |
+{ |
|
94 |
+ global $smcFunc, $context, $modSettings, $scripturl; |
|
95 |
+ |
|
96 |
+ // Is this mic on? |
|
97 |
+ if (!in_array('email_notifications', $context['shd_plugins'])) |
|
98 |
+ return; |
|
99 |
+ |
|
100 |
+ // We did actually get a reply? Sometimes shd_modify_ticket_post() is called for other things, not just on reply. |
|
101 |
+ if (empty($msgOptions['body'])) |
|
102 |
+ return; |
|
103 |
+ |
|
104 |
+ // We're doing various things here, so grab some general details, not just what we may have been passed before. |
|
105 |
+ $ticketinfo = shd_load_ticket($ticketOptions['id']); |
|
106 |
+ $staff = shd_members_allowed_to('shd_staff'); |
|
107 |
+ |
|
108 |
+ // Might as well kick this off here. |
|
109 |
+ $notify_data = array( |
|
110 |
+ 'members' => array(), |
|
111 |
+ 'ticketlink' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticketOptions['id'] . '.msg' . $msgOptions['id'] . '#msg' . $msgOptions['id'], |
|
112 |
+ 'subject' => $ticketinfo['subject'], |
|
113 |
+ ); |
|
114 |
+ |
|
115 |
+ $members = array(); // who should get what type of notification, preferences depending |
|
116 |
+ |
|
117 |
+ // Someone replied to MY ticket? And it isn't me? Tell me about it! |
|
118 |
+ if (!empty($modSettings['shd_notify_new_reply_own'])) |
|
119 |
+ { |
|
120 |
+ if ($posterOptions['id'] != $ticketinfo['starter_id']) |
|
121 |
+ $members[$ticketinfo['starter_id']] = 'new_reply_own'; |
|
122 |
+ } |
|
123 |
+ |
|
124 |
+ // So this is a ticket I'm supposed to deal with... has someone said something I missed? (And just in case it's our ticket, don't send another) |
|
125 |
+ if (!empty($modSettings['shd_notify_new_reply_assigned'])) |
|
126 |
+ { |
|
127 |
+ if ($posterOptions['id'] != $ticketinfo['assigned_id'] && empty($members[$ticketinfo['assigned_id']])) |
|
128 |
+ $members[$ticketinfo['assigned_id']] = 'new_reply_assigned'; |
|
129 |
+ } |
|
130 |
+ |
|
131 |
+ // So, if you're staff, and you've replied to a ticket before, do you want to be notified this time? |
|
132 |
+ if (!empty($modSettings['shd_notify_new_reply_previous'])) |
|
133 |
+ { |
|
134 |
+ $query = $smcFunc['db_query']('', ' |
|
135 |
+ SELECT id_member |
|
136 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
137 |
+ WHERE id_ticket = {int:ticket} |
|
138 |
+ GROUP BY id_member', |
|
139 |
+ array( |
|
140 |
+ 'ticket' => $ticketOptions['id'], |
|
141 |
+ ) |
|
142 |
+ ); |
|
143 |
+ $responders = array(); |
|
144 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
145 |
+ $responders[] = $row[0]; // this shouldn't be nil, ever, because we're replying, so the topic already exists so there's at least one name in there... |
|
146 |
+ $smcFunc['db_free_result']($query); |
|
147 |
+ |
|
148 |
+ $responders = array_intersect($responders, $staff); |
|
149 |
+ foreach ($responders as $id) |
|
150 |
+ { |
|
151 |
+ if (empty($members[$id])) |
|
152 |
+ $members[$id] = 'new_reply_previous'; |
|
153 |
+ } |
|
154 |
+ } |
|
155 |
+ |
|
156 |
+ // Do staff just want general notifications about everything? Don't change things if they already had a notice though, this is just for the rabble at the back |
|
157 |
+ if (!empty($modSettings['shd_notify_new_reply_any'])) |
|
158 |
+ { |
|
159 |
+ foreach ($staff as $id) |
|
160 |
+ { |
|
161 |
+ if (empty($members[$id])) |
|
162 |
+ $members[$id] = 'new_reply_any'; |
|
163 |
+ } |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ if (empty($members)) |
|
167 |
+ return; |
|
168 |
+ |
|
169 |
+ if (!empty($members[$context['user']['id']])) |
|
170 |
+ unset($members[$context['user']['id']]); |
|
171 |
+ |
|
172 |
+ // Get the default preference (since this is controlled by plugin, i.e. here, we could just hardcode it, but in case someone modifies the default, let's load it from here) |
|
173 |
+ $pref_groups = array(); |
|
174 |
+ $base_prefs = array(); |
|
175 |
+ shd_notifications_prefs($pref_groups, $base_prefs); |
|
176 |
+ |
|
177 |
+ // Build a list of users -> default prefs |
|
178 |
+ $member_prefs = array(); |
|
179 |
+ foreach ($members as $id => $type) |
|
180 |
+ $member_prefs[$id] = $base_prefs['notify_' . $type]['default']; |
|
181 |
+ |
|
182 |
+ // Grab pref list from DB for these users and update |
|
183 |
+ $pref_list = array_unique(array_keys($members)); |
|
184 |
+ $query = $smcFunc['db_query']('', ' |
|
185 |
+ SELECT id_member, variable, value |
|
186 |
+ FROM {db_prefix}helpdesk_preferences |
|
187 |
+ WHERE id_member IN ({array_int:members}) |
|
188 |
+ AND variable IN ({array_string:variables})', |
|
189 |
+ array( |
|
190 |
+ 'members' => array_keys($members), |
|
191 |
+ 'variables' => $pref_list, |
|
192 |
+ ) |
|
193 |
+ ); |
|
194 |
+ |
|
195 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
196 |
+ { |
|
197 |
+ $row['id_member'] = (int) $row['id_member']; |
|
198 |
+ if ($row['variable'] == 'notify_' . $members[$row['id_member']]) |
|
199 |
+ $member_prefs[$id] = $row['value']; |
|
200 |
+ } |
|
201 |
+ $smcFunc['db_free_result']($query); |
|
202 |
+ |
|
203 |
+ // unset $members where member pref doesn't fit |
|
204 |
+ foreach ($member_prefs as $id => $value) |
|
205 |
+ { |
|
206 |
+ if (empty($value)) |
|
207 |
+ unset($members[$id]); |
|
208 |
+ } |
|
209 |
+ |
|
210 |
+ // move $members to $notify_data['members'] |
|
211 |
+ $notify_data['members'] = $members; |
|
212 |
+ |
|
213 |
+ // AAAAAAAAAAAAND WE'RE OFF! |
|
214 |
+ if (!empty($notify_data['members'])) |
|
215 |
+ shd_notify_users($notify_data); |
|
216 |
+} |
|
217 |
+ |
|
218 |
+function shd_notifications_notify_assign(&$ticket, &$assignment) |
|
219 |
+{ |
|
220 |
+ global $smcFunc, $context, $modSettings, $scripturl; |
|
221 |
+ |
|
222 |
+ if (!in_array('email_notifications', $context['shd_plugins']) || (empty($modSettings['shd_notify_assign_me']) && empty($modSettings['shd_notify_assign_own']))) |
|
223 |
+ return; |
|
224 |
+ |
|
225 |
+ $ticketinfo = shd_load_ticket($ticket); |
|
226 |
+ // ticket starter = $ticketinfo['starter_id'] |
|
227 |
+ // $assignment = user id of assignee (0 for no longer being assigned) |
|
228 |
+ |
|
229 |
+ $notify_data = array( |
|
230 |
+ 'members' => array(), |
|
231 |
+ 'ticketlink' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticket . '.0', |
|
232 |
+ 'subject' => $ticketinfo['subject'], |
|
233 |
+ ); |
|
234 |
+ |
|
235 |
+ // Get the default preference (since this is controlled by plugin, i.e. here, we could just hardcode it, but in case someone modifies the default, let's load it from here) |
|
236 |
+ $pref_groups = array(); |
|
237 |
+ $base_prefs = array(); |
|
238 |
+ shd_notifications_prefs($pref_groups, $base_prefs); |
|
239 |
+ |
|
240 |
+ $members = array(); |
|
241 |
+ $member_prefs = array(); |
|
242 |
+ // So, does the starter want to be notified if the ticket is assigned? |
|
243 |
+ if (!empty($ticketinfo['starter_id']) && !empty($modSettings['shd_notify_assign_own'])) |
|
244 |
+ { |
|
245 |
+ $members[$ticketinfo['starter_id']] = 'assign_own'; |
|
246 |
+ $member_prefs[$ticketinfo['starter_id']] = $base_prefs['notify_assign_own']['default']; |
|
247 |
+ } |
|
248 |
+ |
|
249 |
+ // Does the assignee want to be notified? This assumes it is actually a person... |
|
250 |
+ if (!empty($assignment) && !empty($modSettings['shd_notify_assign_me'])) |
|
251 |
+ { |
|
252 |
+ $members[$assignment] = 'assign_me'; |
|
253 |
+ $member_prefs[$assignment] = $base_prefs['notify_assign_me']['default']; |
|
254 |
+ } |
|
255 |
+ |
|
256 |
+ if (empty($members)) |
|
257 |
+ return; // whoops |
|
258 |
+ |
|
259 |
+ // OK, so we've figured out what we'd send to folks. Now let's see what the users want |
|
260 |
+ $query = $smcFunc['db_query']('', ' |
|
261 |
+ SELECT id_member, variable, value |
|
262 |
+ FROM {db_prefix}helpdesk_preferences |
|
263 |
+ WHERE id_member IN ({array_int:members}) |
|
264 |
+ AND variable IN ({array_string:variables})', |
|
265 |
+ array( |
|
266 |
+ 'members' => array_keys($members), |
|
267 |
+ 'variables' => array('assign_me', 'assign_own'), |
|
268 |
+ ) |
|
269 |
+ ); |
|
270 |
+ |
|
271 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
272 |
+ { |
|
273 |
+ $row['id_member'] = (int) $row['id_member']; |
|
274 |
+ if ($row['variable'] == 'notify_' . $members[$row['id_member']]) |
|
275 |
+ $member_prefs[$id] = $row['value']; |
|
276 |
+ } |
|
277 |
+ $smcFunc['db_free_result']($query); |
|
278 |
+ |
|
279 |
+ // unset $members where member pref doesn't fit |
|
280 |
+ foreach ($member_prefs as $id => $value) |
|
281 |
+ { |
|
282 |
+ if (empty($value)) |
|
283 |
+ unset($members[$id]); |
|
284 |
+ } |
|
285 |
+ |
|
286 |
+ // move $members to $notify_data['members'] |
|
287 |
+ $notify_data['members'] = $members; |
|
288 |
+ |
|
289 |
+ // AAAAAAAAAAAAND WE'RE OFF! |
|
290 |
+ if (!empty($notify_data['members'])) |
|
291 |
+ shd_notify_users($notify_data); |
|
292 |
+} |
|
293 |
+ |
|
294 |
+/** |
|
295 |
+ * Handle email notifications |
|
296 |
+ * |
|
297 |
+ * @todo Finish documenting |
|
298 |
+ * @since 1.1 |
|
299 |
+*/ |
|
300 |
+function shd_notify_users($notify_data) |
|
301 |
+{ |
|
302 |
+ global $context, $txt, $modSettings, $language, $smcFunc, $sourcedir; |
|
303 |
+ |
|
304 |
+ if (empty($notify_data['members'])) |
|
305 |
+ return; |
|
306 |
+ |
|
307 |
+ // So, for the folks we're sending a message to, figure out what languages etc we're loading |
|
308 |
+ $notify_lang = array(); |
|
309 |
+ $emails = array(); |
|
310 |
+ $query = $smcFunc['db_query']('', ' |
|
311 |
+ SELECT id_member, lngfile, email_address |
|
312 |
+ FROM {db_prefix}members |
|
313 |
+ WHERE id_member IN ({array_int:members})', |
|
314 |
+ array( |
|
315 |
+ 'members' => array_keys($notify_data['members']), |
|
316 |
+ ) |
|
317 |
+ ); |
|
318 |
+ |
|
319 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
320 |
+ { |
|
321 |
+ $needed_language = empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']; |
|
322 |
+ if (empty($notify_lang[$needed_language])) |
|
323 |
+ $notify_lang[$needed_language] = array(); |
|
324 |
+ |
|
325 |
+ $notify_lang[$needed_language][] = $row['id_member']; |
|
326 |
+ $emails[$row['id_member']] = $row['email_address']; |
|
327 |
+ } |
|
328 |
+ $smcFunc['db_free_result']($query); |
|
329 |
+ |
|
330 |
+ // So, at this point, we have our list of language files to load so we can minimise the amount of actual work going on, and let's get ready |
|
331 |
+ $replacements = array( |
|
332 |
+ '{subject}' => $notify_data['subject'], |
|
333 |
+ '{ticketlink}' => $notify_data['ticketlink'], |
|
334 |
+ ); |
|
335 |
+ |
|
336 |
+ // Also note, we may not be coming from the post code... so make sure sendmail() is available |
|
337 |
+ if (!function_exists('sendmail')) |
|
338 |
+ require($sourcedir . '/Subs-Post.php'); |
|
339 |
+ |
|
340 |
+ foreach ($notify_lang as $this_lang => $lang_members) |
|
341 |
+ { |
|
342 |
+ shd_load_language('SDPluginEmailNotifications', $this_lang); |
|
343 |
+ |
|
344 |
+ foreach ($lang_members as $member) |
|
345 |
+ { |
|
346 |
+ $email_type = $notify_data['members'][$member]; |
|
347 |
+ |
|
348 |
+ $subject = str_replace(array_keys($replacements), array_values($replacements), $txt['template_subject_notify_' . $email_type]); |
|
349 |
+ |
|
350 |
+ $body = $txt['template_body_notify_' . $email_type] . "\n\n" . $txt['regards_team']; |
|
351 |
+ $body = str_replace(array_keys($replacements), array_values($replacements), $body); |
|
352 |
+ |
|
353 |
+ //function sendmail($to, $subject, $message, $from = null, $message_id = null, $send_html = false, $priority = 3, $hotmail_fix = null, $is_private = false) |
|
354 |
+ sendmail($emails[$member], $subject, $body, null, 'shd_notify_' . $email_type . '_' . $member); |
|
355 |
+ } |
|
356 |
+ } |
|
357 |
+} |
|
358 |
+ |
|
359 |
+/** |
|
360 |
+ * Displays notifications options within SD ACP / Options / Notifications |
|
361 |
+ * |
|
362 |
+ * <ul> |
|
363 |
+ * <li>'shd_notify_new_ticket' (checkbox) - if checked, staff have the option of being notified when a new ticket is posted</li> |
|
364 |
+ * <li>'shd_notify_new_reply_own' (checkbox) - if checked, users have the option to have notifications upon reply to any ticket they started</li> |
|
365 |
+ * <li>'shd_notify_new_reply_assigned' (checkbox) - if checked, staff have the option to select notifications upon reply to any ticket assigned to them</li> |
|
366 |
+ * <li>'shd_notify_new_reply_previous' (checkbox) - if checked, staff have the option to select notifications upon reply to any ticket they already replied to</li> |
|
367 |
+ * <li>'shd_notify_new_reply_any' (checkbox) - if checked, staff have the option to select notifications upon any reply to any ticket they can see</li> |
|
368 |
+ * <li>'shd_notify_assign_me' (checkbox) - if checked, staff have the option to have notifications sent to them when tickets are assigned to them</li> |
|
369 |
+ * <li>'shd_notify_assign_own' (checkbox) - if checked, users have the option to be notified when one of their tickets is assigned to a staff member</li> |
|
370 |
+ * </ul> |
|
371 |
+ * |
|
372 |
+ * @param bool $return_config Whether to return configuration items or not; this is provided solely for SMF ACP compatibility (it expects to pass bool true in to get a list of options) |
|
373 |
+ * |
|
374 |
+ * @return array An array of items that make up the search options on the given admin page, each item is itself an array of (type, option name/language string, [other related information]) |
|
375 |
+*/ |
|
376 |
+function shd_modify_notifications_options($return_config) |
|
377 |
+{ |
|
378 |
+ global $context, $modSettings, $txt; |
|
379 |
+ |
|
380 |
+ $config_vars = array( |
|
381 |
+ array('check', 'shd_notify_new_ticket'), |
|
382 |
+ array('check', 'shd_notify_new_reply_own'), |
|
383 |
+ array('check', 'shd_notify_new_reply_assigned'), |
|
384 |
+ array('check', 'shd_notify_new_reply_previous'), |
|
385 |
+ array('check', 'shd_notify_new_reply_any'), |
|
386 |
+ array('check', 'shd_notify_assign_me'), |
|
387 |
+ array('check', 'shd_notify_assign_own'), |
|
388 |
+ ); |
|
389 |
+ $context['settings_title'] = $txt['shd_admin_options_notifications']; |
|
390 |
+ $context['settings_icon'] = 'email.png'; |
|
391 |
+ |
|
392 |
+ // If we're being called from admin search, just return stuff |
|
393 |
+ if ($return_config) |
|
394 |
+ return $config_vars; |
|
395 |
+ |
|
396 |
+ // Otherwise... this is where things get... interesting. |
|
397 |
+ $subtext = array( |
|
398 |
+ 'shd_notify_new_ticket' => '', |
|
399 |
+ 'shd_notify_new_reply_own' => $txt['shd_notify_send_to'] . ': ' . $txt['shd_notify_ticket_starter'], |
|
400 |
+ 'shd_notify_new_reply_assigned' => '', |
|
401 |
+ 'shd_notify_new_reply_previous' => '', |
|
402 |
+ 'shd_notify_new_reply_any' => '', |
|
403 |
+ 'shd_notify_assign_me' => '', |
|
404 |
+ 'shd_notify_assign_own' => $txt['shd_notify_send_to'] . ': ' . $txt['shd_notify_ticket_starter'], |
|
405 |
+ ); |
|
406 |
+ |
|
407 |
+ $staff = shd_members_allowed_to('shd_staff'); |
|
408 |
+ |
|
409 |
+ foreach ($config_vars as $id => $item) |
|
410 |
+ { |
|
411 |
+ list(, $item_id) = $item; |
|
412 |
+ if (!empty($subtext[$item_id])) |
|
413 |
+ $config_vars[$id]['subtext'] = $subtext[$item_id]; |
|
414 |
+ } |
|
415 |
+ |
|
416 |
+ return $config_vars; |
|
417 |
+} |
|
418 |
+ |
|
419 |
+function shd_notifications_adminmenu(&$admin_areas) |
|
420 |
+{ |
|
421 |
+ global $context, $modSettings, $txt; |
|
422 |
+ |
|
423 |
+ // Enabled? |
|
424 |
+ if (!in_array('email_notifications', $context['shd_plugins'])) |
|
425 |
+ return; |
|
426 |
+ |
|
427 |
+ $admin_areas['helpdesk_info']['areas']['helpdesk_options']['subsections']['notifications'] = array($txt['shd_admin_options_notifications']); |
|
428 |
+} |
|
429 |
+ |
|
430 |
+function shd_notifications_hdadminopts() |
|
431 |
+{ |
|
432 |
+ global $context, $modSettings, $txt; |
|
433 |
+ |
|
434 |
+ // Enabled? |
|
435 |
+ if (!in_array('email_notifications', $context['shd_plugins'])) |
|
436 |
+ return; |
|
437 |
+ |
|
438 |
+ $context[$context['admin_menu_name']]['tab_data']['tabs']['notifications'] = array( |
|
439 |
+ 'description' => $txt['shd_admin_options_notifications_desc'], |
|
440 |
+ 'function' => 'shd_modify_notifications_options', |
|
441 |
+ ); |
|
442 |
+} |
|
443 |
+ |
|
444 |
+function shd_notifications_hdadminoptssrch(&$settings_search) |
|
445 |
+{ |
|
446 |
+ global $context, $modSettings; |
|
447 |
+ |
|
448 |
+ // Enabled? |
|
449 |
+ if (!in_array('email_notifications', $context['shd_plugins'])) |
|
450 |
+ return; |
|
451 |
+ |
|
452 |
+ $settings_search[] = array('shd_modify_notifications_options', 'area=helpdesk_options;sa=notifications'); |
|
453 |
+} |
|
454 |
+ |
|
455 |
+function shd_notifications_prefs(&$pref_groups, &$base_prefs) |
|
456 |
+{ |
|
457 |
+ global $context, $modSettings; |
|
458 |
+ |
|
459 |
+ // Enabled? |
|
460 |
+ if (!in_array('email_notifications', $context['shd_plugins'])) |
|
461 |
+ return; |
|
462 |
+ |
|
463 |
+ $pref_groups += array( |
|
464 |
+ 'notify' => array( |
|
465 |
+ 'icon' => 'email.png', |
|
466 |
+ 'enabled' => true, |
|
467 |
+ ), |
|
468 |
+ ); |
|
469 |
+ |
|
470 |
+ $base_prefs += array( |
|
471 |
+ 'notify_new_ticket' => array( |
|
472 |
+ 'default' => 1, |
|
473 |
+ 'type' => 'check', |
|
474 |
+ 'icon' => 'log_newticket.png', |
|
475 |
+ 'group' => 'notify', |
|
476 |
+ 'permission' => 'shd_staff', |
|
477 |
+ 'show' => !empty($modSettings['shd_notify_new_ticket']), |
|
478 |
+ ), |
|
479 |
+ 'notify_new_reply_own' => array( |
|
480 |
+ 'default' => 1, |
|
481 |
+ 'type' => 'check', |
|
482 |
+ 'icon' => 'log_newreply.png', |
|
483 |
+ 'group' => 'notify', |
|
484 |
+ 'permission' => 'shd_new_ticket', |
|
485 |
+ 'show' => !empty($modSettings['shd_notify_new_reply_own']), |
|
486 |
+ ), |
|
487 |
+ 'notify_new_reply_assigned' => array( |
|
488 |
+ 'default' => 1, |
|
489 |
+ 'type' => 'check', |
|
490 |
+ 'icon' => 'log_assign.png', |
|
491 |
+ 'group' => 'notify', |
|
492 |
+ 'permission' => 'shd_staff', |
|
493 |
+ 'show' => !empty($modSettings['shd_notify_new_reply_assigned']), |
|
494 |
+ ), |
|
495 |
+ 'notify_new_reply_previous' => array( |
|
496 |
+ 'default' => 1, |
|
497 |
+ 'type' => 'check', |
|
498 |
+ 'icon' => 'log_newreply.png', |
|
499 |
+ 'group' => 'notify', |
|
500 |
+ 'permission' => 'shd_staff', |
|
501 |
+ 'show' => !empty($modSettings['shd_notify_new_reply_previous']), |
|
502 |
+ ), |
|
503 |
+ 'notify_new_reply_any' => array( |
|
504 |
+ 'default' => 1, |
|
505 |
+ 'type' => 'check', |
|
506 |
+ 'icon' => 'log_newreply.png', |
|
507 |
+ 'group' => 'notify', |
|
508 |
+ 'permission' => 'shd_staff', |
|
509 |
+ 'show' => !empty($modSettings['shd_notify_new_reply_any']), |
|
510 |
+ ), |
|
511 |
+ 'notify_assign_me' => array( |
|
512 |
+ 'default' => 1, |
|
513 |
+ 'type' => 'check', |
|
514 |
+ 'icon' => 'assign.png', |
|
515 |
+ 'group' => 'notify', |
|
516 |
+ 'permission' => 'shd_staff', |
|
517 |
+ 'show' => !empty($modSettings['shd_notify_assign_me']), |
|
518 |
+ ), |
|
519 |
+ 'notify_assign_own' => array( |
|
520 |
+ 'default' => 1, |
|
521 |
+ 'type' => 'check', |
|
522 |
+ 'icon' => 'assign.png', |
|
523 |
+ 'group' => 'notify', |
|
524 |
+ 'permission' => 'shd_new_ticket', |
|
525 |
+ 'show' => !empty($modSettings['shd_notify_assign_own']), |
|
526 |
+ ), |
|
527 |
+ ); |
|
528 |
+} |
|
529 |
+ |
|
530 |
+?> |
|
0 | 531 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,84 @@ |
1 |
+<?php |
|
2 |
+################################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+# Email Notifications Plugin # |
|
5 |
+################################################################### |
|
6 |
+# An advanced help desk modifcation built on SMF # |
|
7 |
+################################################################### |
|
8 |
+# # |
|
9 |
+# * Copyright 2010 - SimpleDesk.net # |
|
10 |
+# # |
|
11 |
+# This file and its contents are subject to the license # |
|
12 |
+# included with this distribution, license.txt, which # |
|
13 |
+# states that this software is New BSD Licensed. # |
|
14 |
+# Any questions, please contact SimpleDesk.net # |
|
15 |
+# # |
|
16 |
+################################################################### |
|
17 |
+# SimpleDesk Version: 1.0 Felidae # |
|
18 |
+# File Info: index.php / 1.0 Felidae # |
|
19 |
+################################################################### |
|
20 |
+ |
|
21 |
+/** |
|
22 |
+ * @package plugin-emailnotifications |
|
23 |
+ * @since 1.1 |
|
24 |
+*/ |
|
25 |
+ |
|
26 |
+if (!defined('SHD_VERSION')) |
|
27 |
+ die('Hacking attempt...'); |
|
28 |
+ |
|
29 |
+/* |
|
30 |
+ * Return information about this plugin. |
|
31 |
+ * |
|
32 |
+ * details |
|
33 |
+ * - name: a $txt reference for the plugin's name (so it can be translated), if not present as a $txt will be used as a literal. (Note, see includes - language below) |
|
34 |
+ * - description: a $txt reference one line description of the mod (translatable) - if not present, it will be used as a literal. |
|
35 |
+ * - author: Author's name, literal |
|
36 |
+ * - website: Website to link back to the author |
|
37 |
+ * - version: Plugin version |
|
38 |
+ * - compatibility: Array of supported SD version-strings |
|
39 |
+ * |
|
40 |
+ * includes |
|
41 |
+ * - source: a key-value pair array of file names to include at strategic points, key name is the point to include it on, value is a filename or array of filenames to include within the plugin's dir |
|
42 |
+ * - language: a key-value pair of array of language files to include, much like source. |
|
43 |
+ * |
|
44 |
+ * hooks |
|
45 |
+ * - key-value pair of hook name to function name or array of function names to be called at the hook point |
|
46 |
+ * |
|
47 |
+ * @since 1.1 |
|
48 |
+*/ |
|
49 |
+function shdplugin_email_notifications() |
|
50 |
+{ |
|
51 |
+ return array( |
|
52 |
+ 'details' => array( // general plugin details |
|
53 |
+ 'title' => 'email_notifications', |
|
54 |
+ 'description' => 'email_notifications_desc', |
|
55 |
+ 'author' => 'SimpleDesk Team', |
|
56 |
+ 'website' => 'http://www.simpledesk.net/', |
|
57 |
+ 'version' => '1.0', |
|
58 |
+ 'compatibility' => array( |
|
59 |
+ 'SimpleDesk 1.0 Felidae', // should tie up with the SHD_VERSION constants |
|
60 |
+ ), |
|
61 |
+ 'acp_url' => 'action=admin;area=helpdesk_options;sa=notifications', |
|
62 |
+ ), |
|
63 |
+ 'includes' => array( |
|
64 |
+ 'source' => array( |
|
65 |
+ 'init' => 'SDPluginEmailNotifications.php', |
|
66 |
+ ), |
|
67 |
+ 'language' => array( |
|
68 |
+ 'hdadmin' => 'SDPluginEmailNotifications', |
|
69 |
+ 'hdprofile' => 'SDPluginEmailNotifications', |
|
70 |
+ ), |
|
71 |
+ ), |
|
72 |
+ 'hooks' => array( // what functions to call when |
|
73 |
+ 'hdadminopts' => 'shd_notifications_hdadminopts', |
|
74 |
+ 'hdadminoptssrch' => 'shd_notifications_hdadminoptssrch', |
|
75 |
+ 'adminmenu' => 'shd_notifications_adminmenu', |
|
76 |
+ 'prefs' => 'shd_notifications_prefs', |
|
77 |
+ 'newticket' => 'shd_notifications_notify_newticket', |
|
78 |
+ 'newreply' => 'shd_notifications_notify_newreply', |
|
79 |
+ 'assign' => 'shd_notifications_notify_assign', |
|
80 |
+ ), |
|
81 |
+ ); |
|
82 |
+} |
|
83 |
+ |
|
84 |
+?> |
|
0 | 85 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,16 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+// This file is here solely to protect your plugins' source directory. |
|
4 |
+ |
|
5 |
+// Look for Settings.php.... |
|
6 |
+if (file_exists(dirname(dirname(dirname(__FILE__))) . '/Settings.php')) |
|
7 |
+{ |
|
8 |
+ // Found it! |
|
9 |
+ require(dirname(dirname(dirname(__FILE__))) . '/Settings.php'); |
|
10 |
+ header('Location: ' . $boardurl); |
|
11 |
+} |
|
12 |
+// Can't find it... just forget it. |
|
13 |
+else |
|
14 |
+ exit; |
|
15 |
+ |
|
16 |
+?> |
|
0 | 17 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,16 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+// This file is here solely to protect your plugins' template directory. |
|
4 |
+ |
|
5 |
+// Look for Settings.php.... |
|
6 |
+if (file_exists(dirname(dirname(dirname(__FILE__))) . '/Settings.php')) |
|
7 |
+{ |
|
8 |
+ // Found it! |
|
9 |
+ require(dirname(dirname(dirname(__FILE__))) . '/Settings.php'); |
|
10 |
+ header('Location: ' . $boardurl); |
|
11 |
+} |
|
12 |
+// Can't find it... just forget it. |
|
13 |
+else |
|
14 |
+ exit; |
|
15 |
+ |
|
16 |
+?> |
|
0 | 17 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,775 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Admin.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles the core of SimpleDesk's administrative information and options from within SMF's own admin panel. |
|
22 |
+ * |
|
23 |
+ * @package source |
|
24 |
+ * @since 1.0 |
|
25 |
+*/ |
|
26 |
+if (!defined('SMF')) |
|
27 |
+ die('Hacking attempt...'); |
|
28 |
+ |
|
29 |
+/** |
|
30 |
+ * The start point for all interaction with the SimpleDesk administration area. |
|
31 |
+ * |
|
32 |
+ * Enforces that users attempting to access the area have either forum or helpdesk administrative privileges, loads the SimpleDesk |
|
33 |
+ * administrative CSS and Javascript and promptly directs users to the specific function for the task they are performing. |
|
34 |
+ * |
|
35 |
+ * @since 1.0 |
|
36 |
+*/ |
|
37 |
+function shd_admin_main() |
|
38 |
+{ |
|
39 |
+ global $context, $scripturl, $sourcedir, $settings, $txt, $modSettings; |
|
40 |
+ |
|
41 |
+ shd_init(); |
|
42 |
+ shd_load_language('SimpleDeskAdmin'); |
|
43 |
+ |
|
44 |
+ // Kick them in the kneecaps! |
|
45 |
+ if (!shd_allowed_to('admin_helpdesk')) |
|
46 |
+ isAllowedTo('admin_forum'); |
|
47 |
+ |
|
48 |
+ // Templates and stuff (like hook files) |
|
49 |
+ loadTemplate('sd_template/SimpleDesk-Admin'); |
|
50 |
+ $context['shd_preferences'] = shd_load_user_prefs(); |
|
51 |
+ shd_load_plugin_files('hdadmin'); |
|
52 |
+ shd_load_plugin_langfiles('hdadmin'); |
|
53 |
+ |
|
54 |
+ // Load some extra CSS |
|
55 |
+ $context['html_headers'] .= ' |
|
56 |
+ <link rel="stylesheet" type="text/css" href="' . $settings['default_theme_url'] . '/css/helpdesk_admin.css" /> |
|
57 |
+ <link rel="stylesheet" type="text/css" href="' . $settings['default_theme_url'] . '/css/helpdesk.css" /> |
|
58 |
+ <script type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/helpdesk_admin.js?rc2"></script>'; |
|
59 |
+ $context['page_title'] = $txt['shd_admin_title']; |
|
60 |
+ |
|
61 |
+ // We need this for later |
|
62 |
+ require_once($sourcedir . '/ManageServer.php'); |
|
63 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskAdmin.php'); |
|
64 |
+ |
|
65 |
+ // Create some subactions |
|
66 |
+ $subActions = array( |
|
67 |
+ 'helpdesk_info' => array(null, 'shd_admin_info'), |
|
68 |
+ 'helpdesk_options' => array(null, 'shd_admin_options'), |
|
69 |
+ 'helpdesk_customfield' => array('SimpleDesk-AdminCustomField.php', 'shd_admin_custom'), |
|
70 |
+ 'helpdesk_permissions' => array('SimpleDesk-AdminPermissions.php', 'shd_admin_permissions'), |
|
71 |
+ 'helpdesk_plugins' => array('SimpleDesk-AdminPlugins.php', 'shd_admin_plugins'), |
|
72 |
+ ); |
|
73 |
+ |
|
74 |
+ // Int hooks - after we basically set everything up (so it's manipulatable by the hook, but before we do the last bits of finalisation) |
|
75 |
+ if (!empty($modSettings['shd_hook_hdadmin'])) |
|
76 |
+ { |
|
77 |
+ $functions = explode(',', $modSettings['shd_hook_hdadmin']); |
|
78 |
+ foreach ($functions as $function) |
|
79 |
+ { |
|
80 |
+ if (is_callable($function)) |
|
81 |
+ $function($subActions); // this should be picked up by reference in the called function or it won't do anything! |
|
82 |
+ } |
|
83 |
+ } |
|
84 |
+ |
|
85 |
+ // Make sure we can find a subaction. If not set, default to info |
|
86 |
+ $_REQUEST['area'] = isset($_REQUEST['area']) && isset($subActions[$_REQUEST['area']]) ? $_REQUEST['area'] : 'helpdesk_info'; |
|
87 |
+ $context['sub_action'] = $_REQUEST['area']; |
|
88 |
+ |
|
89 |
+ if (!empty($subActions[$_REQUEST['area']][0])) |
|
90 |
+ require ($sourcedir . '/sd_source/' . $subActions[$_REQUEST['area']][0]); |
|
91 |
+ |
|
92 |
+ // Call our subaction |
|
93 |
+ if ($_REQUEST['area'] == 'helpdesk_options') |
|
94 |
+ $subActions[$_REQUEST['area']][1](false); |
|
95 |
+ else |
|
96 |
+ $subActions[$_REQUEST['area']][1](); |
|
97 |
+ |
|
98 |
+ // Important ACS666 check up. |
|
99 |
+ if (isset($_REQUEST['cookies'])) |
|
100 |
+ shd_do_important(); |
|
101 |
+ |
|
102 |
+ // Maintenance mode? If it were, the helpdesk is considered inactive for the purposes of everything to all but those without admin-helpdesk rights - but we must have them if we're here! |
|
103 |
+ if (!empty($modSettings['shd_maintenance_mode'])) |
|
104 |
+ { |
|
105 |
+ loadTemplate('sd_template/SimpleDesk'); |
|
106 |
+ $temp_layers = $context['template_layers']; |
|
107 |
+ $context['template_layers'] = array(); |
|
108 |
+ foreach ($temp_layers as $layer) |
|
109 |
+ { |
|
110 |
+ $context['template_layers'][] = $layer; |
|
111 |
+ if ($layer == 'body') |
|
112 |
+ $context['template_layers'][] = 'shd_maintenance'; |
|
113 |
+ } |
|
114 |
+ } |
|
115 |
+} |
|
116 |
+ |
|
117 |
+/** |
|
118 |
+ * Loads the main SimpleDesk information page for forum administrators. |
|
119 |
+ * |
|
120 |
+ * This function is the main focus point for information about SimpleDesk in the admin panel, primarily it collects the following for the template: |
|
121 |
+ * <ul> |
|
122 |
+ * <li>list of helpdesk staff</li> |
|
123 |
+ * <li>totals of tickets in the system (open/closed/deleted)</li> |
|
124 |
+ * <li>credits</li> |
|
125 |
+ * <li>also, in the template, whether this is a current or outdated version of SimpleDesk</li> |
|
126 |
+ * </ul> |
|
127 |
+ * |
|
128 |
+ * Since 1.1, it also receives the requests for subactions for action log and support page (since these are sub menu items) but simply directs them onward. |
|
129 |
+ * |
|
130 |
+ * @see shd_admin_action_log() |
|
131 |
+ * @see shd_admin_support() |
|
132 |
+ * |
|
133 |
+ * @since 1.0 |
|
134 |
+*/ |
|
135 |
+function shd_admin_info() |
|
136 |
+{ |
|
137 |
+ global $context, $settings, $scripturl, $txt, $sourcedir, $smcFunc; |
|
138 |
+ |
|
139 |
+ // No little pixies allowed! |
|
140 |
+ shd_is_allowed_to(array('admin_forum', 'admin_helpdesk')); |
|
141 |
+ |
|
142 |
+ $subactions = array( |
|
143 |
+ 'main' => array( |
|
144 |
+ 'function' => false, |
|
145 |
+ 'icon' => 'simpledesk.png', |
|
146 |
+ 'title' => $txt['shd_admin_info'], |
|
147 |
+ ), |
|
148 |
+ 'actionlog' => array( |
|
149 |
+ 'function' => 'shd_admin_action_log', |
|
150 |
+ 'icon' => 'log.png', |
|
151 |
+ 'title' => $txt['shd_admin_actionlog_title'], |
|
152 |
+ ), |
|
153 |
+ 'support' => array( |
|
154 |
+ 'function' => 'shd_admin_support', |
|
155 |
+ 'icon' => 'support.png', |
|
156 |
+ 'title' => $txt['shd_admin_support'], |
|
157 |
+ ), |
|
158 |
+ ); |
|
159 |
+ $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subactions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'main'; |
|
160 |
+ |
|
161 |
+ $context[$context['admin_menu_name']]['tab_data'] = array( |
|
162 |
+ 'title' => '<img src="' . $settings['images_url'] . '/admin/shd/' . $subactions[$_REQUEST['sa']]['icon'] . '" class="icon" alt="*" />' . $subactions[$_REQUEST['sa']]['title'], |
|
163 |
+ 'description' => $txt['shd_admin_options_desc'], |
|
164 |
+ 'tabs' => array( |
|
165 |
+ 'main' => array( |
|
166 |
+ 'description' => '<strong>' . $txt['hello_guest'] . ' ' . $context['user']['name'] . '!</strong><br />' . $txt['shd_admin_info_desc'], |
|
167 |
+ ), |
|
168 |
+ 'actionlog' => array( |
|
169 |
+ 'description' => $txt['shd_admin_actionlog_desc'] . '<br />' . (!empty($modSettings['shd_disable_action_log']) ? '<span class="smalltext">' . $txt['shd_action_log_disabled'] . '</span>' : ''), |
|
170 |
+ ), |
|
171 |
+ 'support' => array( |
|
172 |
+ 'description' => $txt['shd_admin_support_desc'], |
|
173 |
+ ), |
|
174 |
+ ), |
|
175 |
+ ); |
|
176 |
+ |
|
177 |
+ // Are we doing the main page, or leaving here? |
|
178 |
+ if (!empty($subactions[$_REQUEST['sa']]['function'])) |
|
179 |
+ { |
|
180 |
+ $subactions[$_REQUEST['sa']]['function'](); |
|
181 |
+ return; |
|
182 |
+ } |
|
183 |
+ |
|
184 |
+ // Get a list of the staff members of the helpdesk. |
|
185 |
+ $members = shd_members_allowed_to('shd_staff'); |
|
186 |
+ $query = shd_db_query('', ' |
|
187 |
+ SELECT id_member, real_name |
|
188 |
+ FROM {db_prefix}members |
|
189 |
+ WHERE id_member IN ({array_int:members}) |
|
190 |
+ ORDER BY real_name', |
|
191 |
+ array( |
|
192 |
+ 'members' => $members, |
|
193 |
+ ) |
|
194 |
+ ); |
|
195 |
+ |
|
196 |
+ // Note this just gets everyone, doesn't worry about limiting it - IMO that's something for the template to decide. |
|
197 |
+ $context['staff'] = array(); |
|
198 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
199 |
+ $context['staff'][] = shd_profile_link($row['real_name'], $row['id_member']); |
|
200 |
+ |
|
201 |
+ $smcFunc['db_free_result']($query); |
|
202 |
+ |
|
203 |
+ // Make we sure give these slackers some credit. After all, they made sumfin fer ya! |
|
204 |
+ shd_credits(); |
|
205 |
+ |
|
206 |
+ $context['total_tickets'] = shd_count_helpdesk_tickets(); |
|
207 |
+ $context['open_tickets'] = shd_count_helpdesk_tickets('open'); |
|
208 |
+ $context['closed_tickets'] = shd_count_helpdesk_tickets('closed'); |
|
209 |
+ $context['recycled_tickets'] = shd_count_helpdesk_tickets('recycled'); |
|
210 |
+ |
|
211 |
+ // Final stuff before we go. |
|
212 |
+ $context['page_title'] = $txt['shd_admin_title']; |
|
213 |
+ $context['sub_template'] = 'shd_admin'; |
|
214 |
+} |
|
215 |
+ |
|
216 |
+/** |
|
217 |
+ * Configuration options and save functions generally for SimpleDesk. |
|
218 |
+ * |
|
219 |
+ * This function handles all the sub areas under General Options, and adds the options listed in the relevant functions. In 1.0, all the options were stored in here, but in 1.1 they have been moved into their own functions. |
|
220 |
+ * |
|
221 |
+ * @since 1.0 |
|
222 |
+*/ |
|
223 |
+function shd_admin_options($return_config) |
|
224 |
+{ |
|
225 |
+ global $context, $scripturl, $sourcedir, $txt, $modSettings, $settings; |
|
226 |
+ |
|
227 |
+ $context['settings_pre_javascript'] = ' |
|
228 |
+ function shd_switchable_item(item, state) |
|
229 |
+ { |
|
230 |
+ document.getElementById(item).disabled = state; |
|
231 |
+ document.getElementById("label_" + item).parentNode.className = state ? "disabled" : ""; |
|
232 |
+ } |
|
233 |
+ '; |
|
234 |
+ |
|
235 |
+ $context[$context['admin_menu_name']]['tab_data'] = array( |
|
236 |
+ 'title' => '<img src="' . $settings['default_images_url'] . '/simpledesk/status.png" class="icon" alt="*" />' . $txt['shd_admin_options'], |
|
237 |
+ 'description' => $txt['shd_admin_options_desc'], |
|
238 |
+ 'tabs' => array( |
|
239 |
+ 'display' => array( |
|
240 |
+ 'description' => $txt['shd_admin_options_display_desc'], |
|
241 |
+ 'function' => 'shd_modify_display_options', |
|
242 |
+ ), |
|
243 |
+ 'posting' => array( |
|
244 |
+ 'description' => $txt['shd_admin_options_posting_desc'], |
|
245 |
+ 'function' => 'shd_modify_posting_options', |
|
246 |
+ ), |
|
247 |
+ 'admin' => array( |
|
248 |
+ 'description' => $txt['shd_admin_options_admin_desc'], |
|
249 |
+ 'function' => 'shd_modify_admin_options', |
|
250 |
+ ), |
|
251 |
+ 'standalone' => array( |
|
252 |
+ 'description' => $txt['shd_admin_options_standalone_desc'], |
|
253 |
+ 'function' => 'shd_modify_standalone_options', |
|
254 |
+ ), |
|
255 |
+ 'actionlog' => array( |
|
256 |
+ 'description' => $txt['shd_admin_options_actionlog_desc'], |
|
257 |
+ 'function' => 'shd_modify_actionlog_options', |
|
258 |
+ ), |
|
259 |
+ ), |
|
260 |
+ ); |
|
261 |
+ |
|
262 |
+ // Int hooks - after we basically set everything up (so it's manipulatable by the hook, but before we do the last bits of finalisation) |
|
263 |
+ if (!empty($modSettings['shd_hook_hdadminopts'])) |
|
264 |
+ { |
|
265 |
+ $functions = explode(',', $modSettings['shd_hook_hdadminopts']); |
|
266 |
+ foreach ($functions as $function) |
|
267 |
+ { |
|
268 |
+ if (is_callable($function)) |
|
269 |
+ $function(); // everything should be in $context that we need to touch here |
|
270 |
+ } |
|
271 |
+ } |
|
272 |
+ |
|
273 |
+ $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($context[$context['admin_menu_name']]['tab_data']['tabs'][$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'display'; |
|
274 |
+ |
|
275 |
+ $config_vars = $context[$context['admin_menu_name']]['tab_data']['tabs'][$_REQUEST['sa']]['function']($return_config); |
|
276 |
+ |
|
277 |
+ if ($return_config) |
|
278 |
+ return $config_vars; |
|
279 |
+ |
|
280 |
+ loadTemplate('sd_template/SimpleDesk-Admin'); |
|
281 |
+ $context['sub_template'] = 'shd_show_settings'; |
|
282 |
+ |
|
283 |
+ $context['post_url'] = $scripturl . '?action=admin;area=helpdesk_options;save;sa=' . $_REQUEST['sa']; |
|
284 |
+ |
|
285 |
+ // Saving? |
|
286 |
+ if (isset($_GET['save'])) |
|
287 |
+ { |
|
288 |
+ checkSession(); |
|
289 |
+ $save_vars = $config_vars; |
|
290 |
+ |
|
291 |
+ // If we're saving the posting options, we need to process the BBC tags. |
|
292 |
+ if ($_REQUEST['sa'] == 'posting') |
|
293 |
+ { |
|
294 |
+ |
|
295 |
+ if (!isset($_POST['shd_bbc_enabledTags'])) |
|
296 |
+ $_POST['shd_bbc_enabledTags'] = array(); |
|
297 |
+ elseif (!is_array($_POST['shd_bbc_enabledTags'])) |
|
298 |
+ $_POST['shd_bbc_enabledTags'] = array($_POST['shd_bbc_enabledTags']); |
|
299 |
+ |
|
300 |
+ $_POST['shd_enabled_bbc'] = implode(',', $_POST['shd_bbc_enabledTags']); |
|
301 |
+ |
|
302 |
+ if (empty($_POST['shd_enabled_bbc'])) |
|
303 |
+ $_POST['shd_enabled_bbc'] = 'shd_all_tags_disabled'; |
|
304 |
+ |
|
305 |
+ $save_vars[] = array('text', 'shd_enabled_bbc'); |
|
306 |
+ } |
|
307 |
+ |
|
308 |
+ saveDBSettings($save_vars); |
|
309 |
+ redirectexit('action=admin;area=helpdesk_options;sa=' . $_REQUEST['sa']); |
|
310 |
+ } |
|
311 |
+ |
|
312 |
+ prepareDBSettingContext($config_vars); |
|
313 |
+} |
|
314 |
+ |
|
315 |
+/** |
|
316 |
+ * Sets up display options for SimpleDesk. |
|
317 |
+ * |
|
318 |
+ * <ul> |
|
319 |
+ * <li>'shd_staff_badge' (dropdown) - selects the type of badge(s) to display: |
|
320 |
+ * <ul> |
|
321 |
+ * <li>nobadge (default): Display no badges, just a small staff icon for staff members</li> |
|
322 |
+ * <li>staffbadge: Display nothing for normal users, and badge/stars for staff</li> |
|
323 |
+ * <li>userbadge: Display nothing for staff and normal badge/staff for regular users</li> |
|
324 |
+ * <li>bothbadge: Display regular badges/stars for both staff and users</li> |
|
325 |
+ * </ul> |
|
326 |
+ * </li> |
|
327 |
+ * <li>'shd_display_avatar' (checkbox) - whether to display avatars in the replies area or not</li> |
|
328 |
+ * <li>'shd_ticketnav_style' (dropdown) - selects the type of navigation in the ticket area: |
|
329 |
+ * <ul> |
|
330 |
+ * <li>sd (default): use the original SimpleDesk style, icons+text in the bar just above the main ticket area</li> |
|
331 |
+ * <li>sdcompact: use the SimpleDesk icons, in the bar just above the main ticket area, but no captions</li> |
|
332 |
+ * <li>smf: use an SMF style button-strip above the ticket menu</li> |
|
333 |
+ * </ul> |
|
334 |
+ * </li> |
|
335 |
+ * |
|
336 |
+ * @param bool $return_config Whether to return configuration items or not; this is provided solely for SMF ACP compatibility (it expects to pass bool true in to get a list of options) |
|
337 |
+ * |
|
338 |
+ * @return array An array of items that make up the search options on the given admin page, each item is itself an array of (type, option name/language string, [other related information]) |
|
339 |
+ * @since 1.0 |
|
340 |
+ * @see shd_admin_options() |
|
341 |
+*/ |
|
342 |
+function shd_modify_display_options($return_config) |
|
343 |
+{ |
|
344 |
+ global $context, $modSettings, $txt; |
|
345 |
+ |
|
346 |
+ $config_vars = array( |
|
347 |
+ array('select', 'shd_staff_badge', array('nobadge' => $txt['shd_staff_badge_nobadge'], 'staffbadge' => $txt['shd_staff_badge_staffbadge'], 'userbadge' => $txt['shd_staff_badge_userbadge'], 'bothbadge' => $txt['shd_staff_badge_bothbadge']), 'subtext' => $txt['shd_staff_badge_note']), |
|
348 |
+ array('check', 'shd_display_avatar'), |
|
349 |
+ array('select', 'shd_ticketnav_style', array('sd' => $txt['shd_ticketnav_style_sd'], 'sdcompact' => $txt['shd_ticketnav_style_sdcompact'], 'smf' => $txt['shd_ticketnav_style_smf']), 'subtext' => $txt['shd_ticketnav_style_note']), |
|
350 |
+ ); |
|
351 |
+ $context['settings_title'] = $txt['shd_admin_options_display']; |
|
352 |
+ $context['settings_icon'] = 'details.png'; |
|
353 |
+ |
|
354 |
+ return $config_vars; |
|
355 |
+} |
|
356 |
+ |
|
357 |
+/** |
|
358 |
+ * General posting options for SimpleDesk. |
|
359 |
+ * |
|
360 |
+ * <ul> |
|
361 |
+ * <li>'shd_thank_you_post' (checkbox) - if checked, use $txt['shd_ticket_posted_body'] (in SimpleDesk.english.php) as a template of a message to display to the user thanking them for their ticket - and advising what's to come later.</li> |
|
362 |
+ * <li>'shd_thank_you_nonstaff' (checkbox) - if checked, when the above option is invoked, only display the message to non staff members when they create their tickets.</li> |
|
363 |
+ * <li>'shd_allow_wikilinks' (checkbox) - enable conversion of [[ticket:123]] into a regular link</li> |
|
364 |
+ * <li>'shd_allow_ticket_bbc' (checkbox) - one-stop enable/disable of bbcode in tickets (see {@link shd_format_text()} for where this is used)</li> |
|
365 |
+ * <li>'shd_allow_ticket_smileys' (checkbox) - one-stop enable/disable of smileys in tickets (see {@link shd_format_text()} for where this is used)</li> |
|
366 |
+ * <li>'shd_attachments_mode' (dropdown) - selects the presentation of attachments to users: |
|
367 |
+ * <ul> |
|
368 |
+ * <li>ticket (default): treat attachments as if they are attached to the ticket overall; do not enforce max number per ticket</li> |
|
369 |
+ * <li>reply: treat all attachments as attached to replies; enforce same limit per reply as with posts normally</li> |
|
370 |
+ * </ul> |
|
371 |
+ * </li> |
|
372 |
+ * <li>'shd_bbc' (bbc) - enable/disable individual BBC tags around the helpdesk (see {@link shd_format_text()} for where this is used)</li> |
|
373 |
+ * </ul> |
|
374 |
+ * |
|
375 |
+ * @param bool $return_config Whether to return configuration items or not; this is provided solely for SMF ACP compatibility (it expects to pass bool true in to get a list of options) |
|
376 |
+ * |
|
377 |
+ * @return array An array of items that make up the search options on the given admin page, each item is itself an array of (type, option name/language string, [other related information]) |
|
378 |
+ * @since 1.0 |
|
379 |
+ * @see shd_admin_options() |
|
380 |
+ * @see shd_format_text() |
|
381 |
+*/ |
|
382 |
+function shd_modify_posting_options($return_config) |
|
383 |
+{ |
|
384 |
+ global $context, $modSettings, $txt; |
|
385 |
+ |
|
386 |
+ $config_vars = array( |
|
387 |
+ array('check', 'shd_thank_you_post', 'javascript' => ' onchange="javascript:switchtyitems();"'), |
|
388 |
+ array('check', 'shd_thank_you_nonstaff', 'disabled' => empty($modSettings['shd_thank_you_post'])), |
|
389 |
+ '', |
|
390 |
+ array('check', 'shd_allow_wikilinks'), |
|
391 |
+ array('check', 'shd_allow_ticket_bbc', 'javascript' => ' onchange="javascript:switchitems();"'), |
|
392 |
+ array('check', 'shd_allow_ticket_smileys'), |
|
393 |
+ array('select', 'shd_attachments_mode', array('ticket' => $txt['shd_attachments_mode_ticket'], 'reply' => $txt['shd_attachments_mode_reply']), 'subtext' => $txt['shd_attachments_mode_note']), |
|
394 |
+ array('bbc', 'shd_bbc', 'subtext' => $txt['shd_bbc_desc'], 'invisible' => empty($modSettings['shd_allow_ticket_bbc']), 'force_div_id' => 'shd_bbc_dt'), |
|
395 |
+ ); |
|
396 |
+ $context['settings_title'] = $txt['shd_admin_options_posting']; |
|
397 |
+ $context['settings_icon'] = 'smiley.png'; |
|
398 |
+ $context['enabled_tags']['shd_bbc'] = !empty($modSettings['shd_enabled_bbc']) ? explode(',', $modSettings['shd_enabled_bbc']) : array(); |
|
399 |
+ $context['available_tags'] = parse_bbc(false); |
|
400 |
+ $context['all_enabled']['shd_bbc'] = count($context['available_tags']) == count($context['enabled_tags']['shd_bbc']) ? 1 : 0; |
|
401 |
+ |
|
402 |
+ if (empty($context['settings_pre_javascript'])) |
|
403 |
+ $context['settings_pre_javascript'] = ''; |
|
404 |
+ |
|
405 |
+ $context['settings_pre_javascript'] .= ' |
|
406 |
+ function switchtyitems() |
|
407 |
+ { |
|
408 |
+ var state = !document.getElementById("shd_thank_you_post").checked; |
|
409 |
+ shd_switchable_item("shd_thank_you_nonstaff", state); |
|
410 |
+ }; |
|
411 |
+ function switchitems() |
|
412 |
+ { |
|
413 |
+ var state = document.getElementById("shd_allow_ticket_bbc").checked; |
|
414 |
+ document.getElementById("shd_bbc_dt").style.display = state ? "" : "none"; |
|
415 |
+ document.getElementById("shd_bbc_dt_dd").style.display = state ? "" : "none"; |
|
416 |
+ }'; |
|
417 |
+ |
|
418 |
+ return $config_vars; |
|
419 |
+} |
|
420 |
+ |
|
421 |
+/** |
|
422 |
+ * General administrative options for SimpleDesk. |
|
423 |
+ * |
|
424 |
+ * <ul> |
|
425 |
+ * <li>'shd_maintenance_mode' (checkbox) - if checked, only forum adminstrators (group 1) and helpdesk admins can see the helpdesk</li> |
|
426 |
+ * <li>'shd_staff_ticket_self' (checkbox) - if checked, a ticket opened by a staff member can be assigned to them to action.</li> |
|
427 |
+ * <li>'shd_admins_not_assignable' (checkbox) - if checked, a ticket cannot be assigned to forum admins, only regular staff. (Since 1.1 only)</li> |
|
428 |
+ * <li>'shd_privacy_display' (dropdown) - whether to display privacy or not: |
|
429 |
+ * <ul> |
|
430 |
+ * <li>smart (default): Display ticket privacy if it's likely to be relevant (if users can alter ticket privacy, and/or see private tickets AND the ticket is private, show it)</li> |
|
431 |
+ * <li>always: Always display ticket privacy; likely to be confusing</li> |
|
432 |
+ * </ul> |
|
433 |
+ * </li> |
|
434 |
+ * <li>'shd_disable_tickettotopic' (checkbox) - if checked, ticket to topic mode is entirely disabled.</li> |
|
435 |
+ * </ul> |
|
436 |
+ * |
|
437 |
+ * @param bool $return_config Whether to return configuration items or not; this is provided solely for SMF ACP compatibility (it expects to pass bool true in to get a list of options) |
|
438 |
+ * |
|
439 |
+ * @return array An array of items that make up the search options on the given admin page, each item is itself an array of (type, option name/language string, [other related information]) |
|
440 |
+ * @since 1.0 |
|
441 |
+ * @see shd_admin_options() |
|
442 |
+*/ |
|
443 |
+function shd_modify_admin_options($return_config) |
|
444 |
+{ |
|
445 |
+ global $context, $modSettings, $txt; |
|
446 |
+ |
|
447 |
+ $config_vars = array( |
|
448 |
+ array('check', 'shd_maintenance_mode'), |
|
449 |
+ array('check', 'shd_staff_ticket_self'), |
|
450 |
+ array('check', 'shd_admins_not_assignable'), |
|
451 |
+ array('select', 'shd_privacy_display', array('smart' => $txt['shd_privacy_display_smart'], 'always' => $txt['shd_privacy_display_always']), 'subtext' => $txt['shd_privacy_display_note']), |
|
452 |
+ array('check' , 'shd_disable_tickettotopic', 'subtext' => $txt['shd_disable_tickettotopic_note'], 'disabled' => !empty($modSettings['shd_helpdesk_only'])), |
|
453 |
+ ); |
|
454 |
+ $context['settings_title'] = $txt['shd_admin_options_admin']; |
|
455 |
+ $context['settings_icon'] = 'admin.png'; |
|
456 |
+ |
|
457 |
+ return $config_vars; |
|
458 |
+} |
|
459 |
+ |
|
460 |
+/** |
|
461 |
+ * Configuration options for Standalone mode. |
|
462 |
+ * |
|
463 |
+ * <ul> |
|
464 |
+ * <li>'shd_helpdesk_only' (checkbox) - if checked, Standalone mode is active.</li> |
|
465 |
+ * <li>'shd_disable_pm' (checkbox) - if checked, personal messages will not be available at all when SimpleDesk is in (active) Standalone mode</li> |
|
466 |
+ * <li>'shd_disable_mlist' (checkbox) - if checked, the memberlist will not be available at all when SimpleDesk is in (active) Standalone mode</li> |
|
467 |
+ * </ul> |
|
468 |
+ * |
|
469 |
+ * @param bool $return_config Whether to return configuration items or not; this is provided solely for SMF ACP compatibility (it expects to pass bool true in to get a list of options) |
|
470 |
+ * |
|
471 |
+ * @return array An array of items that make up the search options on the given admin page, each item is itself an array of (type, option name/language string, [other related information]) |
|
472 |
+ * @since 1.0 |
|
473 |
+ * @see shd_admin_options() |
|
474 |
+*/ |
|
475 |
+function shd_modify_standalone_options($return_config) |
|
476 |
+{ |
|
477 |
+ global $context, $modSettings, $txt; |
|
478 |
+ |
|
479 |
+ $config_vars = array( |
|
480 |
+ array('check', 'shd_helpdesk_only', 'subtext' => $txt['shd_helpdesk_only_note'], 'javascript' => ' onchange="javascript:switchitems();"'), |
|
481 |
+ array('check', 'shd_disable_pm', 'disabled' => empty($modSettings['shd_helpdesk_only'])), |
|
482 |
+ array('check', 'shd_disable_mlist', 'disabled' => empty($modSettings['shd_helpdesk_only'])), |
|
483 |
+ ); |
|
484 |
+ $context['settings_title'] = $txt['shd_admin_options_standalone']; |
|
485 |
+ $context['settings_icon'] = 'standalone.png'; |
|
486 |
+ |
|
487 |
+ if (empty($context['settings_pre_javascript'])) |
|
488 |
+ $context['settings_pre_javascript'] = ''; |
|
489 |
+ |
|
490 |
+ $context['settings_pre_javascript'] .= ' |
|
491 |
+ function switchitems() |
|
492 |
+ { |
|
493 |
+ var state = !document.getElementById("shd_helpdesk_only").checked; |
|
494 |
+ shd_switchable_item("shd_disable_pm", state); |
|
495 |
+ shd_switchable_item("shd_disable_mlist", state); |
|
496 |
+ }'; |
|
497 |
+ |
|
498 |
+ return $config_vars; |
|
499 |
+} |
|
500 |
+ |
|
501 |
+/** |
|
502 |
+ * Provides configuration options for the action log. |
|
503 |
+ * |
|
504 |
+ * <ul> |
|
505 |
+ * <li>'shd_disable_action_log' (checkbox) - if checked, no actions are added to the action log.</li> |
|
506 |
+ * <li>'shd_display_ticket_logs' (checkbox) - if checked, a ticket's specific log is displayed at the foot of the ticket.</li> |
|
507 |
+ * <li>'shd_logopt_newposts' (checkbox) - if checked, a ticket's being creation and subsequent replies will be logged.</li> |
|
508 |
+ * <li>'shd_logopt_editposts' (checkbox) - if checked, a ticket or its replies being edited will be logged.</li> |
|
509 |
+ * <li>'shd_logopt_resolve' (checkbox) - if checked, a ticket's being closed and/or reopened will be logged.</li> |
|
510 |
+ * <li>'shd_logopt_assign' (checkbox) - if checked, a ticket being assigned/reassigned/unassigned will be logged.</li> |
|
511 |
+ * <li>'shd_logopt_privacy' (checkbox) - if checked, ticket privacy changes will be logged.</li> |
|
512 |
+ * <li>'shd_logopt_urgency' (checkbox) - if checked, ticket urgency changes will be logged.</li> |
|
513 |
+ * <li>'shd_logopt_tickettopicmove' (checkbox) - if checked, ticket to topic moves and back will be logged.</li> |
|
514 |
+ * <li>'shd_logopt_delete' (checkbox) - if checked, ticket/reply deletions (not permadelete) will be logged.</li> |
|
515 |
+ * <li>'shd_logopt_restore' (checkbox) - if checked, ticket/reply restores will be logged.</li> |
|
516 |
+ * <li>'shd_logopt_permadelete' (checkbox) - if checked, permadeletes will be logged.</li> |
|
517 |
+ * <li>'shd_logopt_relationships' (checkbox) - if checked, ticket relationship changes will be logged.</li> |
|
518 |
+ * <li>'shd_logopt_split' (checkbox) - if checked, splitting a topic will be logged.</li> |
|
519 |
+ * </ul> |
|
520 |
+ * |
|
521 |
+ * @param bool $return_config Whether to return configuration items or not; this is provided solely for SMF ACP compatibility (it expects to pass bool true in to get a list of options) |
|
522 |
+ * |
|
523 |
+ * @return array An array of items that make up the search options on the given admin page, each item is itself an array of (type, option name/language string, [other related information]) |
|
524 |
+ * @since 1.0 |
|
525 |
+ * @see shd_admin_options() |
|
526 |
+*/ |
|
527 |
+function shd_modify_actionlog_options($return_config) |
|
528 |
+{ |
|
529 |
+ global $context, $modSettings, $txt; |
|
530 |
+ |
|
531 |
+ $config_vars = array( |
|
532 |
+ array('check', 'shd_disable_action_log', 'javascript' => ' onchange="javascript:switchitems();"'), |
|
533 |
+ array('check', 'shd_display_ticket_logs', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
534 |
+ '', |
|
535 |
+ array('check', 'shd_logopt_newposts', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
536 |
+ array('check', 'shd_logopt_editposts', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
537 |
+ array('check', 'shd_logopt_resolve', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
538 |
+ array('check', 'shd_logopt_assign', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
539 |
+ array('check', 'shd_logopt_privacy', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
540 |
+ array('check', 'shd_logopt_urgency', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
541 |
+ array('check', 'shd_logopt_tickettopicmove', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
542 |
+ array('check', 'shd_logopt_delete', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
543 |
+ array('check', 'shd_logopt_restore', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
544 |
+ array('check', 'shd_logopt_permadelete', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
545 |
+ array('check', 'shd_logopt_relationships', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
546 |
+ array('check', 'shd_logopt_split', 'disabled' => !empty($modSettings['shd_disable_action_log'])), |
|
547 |
+ ); |
|
548 |
+ $context['settings_title'] = $txt['shd_admin_options_actionlog']; |
|
549 |
+ $context['settings_icon'] = 'log.png'; |
|
550 |
+ |
|
551 |
+ if (empty($context['settings_pre_javascript'])) |
|
552 |
+ $context['settings_pre_javascript'] = ''; |
|
553 |
+ |
|
554 |
+ $context['settings_pre_javascript'] .= ' |
|
555 |
+ function switchitems() |
|
556 |
+ { |
|
557 |
+ var state = document.getElementById("shd_disable_action_log").checked; |
|
558 |
+ shd_switchable_item("shd_display_ticket_logs", state); |
|
559 |
+ shd_switchable_item("shd_logopt_newposts", state); |
|
560 |
+ shd_switchable_item("shd_logopt_editposts", state); |
|
561 |
+ shd_switchable_item("shd_logopt_resolve", state); |
|
562 |
+ shd_switchable_item("shd_logopt_assign", state); |
|
563 |
+ shd_switchable_item("shd_logopt_privacy", state); |
|
564 |
+ shd_switchable_item("shd_logopt_urgency", state); |
|
565 |
+ shd_switchable_item("shd_logopt_tickettopicmove", state); |
|
566 |
+ shd_switchable_item("shd_logopt_delete", state); |
|
567 |
+ shd_switchable_item("shd_logopt_restore", state); |
|
568 |
+ shd_switchable_item("shd_logopt_permadelete", state); |
|
569 |
+ shd_switchable_item("shd_logopt_relationships", state); |
|
570 |
+ shd_switchable_item("shd_logopt_split", state); |
|
571 |
+ }'; |
|
572 |
+ |
|
573 |
+ return $config_vars; |
|
574 |
+} |
|
575 |
+ |
|
576 |
+/** |
|
577 |
+ * Initialises the helpdesk action log. |
|
578 |
+ * |
|
579 |
+ * This function loads the language strings, and hands off to {@link shd_load_action_log_entries()} to perform the actual log |
|
580 |
+ * generation. |
|
581 |
+ * |
|
582 |
+ * Before doing so, however, this function will also prepare for deletion of old entries, as well as sorting out the columns and |
|
583 |
+ * ordering rules before handing control to the other function. |
|
584 |
+ * |
|
585 |
+ * @since 1.0 |
|
586 |
+*/ |
|
587 |
+function shd_admin_action_log() |
|
588 |
+{ |
|
589 |
+ global $context, $settings, $scripturl, $txt, $sourcedir, $smcFunc, $sort_types; |
|
590 |
+ |
|
591 |
+ shd_load_language('SimpleDeskLogAction'); |
|
592 |
+ |
|
593 |
+ $context['can_delete'] = shd_allowed_to('admin_forum'); |
|
594 |
+ |
|
595 |
+ $context['displaypage'] = 30; |
|
596 |
+ $context['hoursdisable'] = 24; |
|
597 |
+ $context['waittime'] = time() - $context['hoursdisable'] * 3600; |
|
598 |
+ |
|
599 |
+ // Handle deletion... |
|
600 |
+ if (isset($_REQUEST['removeall']) && $context['can_delete']) |
|
601 |
+ shd_db_query('', ' |
|
602 |
+ DELETE FROM {db_prefix}helpdesk_log_action |
|
603 |
+ WHERE log_time < {int:twenty_four_hours_wait}', |
|
604 |
+ array( |
|
605 |
+ 'twenty_four_hours_wait' => $context['waittime'], |
|
606 |
+ ) |
|
607 |
+ ); |
|
608 |
+ elseif (!empty($_REQUEST['remove']) && $context['can_delete']) |
|
609 |
+ shd_db_query('', ' |
|
610 |
+ DELETE FROM {db_prefix}helpdesk_log_action |
|
611 |
+ WHERE id_action = {int:gtfo} |
|
612 |
+ AND log_time < {int:twenty_four_hours_wait}', |
|
613 |
+ array( |
|
614 |
+ 'twenty_four_hours_wait' => $context['waittime'], |
|
615 |
+ 'gtfo' => (int) $_REQUEST['remove'], |
|
616 |
+ ) |
|
617 |
+ ); |
|
618 |
+ |
|
619 |
+ // Do the column stuff! |
|
620 |
+ $sort_types = array( |
|
621 |
+ 'action' =>'la.action', |
|
622 |
+ 'time' => 'la.log_time', |
|
623 |
+ 'member' => 'mem.real_name', |
|
624 |
+ 'position' => 'mg.group_name', |
|
625 |
+ 'ip' => 'la.ip', |
|
626 |
+ ); |
|
627 |
+ |
|
628 |
+ // Setup the direction stuff... |
|
629 |
+ $context['sort'] = isset($_REQUEST['sort']) && isset($sort_types[$_REQUEST['sort']]) ? $sort_types[$_REQUEST['sort']] : $sort_types['time']; |
|
630 |
+ $context['start'] = isset($_REQUEST['start']) ? $_REQUEST['start'] : 0; |
|
631 |
+ $context['order'] = isset($_REQUEST['asc']) ? 'ASC' : 'DESC'; |
|
632 |
+ $context['url_sort'] = isset($_REQUEST['sort']) ? ';sort=' . $_REQUEST['sort'] : ''; |
|
633 |
+ $context['url_order'] = isset($_REQUEST['asc']) ? ';asc' : ''; |
|
634 |
+ |
|
635 |
+ // Get all action log entries |
|
636 |
+ $context['actions'] = shd_load_action_log_entries($context['start'], $context['displaypage'], $context['sort'], $context['order']); |
|
637 |
+ |
|
638 |
+ $context['page_index'] = shd_no_expand_pageindex($scripturl . '?action=admin;area=helpdesk_info;sa=actionlog' . $context['url_sort'] . $context['url_order'], $_REQUEST['start'], shd_count_action_log_entries(), $context['displaypage']); |
|
639 |
+ |
|
640 |
+ $context['sub_template'] = 'shd_action_log'; |
|
641 |
+} |
|
642 |
+ |
|
643 |
+/** |
|
644 |
+ * Loads the support page for users to submit support requests directly to SimpleDesk.net |
|
645 |
+ * |
|
646 |
+ * Very small function because essentially it just loads a template; there is no logic or processing to actually perform. |
|
647 |
+ * |
|
648 |
+ * @since 1.0 |
|
649 |
+*/ |
|
650 |
+function shd_admin_support() |
|
651 |
+{ |
|
652 |
+ global $context; |
|
653 |
+ |
|
654 |
+ $context['shd_support_url'] = 'http://www.simpledesk.net/support/post.php'; |
|
655 |
+ $context['sub_template'] = 'shd_support'; |
|
656 |
+} |
|
657 |
+ |
|
658 |
+/** |
|
659 |
+ * Loads the list of credits of people who've worked on SimpleDesk. |
|
660 |
+ * |
|
661 |
+ * This defines the list of peoples' names, and none of it will be in language strings; the actual category titles and positions |
|
662 |
+ * will be, but the names themselves can live in this file normally. |
|
663 |
+ * |
|
664 |
+ * @since 1.0 |
|
665 |
+*/ |
|
666 |
+function shd_credits() |
|
667 |
+{ |
|
668 |
+ global $context, $txt, $scripturl; |
|
669 |
+ |
|
670 |
+ // Credits! |
|
671 |
+ $context['shd_credits'] = array( |
|
672 |
+ array( |
|
673 |
+ 'pretext' => $txt['shd_credits_pretext'], |
|
674 |
+ 'groups' => array( |
|
675 |
+ array( |
|
676 |
+ 'title' => $txt['shd_credits_devs'], |
|
677 |
+ 'desc' => $txt['shd_credits_devs_desc'], |
|
678 |
+ 'icon' => 'devs.png', |
|
679 |
+ 'members' => array( |
|
680 |
+ 'Peter "Arantor" Spicer', |
|
681 |
+ 'Jason "JBlaze" Clemons', |
|
682 |
+ 'Marcus "Nas" Forsberg', |
|
683 |
+ ), |
|
684 |
+ ), |
|
685 |
+ array( |
|
686 |
+ 'title' => $txt['shd_credits_projectsupport'], |
|
687 |
+ 'desc' => $txt['shd_credits_projectsupport_desc'], |
|
688 |
+ 'icon' => 'managers.png', |
|
689 |
+ 'members' => array( |
|
690 |
+ 'Graeme "Trekkie101" Spence', |
|
691 |
+ 'Jeremy "SleePy" Darwood', |
|
692 |
+ ), |
|
693 |
+ ), |
|
694 |
+ array( |
|
695 |
+ 'title' => $txt['shd_credits_marketing'], |
|
696 |
+ 'desc' => $txt['shd_credits_marketing_desc'], |
|
697 |
+ 'icon' => 'marketers.png', |
|
698 |
+ 'members' => array( |
|
699 |
+ 'Brannon "Bª" Hall', |
|
700 |
+ ), |
|
701 |
+ ), |
|
702 |
+ array( |
|
703 |
+ 'title' => $txt['shd_credits_globalizer'], |
|
704 |
+ 'desc' => $txt['shd_credits_globalizer_desc'], |
|
705 |
+ 'icon' => 'globalizers.png', |
|
706 |
+ 'members' => array( |
|
707 |
+ 'Jerry Osborne', |
|
708 |
+ ), |
|
709 |
+ ), |
|
710 |
+ array( |
|
711 |
+ 'title' => $txt['shd_credits_support'], |
|
712 |
+ 'desc' => $txt['shd_credits_support_desc'], |
|
713 |
+ 'icon' => 'support.png', |
|
714 |
+ 'members' => array( |
|
715 |
+ 'Tyrsson', |
|
716 |
+ 'Ha2', |
|
717 |
+ 'Aldo "hadesflames" Barreras', |
|
718 |
+ ), |
|
719 |
+ ), |
|
720 |
+ array( |
|
721 |
+ 'title' => $txt['shd_credits_qualityassurance'], |
|
722 |
+ 'desc' => $txt['shd_credits_qualityassurance_desc'], |
|
723 |
+ 'icon' => 'qa.png', |
|
724 |
+ 'members' => array( |
|
725 |
+ 'Sinan "[SiNaN]" Çevik', |
|
726 |
+ 'Alex "Cleo" Tokar', |
|
727 |
+ 'Paul "tfs" Laufer', |
|
728 |
+ ), |
|
729 |
+ ), |
|
730 |
+ array( |
|
731 |
+ 'title' => $txt['shd_credits_beta'], |
|
732 |
+ 'desc' => $txt['shd_credits_beta_desc'], |
|
733 |
+ 'icon' => 'testers.png', |
|
734 |
+ 'members' => array( |
|
735 |
+ 'Chris "ccbtimewiz" Batista', |
|
736 |
+ 'Wade "Acans" Poulsen', |
|
737 |
+ 'Edwin "Dismal Shadow" Mendez', |
|
738 |
+ 'Treznax', |
|
739 |
+ 'Mark "KiLLuMiNaTi−7−" Longworth', |
|
740 |
+ 'NIBOGO', |
|
741 |
+ 'Robert "Robbo" Clancy', |
|
742 |
+ 'Yağizcan Arslan', |
|
743 |
+ 'MultiformeIngegno', |
|
744 |
+ 'flapjack', |
|
745 |
+ 'feline', |
|
746 |
+ 'Sordell Media', |
|
747 |
+ ), |
|
748 |
+ ), |
|
749 |
+ array( |
|
750 |
+ 'title' => $txt['shd_credits_alltherest'], |
|
751 |
+ 'desc' => '', // This group has its description included in the title. |
|
752 |
+ 'icon' => 'others.png', |
|
753 |
+ 'members' => array( |
|
754 |
+ 'Fluffy - ' . sprintf($txt['shd_fluffy'],'onclick="window.location.href=\'' . $scripturl . '?action=admin;area=helpdesk_info;cookies\'"'), |
|
755 |
+ '<br />' . $txt['shd_credits_translators'], |
|
756 |
+ '<br />' . sprintf($txt['shd_credits_icons'], 'http://led24.de/iconset/', 'http://wefunction.com/2008/07/function-free-icon-set/', 'http://www.famfamfam.com/lab/icons/flags/'), |
|
757 |
+ '<br />' . $txt['shd_credits_user'], |
|
758 |
+ ), |
|
759 |
+ ), |
|
760 |
+ ), |
|
761 |
+ ), |
|
762 |
+ ); |
|
763 |
+} |
|
764 |
+ |
|
765 |
+/** |
|
766 |
+ * @ignore |
|
767 |
+ * @since 1.0 |
|
768 |
+*/ |
|
769 |
+function shd_do_important() |
|
770 |
+{ |
|
771 |
+ // Execute code number 66. |
|
772 |
+ die(base64_decode('PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBYSFRNTCAxLjAgVHJhbnNpdGlvbmFsLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL1RSL3hodG1sMS9EVEQveGh0bWwxLXRyYW5zaXRpb25hbC5kdGQiPjxodG1sIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj48aGVhZD48dGl0bGU+Rmx1ZmZ5IC0gR3VhcmRpYW4gb2YgdGhlIGNvb2tpZXo8L3RpdGxlPjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Ym9keXtiYWNrZ3JvdW5kOnB1cnBsZTtjb2xvcjp3aGl0ZTtmb250LXNpemU6MzBweDt0ZXh0LWFsaWduOmNlbnRlcjt9PC9zdHlsZT48L2hlYWQ+PGJvZHk+PGltZyBzcmM9Imh0dHA6Ly93d3cuc2ltcGxlZGVzay5uZXQvaW1hZ2VzL3NpdGUvZ3VhcmRkb2c0MDMuanBnIiBhbHQ9IiIgb25jbGljaz0iYWxlcnQoJ1dhcm5pbmc6IEhlIG1heSBiaXRlIScpIi8+PGJyIC8+PGJyIC8+PHN0cm9uZz5GbHVmZnk8L3N0cm9uZz4gc2VlcyB5b3UuIEZsdWZmeSB3aWxsIHByb3RlY3Qgb3VyIGNhbmR5IDxzdHJvbmc+Zm9yIGV2ZXI8L3N0cm9uZz4uIEZsdWZmeSBpcyB0aGUgPHN0cm9uZz5ndWFyZGlhbjwvc3Ryb25nPiBvZiB0aGUgPHN0cm9uZz5jb29raWVzPC9zdHJvbmc+LiBCZSBhd2FyZS48L2JvZHk+PC9odG1sPg==')); // It will be done, my lord. |
|
773 |
+} |
|
774 |
+ |
|
775 |
+?> |
|
0 | 776 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,330 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-AdminCustomField.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles the core of SimpleDesk's custom ticket fields interface and code. |
|
22 |
+ * |
|
23 |
+ * @package source |
|
24 |
+ * @since 1.1 |
|
25 |
+*/ |
|
26 |
+if (!defined('SMF')) |
|
27 |
+ die('Hacking attempt...'); |
|
28 |
+ |
|
29 |
+/** |
|
30 |
+ * The start point for all interaction with the SimpleDesk custom field administration. |
|
31 |
+ * |
|
32 |
+ * Directed here from the main administration centre, after permission checks and a few dependencies loaded, this deals solely with managing custom fields. |
|
33 |
+ * |
|
34 |
+ * @since 1.1 |
|
35 |
+*/ |
|
36 |
+function shd_admin_custom() |
|
37 |
+{ |
|
38 |
+ global $context, $scripturl, $sourcedir, $settings, $txt, $modSettings; |
|
39 |
+ |
|
40 |
+ loadTemplate('sd_template/SimpleDesk-AdminCustomField'); |
|
41 |
+ |
|
42 |
+ $subactions = array( |
|
43 |
+ 'main' => 'shd_admin_custom_main', |
|
44 |
+ 'new' => 'shd_admin_custom_new', |
|
45 |
+ 'edit' => 'shd_admin_custom_edit', |
|
46 |
+ 'move' => 'shd_admin_custom_move', |
|
47 |
+ 'save' => 'shd_admin_custom_save', |
|
48 |
+ ); |
|
49 |
+ |
|
50 |
+ $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subactions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'main'; |
|
51 |
+ |
|
52 |
+ $context['field_types'] = array( |
|
53 |
+ CFIELD_TYPE_TEXT => array($txt['shd_admin_custom_fields_ui_text'], 'text'), |
|
54 |
+ CFIELD_TYPE_LARGETEXT => array($txt['shd_admin_custom_fields_ui_largetext'], 'largetext'), |
|
55 |
+ CFIELD_TYPE_INT => array($txt['shd_admin_custom_fields_ui_int'], 'int'), |
|
56 |
+ CFIELD_TYPE_FLOAT => array($txt['shd_admin_custom_fields_ui_float'], 'float'), |
|
57 |
+ CFIELD_TYPE_SELECT => array($txt['shd_admin_custom_fields_ui_select'], 'select'), |
|
58 |
+ CFIELD_TYPE_CHECKBOX => array($txt['shd_admin_custom_fields_ui_checkbox'], 'checkbox'), |
|
59 |
+ CFIELD_TYPE_RADIO => array($txt['shd_admin_custom_fields_ui_radio'], 'radio'), |
|
60 |
+ ); |
|
61 |
+ |
|
62 |
+ $subactions[$_REQUEST['sa']](); |
|
63 |
+} |
|
64 |
+ |
|
65 |
+/** |
|
66 |
+ * Display all the custom fields, including new/edit/save/delete UI hooks |
|
67 |
+ * |
|
68 |
+ * @since 1.1 |
|
69 |
+*/ |
|
70 |
+function shd_admin_custom_main() |
|
71 |
+{ |
|
72 |
+ global $context, $smcFunc, $modSettings, $txt; |
|
73 |
+ |
|
74 |
+ $context['custom_fields'] = array(); |
|
75 |
+ |
|
76 |
+ $query = shd_db_query('', ' |
|
77 |
+ SELECT id_field, active, field_order, field_name, field_desc, field_loc, icon, field_type |
|
78 |
+ FROM {db_prefix}helpdesk_custom_fields', |
|
79 |
+ array() |
|
80 |
+ ); |
|
81 |
+ |
|
82 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
83 |
+ { |
|
84 |
+ $row['active_string'] = empty($row['active']) ? 'inactive' : 'active'; |
|
85 |
+ $row['field_type'] = $context['field_types'][$row['field_type']][1]; // convert the integer in the DB into the string for language + image uses |
|
86 |
+ $context['custom_fields'][$row['field_order']] = $row; |
|
87 |
+ } |
|
88 |
+ |
|
89 |
+ ksort($context['custom_fields']); |
|
90 |
+ |
|
91 |
+ if (!empty($context['custom_fields'])) |
|
92 |
+ { |
|
93 |
+ $context['custom_fields'][0]['is_first'] = true; |
|
94 |
+ $context['custom_fields'][count($context['custom_fields']) - 1]['is_last'] = true; |
|
95 |
+ } |
|
96 |
+ // Final stuff before we go. |
|
97 |
+ $context['page_title'] = $txt['shd_admin_custom_fields']; |
|
98 |
+ $context['sub_template'] = 'shd_custom_field_home'; |
|
99 |
+} |
|
100 |
+ |
|
101 |
+/** |
|
102 |
+ * Display the new field UI |
|
103 |
+ * |
|
104 |
+ * @since 1.1 |
|
105 |
+*/ |
|
106 |
+function shd_admin_custom_new() |
|
107 |
+{ |
|
108 |
+ global $context, $smcFunc, $modSettings, $txt, $scripturl; |
|
109 |
+ |
|
110 |
+ $context = array_merge($context, array( |
|
111 |
+ 'sub_template' => 'shd_custom_field_edit', |
|
112 |
+ 'page_title' => $txt['shd_admin_new_custom_field'], |
|
113 |
+ 'field_type_value' => CFIELD_TYPE_TEXT, |
|
114 |
+ 'field_icons' => shd_admin_cf_icons(), |
|
115 |
+ 'field_icon_value' => '', |
|
116 |
+ )); |
|
117 |
+/* |
|
118 |
+ $context += array( |
|
119 |
+ 'sub_template' => 'shd_show_settings', |
|
120 |
+ 'settings_title' => $txt['shd_admin_new_custom_field'], |
|
121 |
+ 'settings_icon' => 'custom_fields.png', |
|
122 |
+ 'config_vars' => array( |
|
123 |
+ array( |
|
124 |
+ 'type' => 'text', |
|
125 |
+ 'name' => 'field_name', |
|
126 |
+ 'label' => $txt['shd_admin_custom_fields_fieldname'], |
|
127 |
+ 'value' => '', |
|
128 |
+ 'help' => 'shd_admin_custom_fields_fieldname_desc', |
|
129 |
+ ), |
|
130 |
+ array( |
|
131 |
+ 'type' => 'check', |
|
132 |
+ 'name' => 'active', |
|
133 |
+ 'label' => $txt['shd_admin_custom_fields_active'], |
|
134 |
+ 'value' => true, |
|
135 |
+ 'help' => 'shd_admin_custom_fields_active_desc', |
|
136 |
+ ), |
|
137 |
+ array( |
|
138 |
+ 'type' => 'large_text', |
|
139 |
+ 'name' => 'field_desc', |
|
140 |
+ 'label' => $txt['shd_admin_custom_fields_fielddesc'], |
|
141 |
+ 'value' => '', |
|
142 |
+ 'help' => 'shd_admin_custom_fields_fielddesc_desc', |
|
143 |
+ 'size' => 4, |
|
144 |
+ ), |
|
145 |
+ array( |
|
146 |
+ 'type' => 'select', |
|
147 |
+ 'name' => 'field_type', |
|
148 |
+ 'label' => $txt['shd_admin_custom_fields_icon'], |
|
149 |
+ 'value' => '', |
|
150 |
+ 'data' => shd_admin_cf_icons(), |
|
151 |
+ 'help' => 'shd_admin_custom_fields_icon_desc', |
|
152 |
+ ), |
|
153 |
+ array( |
|
154 |
+ 'type' => 'select', |
|
155 |
+ 'name' => 'field_type', |
|
156 |
+ 'label' => $txt['shd_admin_custom_fields_fieldtype'], |
|
157 |
+ 'value' => 0, |
|
158 |
+ 'data' => array( |
|
159 |
+ array(CFIELD_TYPE_TEXT, $txt['shd_admin_custom_fields_ui_text']), |
|
160 |
+ array(CFIELD_TYPE_LARGETEXT, $txt['shd_admin_custom_fields_ui_largetext']), |
|
161 |
+ array(CFIELD_TYPE_INT, $txt['shd_admin_custom_fields_ui_int']), |
|
162 |
+ array(CFIELD_TYPE_FLOAT, $txt['shd_admin_custom_fields_ui_float']), |
|
163 |
+ array(CFIELD_TYPE_SELECT, $txt['shd_admin_custom_fields_ui_select']), |
|
164 |
+ array(CFIELD_TYPE_CHECKBOX, $txt['shd_admin_custom_fields_ui_checkbox']), |
|
165 |
+ array(CFIELD_TYPE_RADIO, $txt['shd_admin_custom_fields_ui_radio']), |
|
166 |
+ ), |
|
167 |
+ 'help' => 'shd_admin_custom_fields_fieldtype_desc', |
|
168 |
+ ), |
|
169 |
+ array( |
|
170 |
+ 'type' => 'select', |
|
171 |
+ 'name' => 'field_type', |
|
172 |
+ 'label' => $txt['shd_admin_custom_fields_visible'], |
|
173 |
+ 'value' => CFIELD_TICKET, |
|
174 |
+ 'data' => array( |
|
175 |
+ array(CFIELD_TICKET, $txt['shd_admin_custom_fields_visible_ticket']), |
|
176 |
+ array(CFIELD_REPLY, $txt['shd_admin_custom_fields_visible_field']), |
|
177 |
+ array((CFIELD_TICKET | CFIELD_REPLY), $txt['shd_admin_custom_fields_visible_both']), |
|
178 |
+ ), |
|
179 |
+ 'help' => 'shd_admin_custom_fields_visible_desc', |
|
180 |
+ ), |
|
181 |
+ ), |
|
182 |
+ 'post_url' => $scripturl . '?action=admin;area=helpdesk_customfield;sa=save', |
|
183 |
+ ); |
|
184 |
+ |
|
185 |
+ foreach ($context['config_vars'] as $key => $item) |
|
186 |
+ { |
|
187 |
+ if (!isset($item['javascript'])) |
|
188 |
+ $context['config_vars'][$key]['javascript'] = ''; |
|
189 |
+ if (!isset($item['preinput'])) |
|
190 |
+ $context['config_vars'][$key]['preinput'] = ''; |
|
191 |
+ if (!isset($item['disabled'])) |
|
192 |
+ $context['config_vars'][$key]['disabled'] = false; |
|
193 |
+ if (!isset($item['invalid'])) |
|
194 |
+ $context['config_vars'][$key]['invalid'] = false; |
|
195 |
+ }*/ |
|
196 |
+} |
|
197 |
+ |
|
198 |
+/** |
|
199 |
+ * Display the edit field UI |
|
200 |
+ * |
|
201 |
+ * @since 1.1 |
|
202 |
+*/ |
|
203 |
+function shd_admin_custom_edit() |
|
204 |
+{ |
|
205 |
+ global $context, $smcFunc, $modSettings, $txt; |
|
206 |
+ |
|
207 |
+ $_REQUEST['field'] = isset($_REQUEST['field']) ? (int) $_REQUEST['field'] : 0; |
|
208 |
+ |
|
209 |
+ $query = shd_db_query('', ' |
|
210 |
+ SELECT id_field, active, field_order, field_name, field_desc, field_loc, icon, field_type |
|
211 |
+ FROM {db_prefix}helpdesk_custom_fields |
|
212 |
+ WHERE id_field = {int:field}', |
|
213 |
+ array( |
|
214 |
+ 'field' => $_REQUEST['field'], |
|
215 |
+ ) |
|
216 |
+ ); |
|
217 |
+ |
|
218 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
219 |
+ { |
|
220 |
+ $smcFunc['db_free_result']($query); |
|
221 |
+ $context['custom_field'] = $row; |
|
222 |
+ $context['section_title'] = $txt['shd_admin_edit_custom_field']; |
|
223 |
+ $context['section_desc'] = $txt['shd_admin_edit_custom_field_desc']; |
|
224 |
+ $context['page_title'] = $txt['shd_admin_edit_custom_field']; |
|
225 |
+ $context['sub_template'] = 'shd_custom_field_edit'; |
|
226 |
+ } |
|
227 |
+ else |
|
228 |
+ { |
|
229 |
+ $smcFunc['db_free_result']($query); |
|
230 |
+ fatal_lang_error('shd_admin_cannot_edit_custom_field', false); |
|
231 |
+ } |
|
232 |
+} |
|
233 |
+ |
|
234 |
+/** |
|
235 |
+ * Handle saving a new field |
|
236 |
+ * |
|
237 |
+ * @since 1.1 |
|
238 |
+*/ |
|
239 |
+function shd_admin_custom_save() |
|
240 |
+{ |
|
241 |
+ global $context, $smcFunc, $modSettings; |
|
242 |
+ |
|
243 |
+ checkSession(); |
|
244 |
+} |
|
245 |
+ |
|
246 |
+/** |
|
247 |
+ * Handle moving a custom field up or down |
|
248 |
+ * |
|
249 |
+ * @since 1.1 |
|
250 |
+*/ |
|
251 |
+function shd_admin_custom_move() |
|
252 |
+{ |
|
253 |
+ global $context, $smcFunc, $modSettings; |
|
254 |
+ |
|
255 |
+ checkSession('get'); |
|
256 |
+ |
|
257 |
+ $_REQUEST['field'] = isset($_REQUEST['field']) ? (int) $_REQUEST['field'] : 0; |
|
258 |
+ $_REQUEST['direction'] = isset($_REQUEST['direction']) && in_array($_REQUEST['direction'], array('up', 'down')) ? $_REQUEST['direction'] : ''; |
|
259 |
+ |
|
260 |
+ $query = shd_db_query('', ' |
|
261 |
+ SELECT id_field, field_order |
|
262 |
+ FROM {db_prefix}helpdesk_custom_fields', |
|
263 |
+ array() |
|
264 |
+ ); |
|
265 |
+ |
|
266 |
+ if ($smcFunc['db_num_rows']($query) == 0 || empty($_REQUEST['direction'])) |
|
267 |
+ { |
|
268 |
+ $smcFunc['db_free_result']($query); |
|
269 |
+ fatal_lang_error('shd_admin_cannot_move_custom_field', false); |
|
270 |
+ } |
|
271 |
+ |
|
272 |
+ $fields = array(); |
|
273 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
274 |
+ $fields[$row['field_order']] = $row['id_field']; |
|
275 |
+ |
|
276 |
+ ksort($fields); |
|
277 |
+ |
|
278 |
+ $fields_map = array_flip($fields); |
|
279 |
+ if (empty($fields_map[$_REQUEST['field']])) |
|
280 |
+ fatal_lang_error('shd_admin_cannot_move_custom_field', false); |
|
281 |
+ |
|
282 |
+ $current_pos = $fields_map[$_REQUEST['field']]; |
|
283 |
+ $destination = $current_pos + ($_REQUEST['direction'] == 'up' ? -1 : 1); |
|
284 |
+ |
|
285 |
+ if (empty($fields[$destination])) |
|
286 |
+ fatal_lang_error('shd_admin_cannot_move_custom_field_' . $_REQUEST['direction'], false); |
|
287 |
+ |
|
288 |
+ $other_field = $fields[$destination]; |
|
289 |
+ |
|
290 |
+ shd_db_query('', ' |
|
291 |
+ UPDATE {db_prefix}helpdesk_custom_fields |
|
292 |
+ SET field_order = {int:new_pos} |
|
293 |
+ WHERE id_field = {int:field}', |
|
294 |
+ array( |
|
295 |
+ 'new_pos' => $destination, |
|
296 |
+ 'field' => $_REQUEST['field'], |
|
297 |
+ ) |
|
298 |
+ ); |
|
299 |
+ |
|
300 |
+ shd_db_query('', ' |
|
301 |
+ UPDATE {db_prefix}helpdesk_custom_fields |
|
302 |
+ SET field_order = {int:old_pos} |
|
303 |
+ WHERE id_field = {int:other_field}', |
|
304 |
+ array( |
|
305 |
+ 'old_pos' => $current_pos, |
|
306 |
+ 'other_field' => $other_field, |
|
307 |
+ ) |
|
308 |
+ ); |
|
309 |
+ |
|
310 |
+ redirectexit('action=admin;area=helpdesk_customfield;' . $context['session_var'] . '=' . $context['session_id']); |
|
311 |
+} |
|
312 |
+ |
|
313 |
+/** |
|
314 |
+ * Get possible icons |
|
315 |
+ * |
|
316 |
+ * @return array A list of possible images for the icon selector (everything in Themes/default/images/simpledesk/cf/ that's an image). Each item in the principle array is an array of value/caption pairs. |
|
317 |
+ * @since 1.1 |
|
318 |
+*/ |
|
319 |
+function shd_admin_cf_icons() |
|
320 |
+{ |
|
321 |
+ global $context, $settings, $txt; |
|
322 |
+ |
|
323 |
+ $iconlist = array( |
|
324 |
+ array('', $txt['shd_admin_custom_fields_none']), |
|
325 |
+ ); |
|
326 |
+ |
|
327 |
+ return $iconlist; |
|
328 |
+} |
|
329 |
+ |
|
330 |
+?> |
|
0 | 331 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,644 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-AdminPermissions.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles the core of SimpleDesk's permissions system. |
|
22 |
+ * |
|
23 |
+ * @package source |
|
24 |
+ * @since 1.1 |
|
25 |
+*/ |
|
26 |
+if (!defined('SMF')) |
|
27 |
+ die('Hacking attempt...'); |
|
28 |
+ |
|
29 |
+/** |
|
30 |
+ * This function is the start point for configuration of permissions within SimpleDesk. |
|
31 |
+ * |
|
32 |
+ * @since 1.1 |
|
33 |
+*/ |
|
34 |
+function shd_admin_permissions() |
|
35 |
+{ |
|
36 |
+ global $context, $scripturl, $sourcedir, $settings, $txt, $modSettings; |
|
37 |
+ |
|
38 |
+ shd_load_all_permission_sets(); |
|
39 |
+ loadTemplate('sd_template/SimpleDesk-AdminPermissions'); |
|
40 |
+ shd_load_language('SimpleDeskPermissions'); |
|
41 |
+ |
|
42 |
+ $subactions = array( |
|
43 |
+ 'main' => 'shd_admin_role_list', |
|
44 |
+ 'createrole' => 'shd_admin_create_role', |
|
45 |
+ 'editrole' => 'shd_admin_edit_role', |
|
46 |
+ 'saverole' => 'shd_admin_save_role', |
|
47 |
+ 'copyrole' => 'shd_admin_copy_role', |
|
48 |
+ ); |
|
49 |
+ |
|
50 |
+ $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subactions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'main'; |
|
51 |
+ |
|
52 |
+ $subactions[$_REQUEST['sa']](); |
|
53 |
+} |
|
54 |
+ |
|
55 |
+/** |
|
56 |
+ * This function handles displaying a list of roles known to the system. |
|
57 |
+ * |
|
58 |
+ * @since 1.1 |
|
59 |
+*/ |
|
60 |
+function shd_admin_role_list() |
|
61 |
+{ |
|
62 |
+ global $context, $txt, $smcFunc; |
|
63 |
+ |
|
64 |
+ $context['page_title'] = $txt['shd_admin_permissions']; |
|
65 |
+ $context['sub_template'] = 'shd_permissions_home'; |
|
66 |
+ |
|
67 |
+ shd_load_role(); |
|
68 |
+} |
|
69 |
+ |
|
70 |
+/** |
|
71 |
+ * This function deals with creating a new role in the database, based on a specified template. |
|
72 |
+ * |
|
73 |
+ * @since 1.1 |
|
74 |
+*/ |
|
75 |
+function shd_admin_create_role() |
|
76 |
+{ |
|
77 |
+ global $context, $txt, $smcFunc; |
|
78 |
+ |
|
79 |
+ $_REQUEST['template'] = isset($_REQUEST['template']) ? (int) $_REQUEST['template'] : 0; |
|
80 |
+ if (empty($context['shd_permissions']['roles'][$_REQUEST['template']])) |
|
81 |
+ fatal_lang_error('shd_unknown_template', false); |
|
82 |
+ |
|
83 |
+ if (empty($_REQUEST['part'])) |
|
84 |
+ { |
|
85 |
+ $context['page_title'] = $txt['shd_create_role']; |
|
86 |
+ $context['sub_template'] = 'shd_create_role'; |
|
87 |
+ checkSubmitOnce('register'); |
|
88 |
+ } |
|
89 |
+ else |
|
90 |
+ { |
|
91 |
+ checkSubmitOnce('check'); |
|
92 |
+ checkSession(); |
|
93 |
+ |
|
94 |
+ // Boring stuff like session checks done. Were you a naughty admin and didn't set it properly? |
|
95 |
+ if (!isset($_POST['rolename']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['rolename'])) === '') |
|
96 |
+ fatal_lang_error('shd_no_role_name', false); |
|
97 |
+ else |
|
98 |
+ $_POST['rolename'] = strtr($smcFunc['htmlspecialchars']($_POST['rolename']), array("\r" => '', "\n" => '', "\t" => '')); |
|
99 |
+ |
|
100 |
+ // So here we are, template id is valid, we're good little admins and specified a name, so let's create the new role in the DB. |
|
101 |
+ $smcFunc['db_insert']('insert', |
|
102 |
+ '{db_prefix}helpdesk_roles', |
|
103 |
+ array( |
|
104 |
+ 'template' => 'int', 'role_name' => 'string', |
|
105 |
+ ), |
|
106 |
+ array( |
|
107 |
+ $_REQUEST['template'], $_POST['rolename'], |
|
108 |
+ ), |
|
109 |
+ array( |
|
110 |
+ 'id_role', |
|
111 |
+ ) |
|
112 |
+ ); |
|
113 |
+ |
|
114 |
+ $newrole = $smcFunc['db_insert_id']('{db_prefix}helpdesk_roles', 'id_role'); |
|
115 |
+ if (empty($newrole)) |
|
116 |
+ fatal_lang_error('shd_could_not_create_role', false); |
|
117 |
+ |
|
118 |
+ // Take them to the edit screen! |
|
119 |
+ redirectexit('action=admin;area=helpdesk_permissions;sa=editrole;role=' . $newrole); |
|
120 |
+ } |
|
121 |
+} |
|
122 |
+ |
|
123 |
+function shd_admin_edit_role() |
|
124 |
+{ |
|
125 |
+ global $context, $txt, $smcFunc, $scripturl; |
|
126 |
+ |
|
127 |
+ $_REQUEST['role'] = isset($_REQUEST['role']) ? (int) $_REQUEST['role'] : 0; |
|
128 |
+ shd_load_role($_REQUEST['role']); |
|
129 |
+ |
|
130 |
+ if (empty($context['shd_permissions']['user_defined_roles'][$_REQUEST['role']])) |
|
131 |
+ fatal_lang_error('shd_unknown_role', false); |
|
132 |
+ |
|
133 |
+ // OK, figure out what groups are possible groups (including regular members), and what groups this role has. |
|
134 |
+ // We're not interested in admin (group 1), board mod (group 3) or post count groups (min_posts != -1) |
|
135 |
+ $context['membergroups'][0] = array( |
|
136 |
+ 'group_name' => $txt['membergroups_members'], |
|
137 |
+ 'color' => '', |
|
138 |
+ 'link' => $txt['membergroups_members'], |
|
139 |
+ 'stars' => '', |
|
140 |
+ ); |
|
141 |
+ |
|
142 |
+ $query = $smcFunc['db_query']('', ' |
|
143 |
+ SELECT mg.id_group, mg.group_name, mg.online_color, mg.stars |
|
144 |
+ FROM {db_prefix}membergroups AS mg |
|
145 |
+ WHERE mg.min_posts = -1 |
|
146 |
+ AND mg.id_group NOT IN (1,3) |
|
147 |
+ ORDER BY id_group', |
|
148 |
+ array() |
|
149 |
+ ); |
|
150 |
+ |
|
151 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
152 |
+ { |
|
153 |
+ $context['membergroups'][$row['id_group']] = array( |
|
154 |
+ 'name' => $row['group_name'], |
|
155 |
+ 'color' => $row['online_color'], |
|
156 |
+ 'link' => '<a href="' . $scripturl . '?action=groups;sa=members;group=' . $row['id_group'] . '"' . (empty($row['online_color']) ? '' : ' style="color: ' . $row['online_color'] . ';"') . '>' . $row['group_name'] . '</a>', |
|
157 |
+ 'stars' => $row['stars'], |
|
158 |
+ ); |
|
159 |
+ } |
|
160 |
+ |
|
161 |
+ $smcFunc['db_free_result']($query); |
|
162 |
+ |
|
163 |
+ // Now for this role's groups, if it has any. |
|
164 |
+ $context['role_groups'] = array(); |
|
165 |
+ |
|
166 |
+ $query = $smcFunc['db_query']('', ' |
|
167 |
+ SELECT id_group |
|
168 |
+ FROM {db_prefix}helpdesk_role_groups |
|
169 |
+ WHERE id_role = {int:role}', |
|
170 |
+ array( |
|
171 |
+ 'role' => $_REQUEST['role'], |
|
172 |
+ ) |
|
173 |
+ ); |
|
174 |
+ |
|
175 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
176 |
+ $context['role_groups'][] = $row['id_group']; |
|
177 |
+ |
|
178 |
+ $smcFunc['db_free_result']($query); |
|
179 |
+ |
|
180 |
+ $context['page_title'] = $txt['shd_edit_role']; |
|
181 |
+ $context['sub_template'] = 'shd_edit_role'; |
|
182 |
+} |
|
183 |
+ |
|
184 |
+/** |
|
185 |
+ * Handle saving a user defined role. |
|
186 |
+ * |
|
187 |
+ * @since 1.1 |
|
188 |
+*/ |
|
189 |
+function shd_admin_save_role() |
|
190 |
+{ |
|
191 |
+ global $context, $txt, $smcFunc, $scripturl; |
|
192 |
+ |
|
193 |
+ // 1. Time for one of our sessions, mistress? |
|
194 |
+ checkSession(); |
|
195 |
+ |
|
196 |
+ // 2. Acting in a role, are we? Is it one we have the script for? |
|
197 |
+ $_REQUEST['role'] = isset($_REQUEST['role']) ? (int) $_REQUEST['role'] : 0; |
|
198 |
+ shd_load_role($_REQUEST['role']); |
|
199 |
+ |
|
200 |
+ // Hah, no, you're just an extra, bye. |
|
201 |
+ if (empty($context['shd_permissions']['user_defined_roles'][$_REQUEST['role']])) |
|
202 |
+ fatal_lang_error('shd_unknown_role', false); |
|
203 |
+ |
|
204 |
+ // 2b. Oh, we have actually heard of you. That's fine, we'll just refer to you by codename because we're lazy. |
|
205 |
+ $role = &$context['shd_permissions']['user_defined_roles'][$_REQUEST['role']]; |
|
206 |
+ |
|
207 |
+ // 3. Are you the gunman behind the grassy knoll? |
|
208 |
+ if (isset($_POST['delete'])) |
|
209 |
+ { |
|
210 |
+ // Oops, bang you're dead. |
|
211 |
+ $smcFunc['db_query']('', ' |
|
212 |
+ DELETE FROM {db_prefix}helpdesk_roles |
|
213 |
+ WHERE id_role = {int:role}', |
|
214 |
+ array( |
|
215 |
+ 'role' => $_REQUEST['role'], |
|
216 |
+ ) |
|
217 |
+ ); |
|
218 |
+ |
|
219 |
+ $smcFunc['db_query']('', ' |
|
220 |
+ DELETE FROM {db_prefix}helpdesk_role_groups |
|
221 |
+ WHERE id_role = {int:role}', |
|
222 |
+ array( |
|
223 |
+ 'role' => $_REQUEST['role'], |
|
224 |
+ ) |
|
225 |
+ ); |
|
226 |
+ |
|
227 |
+ $smcFunc['db_query']('', ' |
|
228 |
+ DELETE FROM {db_prefix}helpdesk_role_permissions |
|
229 |
+ WHERE id_role = {int:role}', |
|
230 |
+ array( |
|
231 |
+ 'role' => $_REQUEST['role'], |
|
232 |
+ ) |
|
233 |
+ ); |
|
234 |
+ |
|
235 |
+ // Bat out of hell |
|
236 |
+ redirectexit('action=admin;area=helpdesk_permissions'); |
|
237 |
+ } |
|
238 |
+ |
|
239 |
+ // 4. The unknown actor in a role? |
|
240 |
+ if (!isset($_POST['rolename']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['rolename'])) === '') |
|
241 |
+ fatal_lang_error('shd_no_role_name', false); |
|
242 |
+ else |
|
243 |
+ $_POST['rolename'] = strtr($smcFunc['htmlspecialchars']($_POST['rolename']), array("\r" => '', "\n" => '', "\t" => '')); |
|
244 |
+ |
|
245 |
+ // 4. Is the role different to what we thought it was? If so, informer the director, our good friend Mr. Database |
|
246 |
+ if ($role['name'] != $_POST['rolename']) |
|
247 |
+ { |
|
248 |
+ $smcFunc['db_query']('', ' |
|
249 |
+ UPDATE {db_prefix}helpdesk_roles |
|
250 |
+ SET role_name = {string:rolename} |
|
251 |
+ WHERE id_role = {int:role}', |
|
252 |
+ array( |
|
253 |
+ 'role' => $_REQUEST['role'], |
|
254 |
+ 'rolename' => $_POST['rolename'], |
|
255 |
+ ) |
|
256 |
+ ); |
|
257 |
+ } |
|
258 |
+ |
|
259 |
+ // 5. Tick off what we can and can't do, it all sounds like so much fun. |
|
260 |
+ $perm_changes = array( |
|
261 |
+ 'add_update' => array(), |
|
262 |
+ 'remove' => array(), |
|
263 |
+ ); |
|
264 |
+ |
|
265 |
+ $assoc = array( |
|
266 |
+ 'allow' => ROLEPERM_ALLOW, |
|
267 |
+ 'disallow' => ROLEPERM_DISALLOW, |
|
268 |
+ 'deny' => ROLEPERM_DENY, |
|
269 |
+ ); |
|
270 |
+ |
|
271 |
+ foreach ($context['shd_permissions']['permission_list'] as $permission => $details) |
|
272 |
+ { |
|
273 |
+ list($ownany, $group, $icon) = $details; |
|
274 |
+ if (empty($icon)) |
|
275 |
+ continue; // this gets rid of the user/staff/admin permission items! |
|
276 |
+ |
|
277 |
+ if ($ownany) |
|
278 |
+ { |
|
279 |
+ if (empty($_POST['perm_' . $permission]) || !in_array($_POST['perm_' . $permission], array('allow_any', 'allow_own', 'disallow', 'deny'))) |
|
280 |
+ $_POST['perm_' . $permission] = 'disallow'; |
|
281 |
+ |
|
282 |
+ switch ($_POST['perm_' . $permission]) |
|
283 |
+ { |
|
284 |
+ case 'allow_any': |
|
285 |
+ // If it's not in the table of perms, or it is but it's not allowed thus far, change it |
|
286 |
+ if (!isset($role['permissions'][$permission . '_any']) || $role['permissions'][$permission . '_any'] != ROLEPERM_ALLOW) |
|
287 |
+ $perm_changes['add_update'][$permission . '_any'] = ROLEPERM_ALLOW; |
|
288 |
+ $perm_changes['remove'][] = $permission . '_own'; |
|
289 |
+ break; |
|
290 |
+ case 'allow_own': |
|
291 |
+ // If it's not in the table of perms, or it is but it's not allowed thus far, change it |
|
292 |
+ if (!isset($role['permissions'][$permission . '_own']) || $role['permissions'][$permission . '_own'] != ROLEPERM_ALLOW) |
|
293 |
+ $perm_changes['add_update'][$permission . '_own'] = ROLEPERM_ALLOW; |
|
294 |
+ |
|
295 |
+ // This is where it gets interesting. If the template allows _any, but user wants _own, ensure that is duly noted |
|
296 |
+ if (!empty($context['shd_permissions']['roles'][$role['template']]['permissions'][$permission . '_any']) && $context['shd_permissions']['roles'][$role['template']]['permissions'][$permission . '_any'] == ROLEPERM_ALLOW) |
|
297 |
+ $perm_changes['add_update'][$permission . '_any'] = ROLEPERM_DISALLOW; |
|
298 |
+ else |
|
299 |
+ $perm_changes['remove'][] = $permission . '_any'; |
|
300 |
+ break; |
|
301 |
+ case 'disallow': |
|
302 |
+ // If it doesn't exist in the table, it's a non issue, if it does exit and it's different it needs changing |
|
303 |
+ if (isset($role['permissions'][$permission . '_any']) && $role['permissions'][$permission . '_any'] != ROLEPERM_DISALLOW) |
|
304 |
+ $perm_changes['add_update'][$permission . '_any'] = ROLEPERM_DISALLOW; |
|
305 |
+ if (isset($role['permissions'][$permission . '_own']) && $role['permissions'][$permission . '_own'] != ROLEPERM_DISALLOW) |
|
306 |
+ $perm_changes['add_update'][$permission . '_own'] = ROLEPERM_DISALLOW; |
|
307 |
+ |
|
308 |
+ break; |
|
309 |
+ case 'deny': // we're denying the permission as a whole, block it out on both levels |
|
310 |
+ $perm_changes['add_update'] += array( |
|
311 |
+ ($permission . '_any') => ROLEPERM_DENY, |
|
312 |
+ ($permission . '_own') => ROLEPERM_DENY, |
|
313 |
+ ); |
|
314 |
+ break; |
|
315 |
+ } |
|
316 |
+ } |
|
317 |
+ else |
|
318 |
+ { |
|
319 |
+ if (empty($_POST['perm_' . $permission]) || !in_array($_POST['perm_' . $permission], array('allow', 'disallow', 'deny'))) |
|
320 |
+ $_POST['perm_' . $permission] = 'disallow'; |
|
321 |
+ |
|
322 |
+ if ((!isset($role['permissions'][$permission]) && $assoc[$_POST['perm_' . $permission]] != ROLEPERM_DISALLOW) || (isset($role['permissions'][$permission]) && $role['permissions'][$permission] != $assoc[$_POST['perm_' . $permission]])) // it's not actually set, so it's new, or it's different to what we had before |
|
323 |
+ $perm_changes['add_update'][$permission] = $assoc[$_POST['perm_' . $permission]]; |
|
324 |
+ } |
|
325 |
+ } |
|
326 |
+ |
|
327 |
+ // 6b. Rack 'em up for the database |
|
328 |
+ if (!empty($perm_changes['add_update'])) |
|
329 |
+ { |
|
330 |
+ $insert = array(); |
|
331 |
+ foreach ($perm_changes['add_update'] as $perm => $permvalue) |
|
332 |
+ $insert[] = array($_REQUEST['role'], $perm, $permvalue); |
|
333 |
+ |
|
334 |
+ $smcFunc['db_insert']('replace', |
|
335 |
+ '{db_prefix}helpdesk_role_permissions', |
|
336 |
+ array( |
|
337 |
+ 'id_role' => 'int', 'permission' => 'string', 'add_type' => 'int', |
|
338 |
+ ), |
|
339 |
+ $insert, |
|
340 |
+ array( |
|
341 |
+ 'id_role', 'permission', |
|
342 |
+ ) |
|
343 |
+ ); |
|
344 |
+ } |
|
345 |
+ |
|
346 |
+ if (!empty($perm_changes['remove'])) |
|
347 |
+ { |
|
348 |
+ $smcFunc['db_query']('', ' |
|
349 |
+ DELETE FROM {db_prefix}helpdesk_role_permissions |
|
350 |
+ WHERE id_role = {int:role} |
|
351 |
+ AND permission IN ({array_string:permissions}) |
|
352 |
+ LIMIT 1', |
|
353 |
+ array( |
|
354 |
+ 'role' => $_REQUEST['role'], |
|
355 |
+ 'permissions' => $perm_changes['remove'], |
|
356 |
+ ) |
|
357 |
+ ); |
|
358 |
+ |
|
359 |
+ } |
|
360 |
+ |
|
361 |
+ // 7. (serious voice) OK let's do groups. Grab the ones that are valid groups in SMF, ignore everything else |
|
362 |
+ // We're not interested in admin (group 1), board mod (group 3) or post count groups (min_posts != -1) |
|
363 |
+ $context['membergroups'] = array(0); |
|
364 |
+ |
|
365 |
+ $query = $smcFunc['db_query']('', ' |
|
366 |
+ SELECT mg.id_group |
|
367 |
+ FROM {db_prefix}membergroups AS mg |
|
368 |
+ WHERE mg.min_posts = -1 |
|
369 |
+ AND mg.id_group NOT IN (1,3) |
|
370 |
+ ORDER BY id_group', |
|
371 |
+ array() |
|
372 |
+ ); |
|
373 |
+ |
|
374 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
375 |
+ $context['membergroups'][] = $row['id_group']; |
|
376 |
+ |
|
377 |
+ $groups = array( |
|
378 |
+ 'add' => array(), |
|
379 |
+ 'remove' => array(), |
|
380 |
+ ); |
|
381 |
+ |
|
382 |
+ foreach ($context['membergroups'] as $group) |
|
383 |
+ { |
|
384 |
+ if (!empty($_POST['group' . $group])) |
|
385 |
+ { |
|
386 |
+ if (empty($role['groups'][$group])) // box is ticked but it's one we don't know about already |
|
387 |
+ $groups['add'][] = $group; |
|
388 |
+ } |
|
389 |
+ else |
|
390 |
+ { |
|
391 |
+ if (!empty($role['groups'][$group])) // box is empty but it's one that was attached to this role |
|
392 |
+ $groups['remove'][] = $group; |
|
393 |
+ } |
|
394 |
+ } |
|
395 |
+ |
|
396 |
+ if (!empty($groups['remove'])) |
|
397 |
+ { |
|
398 |
+ $smcFunc['db_query']('', ' |
|
399 |
+ DELETE FROM {db_prefix}helpdesk_role_groups |
|
400 |
+ WHERE id_role = {int:role} |
|
401 |
+ AND id_group IN ({array_int:groups})', |
|
402 |
+ array( |
|
403 |
+ 'role' => $_REQUEST['role'], |
|
404 |
+ 'groups' => $groups['remove'], |
|
405 |
+ ) |
|
406 |
+ ); |
|
407 |
+ } |
|
408 |
+ |
|
409 |
+ if (!empty($groups['add'])) |
|
410 |
+ { |
|
411 |
+ $insert = array(); |
|
412 |
+ foreach ($groups['add'] as $add) |
|
413 |
+ $insert[] = array($_REQUEST['role'], $add); |
|
414 |
+ |
|
415 |
+ $smcFunc['db_insert']('replace', |
|
416 |
+ '{db_prefix}helpdesk_role_groups', |
|
417 |
+ array( |
|
418 |
+ 'id_role' => 'int', 'id_group' => 'int', |
|
419 |
+ ), |
|
420 |
+ $insert, |
|
421 |
+ array( |
|
422 |
+ 'id_role', 'id_group', |
|
423 |
+ ) |
|
424 |
+ ); |
|
425 |
+ } |
|
426 |
+ |
|
427 |
+ // All done, back to the main screen |
|
428 |
+ redirectexit('action=admin;area=helpdesk_permissions'); |
|
429 |
+} |
|
430 |
+ |
|
431 |
+/** |
|
432 |
+ * Handles user requests to copy an existing role. |
|
433 |
+ * |
|
434 |
+ * @since 1.1 |
|
435 |
+*/ |
|
436 |
+function shd_admin_copy_role() |
|
437 |
+{ |
|
438 |
+ global $context, $txt, $smcFunc; |
|
439 |
+ |
|
440 |
+ $_REQUEST['role'] = isset($_REQUEST['role']) ? (int) $_REQUEST['role'] : 0; |
|
441 |
+ shd_load_role($_REQUEST['role']); |
|
442 |
+ |
|
443 |
+ // Hah, no, you're just an extra, bye. |
|
444 |
+ if (empty($context['shd_permissions']['user_defined_roles'][$_REQUEST['role']])) |
|
445 |
+ fatal_lang_error('shd_unknown_role', false); |
|
446 |
+ |
|
447 |
+ if (empty($_REQUEST['part'])) |
|
448 |
+ { |
|
449 |
+ $context['page_title'] = $txt['shd_copy_role']; |
|
450 |
+ $context['sub_template'] = 'shd_copy_role'; |
|
451 |
+ checkSubmitOnce('register'); |
|
452 |
+ } |
|
453 |
+ else |
|
454 |
+ { |
|
455 |
+ checkSubmitOnce('check'); |
|
456 |
+ checkSession(); |
|
457 |
+ |
|
458 |
+ // Boring stuff like session checks done. Were you a naughty admin and didn't set it properly? |
|
459 |
+ if (!isset($_POST['rolename']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['rolename'])) === '') |
|
460 |
+ fatal_lang_error('shd_no_role_name', false); |
|
461 |
+ else |
|
462 |
+ $_POST['rolename'] = strtr($smcFunc['htmlspecialchars']($_POST['rolename']), array("\r" => '', "\n" => '', "\t" => '')); |
|
463 |
+ |
|
464 |
+ // So here we are, source role is valid, we're good little admins and specified a name, so let's create the new role in the DB. |
|
465 |
+ $smcFunc['db_insert']('insert', |
|
466 |
+ '{db_prefix}helpdesk_roles', |
|
467 |
+ array( |
|
468 |
+ 'template' => 'int', 'role_name' => 'string', |
|
469 |
+ ), |
|
470 |
+ array( |
|
471 |
+ $context['shd_permissions']['user_defined_roles'][$_REQUEST['role']]['template'], $_POST['rolename'], |
|
472 |
+ ), |
|
473 |
+ array( |
|
474 |
+ 'id_role', |
|
475 |
+ ) |
|
476 |
+ ); |
|
477 |
+ |
|
478 |
+ $newrole = $smcFunc['db_insert_id']('{db_prefix}helpdesk_roles', 'id_role'); |
|
479 |
+ if (empty($newrole)) |
|
480 |
+ fatal_lang_error('shd_could_not_create_role', false); |
|
481 |
+ |
|
482 |
+ // OK, so we made the role. Now add the permissions from the existing role, first grab 'em |
|
483 |
+ $new_perms = array(); |
|
484 |
+ $query = $smcFunc['db_query']('', ' |
|
485 |
+ SELECT permission, add_type |
|
486 |
+ FROM {db_prefix}helpdesk_role_permissions |
|
487 |
+ WHERE id_role = {int:role}', |
|
488 |
+ array( |
|
489 |
+ 'role' => $_REQUEST['role'], |
|
490 |
+ ) |
|
491 |
+ ); |
|
492 |
+ |
|
493 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
494 |
+ $new_perms[] = array((int) $newrole, $row['permission'], (int) $row['add_type']); |
|
495 |
+ |
|
496 |
+ $smcFunc['db_free_result']($query); |
|
497 |
+ |
|
498 |
+ // Now insert them new perms if they got any |
|
499 |
+ if (!empty($new_perms)) |
|
500 |
+ { |
|
501 |
+ $smcFunc['db_insert']('insert', |
|
502 |
+ '{db_prefix}helpdesk_role_permissions', |
|
503 |
+ array( |
|
504 |
+ 'id_role' => 'int', 'permission' => 'string', 'add_type' => 'int', |
|
505 |
+ ), |
|
506 |
+ $new_perms, |
|
507 |
+ array( |
|
508 |
+ 'id_role', 'permission', |
|
509 |
+ ) |
|
510 |
+ ); |
|
511 |
+ } |
|
512 |
+ |
|
513 |
+ // Now copy the groups if they wanted to |
|
514 |
+ if (!empty($_REQUEST['copygroups'])) |
|
515 |
+ { |
|
516 |
+ $groups = array(); |
|
517 |
+ $query = $smcFunc['db_query']('', ' |
|
518 |
+ SELECT id_group |
|
519 |
+ FROM {db_prefix}helpdesk_role_groups |
|
520 |
+ WHERE id_role = {int:role}', |
|
521 |
+ array( |
|
522 |
+ 'role' => $_REQUEST['role'], |
|
523 |
+ ) |
|
524 |
+ ); |
|
525 |
+ |
|
526 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
527 |
+ $groups = array((int) $newrole, (int) $row['id_group']); |
|
528 |
+ |
|
529 |
+ $smcFunc['db_free_result']($query); |
|
530 |
+ |
|
531 |
+ if (!empty($groups)) |
|
532 |
+ { |
|
533 |
+ $smcFunc['db_insert']('insert', |
|
534 |
+ '{db_prefix}helpdesk_role_groups', |
|
535 |
+ array( |
|
536 |
+ 'id_role' => 'int', 'id_group' => 'int', |
|
537 |
+ ), |
|
538 |
+ $groups, |
|
539 |
+ array( |
|
540 |
+ 'id_role', 'id_group', |
|
541 |
+ ) |
|
542 |
+ ); |
|
543 |
+ } |
|
544 |
+ } |
|
545 |
+ |
|
546 |
+ // Take them to the edit screen! |
|
547 |
+ redirectexit('action=admin;area=helpdesk_permissions;sa=editrole;role=' . $newrole); |
|
548 |
+ } |
|
549 |
+} |
|
550 |
+ |
|
551 |
+/** |
|
552 |
+ * Loads user defined roles. |
|
553 |
+ * |
|
554 |
+ * @param int $loadrole Specifies the role to load from the database. If not specified, loads all known roles. |
|
555 |
+ * |
|
556 |
+ * @since 1.1 |
|
557 |
+*/ |
|
558 |
+function shd_load_role($loadrole = 0) |
|
559 |
+{ |
|
560 |
+ global $context, $smcFunc, $scripturl, $txt; |
|
561 |
+ $loadrole = (int) $loadrole; // just in case |
|
562 |
+ |
|
563 |
+ $query = $smcFunc['db_query']('', ' |
|
564 |
+ SELECT id_role, template, role_name |
|
565 |
+ FROM {db_prefix}helpdesk_roles' . (empty($loadrole) ? '' : ' |
|
566 |
+ WHERE id_role = {int:role}') . ' |
|
567 |
+ ORDER BY id_role', |
|
568 |
+ array( |
|
569 |
+ 'role' => $loadrole, |
|
570 |
+ ) |
|
571 |
+ ); |
|
572 |
+ |
|
573 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
574 |
+ { |
|
575 |
+ $context['shd_permissions']['user_defined_roles'][$row['id_role']] = array( |
|
576 |
+ 'template' => $row['template'], |
|
577 |
+ 'name' => $row['role_name'], |
|
578 |
+ ); |
|
579 |
+ } |
|
580 |
+ $smcFunc['db_free_result']($query); |
|
581 |
+ |
|
582 |
+ // OK, are we done already? |
|
583 |
+ if (empty($context['shd_permissions']['user_defined_roles']) || (!empty($loadrole) && empty($context['shd_permissions']['user_defined_roles'][$loadrole]))) |
|
584 |
+ return; |
|
585 |
+ |
|
586 |
+ // Guess not. Now load the roles that are attached to the group(s) |
|
587 |
+ $query = $smcFunc['db_query']('', ' |
|
588 |
+ SELECT hdrg.id_role, hdrg.id_group, mg.group_name, mg.online_color |
|
589 |
+ FROM {db_prefix}helpdesk_role_groups AS hdrg |
|
590 |
+ LEFT JOIN {db_prefix}membergroups AS mg ON (hdrg.id_group = mg.id_group)' . (empty($loadrole) ? '' : ' |
|
591 |
+ WHERE id_role = {int:role}') . ' |
|
592 |
+ ORDER BY hdrg.id_role, hdrg.id_group', |
|
593 |
+ array( |
|
594 |
+ 'role' => $loadrole, |
|
595 |
+ ) |
|
596 |
+ ); |
|
597 |
+ |
|
598 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
599 |
+ { |
|
600 |
+ // WHAT? You're letting REGULAR MEMBERS in?! LIEK 4 REALZ? *shrug* Come on in! :P |
|
601 |
+ if (empty($row['id_group'])) |
|
602 |
+ { |
|
603 |
+ $row['id_group'] = 0; |
|
604 |
+ $row['group_name'] = $txt['membergroups_members']; |
|
605 |
+ $row['color'] = ''; |
|
606 |
+ } |
|
607 |
+ |
|
608 |
+ $context['shd_permissions']['user_defined_roles'][$row['id_role']]['groups'][$row['id_group']] = array( |
|
609 |
+ 'name' => $row['group_name'], |
|
610 |
+ 'color' => $row['online_color'], |
|
611 |
+ 'link' => empty($row['id_group']) ? $row['group_name'] : '<a href="' . $scripturl . '?action=groups;sa=members;group=' . $row['id_group'] . '"' . (empty($row['online_color']) ? '' : ' style="color: ' . $row['online_color'] . ';"') . '>' . $row['group_name'] . '</a>', |
|
612 |
+ ); |
|
613 |
+ } |
|
614 |
+ $smcFunc['db_free_result']($query); |
|
615 |
+ |
|
616 |
+ // OK, lastly fire up the permissions! |
|
617 |
+ // 1. Load the templates |
|
618 |
+ foreach ($context['shd_permissions']['user_defined_roles'] as $role => $role_details) |
|
619 |
+ { |
|
620 |
+ $template = &$context['shd_permissions']['roles'][$role_details['template']]; |
|
621 |
+ $context['shd_permissions']['user_defined_roles'][$role] += array( |
|
622 |
+ 'permissions' => $template['permissions'], |
|
623 |
+ 'template_icon' => $template['icon'], |
|
624 |
+ 'template_name' => $txt[$template['description']], |
|
625 |
+ ); |
|
626 |
+ } |
|
627 |
+ |
|
628 |
+ // 2. Apply the changes from the table to the template(s) forms |
|
629 |
+ $query = $smcFunc['db_query']('', ' |
|
630 |
+ SELECT id_role, permission, add_type |
|
631 |
+ FROM {db_prefix}helpdesk_role_permissions' . (empty($loadrole) ? '' : ' |
|
632 |
+ WHERE id_role = {int:role}'), |
|
633 |
+ array( |
|
634 |
+ 'role' => $loadrole, |
|
635 |
+ ) |
|
636 |
+ ); |
|
637 |
+ |
|
638 |
+ while($row = $smcFunc['db_fetch_assoc']($query)) |
|
639 |
+ $context['shd_permissions']['user_defined_roles'][$row['id_role']]['permissions'][$row['permission']] = $row['add_type']; // if it's defined in the DB it's somehow different to what the template so replace the template |
|
640 |
+ |
|
641 |
+ $smcFunc['db_free_result']($query); |
|
642 |
+} |
|
643 |
+ |
|
644 |
+?> |
|
0 | 645 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,341 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-AdminPlugins.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles the core of SimpleDesk's plugin system administration. |
|
22 |
+ * |
|
23 |
+ * @package source |
|
24 |
+ * @since 1.1 |
|
25 |
+*/ |
|
26 |
+if (!defined('SMF')) |
|
27 |
+ die('Hacking attempt...'); |
|
28 |
+ |
|
29 |
+/** |
|
30 |
+ * The start point for all interaction with the SimpleDesk plugins. |
|
31 |
+ * |
|
32 |
+ * Directed here from the main administration centre, after permission checks and a few dependencies loaded, this deals solely with managing custom fields. |
|
33 |
+ * |
|
34 |
+ * @since 1.1 |
|
35 |
+*/ |
|
36 |
+function shd_admin_plugins() |
|
37 |
+{ |
|
38 |
+ global $context, $scripturl, $sourcedir, $settings, $txt, $modSettings; |
|
39 |
+ |
|
40 |
+ loadTemplate('sd_template/SimpleDesk-AdminPlugins'); |
|
41 |
+ shd_load_language('ManageSettings'); |
|
42 |
+ loadTemplate(false, array('admin', 'helpdesk_admin')); |
|
43 |
+ |
|
44 |
+ $context['shd_enabled_plugins'] = !empty($modSettings['shd_enabled_plugins']) ? explode(',', $modSettings['shd_enabled_plugins']) : array(); |
|
45 |
+ |
|
46 |
+ // 1. Look at the plugin directory and figure out whether or not there are some plugins. |
|
47 |
+ $plugins = array(); |
|
48 |
+ $plugindir = $sourcedir . '/sd_plugins_source'; |
|
49 |
+ $handle = @opendir($plugindir); |
|
50 |
+ while ($dir_entry = readdir($handle)) |
|
51 |
+ { |
|
52 |
+ if (is_dir($plugindir . '/' . $dir_entry) && $dir_entry != '.' && $dir_entry != '..' && file_exists($plugindir . '/' . $dir_entry . '/index.php')) |
|
53 |
+ { |
|
54 |
+ include($plugindir . '/' . $dir_entry . '/index.php'); |
|
55 |
+ $function = 'shdplugin_' . $dir_entry; |
|
56 |
+ if (function_exists($function)) |
|
57 |
+ { |
|
58 |
+ $plugins[$dir_entry] = $function(); |
|
59 |
+ } |
|
60 |
+ } |
|
61 |
+ } |
|
62 |
+ @closedir($handle); |
|
63 |
+ |
|
64 |
+ // 2. Figure out what language stuff is going on |
|
65 |
+ $master_langlist = array( |
|
66 |
+ 'albanian', |
|
67 |
+ 'arabic', |
|
68 |
+ 'bangla', |
|
69 |
+ 'bulgarian', |
|
70 |
+ 'catalan', |
|
71 |
+ 'chinese_simplified', |
|
72 |
+ 'chinese_traditional', |
|
73 |
+ 'croatian', |
|
74 |
+ 'czech', |
|
75 |
+ 'danish', |
|
76 |
+ 'dutch', |
|
77 |
+ 'english', |
|
78 |
+ 'english_british', |
|
79 |
+ 'finnish', |
|
80 |
+ 'french', |
|
81 |
+ 'galician', |
|
82 |
+ 'german', |
|
83 |
+ 'hebrew', |
|
84 |
+ 'hindi', |
|
85 |
+ 'hungarian', |
|
86 |
+ 'indonesian', |
|
87 |
+ 'italian', |
|
88 |
+ 'japanese', |
|
89 |
+ 'kurdish_kurmanji', |
|
90 |
+ 'kurdish_sorani', |
|
91 |
+ 'macedonian', |
|
92 |
+ 'malay', |
|
93 |
+ 'norwegian', |
|
94 |
+ 'persian', |
|
95 |
+ 'polish', |
|
96 |
+ 'portuguese_brazilian', |
|
97 |
+ 'portuguese_pt', |
|
98 |
+ 'romanian', |
|
99 |
+ 'russian', |
|
100 |
+ 'serbian_cyrillic', |
|
101 |
+ 'serbian_latin', |
|
102 |
+ 'slovak', |
|
103 |
+ 'spanish_es', |
|
104 |
+ 'spanish_latin', |
|
105 |
+ 'swedish', |
|
106 |
+ 'thai', |
|
107 |
+ 'turkish', |
|
108 |
+ 'ukrainian', |
|
109 |
+ 'urdu', |
|
110 |
+ 'uzbek_latin', |
|
111 |
+ 'vietnamese', |
|
112 |
+ ); |
|
113 |
+ $langtemplates = array(); |
|
114 |
+ $langfilelist = @opendir($settings['default_theme_dir'] . '/languages/'); |
|
115 |
+ while ($langfile_entry = readdir($langfilelist)) |
|
116 |
+ { |
|
117 |
+ if (preg_match('~([a-z0-9]+)\.([a-z\-\_]+)(-utf8)?\.php$~i', $langfile_entry, $matches)) |
|
118 |
+ $langtemplates[$matches[1]][$matches[2]] = true; |
|
119 |
+ } |
|
120 |
+ @closedir($langfilelist); |
|
121 |
+ |
|
122 |
+ // 3. Figure out what shape the plugins are in |
|
123 |
+ foreach ($plugins as $id => $plugin) |
|
124 |
+ { |
|
125 |
+ // 3.1 Is installable? |
|
126 |
+ if (empty($plugins[$id]['details']['compatibility'])) |
|
127 |
+ $plugins[$id]['details']['compatibility'] = array($txt['unknown']); |
|
128 |
+ $plugins[$id]['installable'] = in_array(SHD_VERSION, $plugin['details']['compatibility']); |
|
129 |
+ |
|
130 |
+ // 3.2 Admin language files? (That also means, let's get a list of known languages for this mod) |
|
131 |
+ $plugins[$id]['languages'] = array(); |
|
132 |
+ if (!empty($plugin['includes']['language']['hdadmin'])) |
|
133 |
+ { |
|
134 |
+ $include = is_array($plugin['includes']['language']['hdadmin']) ? $plugin['includes']['language']['hdadmin'] : array($plugin['includes']['language']['hdadmin']); |
|
135 |
+ if (!empty($include[0])) |
|
136 |
+ $plugins[$id]['languages'] = array_keys($langtemplates[$include[0]]); |
|
137 |
+ foreach ($include as $langfile) |
|
138 |
+ shd_load_language($langfile); |
|
139 |
+ } |
|
140 |
+ |
|
141 |
+ // 3.3 Sort out some strings - now we've loaded the lang file |
|
142 |
+ if (!empty($txt[$plugin['details']['title']])) |
|
143 |
+ $plugins[$id]['details']['title'] = $txt[$plugin['details']['title']]; |
|
144 |
+ if (!empty($plugin['details']['description']) && !empty($txt[$plugin['details']['description']])) |
|
145 |
+ $plugins[$id]['details']['description'] = $txt[$plugin['details']['description']]; |
|
146 |
+ if (empty($plugin['details']['author'])) |
|
147 |
+ $plugins[$id]['details']['author'] = $txt['unknown']; |
|
148 |
+ |
|
149 |
+ // 3.4 Is it enabled? |
|
150 |
+ $plugins[$id]['enabled'] = in_array($id, $context['shd_enabled_plugins']); |
|
151 |
+ $plugins[$id]['details']['acp_url'] = !empty($plugin['details']['acp_url']) && $plugins[$id]['enabled'] ? $plugin['details']['acp_url'] : false; |
|
152 |
+ } |
|
153 |
+ |
|
154 |
+ // 3. Throw it at the template. |
|
155 |
+ $context['sub_template'] = 'shd_plugin_listing'; |
|
156 |
+ $context['plugins'] = $plugins; |
|
157 |
+ $context['page_title'] = $txt['shd_admin_plugins']; |
|
158 |
+ |
|
159 |
+ // 4. Are we saving any changes? |
|
160 |
+ if (isset($_POST['save'])) |
|
161 |
+ { |
|
162 |
+ checkSession(); |
|
163 |
+ |
|
164 |
+ $list_of_settings = shd_list_hooks(); |
|
165 |
+ $setting_changes = array(); |
|
166 |
+ foreach ($list_of_settings as $item) |
|
167 |
+ $setting_changes[$item] = array(); |
|
168 |
+ |
|
169 |
+ $post_var_prefix = empty($_POST['js_worked']) ? 'feature_plain_' : 'feature_'; |
|
170 |
+ |
|
171 |
+ foreach ($plugins as $id => $plugin) |
|
172 |
+ { |
|
173 |
+ if (empty($plugin['installable'])) |
|
174 |
+ continue; // GET OUT YE WRONGLY VERSIONED SHI--STUFF |
|
175 |
+ |
|
176 |
+ // Is it enabled, if so, go do the voodoo that you do so well!!!! |
|
177 |
+ if (!empty($_POST[$post_var_prefix . $id])) |
|
178 |
+ { |
|
179 |
+ $setting_changes['shd_enabled_plugins'][] = $id; |
|
180 |
+ foreach ($plugin['includes']['source'] as $include_point => $include_file) |
|
181 |
+ { |
|
182 |
+ if (isset($setting_changes['shd_include_' . $include_point]) && file_exists($sourcedir . '/sd_plugins_source/' . $id . '/' . $include_file)) |
|
183 |
+ $setting_changes['shd_include_' . $include_point][] = $id . '/' . $include_file; |
|
184 |
+ } |
|
185 |
+ foreach ($plugin['includes']['language'] as $include_point => $include_file) |
|
186 |
+ { |
|
187 |
+ if (isset($setting_changes['shd_includelang_' . $include_point])) |
|
188 |
+ $setting_changes['shd_includelang_' . $include_point][] = $include_file; |
|
189 |
+ } |
|
190 |
+ foreach ($plugin['hooks'] as $include_point => $function) |
|
191 |
+ { |
|
192 |
+ if (isset($setting_changes['shd_hook_' . $include_point])) |
|
193 |
+ $setting_changes['shd_hook_' . $include_point][] = $function; |
|
194 |
+ } |
|
195 |
+ } |
|
196 |
+ |
|
197 |
+ // Is there a call back for settings? |
|
198 |
+ if (isset($plugin['setting_callback'])) |
|
199 |
+ { |
|
200 |
+ $returned_settings = $plugin['setting_callback'](!empty($_POST[$post_var_prefix . $id])); |
|
201 |
+ if (!empty($returned_settings)) |
|
202 |
+ $setting_changes = array_merge($setting_changes, $returned_settings); |
|
203 |
+ } |
|
204 |
+ |
|
205 |
+ // Standard save callback? |
|
206 |
+ if (isset($plugin['on_save'])) |
|
207 |
+ $plugin['on_save'](); |
|
208 |
+ } |
|
209 |
+ |
|
210 |
+ // OK, so whatever we have at this point, we know we're going to be implode'ing and saving. |
|
211 |
+ foreach ($setting_changes as $setting => $array) |
|
212 |
+ $setting_changes[$setting] = implode(',', $array); |
|
213 |
+ |
|
214 |
+ updateSettings($setting_changes); |
|
215 |
+ |
|
216 |
+ // Any post save things? |
|
217 |
+ foreach ($plugins as $id => $plugin) |
|
218 |
+ { |
|
219 |
+ // Standard save callback? |
|
220 |
+ if (isset($plugin['save_callback'])) |
|
221 |
+ $plugin['save_callback'](!empty($_POST[$post_var_prefix . $id])); |
|
222 |
+ } |
|
223 |
+ |
|
224 |
+ redirectexit('action=admin;area=helpdesk_plugins;' . $context['session_var'] . '=' . $context['session_id']); |
|
225 |
+ } |
|
226 |
+} |
|
227 |
+ |
|
228 |
+/** |
|
229 |
+ * Unregister a plugin, to be called from plugin uninstallers. |
|
230 |
+ * |
|
231 |
+ * Expects $context['uninstall_plugin'] to have been defined, as an array with up to four keys: |
|
232 |
+ * - 'name' as a string of the plugin's name (required) |
|
233 |
+ * - 'sources' as an array of files to be purged from source file loaders (e.g. SDPluginMymod.php) |
|
234 |
+ * - 'languages' as an array of files to be purged from language loaders (e.g. SDPluginMymod) |
|
235 |
+ * - 'functions' as an array of functions to be purged from function calls (e.g. shd_mymod_helpdesk, shd_mymod_adminopts) |
|
236 |
+ * |
|
237 |
+ * @since 1.1 |
|
238 |
+*/ |
|
239 |
+function shd_unregister_plugin() |
|
240 |
+{ |
|
241 |
+ global $context, $modSettings; |
|
242 |
+ |
|
243 |
+ // Make sure we're dealing with something sensible |
|
244 |
+ if (empty($context['uninstall_plugin']['sources'])) |
|
245 |
+ $context['uninstall_plugin']['sources'] = array(); |
|
246 |
+ |
|
247 |
+ foreach ($context['uninstall_plugin']['sources'] as $id => $file) |
|
248 |
+ $context['uninstall_plugin']['sources'][$id] = $context['uninstall_plugin']['name'] . '/' . $file; |
|
249 |
+ |
|
250 |
+ // Now language files |
|
251 |
+ if (empty($context['uninstall_plugin']['languages'])) |
|
252 |
+ $context['uninstall_plugin']['languages'] = array(); |
|
253 |
+ |
|
254 |
+ // Now functions |
|
255 |
+ if (empty($context['uninstall_plugin']['functions'])) |
|
256 |
+ $context['uninstall_plugin']['functions'] = array(); |
|
257 |
+ |
|
258 |
+ // Get all the hook points |
|
259 |
+ $hooks = shd_list_hooks(); |
|
260 |
+ |
|
261 |
+ $changes = array(); |
|
262 |
+ foreach ($hooks as $hookpoint) |
|
263 |
+ { |
|
264 |
+ $hook = explode('_', $hookpoint); |
|
265 |
+ if (empty($modSettings[$hookpoint])) |
|
266 |
+ continue; |
|
267 |
+ |
|
268 |
+ switch ($hook[1]) |
|
269 |
+ { |
|
270 |
+ case 'include': |
|
271 |
+ $hooked = explode(',', $modSettings[$hookpoint]); |
|
272 |
+ $hooked = array_diff($hooked, $context['uninstall_plugin']['sources']); |
|
273 |
+ $changes[$hookpoint] = implode(',', $hooked); |
|
274 |
+ break; |
|
275 |
+ case 'includelang': |
|
276 |
+ $hooked = explode(',', $modSettings[$hookpoint]); |
|
277 |
+ $hooked = array_diff($hooked, $context['uninstall_plugin']['languages']); |
|
278 |
+ $changes[$hookpoint] = implode(',', $hooked); |
|
279 |
+ break; |
|
280 |
+ case 'hook': |
|
281 |
+ $hooked = explode(',', $modSettings[$hookpoint]); |
|
282 |
+ $hooked = array_diff($hooked, $context['uninstall_plugin']['functions']); |
|
283 |
+ $changes[$hookpoint] = implode(',', $hooked); |
|
284 |
+ break; |
|
285 |
+ case 'enabled': |
|
286 |
+ $hooked = explode(',', $modSettings[$hookpoint]); |
|
287 |
+ $hooked = array_diff($hooked, array($context['uninstall_plugin']['name'])); |
|
288 |
+ $changes[$hookpoint] = implode(',', $hooked); |
|
289 |
+ break; |
|
290 |
+ } |
|
291 |
+ } |
|
292 |
+ |
|
293 |
+ updateSettings($changes, true); |
|
294 |
+} |
|
295 |
+ |
|
296 |
+function shd_list_hooks() |
|
297 |
+{ |
|
298 |
+ // This is our master set of hooks and stuff, so FOR THE LOVE OF DEITIES, GET IT RIGHT. |
|
299 |
+ // Anything added here should also be added to the master uninstall-optional.php too |
|
300 |
+ return array( |
|
301 |
+ 'shd_enabled_plugins', // for the list of plugins generally |
|
302 |
+ |
|
303 |
+ // File loading - sources |
|
304 |
+ 'shd_include_init', // source files to include on SD init, i.e. every page load when the helpdesk is active |
|
305 |
+ 'shd_include_helpdesk', // source files to include when going into the helpdesk (action=helpdesk) |
|
306 |
+ 'shd_include_hdadmin', // source files to include when going into any part of the helpdesk admin |
|
307 |
+ 'shd_include_hdprofile', // source files to include when going into any part of the helpdesk profile |
|
308 |
+ |
|
309 |
+ // File loading - lang files |
|
310 |
+ 'shd_includelang_init', // language files to include on SD init, i.e. every page load when the helpdesk is active |
|
311 |
+ 'shd_includelang_helpdesk', // language files to include when going into the helpdesk (action=helpdesk) |
|
312 |
+ 'shd_includelang_hdadmin', // language files to include when going into any part of the helpdesk admin |
|
313 |
+ 'shd_includelang_hdprofile', // language files to include when going into any part of the helpdesk profile |
|
314 |
+ 'shd_includelang_who', // language files to include when going into Who's Online |
|
315 |
+ |
|
316 |
+ // General hooks |
|
317 |
+ 'shd_hook_actions', // functions to run when looking at the action array (where action=x is evaluated) |
|
318 |
+ 'shd_hook_perms', // functions to add permissions (relevant file probably should be included in the _include_init hook) |
|
319 |
+ 'shd_hook_permstemplate', // functions to add permissions to any of the templates (relevant file probably should be included in the _include_init hook) |
|
320 |
+ 'shd_hook_prefs', // functions to add preferences (relevant file probably should be included in the _include_init hook) |
|
321 |
+ 'shd_hook_newticket', // functions to call when just a new ticket is made |
|
322 |
+ 'shd_hook_newreply', // functions to call when a new reply is made |
|
323 |
+ 'shd_hook_modpost', // functions to call when a ticket or reply is edited (since all kinds of things might be altered) |
|
324 |
+ 'shd_hook_assign', // functions to call when a ticket is assigned to someone |
|
325 |
+ 'shd_hook_buffer', // functions to call prior to the final page generation |
|
326 |
+ 'shd_hook_postingopts', // functions to call to augment the additional options on posting screen |
|
327 |
+ |
|
328 |
+ // Menu hooks - called after the rest of menu configuration is done (meaning menu items may or may not exist depending on permissions) |
|
329 |
+ 'shd_hook_mainmenu', // functions to call when looking at the main menu |
|
330 |
+ 'shd_hook_profilemenu', // functions to call when specifically modifying the profile menu |
|
331 |
+ 'shd_hook_adminmenu', // functions to call when specifically modifying the admin menu |
|
332 |
+ |
|
333 |
+ // Area level hooks |
|
334 |
+ 'shd_hook_helpdesk', // functions to run when starting the main helpdesk (before going off to subactions) |
|
335 |
+ 'shd_hook_hdadmin', // functions to run when starting the main SimpleDesk admin area (probably should include via _include_hdadmin) |
|
336 |
+ 'shd_hook_hdadminopts', // functions to run when working in the SimpleDesk options submenu structure (probably should include via _include_hdadmin) |
|
337 |
+ 'shd_hook_hdadminoptssrch', // functions to run when setting up admin panel search for SimpleDesk options submenu structure (probably should include via _include_hdadmin) |
|
338 |
+ 'shd_hook_hdprofile', // functions to call when going into the helpdesk profile area |
|
339 |
+ ); |
|
340 |
+} |
|
341 |
+?> |
|
0 | 342 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,361 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-AjaxHandler.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles all the actions that can be carried out through AJAX methods, performing them and providing adequate feedback/information. |
|
22 |
+ * |
|
23 |
+ * @package source |
|
24 |
+ * @since 1.0 |
|
25 |
+*/ |
|
26 |
+ |
|
27 |
+if (!defined('SMF')) |
|
28 |
+ die('Hacking attempt...'); |
|
29 |
+ |
|
30 |
+// This file handles AJAX actions. This file accepts params and only dumps XML out, much like News.php we do it all here. |
|
31 |
+// What happens is we expect $context['ajax_return'], an array of responses, to be populated. |
|
32 |
+// key => value for single XML tag, key => array (values) for multiple tags |
|
33 |
+// e.g. array('errors' => 'You do not have permission') => <errors><![CDATA[You do not have permission]]></errors> |
|
34 |
+// or array('data' => array('myval1', 'myval2')) => <data><![CDATA[myval1]]></data> <data><![CDATA[myval2]]></data> |
|
35 |
+ |
|
36 |
+/** |
|
37 |
+ * Receives AJAX requests and facilitates replying to them. |
|
38 |
+ * |
|
39 |
+ * This function sets up and calls the AJAX handlers; it is the primary receiver for action=helpdesk;sa=ajax. |
|
40 |
+ * |
|
41 |
+ * Primarily, it expects $context['ajax_return'] to be populated as an array of tags to be returned as XML items to the user, with this element |
|
42 |
+ * being a key-value pair (e.g. $context['ajax_return']['message'] = 'Success!') to be returned as a literal tag, element message, value of |
|
43 |
+ * Success!, wrapped in the character data block. |
|
44 |
+ * |
|
45 |
+ * An AJAX handler function may also return content in $context['ajax_raw'], this is when the function has prepared its own XML block to return. |
|
46 |
+ * In such an instance, this function simply outputs the xml headers and assumes the return value is otherwise value. |
|
47 |
+ * |
|
48 |
+ * For example, if the error subarray is populated (['error'] = 'Insufficient permission'), the XML block will contain a tag called error, |
|
49 |
+ * with a CDATA block containing 'Insufficient permission'. |
|
50 |
+ * |
|
51 |
+ * @since 1.0 |
|
52 |
+*/ |
|
53 |
+function shd_ajax() |
|
54 |
+{ |
|
55 |
+ global $context; |
|
56 |
+ |
|
57 |
+ // Just in case |
|
58 |
+ loadLanguage('Errors'); |
|
59 |
+ |
|
60 |
+ $subactions = array( |
|
61 |
+ 'privacy' => 'shd_ajax_privacy', |
|
62 |
+ 'urgency' => 'shd_ajax_urgency', |
|
63 |
+ 'quote' => 'shd_ajax_quote', |
|
64 |
+ ); |
|
65 |
+ |
|
66 |
+ $context['ajax_return'] = array(); |
|
67 |
+ $context['ajax_raw'] = ''; |
|
68 |
+ |
|
69 |
+ if (!empty($_REQUEST['op']) && !empty($subactions[$_REQUEST['op']])) |
|
70 |
+ $subactions[$_REQUEST['op']](); |
|
71 |
+ |
|
72 |
+ header('Content-Type: text/xml; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); |
|
73 |
+ echo '<?xml version="1.0" encoding="', $context['character_set'], '"?' . '>'; |
|
74 |
+ |
|
75 |
+ if (empty($context['ajax_raw'])) // if something wants to do something funky, let it otherwise use the standard format |
|
76 |
+ { |
|
77 |
+ echo '<response>'; |
|
78 |
+ |
|
79 |
+ if (!empty($context['ajax_return'])) |
|
80 |
+ { |
|
81 |
+ foreach ($context['ajax_return'] as $key => $value) |
|
82 |
+ { |
|
83 |
+ if (empty($value)) // for <tag /> |
|
84 |
+ echo ' |
|
85 |
+ <', $key, ' />'; |
|
86 |
+ else |
|
87 |
+ { |
|
88 |
+ $value = (array) $value; |
|
89 |
+ foreach ($value as $thisvalue) |
|
90 |
+ echo ' |
|
91 |
+ <', $key, '><![CDATA[', $thisvalue, ']]></', $key, '>'; |
|
92 |
+ } |
|
93 |
+ } |
|
94 |
+ } |
|
95 |
+ |
|
96 |
+ echo ' |
|
97 |
+</response>'; |
|
98 |
+ } |
|
99 |
+ else |
|
100 |
+ { |
|
101 |
+ echo $context['ajax_raw']; // assumed to be just well formed XML sans the header |
|
102 |
+ } |
|
103 |
+ obExit(false); |
|
104 |
+} |
|
105 |
+ |
|
106 |
+/** |
|
107 |
+ * Handles AJAX updates to privacy. |
|
108 |
+ * |
|
109 |
+ * Receives a request via ?action=helpdesk;sa=ajax;op=privacy to flip the privacy setting. |
|
110 |
+ * |
|
111 |
+ * Operations: |
|
112 |
+ * - silent session check; if fail, add to $context['ajax_return']['error'] |
|
113 |
+ * - ticket id check; if fail, add to $context['ajax_return']['error'] |
|
114 |
+ * - get enough ticket data to do this |
|
115 |
+ * - check if the ticket is not able to be updated (either is closed/deleted, or insufficient permissions); if fail add to $context['ajax_return']['error'] |
|
116 |
+ * - switch privacy, update database |
|
117 |
+ * - clear the cache of tickets for the Helpdesk menu item |
|
118 |
+ * - return $context['ajax_return']['message'] as the new privacy item |
|
119 |
+*/ |
|
120 |
+function shd_ajax_privacy() |
|
121 |
+{ |
|
122 |
+ global $smcFunc, $user_info, $context, $txt, $sourcedir; |
|
123 |
+ |
|
124 |
+ $session_check = checkSession('get', '', false); // check the session but don't die fatally. |
|
125 |
+ if (!empty($session_check)) |
|
126 |
+ { |
|
127 |
+ $context['ajax_return'] = array('error' => $txt[$session_check]); |
|
128 |
+ return; |
|
129 |
+ } |
|
130 |
+ |
|
131 |
+ // First, figure out the state of the ticket - is it private or not? Can we even see it? |
|
132 |
+ if (empty($context['ticket_id'])) |
|
133 |
+ { |
|
134 |
+ $context['ajax_return'] = array('error' => $txt['shd_no_ticket']); |
|
135 |
+ return; |
|
136 |
+ } |
|
137 |
+ |
|
138 |
+ $query = shd_db_query('', ' |
|
139 |
+ SELECT id_member_started, subject, private, status |
|
140 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
141 |
+ WHERE {query_see_ticket} |
|
142 |
+ AND id_ticket = {int:current_ticket}', |
|
143 |
+ array( |
|
144 |
+ 'current_ticket' => $context['ticket_id'], |
|
145 |
+ ) |
|
146 |
+ ); |
|
147 |
+ |
|
148 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
149 |
+ { |
|
150 |
+ if (in_array($row['status'], array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED)) || !shd_allowed_to('shd_alter_privacy_any') && (!shd_allowed_to('shd_alter_privacy_own') || $row['id_member_started'] != $user_info['id'])) |
|
151 |
+ { |
|
152 |
+ $context['ajax_return'] = array('error' => $txt['shd_cannot_change_privacy']); |
|
153 |
+ return; |
|
154 |
+ } |
|
155 |
+ |
|
156 |
+ $smcFunc['db_free_result']($query); |
|
157 |
+ |
|
158 |
+ $new = empty($row['private']) ? 1 : 0; |
|
159 |
+ $action = empty($row['private']) ? 'markprivate' : 'marknotprivate'; |
|
160 |
+ |
|
161 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
162 |
+ $msgOptions = array(); |
|
163 |
+ $posterOptions = array(); |
|
164 |
+ $ticketOptions = array( |
|
165 |
+ 'id' => $context['ticket_id'], |
|
166 |
+ 'private' => empty($row['private']), |
|
167 |
+ ); |
|
168 |
+ |
|
169 |
+ shd_modify_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
170 |
+ |
|
171 |
+ shd_log_action($action, |
|
172 |
+ array( |
|
173 |
+ 'ticket' => $context['ticket_id'], |
|
174 |
+ 'subject' => $row['subject'], |
|
175 |
+ ) |
|
176 |
+ ); |
|
177 |
+ |
|
178 |
+ // Make sure we recalculate the number of tickets on next page load |
|
179 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
180 |
+ |
|
181 |
+ $context['ajax_return'] = array('message' => $new ? $txt['shd_ticket_private'] : $txt['shd_ticket_notprivate']); |
|
182 |
+ } |
|
183 |
+ else |
|
184 |
+ { |
|
185 |
+ $context['ajax_return'] = array('error' => $txt['shd_no_ticket']); |
|
186 |
+ return; |
|
187 |
+ } |
|
188 |
+} |
|
189 |
+ |
|
190 |
+/** |
|
191 |
+ * Handles AJAX updates to ticket urgency. |
|
192 |
+ * |
|
193 |
+ * Receives request through ?action=helpdesk;sa=ajax;op=urgency;change=x where x is increase or decrease. |
|
194 |
+ * |
|
195 |
+ * Operations: |
|
196 |
+ * - silent session check; if fail, add to $context['ajax_return']['error'] |
|
197 |
+ * - ticket id check; if fail, add to $context['ajax_return']['error'] |
|
198 |
+ * - get enough ticket data to do this |
|
199 |
+ * - check permissions with {@link shd_can_alter_urgency()} and permissions; if fail, add to $context['ajax_return']['error'] |
|
200 |
+ * - identify whether the new urgency needs 'urgent' styling or not and put the new urgency in $context['ajax_return']['message'] |
|
201 |
+ * - update the database with the new urgency |
|
202 |
+ * - identify whether the new urgency continues to allow the current user to change urgency or not |
|
203 |
+ * - put the button links if appropriate into $context['ajax_return']['increase'] and $context['ajax_return']['decrease'] and return |
|
204 |
+*/ |
|
205 |
+function shd_ajax_urgency() |
|
206 |
+{ |
|
207 |
+ global $smcFunc, $user_info, $context, $txt, $scripturl, $settings, $sourcedir; |
|
208 |
+ |
|
209 |
+ $session_check = checkSession('get', '', false); // check the session but don't die fatally. |
|
210 |
+ if (!empty($session_check)) |
|
211 |
+ { |
|
212 |
+ $context['ajax_return'] = array('error' => $txt[$session_check]); |
|
213 |
+ return; |
|
214 |
+ } |
|
215 |
+ |
|
216 |
+ // First, figure out the state of the ticket - is it private or not? Can we even see it? |
|
217 |
+ if (empty($context['ticket_id'])) |
|
218 |
+ { |
|
219 |
+ $context['ajax_return'] = array('error' => $txt['shd_no_ticket']); |
|
220 |
+ return; |
|
221 |
+ } |
|
222 |
+ |
|
223 |
+ $query = shd_db_query('', ' |
|
224 |
+ SELECT id_member_started, subject, urgency, status |
|
225 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
226 |
+ WHERE {query_see_ticket} |
|
227 |
+ AND id_ticket = {int:current_ticket}', |
|
228 |
+ array( |
|
229 |
+ 'current_ticket' => $context['ticket_id'], |
|
230 |
+ ) |
|
231 |
+ ); |
|
232 |
+ |
|
233 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
234 |
+ { |
|
235 |
+ $can_urgency = shd_can_alter_urgency($row['urgency'], $row['id_member_started'], ($row['status'] == TICKET_STATUS_CLOSED), ($row['status'] == TICKET_STATUS_DELETED)); |
|
236 |
+ |
|
237 |
+ if (empty($_GET['change']) || empty($can_urgency[$_GET['change']])) |
|
238 |
+ { |
|
239 |
+ $context['ajax_return'] = array('error' => $txt['shd_cannot_change_urgency']); |
|
240 |
+ return; |
|
241 |
+ } |
|
242 |
+ |
|
243 |
+ $new_urgency = $row['urgency'] + ($_GET['change'] == 'increase' ? 1 : -1); |
|
244 |
+ $action = 'urgency_' . $_GET['change']; |
|
245 |
+ |
|
246 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
247 |
+ $msgOptions = array(); |
|
248 |
+ $posterOptions = array(); |
|
249 |
+ $ticketOptions = array( |
|
250 |
+ 'id' => $context['ticket_id'], |
|
251 |
+ 'urgency' => $new_urgency, |
|
252 |
+ ); |
|
253 |
+ |
|
254 |
+ shd_modify_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
255 |
+ |
|
256 |
+ shd_log_action($action, |
|
257 |
+ array( |
|
258 |
+ 'ticket' => $context['ticket_id'], |
|
259 |
+ 'subject' => $row['subject'], |
|
260 |
+ 'urgency' => $new_urgency, |
|
261 |
+ ) |
|
262 |
+ ); |
|
263 |
+ |
|
264 |
+ $new_options = shd_can_alter_urgency($new_urgency, $row['id_member_started'], ($row['status'] == TICKET_STATUS_CLOSED), ($row['status'] == TICKET_STATUS_DELETED)); |
|
265 |
+ |
|
266 |
+ $context['ajax_return'] = array( |
|
267 |
+ 'message' => $new_urgency > TICKET_URGENCY_HIGH ? '<span class="error">' . $txt['shd_urgency_' . $new_urgency] . '</span>' : $txt['shd_urgency_' . $new_urgency], |
|
268 |
+ ); |
|
269 |
+ |
|
270 |
+ $array = array( |
|
271 |
+ 'increase' => '<a id="urglink_increase" href="' . $scripturl . '?action=helpdesk;sa=urgencychange;ticket=' . $context['ticket_id'] . ';change=increase;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_urgency_increase'] . '"><img src="' . $settings['images_url'] . '/sort_up.gif" width="9px" alt="' . $txt['shd_urgency_increase'] . '" /></a>', |
|
272 |
+ 'decrease' => '<a id="urglink_decrease" href="' . $scripturl . '?action=helpdesk;sa=urgencychange;ticket=' . $context['ticket_id'] . ';change=decrease;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_urgency_decrease'] . '"><img src="' . $settings['images_url'] . '/sort_down.gif" width="9px" alt="' . $txt['shd_urgency_decrease'] . '" /></a>', |
|
273 |
+ ); |
|
274 |
+ |
|
275 |
+ foreach ($new_options as $button => $can) |
|
276 |
+ if ($can) |
|
277 |
+ $context['ajax_return'][$button] = $array[$button]; |
|
278 |
+ |
|
279 |
+ return; |
|
280 |
+ } |
|
281 |
+ else |
|
282 |
+ { |
|
283 |
+ $context['ajax_return'] = array('error' => $txt['shd_no_ticket']); |
|
284 |
+ return; |
|
285 |
+ } |
|
286 |
+} |
|
287 |
+ |
|
288 |
+/** |
|
289 |
+ * Collects ticket post data for quoting posts through AJAX (i.e. inserting a quote live into the postbox) |
|
290 |
+ * |
|
291 |
+ * Operations: |
|
292 |
+ * - Session check; failing in a regular fashion (as opposed to normal return since we're using ;xml in the URL; the SMF handler can deal with that) |
|
293 |
+ * - If a message id is provided, query for it. If not found (or not provided), die, otherwise continue. |
|
294 |
+ * - Call un_preparsecode to remove extraneous sanity encoding. |
|
295 |
+ * - Build the [quote] bbcode around the post body. |
|
296 |
+ * - Convert to SMF style BBC-to-HTML if using WYSIWYG |
|
297 |
+ * - Do other XML sanitising |
|
298 |
+ * - Return via $context['ajax_raw'] for {@link shd_ajax()} to output |
|
299 |
+*/ |
|
300 |
+function shd_ajax_quote() |
|
301 |
+{ |
|
302 |
+ global $modSettings, $user_info, $txt, $settings, $context; |
|
303 |
+ global $sourcedir, $smcFunc; |
|
304 |
+ |
|
305 |
+ loadLanguage('Post'); |
|
306 |
+ checkSession('get'); |
|
307 |
+ |
|
308 |
+ include_once($sourcedir . '/Subs-Post.php'); |
|
309 |
+ |
|
310 |
+ $_REQUEST['quote'] = !empty($_REQUEST['quote']) ? (int) $_REQUEST['quote'] : 0; |
|
311 |
+ $message = ''; |
|
312 |
+ if (!empty($_REQUEST['quote'])) |
|
313 |
+ { |
|
314 |
+ $query = shd_db_query('', ' |
|
315 |
+ SELECT hdtr.body, IFNULL(mem.real_name, hdtr.poster_name) AS poster_name, hdtr.poster_time, hdt.id_ticket, hdt.id_first_msg |
|
316 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
317 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket) |
|
318 |
+ LEFT JOIN {db_prefix}members AS mem ON (hdtr.id_member = mem.id_member) |
|
319 |
+ WHERE {query_see_ticket} |
|
320 |
+ AND id_msg = {int:msg}', |
|
321 |
+ array( |
|
322 |
+ 'msg' => $_REQUEST['quote'], |
|
323 |
+ ) |
|
324 |
+ ); |
|
325 |
+ |
|
326 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
327 |
+ { |
|
328 |
+ $smcFunc['db_free_result']($query); |
|
329 |
+ $row['body'] = un_preparsecode($row['body']); |
|
330 |
+ |
|
331 |
+ // Censor the message! |
|
332 |
+ censorText($row['body']); |
|
333 |
+ $row['body'] = preg_replace('~<br ?/?' . '>~i', "\n", $row['body']); |
|
334 |
+ |
|
335 |
+ if (strpos($row['poster_name'], '[') !== false || strpos($row['poster_name'], ']') !== false) |
|
336 |
+ $row['poster_name'] = '"' . $row['poster_name'] . '"'; |
|
337 |
+ |
|
338 |
+ // Make the body HTML if need be. |
|
339 |
+ if (!empty($_REQUEST['mode'])) |
|
340 |
+ { |
|
341 |
+ require_once($sourcedir . '/Subs-Editor.php'); |
|
342 |
+ $row['body'] = strtr($row['body'], array('<' => '#smlt#', '>' => '#smgt#', '&' => '#smamp#')); |
|
343 |
+ $row['body'] = bbc_to_html($row['body']); |
|
344 |
+ $lb = '<br />'; |
|
345 |
+ } |
|
346 |
+ else |
|
347 |
+ $lb = "\n"; |
|
348 |
+ |
|
349 |
+ $message = '[quote author=' . $row['poster_name'] . ' link=action=helpdesk;sa=ticket;ticket=' . $row['id_ticket']; |
|
350 |
+ if ($row['id_first_msg'] != $_REQUEST['quote']) // don't add the msg if we're quoting the ticket itself |
|
351 |
+ $message .= '.msg' . $_REQUEST['quote'] . '#msg' . $_REQUEST['quote']; |
|
352 |
+ |
|
353 |
+ $message .= ' date=' . $row['poster_time'] . ']' . $lb . $row['body'] . $lb . '[/quote]'; |
|
354 |
+ } |
|
355 |
+ } |
|
356 |
+ |
|
357 |
+ $message = strtr($message, array(' ' => ' ', '<' => '<', '>' => '>')); |
|
358 |
+ |
|
359 |
+ $context['ajax_raw'] = '<quote>' . $message . '</quote>'; |
|
360 |
+} |
|
361 |
+?> |
|
0 | 362 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,370 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Assign.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles ticket assignments, both the user interface for the assignment page, plus |
|
22 |
+ * actually assigning users to tickets. There are also helper functions here for that purpose. |
|
23 |
+ * |
|
24 |
+ * @package source |
|
25 |
+ * @since 1.0 |
|
26 |
+*/ |
|
27 |
+ |
|
28 |
+if (!defined('SMF')) |
|
29 |
+ die('Hacking attempt...'); |
|
30 |
+ |
|
31 |
+/** |
|
32 |
+ * Sets up the assignment UI and invokes the template. |
|
33 |
+ * |
|
34 |
+ * This validates that the user can see the ticket in question initially, before determining the level of assignment that can be |
|
35 |
+ * carried out. |
|
36 |
+ * |
|
37 |
+ * Users who can assign any ticket cause a query to trigger to identify users who have shd_staff permission (and thus can be the |
|
38 |
+ * target of assignment) and the template is loaded with a dropdown to provide this choice to the user. |
|
39 |
+ * |
|
40 |
+ * Users who can only assign to themselves will at this point have the ticket assigned to them if it was unassigned before, or |
|
41 |
+ * unassigned from them if they are able to assign tickets to themselves in the first place; if it was assigned to someone else, |
|
42 |
+ * they will not have the option. |
|
43 |
+ * |
|
44 |
+ * Access through action=helpdesk;sa=assign;ticket=x;sessvar=sessid before redirecting back to the ticket, or add ;home to the |
|
45 |
+ * URL to have it redirect back to the home page (passed through to the form for {@link shd_assign2()}'s use too) |
|
46 |
+ * |
|
47 |
+ * @see shd_assign2() |
|
48 |
+ * @see shd_get_possible_assignees() |
|
49 |
+ * @since 1.0 |
|
50 |
+*/ |
|
51 |
+function shd_assign() |
|
52 |
+{ |
|
53 |
+ global $smcFunc, $context, $user_info, $sourcedir, $txt, $scripturl; |
|
54 |
+ |
|
55 |
+ checkSession('get'); |
|
56 |
+ |
|
57 |
+ if (empty($context['ticket_id'])) |
|
58 |
+ fatal_lang_error('shd_no_ticket'); |
|
59 |
+ |
|
60 |
+ $context['shd_return_to'] = isset($_REQUEST['home']) ? 'home' : 'ticket'; |
|
61 |
+ |
|
62 |
+ // Get ticket details - and kick it out if they shouldn't be able to see it. |
|
63 |
+ $query = shd_db_query('', ' |
|
64 |
+ SELECT id_member_started, id_member_assigned, private, subject |
|
65 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
66 |
+ WHERE {query_see_ticket} AND id_ticket = {int:ticket}', |
|
67 |
+ array( |
|
68 |
+ 'ticket' => $context['ticket_id'], |
|
69 |
+ ) |
|
70 |
+ ); |
|
71 |
+ |
|
72 |
+ $log_params = array(); |
|
73 |
+ if ($row = $smcFunc['db_fetch_row']($query)) |
|
74 |
+ { |
|
75 |
+ list($ticket_starter, $ticket_owner, $private, $subject) = $row; |
|
76 |
+ $log_params = array( |
|
77 |
+ 'subject' => $subject, |
|
78 |
+ 'ticket' => $context['ticket_id'], |
|
79 |
+ ); |
|
80 |
+ } |
|
81 |
+ else |
|
82 |
+ { |
|
83 |
+ $smcFunc['db_free_result']($query); |
|
84 |
+ fatal_lang_error('shd_no_ticket'); |
|
85 |
+ } |
|
86 |
+ |
|
87 |
+ if (shd_allowed_to('shd_assign_ticket_any')) // can regularly assign? If so, load up potential candidates and throw it at the template. |
|
88 |
+ { |
|
89 |
+ $members = shd_get_possible_assignees($private, $ticket_starter); |
|
90 |
+ |
|
91 |
+ if (!in_array($ticket_owner, $members)) // if for whatever reason the current assignee is not accessible staff, treat it as unassigned |
|
92 |
+ $ticket_owner = 0; |
|
93 |
+ |
|
94 |
+ if (!empty($members)) |
|
95 |
+ { |
|
96 |
+ $query = shd_db_query('', ' |
|
97 |
+ SELECT id_member, real_name |
|
98 |
+ FROM {db_prefix}members |
|
99 |
+ WHERE id_member IN ({array_int:members}) |
|
100 |
+ ORDER BY real_name', |
|
101 |
+ array( |
|
102 |
+ 'members' => $members, |
|
103 |
+ ) |
|
104 |
+ ); |
|
105 |
+ |
|
106 |
+ $members = array(); |
|
107 |
+ |
|
108 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
109 |
+ $members[$row['id_member']] = $row['real_name']; |
|
110 |
+ } |
|
111 |
+ |
|
112 |
+ if (empty($members)) |
|
113 |
+ fatal_lang_error('shd_no_staff_assign'); |
|
114 |
+ |
|
115 |
+ $context['linktree'][] = array( |
|
116 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
117 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
118 |
+ ); |
|
119 |
+ $context['linktree'][] = array( |
|
120 |
+ 'url' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'], |
|
121 |
+ 'name' => $subject, |
|
122 |
+ ); |
|
123 |
+ $context['linktree'][] = array( |
|
124 |
+ 'name' => $txt['shd_ticket_assign_ticket'], |
|
125 |
+ ); |
|
126 |
+ |
|
127 |
+ $context['member_list'] = array(0 => $txt['shd_unassigned']) + $members; |
|
128 |
+ $context['ticket_assigned'] = $ticket_owner; |
|
129 |
+ |
|
130 |
+ $context['page_title'] = $txt['shd_ticket_assign_ticket']; |
|
131 |
+ |
|
132 |
+ loadTemplate('sd_template/SimpleDesk-Assign'); |
|
133 |
+ $context['sub_template'] = 'assign'; |
|
134 |
+ } |
|
135 |
+ elseif (shd_allowed_to('shd_assign_ticket_own') && shd_allowed_to('shd_staff')) // can't just randomly assign (and must be staff), so look at if it's already assigned or not. |
|
136 |
+ { |
|
137 |
+ if ($ticket_owner == 0) // unassigned |
|
138 |
+ { |
|
139 |
+ $log_params += array( |
|
140 |
+ 'user_id' => $user_info['id'], |
|
141 |
+ 'user_name' => $user_info['name'], |
|
142 |
+ ); |
|
143 |
+ shd_log_action('assign', $log_params); |
|
144 |
+ shd_commit_assignment($context['ticket_id'], $user_info['id']); |
|
145 |
+ } |
|
146 |
+ elseif ($ticket_starter == $user_info['id']) // assigned to self already, unassign it |
|
147 |
+ { |
|
148 |
+ shd_log_action('unassign', $log_params); |
|
149 |
+ shd_commit_assignment($context['ticket_id'], 0); |
|
150 |
+ } |
|
151 |
+ else // oops, assigned to somebody else |
|
152 |
+ fatal_lang_error('shd_cannot_assign_other', false); |
|
153 |
+ } |
|
154 |
+ else |
|
155 |
+ fatal_lang_error('shd_cannot_assign', false); |
|
156 |
+} |
|
157 |
+ |
|
158 |
+/** |
|
159 |
+ * Handles the actual assignment form, validates it and carries it out. |
|
160 |
+ * |
|
161 |
+ * Primarily this is just about receiving the form, making the same checks that {@link shd_assign()} does and then |
|
162 |
+ * logging the action before passing over to {@link shd_commit_assignment()} to actually assign the ticket. |
|
163 |
+ * |
|
164 |
+ * @see shd_assign() |
|
165 |
+ * @see shd_commit_assignment() |
|
166 |
+ * @since 1.0 |
|
167 |
+*/ |
|
168 |
+function shd_assign2() |
|
169 |
+{ |
|
170 |
+ global $context, $smcFunc, $user_info, $sourcedir; |
|
171 |
+ |
|
172 |
+ checkSession(); |
|
173 |
+ checkSubmitOnce('check'); |
|
174 |
+ |
|
175 |
+ if (empty($context['ticket_id'])) |
|
176 |
+ fatal_lang_error('shd_no_ticket'); |
|
177 |
+ |
|
178 |
+ $context['shd_return_to'] = isset($_REQUEST['home']) ? 'home' : 'ticket'; |
|
179 |
+ |
|
180 |
+ $assignee = isset($_REQUEST['to_user']) ? (int) $_REQUEST['to_user'] : 0; |
|
181 |
+ |
|
182 |
+ // Get ticket details - and kick it out if they shouldn't be able to see it. |
|
183 |
+ $query = shd_db_query('', ' |
|
184 |
+ SELECT id_member_started, id_member_assigned, private, subject |
|
185 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
186 |
+ WHERE {query_see_ticket} AND id_ticket = {int:ticket}', |
|
187 |
+ array( |
|
188 |
+ 'ticket' => $context['ticket_id'], |
|
189 |
+ ) |
|
190 |
+ ); |
|
191 |
+ |
|
192 |
+ $log_params = array(); |
|
193 |
+ |
|
194 |
+ if ($row = $smcFunc['db_fetch_row']($query)) |
|
195 |
+ { |
|
196 |
+ list($ticket_starter, $ticket_owner, $private, $subject) = $row; |
|
197 |
+ |
|
198 |
+ // The core details that we'll be logging |
|
199 |
+ $log_params = array( |
|
200 |
+ 'subject' => $subject, |
|
201 |
+ 'ticket' => $context['ticket_id'], |
|
202 |
+ ); |
|
203 |
+ } |
|
204 |
+ else |
|
205 |
+ { |
|
206 |
+ $smcFunc['db_free_result']($query); |
|
207 |
+ fatal_lang_error('shd_no_ticket'); |
|
208 |
+ } |
|
209 |
+ |
|
210 |
+ // Just in case, are they cancelling? |
|
211 |
+ if (isset($_REQUEST['cancel'])) |
|
212 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
213 |
+ |
|
214 |
+ if (shd_allowed_to('shd_assign_ticket_any')) // can regularly assign? If so, see if our requested member is staff and can see the ticket |
|
215 |
+ { |
|
216 |
+ if ($assignee == 0) // can always unassign a ticket |
|
217 |
+ { |
|
218 |
+ shd_log_action('unassign', $log_params); |
|
219 |
+ shd_commit_assignment($context['ticket_id'], 0); |
|
220 |
+ } |
|
221 |
+ else |
|
222 |
+ { |
|
223 |
+ $members = shd_get_possible_assignees($private, $ticket_starter); |
|
224 |
+ |
|
225 |
+ if (in_array($assignee, $members)) // can only assign a ticket to a member if they're on Santa's good list |
|
226 |
+ { |
|
227 |
+ global $user_profile; |
|
228 |
+ loadMemberData($assignee, false, 'minimal'); |
|
229 |
+ $log_params += array( |
|
230 |
+ 'user_id' => $assignee, |
|
231 |
+ 'user_name' => $user_profile[$assignee]['real_name'], |
|
232 |
+ ); |
|
233 |
+ shd_log_action('assign', $log_params); |
|
234 |
+ shd_commit_assignment($context['ticket_id'], $assignee); |
|
235 |
+ } |
|
236 |
+ else |
|
237 |
+ fatal_lang_error('shd_assigned_not_permitted', false); |
|
238 |
+ } |
|
239 |
+ } |
|
240 |
+ elseif (shd_allowed_to('shd_assign_ticket_own') && shd_allowed_to('shd_staff')) // can't just randomly assign (and must be staff), so look at if it's already assigned or not. |
|
241 |
+ { |
|
242 |
+ if ($ticket_owner == 0) // unassigned |
|
243 |
+ { |
|
244 |
+ $log_params += array( |
|
245 |
+ 'user_id' => $user_info['id'], |
|
246 |
+ 'user_name' => $user_info['name'], |
|
247 |
+ ); |
|
248 |
+ shd_log_action('assign', $log_params); |
|
249 |
+ shd_commit_assignment($context['ticket_id'], $user_info['id']); |
|
250 |
+ } |
|
251 |
+ elseif ($ticket_starter == $user_info['id']) // assigned to self already, unassign it |
|
252 |
+ { |
|
253 |
+ shd_log_action('unassign', $log_params); |
|
254 |
+ shd_commit_assignment($context['ticket_id'], 0); |
|
255 |
+ } |
|
256 |
+ else // oops, assigned to somebody else |
|
257 |
+ fatal_lang_error('shd_cannot_assign_other', false); |
|
258 |
+ } |
|
259 |
+ else |
|
260 |
+ fatal_lang_error('shd_cannot_assign', false); |
|
261 |
+} |
|
262 |
+ |
|
263 |
+/** |
|
264 |
+ * Actually commits a ticket assignment to the database. |
|
265 |
+ * |
|
266 |
+ * This function sets up the relevant options before handing over to shd_modify_ticket_post() which is the preferred way to modify |
|
267 |
+ * tickets generally. No permissions check is performed here. |
|
268 |
+ * |
|
269 |
+ * Relies on $context['shd_return_to'] to have been set, defaults to 'ticket' to return to ticket, otherwise return to home page |
|
270 |
+ * on value of 'home'. |
|
271 |
+ * |
|
272 |
+ * @param int $ticket Ticket id number, assumed to exist. |
|
273 |
+ * @param int $assignment User id of the user to which this ticket will be assigned; can be 0 to unassign a ticket |
|
274 |
+ * |
|
275 |
+ * @see shd_assign() |
|
276 |
+ * @see shd_assign2() |
|
277 |
+*/ |
|
278 |
+function shd_commit_assignment($ticket, $assignment) |
|
279 |
+{ |
|
280 |
+ global $smcFunc, $sourcedir, $context, $modSettings; |
|
281 |
+ |
|
282 |
+ require($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
283 |
+ |
|
284 |
+ $msgOptions = array(); |
|
285 |
+ $posterOptions = array(); |
|
286 |
+ $ticketOptions = array( |
|
287 |
+ 'id' => $context['ticket_id'], |
|
288 |
+ 'assigned' => $assignment, |
|
289 |
+ ); |
|
290 |
+ |
|
291 |
+ // Int hooks - after we've set everything up but before we actually press the button |
|
292 |
+ if (!empty($modSettings['shd_hook_assign'])) |
|
293 |
+ { |
|
294 |
+ $functions = explode(',', $modSettings['shd_hook_assign']); |
|
295 |
+ foreach ($functions as $function) |
|
296 |
+ { |
|
297 |
+ if (is_callable($function)) |
|
298 |
+ $function($ticket, $assignment); // by reference |
|
299 |
+ } |
|
300 |
+ } |
|
301 |
+ |
|
302 |
+ shd_modify_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
303 |
+ |
|
304 |
+ if (!empty($context['shd_return_to']) && $context['shd_return_to'] == 'home') |
|
305 |
+ redirectexit('action=helpdesk;sa=main'); |
|
306 |
+ else |
|
307 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $ticket); |
|
308 |
+} |
|
309 |
+ |
|
310 |
+/** |
|
311 |
+ * Return a list of possible users that can be assigned a ticket. |
|
312 |
+ * |
|
313 |
+ * This function centralises who a ticket can be assigned to. Currently this is: |
|
314 |
+ * - user with shd_staff permission |
|
315 |
+ * - can see "any" ticket (not just their own) |
|
316 |
+ * - additionally, if the ticket is private, the user must also be able to see 'any' private ticket. |
|
317 |
+ * - additionally, check whether user is staff + ticket starter, and then whether we should block them from being assigned |
|
318 |
+ * - (since 1.1) additionally if we have set the option, which users are true admins, and if so, remove them from the list too |
|
319 |
+ * |
|
320 |
+ * @param bool $private Whether the ticket in question is private or not. |
|
321 |
+ * @param int $ticket_owner User id of the ticket owner |
|
322 |
+ * |
|
323 |
+ * @return array An indexed array of member ids that this ticket could be assigned to. |
|
324 |
+ * @see shd_assign() |
|
325 |
+ * @see shd_assign2() |
|
326 |
+ * @since 1.0 |
|
327 |
+*/ |
|
328 |
+function shd_get_possible_assignees($private = false, $ticket_owner = 0) |
|
329 |
+{ |
|
330 |
+ global $context, $smcFunc, $modSettings; |
|
331 |
+ |
|
332 |
+ // people who can handle a ticket |
|
333 |
+ $staff = shd_members_allowed_to('shd_staff'); |
|
334 |
+ |
|
335 |
+ // is it private, if so, remove that list |
|
336 |
+ if ((bool) $private == true) |
|
337 |
+ { |
|
338 |
+ $private = shd_members_allowed_to('shd_view_ticket_private_any'); |
|
339 |
+ $staff = array_intersect($staff, $private); |
|
340 |
+ } |
|
341 |
+ |
|
342 |
+ // What about admins? We ignoring them? Note we're talking about *real* admins who implicitly have every permission, not any homebrew |
|
343 |
+ if (!empty($modSettings['shd_admins_not_assignable'])) |
|
344 |
+ { |
|
345 |
+ $query = $smcFunc['db_query']('', ' |
|
346 |
+ SELECT id_member |
|
347 |
+ FROM {db_prefix}members |
|
348 |
+ WHERE id_group = 1 |
|
349 |
+ OR FIND_IN_SET(1, additional_groups)', |
|
350 |
+ array() |
|
351 |
+ ); |
|
352 |
+ |
|
353 |
+ $admins = array(); |
|
354 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
355 |
+ $admins[] = $row[0]; |
|
356 |
+ |
|
357 |
+ $smcFunc['db_free_result']($query); |
|
358 |
+ $staff = array_diff($staff, $admins); |
|
359 |
+ } |
|
360 |
+ |
|
361 |
+ // can they actually see said ticket |
|
362 |
+ $visible = shd_members_allowed_to('shd_view_ticket_any'); |
|
363 |
+ |
|
364 |
+ if (empty($modSettings['shd_staff_ticket_self'])) // by default, staff members can't be assigned a ticket if they started it |
|
365 |
+ $staff = array_diff($staff, array($ticket_owner)); |
|
366 |
+ |
|
367 |
+ // spit back the list of staff members who can see any ticket (+private if dealt with) |
|
368 |
+ return array_intersect($staff, $visible); |
|
369 |
+} |
|
370 |
+?> |
|
0 | 371 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,531 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Delete.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file deals with deletion/recycling of tickets and replies, subsequent restoration back to |
|
22 |
+ * the helpdesk, and lastly, permanent deletion of the same. |
|
23 |
+ * |
|
24 |
+ * @package source |
|
25 |
+ * @todo Finish documenting this file. |
|
26 |
+ * @since 1.0 |
|
27 |
+*/ |
|
28 |
+ |
|
29 |
+if (!defined('SMF')) |
|
30 |
+ die('Hacking attempt...'); |
|
31 |
+ |
|
32 |
+/** |
|
33 |
+ * Delete the given ticket, i.e move it to the recycling bin. |
|
34 |
+ * |
|
35 |
+ * Accessed through ?action=helpdesk;sa=deleteticket;ticket=x;sessvar=sessid |
|
36 |
+ * |
|
37 |
+ * Operations: |
|
38 |
+ * - Session check |
|
39 |
+ * - Check there's a ticket id |
|
40 |
+ * - Check the ticket exists and is visible to the current user |
|
41 |
+ * - Check permission to delete ticket matches (i.e. can delete any, or can delete own and this is one of ours) |
|
42 |
+ * - Update the ticket's status to deleted |
|
43 |
+ * - Log the deletion |
|
44 |
+ * - Clear the menu's Helpdesk active items cache |
|
45 |
+ * - return to the front page |
|
46 |
+ * |
|
47 |
+ * @since 1.0 |
|
48 |
+*/ |
|
49 |
+function shd_ticket_delete() |
|
50 |
+{ |
|
51 |
+ global $smcFunc, $user_info, $context; |
|
52 |
+ |
|
53 |
+ checkSession('get'); |
|
54 |
+ |
|
55 |
+ if (empty($context['ticket_id'])) |
|
56 |
+ fatal_lang_error('shd_no_ticket', false); |
|
57 |
+ |
|
58 |
+ // Check we can actually see the ticket we're deleting, and if we can only delete our own, we are the owner |
|
59 |
+ $query_ticket = shd_db_query('', ' |
|
60 |
+ SELECT id_ticket, id_member_started, subject |
|
61 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
62 |
+ WHERE {query_see_ticket} |
|
63 |
+ AND id_ticket = {int:ticket}', |
|
64 |
+ array( |
|
65 |
+ 'ticket' => $context['ticket_id'], |
|
66 |
+ ) |
|
67 |
+ ); |
|
68 |
+ |
|
69 |
+ if ($row = $smcFunc['db_fetch_assoc']($query_ticket)) |
|
70 |
+ { |
|
71 |
+ $smcFunc['db_free_result']($query_ticket); |
|
72 |
+ if (!shd_allowed_to('shd_delete_ticket_any') && (!shd_allowed_to('shd_delete_ticket_own') || $user_info['id'] != $row['id_member_started'])) |
|
73 |
+ fatal_lang_error('shd_cannot_delete_ticket', false); |
|
74 |
+ } |
|
75 |
+ else |
|
76 |
+ { |
|
77 |
+ $smcFunc['db_free_result']($query_ticket); |
|
78 |
+ fatal_lang_error('shd_no_ticket', false); |
|
79 |
+ } |
|
80 |
+ |
|
81 |
+ $subject = $row['subject']; |
|
82 |
+ |
|
83 |
+ // Move it to deleted status |
|
84 |
+ $query_ticket = shd_db_query('', ' |
|
85 |
+ UPDATE {db_prefix}helpdesk_tickets AS hdt |
|
86 |
+ SET status = {int:status_deleted}, |
|
87 |
+ id_member_assigned = 0 |
|
88 |
+ WHERE id_ticket = {int:current_ticket} |
|
89 |
+ AND {query_see_ticket}', |
|
90 |
+ array( |
|
91 |
+ 'current_ticket' => $context['ticket_id'], |
|
92 |
+ 'status_deleted' => TICKET_STATUS_DELETED, // just move it, don't bother calling merge (or shd_determine_status) |
|
93 |
+ ) |
|
94 |
+ ); |
|
95 |
+ |
|
96 |
+ shd_log_action('delete', |
|
97 |
+ array( |
|
98 |
+ 'ticket' => $context['ticket_id'], |
|
99 |
+ 'subject' => $subject, |
|
100 |
+ ) |
|
101 |
+ ); |
|
102 |
+ |
|
103 |
+ // Expire the cache of count(active tickets) |
|
104 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
105 |
+ |
|
106 |
+ // Go to the home |
|
107 |
+ redirectexit('action=helpdesk;sa=main'); |
|
108 |
+} |
|
109 |
+ |
|
110 |
+function shd_reply_delete() |
|
111 |
+{ |
|
112 |
+ global $smcFunc, $user_info, $context, $sourcedir; |
|
113 |
+ |
|
114 |
+ checkSession('get'); |
|
115 |
+ |
|
116 |
+ $_REQUEST['reply'] = !empty($_REQUEST['reply']) ? (int) $_REQUEST['reply'] : 0; |
|
117 |
+ |
|
118 |
+ if (empty($_REQUEST['reply']) || empty($context['ticket_id'])) |
|
119 |
+ fatal_lang_error('shd_no_ticket'); |
|
120 |
+ |
|
121 |
+ // Check we can actually see the ticket we're deleting, that this reply is in this ticket and that we can delete this reply |
|
122 |
+ $query_ticket = shd_db_query('', ' |
|
123 |
+ SELECT hdt.id_ticket, hdtr.id_member, hdt.id_member_started, subject, status |
|
124 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
125 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdt.id_ticket = hdtr.id_ticket) |
|
126 |
+ WHERE {query_see_ticket} |
|
127 |
+ AND hdt.id_ticket = {int:ticket} |
|
128 |
+ AND hdtr.id_msg = {int:reply} |
|
129 |
+ AND hdt.id_first_msg != {int:reply2}', |
|
130 |
+ array( |
|
131 |
+ 'ticket' => $context['ticket_id'], |
|
132 |
+ 'reply' => $_REQUEST['reply'], |
|
133 |
+ 'reply2' => $_REQUEST['reply'], // since we can't delete the first message through the reply interface! |
|
134 |
+ ) |
|
135 |
+ ); |
|
136 |
+ |
|
137 |
+ if ($row = $smcFunc['db_fetch_assoc']($query_ticket)) |
|
138 |
+ { |
|
139 |
+ $smcFunc['db_free_result']($query_ticket); |
|
140 |
+ if (($row['status'] == TICKET_STATUS_CLOSED || $row['status'] == TICKET_STATUS_DELETED) || (!shd_allowed_to('shd_delete_ticket_any') && (!shd_allowed_to('shd_delete_ticket_own') || $user_info['id'] != $row['id_member']))) |
|
141 |
+ fatal_lang_error('shd_cannot_delete_reply', false); |
|
142 |
+ } |
|
143 |
+ else |
|
144 |
+ { |
|
145 |
+ $smcFunc['db_free_result']($query_ticket); |
|
146 |
+ fatal_lang_error('shd_no_ticket', false); |
|
147 |
+ } |
|
148 |
+ |
|
149 |
+ $subject = $row['subject']; |
|
150 |
+ |
|
151 |
+ // OK, let's clear this one, hasta la vista... ticket. |
|
152 |
+ shd_db_query('', ' |
|
153 |
+ UPDATE {db_prefix}helpdesk_ticket_replies |
|
154 |
+ SET message_status = {int:msg_status_deleted} |
|
155 |
+ WHERE id_msg = {int:reply}', |
|
156 |
+ array( |
|
157 |
+ 'msg_status_deleted' => MSG_STATUS_DELETED, |
|
158 |
+ 'reply' => $_REQUEST['reply'], |
|
159 |
+ ) |
|
160 |
+ ); |
|
161 |
+ |
|
162 |
+ // Logtastic! |
|
163 |
+ shd_log_action('delete_reply', |
|
164 |
+ array( |
|
165 |
+ 'ticket' => $context['ticket_id'], |
|
166 |
+ 'subject' => $subject, |
|
167 |
+ 'msg' => $_REQUEST['reply'], |
|
168 |
+ ) |
|
169 |
+ ); |
|
170 |
+ |
|
171 |
+ // OK, last but definitely not least, update num_replies and id_last_msg on the old ticket, and fix the old ticket's status |
|
172 |
+ list($starter, $replier, $num_replies) = shd_recalc_ids($context['ticket_id']); |
|
173 |
+ $query_reply = shd_db_query('', ' |
|
174 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
175 |
+ SET status = {int:status} |
|
176 |
+ WHERE id_ticket = {int:ticket}', |
|
177 |
+ array( |
|
178 |
+ 'ticket' => $context['ticket_id'], |
|
179 |
+ 'status' => shd_determine_status('deletereply', $starter, $replier, $num_replies), |
|
180 |
+ ) |
|
181 |
+ ); |
|
182 |
+ |
|
183 |
+ // Expire the cache of count(active tickets) |
|
184 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
185 |
+ |
|
186 |
+ // Back to the ticket |
|
187 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
188 |
+} |
|
189 |
+ |
|
190 |
+// Delete the given reply or ticket from the database. This is the final deletion which cannot be undone. |
|
191 |
+function shd_perma_delete() |
|
192 |
+{ |
|
193 |
+ global $smcFunc, $user_info, $context, $sourcedir; |
|
194 |
+ |
|
195 |
+ checkSession('get'); |
|
196 |
+ shd_is_allowed_to('shd_delete_recycling'); |
|
197 |
+ |
|
198 |
+ // We have to have either a ticket or a reply to know what to delete (Or do you want me to drop your whole database? >:D) |
|
199 |
+ if (empty($context['ticket_id']) && empty($_REQUEST['reply'])) |
|
200 |
+ fatal_lang_error('shd_no_ticket', false); |
|
201 |
+ |
|
202 |
+ // If we're deleting a whole ticket... |
|
203 |
+ if (!empty($context['ticket_id']) && empty($_REQUEST['reply'])) |
|
204 |
+ { |
|
205 |
+ // Can we even see this ticket? |
|
206 |
+ $query_ticket = shd_db_query('', ' |
|
207 |
+ SELECT id_ticket, subject, id_member_started, status |
|
208 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
209 |
+ WHERE {query_see_ticket} |
|
210 |
+ AND id_ticket = {int:ticket}', |
|
211 |
+ array( |
|
212 |
+ 'ticket' => $context['ticket_id'], |
|
213 |
+ ) |
|
214 |
+ ); |
|
215 |
+ |
|
216 |
+ if ($smcFunc['db_num_rows']($query_ticket) == 0) |
|
217 |
+ { |
|
218 |
+ $smcFunc['db_free_result']($query_ticket); |
|
219 |
+ fatal_lang_error('shd_no_ticket', false); |
|
220 |
+ } |
|
221 |
+ else |
|
222 |
+ { |
|
223 |
+ $row = $smcFunc['db_fetch_assoc']($query_ticket); |
|
224 |
+ $smcFunc['db_free_result']($query_ticket); |
|
225 |
+ } |
|
226 |
+ |
|
227 |
+ if ($row['status'] != TICKET_STATUS_DELETED) |
|
228 |
+ fatal_lang_error('shd_cannot_delete_ticket', false); |
|
229 |
+ |
|
230 |
+ $subject = $row['subject']; |
|
231 |
+ // Expire the cache of count(active tickets) |
|
232 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
233 |
+ |
|
234 |
+ // Start by deleting the actual ticket. |
|
235 |
+ shd_db_query('', ' |
|
236 |
+ DELETE FROM {db_prefix}helpdesk_tickets |
|
237 |
+ WHERE id_ticket = {int:current_ticket}', |
|
238 |
+ array( |
|
239 |
+ 'current_ticket' => $context['ticket_id'], |
|
240 |
+ ) |
|
241 |
+ ); |
|
242 |
+ |
|
243 |
+ // Then remove any replies associated with it. |
|
244 |
+ shd_db_query('', ' |
|
245 |
+ DELETE FROM {db_prefix}helpdesk_ticket_replies |
|
246 |
+ WHERE id_ticket = {int:current_ticket}', |
|
247 |
+ array( |
|
248 |
+ 'current_ticket' => $context['ticket_id'], |
|
249 |
+ ) |
|
250 |
+ ); |
|
251 |
+ |
|
252 |
+ // And attachments... work out which attachments that is |
|
253 |
+ $query = shd_db_query('', ' |
|
254 |
+ SELECT id_attach |
|
255 |
+ FROM {db_prefix}helpdesk_attachments |
|
256 |
+ WHERE id_ticket = {int:ticket}', |
|
257 |
+ array( |
|
258 |
+ 'ticket' => $context['ticket_id'], |
|
259 |
+ ) |
|
260 |
+ ); |
|
261 |
+ |
|
262 |
+ $attachIDs = array(); |
|
263 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
264 |
+ $attachIDs[] = $row[0]; |
|
265 |
+ |
|
266 |
+ $smcFunc['db_free_result']($query); |
|
267 |
+ |
|
268 |
+ if (!empty($attachIDs)) |
|
269 |
+ { |
|
270 |
+ // OK, so we have some ids |
|
271 |
+ require_once($sourcedir . '/ManageAttachments.php'); |
|
272 |
+ $attachmentQuery = array( |
|
273 |
+ 'attachment_type' => 0, |
|
274 |
+ 'id_msg' => 0, |
|
275 |
+ 'id_attach' => $attachIDs, |
|
276 |
+ ); |
|
277 |
+ removeAttachments($attachmentQuery); |
|
278 |
+ } |
|
279 |
+ |
|
280 |
+ shd_log_action('permadelete', |
|
281 |
+ array( |
|
282 |
+ 'ticket' => $context['ticket_id'], |
|
283 |
+ 'subject' => $subject, |
|
284 |
+ ) |
|
285 |
+ ); |
|
286 |
+ |
|
287 |
+ redirectexit('action=helpdesk;sa=recyclebin'); |
|
288 |
+ } |
|
289 |
+ // Or just a single reply... |
|
290 |
+ elseif (!empty($_REQUEST['reply'])) |
|
291 |
+ { |
|
292 |
+ // Check we can actually see the ticket we're deleting, that this reply is in this ticket and that we can delete this reply |
|
293 |
+ $query_ticket = shd_db_query('', ' |
|
294 |
+ SELECT hdt.id_ticket, hdtr.id_member, hdt.subject, hdt.id_member_started, hdt.status, hdtr.message_status |
|
295 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
296 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdt.id_ticket = hdtr.id_ticket) |
|
297 |
+ WHERE {query_see_ticket} |
|
298 |
+ AND hdt.id_ticket = {int:ticket} |
|
299 |
+ AND hdtr.id_msg = {int:reply} |
|
300 |
+ AND hdt.id_first_msg != {int:reply2}', |
|
301 |
+ array( |
|
302 |
+ 'ticket' => $context['ticket_id'], |
|
303 |
+ 'reply' => $_REQUEST['reply'], |
|
304 |
+ 'reply2' => $_REQUEST['reply'], // since we can't delete the first message through the reply interface! |
|
305 |
+ ) |
|
306 |
+ ); |
|
307 |
+ |
|
308 |
+ if ($smcFunc['db_num_rows']($query_ticket) == 0) |
|
309 |
+ { |
|
310 |
+ $smcFunc['db_free_result']($query_ticket); |
|
311 |
+ fatal_lang_error('shd_no_ticket', false); |
|
312 |
+ } |
|
313 |
+ else |
|
314 |
+ { |
|
315 |
+ $row = $smcFunc['db_fetch_assoc']($query_ticket); |
|
316 |
+ $smcFunc['db_free_result']($query_ticket); |
|
317 |
+ } |
|
318 |
+ |
|
319 |
+ if ($row['status'] == TICKET_STATUS_DELETED || $row['message_status'] != MSG_STATUS_DELETED) |
|
320 |
+ fatal_lang_error('shd_cannot_delete_reply', false); |
|
321 |
+ |
|
322 |
+ $subject = $row['subject']; |
|
323 |
+ // Expire the cache of count(active tickets) |
|
324 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
325 |
+ |
|
326 |
+ // Just remove the reply. |
|
327 |
+ $query_reply = shd_db_query('', ' |
|
328 |
+ DELETE FROM {db_prefix}helpdesk_ticket_replies |
|
329 |
+ WHERE id_msg = {int:current_reply}', |
|
330 |
+ array( |
|
331 |
+ 'current_reply' => (int) $_REQUEST['reply'], |
|
332 |
+ ) |
|
333 |
+ ); |
|
334 |
+ |
|
335 |
+ // Now to handle attachments |
|
336 |
+ $query = shd_db_query('', ' |
|
337 |
+ SELECT id_attach |
|
338 |
+ FROM {db_prefix}helpdesk_attachments |
|
339 |
+ WHERE id_msg = {int:msg}', |
|
340 |
+ array( |
|
341 |
+ 'msg' => (int) $_REQUEST['reply'], |
|
342 |
+ ) |
|
343 |
+ ); |
|
344 |
+ |
|
345 |
+ $attachIDs = array(); |
|
346 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
347 |
+ $attachIDs[] = $row[0]; |
|
348 |
+ |
|
349 |
+ $smcFunc['db_free_result']($query); |
|
350 |
+ |
|
351 |
+ if (!empty($attachIDs)) |
|
352 |
+ { |
|
353 |
+ // OK, so we have some ids |
|
354 |
+ require_once($sourcedir . '/ManageAttachments.php'); |
|
355 |
+ $attachmentQuery = array( |
|
356 |
+ 'attachment_type' => 0, |
|
357 |
+ 'id_msg' => 0, |
|
358 |
+ 'id_attach' => $attachIDs, |
|
359 |
+ ); |
|
360 |
+ removeAttachments($attachmentQuery); |
|
361 |
+ } |
|
362 |
+ |
|
363 |
+ shd_log_action('permadelete_reply', |
|
364 |
+ array( |
|
365 |
+ 'ticket' => $context['ticket_id'], |
|
366 |
+ 'subject' => $subject, |
|
367 |
+ ) |
|
368 |
+ ); |
|
369 |
+ |
|
370 |
+ list($starter, $replier, $num_replies) = shd_recalc_ids($context['ticket_id']); |
|
371 |
+ $query_reply = shd_db_query('', ' |
|
372 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
373 |
+ SET status = {int:status} |
|
374 |
+ WHERE id_ticket = {int:ticket}', |
|
375 |
+ array( |
|
376 |
+ 'ticket' => $context['ticket_id'], |
|
377 |
+ 'status' => shd_determine_status('deletereply', $starter, $replier, $num_replies), |
|
378 |
+ ) |
|
379 |
+ ); |
|
380 |
+ |
|
381 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
382 |
+ } |
|
383 |
+ else |
|
384 |
+ fatal_lang_error('shd_no_ticket'); |
|
385 |
+} |
|
386 |
+ |
|
387 |
+// Restore the given ticket from the recycling bin. |
|
388 |
+function shd_ticket_restore() |
|
389 |
+{ |
|
390 |
+ global $smcFunc, $user_info, $context; |
|
391 |
+ |
|
392 |
+ checkSession('get'); |
|
393 |
+ |
|
394 |
+ if (empty($context['ticket_id'])) |
|
395 |
+ fatal_lang_error('shd_no_ticket', false); |
|
396 |
+ |
|
397 |
+ // Does the ticket we're trying to restore exist and can we see it? |
|
398 |
+ $query_ticket = shd_db_query('', ' |
|
399 |
+ SELECT id_ticket, id_member_started, id_member_updated, subject, num_replies, status |
|
400 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
401 |
+ WHERE {query_see_ticket} |
|
402 |
+ AND id_ticket = {int:ticket}', |
|
403 |
+ array( |
|
404 |
+ 'ticket' => $context['ticket_id'], |
|
405 |
+ ) |
|
406 |
+ ); |
|
407 |
+ |
|
408 |
+ if ($row = $smcFunc['db_fetch_assoc']($query_ticket)) |
|
409 |
+ { |
|
410 |
+ $smcFunc['db_free_result']($query_ticket); |
|
411 |
+ if ($row['status'] != TICKET_STATUS_DELETED || (!shd_allowed_to('shd_restore_ticket_any') && (!shd_allowed_to('shd_restore_ticket_own') || $user_info['id'] != $row['id_member_started']))) |
|
412 |
+ fatal_lang_error('shd_cannot_restore_ticket', false); |
|
413 |
+ |
|
414 |
+ $subject = $row['subject']; |
|
415 |
+ $starter = $row['id_member_started']; |
|
416 |
+ $replier = $row['id_member_updated']; |
|
417 |
+ $num_replies = $row['num_replies']; |
|
418 |
+ } |
|
419 |
+ else |
|
420 |
+ { |
|
421 |
+ $smcFunc['db_free_result']($query_ticket); |
|
422 |
+ fatal_lang_error('shd_no_ticket', false); |
|
423 |
+ } |
|
424 |
+ |
|
425 |
+ shd_db_query('', ' |
|
426 |
+ UPDATE {db_prefix}helpdesk_tickets AS hdt |
|
427 |
+ SET status = {int:status_new} |
|
428 |
+ WHERE id_ticket = {int:current_ticket} |
|
429 |
+ AND {query_see_ticket}', |
|
430 |
+ array( |
|
431 |
+ 'current_ticket' => $context['ticket_id'], |
|
432 |
+ 'status_new' => shd_determine_status('restoreticket', $starter, $replier, $num_replies), |
|
433 |
+ ) |
|
434 |
+ ); |
|
435 |
+ |
|
436 |
+ // Expire the cache of count(active tickets) |
|
437 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
438 |
+ |
|
439 |
+ shd_log_action('restore', |
|
440 |
+ array( |
|
441 |
+ 'ticket' => $context['ticket_id'], |
|
442 |
+ 'subject' => $subject, |
|
443 |
+ ) |
|
444 |
+ ); |
|
445 |
+ |
|
446 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
447 |
+} |
|
448 |
+ |
|
449 |
+// Restore the given reply from the recycling bin. |
|
450 |
+function shd_reply_restore() |
|
451 |
+{ |
|
452 |
+ global $smcFunc, $user_info, $context, $sourcedir; |
|
453 |
+ |
|
454 |
+ checkSession('get'); |
|
455 |
+ |
|
456 |
+ $_REQUEST['reply'] = empty($_REQUEST['reply']) ? 0 : (int) $_REQUEST['reply']; |
|
457 |
+ |
|
458 |
+ if (empty($_REQUEST['reply'])) |
|
459 |
+ fatal_lang_error('shd_no_ticket', false); |
|
460 |
+ |
|
461 |
+ // Check we can actually see the ticket we're restoring from, and that we can restore this reply |
|
462 |
+ $query_ticket = shd_db_query('', ' |
|
463 |
+ SELECT hdt.id_ticket, hdtr.id_member, hdt.id_member_started, hdt.id_member_updated, hdt.num_replies, hdt.subject, hdt.status, hdtr.message_status |
|
464 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
465 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdt.id_ticket = hdtr.id_ticket) |
|
466 |
+ WHERE {query_see_ticket} |
|
467 |
+ AND hdtr.id_msg = {int:reply} |
|
468 |
+ AND hdt.id_first_msg != {int:reply2}', |
|
469 |
+ array( |
|
470 |
+ 'reply' => $_REQUEST['reply'], |
|
471 |
+ 'reply2' => $_REQUEST['reply'], |
|
472 |
+ ) |
|
473 |
+ ); |
|
474 |
+ |
|
475 |
+ if ($row = $smcFunc['db_fetch_assoc']($query_ticket)) |
|
476 |
+ { |
|
477 |
+ $smcFunc['db_free_result']($query_ticket); |
|
478 |
+ if (($row['status'] == TICKET_STATUS_DELETED || $row['status'] == TICKET_STATUS_CLOSED || $row['message_status'] != MSG_STATUS_DELETED) || (!shd_allowed_to('shd_restore_reply_any') && (!shd_allowed_to('shd_restore_reply_own') || $user_info['id'] != $row['id_member']))) |
|
479 |
+ fatal_lang_error('shd_cannot_restore_reply', false); |
|
480 |
+ |
|
481 |
+ $context['ticket_id'] = (int) $row['id_ticket']; |
|
482 |
+ $subject = $row['subject']; |
|
483 |
+ $starter = $row['id_member_started']; |
|
484 |
+ $replier = $row['id_member_updated']; |
|
485 |
+ $num_replies = $row['num_replies']; |
|
486 |
+ } |
|
487 |
+ else |
|
488 |
+ { |
|
489 |
+ $smcFunc['db_free_result']($query_ticket); |
|
490 |
+ fatal_lang_error('shd_no_ticket', false); |
|
491 |
+ } |
|
492 |
+ |
|
493 |
+ // OK, let's clear this one, hasta la vista... ticket. |
|
494 |
+ shd_db_query('', ' |
|
495 |
+ UPDATE {db_prefix}helpdesk_ticket_replies |
|
496 |
+ SET message_status = {int:msg_status_deleted} |
|
497 |
+ WHERE id_msg = {int:reply}', |
|
498 |
+ array( |
|
499 |
+ 'msg_status_deleted' => MSG_STATUS_NORMAL, |
|
500 |
+ 'reply' => $_REQUEST['reply'], |
|
501 |
+ ) |
|
502 |
+ ); |
|
503 |
+ |
|
504 |
+ // Captain's Log, stardate 18.3.10.1010 |
|
505 |
+ shd_log_action('restore_reply', |
|
506 |
+ array( |
|
507 |
+ 'ticket' => $context['ticket_id'], |
|
508 |
+ 'subject' => $subject, |
|
509 |
+ 'msg' => $_REQUEST['reply'], |
|
510 |
+ ) |
|
511 |
+ ); |
|
512 |
+ |
|
513 |
+ // Fix the topic data |
|
514 |
+ list($starter, $replier, $num_replies) = shd_recalc_ids($context['ticket_id']); |
|
515 |
+ $query_reply = shd_db_query('', ' |
|
516 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
517 |
+ SET status = {int:status} |
|
518 |
+ WHERE id_ticket = {int:ticket}', |
|
519 |
+ array( |
|
520 |
+ 'ticket' => $context['ticket_id'], |
|
521 |
+ 'status' => shd_determine_status('restorereply', $starter, $replier, $num_replies), |
|
522 |
+ ) |
|
523 |
+ ); |
|
524 |
+ |
|
525 |
+ // Expire the cache of count(active tickets) |
|
526 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
527 |
+ |
|
528 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
529 |
+} |
|
530 |
+ |
|
531 |
+?> |
|
0 | 532 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,1046 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Display.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file sets up the regular ticket view, including the menu of operations that can |
|
22 |
+ * be applied to a ticket. It is also resposible for setting up the AJAX items for modifying privacy and urgency from |
|
23 |
+ * the ticket view itself, as well as all the handling responsible for Quick Reply including the 'Go Advanced' mode. |
|
24 |
+ * |
|
25 |
+ * @package source |
|
26 |
+ * @since 1.0 |
|
27 |
+*/ |
|
28 |
+ |
|
29 |
+if (!defined('SMF')) |
|
30 |
+ die('Hacking attempt...'); |
|
31 |
+ |
|
32 |
+/** |
|
33 |
+ * Loads all the data and sets all the options for displaying a ticket. |
|
34 |
+ * |
|
35 |
+ * This function does a lot of work in setting up a ticket to be displayed: |
|
36 |
+ * <ul> |
|
37 |
+ * <li>Invokes shd_load_ticket() to get the principle data</li> |
|
38 |
+ * <li>Creates $context['ticket'] to hold the data block, some of which is derived from the return of shd_load_ticket(): |
|
39 |
+ * <ul> |
|
40 |
+ * <li>id: regular numeric ticket id</li> |
|
41 |
+ * <li>display_id: zero padded ticket id (e.g. 00001)</li> |
|
42 |
+ * <li>subject: censored version of the subject</li> |
|
43 |
+ * <li>first_msg: id of the opening post that forms the ticket body</li> |
|
44 |
+ * <li>body: formatted (parsed for smileys and bbcode) version of the ticket post</li> |
|
45 |
+ * <li>id_member: user id of the ticket's poster</li> |
|
46 |
+ * <li>id_member_assigned: user id of the ticket's assigned user</li> |
|
47 |
+ * <li>member: hash array of the ticket poster's details: |
|
48 |
+ * <ul> |
|
49 |
+ * <li>id: their user id</li> |
|
50 |
+ * <li>name: the name stated in the ticket post for that use</li> |
|
51 |
+ * <li>link: link to the profile of the user</li> |
|
52 |
+ * </ul> |
|
53 |
+ * </li> |
|
54 |
+ * <li>assigned: hash array of the assignee of the ticket: |
|
55 |
+ * <ul> |
|
56 |
+ * <li>id: their user id</li> |
|
57 |
+ * <li>name: name of the assignee, or 'Unassigned'</li> |
|
58 |
+ * <li>link: a full HTML link to their profile, or 'Unassigned' in red text</li> |
|
59 |
+ * </ul> |
|
60 |
+ * </li> |
|
61 |
+ * <li>assigned_self: boolean, whether the ticket is assigned to the current user or not</li> |
|
62 |
+ * <li>ticket_opener: boolean, whether the current user is the user who opened this ticket</li> |
|
63 |
+ * <li>urgency: hash array |
|
64 |
+ * <ul> |
|
65 |
+ * <li>level: numeric identifier of current ticket urgency</li> |
|
66 |
+ * <li>label: the HTML label of the urgency, including being in red for "Very High" or above</li> |
|
67 |
+ * <li>increase: Boolean, whether the current ticket urgency can be increased given the current ticket state and user permissions</li> |
|
68 |
+ * <li>decrease: Boolean, whether the current ticket urgency can be increased given the current ticket state and user permissions</li> |
|
69 |
+ * </ul> |
|
70 |
+ * </li> |
|
71 |
+ * <li>status: hash array |
|
72 |
+ * <ul> |
|
73 |
+ * <li>level: numeric, current status identifier</li> |
|
74 |
+ * <li>label: string representing the current status</li> |
|
75 |
+ * </ul> |
|
76 |
+ * <li>num_replies: the number of replies to the ticket so far</li> |
|
77 |
+ * <li>deleted_replies: how many deleted replies in this ticket</li> |
|
78 |
+ * <li>poster_time: formatted string containing the time the ticket was opened</li> |
|
79 |
+ * <li>privacy: hash array |
|
80 |
+ * <ul> |
|
81 |
+ * <li>label: current label to be used with the privacy item</li> |
|
82 |
+ * <li>can_change: Boolean, whether the user's permission with this ticket allows us to edit the ticket privacy</li> |
|
83 |
+ * </ul> |
|
84 |
+ * </li> |
|
85 |
+ * <li>closed: Boolean, represents whether this ticket is closed (used a lot with the navigation menu)</li> |
|
86 |
+ * <li>deleted: Boolean, represents whether this ticket is deleted (used a lot with the navigation menu)</li> |
|
87 |
+ * <li>ip_address: IP address logged at the time the ticket was opened; if moderate_forum_members permission is available, this will be a link to the track IP area</li> |
|
88 |
+ * <li>modified: if the ticket has been modified, also get the modified details: |
|
89 |
+ * <ul> |
|
90 |
+ * <li>id: user id who edited the ticket (not always available)</li> |
|
91 |
+ * <li>time: formatted string of the time the post was edited</li> |
|
92 |
+ * <li>timestamp: raw timestamp of the time the post was edited</li> |
|
93 |
+ * <li>name: user name of the editing user; if we have a definite user id, this should contain the current name, falling back to the previously stored name</li> |
|
94 |
+ * <li>link: if we have a known, valid user id for the post's editor, this will contain a link to their profile, with the link text using their current display name; alternatively it will contain a regular string which is the username stored with the edit.</li> |
|
95 |
+ * </ul> |
|
96 |
+ * </li> |
|
97 |
+ * <li>display_recycle: Either holds the $txt identifier of the message to apply as a warning, or false if displaying of recycling stuff in this ticket isn't appropriate (either for permissions or just because of no deleted replies, or we're just in regular ticket view)</li> |
|
98 |
+ * </ul> |
|
99 |
+ * </li> |
|
100 |
+ * <li>define the page index with SMF's constructPageIndex</li> |
|
101 |
+ * <li>query for all the ids of messages we might display, followed by querying for the message details themselves, pushing that query resource to $reply_request so we can use it in shd_view_replies() later</li> |
|
102 |
+ * <li>load details of all the users applicable for posts in this page</li> |
|
103 |
+ * <li>request all the visible attachments from {@link shd_display_load_attachments()}</li> |
|
104 |
+ * <li>since we are viewing this ticket, mark it read</li> |
|
105 |
+ * <li>set up the breadcrumb trail</li> |
|
106 |
+ * <li>set up the ticket navigation menu</li> |
|
107 |
+ * <li>call in the editor component from SimpleDesk-Post.php and friends, ready for Quick Reply</li> |
|
108 |
+ * <li>invoke the different Javascript objects that are applicable on the page: |
|
109 |
+ * <ul> |
|
110 |
+ * <li>privacy changer</li> |
|
111 |
+ * <li>urgency changer</li> |
|
112 |
+ * <li>quick reply / quote / go advanced</li> |
|
113 |
+ * </ul> |
|
114 |
+ * </li> |
|
115 |
+ * </ul> |
|
116 |
+ * |
|
117 |
+ * @see shd_prepare_ticket_context() |
|
118 |
+ * @since 1.0 |
|
119 |
+*/ |
|
120 |
+function shd_view_ticket() |
|
121 |
+{ |
|
122 |
+ global $context, $txt, $scripturl, $settings, $reply_request, $smcFunc, $modSettings, $memberContext, $sourcedir, $user_info, $options; |
|
123 |
+ |
|
124 |
+ loadTemplate('sd_template/SimpleDesk-Display'); |
|
125 |
+ |
|
126 |
+ $ticketinfo = shd_load_ticket(); |
|
127 |
+ |
|
128 |
+ // How much are we sticking on each page? |
|
129 |
+ $context['messages_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) && !WIRELESS ? $options['messages_per_page'] : $modSettings['defaultMaxMessages']; |
|
130 |
+ |
|
131 |
+ censorText($ticketinfo['subject']); |
|
132 |
+ censorText($ticketinfo['body']); |
|
133 |
+ |
|
134 |
+ $context['user_list'] = array(); // as we go along, build a list of users who are relevant |
|
135 |
+ |
|
136 |
+ $context['ticket'] = array( |
|
137 |
+ 'id' => $context['ticket_id'], |
|
138 |
+ 'display_id' => str_pad($context['ticket_id'], 5, '0', STR_PAD_LEFT), |
|
139 |
+ 'subject' => $ticketinfo['subject'], |
|
140 |
+ 'first_msg' => $ticketinfo['id_first_msg'], |
|
141 |
+ 'body' => shd_format_text($ticketinfo['body'], $ticketinfo['smileys_enabled'], 'shd_reply_' . $ticketinfo['id_first_msg']), |
|
142 |
+ 'id_member' => $ticketinfo['id_member'], |
|
143 |
+ 'id_member_assigned' => $ticketinfo['assigned_id'], |
|
144 |
+ 'member' => array( |
|
145 |
+ 'id' => $ticketinfo['starter_id'], |
|
146 |
+ 'name' => $ticketinfo['starter_name'], |
|
147 |
+ 'link' => shd_profile_link($ticketinfo['starter_name'], $ticketinfo['starter_id']), |
|
148 |
+ ), |
|
149 |
+ 'assigned' => array( |
|
150 |
+ 'id' => $ticketinfo['assigned_id'], |
|
151 |
+ 'name' => ($ticketinfo['assigned_id'] > 0) ? $ticketinfo['assigned_name'] : $txt['shd_unassigned'], |
|
152 |
+ 'link' => ($ticketinfo['assigned_id'] > 0) ? shd_profile_link($ticketinfo['assigned_name'], $ticketinfo['assigned_id']) : '<span class="error">' . $txt['shd_unassigned'] . '</span>', |
|
153 |
+ ), |
|
154 |
+ 'assigned_self' => $ticketinfo['assigned_id'] == $user_info['id'], |
|
155 |
+ 'ticket_opener' => $ticketinfo['starter_id'] == $user_info['id'], |
|
156 |
+ 'urgency' => array( |
|
157 |
+ 'level' => $ticketinfo['urgency'], |
|
158 |
+ 'label' => $ticketinfo['urgency'] > TICKET_URGENCY_HIGH ? '<span class="error">' . $txt['shd_urgency_' . $ticketinfo['urgency']] . '</span>' : $txt['shd_urgency_' . $ticketinfo['urgency']], |
|
159 |
+ ), |
|
160 |
+ 'status' => array( |
|
161 |
+ 'level' => $ticketinfo['status'], |
|
162 |
+ 'label' => $txt['shd_status_' . $ticketinfo['status']], |
|
163 |
+ ), |
|
164 |
+ 'num_replies' => $ticketinfo['num_replies'], |
|
165 |
+ 'deleted_replies' => $ticketinfo['deleted_replies'], |
|
166 |
+ 'poster_time' => timeformat($ticketinfo['poster_time']), |
|
167 |
+ 'privacy' => array( |
|
168 |
+ 'label' => $ticketinfo['private'] ? $txt['shd_ticket_private'] : $txt['shd_ticket_notprivate'], |
|
169 |
+ 'can_change' => shd_allowed_to('shd_alter_privacy_any') || (shd_allowed_to('shd_alter_privacy_own') && $ticketinfo['id_member'] == $user_info['id']), |
|
170 |
+ ), |
|
171 |
+ 'closed' => $ticketinfo['closed'], |
|
172 |
+ 'deleted' => $ticketinfo['deleted'], |
|
173 |
+ ); |
|
174 |
+ |
|
175 |
+ // IP address next |
|
176 |
+ $context['link_ip_address'] = allowedTo('moderate_forum'); // for trackip access |
|
177 |
+ if (shd_allowed_to('shd_view_ip_any') || ($context['ticket']['ticket_opener'] && shd_allowed_to('shd_view_ip_own'))) |
|
178 |
+ $context['ticket']['ip_address'] = $context['link_ip_address'] ? ('<a href="' . $scripturl . '?action=trackip;searchip=' . $ticketinfo['starter_ip'] . '">' . $ticketinfo['starter_ip'] . '</a>') : $ticketinfo['starter_ip']; |
|
179 |
+ |
|
180 |
+ // Stuff concerning whether the ticket is deleted or not |
|
181 |
+ // Display recycling stuff if: ticket is deleted (if we can see it, we can see the bin) OR ticket has deleted replies and we can see the bin and we requested to see them |
|
182 |
+ $context['ticket']['display_recycle_replies'] = true; |
|
183 |
+ if ($context['ticket']['deleted']) |
|
184 |
+ $context['ticket']['display_recycle'] = $txt['shd_ticket_has_been_deleted']; |
|
185 |
+ elseif ($context['ticket']['deleted_replies'] > 0) |
|
186 |
+ { |
|
187 |
+ if (shd_allowed_to('shd_access_recyclebin')) |
|
188 |
+ { |
|
189 |
+ $context['ticket']['display_recycle'] = $txt['shd_ticket_replies_deleted']; |
|
190 |
+ $ticketlink = $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . (isset($_REQUEST['recycle']) ? '' : ';recycle'); |
|
191 |
+ $context['ticket']['display_recycle'] .= ' ' . sprintf((isset($_REQUEST['recycle']) ? $txt['shd_ticket_replies_deleted_view'] : $txt['shd_ticket_replies_deleted_link']), $ticketlink); |
|
192 |
+ $context['ticket']['display_recycle_replies'] = (isset($_REQUEST['recycle'])); |
|
193 |
+ } |
|
194 |
+ else |
|
195 |
+ $context['ticket']['display_recycle_replies'] = false; |
|
196 |
+ } |
|
197 |
+ else |
|
198 |
+ { |
|
199 |
+ $context['ticket']['display_recycle'] = false; |
|
200 |
+ $context['ticket']['display_recycle_replies'] = false; |
|
201 |
+ } |
|
202 |
+ |
|
203 |
+ // Ticket privacy |
|
204 |
+ $context['ticket']['privacy']['can_change'] = $context['ticket']['privacy']['can_change'] && (!$context['ticket']['closed'] && !$context['ticket']['deleted']); |
|
205 |
+ if (empty($modSettings['shd_privacy_display']) || $modSettings['shd_privacy_display'] == 'smart') |
|
206 |
+ $context['display_private'] = shd_allowed_to('shd_view_ticket_private_any') || shd_allowed_to('shd_alter_privacy_own') || shd_allowed_to('shd_alter_privacy_any') || $ticketinfo['private']; |
|
207 |
+ else |
|
208 |
+ $context['display_private'] = true; |
|
209 |
+ |
|
210 |
+ if ($ticketinfo['modified_time'] > 0) |
|
211 |
+ { |
|
212 |
+ $context['ticket']['modified'] = array( |
|
213 |
+ 'id' => $ticketinfo['modified_id'], |
|
214 |
+ 'name' => $ticketinfo['modified_name'], |
|
215 |
+ 'link' => shd_profile_link($ticketinfo['modified_name'], $ticketinfo['modified_id']), |
|
216 |
+ 'timestamp' => $ticketinfo['modified_time'], |
|
217 |
+ 'time' => timeformat($ticketinfo['modified_time']), |
|
218 |
+ ); |
|
219 |
+ } |
|
220 |
+ |
|
221 |
+ $context['ticket']['urgency'] += shd_can_alter_urgency($ticketinfo['urgency'], $ticketinfo['starter_id'], $ticketinfo['closed'], $ticketinfo['deleted']); |
|
222 |
+ |
|
223 |
+ $context['page_index'] = shd_no_expand_pageindex($scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '.%1$d#replies', $context['ticket_start'], (empty($context['display_recycle']) ? $context['ticket']['num_replies'] : (int) $context['ticket']['num_replies'] + (int) $context['ticket']['deleted_replies']), $context['messages_per_page'], true); |
|
224 |
+ |
|
225 |
+ $context['get_replies'] = 'shd_prepare_ticket_context'; |
|
226 |
+ |
|
227 |
+ $query = shd_db_query('', ' |
|
228 |
+ SELECT id_msg, id_member, modified_member |
|
229 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
230 |
+ WHERE id_ticket = {int:ticket} |
|
231 |
+ AND id_msg > {int:first_msg}' . (!empty($context['ticket']['display_recycle_replies']) ? '' : ' |
|
232 |
+ AND message_status = {int:msg_status}') . ' |
|
233 |
+ ORDER BY id_msg ' . ($context['messages_per_page'] == -1 ? '' : ' |
|
234 |
+ LIMIT ' . $context['ticket_start'] . ', ' . $context['messages_per_page']), |
|
235 |
+ array( |
|
236 |
+ 'ticket' => $context['ticket_id'], |
|
237 |
+ 'first_msg' => $ticketinfo['id_first_msg'], |
|
238 |
+ 'msg_status' => MSG_STATUS_NORMAL, |
|
239 |
+ ) |
|
240 |
+ ); |
|
241 |
+ |
|
242 |
+ $context['ticket_messages'] = array(); |
|
243 |
+ $posters = array(); |
|
244 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
245 |
+ { |
|
246 |
+ if (!empty($row['id_member'])) |
|
247 |
+ $posters[] = $row['id_member']; |
|
248 |
+ |
|
249 |
+ if (!empty($row['modified_member'])) |
|
250 |
+ $posters[] = $row['modified_member']; |
|
251 |
+ |
|
252 |
+ $context['ticket_messages'][] = $row['id_msg']; |
|
253 |
+ } |
|
254 |
+ $smcFunc['db_free_result']($query); |
|
255 |
+ |
|
256 |
+ // We might want the OP's avatar, add 'em to the list -- just in case. |
|
257 |
+ $posters[] = $context['ticket']['id_member']; |
|
258 |
+ |
|
259 |
+ $posters = array_unique($posters); |
|
260 |
+ |
|
261 |
+ $context['shd_is_staff'] = array(); |
|
262 |
+ // Get the poster data |
|
263 |
+ if (!empty($posters)) |
|
264 |
+ { |
|
265 |
+ loadMemberData($posters); |
|
266 |
+ |
|
267 |
+ // Are they current team members? |
|
268 |
+ $team = array_intersect($posters, shd_members_allowed_to('shd_staff')); |
|
269 |
+ |
|
270 |
+ foreach ($team as $member) |
|
271 |
+ $context['shd_is_staff'][$member] = true; |
|
272 |
+ } |
|
273 |
+ |
|
274 |
+ if (!empty($context['ticket_messages'])) |
|
275 |
+ { |
|
276 |
+ $reply_request = shd_db_query('', ' |
|
277 |
+ SELECT |
|
278 |
+ id_msg, poster_time, poster_ip, id_member, modified_time, modified_name, modified_member, body, |
|
279 |
+ smileys_enabled, poster_name, poster_email, message_status |
|
280 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
281 |
+ WHERE id_msg IN ({array_int:message_list})' . (!empty($context['ticket']['display_recycle']) ? '' : ' |
|
282 |
+ AND message_status IN ({array_int:msg_normal})') . ' |
|
283 |
+ ORDER BY id_msg', |
|
284 |
+ array( |
|
285 |
+ 'message_list' => $context['ticket_messages'], |
|
286 |
+ 'msg_normal' => array(MSG_STATUS_NORMAL), |
|
287 |
+ ) |
|
288 |
+ ); |
|
289 |
+ } |
|
290 |
+ else |
|
291 |
+ { |
|
292 |
+ $reply_request = false; |
|
293 |
+ $context['first_message'] = 0; |
|
294 |
+ $context['first_new_message'] = false; |
|
295 |
+ } |
|
296 |
+ |
|
297 |
+ // Grab the avatar for the poster |
|
298 |
+ $context['ticket']['poster_avatar'] = empty($context['ticket']['member']['id']) ? array() : (loadMemberContext($context['ticket']['id_member']) ? $memberContext[$context['ticket']['id_member']]['avatar'] : array()); |
|
299 |
+ |
|
300 |
+ // Before we grab attachments, also make sure we get any from the first msg (i.e. the ticket) |
|
301 |
+ $context['ticket_messages'][] = $context['ticket']['first_msg']; |
|
302 |
+ shd_display_load_attachments(); |
|
303 |
+ |
|
304 |
+ // Mark read goes here |
|
305 |
+ if (!empty($user_info['id'])) |
|
306 |
+ { |
|
307 |
+ $smcFunc['db_insert']('replace', |
|
308 |
+ '{db_prefix}helpdesk_log_read', |
|
309 |
+ array( |
|
310 |
+ 'id_ticket' => 'int', 'id_member' => 'int', 'id_msg' => 'int', |
|
311 |
+ ), |
|
312 |
+ array( |
|
313 |
+ $context['ticket_id'], $user_info['id'], $ticketinfo['id_last_msg'], |
|
314 |
+ ), |
|
315 |
+ array('id_member', 'id_topic') |
|
316 |
+ ); |
|
317 |
+ } |
|
318 |
+ |
|
319 |
+ // Build the link tree. If the ticket is recycled, display 'Recycle bin', else 'Tickets'. |
|
320 |
+ $context['linktree'][] = array( |
|
321 |
+ 'url' => $context['ticket']['status']['level'] == TICKET_STATUS_DELETED ? $scripturl . '?action=helpdesk;sa=recyclebin' : $scripturl . '?action=helpdesk;sa=main', |
|
322 |
+ 'name' => $context['ticket']['status']['level'] == TICKET_STATUS_DELETED ? $txt['shd_recycle_bin'] : $txt['shd_linktree_tickets'], |
|
323 |
+ ); |
|
324 |
+ // If it's closed, add that to the linktree. |
|
325 |
+ if ($context['ticket']['status']['level'] == TICKET_STATUS_CLOSED) |
|
326 |
+ $context['linktree'][] = array( |
|
327 |
+ 'url' => $scripturl . '?action=helpdesk;sa=closedtickets', |
|
328 |
+ 'name' => $txt['shd_tickets_closed'], |
|
329 |
+ ); |
|
330 |
+ // Lastly add the ticket name and link. |
|
331 |
+ $context['linktree'][] = array( |
|
332 |
+ 'url' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'], |
|
333 |
+ 'name' => $context['ticket']['subject'], |
|
334 |
+ ); |
|
335 |
+ |
|
336 |
+ // Template stuff |
|
337 |
+ $context['sub_template'] = 'viewticket'; |
|
338 |
+ $context['page_title'] = $txt['shd_helpdesk'] . ' [' . $context['ticket']['display_id'] . '] ' . $context['ticket']['subject']; |
|
339 |
+ |
|
340 |
+ // Ticket navigation / permission |
|
341 |
+ $context['can_reply'] = !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_reply_ticket_any') || ($context['ticket']['ticket_opener'] && shd_allowed_to('shd_reply_ticket_own'))); // needs perms - calc'd here because we use it in display template too |
|
342 |
+ $context['can_quote'] = $context['can_reply'] && !empty($modSettings['shd_allow_ticket_bbc']); |
|
343 |
+ $context['can_go_advanced'] = !empty($modSettings['shd_allow_ticket_bbc']) || !empty($modSettings['allow_ticket_smileys']) || shd_allowed_to('shd_post_attachment'); |
|
344 |
+ $context['shd_can_move_to_topic'] = empty($modSettings['shd_disable_tickettotopic']) && shd_allowed_to('shd_ticket_to_topic') && empty($modSettings['shd_helpdesk_only']); |
|
345 |
+ $context['can_solve'] = !$context['ticket']['deleted'] && (shd_allowed_to('shd_resolve_ticket_any') || (shd_allowed_to('shd_resolve_ticket_own') && $context['ticket']['ticket_opener'])); |
|
346 |
+ |
|
347 |
+ // And off we go |
|
348 |
+ $context['ticket_navigation'] = array(); |
|
349 |
+ $context['ticket_navigation'][] = array( |
|
350 |
+ 'url' => $scripturl . '?action=helpdesk;sa=editticket;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
|
351 |
+ 'icon' => 'edit', |
|
352 |
+ 'alt' => '*', |
|
353 |
+ 'display' => !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_edit_reply_any') || ($context['ticket']['ticket_opener'] && shd_allowed_to('shd_edit_reply_own'))), |
|
354 |
+ 'text' => 'shd_ticket_edit', |
|
355 |
+ ); |
|
356 |
+ $context['ticket_navigation'][] = array( |
|
357 |
+ 'url' => $scripturl . '?action=helpdesk;sa=markunread;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
|
358 |
+ 'icon' => 'unread', |
|
359 |
+ 'alt' => '*', |
|
360 |
+ 'display' => !$context['ticket']['closed'] && !$context['ticket']['deleted'], |
|
361 |
+ 'text' => 'shd_ticket_markunread', |
|
362 |
+ ); |
|
363 |
+ $context['ticket_navigation'][] = array( |
|
364 |
+ 'url' => $scripturl . '?action=helpdesk;sa=resolveticket;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
|
365 |
+ 'icon' => !$context['ticket']['closed'] ? 'resolved' : 'unresolved', |
|
366 |
+ 'alt' => '*', |
|
367 |
+ 'display' => $context['can_solve'], |
|
368 |
+ 'text' => !$context['ticket']['closed'] ? 'shd_ticket_resolved' : 'shd_ticket_unresolved', |
|
369 |
+ ); |
|
370 |
+ |
|
371 |
+ // This is always going to be a pain. But it should be possible to contextualise it nicely. |
|
372 |
+ // And while this isn't quite as nicely formatted as a single nice array definition, |
|
373 |
+ // imagine trying to debug the display and text options later if it were done with nested ternaries... *shudder* |
|
374 |
+ $assign_nav = array( |
|
375 |
+ 'url' => $scripturl . '?action=helpdesk;sa=assign;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
|
376 |
+ 'icon' => 'assign', |
|
377 |
+ 'alt' => '*', |
|
378 |
+ 'text' => '', |
|
379 |
+ 'display' => false, |
|
380 |
+ ); |
|
381 |
+ if (shd_allowed_to('shd_assign_ticket_any')) |
|
382 |
+ { |
|
383 |
+ $assign_nav['display'] = shd_allowed_to('shd_staff') && !$context['ticket']['closed'] && !$context['ticket']['deleted']; |
|
384 |
+ $assign_nav['text'] = empty($context['ticket']['id_member_assigned']) ? 'shd_ticket_assign' : 'shd_ticket_reassign'; |
|
385 |
+ } |
|
386 |
+ elseif (shd_allowed_to('shd_assign_ticket_own')) |
|
387 |
+ { |
|
388 |
+ $assign_nav['display'] = !$context['ticket']['closed'] && !$context['ticket']['deleted'] && shd_allowed_to('shd_staff') && (empty($context['ticket']['id_member_assigned']) || $context['ticket']['assigned_self']); // either not assigned or assigned to self |
|
389 |
+ $assign_nav['text'] = $context['ticket']['assigned_self'] ? 'shd_ticket_unassign' : 'shd_ticket_assign_self'; |
|
390 |
+ } |
|
391 |
+ |
|
392 |
+ $context['ticket_navigation'][] = $assign_nav; |
|
393 |
+ |
|
394 |
+ $context['ticket_navigation'][] = array( |
|
395 |
+ 'url' => $scripturl . '?action=helpdesk;sa=deleteticket;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
|
396 |
+ 'icon' => 'delete', |
|
397 |
+ 'alt' => '*', |
|
398 |
+ 'display' => !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_delete_ticket_any') || (shd_allowed_to('shd_delete_ticket_own') && $context['ticket']['ticket_opener'])), |
|
399 |
+ 'text' => 'shd_ticket_delete', |
|
400 |
+ 'onclick' => 'return confirm(' . JavaScriptEscape($txt['shd_delete_confirm']) . ');', |
|
401 |
+ ); |
|
402 |
+ $context['ticket_navigation'][] = array( |
|
403 |
+ 'url' => $scripturl . '?action=helpdesk;sa=restoreticket;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
|
404 |
+ 'icon' => 'restore', |
|
405 |
+ 'alt' => '*', |
|
406 |
+ 'display' => $context['ticket']['deleted'] && (shd_allowed_to('shd_restore_ticket_any') || (shd_allowed_to('shd_restore_ticket_own') && $context['ticket']['ticket_opener'])), |
|
407 |
+ 'text' => 'shd_ticket_restore', |
|
408 |
+ ); |
|
409 |
+ $context['ticket_navigation'][] = array( |
|
410 |
+ 'url' => $scripturl . '?action=helpdesk;sa=permadelete;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
|
411 |
+ 'icon' => 'delete', |
|
412 |
+ 'alt' => '*', |
|
413 |
+ 'display' => $context['ticket']['deleted'] && shd_allowed_to('shd_delete_recycling'), |
|
414 |
+ 'text' => 'shd_delete_permanently', |
|
415 |
+ 'onclick' => 'return confirm(' . JavaScriptEscape($txt['shd_delete_permanently_confirm']) . ');', |
|
416 |
+ ); |
|
417 |
+ $context['ticket_navigation'][] = array( |
|
418 |
+ 'url' => $scripturl . '?action=helpdesk;sa=tickettotopic;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
|
419 |
+ 'icon' => 'tickettotopic', |
|
420 |
+ 'alt' => '*', |
|
421 |
+ 'display' => $context['shd_can_move_to_topic'] && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && ($context['ticket']['deleted_replies'] == 0 || shd_allowed_to('shd_access_recyclebin')), |
|
422 |
+ 'text' => 'shd_ticket_move_to_topic', |
|
423 |
+ ); |
|
424 |
+ |
|
425 |
+ // If we are going SMF style with the navigation, we need to rework the structure a wee bit. |
|
426 |
+ // No sense making a new array, mind, just fix up the existing one a touch, and don't do this on the master as we don't always need it. |
|
427 |
+ if (empty($modSettings['shd_ticketnav_style']) || !in_array($modSettings['shd_ticketnav_style'], array('sd', 'sdcompact', 'smf'))) |
|
428 |
+ $modSettings['shd_ticketnav_style'] = 'sd'; |
|
429 |
+ |
|
430 |
+ if ($modSettings['shd_ticketnav_style'] == 'smf') |
|
431 |
+ foreach ($context['ticket_navigation'] as $key => $button) |
|
432 |
+ { |
|
433 |
+ $context['can_' . $button['text']] = $button['display']; |
|
434 |
+ $context['ticket_navigation'][$key] += array( |
|
435 |
+ 'lang' => true, |
|
436 |
+ 'test' => 'can_' . $button['text'], |
|
437 |
+ 'image' => 'shd_ticket_' . $button['icon'] . '.png', |
|
438 |
+ ); |
|
439 |
+ } |
|
440 |
+ |
|
441 |
+ // Quick reply stuffs |
|
442 |
+ require_once($sourcedir . '/sd_source/SimpleDesk-Post.php'); |
|
443 |
+ require_once($sourcedir . '/Subs-Editor.php'); |
|
444 |
+ loadTemplate('sd_template/SimpleDesk-Post'); |
|
445 |
+ |
|
446 |
+ $context['ticket_form']['ticket'] = $context['ticket_id']; |
|
447 |
+ $context['ticket_form']['num_allowed_attachments'] = empty($modSettings['attachmentNumPerPostLimit']) || $modSettings['shd_attachments_mode'] == 'ticket' ? -1 : $modSettings['attachmentNumPerPostLimit']; |
|
448 |
+ $context['ticket_form']['do_attach'] = shd_allowed_to('shd_post_attachment'); |
|
449 |
+ $context['ticket_form']['num_replies'] = $context['ticket']['num_replies']; |
|
450 |
+ $context['ticket_form']['disable_smileys'] = empty($modSettings['shd_allow_ticket_smileys']); |
|
451 |
+ shd_posting_additional_options(); |
|
452 |
+ |
|
453 |
+ // Set up the fancy editor |
|
454 |
+ shd_postbox( |
|
455 |
+ 'shd_message', |
|
456 |
+ '', |
|
457 |
+ array( |
|
458 |
+ 'post_button' => $txt['shd_reply_ticket'], |
|
459 |
+ ) |
|
460 |
+ ); |
|
461 |
+ |
|
462 |
+ // Lastly, our magic AJAX stuff ;D and we know we already made html_headers exist in SimpleDesk.php, score! |
|
463 |
+ $context['html_headers'] .= ' |
|
464 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
465 |
+ var sSessI = "' . $context['session_id'] . '"; |
|
466 |
+ var sSessV = "' . $context['session_var'] . '";'; |
|
467 |
+ |
|
468 |
+ if ($context['ticket']['privacy']['can_change']) |
|
469 |
+ $context['html_headers'] .= ' |
|
470 |
+ var shd_ajax_problem = ' . JavaScriptEscape($txt['shd_ajax_problem']) . '; |
|
471 |
+ var privacyCtl = new shd_privacyControl({ |
|
472 |
+ ticket: ' . $context['ticket_id'] . ', |
|
473 |
+ sUrl: smf_scripturl + "?action=helpdesk;sa=ajax;op=privacy;ticket=' . $context['ticket_id'] . '", |
|
474 |
+ sSession: sSessV + "=" + sSessI, |
|
475 |
+ sSrcA: "privlink", |
|
476 |
+ sDestSpan: "privacy" |
|
477 |
+ });'; |
|
478 |
+ |
|
479 |
+ if ($context['ticket']['urgency']['increase'] || $context['ticket']['urgency']['decrease']) |
|
480 |
+ $context['html_headers'] .= ' |
|
481 |
+ var urgencyCtl = new shd_urgencyControl({ |
|
482 |
+ ticket: ' . $context['ticket_id'] . ', |
|
483 |
+ sUrl: smf_scripturl + "?action=helpdesk;sa=ajax;op=urgency;ticket=' . $context['ticket_id'] . ';change=", |
|
484 |
+ sSession: sSessV + "=" + sSessI, |
|
485 |
+ sDestSpan: "urgency", |
|
486 |
+ aButtons: ["up", "down"], |
|
487 |
+ aButtonOps: { up: "increase", down: "decrease" } |
|
488 |
+ });'; |
|
489 |
+ |
|
490 |
+ if (!empty($options['display_quick_reply'])) |
|
491 |
+ $context['html_headers'] .= ' |
|
492 |
+ var oQuickReply = new QuickReply({ |
|
493 |
+ bDefaultCollapsed: ' . (!empty($options['display_quick_reply']) && $options['display_quick_reply'] == 2 ? 'false' : 'true') . ', |
|
494 |
+ iTicketId: ' . $context['ticket_id'] . ', |
|
495 |
+ iStart: ' . $context['start'] . ', |
|
496 |
+ sScriptUrl: smf_scripturl, |
|
497 |
+ sImagesUrl: "' . $settings['images_url'] . '", |
|
498 |
+ sContainerId: "quickReplyOptions", |
|
499 |
+ sImageId: "quickReplyExpand", |
|
500 |
+ sImageCollapsed: "collapse.gif", |
|
501 |
+ sImageExpanded: "expand.gif", |
|
502 |
+ sJumpAnchor: "quickreply", |
|
503 |
+ sHeaderId: "quickreplyheader", |
|
504 |
+ sFooterId: "quickreplyfooter" |
|
505 |
+ });'; |
|
506 |
+ |
|
507 |
+ $context['html_headers'] .= ' |
|
508 |
+ var ActionLog = new ActionLog({ |
|
509 |
+ sImagesUrl: "' . $settings['images_url'] . '", |
|
510 |
+ sContainerId: "ticket_log", |
|
511 |
+ sImageId: "shd_ticket_log_expand", |
|
512 |
+ sImageCollapsed: "collapse.gif", |
|
513 |
+ sImageExpanded: "expand.gif", |
|
514 |
+ sHeaderId: "ticket_log_header", |
|
515 |
+ });'; |
|
516 |
+ |
|
517 |
+ if (!empty($options['display_quick_reply']) && $context['can_go_advanced']) |
|
518 |
+ $context['html_headers'] .= ' |
|
519 |
+ function goAdvanced() |
|
520 |
+ { |
|
521 |
+ document.getElementById("shd_bbcbox").style.display = ' . (!empty($modSettings['shd_allow_ticket_bbc']) ? '""' : '"none"') . '; |
|
522 |
+ document.getElementById("shd_smileybox").style.display = ' . (!empty($modSettings['shd_allow_ticket_smileys']) ? '""' : '"none"') . '; |
|
523 |
+ document.getElementById("shd_attach_container").style.display = ' . (!empty($context['ticket_form']['do_attach']) ? '""' : '"none"') . '; |
|
524 |
+ document.getElementById("shd_goadvancedbutton").style.display = "none";' . (!empty($context['controls']['richedit']['shd_message']['rich_active']) ? ' |
|
525 |
+ oEditorHandle_shd_message.toggleView(true);' : '') . ' |
|
526 |
+ } |
|
527 |
+ '; |
|
528 |
+ |
|
529 |
+ $context['html_headers'] .= ' |
|
530 |
+ // ]' . ']></script>'; |
|
531 |
+ |
|
532 |
+ $context['shd_display'] = true; |
|
533 |
+ $context['controls']['richedit']['shd_message']['rich_active'] = 0; // we don't want it by default! |
|
534 |
+ |
|
535 |
+ // Register this form in the session variables. |
|
536 |
+ checkSubmitOnce('register'); |
|
537 |
+ |
|
538 |
+ // Should we load and display this ticket's action log? |
|
539 |
+ $context['display_ticket_log'] = !empty($modSettings['shd_display_ticket_logs']) && (shd_allowed_to('shd_view_ticket_logs_any') || (shd_allowed_to('shd_view_ticket_logs_own') && $context['ticket']['ticket_opener'])); |
|
540 |
+ |
|
541 |
+ // If yes, go ahead and load the log entries (Re-using a couple of functions from the ACP) |
|
542 |
+ if (!empty($context['display_ticket_log'])) |
|
543 |
+ { |
|
544 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskAdmin.php'); |
|
545 |
+ $context['ticket_log'] = shd_load_action_log_entries(0, 10, '', '', 'la.id_ticket = ' . $context['ticket_id']); |
|
546 |
+ $context['ticket_log_count'] = shd_count_action_log_entries('la.id_ticket = ' . $context['ticket_id']); |
|
547 |
+ $context['ticket_full_log'] = allowedTo('admin_forum') || shd_allowed_to('admin_helpdesk'); |
|
548 |
+ } |
|
549 |
+ |
|
550 |
+ // Lastly, what about related tickets? |
|
551 |
+ $context['create_relationships'] = shd_allowed_to('shd_create_relationships'); |
|
552 |
+ $context['display_relationships'] = shd_allowed_to('shd_view_relationships') || $context['create_relationships']; |
|
553 |
+ $context['delete_relationships'] = shd_allowed_to('shd_delete_relationships'); |
|
554 |
+ if (!empty($context['display_relationships'])) |
|
555 |
+ { |
|
556 |
+ shd_load_relationships($context['ticket_id']); |
|
557 |
+ if ($context['relationships_count'] == 0 && empty($context['create_relationships'])) |
|
558 |
+ $context['display_relationships'] = false; |
|
559 |
+ } |
|
560 |
+} |
|
561 |
+ |
|
562 |
+/** |
|
563 |
+ * Callback function for the template to load messages. |
|
564 |
+ * |
|
565 |
+ * The process set up by shd_view_ticket() and invoked within template_view_replies() is reasonably complex. |
|
566 |
+ * {@link shd_view_ticket()} identifies what messages should be displayed on the current page of the ticket, and performs a query |
|
567 |
+ * to load the ticket data. Instead, however, of retrieving every row directly into memory before passing to the template, |
|
568 |
+ * it passes the query result, and the name of a handler function into $context, so the template can call to get an |
|
569 |
+ * individual row at a time, which saves memory amongst other things. |
|
570 |
+ * |
|
571 |
+ * With respect to {@link shd_view_ticket()}, the relevant items are $reply_request being defined and $context['get_replies'] |
|
572 |
+ * being defined as the name of this function, and in {@link template_view_replies()}, the reference is $reply = $context['get_replies']() |
|
573 |
+ * |
|
574 |
+ * @return mixed The function returns the "next" message reply's details, or simply false if no replies were available, or no further replies are available. Assuming a reply can be returned, it will be a hash array in the following format: |
|
575 |
+ * <ul> |
|
576 |
+ * <li>id: numeric message id</li> |
|
577 |
+ * <li>member: hash array containing details of the poster; normally the return value from SMF's loadMemberContext() function. A minimal set of details is prepared if the poster holds no current SMF account. Common values: |
|
578 |
+ * <ul> |
|
579 |
+ * <li>name: User's name (falls back to the poster name specified in the replies table)</li> |
|
580 |
+ * <li>id: User's id</li> |
|
581 |
+ * <li>group: Name of the assigned group/post count group of the user</li> |
|
582 |
+ * <li>link: HTML for a hyperlink to their profile</li> |
|
583 |
+ * <li>email: Email address of the poster</li> |
|
584 |
+ * <li>ip: IP address of the poster</li> |
|
585 |
+ * </ul> |
|
586 |
+ * </li> |
|
587 |
+ * <li>body: censored, parsed for smileys and bbcode (in {@link shd_format_text()})</li> |
|
588 |
+ * <li>time: string of the time the reply was posted</li> |
|
589 |
+ * <li>timestamp: internal stored timestamp attached to the reply</li> |
|
590 |
+ * <li>is_staff: boolean value of whether the posting member is currently helpdesk staff</li> |
|
591 |
+ * <li>can_edit: boolean value reflecting if this reply can be edited</li> |
|
592 |
+ * <li>can_delete: boolean value reflecting if this reply can be deleted</li> |
|
593 |
+ * <li>can_restore: boolean value reflecting if this reply can be restored</li> |
|
594 |
+ * <li>ip_address: IP address used to post the message (not necessarily the user's normal IP address); if the user has moderate_forum_members permission, this returns a link to the track IP area, with the IP address as the link text, alternatively simply the IP address if not (is only displayed to helpdesk staff)</li> |
|
595 |
+ * <li>modified: may not be declared, if it is, the message was modified some time after posting, and the following data items are in the hash array within: |
|
596 |
+ * <ul> |
|
597 |
+ * <li>id: user id who edited the reply (not always available)</li> |
|
598 |
+ * <li>time: formatted string of the time the post was edited</li> |
|
599 |
+ * <li>timestamp: raw timestamp of the time the post was edited</li> |
|
600 |
+ * <li>name: user name of the editing user; if we have a definite user id, this should contain the current name, falling back to the previously stored name</li> |
|
601 |
+ * <li>link: if we have a known, valid user id for the post's editor, this will contain a link to their profile, with the link text using their current display name; alternatively it will contain a regular string which is the username stored with the edit.</li> |
|
602 |
+ * </ul> |
|
603 |
+ * </li> |
|
604 |
+ * </ul> |
|
605 |
+ * |
|
606 |
+ * @see shd_view_ticket() |
|
607 |
+ * @since 1.0 |
|
608 |
+*/ |
|
609 |
+function shd_prepare_ticket_context() |
|
610 |
+{ |
|
611 |
+ global $settings, $txt, $modSettings, $scripturl, $options, $user_info, $smcFunc; |
|
612 |
+ global $memberContext, $context, $reply_request, $user_profile; |
|
613 |
+ |
|
614 |
+ if (empty($reply_request)) |
|
615 |
+ return false; |
|
616 |
+ |
|
617 |
+ $message = $smcFunc['db_fetch_assoc']($reply_request); |
|
618 |
+ if (!$message) |
|
619 |
+ { |
|
620 |
+ $smcFunc['db_free_result']($reply_request); |
|
621 |
+ return false; |
|
622 |
+ } |
|
623 |
+ |
|
624 |
+ if (!loadMemberContext($message['id_member'], true)) |
|
625 |
+ { |
|
626 |
+ // Notice this information isn't used anywhere else.... |
|
627 |
+ $memberContext[$message['id_member']]['name'] = $message['poster_name']; |
|
628 |
+ $memberContext[$message['id_member']]['id'] = 0; |
|
629 |
+ $memberContext[$message['id_member']]['group'] = $txt['guest_title']; |
|
630 |
+ $memberContext[$message['id_member']]['link'] = $message['poster_name']; |
|
631 |
+ $memberContext[$message['id_member']]['email'] = $message['poster_email']; |
|
632 |
+ $memberContext[$message['id_member']]['show_email'] = showEmailAddress(true, 0); |
|
633 |
+ $memberContext[$message['id_member']]['is_guest'] = true; |
|
634 |
+ $memberContext[$message['id_member']]['group_stars'] = ''; |
|
635 |
+ } |
|
636 |
+ $memberContext[$message['id_member']]['ip'] = $message['poster_ip']; |
|
637 |
+ |
|
638 |
+ censorText($message['body']); |
|
639 |
+ $message['body'] = shd_format_text($message['body'], $message['smileys_enabled'], 'shd_reply_' . $message['id_msg']); |
|
640 |
+ |
|
641 |
+ $output = array( |
|
642 |
+ 'id' => $message['id_msg'], |
|
643 |
+ 'member' => &$memberContext[$message['id_member']], |
|
644 |
+ 'time' => timeformat($message['poster_time']), |
|
645 |
+ 'timestamp' => forum_time(true, $message['poster_time']), |
|
646 |
+ 'body' => $message['body'], |
|
647 |
+ 'is_staff' => !empty($context['shd_is_staff'][$message['id_member']]), |
|
648 |
+ 'can_edit' => $message['message_status'] != MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_edit_reply_any') || ($message['id_member'] == $user_info['id'] && shd_allowed_to('shd_edit_reply_own'))), |
|
649 |
+ 'can_delete' => $message['message_status'] != MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_delete_reply_any') || ($message['id_member'] == $user_info['id'] && shd_allowed_to('shd_delete_reply_own'))), |
|
650 |
+ 'can_restore' => $message['message_status'] == MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_restore_reply_any') || ($message['id_member'] == $user_info['id'] && shd_allowed_to('shd_restore_reply_own'))), |
|
651 |
+ 'can_permadelete' => $message['message_status'] == MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && shd_allowed_to('shd_delete_recycling'), |
|
652 |
+ 'can_split' => $message['message_status'] != MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_split_ticket_any') || ($context['ticket']['ticket_opener'] && shd_allowed_to('shd_split_ticket_own'))), |
|
653 |
+ 'message_status' => $message['message_status'], |
|
654 |
+ 'link' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '.msg' . $message['id_msg'] . '#msg' . $message['id_msg'], |
|
655 |
+ ); |
|
656 |
+ |
|
657 |
+ if (shd_allowed_to('shd_view_ip_any') || ($message['id_member'] == $user_info['id'] && shd_allowed_to('shd_view_ip_own'))) |
|
658 |
+ $output['ip_address'] = $context['link_ip_address'] ? ('<a href="' . $scripturl . '?action=trackip;searchip=' . $message['poster_ip'] . '">' . $message['poster_ip'] . '</a>') : $message['poster_ip']; |
|
659 |
+ |
|
660 |
+ if (!empty($message['modified_time'])) |
|
661 |
+ { |
|
662 |
+ $output['modified'] = array( |
|
663 |
+ 'time' => timeformat($message['modified_time']), |
|
664 |
+ 'timestamp' => forum_time(true, $message['modified_time']), |
|
665 |
+ 'id' => !empty($user_profile[$message['modified_member']]) ? $message['modified_member'] : 0, |
|
666 |
+ 'name' => !empty($user_profile[$message['modified_member']]) ? $user_profile[$message['modified_member']]['real_name'] : $message['modified_name'], |
|
667 |
+ ); |
|
668 |
+ $output['modified']['link'] = shd_profile_link($output['modified']['name'], $output['modified']['id']); |
|
669 |
+ } |
|
670 |
+ |
|
671 |
+ if (!empty($context['ticket_start_newfrom']) && $context['ticket_start_newfrom'] == $message['id_msg']) |
|
672 |
+ $output['is_new'] = true; |
|
673 |
+ |
|
674 |
+ return $output; |
|
675 |
+} |
|
676 |
+ |
|
677 |
+/** |
|
678 |
+ * Loads data on all the attachments that will be displayed in a ticket's view. |
|
679 |
+ * |
|
680 |
+ * Queries the {db_prefix}helpdesk_attachments table for the current ticket, or the messages that will be displayed |
|
681 |
+ * (previously identified by {@link shd_view_ticket()}) and loads the id, name and size of them for display purposes. Differentiation |
|
682 |
+ * between "attach to ticket" and "attach to reply" is made here; the data is loaded differently depending on the context; |
|
683 |
+ * "attach to ticket" is simply loaded into an indexed array stored in $context['ticket_attach']['ticket'], while "attach |
|
684 |
+ * to reply" is loaded into an indexed array subset in $context['ticket_attach']['reply'][msg_id] to retain the association. |
|
685 |
+ * |
|
686 |
+ * @return array Builds an array within $contxt['ticket_attach'], as noted above. The individual data items per attachment are: |
|
687 |
+ * - id: Numeric id for attachment itself |
|
688 |
+ * - name: HTML sanitised name of the attachment's filename |
|
689 |
+ * - size: string listing the size of the attachment, converted to kilobytes and rounded to two decimal places |
|
690 |
+ * - byte_size: integer of raw size of attachment |
|
691 |
+ * - href: the URL that would be used to access the attachment (required $context['ticket_id'] to be available, which it would anyway) |
|
692 |
+ * - link: full HTML "a" element linking to the attachment, using the filename as the link text and (since 1.1) with icon img element |
|
693 |
+ * @since 1.0 |
|
694 |
+*/ |
|
695 |
+function shd_display_load_attachments() |
|
696 |
+{ |
|
697 |
+ global $modSettings, $context, $smcFunc, $scripturl, $txt; |
|
698 |
+ |
|
699 |
+ $context['ticket_attach'][$modSettings['shd_attachments_mode']] = array(); |
|
700 |
+ |
|
701 |
+ if ($modSettings['shd_attachments_mode'] == 'ticket') |
|
702 |
+ { |
|
703 |
+ $query = shd_db_query('', ' |
|
704 |
+ SELECT hda.id_attach, hda.id_msg, hda.id_ticket, a.filename, a.id_folder, a.file_hash, IFNULL(a.size, 0) AS filesize, |
|
705 |
+ a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ', |
|
706 |
+ IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . ' |
|
707 |
+ FROM {db_prefix}helpdesk_attachments AS hda |
|
708 |
+ INNER JOIN {db_prefix}attachments AS a ON (hda.id_attach = a.id_attach)' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ' |
|
709 |
+ LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . ' |
|
710 |
+ WHERE hda.id_ticket = {int:ticket} |
|
711 |
+ AND a.attachment_type = {int:attachment_type} |
|
712 |
+ ORDER BY hda.id_attach', |
|
713 |
+ array( |
|
714 |
+ 'ticket' => $context['ticket_id'], |
|
715 |
+ 'attachment_type' => 0, |
|
716 |
+ ) |
|
717 |
+ ); |
|
718 |
+ |
|
719 |
+ // Ticket ones can just be added on, they're nice and straightforward |
|
720 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
721 |
+ $context['ticket_attach'][$modSettings['shd_attachments_mode']][$row['id_attach']] = shd_attachment_info($row); |
|
722 |
+ |
|
723 |
+ if (empty($context['ticket_attach'][$modSettings['shd_attachments_mode']])) |
|
724 |
+ $context['ticket_attach'][$modSettings['shd_attachments_mode']] = array(); |
|
725 |
+ |
|
726 |
+ ksort($context['ticket_attach'][$modSettings['shd_attachments_mode']]); |
|
727 |
+ } |
|
728 |
+ else |
|
729 |
+ { |
|
730 |
+ if (empty($context['ticket_messages'])) |
|
731 |
+ return; |
|
732 |
+ |
|
733 |
+ $query = shd_db_query('', ' |
|
734 |
+ SELECT hda.id_attach, hda.id_msg, hda.id_ticket, a.filename, a.id_folder, a.file_hash, IFNULL(a.size, 0) AS filesize, |
|
735 |
+ a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ', |
|
736 |
+ IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . ' |
|
737 |
+ FROM {db_prefix}helpdesk_attachments AS hda |
|
738 |
+ INNER JOIN {db_prefix}attachments AS a ON (hda.id_attach = a.id_attach)' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ' |
|
739 |
+ LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . ' |
|
740 |
+ WHERE hda.id_msg IN ({array_int:msg}) |
|
741 |
+ AND a.attachment_type = {int:attachment_type} |
|
742 |
+ ORDER BY hda.id_attach', |
|
743 |
+ array( |
|
744 |
+ 'msg' => $context['ticket_messages'], |
|
745 |
+ 'attachment_type' => 0, |
|
746 |
+ ) |
|
747 |
+ ); |
|
748 |
+ |
|
749 |
+ // Message ones are a little trickier since we actually need to tie them to msg ids |
|
750 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
751 |
+ $context['ticket_attach'][$modSettings['shd_attachments_mode']][$row['id_msg']][$row['id_attach']] = shd_attachment_info($row); |
|
752 |
+ |
|
753 |
+ foreach ($context['ticket_attach'][$modSettings['shd_attachments_mode']] as $msg => $attachments) |
|
754 |
+ { |
|
755 |
+ if (empty($context['ticket_attach'][$modSettings['shd_attachments_mode']][$msg])) |
|
756 |
+ $context['ticket_attach'][$modSettings['shd_attachments_mode']][$msg] = array(); |
|
757 |
+ |
|
758 |
+ ksort($context['ticket_attach'][$modSettings['shd_attachments_mode']][$msg]); |
|
759 |
+ } |
|
760 |
+ } |
|
761 |
+ |
|
762 |
+ $smcFunc['db_free_result']($query); |
|
763 |
+} |
|
764 |
+ |
|
765 |
+function shd_attachment_info($attach_info) |
|
766 |
+{ |
|
767 |
+ global $scripturl, $context, $modSettings, $txt, $sourcedir, $smcFunc; |
|
768 |
+ |
|
769 |
+ $filename = preg_replace('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attach_info['filename'])); |
|
770 |
+ |
|
771 |
+ $attach = array( |
|
772 |
+ 'id' => $attach_info['id_attach'], |
|
773 |
+ 'name' => $filename, |
|
774 |
+ 'size' => round($attach_info['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'], |
|
775 |
+ 'byte_size' => $attach_info['filesize'], |
|
776 |
+ 'href' => $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_attach'], |
|
777 |
+ 'link' => shd_attach_icon($filename) . ' <a href="' . $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_attach'] . '">' . htmlspecialchars($attach_info['filename']) . '</a>', |
|
778 |
+ 'is_image' => !empty($modSettings['attachmentShowImages']) && !empty($attach_info['width']) && !empty($attach_info['height']), |
|
779 |
+ ); |
|
780 |
+ |
|
781 |
+ if ($attach['is_image']) |
|
782 |
+ { |
|
783 |
+ $attach += array( |
|
784 |
+ 'real_width' => $attach_info['width'], |
|
785 |
+ 'width' => $attach_info['width'], |
|
786 |
+ 'real_height' => $attach_info['height'], |
|
787 |
+ 'height' => $attach_info['height'], |
|
788 |
+ ); |
|
789 |
+ |
|
790 |
+ // Let's see, do we want thumbs? |
|
791 |
+ if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attach_info['width'] > $modSettings['attachmentThumbWidth'] || $attach_info['height'] > $modSettings['attachmentThumbHeight']) && strlen($attach_info['filename']) < 249) |
|
792 |
+ { |
|
793 |
+ // A proper thumb doesn't exist yet? Create one! |
|
794 |
+ if (empty($attach_info['id_thumb']) || $attach_info['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attach_info['thumb_height'] > $modSettings['attachmentThumbHeight'] || ($attach_info['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attach_info['thumb_height'] < $modSettings['attachmentThumbHeight'])) |
|
795 |
+ { |
|
796 |
+ $filename = getAttachmentFilename($attach_info['filename'], $attach_info['id_attach'], $attach_info['id_folder']); |
|
797 |
+ |
|
798 |
+ require_once($sourcedir . '/Subs-Graphics.php'); |
|
799 |
+ if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) |
|
800 |
+ { |
|
801 |
+ // So what folder are we putting this image in? |
|
802 |
+ if (!empty($modSettings['currentAttachmentUploadDir'])) |
|
803 |
+ { |
|
804 |
+ if (!is_array($modSettings['attachmentUploadDir'])) |
|
805 |
+ $modSettings['attachmentUploadDir'] = @unserialize($modSettings['attachmentUploadDir']); |
|
806 |
+ $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']]; |
|
807 |
+ $id_folder_thumb = $modSettings['currentAttachmentUploadDir']; |
|
808 |
+ } |
|
809 |
+ else |
|
810 |
+ { |
|
811 |
+ $path = $modSettings['attachmentUploadDir']; |
|
812 |
+ $id_folder_thumb = 1; |
|
813 |
+ } |
|
814 |
+ |
|
815 |
+ // Calculate the size of the created thumbnail. |
|
816 |
+ $size = @getimagesize($filename . '_thumb'); |
|
817 |
+ list ($attach_info['thumb_width'], $attach_info['thumb_height']) = $size; |
|
818 |
+ $thumb_size = filesize($filename . '_thumb'); |
|
819 |
+ |
|
820 |
+ // These are the only valid image types for SMF. |
|
821 |
+ $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff'); |
|
822 |
+ |
|
823 |
+ // What about the extension? |
|
824 |
+ $thumb_ext = isset($validImageTypes[$size[2]]) ? $validImageTypes[$size[2]] : ''; |
|
825 |
+ |
|
826 |
+ // Figure out the mime type. |
|
827 |
+ if (!empty($size['mime'])) |
|
828 |
+ $thumb_mime = $size['mime']; |
|
829 |
+ else |
|
830 |
+ $thumb_mime = 'image/' . $thumb_ext; |
|
831 |
+ |
|
832 |
+ $thumb_filename = $attach_info['filename'] . '_thumb'; |
|
833 |
+ $thumb_hash = getAttachmentFilename($thumb_filename, false, null, true); |
|
834 |
+ |
|
835 |
+ // Add this beauty to the database. |
|
836 |
+ $smcFunc['db_insert']('', |
|
837 |
+ '{db_prefix}attachments', |
|
838 |
+ array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'fileext' => 'string', 'mime_type' => 'string'), |
|
839 |
+ array($id_folder_thumb, 0, 3, $thumb_filename, $thumb_hash, (int) $thumb_size, (int) $attach_info['thumb_width'], (int) $attach_info['thumb_height'], $thumb_ext, $thumb_mime), |
|
840 |
+ array('id_attach') |
|
841 |
+ ); |
|
842 |
+ $old_id_thumb = $attach_info['id_thumb']; |
|
843 |
+ $attach_info['id_thumb'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach'); |
|
844 |
+ if (!empty($attach_info['id_thumb'])) |
|
845 |
+ { |
|
846 |
+ // Update the tables to notify that we has us a thumbnail |
|
847 |
+ $smcFunc['db_query']('', ' |
|
848 |
+ UPDATE {db_prefix}attachments |
|
849 |
+ SET id_thumb = {int:id_thumb} |
|
850 |
+ WHERE id_attach = {int:id_attach}', |
|
851 |
+ array( |
|
852 |
+ 'id_thumb' => $attach_info['id_thumb'], |
|
853 |
+ 'id_attach' => $attach_info['id_attach'], |
|
854 |
+ ) |
|
855 |
+ ); |
|
856 |
+ |
|
857 |
+ $smcFunc['db_insert']('replace', |
|
858 |
+ '{db_prefix}helpdesk_attachments', |
|
859 |
+ array('id_attach' => 'int', 'id_ticket' => 'int', 'id_msg' => 'int'), |
|
860 |
+ array($attach_info['id_thumb'], $attach_info['id_ticket'], $attach_info['id_msg']), |
|
861 |
+ array('id_attach') |
|
862 |
+ ); |
|
863 |
+ |
|
864 |
+ $thumb_realname = getAttachmentFilename($thumb_filename, $attach_info['id_thumb'], $id_folder_thumb, false, $thumb_hash); |
|
865 |
+ rename($filename . '_thumb', $thumb_realname); |
|
866 |
+ |
|
867 |
+ // Do we need to remove an old thumbnail? |
|
868 |
+ if (!empty($old_id_thumb)) |
|
869 |
+ { |
|
870 |
+ require_once($sourcedir . '/ManageAttachments.php'); |
|
871 |
+ removeAttachments(array('id_attach' => $old_id_thumb), '', false, false); |
|
872 |
+ } |
|
873 |
+ } |
|
874 |
+ } |
|
875 |
+ } |
|
876 |
+ |
|
877 |
+ // Only adjust dimensions on successful thumbnail creation. |
|
878 |
+ if (!empty($attach_info['thumb_width']) && !empty($attach_info['thumb_height'])) |
|
879 |
+ { |
|
880 |
+ $attach['width'] = $attach_info['thumb_width']; |
|
881 |
+ $attach['height'] = $attach_info['thumb_height']; |
|
882 |
+ } |
|
883 |
+ } |
|
884 |
+ |
|
885 |
+ if (!empty($attach_info['id_thumb'])) |
|
886 |
+ $attach['thumbnail'] = array( |
|
887 |
+ 'id' => $attach_info['id_thumb'], |
|
888 |
+ 'href' => $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_thumb'] . ';image', |
|
889 |
+ ); |
|
890 |
+ $attach['thumbnail']['has_thumb'] = !empty($attach_info['id_thumb']); |
|
891 |
+ |
|
892 |
+ // If thumbnails are disabled, check the maximum size of the image. |
|
893 |
+ if (!$attach['thumbnail']['has_thumb'] && ((!empty($modSettings['max_image_width']) && $attach_info['width'] > $modSettings['max_image_width']) || (!empty($modSettings['max_image_height']) && $attach_info['height'] > $modSettings['max_image_height']))) |
|
894 |
+ { |
|
895 |
+ if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attach_info['height'] * $modSettings['max_image_width'] / $attach_info['width'] <= $modSettings['max_image_height'])) |
|
896 |
+ { |
|
897 |
+ $attach['width'] = $modSettings['max_image_width']; |
|
898 |
+ $attach['height'] = floor($attach_info['height'] * $modSettings['max_image_width'] / $attach_info['width']); |
|
899 |
+ } |
|
900 |
+ elseif (!empty($modSettings['max_image_width'])) |
|
901 |
+ { |
|
902 |
+ $attach['width'] = floor($attach['width'] * $modSettings['max_image_height'] / $attach['height']); |
|
903 |
+ $attach['height'] = $modSettings['max_image_height']; |
|
904 |
+ } |
|
905 |
+ } |
|
906 |
+ elseif ($attach['thumbnail']['has_thumb']) |
|
907 |
+ // Make it a popup (since invariably it'll break the layout otherwise) |
|
908 |
+ $attach['thumbnail']['javascript'] = 'return reqWin(\'' . $attach['href'] . ';image\', ' . ($attach_info['width'] + 20) . ', ' . ($attach_info['height'] + 20) . ', true);'; |
|
909 |
+ } |
|
910 |
+ |
|
911 |
+ return $attach; |
|
912 |
+} |
|
913 |
+ |
|
914 |
+/** |
|
915 |
+ * Returns the icon name to use given the filename, i.e. looks up icons from a list of known extensions. |
|
916 |
+ * |
|
917 |
+ * @param string $filename The filename of an attachment. |
|
918 |
+ * |
|
919 |
+ * @return string A full link to the image for this attachment. |
|
920 |
+ * @see shd_display_load_attachments() |
|
921 |
+ * @since 1.0 |
|
922 |
+*/ |
|
923 |
+function shd_attach_icon($filename) |
|
924 |
+{ |
|
925 |
+ global $settings, $txt; |
|
926 |
+ static $extension_map = 0; |
|
927 |
+ |
|
928 |
+ // If adding to this list, please remember to update SimpleDesk.english.php with a description in $txt['shd_attachtype_' . $extension] |
|
929 |
+ if (empty($extension_map)) |
|
930 |
+ $extension_map = array( |
|
931 |
+ // Archive formats |
|
932 |
+ 'bz2' => 'zip.png', |
|
933 |
+ 'gz' => 'zip.png', |
|
934 |
+ 'rar' => 'zip.png', |
|
935 |
+ 'zip' => 'zip.png', |
|
936 |
+ // Media: Audio formats |
|
937 |
+ 'mp3' => 'audio.png', |
|
938 |
+ // Media: Image formats |
|
939 |
+ 'bmp' => 'image.png', |
|
940 |
+ 'gif' => 'image.png', |
|
941 |
+ 'jpeg' => 'image.png', |
|
942 |
+ 'jpg' => 'image.png', |
|
943 |
+ 'png' => 'image.png', |
|
944 |
+ 'svg' => 'vector.png', |
|
945 |
+ // Media: Video formats |
|
946 |
+ 'wmv' => 'video.png', |
|
947 |
+ // Office formats |
|
948 |
+ 'doc' => 'word.png', |
|
949 |
+ 'mdb' => 'access.png', |
|
950 |
+ 'ppt' => 'ppoint.png', |
|
951 |
+ 'xls' => 'excel.png', |
|
952 |
+ // Programming languages |
|
953 |
+ 'cpp' => 'cpp.png', |
|
954 |
+ 'php' => 'php.png', |
|
955 |
+ 'py' => 'python.png', |
|
956 |
+ 'rb' => 'ruby.png', |
|
957 |
+ 'sql' => 'sql.png', |
|
958 |
+ // Proprietory formats |
|
959 |
+ 'kmz' => 'world.png', |
|
960 |
+ 'pdf' => 'pdf.png', |
|
961 |
+ 'psd' => 'psd.png', |
|
962 |
+ 'swf' => 'flash.png', |
|
963 |
+ // Miscellaneous |
|
964 |
+ 'exe' => 'app.png', |
|
965 |
+ 'htm' => 'html.png', |
|
966 |
+ 'html' => 'html.png', |
|
967 |
+ 'rtf' => 'rtf.png', |
|
968 |
+ 'txt' => 'text.png', |
|
969 |
+ ); |
|
970 |
+ |
|
971 |
+ $filename = trim($filename); |
|
972 |
+ $extension = ($filename != '') ? strtolower(substr(strrchr($filename, '.'), 1)) : ''; |
|
973 |
+ |
|
974 |
+ if (isset($extension_map[$extension])) |
|
975 |
+ $image = '<img src="' . $settings['default_images_url'] . '/simpledesk/attach/' . $extension_map[$extension] . '"' . (!empty($txt['shd_attachtype_' . $extension]) ? ' alt="' . $txt['shd_attachtype_' . $extension] . '" title="' . $txt['shd_attachtype_' . $extension] . '"' : ' alt=""') . ' />'; |
|
976 |
+ else |
|
977 |
+ $image = '<img src="' . $settings['default_images_url'] . '/simpledesk/attach/blank.png" alt="" />'; |
|
978 |
+ |
|
979 |
+ return $image; |
|
980 |
+} |
|
981 |
+ |
|
982 |
+/** |
|
983 |
+ * Identifies the tickets related to a given ticket. |
|
984 |
+ * |
|
985 |
+ * Queries the system for all tickets related to the specified (typically current) ticket, subject to current user's permissions, and populates $context. |
|
986 |
+ * |
|
987 |
+ * The function populates $context['relationships_count'] with the number of relationships found, and $context['ticket_relationships'] contains an array of the following keys: |
|
988 |
+ * - parent: Current ticket is the parent of the discovered ticket |
|
989 |
+ * - child: Current ticket is a child of the discovered ticket |
|
990 |
+ * - linked: Current ticket is related to discovered ticket |
|
991 |
+ * - duplicated: Curent ticket is a duplicate of discovered ticket |
|
992 |
+ * |
|
993 |
+ * Each of the keyed arrays is an indexed array (each index representing one ticket), of which those are hash arrays containing: |
|
994 |
+ * - id: id of the ticket |
|
995 |
+ * - display_id: zero padded display id of the ticket |
|
996 |
+ * - subject: ticket's name |
|
997 |
+ * - status: status of the discovered ticket (numeric) |
|
998 |
+ * - status_txt: status of the discovered ticket (textual) |
|
999 |
+ * |
|
1000 |
+ * @since 1.1 |
|
1001 |
+*/ |
|
1002 |
+function shd_load_relationships($ticket = 0) |
|
1003 |
+{ |
|
1004 |
+ global $context, $smcFunc, $txt; |
|
1005 |
+ |
|
1006 |
+ if ($ticket == 0) |
|
1007 |
+ $ticket = $context['ticket_id']; |
|
1008 |
+ |
|
1009 |
+ $reltypes = array( |
|
1010 |
+ RELATIONSHIP_ISPARENT => 'parent', |
|
1011 |
+ RELATIONSHIP_ISCHILD => 'child', |
|
1012 |
+ RELATIONSHIP_LINKED => 'linked', |
|
1013 |
+ RELATIONSHIP_DUPLICATED => 'duplicated', |
|
1014 |
+ ); |
|
1015 |
+ |
|
1016 |
+ $context['relationships_count'] = 0; |
|
1017 |
+ foreach ($reltypes as $type) |
|
1018 |
+ $context['ticket_relationships'][$type] = array(); |
|
1019 |
+ |
|
1020 |
+ $query = shd_db_query('', ' |
|
1021 |
+ SELECT hdt.id_ticket, hdt.subject, hdt.status, hdr.rel_type |
|
1022 |
+ FROM {db_prefix}helpdesk_relationships AS hdr |
|
1023 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdr.secondary_ticket = hdt.id_ticket) |
|
1024 |
+ WHERE hdr.primary_ticket = {int:ticket} |
|
1025 |
+ AND {query_see_ticket}', |
|
1026 |
+ array( |
|
1027 |
+ 'ticket' => $ticket, |
|
1028 |
+ ) |
|
1029 |
+ ); |
|
1030 |
+ |
|
1031 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
1032 |
+ { |
|
1033 |
+ $context['relationships_count']++; |
|
1034 |
+ $context['ticket_relationships'][$reltypes[$row['rel_type']]][] = array( |
|
1035 |
+ 'id' => $row['id_ticket'], |
|
1036 |
+ 'display_id' => str_pad($row['id_ticket'], 5, '0', STR_PAD_LEFT), |
|
1037 |
+ 'subject' => $row['subject'], |
|
1038 |
+ 'status' => $row['status'], |
|
1039 |
+ 'status_txt' => $txt['shd_status_' . $row['status']], |
|
1040 |
+ ); |
|
1041 |
+ } |
|
1042 |
+ |
|
1043 |
+ $smcFunc['db_free_result']($query); |
|
1044 |
+} |
|
1045 |
+ |
|
1046 |
+?> |
|
0 | 1047 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,399 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-MergeSplit.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles merging and splitting of tickets, both handling the interface and actual processing thereof. |
|
22 |
+ * |
|
23 |
+ * @package source |
|
24 |
+ * @since 1.1 |
|
25 |
+*/ |
|
26 |
+ |
|
27 |
+if (!defined('SMF')) |
|
28 |
+ die('Hacking attempt...'); |
|
29 |
+ |
|
30 |
+function shd_merge_ticket() |
|
31 |
+{ |
|
32 |
+ global $smcFunc, $context, $user_info, $sourcedir, $txt, $scripturl; |
|
33 |
+ |
|
34 |
+ if (empty($context['ticket_id'])) |
|
35 |
+ fatal_lang_error('shd_no_ticket'); |
|
36 |
+ |
|
37 |
+ $query = shd_db_query('', ' |
|
38 |
+ SELECT subject, id_member_started |
|
39 |
+ FROM {db_prefix}helpdesk_tickets |
|
40 |
+ WHERE {query_see_ticket} |
|
41 |
+ AND id_ticket = {int:ticket}', |
|
42 |
+ array( |
|
43 |
+ 'ticket' => $context['ticket_id'], |
|
44 |
+ ) |
|
45 |
+ ); |
|
46 |
+ |
|
47 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
48 |
+ { |
|
49 |
+ $smcFunc['db_free_result']($query); |
|
50 |
+ $context['current_ticket'] = $row; |
|
51 |
+ |
|
52 |
+ // Now we have something to play with, let's see if we have the permissions to do it. |
|
53 |
+ if (!shd_allowed_to('shd_merge_ticket_any') && (!shd_allowed_to('shd_merge_ticket_own') || ($row['id_member_started'] != $context['user']['id']))) |
|
54 |
+ fatal_lang_error('shd_cannot_merge', false); |
|
55 |
+ } |
|
56 |
+ else |
|
57 |
+ { |
|
58 |
+ $smcFunc['db_free_result']($query); |
|
59 |
+ fatal_lang_error('shd_no_ticket'); |
|
60 |
+ } |
|
61 |
+ |
|
62 |
+ // OK, so we can merge this ticket with something else. Let's get the other tickets that we can possibly merge this with. |
|
63 |
+ $query = shd_db_query('', ' |
|
64 |
+ SELECT id_ticket, subject |
|
65 |
+ FROM {db_prefix}helpdesk_tickets |
|
66 |
+ WHERE {query_see_ticket} |
|
67 |
+ AND id_ticket != {int:ticket}', |
|
68 |
+ array( |
|
69 |
+ 'ticket' => $context['ticket_id'], |
|
70 |
+ ) |
|
71 |
+ ); |
|
72 |
+ |
|
73 |
+ // Are there any tickets? If not, die. |
|
74 |
+ if ($smcFunc['db_num_rows']($query) == 0) |
|
75 |
+ { |
|
76 |
+ $smcFunc['db_free_result']($query); |
|
77 |
+ fatal_lang_error('shd_no_tickets_to_merge', false); |
|
78 |
+ } |
|
79 |
+ else |
|
80 |
+ { |
|
81 |
+ // She might have, but I KNOW I got a ticket to merge... but she don't care :P |
|
82 |
+ $context['tickets_to_merge'] = array(); |
|
83 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
84 |
+ $context['tickets_to_merge'][] = $row; |
|
85 |
+ } |
|
86 |
+ |
|
87 |
+ // OK, we've done all the easy bits, now just the boring bits like setting up the template. |
|
88 |
+ $context['linktree'][] = array( |
|
89 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
90 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
91 |
+ ); |
|
92 |
+ $context['linktree'][] = array( |
|
93 |
+ 'url' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'], |
|
94 |
+ 'name' => $context['current_ticket']['subject'], |
|
95 |
+ ); |
|
96 |
+ $context['linktree'][] = array( |
|
97 |
+ 'name' => $txt['shd_ticket_merge_tickets'], |
|
98 |
+ ); |
|
99 |
+ |
|
100 |
+ $context['page_title'] = $txt['shd_ticket_merge_tickets']; |
|
101 |
+ |
|
102 |
+ loadTemplate('sd_template/SimpleDesk-MergeSplit'); |
|
103 |
+ $context['sub_template'] = 'shd_merge_ticket'; |
|
104 |
+ |
|
105 |
+ checkSubmitOnce('register'); |
|
106 |
+} |
|
107 |
+ |
|
108 |
+function shd_merge_ticket2() |
|
109 |
+{ |
|
110 |
+ |
|
111 |
+} |
|
112 |
+ |
|
113 |
+function shd_split_ticket() |
|
114 |
+{ |
|
115 |
+ global $smcFunc, $context, $user_info, $sourcedir, $txt, $scripturl; |
|
116 |
+ |
|
117 |
+ // Load the ticket from $context['ticket_id'] and die if not found |
|
118 |
+ $ticketinfo = shd_load_ticket(); |
|
119 |
+ |
|
120 |
+ $_REQUEST['at_msg'] = isset($_REQUEST['at_msg']) ? (int) $_REQUEST['at_msg'] : 0; |
|
121 |
+ |
|
122 |
+ // So, are you in or out? For us to be able to split, we know we can see the ticket, but the split point must be not the first msg and not deleted |
|
123 |
+ $query = shd_db_query('', ' |
|
124 |
+ SELECT id_msg |
|
125 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
126 |
+ WHERE id_ticket = {int:ticket} |
|
127 |
+ AND id_msg = {int:msg} |
|
128 |
+ AND id_msg > {int:firstmsg} |
|
129 |
+ AND message_status = {int:message_status}', |
|
130 |
+ array( |
|
131 |
+ 'ticket' => $context['ticket_id'], |
|
132 |
+ 'msg' => $_REQUEST['at_msg'], |
|
133 |
+ 'firstmsg' => $ticketinfo['id_first_msg'], |
|
134 |
+ 'message_status' => MSG_STATUS_NORMAL, |
|
135 |
+ ) |
|
136 |
+ ); |
|
137 |
+ |
|
138 |
+ $found = $smcFunc['db_num_rows']($query) > 0; |
|
139 |
+ $smcFunc['db_free_result']($query); |
|
140 |
+ if (!$found) |
|
141 |
+ fatal_lang_error('shd_no_reply', false); |
|
142 |
+ |
|
143 |
+ // Permission checking time |
|
144 |
+ if ($ticketinfo['id_member_started'] == $user_info['id']) |
|
145 |
+ shd_is_allowed_to('shd_split_ticket_own'); |
|
146 |
+ else |
|
147 |
+ shd_is_allowed_to('shd_split_ticket_any'); |
|
148 |
+ |
|
149 |
+ if (in_array($ticketinfo['status'], array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED))) |
|
150 |
+ fatal_lang_error('shd_ticket_unavailable', false); |
|
151 |
+ |
|
152 |
+ // So, we know we can split at this point. Let's prep the items we need for the form: ticket id (check), msg id (check), current ticket title... |
|
153 |
+ $context['ticket_title'] = $ticketinfo['subject']; |
|
154 |
+ |
|
155 |
+ $context['linktree'][] = array( |
|
156 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
157 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
158 |
+ ); |
|
159 |
+ $context['linktree'][] = array( |
|
160 |
+ 'url' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'], |
|
161 |
+ 'name' => $ticketinfo['subject'], |
|
162 |
+ ); |
|
163 |
+ $context['linktree'][] = array( |
|
164 |
+ 'name' => $txt['shd_ticket_split_ticket'], |
|
165 |
+ ); |
|
166 |
+ |
|
167 |
+ $context['page_title'] = $txt['shd_split_ticket']; |
|
168 |
+ |
|
169 |
+ loadTemplate('sd_template/SimpleDesk-MergeSplit'); |
|
170 |
+ $context['sub_template'] = 'shd_split_ticket'; |
|
171 |
+} |
|
172 |
+ |
|
173 |
+function shd_split_ticket2() |
|
174 |
+{ |
|
175 |
+ global $smcFunc, $context, $user_info, $sourcedir, $txt, $scripturl; |
|
176 |
+ |
|
177 |
+ checkSession(); |
|
178 |
+ |
|
179 |
+ // Load the ticket from $context['ticket_id'] and die if not found |
|
180 |
+ $ticketinfo = shd_load_ticket(); |
|
181 |
+ |
|
182 |
+ $_REQUEST['at_msg'] = isset($_REQUEST['at_msg']) ? (int) $_REQUEST['at_msg'] : 0; |
|
183 |
+ |
|
184 |
+ // So, are you in or out? For us to be able to split, we know we can see the ticket, but the split point must be not the first msg and not deleted |
|
185 |
+ $query = shd_db_query('', ' |
|
186 |
+ SELECT id_msg, id_member |
|
187 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
188 |
+ WHERE id_ticket = {int:ticket} |
|
189 |
+ AND id_msg = {int:msg} |
|
190 |
+ AND id_msg > {int:firstmsg} |
|
191 |
+ AND message_status = {int:message_status}', |
|
192 |
+ array( |
|
193 |
+ 'ticket' => $context['ticket_id'], |
|
194 |
+ 'msg' => $_REQUEST['at_msg'], |
|
195 |
+ 'firstmsg' => $ticketinfo['id_first_msg'], |
|
196 |
+ 'message_status' => MSG_STATUS_NORMAL, |
|
197 |
+ ) |
|
198 |
+ ); |
|
199 |
+ |
|
200 |
+ $found = $smcFunc['db_num_rows']($query) > 0; |
|
201 |
+ |
|
202 |
+ if (!$found) |
|
203 |
+ { |
|
204 |
+ $smcFunc['db_free_result']($query); |
|
205 |
+ fatal_lang_error('shd_no_reply', false); |
|
206 |
+ } |
|
207 |
+ else |
|
208 |
+ { |
|
209 |
+ $msginfo = $smcFunc['db_fetch_assoc']($query); |
|
210 |
+ $smcFunc['db_free_result']($query); |
|
211 |
+ } |
|
212 |
+ |
|
213 |
+ // Permission checking time |
|
214 |
+ if ($ticketinfo['id_member_started'] == $user_info['id']) |
|
215 |
+ shd_is_allowed_to('shd_split_ticket_own'); |
|
216 |
+ else |
|
217 |
+ shd_is_allowed_to('shd_split_ticket_any'); |
|
218 |
+ |
|
219 |
+ if (in_array($ticketinfo['status'], array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED))) |
|
220 |
+ fatal_lang_error('shd_ticket_unavailable', false); |
|
221 |
+ |
|
222 |
+ // Lastly, check they actually specified both a subject and a suitably splitting option |
|
223 |
+ if (!isset($_POST['new_subject']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['new_subject'])) === '') |
|
224 |
+ fatal_lang_error('shd_split_no_title', false); |
|
225 |
+ else |
|
226 |
+ $_POST['new_subject'] = strtr($smcFunc['htmlspecialchars']($_POST['new_subject']), array("\r" => '', "\n" => '', "\t" => '')); |
|
227 |
+ |
|
228 |
+ if (isset($_POST['send_pm']) && (!isset($_POST['pm_content']) || trim($_POST['pm_content']) == '')) |
|
229 |
+ fatal_lang_error('shd_split_no_pm', false); |
|
230 |
+ |
|
231 |
+ if (empty($_REQUEST['split_type'])) |
|
232 |
+ $_REQUEST['split_type'] = ''; |
|
233 |
+ |
|
234 |
+ if (!in_array($_REQUEST['split_type'], array('onlythis', 'afterthis'))) |
|
235 |
+ fatal_lang_error('shd_split_invalid_type', false); |
|
236 |
+ |
|
237 |
+ // Right, if we're here, we're all good to go (the ticket is valid, the post is not deleted and in ticket, we know what we're doing, so let's go do!) |
|
238 |
+ $msgs_affected = array(); |
|
239 |
+ if ($_REQUEST['split_type'] == 'onlythis') |
|
240 |
+ $msg_affected[] = $_REQUEST['at_msg']; |
|
241 |
+ else |
|
242 |
+ { |
|
243 |
+ $query = shd_db_query('', ' |
|
244 |
+ SELECT id_msg |
|
245 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
246 |
+ WHERE id_ticket = {int:ticket} |
|
247 |
+ AND id_msg >= {int:msg}', |
|
248 |
+ array( |
|
249 |
+ 'ticket' => $context['ticket_id'], |
|
250 |
+ 'msg' => $_REQUEST['at_msg'], |
|
251 |
+ ) |
|
252 |
+ ); |
|
253 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
254 |
+ $msg_affected[] = $row[0]; |
|
255 |
+ } |
|
256 |
+ |
|
257 |
+ // 1. Create the new container ticket |
|
258 |
+ $smcFunc['db_insert']('insert', |
|
259 |
+ '{db_prefix}helpdesk_tickets', |
|
260 |
+ array( |
|
261 |
+ 'id_first_msg' => 'int', 'id_member_started' => 'int', 'subject' => 'string', 'urgency' => 'int', 'private' => 'int', |
|
262 |
+ ), |
|
263 |
+ array( |
|
264 |
+ $_REQUEST['at_msg'], $msginfo['id_member'], $_POST['new_subject'], $ticketinfo['urgency'], $ticketinfo['private'], |
|
265 |
+ ), |
|
266 |
+ array('id_ticket') |
|
267 |
+ ); |
|
268 |
+ |
|
269 |
+ $new_ticket = $smcFunc['db_insert_id']('{db_prefix}helpdesk_tickets', 'id_ticket'); |
|
270 |
+ |
|
271 |
+ // 2. Move the message(s) to the new ticket |
|
272 |
+ shd_db_query('', ' |
|
273 |
+ UPDATE {db_prefix}helpdesk_ticket_replies |
|
274 |
+ SET id_ticket = {int:new_ticket} |
|
275 |
+ WHERE id_ticket = {int:old_ticket} |
|
276 |
+ AND id_msg IN ({array_int:msgs})', |
|
277 |
+ array( |
|
278 |
+ 'new_ticket' => $new_ticket, |
|
279 |
+ 'old_ticket' => $context['ticket_id'], |
|
280 |
+ 'msgs' => $msg_affected, |
|
281 |
+ ) |
|
282 |
+ ); |
|
283 |
+ |
|
284 |
+ // 3. Move their attachments too |
|
285 |
+ shd_db_query('', ' |
|
286 |
+ UPDATE {db_prefix}helpdesk_attachments |
|
287 |
+ SET id_ticket = {int:new_ticket} |
|
288 |
+ WHERE id_ticket = {int:old_ticket} |
|
289 |
+ AND id_msg IN ({array_int:msgs})', |
|
290 |
+ array( |
|
291 |
+ 'new_ticket' => $new_ticket, |
|
292 |
+ 'old_ticket' => $context['ticket_id'], |
|
293 |
+ 'msgs' => $msg_affected, |
|
294 |
+ ) |
|
295 |
+ ); |
|
296 |
+ |
|
297 |
+ // 4. Clean up ids etc |
|
298 |
+ // 4.1 Origin ticket |
|
299 |
+ list($starter, $replier, $num_replies) = shd_recalc_ids($context['ticket_id']); |
|
300 |
+ $query_reply = shd_db_query('', ' |
|
301 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
302 |
+ SET status = {int:status} |
|
303 |
+ WHERE id_ticket = {int:ticket}', |
|
304 |
+ array( |
|
305 |
+ 'ticket' => $context['ticket_id'], |
|
306 |
+ 'status' => shd_determine_status('mergesplit', $starter, $replier, $num_replies), |
|
307 |
+ ) |
|
308 |
+ ); |
|
309 |
+ $owner = $starter; |
|
310 |
+ |
|
311 |
+ // 4.2 New ticket |
|
312 |
+ list($starter, $replier, $num_replies) = shd_recalc_ids($new_ticket); |
|
313 |
+ $query_reply = shd_db_query('', ' |
|
314 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
315 |
+ SET status = {int:status} |
|
316 |
+ WHERE id_ticket = {int:ticket}', |
|
317 |
+ array( |
|
318 |
+ 'ticket' => $new_ticket, |
|
319 |
+ 'status' => shd_determine_status('mergesplit', $starter, $replier, $num_replies), |
|
320 |
+ ) |
|
321 |
+ ); |
|
322 |
+ |
|
323 |
+ // 5. Log the action |
|
324 |
+ shd_log_action('split_origin', |
|
325 |
+ array( |
|
326 |
+ 'ticket' => $context['ticket_id'], |
|
327 |
+ 'subject' => $ticketinfo['subject'], |
|
328 |
+ 'otherticket' => $new_ticket, |
|
329 |
+ 'othersubject' => $_POST['new_subject'], |
|
330 |
+ ) |
|
331 |
+ ); |
|
332 |
+ shd_log_action('split_new', |
|
333 |
+ array( |
|
334 |
+ 'ticket' => $new_ticket, |
|
335 |
+ 'subject' => $_POST['new_subject'], |
|
336 |
+ 'otherticket' => $context['ticket_id'], |
|
337 |
+ 'othersubject' => $ticketinfo['subject'], |
|
338 |
+ ) |
|
339 |
+ ); |
|
340 |
+ |
|
341 |
+ // 6. Empty the cache |
|
342 |
+ shd_clear_active_tickets(); |
|
343 |
+ |
|
344 |
+ // 7. Spam the ticket starter |
|
345 |
+ if (isset($_POST['send_pm'])) |
|
346 |
+ { |
|
347 |
+ require($sourcedir . '/Subs-Post.php'); |
|
348 |
+ $request = shd_db_query('pm_find_username', ' |
|
349 |
+ SELECT id_member, real_name |
|
350 |
+ FROM {db_prefix}members |
|
351 |
+ WHERE id_member = {int:user} |
|
352 |
+ LIMIT 1', |
|
353 |
+ array( |
|
354 |
+ 'user' => $owner, |
|
355 |
+ ) |
|
356 |
+ ); |
|
357 |
+ list ($userid,$username) = $smcFunc['db_fetch_row']($request); |
|
358 |
+ $smcFunc['db_free_result']($request); |
|
359 |
+ |
|
360 |
+ // Fix the content |
|
361 |
+ $replacements = array( |
|
362 |
+ '{user}' => $username, |
|
363 |
+ '{source}' => $ticketinfo['subject'], |
|
364 |
+ '{link}' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'], |
|
365 |
+ '{splitlink}' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $new_ticket, |
|
366 |
+ ); |
|
367 |
+ $message = str_replace(array_keys($replacements), array_values($replacements), $_POST['pm_content']); |
|
368 |
+ |
|
369 |
+ $recipients = array( |
|
370 |
+ 'to' => array($owner), |
|
371 |
+ 'bcc' => array() |
|
372 |
+ ); |
|
373 |
+ |
|
374 |
+ sendpm($recipients, $txt['shd_ticket_split_subject'], un_htmlspecialchars($message)); |
|
375 |
+ } |
|
376 |
+ |
|
377 |
+ // 8. Stick a fork in me, I'm done. User, you should go. Go soon. Go NAO. |
|
378 |
+ $context['linktree'][] = array( |
|
379 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
380 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
381 |
+ ); |
|
382 |
+ $context['linktree'][] = array( |
|
383 |
+ 'name' => $txt['shd_ticket_split_ticket'], |
|
384 |
+ ); |
|
385 |
+ |
|
386 |
+ $context['page_title'] = $txt['shd_split_ticket']; |
|
387 |
+ |
|
388 |
+ loadTemplate('sd_template/SimpleDesk-MergeSplit'); |
|
389 |
+ $context['sub_template'] = 'shd_split_ticket2'; |
|
390 |
+ |
|
391 |
+ $context['split_info'] = array( |
|
392 |
+ 'ticket' => $context['ticket_id'], |
|
393 |
+ 'subject' => $ticketinfo['subject'], |
|
394 |
+ 'otherticket' => $new_ticket, |
|
395 |
+ 'othersubject' => $_POST['new_subject'], |
|
396 |
+ ); |
|
397 |
+} |
|
398 |
+ |
|
399 |
+?> |
|
0 | 400 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,428 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-MiscActions.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles miscellaneous actions that aren't really tied to anything, that are mostly |
|
22 |
+ * self-contained and aren't big enough to warrant their own file. |
|
23 |
+ * |
|
24 |
+ * @package source |
|
25 |
+ * @since 1.0 |
|
26 |
+ */ |
|
27 |
+ |
|
28 |
+if (!defined('SMF')) |
|
29 |
+ die('Hacking attempt...'); |
|
30 |
+ |
|
31 |
+/** |
|
32 |
+ * Marks a ticket unread. |
|
33 |
+ * |
|
34 |
+ * There are no permission checks made; other than that the user is who they claim to be. If a ticket is marked unread |
|
35 |
+ * but they can't see it anyway, the consequence is that the database gets lighter. |
|
36 |
+ * |
|
37 |
+ * Invoked through ?action=helpdesk;sa=unreadticket;ticket=x;sessvar=sessid before redirecting back to the main helpdesk page. |
|
38 |
+ * |
|
39 |
+ * @since 1.0 |
|
40 |
+*/ |
|
41 |
+function shd_ticket_unread() |
|
42 |
+{ |
|
43 |
+ global $smcFunc, $user_info, $context; |
|
44 |
+ |
|
45 |
+ is_not_guest(); |
|
46 |
+ checkSession('get'); |
|
47 |
+ |
|
48 |
+ if (!empty($context['ticket_id'])) |
|
49 |
+ $result = shd_db_query('', ' |
|
50 |
+ DELETE FROM {db_prefix}helpdesk_log_read |
|
51 |
+ WHERE id_ticket = {int:current_ticket} |
|
52 |
+ AND id_member = {int:user}', |
|
53 |
+ array( |
|
54 |
+ 'current_ticket' => $context['ticket_id'], |
|
55 |
+ 'user' => $user_info['id'], |
|
56 |
+ ) |
|
57 |
+ ); |
|
58 |
+ |
|
59 |
+ redirectexit('action=helpdesk;sa=main'); |
|
60 |
+} |
|
61 |
+ |
|
62 |
+/** |
|
63 |
+ * Marks a ticket resolved or unresolved. |
|
64 |
+ * |
|
65 |
+ * This function identifies whether a given ticket is resolved or not, if not resolved, mark it resolved. If it was resolved |
|
66 |
+ * reopen the ticket back to an appropriate status based on last respondent. In both cases, the action is logged in the action log. |
|
67 |
+ * It is also unassigned from having a user on either closure or reopen. |
|
68 |
+ * |
|
69 |
+ * Accessed through ?action=helpdesk;sa=resolve;ticket=x;sessvar=sessid before redirecting back to the ticket, or add ;home to the |
|
70 |
+ * URL to have it redirect back to the home page. |
|
71 |
+ * |
|
72 |
+ * @since 1.0 |
|
73 |
+*/ |
|
74 |
+function shd_ticket_resolve() |
|
75 |
+{ |
|
76 |
+ global $smcFunc, $user_info, $context, $sourcedir; |
|
77 |
+ |
|
78 |
+ checkSession('get'); |
|
79 |
+ |
|
80 |
+ // First, figure out the state of the ticket - is it resolved or not? Can we even see it? |
|
81 |
+ if (empty($context['ticket_id'])) |
|
82 |
+ fatal_lang_error('shd_no_ticket', false); |
|
83 |
+ |
|
84 |
+ $context['shd_return_to'] = isset($_REQUEST['home']) ? 'home' : 'ticket'; |
|
85 |
+ |
|
86 |
+ $query = shd_db_query('', ' |
|
87 |
+ SELECT id_member_started, id_member_updated, status, num_replies, subject |
|
88 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
89 |
+ WHERE {query_see_ticket} |
|
90 |
+ AND id_ticket = {int:current_ticket}', |
|
91 |
+ array( |
|
92 |
+ 'current_ticket' => $context['ticket_id'], |
|
93 |
+ ) |
|
94 |
+ ); |
|
95 |
+ |
|
96 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
97 |
+ { |
|
98 |
+ $smcFunc['db_free_result']($query); |
|
99 |
+ |
|
100 |
+ if (!shd_allowed_to('shd_resolve_ticket_any') && (!shd_allowed_to('shd_resolve_ticket_own') || $row['id_member_started'] != $user_info['id'])) |
|
101 |
+ fatal_lang_error('shd_cannot_resolve', false); |
|
102 |
+ |
|
103 |
+ // OK, so what about any children related tickets that are still open? Eeek, could be awkward. |
|
104 |
+ $query = shd_db_query('', ' |
|
105 |
+ SELECT COUNT(hdt.id_ticket) |
|
106 |
+ FROM {db_prefix}helpdesk_relationships AS rel |
|
107 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (rel.secondary_ticket = hdt.id_ticket) |
|
108 |
+ WHERE rel.primary_ticket = {int:ticket} |
|
109 |
+ AND rel.rel_type = {int:parent} |
|
110 |
+ AND hdt.status NOT IN ({array_int:closed_status})', |
|
111 |
+ array( |
|
112 |
+ 'ticket' => $context['ticket_id'], |
|
113 |
+ 'parent' => RELATIONSHIP_ISPARENT, |
|
114 |
+ 'closed_status' => array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED), |
|
115 |
+ ) |
|
116 |
+ ); |
|
117 |
+ list($count_children) = $smcFunc['db_fetch_row']($query); |
|
118 |
+ $smcFunc['db_free_result']($query); |
|
119 |
+ if (!empty($count_children)) |
|
120 |
+ fatal_lang_error('error_shd_cannot_resolve_children', false); |
|
121 |
+ |
|
122 |
+ $action = ($row['status'] != TICKET_STATUS_CLOSED) ? 'resolve' : 'unresolve'; |
|
123 |
+ $new = shd_determine_status($action, $row['id_member_started'], $row['id_member_updated'], $row['num_replies']); |
|
124 |
+ |
|
125 |
+ shd_db_query('', ' |
|
126 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
127 |
+ SET status = {int:status}, |
|
128 |
+ id_member_assigned = {int:unassigned} |
|
129 |
+ WHERE id_ticket = {int:ticket}', |
|
130 |
+ array( |
|
131 |
+ 'status' => $new, |
|
132 |
+ 'unassigned' => 0, |
|
133 |
+ 'ticket' => $context['ticket_id'], |
|
134 |
+ ) |
|
135 |
+ ); |
|
136 |
+ |
|
137 |
+ shd_log_action($action, |
|
138 |
+ array( |
|
139 |
+ 'ticket' => $context['ticket_id'], |
|
140 |
+ 'subject' => $row['subject'], |
|
141 |
+ ) |
|
142 |
+ ); |
|
143 |
+ |
|
144 |
+ // Make sure we recalculate the number of tickets on next page load (here it will affect visibility) |
|
145 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
146 |
+ |
|
147 |
+ if ($context['shd_return_to'] == 'home') |
|
148 |
+ redirectexit('action=helpdesk;sa=main'); |
|
149 |
+ else |
|
150 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
151 |
+ } |
|
152 |
+ else |
|
153 |
+ fatal_lang_error('shd_no_ticket', false); |
|
154 |
+} |
|
155 |
+ |
|
156 |
+/** |
|
157 |
+ * Marks a ticket private/not private if the user isn't using Javascript. |
|
158 |
+ * |
|
159 |
+ * Assuming the user can see the ticket and has suitable permissions, the privacy flag will be inverted for the ticket and |
|
160 |
+ * updated, as well as updating the action log. If they cannot see the ticket, or do not have privacy-change permission, a fatal |
|
161 |
+ * error will be generated. |
|
162 |
+ * |
|
163 |
+ * Accessed through ?action=helpdesk;sa=privacychange;ticket=x;sessvar=sessid before directing back to the ticket page. |
|
164 |
+ * |
|
165 |
+ * @since 1.0 |
|
166 |
+*/ |
|
167 |
+function shd_privacy_change_noajax() |
|
168 |
+{ |
|
169 |
+ global $smcFunc, $user_info, $context, $sourcedir; |
|
170 |
+ |
|
171 |
+ checkSession('get'); |
|
172 |
+ |
|
173 |
+ // First, figure out the state of the ticket - is it private or not? Can we even see it? |
|
174 |
+ if (empty($context['ticket_id'])) |
|
175 |
+ fatal_lang_error('shd_no_ticket', false); |
|
176 |
+ |
|
177 |
+ $query = shd_db_query('', ' |
|
178 |
+ SELECT id_member_started, subject, private, status |
|
179 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
180 |
+ WHERE {query_see_ticket} |
|
181 |
+ AND id_ticket = {int:current_ticket}', |
|
182 |
+ array( |
|
183 |
+ 'current_ticket' => $context['ticket_id'], |
|
184 |
+ ) |
|
185 |
+ ); |
|
186 |
+ |
|
187 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
188 |
+ { |
|
189 |
+ if (in_array($row['status'], array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED)) || !shd_allowed_to('shd_alter_privacy_any') && (!shd_allowed_to('shd_alter_privacy_own') || $row['id_member_started'] != $user_info['id'])) |
|
190 |
+ fatal_lang_error('shd_cannot_change_privacy', false); |
|
191 |
+ |
|
192 |
+ $smcFunc['db_free_result']($query); |
|
193 |
+ |
|
194 |
+ $new = empty($row['private']) ? 1 : 0; |
|
195 |
+ $action = empty($row['private']) ? 'markprivate' : 'marknotprivate'; |
|
196 |
+ |
|
197 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
198 |
+ $msgOptions = array(); |
|
199 |
+ $posterOptions = array(); |
|
200 |
+ $ticketOptions = array( |
|
201 |
+ 'id' => $context['ticket_id'], |
|
202 |
+ 'private' => empty($row['private']), |
|
203 |
+ ); |
|
204 |
+ |
|
205 |
+ shd_modify_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
206 |
+ |
|
207 |
+ shd_log_action($action, |
|
208 |
+ array( |
|
209 |
+ 'ticket' => $context['ticket_id'], |
|
210 |
+ 'subject' => $row['subject'], |
|
211 |
+ ) |
|
212 |
+ ); |
|
213 |
+ |
|
214 |
+ // Make sure we recalculate the number of tickets on next page load (here it may affect ticket visibility so we do it) |
|
215 |
+ shd_clear_active_tickets($row['id_member_started']); |
|
216 |
+ |
|
217 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
218 |
+ } |
|
219 |
+ else |
|
220 |
+ fatal_lang_error('shd_no_ticket', false); |
|
221 |
+} |
|
222 |
+ |
|
223 |
+/** |
|
224 |
+ * Updates a ticket's urgency up or down one level, if the user isn't using Javascript |
|
225 |
+ * |
|
226 |
+ * Assuming the user can see the ticket and has suitable permissions, the urgency of the ticket will be updated and an |
|
227 |
+ * action log entry added. If they cannot see the ticket, or do not have urgency-change permission (including higher |
|
228 |
+ * urgency permission if necessary), a fatal error will be generated. |
|
229 |
+ * |
|
230 |
+ * Accessed through ?action=helpdesk;sa=urgencychange;ticket=x;change=(increase|decrease);sessvar=sessid before directing back to the main helpdesk page. |
|
231 |
+ * |
|
232 |
+ * @see shd_can_alter_urgency() |
|
233 |
+ * |
|
234 |
+ * @since 1.0 |
|
235 |
+*/ |
|
236 |
+function shd_urgency_change_noajax() |
|
237 |
+{ |
|
238 |
+ global $smcFunc, $user_info, $context, $sourcedir; |
|
239 |
+ |
|
240 |
+ checkSession('get'); |
|
241 |
+ |
|
242 |
+ // First, figure out the state of the ticket - is it private or not? Can we even see it? Current urgency? |
|
243 |
+ if (empty($context['ticket_id'])) |
|
244 |
+ fatal_lang_error('shd_no_ticket', false); |
|
245 |
+ |
|
246 |
+ $query = shd_db_query('', ' |
|
247 |
+ SELECT id_member_started, subject, urgency, status |
|
248 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
249 |
+ WHERE {query_see_ticket} |
|
250 |
+ AND id_ticket = {int:current_ticket}', |
|
251 |
+ array( |
|
252 |
+ 'current_ticket' => $context['ticket_id'], |
|
253 |
+ ) |
|
254 |
+ ); |
|
255 |
+ |
|
256 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
257 |
+ { |
|
258 |
+ $can_urgency = shd_can_alter_urgency($row['urgency'], $row['id_member_started'], ($row['status'] == TICKET_STATUS_CLOSED), ($row['status'] == TICKET_STATUS_DELETED)); |
|
259 |
+ |
|
260 |
+ if (empty($_GET['change']) || empty($can_urgency[$_GET['change']])) |
|
261 |
+ fatal_lang_error('shd_cannot_change_urgency'); |
|
262 |
+ |
|
263 |
+ $new_urgency = $row['urgency'] + ($_GET['change'] == 'increase' ? 1 : -1); |
|
264 |
+ $action = 'urgency_' . $_GET['change']; |
|
265 |
+ |
|
266 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
267 |
+ $msgOptions = array(); |
|
268 |
+ $posterOptions = array(); |
|
269 |
+ $ticketOptions = array( |
|
270 |
+ 'id' => $context['ticket_id'], |
|
271 |
+ 'private' => empty($row['private']), |
|
272 |
+ ); |
|
273 |
+ |
|
274 |
+ shd_modify_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
275 |
+ |
|
276 |
+ shd_log_action($action, |
|
277 |
+ array( |
|
278 |
+ 'ticket' => $context['ticket_id'], |
|
279 |
+ 'subject' => $row['subject'], |
|
280 |
+ 'urgency' => $new_urgency, |
|
281 |
+ ) |
|
282 |
+ ); |
|
283 |
+ |
|
284 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
285 |
+ } |
|
286 |
+ else |
|
287 |
+ fatal_lang_error('shd_no_ticket', false); |
|
288 |
+} |
|
289 |
+ |
|
290 |
+/** |
|
291 |
+ * Updates a ticket's relationships. |
|
292 |
+ * |
|
293 |
+ * This function is responsible for adding, updating and removing relationships. |
|
294 |
+ * |
|
295 |
+ * Accessed through ?action=helpdesk;sa=relation;ticket=x;linkticket=y;relation=[linked|duplicated|parent|child|delete];sessvar=sessid and will redirect back to the ticket once complete. |
|
296 |
+ * |
|
297 |
+ * @since 1.1 |
|
298 |
+*/ |
|
299 |
+function shd_ticket_relation() |
|
300 |
+{ |
|
301 |
+ global $context, $smcFunc; |
|
302 |
+ |
|
303 |
+ checkSession('request'); |
|
304 |
+ |
|
305 |
+ $otherticket = isset($_REQUEST['otherticket']) ? (int) $_REQUEST['otherticket'] : 0; |
|
306 |
+ |
|
307 |
+ if (empty($context['ticket_id']) || empty($otherticket)) |
|
308 |
+ fatal_lang_error('shd_no_ticket', false); |
|
309 |
+ |
|
310 |
+ if ($context['ticket_id'] == $otherticket) |
|
311 |
+ fatal_lang_error('shd_cannot_relate_self', false); |
|
312 |
+ |
|
313 |
+ $actions = array( |
|
314 |
+ 'linked', |
|
315 |
+ 'duplicated', |
|
316 |
+ 'parent', |
|
317 |
+ 'child', |
|
318 |
+ 'delete', |
|
319 |
+ ); |
|
320 |
+ |
|
321 |
+ $rel_action = isset($_REQUEST['relation']) && in_array($_REQUEST['relation'], $actions) ? $_REQUEST['relation'] : ''; |
|
322 |
+ if (empty($rel_action)) |
|
323 |
+ fatal_lang_error('shd_invalid_relation', false); |
|
324 |
+ |
|
325 |
+ if ($rel_action == 'delete') |
|
326 |
+ shd_is_allowed_to('shd_delete_relationships'); |
|
327 |
+ else |
|
328 |
+ shd_is_allowed_to('shd_create_relationships'); |
|
329 |
+ |
|
330 |
+ // Quick/consistent way to ensure permissions are adhered to and that the ticket exists. Might as well get the subject while here too. |
|
331 |
+ $ticketinfo = shd_load_ticket($context['ticket_id']); |
|
332 |
+ $primary_subject = $ticketinfo['subject']; |
|
333 |
+ $ticketinfo = shd_load_ticket($otherticket); |
|
334 |
+ $secondary_subject = $ticketinfo['subject']; |
|
335 |
+ |
|
336 |
+ // See if there's an existing relationship with these parameters |
|
337 |
+ $query = shd_db_query('', ' |
|
338 |
+ SELECT rel_type |
|
339 |
+ FROM {db_prefix}helpdesk_relationships |
|
340 |
+ WHERE primary_ticket = {int:ticket} |
|
341 |
+ AND secondary_ticket = {int:otherticket}', |
|
342 |
+ array( |
|
343 |
+ 'ticket' => $context['ticket_id'], |
|
344 |
+ 'otherticket' => $otherticket, |
|
345 |
+ ) |
|
346 |
+ ); |
|
347 |
+ |
|
348 |
+ $new_relationship = ($smcFunc['db_num_rows']($query) == 0); |
|
349 |
+ list($existing_relation) = $new_relationship ? array(-1) : $smcFunc['db_fetch_row']($query); |
|
350 |
+ |
|
351 |
+ $smcFunc['db_free_result']($query); |
|
352 |
+ |
|
353 |
+ if ($rel_action == 'delete' && $new_relationship) |
|
354 |
+ fatal_lang_error('shd_no_relation_delete', false); |
|
355 |
+ |
|
356 |
+ $log_prefix = 'rel_' . ($new_relationship || $rel_action == 'delete' ? '' : 're_'); |
|
357 |
+ $log_map = array( |
|
358 |
+ 'delete' => 'delete', |
|
359 |
+ 'linked' => 'linked', |
|
360 |
+ 'duplicated' => 'duplicated', |
|
361 |
+ 'parent' => 'child', |
|
362 |
+ 'child' => 'parent', |
|
363 |
+ ); |
|
364 |
+ |
|
365 |
+ $log_assoc_ids = array( |
|
366 |
+ 'delete' => -1, // any value not below, really |
|
367 |
+ 'linked' => RELATIONSHIP_LINKED, |
|
368 |
+ 'duplicated' => RELATIONSHIP_DUPLICATED, |
|
369 |
+ 'parent' => RELATIONSHIP_ISPARENT, |
|
370 |
+ 'child' => RELATIONSHIP_ISCHILD, |
|
371 |
+ ); |
|
372 |
+ |
|
373 |
+ $logaction_ticket = $log_prefix . $rel_action; |
|
374 |
+ $logaction_otherticket = $log_prefix . $log_map[$rel_action]; |
|
375 |
+ |
|
376 |
+ if ($rel_action == 'delete') |
|
377 |
+ { |
|
378 |
+ // Delete the link |
|
379 |
+ shd_db_query('', ' |
|
380 |
+ DELETE FROM {db_prefix}helpdesk_relationships |
|
381 |
+ WHERE (primary_ticket = {int:ticket} AND secondary_ticket = {int:otherticket}) |
|
382 |
+ OR (primary_ticket = {int:otherticket} AND secondary_ticket = {int:ticket})', |
|
383 |
+ array( |
|
384 |
+ 'ticket' => $context['ticket_id'], |
|
385 |
+ 'otherticket' => $otherticket, |
|
386 |
+ ) |
|
387 |
+ ); |
|
388 |
+ } |
|
389 |
+ else |
|
390 |
+ { |
|
391 |
+ $smcFunc['db_insert']('replace', |
|
392 |
+ '{db_prefix}helpdesk_relationships', |
|
393 |
+ array( |
|
394 |
+ 'primary_ticket' => 'int', 'secondary_ticket' => 'int', 'rel_type' => 'int', |
|
395 |
+ ), |
|
396 |
+ array( |
|
397 |
+ array($context['ticket_id'], $otherticket, $log_assoc_ids[$rel_action]), |
|
398 |
+ array($otherticket, $context['ticket_id'], $log_assoc_ids[$log_map[$rel_action]]), |
|
399 |
+ ), |
|
400 |
+ array('primary_ticket', 'secondary_ticket') |
|
401 |
+ ); |
|
402 |
+ } |
|
403 |
+ |
|
404 |
+ // Now actually log it, main ticket first -- if it's different to the one we had before |
|
405 |
+ if ($log_assoc_ids[$rel_action] != $existing_relation) |
|
406 |
+ { |
|
407 |
+ $params = array( |
|
408 |
+ 'ticket' => $context['ticket_id'], |
|
409 |
+ 'otherticket' => $otherticket, |
|
410 |
+ 'subject' => $primary_subject, |
|
411 |
+ 'othersubject' => $secondary_subject, |
|
412 |
+ ); |
|
413 |
+ shd_log_action($logaction_ticket, $params); |
|
414 |
+ |
|
415 |
+ $params = array( |
|
416 |
+ 'ticket' => $otherticket, |
|
417 |
+ 'otherticket' => $context['ticket_id'], |
|
418 |
+ 'subject' => $secondary_subject, |
|
419 |
+ 'othersubject' => $primary_subject, |
|
420 |
+ ); |
|
421 |
+ shd_log_action($logaction_otherticket, $params); |
|
422 |
+ } |
|
423 |
+ |
|
424 |
+ // See yah |
|
425 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
426 |
+} |
|
427 |
+ |
|
428 |
+?> |
|
0 | 429 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,1904 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Post.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file is one of the cornerstones of SimpleDesk; it handles displaying the post form to users, both for tickets and replies, |
|
22 |
+ * handles editing of tickets/replies, attachments to tickets/replies and actually saving all that into the database. |
|
23 |
+ * |
|
24 |
+ * @package source |
|
25 |
+ * @todo Finish documenting this file. |
|
26 |
+ * @since 1.0 |
|
27 |
+*/ |
|
28 |
+ |
|
29 |
+if (!defined('SMF')) |
|
30 |
+ die('Hacking attempt...'); |
|
31 |
+ |
|
32 |
+/** |
|
33 |
+ * Create a new ticket |
|
34 |
+*/ |
|
35 |
+function shd_post_ticket() |
|
36 |
+{ |
|
37 |
+ global $context, $user_info, $sourcedir, $txt, $scripturl, $reply_request, $smcFunc, $options, $memberContext, $new_ticket; |
|
38 |
+ $context['tabindex'] = 1; |
|
39 |
+ |
|
40 |
+ $new_ticket = $_REQUEST['sa'] == 'newticket'; |
|
41 |
+ |
|
42 |
+ if ($new_ticket) |
|
43 |
+ shd_is_allowed_to('shd_new_ticket'); |
|
44 |
+ else |
|
45 |
+ { |
|
46 |
+ checkSession('get'); |
|
47 |
+ $ticketinfo = shd_load_ticket(); |
|
48 |
+ if (!shd_allowed_to('shd_edit_ticket_any') && (!shd_allowed_to('shd_edit_ticket_own') || !$ticketinfo['is_own'])) |
|
49 |
+ fatal_lang_error('cannot_shd_edit_ticket'); |
|
50 |
+ } |
|
51 |
+ |
|
52 |
+ // Things we need |
|
53 |
+ loadTemplate('sd_template/SimpleDesk-Post'); |
|
54 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
55 |
+ require_once($sourcedir . '/Subs-Post.php'); |
|
56 |
+ require_once($sourcedir . '/Subs-Editor.php'); |
|
57 |
+ |
|
58 |
+ $context['ticket_form'] = array( // yes, everything goes in here. |
|
59 |
+ 'form_title' => $new_ticket ? $txt['shd_create_ticket'] : $txt['shd_edit_ticket'], |
|
60 |
+ 'form_action' => $scripturl . '?action=helpdesk;sa=saveticket', |
|
61 |
+ 'first_msg' => $new_ticket ? 0 : $ticketinfo['id_first_msg'], |
|
62 |
+ 'message' => $new_ticket ? '' : $ticketinfo['body'], |
|
63 |
+ 'subject' => $new_ticket ? '' : $ticketinfo['subject'], |
|
64 |
+ 'ticket' => $new_ticket ? 0 : $context['ticket_id'], |
|
65 |
+ 'link' => $new_ticket ? '' : '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '">' . $ticketinfo['subject'] . '</a>', |
|
66 |
+ 'msg' => $new_ticket ? 0 : $ticketinfo['id_first_msg'], |
|
67 |
+ 'display_id' => $new_ticket ? '' : str_pad($context['ticket_id'], 5, '0', STR_PAD_LEFT), |
|
68 |
+ 'status' => $new_ticket ? TICKET_STATUS_NEW : $ticketinfo['status'], |
|
69 |
+ 'urgency' => array( |
|
70 |
+ 'setting' => $new_ticket ? TICKET_URGENCY_LOW : $ticketinfo['urgency'], |
|
71 |
+ ), |
|
72 |
+ 'private' => array( |
|
73 |
+ 'setting' => $new_ticket ? false : ($ticketinfo['private'] == 1), |
|
74 |
+ 'can_change' => shd_allowed_to('shd_alter_privacy_any') || (shd_allowed_to('shd_alter_privacy_own') && ($new_ticket || !empty($ticketinfo['is_own']))), |
|
75 |
+ 'options' => array( |
|
76 |
+ 0 => 'shd_ticket_notprivate', |
|
77 |
+ 1 => 'shd_ticket_private', |
|
78 |
+ ), |
|
79 |
+ ), |
|
80 |
+ 'errors' => array(), |
|
81 |
+ 'num_replies' => $new_ticket ? 0 : $ticketinfo['num_replies'], |
|
82 |
+ 'do_attach' => shd_allowed_to('shd_post_attachment'), |
|
83 |
+ 'num_allowed_attachments' => empty($modSettings['attachmentNumPerPostLimit']) || $modSettings['shd_attachments_mode'] == 'ticket' ? -1 : $modSettings['attachmentNumPerPostLimit'], |
|
84 |
+ 'return_to_ticket' => isset($_REQUEST['goback']), |
|
85 |
+ 'disable_smileys' => $new_ticket ? !empty($_REQUEST['no_smileys']) : ($ticketinfo['smileys_enabled'] == 0), |
|
86 |
+ ); |
|
87 |
+ $context['can_solve'] = !$new_ticket && (shd_allowed_to('shd_resolve_ticket_any') || (shd_allowed_to('shd_resolve_ticket_own') && $ticketinfo['starter_id'] == $user_info['id'])); |
|
88 |
+ $context['can_post_proxy'] = $new_ticket && isset($_REQUEST['proxy']) && shd_allowed_to('shd_post_proxy'); |
|
89 |
+ if ($context['can_post_proxy'] && !empty($_REQUEST['proxy'])) |
|
90 |
+ { |
|
91 |
+ // Did they specify a user id? |
|
92 |
+ global $user_profile; |
|
93 |
+ $user = (int) $_REQUEST['proxy']; |
|
94 |
+ if ($user != 0) |
|
95 |
+ { |
|
96 |
+ loadMemberData($user, false, 'minimal'); |
|
97 |
+ if (!empty($user_profile[$user])) |
|
98 |
+ $context['ticket_form']['proxy'] = $user_profile[$user]['real_name']; |
|
99 |
+ } |
|
100 |
+ } |
|
101 |
+ |
|
102 |
+ shd_posting_additional_options(); |
|
103 |
+ |
|
104 |
+ // A few basic checks |
|
105 |
+ if ($context['ticket_form']['status'] == TICKET_STATUS_CLOSED) |
|
106 |
+ fatal_lang_error('shd_cannot_edit_closed', false); |
|
107 |
+ elseif ($context['ticket_form']['status'] == TICKET_STATUS_DELETED) |
|
108 |
+ fatal_lang_error('shd_cannon_edit_deleted', false); |
|
109 |
+ |
|
110 |
+ // Ticket privacy |
|
111 |
+ if (empty($modSettings['shd_privacy_display']) || $modSettings['shd_privacy_display'] == 'smart') |
|
112 |
+ $context['display_private'] = shd_allowed_to('shd_view_ticket_private_any') || shd_allowed_to('shd_alter_privacy_own') || shd_allowed_to('shd_alter_privacy_any') || $context['ticket_form']['private']['setting']; |
|
113 |
+ else |
|
114 |
+ $context['display_private'] = true; |
|
115 |
+ |
|
116 |
+ if ($new_ticket) |
|
117 |
+ { |
|
118 |
+ $context['ticket_form'] += array( |
|
119 |
+ 'member' => array( |
|
120 |
+ 'name' => $context['user']['name'], |
|
121 |
+ 'id' => $context['user']['id'], |
|
122 |
+ 'link' => shd_profile_link($context['user']['name'], $context['user']['id']), |
|
123 |
+ ), |
|
124 |
+ 'assigned' => array( |
|
125 |
+ 'id' => 0, |
|
126 |
+ 'name' => $txt['shd_unassigned'], |
|
127 |
+ 'link' => '<span class="error">' . $txt['shd_unassigned'] . '</span>', |
|
128 |
+ ), |
|
129 |
+ ); |
|
130 |
+ } |
|
131 |
+ else |
|
132 |
+ { |
|
133 |
+ $context['ticket_form'] += array( |
|
134 |
+ 'member' => array( |
|
135 |
+ 'name' => $ticketinfo['starter_name'], |
|
136 |
+ 'id' => $ticketinfo['starter_id'], |
|
137 |
+ 'link' => shd_profile_link($ticketinfo['starter_name'], $ticketinfo['starter_id']), |
|
138 |
+ ), |
|
139 |
+ 'assigned' => array( |
|
140 |
+ 'id' => $ticketinfo['assigned_id'], |
|
141 |
+ 'name' => !empty($ticketinfo['assigned_id']) ? $ticketinfo['assigned_name'] : $txt['shd_unassigned'], |
|
142 |
+ 'link' => !empty($ticketinfo['assigned_id']) ? shd_profile_link($ticketinfo['assigned_name'], $ticketinfo['assigned_id']) : '<span class="error">' . $txt['shd_unassigned'] . '</span>', |
|
143 |
+ ), |
|
144 |
+ ); |
|
145 |
+ |
|
146 |
+ loadMemberData($ticketinfo['starter_id']); |
|
147 |
+ if (loadMemberContext($ticketinfo['starter_id'])) |
|
148 |
+ $context['ticket_form']['member']['avatar'] = $memberContext[$ticketinfo['starter_id']]['avatar']; |
|
149 |
+ |
|
150 |
+ if (!$new_ticket && !empty($ticketinfo['modified_time'])) |
|
151 |
+ { |
|
152 |
+ $context['ticket_form'] += array( |
|
153 |
+ 'modified' => array( |
|
154 |
+ 'name' => $ticketinfo['modified_name'], |
|
155 |
+ 'id' => $ticketinfo['modified_id'], |
|
156 |
+ 'time' => timeformat($ticketinfo['modified_time']), |
|
157 |
+ 'link' => shd_profile_link($ticketinfo['modified_name'], $ticketinfo['modified_id']), |
|
158 |
+ ), |
|
159 |
+ ); |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ // Some other setup stuff |
|
163 |
+ shd_load_attachments(); |
|
164 |
+ |
|
165 |
+ $context['ticket_form']['message'] = un_preparsecode($context['ticket_form']['message']); |
|
166 |
+ censorText($context['ticket_form']['subject']); |
|
167 |
+ censorText($context['ticket_form']['message']); |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ shd_get_urgency_options($new_ticket || $ticketinfo['is_own']); |
|
171 |
+ |
|
172 |
+ if ($context['ticket_form']['num_replies']) |
|
173 |
+ shd_setup_replies($ticketinfo['id_first_msg']); |
|
174 |
+ |
|
175 |
+ shd_check_attachments(); |
|
176 |
+ |
|
177 |
+ // Set up the fancy editor |
|
178 |
+ shd_postbox( |
|
179 |
+ 'shd_message', |
|
180 |
+ $context['ticket_form']['message'], |
|
181 |
+ array( |
|
182 |
+ 'post_button' => $context['ticket_form']['form_title'], |
|
183 |
+ ) |
|
184 |
+ ); |
|
185 |
+ |
|
186 |
+ // Build the link tree and navigation |
|
187 |
+ $context['linktree'][] = array( |
|
188 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
189 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
190 |
+ ); |
|
191 |
+ $context['linktree'][] = array( |
|
192 |
+ 'name' => $new_ticket ? $txt['shd_create_ticket'] : sprintf($txt['shd_edit_ticket_linktree'], $context['ticket_form']['link']), |
|
193 |
+ ); |
|
194 |
+ |
|
195 |
+ $context['page_title'] = $txt['shd_helpdesk']; |
|
196 |
+ $context['sub_template'] = 'ticket_post'; |
|
197 |
+ |
|
198 |
+ // Register this form in the session variables. |
|
199 |
+ checkSubmitOnce('register'); |
|
200 |
+} |
|
201 |
+ |
|
202 |
+// All the magically common posting stuff goes in here |
|
203 |
+function shd_save_post() |
|
204 |
+{ |
|
205 |
+ global $txt, $modSettings, $sourcedir, $context, $scripturl; |
|
206 |
+ global $user_info, $options, $smcFunc; |
|
207 |
+ |
|
208 |
+ // Oh no, robots! |
|
209 |
+ $context['robot_no_index'] = true; |
|
210 |
+ |
|
211 |
+ $context['shd_errors'] = array(); |
|
212 |
+ |
|
213 |
+ // We'll probably be needing these. |
|
214 |
+ require_once($sourcedir . '/Subs-Editor.php'); |
|
215 |
+ require_once($sourcedir . '/Subs-Post.php'); |
|
216 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
217 |
+ loadTemplate('sd_template/SimpleDesk-Post'); |
|
218 |
+ loadLanguage('Errors'); // for some of the errors we already have |
|
219 |
+ loadLanguage('Post'); // for some of the common post errors |
|
220 |
+ |
|
221 |
+ if (!empty($_REQUEST['shd_message_mode']) && isset($_REQUEST['shd_message'])) |
|
222 |
+ { |
|
223 |
+ // If we came from WYSIWYG, we need to convert from HTML to bbc, then unhtml it; then push to $_POST for everything else |
|
224 |
+ $_REQUEST['shd_message'] = un_htmlspecialchars(html_to_bbc($_REQUEST['shd_message'])); |
|
225 |
+ $_POST['shd_message'] = $_REQUEST['shd_message']; |
|
226 |
+ } |
|
227 |
+ |
|
228 |
+ // Check session and double-posting |
|
229 |
+ checkSubmitOnce('check'); |
|
230 |
+ if (checkSession('post', '', false) != '') |
|
231 |
+ $context['shd_errors'][] = 'session_timeout'; |
|
232 |
+ |
|
233 |
+ // Clean up the details |
|
234 |
+ if (!isset($_POST['shd_message']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['shd_message']), ENT_QUOTES) === '') |
|
235 |
+ { |
|
236 |
+ $context['shd_errors'][] = 'no_message'; |
|
237 |
+ $_POST['shd_message'] = ''; |
|
238 |
+ } |
|
239 |
+ else |
|
240 |
+ { |
|
241 |
+ // Pfft. |
|
242 |
+ if (isset($_POST['shd_message']) && strtolower($_POST['shd_message']) == 'this is simpledesk!') |
|
243 |
+ fatal_error('You are not King Leonidas...', false); |
|
244 |
+ $_POST['shd_message'] = $smcFunc['htmlspecialchars']($_POST['shd_message'], ENT_QUOTES); |
|
245 |
+ preparsecode($_POST['shd_message']); |
|
246 |
+ |
|
247 |
+ // Make sure there's something underneath all the tags |
|
248 |
+ if ($smcFunc['htmltrim'](strip_tags(shd_format_text($_POST['shd_message'], false), '<img>')) === '' && (!shd_allowed_to('admin_forum') || strpos($_POST['shd_message'], '[html]') === false)) |
|
249 |
+ $context['shd_errors'][] = 'no_message'; |
|
250 |
+ elseif (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['shd_message']) > $modSettings['max_messageLength']) |
|
251 |
+ { |
|
252 |
+ $context['shd_errors'][] = 'long_message'; |
|
253 |
+ $txt['error_long_message'] = sprintf($txt['error_long_message'], $modSettings['max_messageLength']); |
|
254 |
+ } |
|
255 |
+ } |
|
256 |
+ |
|
257 |
+ // Now send them off to the specific areas, whether that's saving a ticket or a reply |
|
258 |
+ |
|
259 |
+ $actions = array( |
|
260 |
+ 'saveticket' => 'shd_save_ticket', |
|
261 |
+ 'savereply' => 'shd_save_reply', |
|
262 |
+ ); |
|
263 |
+ |
|
264 |
+ if (isset($actions[$_REQUEST['sa']])) |
|
265 |
+ $actions[$_REQUEST['sa']](); |
|
266 |
+} |
|
267 |
+ |
|
268 |
+function shd_save_ticket() |
|
269 |
+{ |
|
270 |
+ global $txt, $modSettings, $sourcedir, $context, $scripturl; |
|
271 |
+ global $user_info, $options, $smcFunc, $memberContext; |
|
272 |
+ |
|
273 |
+ // Ticket's gotta have a subject |
|
274 |
+ if (!isset($_POST['subject']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['subject'])) === '') |
|
275 |
+ { |
|
276 |
+ $context['shd_errors'][] = 'no_subject'; |
|
277 |
+ $_POST['subject'] = ''; |
|
278 |
+ } |
|
279 |
+ else |
|
280 |
+ $_POST['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); |
|
281 |
+ |
|
282 |
+ if (empty($context['ticket_id'])) |
|
283 |
+ { |
|
284 |
+ shd_is_allowed_to('shd_new_ticket'); |
|
285 |
+ |
|
286 |
+ // some healthy defaults |
|
287 |
+ $context['ticket_id'] = 0; |
|
288 |
+ $new_ticket = true; |
|
289 |
+ $msg = 0; |
|
290 |
+ $is_own = true; |
|
291 |
+ $new_status = TICKET_STATUS_NEW; |
|
292 |
+ $private = false; |
|
293 |
+ $urgency = TICKET_URGENCY_LOW; |
|
294 |
+ $assigned = array( |
|
295 |
+ 'id' => 0, |
|
296 |
+ 'name' => $txt['shd_unassigned'], |
|
297 |
+ 'link' => '<span class="error">' . $txt['shd_unassigned'] . '</span>', |
|
298 |
+ ); |
|
299 |
+ $num_replies = 0; |
|
300 |
+ } |
|
301 |
+ else |
|
302 |
+ { |
|
303 |
+ // hmm, we're saving an update, let's get the existing ticket details and we can check permissions and stuff |
|
304 |
+ $new_ticket = false; |
|
305 |
+ |
|
306 |
+ $ticketinfo = shd_load_ticket(); |
|
307 |
+ |
|
308 |
+ // S'pose we'd better check the permissions here |
|
309 |
+ if (!shd_allowed_to('shd_edit_ticket_any') && (!shd_allowed_to('shd_edit_ticket_own') || !$ticketinfo['is_own'])) |
|
310 |
+ fatal_lang_error('cannot_shd_edit_ticket', false); |
|
311 |
+ |
|
312 |
+ $msg = $ticketinfo['id_first_msg']; |
|
313 |
+ $is_own = $ticketinfo['is_own']; |
|
314 |
+ $private = $ticketinfo['private']; |
|
315 |
+ $urgency = $ticketinfo['urgency']; |
|
316 |
+ $new_status = $ticketinfo['status']; |
|
317 |
+ $assigned = array( |
|
318 |
+ 'id' => $ticketinfo['assigned_id'], |
|
319 |
+ 'name' => !empty($ticketinfo['assigned_id']) ? $ticketinfo['assigned_name'] : $txt['shd_unassigned'], |
|
320 |
+ 'link' => !empty($ticketinfo['assigned_id']) ? shd_profile_link($ticketinfo['assigned_name'], $ticketinfo['assigned_id']) : '<span class="error">' . $txt['shd_unassigned'] . '</span>', |
|
321 |
+ ); |
|
322 |
+ $num_replies = $ticketinfo['num_replies']; |
|
323 |
+ } |
|
324 |
+ |
|
325 |
+ $context['ticket_form'] = array( |
|
326 |
+ 'form_title' => $new_ticket ? $txt['shd_create_ticket'] : $txt['shd_edit_ticket'], |
|
327 |
+ 'form_action' => $scripturl . '?action=helpdesk;sa=saveticket', |
|
328 |
+ 'first_msg' => $new_ticket ? 0 : $ticketinfo['id_first_msg'], |
|
329 |
+ 'message' => $_POST['shd_message'], |
|
330 |
+ 'subject' => $_POST['subject'], |
|
331 |
+ 'ticket' => $context['ticket_id'], |
|
332 |
+ 'link' => $new_ticket ? '' : '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '">' . $ticketinfo['subject'] . '</a>', |
|
333 |
+ 'msg' => $msg, |
|
334 |
+ 'display_id' => empty($context['ticket_id']) ? '' : str_pad($context['ticket_id'], 5, '0', STR_PAD_LEFT), |
|
335 |
+ 'status' => $new_status, |
|
336 |
+ 'private' => array( |
|
337 |
+ 'setting' => $private, |
|
338 |
+ 'can_change' => (shd_allowed_to('shd_alter_privacy_any') || ($is_own && shd_allowed_to('shd_alter_privacy_own'))), |
|
339 |
+ 'options' => array( |
|
340 |
+ 0 => 'shd_ticket_notprivate', |
|
341 |
+ 1 => 'shd_ticket_private', |
|
342 |
+ ), |
|
343 |
+ ), |
|
344 |
+ 'assigned' => $assigned, |
|
345 |
+ 'num_replies' => $num_replies, |
|
346 |
+ 'do_attach' => shd_allowed_to('shd_post_attachment'), |
|
347 |
+ 'return_to_ticket' => isset($_REQUEST['goback']), |
|
348 |
+ 'disable_smileys' => !empty($_REQUEST['no_smileys']), |
|
349 |
+ ); |
|
350 |
+ $context['can_solve'] = !$new_ticket && (shd_allowed_to('shd_resolve_ticket_any') || (shd_allowed_to('shd_resolve_ticket_own') && $ticketinfo['starter_id'] == $user_info['id'])); |
|
351 |
+ $context['log_action'] = $new_ticket ? 'newticket' : 'editticket'; |
|
352 |
+ $context['log_params']['subject'] = $context['ticket_form']['subject']; |
|
353 |
+ |
|
354 |
+ $context['can_post_proxy'] = $new_ticket && isset($_REQUEST['proxy']) && shd_allowed_to('shd_post_proxy'); |
|
355 |
+ if ($context['can_post_proxy'] && !empty($_REQUEST['proxy_author'])) |
|
356 |
+ { |
|
357 |
+ // OK, so we have a name... do we know this person? |
|
358 |
+ require_once($sourcedir . '/Subs-Auth.php'); |
|
359 |
+ $proxy_author = $smcFunc['htmlspecialchars']($smcFunc['strtolower'](trim($_REQUEST['proxy_author']))); |
|
360 |
+ $_REQUEST['proxy_author'] = $smcFunc['htmlspecialchars'](trim($_REQUEST['proxy_author'])); |
|
361 |
+ if (!empty($_REQUEST['proxy_author'])) |
|
362 |
+ { |
|
363 |
+ $member = findMembers($proxy_author); |
|
364 |
+ if (!empty($member)) |
|
365 |
+ { |
|
366 |
+ list($context['ticket_form']['proxy_id']) = array_keys($member); |
|
367 |
+ $context['ticket_form']['proxy'] = $member[$context['ticket_form']['proxy_id']]['name']; |
|
368 |
+ } |
|
369 |
+ else |
|
370 |
+ { |
|
371 |
+ $context['ticket_form']['proxy'] = $_REQUEST['proxy_author']; |
|
372 |
+ $context['shd_errors'][] = 'shd_proxy_unknown'; |
|
373 |
+ } |
|
374 |
+ } |
|
375 |
+ } |
|
376 |
+ shd_posting_additional_options(); |
|
377 |
+ |
|
378 |
+ // Ticket privacy |
|
379 |
+ if (empty($modSettings['shd_privacy_display']) || $modSettings['shd_privacy_display'] == 'smart') |
|
380 |
+ $context['display_private'] = shd_allowed_to('shd_view_ticket_private_any') || shd_allowed_to('shd_alter_privacy_own') || shd_allowed_to('shd_alter_privacy_any') || $context['ticket_form']['private']['setting']; |
|
381 |
+ else |
|
382 |
+ $context['display_private'] = true; |
|
383 |
+ |
|
384 |
+ // Preview? |
|
385 |
+ if (isset($_REQUEST['preview'])) |
|
386 |
+ { |
|
387 |
+ $context['ticket_form']['preview'] = array( |
|
388 |
+ 'title' => $txt['shd_previewing_ticket'] . ': ' . (empty($_POST['subject']) ? '<em>' . $txt['no_subject'] . '</em>' : $_POST['subject']), |
|
389 |
+ 'body' => shd_format_text($_POST['shd_message']), |
|
390 |
+ ); |
|
391 |
+ } |
|
392 |
+ |
|
393 |
+ if (!$new_ticket && !empty($ticketinfo['modified_time'])) |
|
394 |
+ { |
|
395 |
+ $context['ticket_form'] += array( |
|
396 |
+ 'modified' => array( |
|
397 |
+ 'name' => $ticketinfo['modified_name'], |
|
398 |
+ 'id' => $ticketinfo['modified_id'], |
|
399 |
+ 'time' => timeformat($ticketinfo['modified_time']), |
|
400 |
+ 'link' => shd_profile_link($ticketinfo['modified_name'], $ticketinfo['modified_id']), |
|
401 |
+ ), |
|
402 |
+ ); |
|
403 |
+ } |
|
404 |
+ |
|
405 |
+ if (!$new_ticket) |
|
406 |
+ { |
|
407 |
+ loadMemberData($ticketinfo['starter_id']); |
|
408 |
+ if (loadMemberContext($ticketinfo['starter_id'])) |
|
409 |
+ $context['ticket_form']['member']['avatar'] = $memberContext[$ticketinfo['starter_id']]['avatar']; |
|
410 |
+ } |
|
411 |
+ |
|
412 |
+ shd_load_attachments(); |
|
413 |
+ |
|
414 |
+ // Ticket privacy, let's see if we can override our healthy default with the post value |
|
415 |
+ if ($context['ticket_form']['private']['can_change']) |
|
416 |
+ { |
|
417 |
+ $new_private = isset($_POST['shd_private']) ? (int) $_POST['shd_private'] : $private; |
|
418 |
+ $context['ticket_form']['private']['setting'] = isset($context['ticket_form']['private']['options'][$new_private]) ? (bool) $new_private : $private; |
|
419 |
+ } |
|
420 |
+ |
|
421 |
+ // Ticket urgency |
|
422 |
+ shd_get_urgency_options($is_own); |
|
423 |
+ if ($context['ticket_form']['urgency']['can_change']) |
|
424 |
+ { |
|
425 |
+ $new_urgency = isset($_POST['shd_urgency']) ? (int) $_POST['shd_urgency'] : $urgency; |
|
426 |
+ $context['ticket_form']['urgency']['setting'] = isset($context['ticket_form']['urgency']['options'][$new_urgency]) ? $new_urgency : $urgency; |
|
427 |
+ } |
|
428 |
+ else |
|
429 |
+ $context['ticket_form']['urgency']['setting'] = $urgency; |
|
430 |
+ |
|
431 |
+ // A few basic checks |
|
432 |
+ if ($context['ticket_form']['status'] == TICKET_STATUS_CLOSED) |
|
433 |
+ fatal_lang_error('shd_cannot_edit_closed', false); |
|
434 |
+ elseif ($context['ticket_form']['status'] == TICKET_STATUS_DELETED) |
|
435 |
+ fatal_lang_error('shd_cannon_edit_deleted', false); |
|
436 |
+ |
|
437 |
+ // OK, does the user want to close this ticket? Are there any problems with that? |
|
438 |
+ if (!empty($context['can_solve']) && !empty($_POST['resolve_ticket'])) |
|
439 |
+ { |
|
440 |
+ $string = shd_check_dependencies(); |
|
441 |
+ if (!empty($string)) |
|
442 |
+ $context['shd_errors'][] = $string; |
|
443 |
+ } |
|
444 |
+ |
|
445 |
+ if (!empty($context['shd_errors']) || !empty($context['ticket_form']['preview'])) // Uh oh, something went wrong, or we're previewing |
|
446 |
+ { |
|
447 |
+ checkSubmitOnce('free'); |
|
448 |
+ |
|
449 |
+ // Anything else for redisplaying the form |
|
450 |
+ $context['page_title'] = $txt['shd_helpdesk']; |
|
451 |
+ $context['sub_template'] = 'ticket_post'; |
|
452 |
+ |
|
453 |
+ shd_check_attachments(); |
|
454 |
+ |
|
455 |
+ // Set up the fancy editor |
|
456 |
+ shd_postbox( |
|
457 |
+ 'shd_message', |
|
458 |
+ un_preparsecode($context['ticket_form']['message']), |
|
459 |
+ array( |
|
460 |
+ 'post_button' => $context['ticket_form']['form_title'], |
|
461 |
+ ) |
|
462 |
+ ); |
|
463 |
+ |
|
464 |
+ // Build the link tree and navigation |
|
465 |
+ $context['linktree'][] = array( |
|
466 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
467 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
468 |
+ ); |
|
469 |
+ $context['linktree'][] = array( |
|
470 |
+ 'name' => $new_ticket ? $txt['shd_create_ticket'] : sprintf($txt['shd_edit_ticket_linktree'], $context['ticket_form']['link']), |
|
471 |
+ ); |
|
472 |
+ |
|
473 |
+ checkSubmitOnce('register'); |
|
474 |
+ } |
|
475 |
+ else |
|
476 |
+ { |
|
477 |
+ // It all worked, w00t, so let's get ready to rumble |
|
478 |
+ $attachIDs = shd_handle_attachments(); |
|
479 |
+ |
|
480 |
+ if ($new_ticket) |
|
481 |
+ { |
|
482 |
+ // Now to add the ticket details |
|
483 |
+ $posterOptions = array( |
|
484 |
+ 'id' => $user_info['id'], |
|
485 |
+ ); |
|
486 |
+ |
|
487 |
+ $msgOptions = array( |
|
488 |
+ 'body' => $context['ticket_form']['message'], |
|
489 |
+ 'id' => $context['ticket_form']['msg'], |
|
490 |
+ 'smileys_enabled' => empty($context['ticket_form']['disable_smileys']), |
|
491 |
+ 'attachments' => $attachIDs, |
|
492 |
+ ); |
|
493 |
+ |
|
494 |
+ $ticketOptions = array( |
|
495 |
+ 'id' => $context['ticket_form']['ticket'], |
|
496 |
+ 'mark_as_read' => true, |
|
497 |
+ 'subject' => $context['ticket_form']['subject'], |
|
498 |
+ 'private' => $context['ticket_form']['private']['setting'], |
|
499 |
+ 'status' => $context['ticket_form']['status'], |
|
500 |
+ 'urgency' => $context['ticket_form']['urgency']['setting'], |
|
501 |
+ 'assigned' => $context['ticket_form']['assigned']['id'], |
|
502 |
+ ); |
|
503 |
+ |
|
504 |
+ // Just before we do... proxy ticket? |
|
505 |
+ if (!empty($context['ticket_form']['proxy_id'])) |
|
506 |
+ { |
|
507 |
+ // 1. Fix the poster options |
|
508 |
+ $posterOptions['id'] = $context['ticket_form']['proxy_id']; |
|
509 |
+ // 2. Make sure it's marked read for the right user |
|
510 |
+ $ticketOptions['mark_as_read_proxy'] = $user_info['id']; |
|
511 |
+ // 3. Fix the log items |
|
512 |
+ $context['log_action'] = 'newticketproxy'; |
|
513 |
+ $context['log_params']['user_id'] = $context['ticket_form']['proxy_id']; |
|
514 |
+ $context['log_params']['user_name'] = $context['ticket_form']['proxy']; |
|
515 |
+ } |
|
516 |
+ |
|
517 |
+ shd_create_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
518 |
+ shd_clear_active_tickets(); |
|
519 |
+ |
|
520 |
+ // Update our nice ticket store with the ticket id |
|
521 |
+ $context['ticket_id'] = $ticketOptions['id']; |
|
522 |
+ $context['ticket_form']['ticket'] = $ticketOptions['id']; |
|
523 |
+ } |
|
524 |
+ else |
|
525 |
+ { |
|
526 |
+ // Only add what has actually changed |
|
527 |
+ // Now to add the ticket details |
|
528 |
+ $posterOptions = array(); |
|
529 |
+ |
|
530 |
+ $msgOptions = array( |
|
531 |
+ 'id' => $context['ticket_form']['msg'], |
|
532 |
+ 'attachments' => $attachIDs, |
|
533 |
+ ); |
|
534 |
+ |
|
535 |
+ $ticketOptions = array( |
|
536 |
+ 'id' => $context['ticket_form']['ticket'], |
|
537 |
+ ); |
|
538 |
+ |
|
539 |
+ if ((bool) $ticketinfo['smileys_enabled'] == $context['ticket_form']['disable_smileys']) // since one is enabled, one is 'now disable'... |
|
540 |
+ $msgOptions['smileys_enabled'] = !$context['ticket_form']['disable_smileys']; |
|
541 |
+ |
|
542 |
+ // This things don't trigger modified time |
|
543 |
+ if ($ticketinfo['private'] != $context['ticket_form']['private']['setting']) |
|
544 |
+ { |
|
545 |
+ $ticketOptions['private'] = $context['ticket_form']['private']['setting']; |
|
546 |
+ // log the change too |
|
547 |
+ $action = empty($context['ticket_form']['private']['setting']) ? 'marknotprivate' : 'markprivate'; // i.e. based on new setting |
|
548 |
+ shd_log_action($action, |
|
549 |
+ array( |
|
550 |
+ 'ticket' => $context['ticket_form']['ticket'], |
|
551 |
+ 'subject' => $context['ticket_form']['subject'], |
|
552 |
+ ) |
|
553 |
+ ); |
|
554 |
+ } |
|
555 |
+ if ($ticketinfo['urgency'] != $context['ticket_form']['urgency']['setting']) |
|
556 |
+ { |
|
557 |
+ $ticketOptions['urgency'] = $context['ticket_form']['urgency']['setting']; |
|
558 |
+ // log the change too |
|
559 |
+ $action = ($context['ticket_form']['urgency']['setting'] > $ticketinfo['urgency']) ? 'urgency_increase' : 'urgency_decrease'; |
|
560 |
+ shd_log_action($action, |
|
561 |
+ array( |
|
562 |
+ 'ticket' => $context['ticket_form']['ticket'], |
|
563 |
+ 'subject' => $context['ticket_form']['subject'], |
|
564 |
+ 'urgency' => $context['ticket_form']['urgency']['setting'], |
|
565 |
+ ) |
|
566 |
+ ); |
|
567 |
+ } |
|
568 |
+ |
|
569 |
+ // But these things do! |
|
570 |
+ if ($ticketinfo['subject'] != $context['ticket_form']['subject']) |
|
571 |
+ $ticketOptions['subject'] = $context['ticket_form']['subject']; |
|
572 |
+ if ($ticketinfo['body'] != $context['ticket_form']['message']) |
|
573 |
+ $msgOptions['body'] = $context['ticket_form']['message']; |
|
574 |
+ |
|
575 |
+ if (isset($ticketOptions['subject']) || isset($msgOptions['body'])) |
|
576 |
+ $msgOptions['modified'] = array( |
|
577 |
+ 'id' => $user_info['id'], |
|
578 |
+ 'name' => $user_info['name'], |
|
579 |
+ 'time' => time(), |
|
580 |
+ ); |
|
581 |
+ |
|
582 |
+ if (!empty($context['can_solve']) && !empty($_POST['resolve_ticket'])) |
|
583 |
+ { |
|
584 |
+ $ticketOptions['status'] = TICKET_STATUS_CLOSED; |
|
585 |
+ shd_log_action('resolve', |
|
586 |
+ array( |
|
587 |
+ 'ticket' => $context['ticket_id'], |
|
588 |
+ 'subject' => $ticketinfo['subject'], |
|
589 |
+ ) |
|
590 |
+ ); |
|
591 |
+ } |
|
592 |
+ |
|
593 |
+ // DOOOOOOOO EEEEEEEEEEET NAO! |
|
594 |
+ shd_modify_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
595 |
+ shd_clear_active_tickets($ticketinfo['id_member_started']); |
|
596 |
+ } |
|
597 |
+ shd_done_posting(); |
|
598 |
+ } |
|
599 |
+} |
|
600 |
+ |
|
601 |
+function shd_post_reply() |
|
602 |
+{ |
|
603 |
+ global $context, $user_info, $sourcedir, $txt, $scripturl, $smcFunc, $reply_request, $modSettings, $settings, $options, $memberContext; |
|
604 |
+ |
|
605 |
+ checkSession('get'); |
|
606 |
+ |
|
607 |
+ $new_reply = $_REQUEST['sa'] == 'reply'; |
|
608 |
+ |
|
609 |
+ // Things we need |
|
610 |
+ loadTemplate('sd_template/SimpleDesk-Post'); |
|
611 |
+ require_once($sourcedir . '/Subs-Post.php'); |
|
612 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
613 |
+ require_once($sourcedir . '/Subs-Editor.php'); |
|
614 |
+ |
|
615 |
+ $ticketinfo = shd_load_ticket(); |
|
616 |
+ $reply = array(); |
|
617 |
+ |
|
618 |
+ // So, at this point, we can see it, but no guarantee we can reply to it. |
|
619 |
+ // Can we reply to any? If so, just go right along. If not, we need to do more work. |
|
620 |
+ if ($new_reply) |
|
621 |
+ { |
|
622 |
+ if (!shd_allowed_to('shd_reply_ticket_any')) |
|
623 |
+ { |
|
624 |
+ if (shd_allowed_to('shd_reply_ticket_own')) |
|
625 |
+ { |
|
626 |
+ if (!$ticketinfo['is_own']) |
|
627 |
+ fatal_lang_error('shd_cannot_reply_any_but_own', false); |
|
628 |
+ } |
|
629 |
+ else |
|
630 |
+ fatal_lang_error('shd_cannot_reply_any', false); // can't do nuthin' |
|
631 |
+ } |
|
632 |
+ } |
|
633 |
+ else |
|
634 |
+ { |
|
635 |
+ $_REQUEST['msg'] = !empty($_REQUEST['msg']) ? (int) $_REQUEST['msg'] : 0; |
|
636 |
+ $query = shd_db_query('', ' |
|
637 |
+ SELECT id_msg, id_member, body, modified_time, modified_member, modified_name |
|
638 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
639 |
+ WHERE id_msg = {int:msg} |
|
640 |
+ AND id_ticket = {int:ticket}', |
|
641 |
+ array( |
|
642 |
+ 'msg' => $_REQUEST['msg'], |
|
643 |
+ 'ticket' => $context['ticket_id'], |
|
644 |
+ ) |
|
645 |
+ ); |
|
646 |
+ |
|
647 |
+ if ($smcFunc['db_num_rows']($query) == 0) |
|
648 |
+ { |
|
649 |
+ $smcFunc['db_free_result']($query); |
|
650 |
+ fatal_lang_error('shd_no_ticket', false); |
|
651 |
+ } |
|
652 |
+ |
|
653 |
+ $reply = $smcFunc['db_fetch_assoc']($query); |
|
654 |
+ |
|
655 |
+ if (!shd_allowed_to('shd_edit_reply_any')) |
|
656 |
+ { |
|
657 |
+ if (shd_allowed_to('shd_edit_reply_own')) |
|
658 |
+ { |
|
659 |
+ if ($reply['id_member'] != $user_info['id']) |
|
660 |
+ fatal_lang_error('shd_cannot_edit_reply_any_but_own', false); |
|
661 |
+ } |
|
662 |
+ else |
|
663 |
+ fatal_lang_error('shd_cannot_edit_reply_any', false); |
|
664 |
+ } |
|
665 |
+ |
|
666 |
+ // Fix the body up for later |
|
667 |
+ $reply['body'] = un_preparsecode($reply['body']); |
|
668 |
+ censorText($reply['body']); |
|
669 |
+ } |
|
670 |
+ |
|
671 |
+ // So it's either our ticket and we can reply to our own, or we can reply to any because we're awesome |
|
672 |
+ // or we're editing and we can haz such powarz |
|
673 |
+ $context['ticket_form'] = array( // yes, everything goes in here. |
|
674 |
+ 'form_title' => !empty($reply['id_msg']) ? $txt['shd_ticket_edit_reply'] : $txt['shd_reply_ticket'], |
|
675 |
+ 'form_action' => $scripturl . '?action=helpdesk;sa=savereply', |
|
676 |
+ 'first_msg' => $new_reply ? 0 : $ticketinfo['id_first_msg'], |
|
677 |
+ 'message' => shd_format_text($ticketinfo['body'], $ticketinfo['smileys_enabled'], ($new_reply ? '' : 'shd_reply_' . $ticketinfo['id_first_msg'])), |
|
678 |
+ 'subject' => $ticketinfo['subject'], |
|
679 |
+ 'ticket' => $context['ticket_id'], |
|
680 |
+ 'msg' => !empty($reply['id_msg']) ? $reply['id_msg'] : 0, |
|
681 |
+ 'ticket_link' => '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '">' . $ticketinfo['subject'] . '</a>', |
|
682 |
+ 'reply_link' => $new_reply ? 0 : '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '.msg' . $reply['id_msg'] . '#msg' . $reply['id_msg'] . '">' . $txt['response_prefix'] . ' ' . $ticketinfo['subject'] . '</a>', |
|
683 |
+ 'display_id' => str_pad($context['ticket_id'], 5, '0', STR_PAD_LEFT), |
|
684 |
+ 'status' => $ticketinfo['status'], |
|
685 |
+ 'urgency' => array( |
|
686 |
+ 'setting' => $ticketinfo['urgency'], |
|
687 |
+ ), |
|
688 |
+ 'private' => array( |
|
689 |
+ 'setting' => $ticketinfo['private'], |
|
690 |
+ 'can_change' => false, |
|
691 |
+ 'options' => array( |
|
692 |
+ 0 => 'shd_ticket_notprivate', |
|
693 |
+ 1 => 'shd_ticket_private', |
|
694 |
+ ), |
|
695 |
+ ), |
|
696 |
+ 'errors' => array(), |
|
697 |
+ 'member' => array( |
|
698 |
+ 'name' => $ticketinfo['starter_name'], |
|
699 |
+ 'id' => $ticketinfo['starter_id'], |
|
700 |
+ 'link' => shd_profile_link($ticketinfo['starter_name'], $ticketinfo['starter_id']), |
|
701 |
+ ), |
|
702 |
+ 'assigned' => array( |
|
703 |
+ 'id' => $ticketinfo['assigned_id'], |
|
704 |
+ 'name' => !empty($ticketinfo['assigned_id']) ? $ticketinfo['assigned_name'] : $txt['shd_unassigned'], |
|
705 |
+ 'link' => !empty($ticketinfo['assigned_id']) ? shd_profile_link($ticketinfo['assigned_name'], $ticketinfo['assigned_id']) : '<span class="error">' . $txt['shd_unassigned'] . '</span>', |
|
706 |
+ ), |
|
707 |
+ 'num_replies' => !empty($ticketinfo['num_replies']) ? $ticketinfo['num_replies'] : 0, |
|
708 |
+ 'do_attach' => shd_allowed_to('shd_post_attachment'), |
|
709 |
+ 'reply' => !empty($reply['body']) ? $reply['body'] : '', |
|
710 |
+ 'return_to_ticket' => isset($_REQUEST['goback']), |
|
711 |
+ 'disable_smileys' => !$new_reply ? !empty($_REQUEST['no_smileys']) : ($ticketinfo['smileys_enabled'] == 0), |
|
712 |
+ ); |
|
713 |
+ $context['can_solve'] = (shd_allowed_to('shd_resolve_ticket_any') || (shd_allowed_to('shd_resolve_ticket_own') && $ticketinfo['starter_id'] == $user_info['id'])); |
|
714 |
+ shd_posting_additional_options(); |
|
715 |
+ |
|
716 |
+ // Ticket privacy |
|
717 |
+ if (empty($modSettings['shd_privacy_display']) || $modSettings['shd_privacy_display'] == 'smart') |
|
718 |
+ $context['display_private'] = shd_allowed_to('shd_view_ticket_private_any') || shd_allowed_to('shd_alter_privacy_own') || shd_allowed_to('shd_alter_privacy_any') || $context['ticket_form']['private']['setting']; |
|
719 |
+ else |
|
720 |
+ $context['display_private'] = true; |
|
721 |
+ |
|
722 |
+ loadMemberData($ticketinfo['starter_id']); |
|
723 |
+ if (loadMemberContext($ticketinfo['starter_id'])) |
|
724 |
+ $context['ticket_form']['member']['avatar'] = $memberContext[$ticketinfo['starter_id']]['avatar']; |
|
725 |
+ |
|
726 |
+ if (!empty($ticketinfo['modified_time'])) |
|
727 |
+ { |
|
728 |
+ $context['ticket_form'] += array( |
|
729 |
+ 'modified' => array( |
|
730 |
+ 'name' => $ticketinfo['modified_name'], |
|
731 |
+ 'id' => $ticketinfo['modified_id'], |
|
732 |
+ 'time' => timeformat($ticketinfo['modified_time']), |
|
733 |
+ 'link' => shd_profile_link($ticketinfo['modified_name'], $ticketinfo['modified_id']), |
|
734 |
+ ), |
|
735 |
+ ); |
|
736 |
+ } |
|
737 |
+ |
|
738 |
+ shd_get_urgency_options($ticketinfo['is_own']); |
|
739 |
+ $context['ticket_form']['urgency']['can_change'] = false; |
|
740 |
+ |
|
741 |
+ if (!empty($ticketinfo['num_replies'])) |
|
742 |
+ shd_setup_replies($ticketinfo['id_first_msg']); |
|
743 |
+ |
|
744 |
+ // A few basic checks |
|
745 |
+ if ($context['ticket_form']['status'] == TICKET_STATUS_CLOSED) |
|
746 |
+ fatal_lang_error('shd_cannot_reply_closed', false); |
|
747 |
+ elseif ($context['ticket_form']['status'] == TICKET_STATUS_DELETED) |
|
748 |
+ fatal_lang_error('shd_cannon_reply_deleted', false); |
|
749 |
+ |
|
750 |
+ shd_load_attachments(); |
|
751 |
+ shd_check_attachments(); |
|
752 |
+ |
|
753 |
+ if (empty($options['no_new_reply_warning']) && isset($_REQUEST['num_replies'])) |
|
754 |
+ { |
|
755 |
+ $_REQUEST['num_replies'] = (int) $_REQUEST['num_replies']; |
|
756 |
+ $newReplies = $context['ticket_form']['num_replies'] > $_REQUEST['num_replies'] ? $context['ticket_form']['num_replies'] - $_REQUEST['num_replies'] : 0; |
|
757 |
+ |
|
758 |
+ if (!empty($newReplies)) |
|
759 |
+ { |
|
760 |
+ loadLanguage('Post'); |
|
761 |
+ if ($newReplies > 1) |
|
762 |
+ $txt['error_new_replies_reading'] = sprintf($txt['error_new_replies_reading'], $newReplies); |
|
763 |
+ |
|
764 |
+ $context['shd_errors'][] = $newReplies == 1 ? 'new_reply_reading' : 'new_replies_reading'; |
|
765 |
+ } |
|
766 |
+ } |
|
767 |
+ |
|
768 |
+ // Are we quoting something? Let's see if we do; we already know we can see the ticket |
|
769 |
+ $_REQUEST['quote'] = !empty($_REQUEST['quote']) ? (int) $_REQUEST['quote'] : 0; |
|
770 |
+ if (!empty($_REQUEST['quote'])) |
|
771 |
+ { |
|
772 |
+ $query = shd_db_query('', ' |
|
773 |
+ SELECT hdtr.body, IFNULL(mem.real_name, hdtr.poster_name) AS poster_name, hdtr.poster_time |
|
774 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
775 |
+ LEFT JOIN {db_prefix}members AS mem ON (hdtr.id_member = mem.id_member) |
|
776 |
+ WHERE id_msg = {int:msg} |
|
777 |
+ AND id_ticket = {int:ticket}', |
|
778 |
+ array( |
|
779 |
+ 'msg' => $_REQUEST['quote'], |
|
780 |
+ 'ticket' => $context['ticket_id'], // make sure it's actually in this ticket! |
|
781 |
+ ) |
|
782 |
+ ); |
|
783 |
+ |
|
784 |
+ if ($row = $smcFunc['db_fetch_assoc']($query)) |
|
785 |
+ { |
|
786 |
+ $smcFunc['db_free_result']($query); |
|
787 |
+ |
|
788 |
+ $row['body'] = un_preparsecode($row['body']); |
|
789 |
+ |
|
790 |
+ // Censor the message! |
|
791 |
+ censorText($row['body']); |
|
792 |
+ $row['body'] = preg_replace('~<br ?/?' . '>~i', "\n", $row['body']); |
|
793 |
+ |
|
794 |
+ if (strpos($row['poster_name'], '[') !== false || strpos($row['poster_name'], ']') !== false) |
|
795 |
+ $row['poster_name'] = '"' . $row['poster_name'] . '"'; |
|
796 |
+ |
|
797 |
+ // Make the body HTML if need be. |
|
798 |
+ if (!empty($_REQUEST['mode'])) |
|
799 |
+ { |
|
800 |
+ require_once($sourcedir . '/Subs-Editor.php'); |
|
801 |
+ $row['body'] = strtr($row['body'], array('<' => '#smlt#', '>' => '#smgt#', '&' => '#smamp#')); |
|
802 |
+ $row['body'] = bbc_to_html($row['body']); |
|
803 |
+ $lb = '<br />'; |
|
804 |
+ } |
|
805 |
+ else |
|
806 |
+ $lb = "\n"; |
|
807 |
+ |
|
808 |
+ $message = '[quote author=' . $row['poster_name'] . ' link=action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']; |
|
809 |
+ if ($ticketinfo['id_first_msg'] != $_REQUEST['quote']) // don't add the msg if we're quoting the ticket itself |
|
810 |
+ $message .= '.msg' . $_REQUEST['quote'] . '#msg' . $_REQUEST['quote']; |
|
811 |
+ |
|
812 |
+ $message .= ' date=' . $row['poster_time'] . ']' . $lb . $row['body'] . $lb . '[/quote]'; |
|
813 |
+ $context['ticket_form']['reply'] = $message; |
|
814 |
+ } |
|
815 |
+ } |
|
816 |
+ |
|
817 |
+ // Set up the awesomeness that is the rich editor |
|
818 |
+ shd_postbox( |
|
819 |
+ 'shd_message', |
|
820 |
+ $context['ticket_form']['reply'], |
|
821 |
+ array( |
|
822 |
+ 'post_button' => !empty($reply['id_msg']) ? $txt['shd_ticket_edit_reply'] : $txt['shd_reply_ticket'], |
|
823 |
+ ) |
|
824 |
+ ); |
|
825 |
+ |
|
826 |
+ // Build the link tree and navigation |
|
827 |
+ $context['linktree'][] = array( |
|
828 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
829 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
830 |
+ ); |
|
831 |
+ $context['linktree'][] = array( |
|
832 |
+ 'name' => $new_reply ? sprintf($txt['shd_reply_ticket_linktree'], $context['ticket_form']['ticket_link']) : sprintf($txt['shd_edit_reply_linktree'], $context['ticket_form']['reply_link']), |
|
833 |
+ ); |
|
834 |
+ |
|
835 |
+ $context['page_title'] = $txt['shd_helpdesk']; |
|
836 |
+ $context['sub_template'] = 'reply_post'; |
|
837 |
+ |
|
838 |
+ // Register this form in the session variables. |
|
839 |
+ checkSubmitOnce('register'); |
|
840 |
+} |
|
841 |
+ |
|
842 |
+function shd_save_reply() |
|
843 |
+{ |
|
844 |
+ global $txt, $modSettings, $sourcedir, $context, $scripturl; |
|
845 |
+ global $user_info, $options, $smcFunc, $memberContext; |
|
846 |
+ |
|
847 |
+ $_REQUEST['msg'] = !empty($_REQUEST['msg']) ? (int) $_REQUEST['msg'] : 0; |
|
848 |
+ |
|
849 |
+ // We're replying so there must be an existing ticket or sumthin's WRONG. |
|
850 |
+ $ticketinfo = shd_load_ticket(); |
|
851 |
+ $reply = array(); |
|
852 |
+ $new_reply = $_REQUEST['msg'] == 0; |
|
853 |
+ |
|
854 |
+ // So, at this point, we can see it, but no guarantee we can reply to it. |
|
855 |
+ // Can we reply to any? If so, just go right along. If not, we need to do more work. |
|
856 |
+ if ($new_reply) |
|
857 |
+ { |
|
858 |
+ if (!shd_allowed_to('shd_reply_ticket_any')) |
|
859 |
+ { |
|
860 |
+ if (shd_allowed_to('shd_reply_ticket_own')) |
|
861 |
+ { |
|
862 |
+ if (!$ticketinfo['is_own']) |
|
863 |
+ fatal_lang_error('shd_cannot_reply_any_but_own', false); |
|
864 |
+ } |
|
865 |
+ else |
|
866 |
+ fatal_lang_error('shd_cannot_reply_any', false); // can't do nuthin' |
|
867 |
+ } |
|
868 |
+ } |
|
869 |
+ else |
|
870 |
+ { |
|
871 |
+ $query = shd_db_query('', ' |
|
872 |
+ SELECT id_msg, id_member, body, modified_time, modified_member, modified_name |
|
873 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
874 |
+ WHERE id_msg = {int:msg} |
|
875 |
+ AND id_ticket = {int:ticket}', |
|
876 |
+ array( |
|
877 |
+ 'msg' => $_REQUEST['msg'], |
|
878 |
+ 'ticket' => $context['ticket_id'], |
|
879 |
+ ) |
|
880 |
+ ); |
|
881 |
+ |
|
882 |
+ if ($smcFunc['db_num_rows']($query) == 0) |
|
883 |
+ { |
|
884 |
+ $smcFunc['db_free_result']($query); |
|
885 |
+ fatal_lang_error('shd_no_ticket', false); |
|
886 |
+ } |
|
887 |
+ |
|
888 |
+ $reply = $smcFunc['db_fetch_assoc']($query); |
|
889 |
+ |
|
890 |
+ if (!shd_allowed_to('shd_edit_reply_any')) |
|
891 |
+ { |
|
892 |
+ if (shd_allowed_to('shd_edit_reply_own')) |
|
893 |
+ { |
|
894 |
+ if ($reply['id_member'] != $user_info['id']) |
|
895 |
+ fatal_lang_error('shd_cannot_edit_reply_any_but_own', false); |
|
896 |
+ } |
|
897 |
+ else |
|
898 |
+ fatal_lang_error('shd_cannot_edit_reply_any', false); |
|
899 |
+ } |
|
900 |
+ } |
|
901 |
+ |
|
902 |
+ $context['ticket_form'] = array( |
|
903 |
+ 'form_title' => $new_reply ? $txt['shd_reply_ticket'] : $txt['shd_ticket_edit_reply'], |
|
904 |
+ 'form_action' => $scripturl . '?action=helpdesk;sa=savereply', |
|
905 |
+ 'first_msg' => $new_reply ? 0 : $ticketinfo['id_first_msg'], |
|
906 |
+ 'message' => shd_format_text($ticketinfo['body'], $ticketinfo['smileys_enabled'], ($new_reply ? '' : 'shd_reply_' . $ticketinfo['id_first_msg'])), |
|
907 |
+ 'subject' => $ticketinfo['subject'], |
|
908 |
+ 'ticket' => $context['ticket_id'], |
|
909 |
+ 'msg' => $_REQUEST['msg'], |
|
910 |
+ 'display_id' => str_pad($context['ticket_id'], 5, '0', STR_PAD_LEFT), |
|
911 |
+ 'urgency' => array( |
|
912 |
+ 'setting' => $ticketinfo['urgency'], |
|
913 |
+ ), |
|
914 |
+ 'private' => array( |
|
915 |
+ 'setting' => $ticketinfo['private'], |
|
916 |
+ 'can_change' => false, |
|
917 |
+ 'options' => array( |
|
918 |
+ 0 => 'shd_ticket_notprivate', |
|
919 |
+ 1 => 'shd_ticket_private', |
|
920 |
+ ), |
|
921 |
+ ), |
|
922 |
+ 'status' => $ticketinfo['status'], // reuse existing status for now |
|
923 |
+ 'member' => array( |
|
924 |
+ 'name' => $ticketinfo['starter_name'], |
|
925 |
+ 'id' => $ticketinfo['starter_id'], |
|
926 |
+ 'link' => shd_profile_link($ticketinfo['starter_name'], $ticketinfo['starter_id']), |
|
927 |
+ ), |
|
928 |
+ 'assigned' => array( |
|
929 |
+ 'id' => $ticketinfo['assigned_id'], |
|
930 |
+ 'name' => !empty($ticketinfo['assigned_id']) ? $ticketinfo['assigned_name'] : $txt['shd_unassigned'], |
|
931 |
+ 'link' => !empty($ticketinfo['assigned_id']) ? shd_profile_link($ticketinfo['assigned_name'], $ticketinfo['assigned_id']) : '<span class="error">' . $txt['shd_unassigned'] . '</span>', |
|
932 |
+ ), |
|
933 |
+ 'num_replies' => $ticketinfo['num_replies'], |
|
934 |
+ 'do_attach' => shd_allowed_to('shd_post_attachment'), |
|
935 |
+ 'reply' => $_POST['shd_message'], |
|
936 |
+ 'return_to_ticket' => isset($_REQUEST['goback']), |
|
937 |
+ 'disable_smileys' => !empty($_REQUEST['no_smileys']), |
|
938 |
+ ); |
|
939 |
+ $context['can_solve'] = (shd_allowed_to('shd_resolve_ticket_any') || (shd_allowed_to('shd_resolve_ticket_own') && $ticketinfo['starter_id'] == $user_info['id'])); |
|
940 |
+ $context['log_action'] = $new_reply ? 'newreply' : 'editreply'; |
|
941 |
+ $context['log_params']['subject'] = $context['ticket_form']['subject']; |
|
942 |
+ shd_posting_additional_options(); |
|
943 |
+ |
|
944 |
+ // Ticket privacy |
|
945 |
+ if (empty($modSettings['shd_privacy_display']) || $modSettings['shd_privacy_display'] == 'smart') |
|
946 |
+ $context['display_private'] = shd_allowed_to('shd_view_ticket_private_any') || shd_allowed_to('shd_alter_privacy_own') || shd_allowed_to('shd_alter_privacy_any') || $context['ticket_form']['private']['setting']; |
|
947 |
+ else |
|
948 |
+ $context['display_private'] = true; |
|
949 |
+ |
|
950 |
+ loadMemberData($ticketinfo['starter_id']); |
|
951 |
+ if (loadMemberContext($ticketinfo['starter_id'])) |
|
952 |
+ $context['ticket_form']['member']['avatar'] = $memberContext[$ticketinfo['starter_id']]['avatar']; |
|
953 |
+ |
|
954 |
+ if (!empty($ticketinfo['modified_time'])) |
|
955 |
+ { |
|
956 |
+ $context['ticket_form'] += array( |
|
957 |
+ 'modified' => array( |
|
958 |
+ 'name' => $ticketinfo['modified_name'], |
|
959 |
+ 'id' => $ticketinfo['modified_id'], |
|
960 |
+ 'time' => timeformat($ticketinfo['modified_time']), |
|
961 |
+ 'link' => shd_profile_link($ticketinfo['modified_name'], $ticketinfo['modified_id']), |
|
962 |
+ ), |
|
963 |
+ ); |
|
964 |
+ } |
|
965 |
+ |
|
966 |
+ if (isset($_REQUEST['preview'])) |
|
967 |
+ { |
|
968 |
+ $context['ticket_form']['preview'] = array( |
|
969 |
+ 'title' => $txt['shd_previewing_reply'] . ': ' . (empty($context['ticket_form']['subject']) ? '<em>' . $txt['no_subject'] . '</em>' : $context['ticket_form']['subject']), |
|
970 |
+ 'body' => shd_format_text($_POST['shd_message']), |
|
971 |
+ ); |
|
972 |
+ } |
|
973 |
+ |
|
974 |
+ shd_load_attachments(); |
|
975 |
+ |
|
976 |
+ shd_get_urgency_options($ticketinfo['is_own']); |
|
977 |
+ $context['ticket_form']['urgency']['can_change'] = false; |
|
978 |
+ |
|
979 |
+ if (!empty($ticketinfo['num_replies'])) |
|
980 |
+ shd_setup_replies($ticketinfo['id_first_msg']); |
|
981 |
+ |
|
982 |
+ // A few basic checks |
|
983 |
+ if ($context['ticket_form']['status'] == TICKET_STATUS_CLOSED) |
|
984 |
+ fatal_lang_error('shd_cannot_edit_closed', false); |
|
985 |
+ elseif ($context['ticket_form']['status'] == TICKET_STATUS_DELETED) |
|
986 |
+ fatal_lang_error('shd_cannon_edit_deleted', false); |
|
987 |
+ |
|
988 |
+ // Have there been any new replies that we missed? |
|
989 |
+ if (empty($options['no_new_reply_warning']) && isset($_REQUEST['num_replies'])) |
|
990 |
+ { |
|
991 |
+ $_REQUEST['num_replies'] = (int) $_REQUEST['num_replies']; |
|
992 |
+ $newReplies = $context['ticket_form']['num_replies'] > $_REQUEST['num_replies'] ? $context['ticket_form']['num_replies'] - $_REQUEST['num_replies'] : 0; |
|
993 |
+ |
|
994 |
+ if (!empty($newReplies)) |
|
995 |
+ { |
|
996 |
+ loadLanguage('Post'); |
|
997 |
+ if ($newReplies > 1) |
|
998 |
+ $txt['error_new_replies'] = sprintf($txt['error_new_replies'], $newReplies); |
|
999 |
+ |
|
1000 |
+ $context['shd_errors'][] = $newReplies == 1 ? 'new_reply' : 'new_replies'; |
|
1001 |
+ } |
|
1002 |
+ } |
|
1003 |
+ |
|
1004 |
+ // OK, does the user want to close this ticket? Are there any problems with that? |
|
1005 |
+ if (!empty($context['can_solve']) && !empty($_POST['resolve_ticket'])) |
|
1006 |
+ { |
|
1007 |
+ $string = shd_check_dependencies(); |
|
1008 |
+ if (!empty($string)) |
|
1009 |
+ $context['shd_errors'][] = $string; |
|
1010 |
+ } |
|
1011 |
+ |
|
1012 |
+ if (!empty($context['shd_errors']) || !empty($context['ticket_form']['preview'])) // Uh oh, something went wrong, or we're previewing |
|
1013 |
+ { |
|
1014 |
+ checkSubmitOnce('free'); |
|
1015 |
+ |
|
1016 |
+ // Anything else for redisplaying the form |
|
1017 |
+ $context['page_title'] = $txt['shd_helpdesk']; |
|
1018 |
+ $context['sub_template'] = 'reply_post'; |
|
1019 |
+ |
|
1020 |
+ shd_check_attachments(); |
|
1021 |
+ |
|
1022 |
+ // Set up the fancy editor |
|
1023 |
+ shd_postbox( |
|
1024 |
+ 'shd_message', |
|
1025 |
+ un_preparsecode($_POST['shd_message']), |
|
1026 |
+ array( |
|
1027 |
+ 'post_button' => $new_reply ? $txt['shd_reply_ticket'] : $txt['shd_ticket_edit_reply'], |
|
1028 |
+ ) |
|
1029 |
+ ); |
|
1030 |
+ |
|
1031 |
+ // Build the link tree and navigation |
|
1032 |
+ $context['linktree'][] = array( |
|
1033 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
1034 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
1035 |
+ ); |
|
1036 |
+ $context['linktree'][] = array( |
|
1037 |
+ 'name' => $txt['shd_reply_ticket'], |
|
1038 |
+ ); |
|
1039 |
+ |
|
1040 |
+ checkSubmitOnce('register'); |
|
1041 |
+ } |
|
1042 |
+ else |
|
1043 |
+ { |
|
1044 |
+ // It all worked, w00t, so let's get ready to rumble |
|
1045 |
+ $attachIDs = shd_handle_attachments(); |
|
1046 |
+ shd_clear_active_tickets($ticketinfo['id_member_started']); |
|
1047 |
+ |
|
1048 |
+ if ($new_reply) |
|
1049 |
+ { |
|
1050 |
+ // So... what is the new status? |
|
1051 |
+ $new_status = shd_determine_status('reply', $ticketinfo['starter_id'], $user_info['id']); |
|
1052 |
+ |
|
1053 |
+ // Now to add the ticket details |
|
1054 |
+ $posterOptions = array( |
|
1055 |
+ 'id' => $user_info['id'], |
|
1056 |
+ ); |
|
1057 |
+ |
|
1058 |
+ $msgOptions = array( |
|
1059 |
+ 'body' => $_POST['shd_message'], |
|
1060 |
+ 'id' => $context['ticket_form']['msg'], |
|
1061 |
+ 'smileys_enabled' => empty($context['ticket_form']['disable_smileys']), |
|
1062 |
+ 'attachments' => $attachIDs, |
|
1063 |
+ ); |
|
1064 |
+ |
|
1065 |
+ $ticketOptions = array( |
|
1066 |
+ 'id' => $context['ticket_form']['ticket'], |
|
1067 |
+ 'mark_as_read' => true, |
|
1068 |
+ 'status' => $new_status, |
|
1069 |
+ ); |
|
1070 |
+ |
|
1071 |
+ if (!empty($context['can_solve']) && !empty($_POST['resolve_ticket'])) |
|
1072 |
+ { |
|
1073 |
+ $ticketOptions['status'] = TICKET_STATUS_CLOSED; |
|
1074 |
+ shd_log_action('resolve', |
|
1075 |
+ array( |
|
1076 |
+ 'ticket' => $context['ticket_id'], |
|
1077 |
+ 'subject' => $ticketinfo['subject'], |
|
1078 |
+ ) |
|
1079 |
+ ); |
|
1080 |
+ } |
|
1081 |
+ |
|
1082 |
+ shd_create_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
1083 |
+ } |
|
1084 |
+ else |
|
1085 |
+ { |
|
1086 |
+ // Only add what has actually changed |
|
1087 |
+ // Now to add the ticket details |
|
1088 |
+ $posterOptions = array(); |
|
1089 |
+ |
|
1090 |
+ $msgOptions = array( |
|
1091 |
+ 'id' => $context['ticket_form']['msg'], |
|
1092 |
+ 'attachments' => $attachIDs, |
|
1093 |
+ ); |
|
1094 |
+ |
|
1095 |
+ $ticketOptions = array( |
|
1096 |
+ 'id' => $context['ticket_form']['ticket'], |
|
1097 |
+ ); |
|
1098 |
+ |
|
1099 |
+ if ((bool) $ticketinfo['smileys_enabled'] == $context['ticket_form']['disable_smileys']) // since one is enabled, one is 'now disable'... |
|
1100 |
+ $msgOptions['smileys_enabled'] = !$context['ticket_form']['disable_smileys']; |
|
1101 |
+ |
|
1102 |
+ if ($reply['body'] != $context['ticket_form']['reply']) |
|
1103 |
+ $msgOptions['body'] = $context['ticket_form']['reply']; |
|
1104 |
+ |
|
1105 |
+ if (isset($msgOptions['body'])) |
|
1106 |
+ $msgOptions['modified'] = array( |
|
1107 |
+ 'id' => $user_info['id'], |
|
1108 |
+ 'name' => $user_info['name'], |
|
1109 |
+ 'time' => time(), |
|
1110 |
+ ); |
|
1111 |
+ |
|
1112 |
+ if (!empty($context['can_solve']) && !empty($_POST['resolve_ticket'])) |
|
1113 |
+ { |
|
1114 |
+ $ticketOptions['status'] = TICKET_STATUS_CLOSED; |
|
1115 |
+ shd_log_action('resolve', |
|
1116 |
+ array( |
|
1117 |
+ 'ticket' => $context['ticket_id'], |
|
1118 |
+ 'subject' => $ticketinfo['subject'], |
|
1119 |
+ ) |
|
1120 |
+ ); |
|
1121 |
+ } |
|
1122 |
+ |
|
1123 |
+ // DOOOOOOOO EEEEEEEEEEET NAO! |
|
1124 |
+ shd_modify_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
1125 |
+ shd_clear_active_tickets($ticketinfo['id_member_started']); |
|
1126 |
+ } |
|
1127 |
+ |
|
1128 |
+ $context['ticket_form']['msg'] = $msgOptions['id']; |
|
1129 |
+ |
|
1130 |
+ shd_done_posting(); |
|
1131 |
+ } |
|
1132 |
+} |
|
1133 |
+ |
|
1134 |
+/** |
|
1135 |
+ * Redirects the user once a ticket has been posted or replied to. |
|
1136 |
+ * |
|
1137 |
+ * Commits the action log entry for what the user has done (since 1.1), then directs the user based on where they were and what was selected: |
|
1138 |
+ * - if 'return to ticket' was not selected, return to the front page |
|
1139 |
+ * - if it was, and we edited a reply, return to the reply |
|
1140 |
+ * - if it was select, but it was a new topic/reply, return just to the topic itself |
|
1141 |
+ * |
|
1142 |
+ * @since 1.0 |
|
1143 |
+*/ |
|
1144 |
+function shd_done_posting() |
|
1145 |
+{ |
|
1146 |
+ global $context, $smcFunc, $modSettings, $txt, $scripturl; |
|
1147 |
+ |
|
1148 |
+ // Do the log stuff |
|
1149 |
+ $context['log_params']['ticket'] = $context['ticket_id']; |
|
1150 |
+ if (!empty($context['ticket_form']['msg'])) |
|
1151 |
+ $context['log_params']['msg'] = $context['ticket_form']['msg']; |
|
1152 |
+ |
|
1153 |
+ if (!empty($context['log_action'])) |
|
1154 |
+ shd_log_action($context['log_action'], $context['log_params']); |
|
1155 |
+ |
|
1156 |
+ $thank_you = false; |
|
1157 |
+ if (!empty($modSettings['shd_thank_you_post']) && empty($context['ticket_form']['msg'])) |
|
1158 |
+ { |
|
1159 |
+ // So we're doing a "thanks for posting, here's what's next" message. Well, it's only to new tickets (not on reply) - but... should it go to everyone, or only non staff? |
|
1160 |
+ if (empty($modSettings['shd_thank_you_nonstaff']) || !shd_allowed_to('shd_staff')) |
|
1161 |
+ { |
|
1162 |
+ $thank_you = true; |
|
1163 |
+ $context['sub_template'] = 'shd_thank_posting'; |
|
1164 |
+ $context['page_icon'] = 'log_newticket.png'; |
|
1165 |
+ $context['page_title'] = $txt['shd_ticket_posted_header']; |
|
1166 |
+ |
|
1167 |
+ // Now customise it |
|
1168 |
+ $replacements = array( |
|
1169 |
+ '{membername}' => $context['user']['name'], |
|
1170 |
+ '{subject}' => $context['ticket_form']['subject'], |
|
1171 |
+ '{ticketurl}' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'], |
|
1172 |
+ '{forum_name}' => $context['forum_name_html_safe'], |
|
1173 |
+ '{newticketlink}' => $scripturl . '?action=helpdesk;sa=newticket', |
|
1174 |
+ '{helpdesklink}' => $scripturl . '?action=helpdesk;sa=main', |
|
1175 |
+ '{forumlink}' => $scripturl, |
|
1176 |
+ ); |
|
1177 |
+ $context['page_body'] = parse_bbc(str_replace(array_keys($replacements), array_values($replacements), $txt['shd_ticket_posted_body']), true); |
|
1178 |
+ } |
|
1179 |
+ } |
|
1180 |
+ |
|
1181 |
+ if (!$thank_you) |
|
1182 |
+ { |
|
1183 |
+ // After all this time... after everything we saw, after everything we lost... I have only one thing to say to you... BYE! |
|
1184 |
+ if (empty($_REQUEST['goback'])) |
|
1185 |
+ redirectexit('action=helpdesk;sa=main'); |
|
1186 |
+ elseif (!empty($context['ticket_form']['msg'])) |
|
1187 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '.msg' . $context['ticket_form']['msg'] . '#msg' . $context['ticket_form']['msg'], $context['browser']['is_ie']); |
|
1188 |
+ else |
|
1189 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
1190 |
+ } |
|
1191 |
+} |
|
1192 |
+ |
|
1193 |
+function shd_setup_replies($first_msg) |
|
1194 |
+{ |
|
1195 |
+ global $reply_request, $context, $smcFunc, $sourcedir, $modSettings, $settings; |
|
1196 |
+ |
|
1197 |
+ $context['ticket_form']['do_replies'] = false; |
|
1198 |
+ $context['can_quote'] = false; |
|
1199 |
+ |
|
1200 |
+ $context['can_see_ip'] = shd_allowed_to('shd_staff'); |
|
1201 |
+ |
|
1202 |
+ // OK, we're done with the ticket's own data. Now for replies. |
|
1203 |
+ $context['get_replies'] = 'shd_prepare_reply_context'; |
|
1204 |
+ $query = shd_db_query('', ' |
|
1205 |
+ SELECT id_msg, id_member, modified_member |
|
1206 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
1207 |
+ WHERE id_ticket = {int:ticket} |
|
1208 |
+ AND message_status = {int:msg_normal} |
|
1209 |
+ AND id_msg > {int:first_msg}' . ((empty($context['ticket_form']['msg']) || $context['ticket_form']['msg'] == $context['ticket_form']['first_msg']) ? '' : ' |
|
1210 |
+ AND id_msg < {int:reply_msg}') . ' |
|
1211 |
+ ORDER BY id_msg DESC |
|
1212 |
+ LIMIT 10', |
|
1213 |
+ array( |
|
1214 |
+ 'ticket' => $context['ticket_id'], |
|
1215 |
+ 'msg_normal' => MSG_STATUS_NORMAL, |
|
1216 |
+ 'first_msg' => $first_msg, |
|
1217 |
+ 'reply_msg' => !empty($context['ticket_form']['msg']) ? $context['ticket_form']['msg'] : 0, |
|
1218 |
+ ) |
|
1219 |
+ ); |
|
1220 |
+ |
|
1221 |
+ $messages = array(); |
|
1222 |
+ $posters = array(); |
|
1223 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
1224 |
+ { |
|
1225 |
+ if (!empty($row['id_member'])) |
|
1226 |
+ $posters[] = $row['id_member']; |
|
1227 |
+ |
|
1228 |
+ if (!empty($row['modified_member'])) |
|
1229 |
+ $posters[] = $row['modified_member']; |
|
1230 |
+ |
|
1231 |
+ $messages[] = $row['id_msg']; |
|
1232 |
+ } |
|
1233 |
+ $smcFunc['db_free_result']($query); |
|
1234 |
+ |
|
1235 |
+ $posters = array_unique($posters); |
|
1236 |
+ |
|
1237 |
+ $context['shd_is_staff'] = array(); |
|
1238 |
+ |
|
1239 |
+ if (!empty($messages)) |
|
1240 |
+ { |
|
1241 |
+ $context['ticket_form']['do_replies'] = true; |
|
1242 |
+ |
|
1243 |
+ // Get the poster data |
|
1244 |
+ if (!empty($posters)) |
|
1245 |
+ { |
|
1246 |
+ loadMemberData($posters); |
|
1247 |
+ |
|
1248 |
+ // Are they current team members? |
|
1249 |
+ $team = array_intersect($posters, shd_members_allowed_to('shd_staff')); |
|
1250 |
+ |
|
1251 |
+ foreach ($team as $member) |
|
1252 |
+ $context['shd_is_staff'][$member] = true; |
|
1253 |
+ } |
|
1254 |
+ |
|
1255 |
+ $reply_request = shd_db_query('', ' |
|
1256 |
+ SELECT |
|
1257 |
+ id_msg, poster_time, poster_ip, id_member, modified_time, modified_name, modified_member, body, |
|
1258 |
+ smileys_enabled, poster_name, poster_email |
|
1259 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
1260 |
+ WHERE id_msg IN ({array_int:message_list}) |
|
1261 |
+ ORDER BY id_msg DESC', |
|
1262 |
+ array( |
|
1263 |
+ 'message_list' => $messages, |
|
1264 |
+ ) |
|
1265 |
+ ); |
|
1266 |
+ |
|
1267 |
+ // Can we have a quote button in the replies? If so, we also need the relevant JS instantiation |
|
1268 |
+ if (!empty($modSettings['shd_allow_ticket_bbc'])) |
|
1269 |
+ { |
|
1270 |
+ $context['can_quote'] = true; |
|
1271 |
+ $context['html_headers'] .= ' |
|
1272 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
1273 |
+ var oQuickReply = new QuickReply({ |
|
1274 |
+ bDefaultCollapsed: false, |
|
1275 |
+ iTicketId: ' . $context['ticket_id'] . ', |
|
1276 |
+ iStart: ' . $context['start'] . ', |
|
1277 |
+ sScriptUrl: smf_scripturl, |
|
1278 |
+ sImagesUrl: "' . $settings['images_url'] . '", |
|
1279 |
+ sContainerId: "quickReplyOptions", |
|
1280 |
+ sImageId: "quickReplyExpand", |
|
1281 |
+ sImageCollapsed: "collapse.gif", |
|
1282 |
+ sImageExpanded: "expand.gif", |
|
1283 |
+ sJumpAnchor: "quickreply", |
|
1284 |
+ sHeaderId: "quickreplyheader", |
|
1285 |
+ sFooterId: "quickreplyfooter" |
|
1286 |
+ }); |
|
1287 |
+ // ]' . ']></script>'; |
|
1288 |
+ } |
|
1289 |
+ } |
|
1290 |
+ else |
|
1291 |
+ { |
|
1292 |
+ $reply_request = false; |
|
1293 |
+ $context['first_message'] = 0; |
|
1294 |
+ $context['first_new_message'] = false; |
|
1295 |
+ } |
|
1296 |
+} |
|
1297 |
+ |
|
1298 |
+function shd_postbox($id, $message, $buttons, $width = '70%') |
|
1299 |
+{ |
|
1300 |
+ global $context, $txt, $modSettings; |
|
1301 |
+ $editorOptions = array( |
|
1302 |
+ 'id' => $id, |
|
1303 |
+ 'value' => $message, |
|
1304 |
+ 'labels' => $buttons, |
|
1305 |
+ 'preview_type' => 0, |
|
1306 |
+ 'width' => $width, |
|
1307 |
+ 'disable_smiley_box' => empty($modSettings['shd_allow_ticket_bbc']) || $context['ticket_form']['disable_smileys'], |
|
1308 |
+ ); |
|
1309 |
+ if (empty($modSettings['shd_allow_ticket_bbc'])) |
|
1310 |
+ $modSettings['disable_wysiwyg'] = 1; |
|
1311 |
+ |
|
1312 |
+ // Hide any disabled tags. |
|
1313 |
+ if (!empty($modSettings['shd_enabled_bbc'])) |
|
1314 |
+ { |
|
1315 |
+ $enabled_tags = explode(',', $modSettings['shd_enabled_bbc']); |
|
1316 |
+ $disabled_tags = array(); |
|
1317 |
+ |
|
1318 |
+ // Loop through all the tags there are in this forum, and and each disabled tag to our 'hide-list'. |
|
1319 |
+ foreach (parse_bbc(false) AS $tag) |
|
1320 |
+ { |
|
1321 |
+ if (!in_array($tag['tag'], $enabled_tags) || $modSettings['shd_enabled_bbc'] == 'shd_all_tags_disabled') |
|
1322 |
+ $disabled_tags[] = $tag['tag']; |
|
1323 |
+ } |
|
1324 |
+ |
|
1325 |
+ // Add them to the editors hide var. |
|
1326 |
+ $modSettings['disabledBBC'] = implode(',', $disabled_tags); |
|
1327 |
+ } |
|
1328 |
+ |
|
1329 |
+ create_control_richedit($editorOptions); |
|
1330 |
+ $context['post_box_name'] = $editorOptions['id']; |
|
1331 |
+ |
|
1332 |
+ // Are there any restrictions on uploading attachments? |
|
1333 |
+ $context['allowed_extensions'] = strtr($modSettings['attachmentExtensions'], array(',' => ', ')); |
|
1334 |
+ $context['attachment_restrictions'] = array(); |
|
1335 |
+ |
|
1336 |
+ if (!empty($modSettings['attachmentNumPerPostLimit']) && $modSettings['shd_attachments_mode'] != 'ticket') |
|
1337 |
+ $context['attachment_restrictions'][] = sprintf($txt['attach_restrict_attachmentNumPerPostLimit'], $modSettings['attachmentNumPerPostLimit']); |
|
1338 |
+ |
|
1339 |
+ if (!empty($modSettings['attachmentPostLimit']) && $modSettings['shd_attachments_mode'] != 'ticket') |
|
1340 |
+ $context['attachment_restrictions'][] = sprintf($txt['attach_restrict_attachmentPostLimit'], $modSettings['attachmentPostLimit']); |
|
1341 |
+ |
|
1342 |
+ if (!empty($modSettings['attachmentSizeLimit'])) |
|
1343 |
+ $context['attachment_restrictions'][] = sprintf($txt['attach_restrict_attachmentSizeLimit'], $modSettings['attachmentSizeLimit']); |
|
1344 |
+} |
|
1345 |
+ |
|
1346 |
+function shd_prepare_reply_context() |
|
1347 |
+{ |
|
1348 |
+ global $settings, $txt, $modSettings, $scripturl, $options, $user_info, $smcFunc; |
|
1349 |
+ global $memberContext, $context, $reply_request; |
|
1350 |
+ |
|
1351 |
+ if (empty($reply_request)) |
|
1352 |
+ return false; |
|
1353 |
+ |
|
1354 |
+ $message = $smcFunc['db_fetch_assoc']($reply_request); |
|
1355 |
+ if (!$message) |
|
1356 |
+ { |
|
1357 |
+ $smcFunc['db_free_result']($reply_request); |
|
1358 |
+ return false; |
|
1359 |
+ } |
|
1360 |
+ |
|
1361 |
+ if (!loadMemberContext($message['id_member'], true)) |
|
1362 |
+ { |
|
1363 |
+ // Notice this information isn't used anywhere else.... |
|
1364 |
+ $memberContext[$message['id_member']]['name'] = $message['poster_name']; |
|
1365 |
+ $memberContext[$message['id_member']]['id'] = 0; |
|
1366 |
+ $memberContext[$message['id_member']]['group'] = $txt['guest_title']; |
|
1367 |
+ $memberContext[$message['id_member']]['link'] = $message['poster_name']; |
|
1368 |
+ $memberContext[$message['id_member']]['email'] = $message['poster_email']; |
|
1369 |
+ $memberContext[$message['id_member']]['show_email'] = showEmailAddress(true, 0); |
|
1370 |
+ $memberContext[$message['id_member']]['is_guest'] = true; |
|
1371 |
+ $memberContext[$message['id_member']]['group_stars'] = ''; |
|
1372 |
+ } |
|
1373 |
+ $memberContext[$message['id_member']]['ip'] = $message['poster_ip']; |
|
1374 |
+ |
|
1375 |
+ censorText($message['body']); |
|
1376 |
+ $message['body'] = shd_format_text($message['body'], $message['smileys_enabled'], 'shd_reply_' . $message['id_msg']); |
|
1377 |
+ |
|
1378 |
+ $output = array( |
|
1379 |
+ 'id' => $message['id_msg'], |
|
1380 |
+ 'member' => &$memberContext[$message['id_member']], |
|
1381 |
+ 'time' => timeformat($message['poster_time']), |
|
1382 |
+ 'timestamp' => forum_time(true, $message['poster_time']), |
|
1383 |
+ 'body' => $message['body'], |
|
1384 |
+ 'is_staff' => !empty($context['shd_is_staff'][$message['id_member']]), |
|
1385 |
+ 'can_edit' => shd_allowed_to('shd_edit_reply_any') || ($message['id_member'] == $user_info['id'] && shd_allowed_to('shd_edit_reply_own')), |
|
1386 |
+ 'ip_address' => $message['poster_ip'], |
|
1387 |
+ ); |
|
1388 |
+ |
|
1389 |
+ if (!empty($message['modified_time'])) |
|
1390 |
+ { |
|
1391 |
+ $output['modified'] = array( |
|
1392 |
+ 'time' => timeformat($message['modified_time']), |
|
1393 |
+ 'timestamp' => forum_time(true, $message['modified_time']), |
|
1394 |
+ 'id' => !empty($user_profile[$message['modified_member']]) ? $message['modified_member'] : 0, |
|
1395 |
+ 'name' => !empty($user_profile[$message['modified_member']]) ? $user_profile[$message['modified_member']]['real_name'] : $message['modified_name'], |
|
1396 |
+ ); |
|
1397 |
+ $output['modified']['link'] = shd_profile_link($output['modified']['name'], $output['modified']['id']); |
|
1398 |
+ } |
|
1399 |
+ |
|
1400 |
+ return $output; |
|
1401 |
+} |
|
1402 |
+ |
|
1403 |
+function shd_load_attachments() |
|
1404 |
+{ |
|
1405 |
+ global $smcFunc, $context, $modSettings; |
|
1406 |
+ |
|
1407 |
+ if (empty($context['current_attachments'])) |
|
1408 |
+ $context['current_attachments'] = array(); |
|
1409 |
+ |
|
1410 |
+ $context['ticket_attach'][$modSettings['shd_attachments_mode']] = array(); |
|
1411 |
+ |
|
1412 |
+ // Get existing attachments |
|
1413 |
+ $query = shd_db_query('', ' |
|
1414 |
+ SELECT a.id_attach, a.filename |
|
1415 |
+ FROM {db_prefix}attachments AS a |
|
1416 |
+ INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (a.id_attach = hda.id_attach) |
|
1417 |
+ WHERE ' . ($modSettings['shd_attachments_mode'] == 'ticket' ? 'hda.id_ticket = {int:ticket}' : 'hda.id_msg = {int:msg}') . ' |
|
1418 |
+ AND a.attachment_type != {int:thumb} |
|
1419 |
+ ORDER BY hda.id_attach', |
|
1420 |
+ array( |
|
1421 |
+ 'msg' => $context['ticket_form']['msg'], |
|
1422 |
+ 'ticket' => $context['ticket_id'], |
|
1423 |
+ 'thumb' => 3, |
|
1424 |
+ ) |
|
1425 |
+ ); |
|
1426 |
+ |
|
1427 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
1428 |
+ $context['current_attachments'][] = array( |
|
1429 |
+ 'id' => $row['id_attach'], |
|
1430 |
+ 'name' => preg_replace('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($row['filename'])), |
|
1431 |
+ ); |
|
1432 |
+ |
|
1433 |
+ $smcFunc['db_free_result']($query); |
|
1434 |
+} |
|
1435 |
+ |
|
1436 |
+function shd_check_attachments() |
|
1437 |
+{ |
|
1438 |
+ global $modSettings, $smcFunc, $context, $user_info, $txt; |
|
1439 |
+ |
|
1440 |
+ if (empty($context['current_attachments'])) |
|
1441 |
+ $context['current_attachments'] = array(); |
|
1442 |
+ |
|
1443 |
+ if (shd_allowed_to('shd_post_attachment')) |
|
1444 |
+ { |
|
1445 |
+ if (empty($_SESSION['temp_attachments'])) |
|
1446 |
+ $_SESSION['temp_attachments'] = array(); |
|
1447 |
+ |
|
1448 |
+ if (!empty($modSettings['currentAttachmentUploadDir'])) |
|
1449 |
+ { |
|
1450 |
+ if (!is_array($modSettings['attachmentUploadDir'])) |
|
1451 |
+ $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); |
|
1452 |
+ |
|
1453 |
+ // Just use the current path for temp files. |
|
1454 |
+ $current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']]; |
|
1455 |
+ } |
|
1456 |
+ else |
|
1457 |
+ $current_attach_dir = $modSettings['attachmentUploadDir']; |
|
1458 |
+ |
|
1459 |
+ // If this isn't a new post, check the current attachments. |
|
1460 |
+ if (($modSettings['shd_attachments_mode'] == 'ticket' && !empty($context['ticket_id'])) || isset($context['ticket_form']['msg'])) |
|
1461 |
+ { |
|
1462 |
+ $request = shd_db_query('', ' |
|
1463 |
+ SELECT COUNT(*), SUM(size) |
|
1464 |
+ FROM {db_prefix}attachments AS a |
|
1465 |
+ INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (a.id_attach = hda.id_attach) |
|
1466 |
+ WHERE ' . ($modSettings['shd_attachments_mode'] == 'ticket' ? 'hda.id_ticket = {int:ticket}' : 'hda.id_msg = {int:msg}') . ' |
|
1467 |
+ AND attachment_type = {int:attachment_type}', |
|
1468 |
+ array( |
|
1469 |
+ 'msg' => $context['ticket_form']['msg'], |
|
1470 |
+ 'ticket' => empty($context['ticket_id']) ? 0 : $context['ticket_id'], |
|
1471 |
+ 'attachment_type' => 0, |
|
1472 |
+ ) |
|
1473 |
+ ); |
|
1474 |
+ list ($quantity, $total_size) = $smcFunc['db_fetch_row']($request); |
|
1475 |
+ $smcFunc['db_free_result']($request); |
|
1476 |
+ } |
|
1477 |
+ else |
|
1478 |
+ { |
|
1479 |
+ $quantity = 0; |
|
1480 |
+ $total_size = 0; |
|
1481 |
+ } |
|
1482 |
+ |
|
1483 |
+ $temp_start = 0; |
|
1484 |
+ |
|
1485 |
+ if (!empty($_SESSION['temp_attachments'])) |
|
1486 |
+ foreach ($_SESSION['temp_attachments'] as $attachID => $name) |
|
1487 |
+ { |
|
1488 |
+ $temp_start++; |
|
1489 |
+ |
|
1490 |
+ if (preg_match('~^post_tmp_' . $user_info['id'] . '_\d+$~', $attachID) == 0) |
|
1491 |
+ { |
|
1492 |
+ unset($_SESSION['temp_attachments'][$attachID]); |
|
1493 |
+ continue; |
|
1494 |
+ } |
|
1495 |
+ |
|
1496 |
+ if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) |
|
1497 |
+ { |
|
1498 |
+ $deleted_attachments = true; |
|
1499 |
+ unset($_SESSION['temp_attachments'][$attachID]); |
|
1500 |
+ @unlink($current_attach_dir . '/' . $attachID); |
|
1501 |
+ continue; |
|
1502 |
+ } |
|
1503 |
+ |
|
1504 |
+ $quantity++; |
|
1505 |
+ $total_size += filesize($current_attach_dir . '/' . $attachID); |
|
1506 |
+ |
|
1507 |
+ $context['current_attachments'][] = array( |
|
1508 |
+ 'name' => $name, |
|
1509 |
+ 'id' => $attachID, |
|
1510 |
+ ); |
|
1511 |
+ } |
|
1512 |
+ |
|
1513 |
+ if (!empty($_POST['attach_del'])) |
|
1514 |
+ { |
|
1515 |
+ $del_temp = array(); |
|
1516 |
+ foreach ($_POST['attach_del'] as $i => $dummy) |
|
1517 |
+ $del_temp[$i] = (int) $dummy; |
|
1518 |
+ |
|
1519 |
+ foreach ($context['current_attachments'] as $k => $dummy) |
|
1520 |
+ if (!in_array($dummy['id'], $del_temp)) |
|
1521 |
+ { |
|
1522 |
+ $context['current_attachments'][$k]['unchecked'] = true; |
|
1523 |
+ $deleted_attachments = !isset($deleted_attachments) || is_bool($deleted_attachments) ? 1 : $deleted_attachments + 1; |
|
1524 |
+ $quantity--; |
|
1525 |
+ } |
|
1526 |
+ } |
|
1527 |
+ |
|
1528 |
+ if (!empty($_FILES)) |
|
1529 |
+ { |
|
1530 |
+ $_FILES = array_reverse($_FILES); |
|
1531 |
+ foreach ($_FILES as $uplfile) |
|
1532 |
+ { |
|
1533 |
+ if ($uplfile['name'] == '') |
|
1534 |
+ continue; |
|
1535 |
+ |
|
1536 |
+ if (!is_uploaded_file($uplfile['tmp_name']) || (@ini_get('open_basedir') == '' && !file_exists($uplfile['tmp_name']))) |
|
1537 |
+ { |
|
1538 |
+ checkSubmitOnce('free'); |
|
1539 |
+ fatal_lang_error('attach_timeout', 'critical'); |
|
1540 |
+ } |
|
1541 |
+ |
|
1542 |
+ if (!empty($modSettings['attachmentSizeLimit']) && $uplfile['size'] > $modSettings['attachmentSizeLimit'] * 1024) |
|
1543 |
+ { |
|
1544 |
+ checkSubmitOnce('free'); |
|
1545 |
+ fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit'])); |
|
1546 |
+ } |
|
1547 |
+ |
|
1548 |
+ $quantity++; |
|
1549 |
+ if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit'] && $modSettings['shd_attachments_mode'] != 'ticket') |
|
1550 |
+ { |
|
1551 |
+ checkSubmitOnce('free'); |
|
1552 |
+ fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit'])); |
|
1553 |
+ } |
|
1554 |
+ |
|
1555 |
+ $total_size += $uplfile['size']; |
|
1556 |
+ if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024) |
|
1557 |
+ { |
|
1558 |
+ checkSubmitOnce('free'); |
|
1559 |
+ fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit'])); |
|
1560 |
+ } |
|
1561 |
+ |
|
1562 |
+ if (!empty($modSettings['attachmentCheckExtensions'])) |
|
1563 |
+ { |
|
1564 |
+ if (!in_array(strtolower(substr(strrchr($uplfile['name'], '.'), 1)), explode(',', strtolower($modSettings['attachmentExtensions'])))) |
|
1565 |
+ { |
|
1566 |
+ checkSubmitOnce('free'); |
|
1567 |
+ fatal_error($uplfile['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false); |
|
1568 |
+ } |
|
1569 |
+ } |
|
1570 |
+ |
|
1571 |
+ if (!empty($modSettings['attachmentDirSizeLimit'])) |
|
1572 |
+ { |
|
1573 |
+ // Make sure the directory isn't full. |
|
1574 |
+ $dirSize = 0; |
|
1575 |
+ $dir = @opendir($current_attach_dir) or fatal_lang_error('cant_access_upload_path', 'critical'); |
|
1576 |
+ while ($file = readdir($dir)) |
|
1577 |
+ { |
|
1578 |
+ if ($file == '.' || $file == '..') |
|
1579 |
+ continue; |
|
1580 |
+ |
|
1581 |
+ if (preg_match('~^post_tmp_\d+_\d+$~', $file) != 0) |
|
1582 |
+ { |
|
1583 |
+ // Temp file is more than 5 hours old! |
|
1584 |
+ if (filemtime($current_attach_dir . '/' . $file) < time() - 18000) |
|
1585 |
+ @unlink($current_attach_dir . '/' . $file); |
|
1586 |
+ continue; |
|
1587 |
+ } |
|
1588 |
+ |
|
1589 |
+ $dirSize += filesize($current_attach_dir . '/' . $file); |
|
1590 |
+ } |
|
1591 |
+ closedir($dir); |
|
1592 |
+ |
|
1593 |
+ // Too big! Maybe you could zip it or something... |
|
1594 |
+ if ($uplfile['size'] + $dirSize > $modSettings['attachmentDirSizeLimit'] * 1024) |
|
1595 |
+ fatal_lang_error('ran_out_of_space'); |
|
1596 |
+ } |
|
1597 |
+ |
|
1598 |
+ if (!is_writable($current_attach_dir)) |
|
1599 |
+ fatal_lang_error('attachments_no_write', 'critical'); |
|
1600 |
+ |
|
1601 |
+ $attachID = 'post_tmp_' . $user_info['id'] . '_' . $temp_start++; |
|
1602 |
+ $_SESSION['temp_attachments'][$attachID] = basename($uplfile['name']); |
|
1603 |
+ $context['current_attachments'][] = array( |
|
1604 |
+ 'name' => basename($uplfile['name']), |
|
1605 |
+ 'id' => $attachID, |
|
1606 |
+ 'approved' => 1, |
|
1607 |
+ ); |
|
1608 |
+ |
|
1609 |
+ $destName = $current_attach_dir . '/' . $attachID; |
|
1610 |
+ |
|
1611 |
+ if (!move_uploaded_file($uplfile['tmp_name'], $destName)) |
|
1612 |
+ fatal_lang_error('attach_timeout', 'critical'); |
|
1613 |
+ @chmod($destName, 0644); |
|
1614 |
+ } |
|
1615 |
+ } |
|
1616 |
+ } |
|
1617 |
+ |
|
1618 |
+ // So, while we're here, how many attachments can we have? |
|
1619 |
+ $context['ticket_form']['num_allowed_attachments'] = empty($modSettings['attachmentNumPerPostLimit']) || $modSettings['shd_attachments_mode'] == 'ticket' ? -1 : $modSettings['attachmentNumPerPostLimit']; |
|
1620 |
+} |
|
1621 |
+ |
|
1622 |
+function shd_handle_attachments() |
|
1623 |
+{ |
|
1624 |
+ global $modSettings, $smcFunc, $context, $user_info, $sourcedir, $txt; |
|
1625 |
+ |
|
1626 |
+ if (!shd_allowed_to('shd_post_attachment')) |
|
1627 |
+ return; |
|
1628 |
+ |
|
1629 |
+ $attachIDs = array(); |
|
1630 |
+ |
|
1631 |
+ // Check if they are trying to delete any current attachments.... |
|
1632 |
+ if (isset($_POST['attach_del'])) |
|
1633 |
+ { |
|
1634 |
+ $del_temp = array(); |
|
1635 |
+ foreach ($_POST['attach_del'] as $i => $dummy) |
|
1636 |
+ $del_temp[$i] = (int) $dummy; |
|
1637 |
+ |
|
1638 |
+ // First, get them from the other table |
|
1639 |
+ $query = shd_db_query('', ' |
|
1640 |
+ SELECT a.id_attach |
|
1641 |
+ FROM {db_prefix}attachments AS a |
|
1642 |
+ INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (hda.id_attach = a.id_attach) |
|
1643 |
+ WHERE ' . ($modSettings['shd_attachments_mode'] == 'ticket' ? 'hda.id_ticket = {int:ticket}' : 'hda.id_msg = {int:msg}'), |
|
1644 |
+ array( |
|
1645 |
+ 'msg' => $context['ticket_form']['msg'], |
|
1646 |
+ 'ticket' => $context['ticket_id'], |
|
1647 |
+ ) |
|
1648 |
+ ); |
|
1649 |
+ |
|
1650 |
+ $attachments = array(); |
|
1651 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
1652 |
+ $attachments[] = $row['id_attach']; |
|
1653 |
+ |
|
1654 |
+ $smcFunc['db_free_result']($query); |
|
1655 |
+ |
|
1656 |
+ // OK, so attachments = full list of attachments on this post, del_temp is list of ones to keep, so look for the ones that aren't in both lists |
|
1657 |
+ $del_temp = array_diff($attachments, $del_temp); |
|
1658 |
+ |
|
1659 |
+ if (!empty($del_temp)) |
|
1660 |
+ { |
|
1661 |
+ $filenames = array(); |
|
1662 |
+ // Before deleting, get the names for the log |
|
1663 |
+ $query = $smcFunc['db_query']('', ' |
|
1664 |
+ SELECT filename |
|
1665 |
+ FROM {db_prefix}attachments |
|
1666 |
+ WHERE id_attach IN ({array_int:attach}) |
|
1667 |
+ ORDER BY id_attach', |
|
1668 |
+ array( |
|
1669 |
+ 'attach' => $del_temp, |
|
1670 |
+ ) |
|
1671 |
+ ); |
|
1672 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
1673 |
+ $filenames[] = htmlspecialchars($row[0]); |
|
1674 |
+ |
|
1675 |
+ if (!empty($filenames)) |
|
1676 |
+ $context['log_params']['att_removed'] = $filenames; |
|
1677 |
+ |
|
1678 |
+ // Now you can delete |
|
1679 |
+ require_once($sourcedir . '/ManageAttachments.php'); |
|
1680 |
+ $attachmentQuery = array( |
|
1681 |
+ 'attachment_type' => 0, |
|
1682 |
+ 'id_msg' => 0, |
|
1683 |
+ 'id_attach' => $del_temp, |
|
1684 |
+ ); |
|
1685 |
+ removeAttachments($attachmentQuery); |
|
1686 |
+ } |
|
1687 |
+ } |
|
1688 |
+ |
|
1689 |
+ // ...or attach a new file... |
|
1690 |
+ if (!empty($_FILES) || !empty($_SESSION['temp_attachments'])) |
|
1691 |
+ { |
|
1692 |
+ if (!empty($FILES)) |
|
1693 |
+ $_FILES = array_reverse($_FILES); |
|
1694 |
+ |
|
1695 |
+ shd_is_allowed_to('shd_post_attachment'); |
|
1696 |
+ |
|
1697 |
+ // Make sure we're uploading to the right place. |
|
1698 |
+ if (!empty($modSettings['currentAttachmentUploadDir'])) |
|
1699 |
+ { |
|
1700 |
+ if (!is_array($modSettings['attachmentUploadDir'])) |
|
1701 |
+ $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); |
|
1702 |
+ |
|
1703 |
+ // The current directory, of course! |
|
1704 |
+ $current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']]; |
|
1705 |
+ } |
|
1706 |
+ else |
|
1707 |
+ $current_attach_dir = $modSettings['attachmentUploadDir']; |
|
1708 |
+ |
|
1709 |
+ // If this isn't a new post, check the current attachments. |
|
1710 |
+ if (isset($_REQUEST['msg']) || !empty($context['ticket_id'])) |
|
1711 |
+ { |
|
1712 |
+ $request = shd_db_query('', ' |
|
1713 |
+ SELECT COUNT(*), SUM(size) |
|
1714 |
+ FROM {db_prefix}attachments AS a |
|
1715 |
+ INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (a.id_attach = hda.id_attach) |
|
1716 |
+ WHERE ' . ($modSettings['shd_attachments_mode'] == 'ticket' ? 'hda.id_ticket = {int:ticket}' : 'hda.id_msg = {int:msg}') . ' |
|
1717 |
+ AND attachment_type = {int:attachment_type}', |
|
1718 |
+ array( |
|
1719 |
+ 'msg' => $context['ticket_form']['msg'], |
|
1720 |
+ 'ticket' => $context['ticket_id'], |
|
1721 |
+ 'attachment_type' => 0, |
|
1722 |
+ ) |
|
1723 |
+ ); |
|
1724 |
+ list ($quantity, $total_size) = $smcFunc['db_fetch_row']($request); |
|
1725 |
+ $smcFunc['db_free_result']($request); |
|
1726 |
+ } |
|
1727 |
+ else |
|
1728 |
+ { |
|
1729 |
+ $quantity = 0; |
|
1730 |
+ $total_size = 0; |
|
1731 |
+ } |
|
1732 |
+ |
|
1733 |
+ if (!empty($_SESSION['temp_attachments'])) |
|
1734 |
+ foreach ($_SESSION['temp_attachments'] as $attachID => $name) |
|
1735 |
+ { |
|
1736 |
+ if (preg_match('~^post_tmp_' . $user_info['id'] . '_\d+$~', $attachID) == 0) |
|
1737 |
+ continue; |
|
1738 |
+ |
|
1739 |
+ if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) |
|
1740 |
+ { |
|
1741 |
+ unset($_SESSION['temp_attachments'][$attachID]); |
|
1742 |
+ @unlink($current_attach_dir . '/' . $attachID); |
|
1743 |
+ continue; |
|
1744 |
+ } |
|
1745 |
+ |
|
1746 |
+ $_FILES['attachment' . $attachID]['tmp_name'] = $attachID; |
|
1747 |
+ $_FILES['attachment' . $attachID]['name'] = $name; |
|
1748 |
+ $_FILES['attachment' . $attachID]['size'] = filesize($current_attach_dir . '/' . $attachID); |
|
1749 |
+ list ($_FILES['attachment' . $attachID]['width'], $_FILES['attachment' . $attachID]['height']) = @getimagesize($current_attach_dir . '/' . $attachID); |
|
1750 |
+ |
|
1751 |
+ unset($_SESSION['temp_attachments'][$attachID]); |
|
1752 |
+ } |
|
1753 |
+ |
|
1754 |
+ foreach ($_FILES as $uplfile) |
|
1755 |
+ { |
|
1756 |
+ if ($uplfile['name'] == '') |
|
1757 |
+ continue; |
|
1758 |
+ |
|
1759 |
+ // Have we reached the maximum number of files we are allowed? |
|
1760 |
+ $quantity++; |
|
1761 |
+ |
|
1762 |
+ $file_limit = (!empty($modSettings['attachmentNumPerPostLimit']) && $modSettings['shd_attachments_mode'] != 'ticket') ? $modSettings['attachmentNumPerPostLimit'] : $quantity + 1; |
|
1763 |
+ |
|
1764 |
+ if ($quantity > $file_limit) |
|
1765 |
+ { |
|
1766 |
+ checkSubmitOnce('free'); |
|
1767 |
+ fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit'])); |
|
1768 |
+ } |
|
1769 |
+ |
|
1770 |
+ // Check the total upload size for this post... |
|
1771 |
+ $total_size += $uplfile['size']; |
|
1772 |
+ $size_limit = (!empty($modSettings['attachmentPostLimit']) && $modSettings['shd_attachments_mode'] != 'ticket') ? $modSettings['attachmentPostLimit'] * 1024 : $total_size + 1024; |
|
1773 |
+ |
|
1774 |
+ if ($total_size > $size_limit) |
|
1775 |
+ { |
|
1776 |
+ checkSubmitOnce('free'); |
|
1777 |
+ fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit'])); |
|
1778 |
+ } |
|
1779 |
+ |
|
1780 |
+ $attachmentOptions = array( |
|
1781 |
+ 'post' => 0, |
|
1782 |
+ 'poster' => $user_info['id'], |
|
1783 |
+ 'name' => $uplfile['name'], |
|
1784 |
+ 'tmp_name' => $uplfile['tmp_name'], |
|
1785 |
+ 'size' => $uplfile['size'], |
|
1786 |
+ ); |
|
1787 |
+ |
|
1788 |
+ if (createAttachment($attachmentOptions)) |
|
1789 |
+ { |
|
1790 |
+ $attachIDs[] = $attachmentOptions['id']; |
|
1791 |
+ if (!empty($attachmentOptions['thumb'])) |
|
1792 |
+ $attachIDs[] = $attachmentOptions['thumb']; |
|
1793 |
+ |
|
1794 |
+ $context['log_params']['att_added'][] = htmlspecialchars($attachmentOptions['name']); |
|
1795 |
+ } |
|
1796 |
+ else |
|
1797 |
+ { |
|
1798 |
+ if (in_array('could_not_upload', $attachmentOptions['errors'])) |
|
1799 |
+ { |
|
1800 |
+ checkSubmitOnce('free'); |
|
1801 |
+ fatal_lang_error('attach_timeout', 'critical'); |
|
1802 |
+ } |
|
1803 |
+ if (in_array('too_large', $attachmentOptions['errors'])) |
|
1804 |
+ { |
|
1805 |
+ checkSubmitOnce('free'); |
|
1806 |
+ fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit'])); |
|
1807 |
+ } |
|
1808 |
+ if (in_array('bad_extension', $attachmentOptions['errors'])) |
|
1809 |
+ { |
|
1810 |
+ checkSubmitOnce('free'); |
|
1811 |
+ fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . strtr($modSettings['attachmentExtensions'], array(',' => ', ')) . '.', false); |
|
1812 |
+ } |
|
1813 |
+ if (in_array('directory_full', $attachmentOptions['errors'])) |
|
1814 |
+ { |
|
1815 |
+ checkSubmitOnce('free'); |
|
1816 |
+ fatal_lang_error('ran_out_of_space', 'critical'); |
|
1817 |
+ } |
|
1818 |
+ if (in_array('bad_filename', $attachmentOptions['errors'])) |
|
1819 |
+ { |
|
1820 |
+ checkSubmitOnce('free'); |
|
1821 |
+ fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['restricted_filename'] . '.', 'critical'); |
|
1822 |
+ } |
|
1823 |
+ if (in_array('taken_filename', $attachmentOptions['errors'])) |
|
1824 |
+ { |
|
1825 |
+ checkSubmitOnce('free'); |
|
1826 |
+ fatal_lang_error('filename_exists'); |
|
1827 |
+ } |
|
1828 |
+ } |
|
1829 |
+ } |
|
1830 |
+ } |
|
1831 |
+ |
|
1832 |
+ return $attachIDs; |
|
1833 |
+} |
|
1834 |
+ |
|
1835 |
+/** |
|
1836 |
+ * Establishes the items for the 'additional options' in the posting screen. |
|
1837 |
+ * |
|
1838 |
+ * @since 1.1 |
|
1839 |
+*/ |
|
1840 |
+function shd_posting_additional_options() |
|
1841 |
+{ |
|
1842 |
+ global $context, $modSettings, $txt, $options, $settings, $new_ticket; |
|
1843 |
+ |
|
1844 |
+ $context['ticket_form']['additional_opts'] = array( |
|
1845 |
+ 'goback' => array( |
|
1846 |
+ 'checked' => !empty($context['ticket_form']['return_to_ticket']) || !empty($options['return_to_post']), |
|
1847 |
+ 'text' => $txt['shd_back_to_ticket'], |
|
1848 |
+ 'show' => ($new_ticket && !empty($modSettings['shd_thank_you_post'])) ? false : true, |
|
1849 |
+ ), |
|
1850 |
+ 'no_smileys' => array( |
|
1851 |
+ 'checked' => !empty($context['ticket_form']['disable_smileys']), |
|
1852 |
+ 'text' => $txt['shd_disable_smileys_post'], |
|
1853 |
+ 'show' => !empty($modSettings['shd_allow_ticket_smileys']), |
|
1854 |
+ ), |
|
1855 |
+ 'resolve_ticket' => array( |
|
1856 |
+ 'checked' => !empty($_POST['resolve_ticket']), |
|
1857 |
+ 'text' => $txt['shd_resolve_this_ticket'], |
|
1858 |
+ 'show' => !empty($context['can_solve']), |
|
1859 |
+ ), |
|
1860 |
+ ); |
|
1861 |
+ |
|
1862 |
+ if (!empty($modSettings['shd_hook_postingopts'])) |
|
1863 |
+ { |
|
1864 |
+ $functions = explode(',', $modSettings['shd_hook_postingopts']); |
|
1865 |
+ foreach ($functions as $function) |
|
1866 |
+ { |
|
1867 |
+ if (is_callable($function)) |
|
1868 |
+ $function(); // It's all in $context |
|
1869 |
+ } |
|
1870 |
+ } |
|
1871 |
+} |
|
1872 |
+ |
|
1873 |
+/** |
|
1874 |
+ * Checks dependencies of the current ticket to see if it can be closed. |
|
1875 |
+ * |
|
1876 |
+ * @return string Returns empty string if the ticket has no dependency issues, or returns the id for $txt to use as error message. |
|
1877 |
+ * @since 1.1 |
|
1878 |
+*/ |
|
1879 |
+function shd_check_dependencies() |
|
1880 |
+{ |
|
1881 |
+ global $context, $smcFunc; |
|
1882 |
+ |
|
1883 |
+ // OK, so what about any children related tickets that are still open? Eeek, could be awkward. |
|
1884 |
+ $query = shd_db_query('', ' |
|
1885 |
+ SELECT COUNT(hdt.id_ticket) |
|
1886 |
+ FROM {db_prefix}helpdesk_relationships AS rel |
|
1887 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (rel.secondary_ticket = hdt.id_ticket) |
|
1888 |
+ WHERE rel.primary_ticket = {int:ticket} |
|
1889 |
+ AND rel.rel_type = {int:parent} |
|
1890 |
+ AND hdt.status NOT IN ({array_int:closed_status})', |
|
1891 |
+ array( |
|
1892 |
+ 'ticket' => $context['ticket_id'], |
|
1893 |
+ 'parent' => RELATIONSHIP_ISPARENT, |
|
1894 |
+ 'closed_status' => array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED), |
|
1895 |
+ ) |
|
1896 |
+ ); |
|
1897 |
+ list($count_children) = $smcFunc['db_fetch_row']($query); |
|
1898 |
+ $smcFunc['db_free_result']($query); |
|
1899 |
+ if (!empty($count_children)) |
|
1900 |
+ return 'shd_cannot_resolve_children'; |
|
1901 |
+ |
|
1902 |
+ return ''; |
|
1903 |
+} |
|
1904 |
+?> |
|
0 | 1905 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,563 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.1 # |
|
17 |
+# File Info: SimpleDesk-Profile.php / 1.1 # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles all aspects of the SimpleDesk profile section. Everything from user preferences |
|
22 |
+ * to personal stats as well as sensitive information (site URL, contact email, etc.). |
|
23 |
+ * |
|
24 |
+ * @package source |
|
25 |
+ * @since 1.1 |
|
26 |
+ */ |
|
27 |
+ |
|
28 |
+if (!defined('SMF')) |
|
29 |
+ die('If only you could draw like a drunken monkey...'); |
|
30 |
+ |
|
31 |
+function shd_profile_main($memID) |
|
32 |
+{ |
|
33 |
+ global $context, $txt, $scripturl, $sourcedir, $user_info, $settings, $user_profile, $modSettings; |
|
34 |
+ |
|
35 |
+ // Load the profile details |
|
36 |
+ loadTemplate('sd_template/SimpleDesk-Profile', array('helpdesk', 'helpdesk_admin')); |
|
37 |
+ shd_load_language('SimpleDeskProfile'); |
|
38 |
+ $context['shd_preferences'] = shd_load_user_prefs(); |
|
39 |
+ shd_load_plugin_files('hdprofile'); |
|
40 |
+ shd_load_plugin_langfiles('hdprofile'); |
|
41 |
+ |
|
42 |
+ $context['page_title'] = $txt['shd_profile_area'] . ' - ' . $txt['shd_profile_main']; |
|
43 |
+ $context['sub_template'] = 'shd_profile_main'; |
|
44 |
+ |
|
45 |
+ $subActions = array( |
|
46 |
+ 'helpdesk' => 'shd_profile_frontpage', |
|
47 |
+ 'hd_prefs' => 'shd_profile_preferences', |
|
48 |
+ 'hd_showtickets' => 'shd_profile_show_tickets', |
|
49 |
+ 'hd_permissions' => 'shd_profile_permissions', |
|
50 |
+ 'hd_actionlog' => 'shd_profile_actionlog', |
|
51 |
+ ); |
|
52 |
+ |
|
53 |
+ $context['shd_profile_menu'] = array( |
|
54 |
+ array( |
|
55 |
+ 'image' => 'user.png', |
|
56 |
+ 'link' => $scripturl . '?action=profile;u=' . $context['member']['id'] . ';area=helpdesk', |
|
57 |
+ 'text' => $txt['shd_profile_home'], |
|
58 |
+ 'show' => true, |
|
59 |
+ ), |
|
60 |
+ array( |
|
61 |
+ 'image' => 'preferences.png', |
|
62 |
+ 'link' => $scripturl . '?action=profile;u=' . $context['member']['id'] . ';area=hd_prefs', |
|
63 |
+ 'text' => $txt['shd_profile_preferences'], |
|
64 |
+ 'show' => true, // !!! |
|
65 |
+ ), |
|
66 |
+ array( |
|
67 |
+ 'image' => 'ticket.png', |
|
68 |
+ 'link' => $scripturl . '?action=profile;u=' . $context['member']['id'] . ';area=hd_showtickets', |
|
69 |
+ 'text' => $txt['shd_profile_show_tickets'], |
|
70 |
+ 'show' => true, |
|
71 |
+ ), |
|
72 |
+ array( |
|
73 |
+ 'image' => 'permissions.png', |
|
74 |
+ 'link' => $scripturl . '?action=profile;u=' . $context['member']['id'] . ';area=hd_permissions', |
|
75 |
+ 'text' => $txt['shd_profile_permissions'], |
|
76 |
+ 'show' => !empty($context['helpdesk_menu']['areas']['hd_permissions']['enabled']), // we already figured this out once before |
|
77 |
+ ), |
|
78 |
+ array( |
|
79 |
+ 'image' => 'log.png', |
|
80 |
+ 'link' => $scripturl . '?action=profile;u=' . $context['member']['id'] . ';area=hd_actionlog', |
|
81 |
+ 'text' => $txt['shd_profile_actionlog'], |
|
82 |
+ 'show' => !empty($context['helpdesk_menu']['areas']['hd_actionlog']['enabled']), // we figured this too |
|
83 |
+ ), |
|
84 |
+ array( |
|
85 |
+ 'image' => 'go_to_helpdesk.png', |
|
86 |
+ 'link' => $scripturl . '?action=helpdesk;sa=main', |
|
87 |
+ 'text' => $txt['shd_profile_go_to_helpdesk'], |
|
88 |
+ 'show' => true, |
|
89 |
+ ), |
|
90 |
+ ); |
|
91 |
+ |
|
92 |
+ // Int hooks - after we basically set everything up (so it's manipulatable by the hook, but before we do the last bits of finalisation) |
|
93 |
+ if (!empty($modSettings['shd_hook_hdprofile'])) |
|
94 |
+ { |
|
95 |
+ $functions = explode(',', $modSettings['shd_hook_hdprofile']); |
|
96 |
+ foreach ($functions as $function) |
|
97 |
+ { |
|
98 |
+ if (is_callable($function)) |
|
99 |
+ $function($subActions, $memID); // these should be picked up by reference in the called function or it won't do anything! (everything else is in $context) |
|
100 |
+ } |
|
101 |
+ } |
|
102 |
+ |
|
103 |
+ // Make sure the menu is configured appropriately |
|
104 |
+ $context['shd_profile_menu'][count($context['shd_profile_menu'])-1]['is_last'] = true; |
|
105 |
+ |
|
106 |
+ $_REQUEST['area'] = isset($_REQUEST['area']) && isset($subActions[$_REQUEST['area']]) ? $_REQUEST['area'] : 'helpdesk'; |
|
107 |
+ $context['sub_action'] = $_REQUEST['area']; |
|
108 |
+ |
|
109 |
+ $subActions[$_REQUEST['area']]($memID); |
|
110 |
+ |
|
111 |
+ // Maintenance mode? If it were, the helpdesk is considered inactive for the purposes of everything to all but those without admin-helpdesk rights - but we must have them if we're here! |
|
112 |
+ if (!empty($modSettings['shd_maintenance_mode'])) |
|
113 |
+ { |
|
114 |
+ loadTemplate('sd_template/SimpleDesk'); |
|
115 |
+ $temp_layers = $context['template_layers']; |
|
116 |
+ $context['template_layers'] = array(); |
|
117 |
+ foreach ($temp_layers as $layer) |
|
118 |
+ { |
|
119 |
+ $context['template_layers'][] = $layer; |
|
120 |
+ if ($layer == 'body') |
|
121 |
+ $context['template_layers'][] = 'shd_maintenance'; |
|
122 |
+ } |
|
123 |
+ } |
|
124 |
+ |
|
125 |
+ $context['template_layers'][] = 'shd_profile_navigation'; |
|
126 |
+} |
|
127 |
+ |
|
128 |
+function shd_profile_frontpage($memID) |
|
129 |
+{ |
|
130 |
+ global $context, $txt, $scripturl, $sourcedir, $user_info, $smcFunc; |
|
131 |
+ |
|
132 |
+ $context['page_title'] = $txt['shd_profile_area'] . ' - ' . $txt['shd_profile_main']; |
|
133 |
+ $context['sub_template'] = 'shd_profile_main'; |
|
134 |
+ |
|
135 |
+ $query = shd_db_query('', ' |
|
136 |
+ SELECT COUNT(id_ticket) AS count, status |
|
137 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
138 |
+ WHERE id_member_started = {int:member} |
|
139 |
+ GROUP BY status', |
|
140 |
+ array( |
|
141 |
+ 'member' => $memID, |
|
142 |
+ ) |
|
143 |
+ ); |
|
144 |
+ |
|
145 |
+ $context['shd_numtickets'] = 0; |
|
146 |
+ $context['shd_numopentickets'] = 0; |
|
147 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
148 |
+ { |
|
149 |
+ $context['shd_numtickets'] += $row['count']; |
|
150 |
+ if ($row['status'] != TICKET_STATUS_CLOSED && $row['status'] != TICKET_STATUS_DELETED) |
|
151 |
+ $context['shd_numopentickets'] += $row['count']; |
|
152 |
+ } |
|
153 |
+ |
|
154 |
+ $context['shd_numtickets'] = comma_format($context['shd_numtickets']); |
|
155 |
+ $context['shd_numopentickets'] = comma_format($context['shd_numopentickets']); |
|
156 |
+ |
|
157 |
+ $smcFunc['db_free_result']($query); |
|
158 |
+ |
|
159 |
+ |
|
160 |
+ $query = shd_db_query('', ' |
|
161 |
+ SELECT COUNT(id_ticket) |
|
162 |
+ FROM {db_prefix}helpdesk_tickets |
|
163 |
+ WHERE id_member_assigned = {int:member}', |
|
164 |
+ array( |
|
165 |
+ 'member' => $memID, |
|
166 |
+ ) |
|
167 |
+ ); |
|
168 |
+ |
|
169 |
+ list($context['shd_numassigned']) = $smcFunc['db_fetch_row']($query); |
|
170 |
+ $smcFunc['db_free_result']($query); |
|
171 |
+ $context['shd_numassigned'] = comma_format($context['shd_numassigned']); |
|
172 |
+ |
|
173 |
+ $context['can_post_proxy'] = shd_allowed_to('shd_new_ticket') && shd_allowed_to('shd_post_proxy'); // since it's YOUR permissions, whether you can post on behalf of this user! |
|
174 |
+} |
|
175 |
+ |
|
176 |
+function shd_profile_preferences($memID) |
|
177 |
+{ |
|
178 |
+ global $context, $txt, $scripturl, $sourcedir, $user_info, $smcFunc; |
|
179 |
+ |
|
180 |
+ $context['page_title'] = $txt['shd_profile_area'] . ' - ' . $txt['shd_profile_preferences']; |
|
181 |
+ $context['sub_template'] = 'shd_profile_preferences'; |
|
182 |
+ |
|
183 |
+ // Load the list of options and the user's individual opts |
|
184 |
+ $context['shd_preferences_options'] = shd_load_user_prefs(false); |
|
185 |
+ $context['member']['shd_preferences'] = shd_load_user_prefs($memID); |
|
186 |
+ |
|
187 |
+ foreach ($context['member']['shd_preferences'] as $pref => $value) |
|
188 |
+ { |
|
189 |
+ if (isset($context['shd_preferences_options']['prefs'][$pref])) |
|
190 |
+ { |
|
191 |
+ $thisgroup = $context['shd_preferences_options']['prefs'][$pref]['group']; |
|
192 |
+ if (!isset($context['shd_preferences_options']['groups'][$thisgroup])) |
|
193 |
+ $context['shd_preferences_options']['groups'][$thisgroup] = array(); |
|
194 |
+ |
|
195 |
+ $context['shd_preferences_options']['groups'][$thisgroup]['groups'][] = $pref; |
|
196 |
+ } |
|
197 |
+ } |
|
198 |
+ |
|
199 |
+ foreach ($context['shd_preferences_options']['groups'] as $group => $groupinfo) |
|
200 |
+ { |
|
201 |
+ if (empty($groupinfo)) |
|
202 |
+ unset($context['shd_preferences_options']['groups'][$group]); |
|
203 |
+ } |
|
204 |
+ |
|
205 |
+ // Are we saving any options? |
|
206 |
+ if (isset($_GET['save'])) |
|
207 |
+ { |
|
208 |
+ $changes = array( |
|
209 |
+ 'add' => array(), |
|
210 |
+ 'remove' => array(), |
|
211 |
+ ); |
|
212 |
+ // Step through each of the options we know are ours and check if they're defined here |
|
213 |
+ foreach ($context['member']['shd_preferences'] as $pref => $current_value) |
|
214 |
+ { |
|
215 |
+ $master_opt = $context['shd_preferences_options']['prefs'][$pref]; |
|
216 |
+ |
|
217 |
+ $new_value = $master_opt['default']; |
|
218 |
+ switch ($master_opt['type']) |
|
219 |
+ { |
|
220 |
+ case 'check': |
|
221 |
+ $new_value = !empty($_POST[$pref]) ? 1 : 0; |
|
222 |
+ break; |
|
223 |
+ } |
|
224 |
+ |
|
225 |
+ if ($master_opt['default'] == $new_value) |
|
226 |
+ { |
|
227 |
+ // The new value is the same as default. If we already had non-default, remove the non-default value. |
|
228 |
+ if ($new_value != $current_value) |
|
229 |
+ $changes['remove'][] = $pref; |
|
230 |
+ } |
|
231 |
+ else |
|
232 |
+ { |
|
233 |
+ if ($new_value != $current_value) |
|
234 |
+ $changes['add'][] = array($memID, $pref, (string) $new_value); |
|
235 |
+ } |
|
236 |
+ |
|
237 |
+ // Finally, make sure whatever's in the array is actually what we've asked for |
|
238 |
+ $context['member']['shd_preferences'][$pref] = $new_value; |
|
239 |
+ } |
|
240 |
+ |
|
241 |
+ // Clean up the database and apply all the changes |
|
242 |
+ if (!empty($changes['add'])) |
|
243 |
+ { |
|
244 |
+ $smcFunc['db_insert']('replace', |
|
245 |
+ '{db_prefix}helpdesk_preferences', |
|
246 |
+ array( |
|
247 |
+ 'id_member' => 'int', 'variable' => 'string', 'value' => 'string', |
|
248 |
+ ), |
|
249 |
+ $changes['add'], |
|
250 |
+ array( |
|
251 |
+ 'id_member', 'variable', |
|
252 |
+ ) |
|
253 |
+ ); |
|
254 |
+ } |
|
255 |
+ |
|
256 |
+ if (!empty($changes['remove'])) |
|
257 |
+ { |
|
258 |
+ $smcFunc['db_query']('', ' |
|
259 |
+ DELETE FROM {db_prefix}helpdesk_preferences |
|
260 |
+ WHERE id_member = {int:member} |
|
261 |
+ AND variable IN ({array_string:prefs})', |
|
262 |
+ array( |
|
263 |
+ 'member' => $memID, |
|
264 |
+ 'prefs' => $changes['remove'], |
|
265 |
+ ) |
|
266 |
+ ); |
|
267 |
+ } |
|
268 |
+ } |
|
269 |
+} |
|
270 |
+ |
|
271 |
+function shd_profile_show_tickets($memID) |
|
272 |
+{ |
|
273 |
+ global $txt, $user_info, $scripturl, $modSettings, $smcFunc, $board, $user_profile, $context; |
|
274 |
+ |
|
275 |
+ $context['page_title'] = $txt['shd_profile_show_tickets'] . ' - ' . $user_profile[$memID]['real_name']; |
|
276 |
+ $context['sub_template'] = 'shd_profile_show_tickets'; |
|
277 |
+ $context['start'] = (int) $_REQUEST['start']; |
|
278 |
+ |
|
279 |
+ // The time has come to choose: Tickets, or just replies? |
|
280 |
+ $context['can_haz_replies'] = isset($_GET['sa']) && $_GET['sa'] == 'replies' ? true : false; |
|
281 |
+ |
|
282 |
+ // Navigation |
|
283 |
+ $context['show_tickets_navigation'] = array( |
|
284 |
+ 'tickets' => array('text' => 'shd_profile_show_tickets', 'lang' => true, 'url' => $scripturl . '?action=profile;u=' . $memID . ';area=hd_showtickets;sa=tickets'), |
|
285 |
+ 'replies' => array('text' => 'shd_profile_show_replies', 'lang' => true, 'url' => $scripturl . '?action=profile;u=' . $memID . ';area=hd_showtickets;sa=replies'), |
|
286 |
+ ); |
|
287 |
+ |
|
288 |
+ // The active button. |
|
289 |
+ if($context['can_haz_replies']) |
|
290 |
+ $context['show_tickets_navigation']['replies']['active'] = true; |
|
291 |
+ else |
|
292 |
+ $context['show_tickets_navigation']['tickets']['active'] = true; |
|
293 |
+ |
|
294 |
+ // "That still only counts as one!" |
|
295 |
+ if ($context['can_haz_replies']) |
|
296 |
+ $request = shd_db_query('', ' |
|
297 |
+ SELECT COUNT(hdtr.id_msg) |
|
298 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
299 |
+ LEFT JOIN {db_prefix}helpdesk_tickets AS hdt ON(hdtr.id_ticket = hdt.id_ticket) |
|
300 |
+ WHERE hdtr.id_member = {int:user} |
|
301 |
+ AND {query_see_ticket}', |
|
302 |
+ array( |
|
303 |
+ 'user' => $memID, |
|
304 |
+ ) |
|
305 |
+ ); |
|
306 |
+ else |
|
307 |
+ $request = shd_db_query('', ' |
|
308 |
+ SELECT COUNT(hdt.id_ticket) |
|
309 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
310 |
+ WHERE hdt.id_member_started = {int:user} |
|
311 |
+ AND {query_see_ticket}', |
|
312 |
+ array( |
|
313 |
+ 'user' => $memID, |
|
314 |
+ ) |
|
315 |
+ ); |
|
316 |
+ list ($item_count) = $smcFunc['db_fetch_row']($request); |
|
317 |
+ $smcFunc['db_free_result']($request); |
|
318 |
+ |
|
319 |
+ // Max? Max? Where are you? |
|
320 |
+ $request = shd_db_query('', ' |
|
321 |
+ SELECT MIN(hdtr.id_msg), MAX(hdtr.id_msg) |
|
322 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
323 |
+ LEFT JOIN {db_prefix}helpdesk_tickets AS hdt ON(hdtr.id_ticket = hdt.id_ticket) |
|
324 |
+ WHERE hdtr.id_member = {int:user} |
|
325 |
+ AND {query_see_ticket}', |
|
326 |
+ array( |
|
327 |
+ 'user' => $memID, |
|
328 |
+ ) |
|
329 |
+ ); |
|
330 |
+ list ($min_msg_member, $max_msg_member) = $smcFunc['db_fetch_row']($request); |
|
331 |
+ $smcFunc['db_free_result']($request); |
|
332 |
+ |
|
333 |
+ $reverse = false; |
|
334 |
+ $max_index = (int) $modSettings['defaultMaxMessages']; |
|
335 |
+ |
|
336 |
+ // A little page index to help us along the way! |
|
337 |
+ $context['page_index'] = shd_no_expand_pageindex($scripturl . '?action=profile;u=' . $memID . ';area=hd_showtickets' . ($context['can_haz_replies'] ? ';sa=replies' : ''), $context['start'], $item_count, $max_index); |
|
338 |
+ $context['current_page'] = $context['start'] / $max_index; |
|
339 |
+ |
|
340 |
+ // Reverse the query if we're past 50% of the pages for better performance. |
|
341 |
+ $start = $context['start']; |
|
342 |
+ $reverse = $_REQUEST['start'] > $item_count / 2; |
|
343 |
+ if ($reverse) // Turn it all around! |
|
344 |
+ { |
|
345 |
+ $max_index = $item_count < $context['start'] + $modSettings['defaultMaxMessages'] + 1 && $item_count > $context['start'] ? $item_count - $context['start'] : (int) $modSettings['defaultMaxMessages']; |
|
346 |
+ $start = $item_count < $context['start'] + $modSettings['defaultMaxMessages'] + 1 || $item_count < $context['start'] + $modSettings['defaultMaxMessages'] ? 0 : $item_count - $context['start'] - $modSettings['defaultMaxMessages']; |
|
347 |
+ } |
|
348 |
+ |
|
349 |
+ // Bring 'em to me! |
|
350 |
+ $looped = false; |
|
351 |
+ while (true) |
|
352 |
+ { |
|
353 |
+ if ($context['can_haz_replies']) |
|
354 |
+ { |
|
355 |
+ $request = shd_db_query('', ' |
|
356 |
+ SELECT |
|
357 |
+ hdtr.id_member, hdt.subject, hdt.id_first_msg, |
|
358 |
+ hdtr.body, hdtr.smileys_enabled, hdtr.poster_time, hdtr.id_ticket, hdtr.id_msg |
|
359 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
360 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdt.id_ticket = hdtr.id_ticket) |
|
361 |
+ WHERE hdtr.id_member = {int:user} |
|
362 |
+ AND {query_see_ticket} |
|
363 |
+ ORDER BY hdtr.id_msg ' . ($reverse ? 'ASC' : 'DESC') . ' |
|
364 |
+ LIMIT ' . $start . ', ' . $max_index, |
|
365 |
+ array( |
|
366 |
+ 'user' => $memID, |
|
367 |
+ ) |
|
368 |
+ ); |
|
369 |
+ } |
|
370 |
+ else |
|
371 |
+ { |
|
372 |
+ $request = shd_db_query('', ' |
|
373 |
+ SELECT |
|
374 |
+ hdt.id_member_started, hdt.id_first_msg, hdt.id_last_msg, hdt.subject, |
|
375 |
+ hdtr.body, hdtr.smileys_enabled, hdtr.poster_time, hdtr.id_ticket, hdtr.id_msg |
|
376 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
377 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdtr.id_msg = hdt.id_first_msg) |
|
378 |
+ WHERE hdt.id_member_started = {int:user} |
|
379 |
+ AND {query_see_ticket} |
|
380 |
+ ORDER BY hdt.id_first_msg ' . ($reverse ? 'ASC' : 'DESC') . ' |
|
381 |
+ LIMIT ' . $start . ', ' . $max_index, |
|
382 |
+ array( |
|
383 |
+ 'user' => $memID, |
|
384 |
+ ) |
|
385 |
+ ); |
|
386 |
+ } |
|
387 |
+ |
|
388 |
+ // Hold it! |
|
389 |
+ if ($smcFunc['db_num_rows']($request) === $max_index || $looped) |
|
390 |
+ break; |
|
391 |
+ $looped = true; |
|
392 |
+ } |
|
393 |
+ |
|
394 |
+ // Start counting at the number of the first message displayed. |
|
395 |
+ $counter = $reverse ? $context['start'] + $max_index + 1 : $context['start']; |
|
396 |
+ $context['items'] = array(); |
|
397 |
+ while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
398 |
+ { |
|
399 |
+ // @[�]@�}**@}$�!!! |
|
400 |
+ censorText($row['body']); |
|
401 |
+ censorText($row['subject']); |
|
402 |
+ |
|
403 |
+ // Do the parsing dance! Eh... |
|
404 |
+ $row['body'] = shd_format_text($row['body'], $row['smileys_enabled'], 'shd_reply_' . $row['id_msg']); |
|
405 |
+ |
|
406 |
+ // And finally, store the load of cr--... the results! |
|
407 |
+ $context['items'][$counter += $reverse ? -1 : 1] = array( |
|
408 |
+ 'body' => $row['body'], |
|
409 |
+ 'counter' => $counter, |
|
410 |
+ 'alternate' => $counter % 2, |
|
411 |
+ 'ticket' => $row['id_ticket'], |
|
412 |
+ 'subject' => $row['subject'], |
|
413 |
+ 'start' => 'msg' . $row['id_msg'], |
|
414 |
+ 'time' => timeformat($row['poster_time']), |
|
415 |
+ 'timestamp' => forum_time(true, $row['poster_time']), |
|
416 |
+ 'msg' => $row['id_msg'], |
|
417 |
+ 'is_ticket' => empty($context['can_haz_replies']) ? true : ($row['id_msg'] == $row['id_first_msg']), |
|
418 |
+ ); |
|
419 |
+ } |
|
420 |
+ // Freedom. |
|
421 |
+ $smcFunc['db_free_result']($request); |
|
422 |
+ |
|
423 |
+ // Head's up, feet's down. |
|
424 |
+ if ($reverse) |
|
425 |
+ $context['items'] = array_reverse($context['items'], true); |
|
426 |
+} |
|
427 |
+ |
|
428 |
+function shd_profile_permissions($memID) |
|
429 |
+{ |
|
430 |
+ global $context, $txt, $scripturl, $sourcedir, $user_info, $smcFunc, $user_profile, $settings; |
|
431 |
+ |
|
432 |
+ shd_load_language('SimpleDeskPermissions'); |
|
433 |
+ |
|
434 |
+ $context['page_title'] = $txt['shd_profile_area'] . ' - ' . $txt['shd_profile_permissions']; |
|
435 |
+ $context['sub_template'] = 'shd_profile_permissions'; |
|
436 |
+ |
|
437 |
+ // OK, start by figuring out what permissions are out there. |
|
438 |
+ shd_load_all_permission_sets(); |
|
439 |
+ |
|
440 |
+ // 1. What groups is this user in? And we need all their groups, which in 'profile' mode, SMF helpfully puts into $user_profile[$memID] for us. |
|
441 |
+ $groups = empty($user_profile[$memID]['additional_groups']) ? array() : explode(',', $user_profile[$memID]['additional_groups']); |
|
442 |
+ $groups[] = $user_profile[$memID]['id_group']; |
|
443 |
+ |
|
444 |
+ // Sanitise this little lot |
|
445 |
+ foreach ($groups as $key => $value) |
|
446 |
+ $groups[$key] = (int) $value; |
|
447 |
+ |
|
448 |
+ // 1b. Hang on, is this user special? Are they, dare I suggest it, a full blown forum admin? |
|
449 |
+ $context['member']['has_all_permissions'] = in_array(1, $groups); |
|
450 |
+ if ($context['member']['has_all_permissions']) |
|
451 |
+ return; |
|
452 |
+ |
|
453 |
+ // 2. Get group colours and names. |
|
454 |
+ $context['membergroups'][0] = array( |
|
455 |
+ 'group_name' => $txt['membergroups_members'], |
|
456 |
+ 'color' => '', |
|
457 |
+ 'link' => $txt['membergroups_members'], |
|
458 |
+ ); |
|
459 |
+ |
|
460 |
+ $query = $smcFunc['db_query']('', ' |
|
461 |
+ SELECT mg.id_group, mg.group_name, mg.online_color |
|
462 |
+ FROM {db_prefix}membergroups AS mg |
|
463 |
+ WHERE mg.id_group IN ({array_int:groups}) |
|
464 |
+ ORDER BY id_group', |
|
465 |
+ array( |
|
466 |
+ 'groups' => $groups, |
|
467 |
+ ) |
|
468 |
+ ); |
|
469 |
+ |
|
470 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
471 |
+ { |
|
472 |
+ $context['membergroups'][$row['id_group']] = array( |
|
473 |
+ 'name' => $row['group_name'], |
|
474 |
+ 'color' => $row['online_color'], |
|
475 |
+ 'link' => '<a href="' . $scripturl . '?action=groups;sa=members;group=' . $row['id_group'] . '"' . (empty($row['online_color']) ? '' : ' style="color: ' . $row['online_color'] . ';"') . '>' . $row['group_name'] . '</a>', |
|
476 |
+ ); |
|
477 |
+ } |
|
478 |
+ |
|
479 |
+ $smcFunc['db_free_result']($query); |
|
480 |
+ |
|
481 |
+ // 3. Get roles that apply to this user, and figure out their groups as we go. |
|
482 |
+ $query = $smcFunc['db_query']('', ' |
|
483 |
+ SELECT hdrg.id_role, hdrg.id_group, hdr.template, hdr.role_name |
|
484 |
+ FROM {db_prefix}helpdesk_role_groups AS hdrg |
|
485 |
+ INNER JOIN {db_prefix}helpdesk_roles AS hdr ON (hdrg.id_role = hdr.id_role) |
|
486 |
+ WHERE hdrg.id_group IN ({array_int:groups}) |
|
487 |
+ ORDER BY hdrg.id_role, hdrg.id_group', |
|
488 |
+ array( |
|
489 |
+ 'groups' => $groups, |
|
490 |
+ ) |
|
491 |
+ ); |
|
492 |
+ |
|
493 |
+ $role_permissions = array(); |
|
494 |
+ $roles = array(); |
|
495 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
496 |
+ { |
|
497 |
+ if (empty($role_permissions[$row['id_role']])) |
|
498 |
+ $role_permissions[$row['id_role']] = $context['shd_permissions']['roles'][$row['template']]['permissions']; |
|
499 |
+ |
|
500 |
+ if (!empty($roles[$row['id_role']])) |
|
501 |
+ $roles[$row['id_role']]['groups'][] = $row['id_group']; |
|
502 |
+ else |
|
503 |
+ $roles[$row['id_role']] = array( |
|
504 |
+ 'name' => $row['role_name'], |
|
505 |
+ 'template' => $row['template'], |
|
506 |
+ 'groups' => array($row['id_group']), |
|
507 |
+ ); |
|
508 |
+ } |
|
509 |
+ |
|
510 |
+ $smcFunc['db_free_result']($query); |
|
511 |
+ |
|
512 |
+ $context['member_roles'] = $roles; |
|
513 |
+ |
|
514 |
+ // 4. Now the hard bit. Figure out what permissions they have. |
|
515 |
+ $context['member_permissions'] = array( |
|
516 |
+ 'allowed' => array(), |
|
517 |
+ 'denied' => array(), |
|
518 |
+ ); |
|
519 |
+ |
|
520 |
+ if (!empty($roles)) |
|
521 |
+ { |
|
522 |
+ $query = $smcFunc['db_query']('', ' |
|
523 |
+ SELECT id_role, permission, add_type |
|
524 |
+ FROM {db_prefix}helpdesk_role_permissions' . (empty($role) ? '' : ' |
|
525 |
+ WHERE id_role IN ({array_int:roles})'), |
|
526 |
+ array( |
|
527 |
+ 'roles' => array_keys($roles), |
|
528 |
+ ) |
|
529 |
+ ); |
|
530 |
+ |
|
531 |
+ while($row = $smcFunc['db_fetch_assoc']($query)) |
|
532 |
+ $role_permissions[$row['id_role']][$row['permission']] = $row['add_type']; // if it's defined in the DB it's somehow different to what the template so replace the template |
|
533 |
+ } |
|
534 |
+ |
|
535 |
+ foreach ($role_permissions as $role_id => $permission_set) |
|
536 |
+ { |
|
537 |
+ foreach ($permission_set as $permission => $state) |
|
538 |
+ { |
|
539 |
+ if ($state == ROLEPERM_ALLOW) |
|
540 |
+ $context['member_permissions']['allowed'][$permission][] = $role_id; |
|
541 |
+ elseif ($state == ROLEPERM_DENY) |
|
542 |
+ $context['member_permissions']['denied'][$permission][] = $role_id; |
|
543 |
+ } |
|
544 |
+ } |
|
545 |
+} |
|
546 |
+ |
|
547 |
+function shd_profile_actionlog($memID) |
|
548 |
+{ |
|
549 |
+ global $context, $txt, $scripturl, $sourcedir, $user_info, $settings; |
|
550 |
+ |
|
551 |
+ loadTemplate('sd_template/SimpleDesk-Profile'); |
|
552 |
+ shd_load_language('SimpleDeskProfile'); |
|
553 |
+ |
|
554 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskAdmin.php'); |
|
555 |
+ $context['action_log'] = shd_load_action_log_entries(0, 10, '', '', 'la.id_member = ' . $memID); |
|
556 |
+ $context['action_log_count'] = shd_count_action_log_entries('la.id_member = ' . $memID); |
|
557 |
+ $context['action_full_log'] = allowedTo('admin_forum') || shd_allowed_to('admin_helpdesk'); |
|
558 |
+ |
|
559 |
+ $context['page_title'] = $txt['shd_profile_area'] . ' - ' . $txt['shd_profile_actionlog']; |
|
560 |
+ $context['sub_template'] = 'shd_profile_actionlog'; |
|
561 |
+ |
|
562 |
+} |
|
563 |
+?> |
|
0 | 564 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,326 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-SSI.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles data gathering primarily for SSI.php purposes. It expects Subs-SimpleDesk.php to have been required as this |
|
22 |
+ * will still be needed for helpdesk permissions checks and base functions. |
|
23 |
+ * |
|
24 |
+ * The function names imply who is expected to be the target, ssi_user functions are those intended for users, ssi_staff for staff |
|
25 |
+ * members, such as ssi_userTickets() is primarily for displaying the tickets started by a given user, ssi_staffAssignedTickets() |
|
26 |
+ * for all the tickets assigned to a given member of staff. |
|
27 |
+ * |
|
28 |
+ * No support for displaying these through SHTML is provided, nor is any planned. |
|
29 |
+ * |
|
30 |
+ * Unlike other SimpleDesk functions, these use a SSI style camel casing. |
|
31 |
+ * |
|
32 |
+ * @package source |
|
33 |
+ * @since 1.1 |
|
34 |
+ */ |
|
35 |
+ |
|
36 |
+if (!defined('SMF')) |
|
37 |
+ die('Hacking attempt...'); |
|
38 |
+ |
|
39 |
+/** |
|
40 |
+ * Gets a list of the tickets currently open that are a given user's (subject to ticket visibility). |
|
41 |
+ * |
|
42 |
+ * @param int $started_by The user id whose tickets you want to examine, defaults to the current user. |
|
43 |
+ * @param int $limit The number of tickets to limit to, default 10. |
|
44 |
+ * @param string $output_method Set to 'echo' for displaying content, set to 'array' to simply return data. |
|
45 |
+ * @return array An array of data, more details under the underlying function {@link ssi_getSDTickets()} |
|
46 |
+ * @since 1.1 |
|
47 |
+*/ |
|
48 |
+function ssi_userTickets($started_by = 0, $limit = 10, $output_method = 'echo') |
|
49 |
+{ |
|
50 |
+ global $user_info; |
|
51 |
+ if (empty($started_by)) |
|
52 |
+ $started_by = $user_info['id']; |
|
53 |
+ |
|
54 |
+ $limit = (int) $limit; |
|
55 |
+ if (empty($limit)) |
|
56 |
+ return; |
|
57 |
+ |
|
58 |
+ $query_where = 'hdt.id_member_started = {int:started}'; |
|
59 |
+ |
|
60 |
+ $query_where_params = array( |
|
61 |
+ 'started' => $started_by, |
|
62 |
+ ); |
|
63 |
+ |
|
64 |
+ return ssi_getSDTickets($query_where, $query_where_params, $limit, 'hdt.id_ticket ASC', $output_method); |
|
65 |
+} |
|
66 |
+ |
|
67 |
+/** |
|
68 |
+ * Gets a list of the tickets currently open that are assigned to the current user (presumably staff, subject to ticket visibility). |
|
69 |
+ * |
|
70 |
+ * @param int $assignee The user id whose tickets whose assigned tickets you want to examine, defaults to the current user. |
|
71 |
+ * @param int $limit The number of tickets to limit to, default 10. |
|
72 |
+ * @param string $output_method Set to 'echo' for displaying content, set to 'array' to simply return data. |
|
73 |
+ * @return array An array of data, more details under the underlying function {@link ssi_getSDTickets()} |
|
74 |
+ * @since 1.1 |
|
75 |
+*/ |
|
76 |
+function ssi_staffAssignedTickets($assignee = 0, $limit = 10, $output_method = 'echo') |
|
77 |
+{ |
|
78 |
+ global $user_info; |
|
79 |
+ if (empty($assignee)) |
|
80 |
+ $assignee = $user_info['id']; |
|
81 |
+ |
|
82 |
+ $limit = (int) $limit; |
|
83 |
+ if (empty($limit)) |
|
84 |
+ return; |
|
85 |
+ |
|
86 |
+ $query_where = 'hdt.id_member_assigned = {int:assigned}'; |
|
87 |
+ |
|
88 |
+ $query_where_params = array( |
|
89 |
+ 'assigned' => $assignee, |
|
90 |
+ ); |
|
91 |
+ |
|
92 |
+ return ssi_getSDTickets($query_where, $query_where_params, '', 'hdt.id_ticket ASC', $output_method); |
|
93 |
+} |
|
94 |
+ |
|
95 |
+/** |
|
96 |
+ * Gets a list of all tickets based on urgency criteria given (subject to ticket visibility) |
|
97 |
+ * |
|
98 |
+ * @param int $urgency The urgency of tickets you want to get. |
|
99 |
+ * @param int $limit The number of tickets to limit to, default 10. |
|
100 |
+ * @param string $output_method Set to 'echo' for displaying content, set to 'array' to simply return data. |
|
101 |
+ * @return array An array of data, more details under the underlying function {@link ssi_getSDTickets()} |
|
102 |
+ * @since 1.1 |
|
103 |
+*/ |
|
104 |
+function ssi_staffTicketsUrgency($urgency, $limit = 10, $output_method = 'echo') |
|
105 |
+{ |
|
106 |
+ $query_where = 'hdt.urgency = {int:urgency}'; |
|
107 |
+ |
|
108 |
+ $query_where_params = array( |
|
109 |
+ 'urgency' => $urgency, |
|
110 |
+ ); |
|
111 |
+ |
|
112 |
+ return ssi_getSDTickets($query_where, $query_where_params, '', 'hdt.id_ticket ASC', $output_method); |
|
113 |
+} |
|
114 |
+ |
|
115 |
+/** |
|
116 |
+ * Gets tickets based on supplied criteria; this is a helper function not really intended to be called directly. |
|
117 |
+ * |
|
118 |
+ * @todo Finish writing and documenting this function. |
|
119 |
+ * @param string $query_where SQL clauses to be supplied to the query in addition to {query_see_ticket} - note 'AND' is not required at the start. |
|
120 |
+ * @param array $query_where_params Key/value associative array to be injected into the query, related to $query_where. |
|
121 |
+ * @param int $query_limit Number of items to limit the query to. |
|
122 |
+ * @param string $query_order The clause to order tickets by, defaults to tickets by order of creation. |
|
123 |
+ * @return array An array of arrays, each primary item containing the following: |
|
124 |
+ * <ul> |
|
125 |
+ * <li>id: Main ticket id</li> |
|
126 |
+ * <li>display_id: Formatted ticket id in [0000x] format</li> |
|
127 |
+ * <li>subject: Ticket subject</li> |
|
128 |
+ * <li>short_subject: Shortened version of ticket subject</li> |
|
129 |
+ * <li>href: Ticket href</li> |
|
130 |
+ * <li>opener: array of details about the ticket starter: |
|
131 |
+ * <ul> |
|
132 |
+ * <li>id: user id of the person who opened the ticket</li> |
|
133 |
+ * <li>name: username of the person who opened the ticket</li> |
|
134 |
+ * <li>link: link to the profile of the person who opened the ticket</li> |
|
135 |
+ * </ul> |
|
136 |
+ * </li> |
|
137 |
+ * <li>replier: array of details about the last person to reply to the ticket: |
|
138 |
+ * <ul> |
|
139 |
+ * <li>id: user id of the last person to reply to the ticket</li> |
|
140 |
+ * <li>name: username of the last person to reply to the ticket</li> |
|
141 |
+ * <li>link: link to the profile of the last person to reply to the ticket</li> |
|
142 |
+ * </ul> |
|
143 |
+ * </li> |
|
144 |
+ * <li>opener: array of details about the person who the ticket is assigned to: |
|
145 |
+ * <ul> |
|
146 |
+ * <li>id: user id of the person who the ticket is assigned to</li> |
|
147 |
+ * <li>name: username of the person who the ticket is assigned to or 'Unassigned' otherwise</li> |
|
148 |
+ * <li>link: link to the profile of the person who the ticket is assigned to or 'Unassigned' otherwise</li> |
|
149 |
+ * </ul> |
|
150 |
+ * </li> |
|
151 |
+ * <li>num_replies: Number of replies in the ticket</li> |
|
152 |
+ * <li>start_time: Formatted string of time the ticket was opened</li> |
|
153 |
+ * <li>start_timestamp: Raw timestamp (adjusted for timezones) of ticket being opened</li> |
|
154 |
+ * <li>last_time: Formatted string of time the ticket was last replied to</li> |
|
155 |
+ * <li>last_timestamp: Raw timestamp (adjusted for timezones) of ticket's last reply</li> |
|
156 |
+ * <li>private: Whether the ticket is private or not</li> |
|
157 |
+ * <li>urgency_id: Number representing ticket urgency</li> |
|
158 |
+ * <li>urgency_text: String representing ticket urgency</li> |
|
159 |
+ * <li>status_id: Number representing ticket status</li> |
|
160 |
+ * <li>status_text: String representing ticket status</li> |
|
161 |
+ * </ul> |
|
162 |
+ * @since 1.1 |
|
163 |
+*/ |
|
164 |
+function ssi_getSDTickets($query_where, $query_where_params = array(), $query_limit = 0, $query_order = 'hdt.id_ticket ASC', $output_method = 'echo') |
|
165 |
+{ |
|
166 |
+ global $smcFunc, $scripturl, $txt; |
|
167 |
+ |
|
168 |
+ $query_limit = (int) $query_limit; |
|
169 |
+ |
|
170 |
+ $query = shd_db_query('', ' |
|
171 |
+ SELECT hdt.id_ticket, hdt.subject, hdt.num_replies, hdt.private, hdt.urgency, hdt.status, |
|
172 |
+ hdtr_first.poster_time AS start_time, hdtr_last.poster_time AS last_time, |
|
173 |
+ IFNULL(mem.real_name, hdtr_first.poster_name) AS starter_name, IFNULL(mem.id_member, 0) AS starter_id, |
|
174 |
+ IFNULL(ma.real_name, 0) AS assigned_name, IFNULL(ma.id_member, 0) AS assigned_id, |
|
175 |
+ IFNULL(mm.real_name, hdtr_last.modified_name) AS modified_name, IFNULL(mm.id_member, 0) AS modified_id |
|
176 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
177 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdt.id_first_msg = hdtr_first.id_msg) |
|
178 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdt.id_last_msg = hdtr_last.id_msg) |
|
179 |
+ LEFT JOIN {db_prefix}members AS mem ON (hdt.id_member_started = mem.id_member) |
|
180 |
+ LEFT JOIN {db_prefix}members AS ma ON (hdt.id_member_assigned = ma.id_member) |
|
181 |
+ LEFT JOIN {db_prefix}members AS mm ON (hdt.id_member_updated = mm.id_member) |
|
182 |
+ WHERE {query_see_ticket} AND ' . $query_where . ' |
|
183 |
+ ORDER BY ' . $query_order . ' |
|
184 |
+ ' . ($query_limit == 0 ? '' : 'LIMIT ' . $query_limit), |
|
185 |
+ array_merge($query_where_params, array( |
|
186 |
+ )) |
|
187 |
+ ); |
|
188 |
+ |
|
189 |
+ $tickets = array(); |
|
190 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
191 |
+ { |
|
192 |
+ censorText($row['subject']); |
|
193 |
+ |
|
194 |
+ $tickets[] = array( |
|
195 |
+ 'id' => $row['id_ticket'], |
|
196 |
+ 'display_id' => str_pad($row['id_ticket'], 5, '0', STR_PAD_LEFT), |
|
197 |
+ 'subject' => $row['subject'], |
|
198 |
+ 'short_subject' => shorten_subject($row['subject'], 25), |
|
199 |
+ 'href' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'], |
|
200 |
+ 'opener' => array( |
|
201 |
+ 'id' => $row['starter_id'], |
|
202 |
+ 'name' => $row['starter_name'], |
|
203 |
+ 'link' => shd_profile_link($row['starter_name'], $row['starter_id']), |
|
204 |
+ ), |
|
205 |
+ 'replier' => array( |
|
206 |
+ 'id' => $row['modified_id'], |
|
207 |
+ 'name' => $row['modified_name'], |
|
208 |
+ 'link' => shd_profile_link($row['modified_name'], $row['modified_id']), |
|
209 |
+ ), |
|
210 |
+ 'assigned' => array( |
|
211 |
+ 'id' => $row['assigned_id'], |
|
212 |
+ 'name' => empty($row['assigned_name']) ? $txt['shd_unassigned'] : $row['assigned_name'], |
|
213 |
+ 'link' => empty($row['assigned_name']) ? '<span class="error">' . $txt['shd_unassigned'] . '</span>' : shd_profile_link($row['assigned_name'], $row['assigned_id']), |
|
214 |
+ ), |
|
215 |
+ 'start_time' => timeformat($row['start_time']), |
|
216 |
+ 'start_timestamp' => forum_time(true, $row['start_time']), |
|
217 |
+ 'last_time' => timeformat($row['last_time']), |
|
218 |
+ 'last_timestamp' => forum_time(true, $row['last_time']), |
|
219 |
+ 'num_replies' => $row['num_replies'], |
|
220 |
+ 'private' => !empty($row['private']), |
|
221 |
+ 'urgency_id' => $row['urgency'], |
|
222 |
+ 'urgency_string' => $txt['shd_urgency_' . $row['urgency']], |
|
223 |
+ 'status_id' => $row['status'], |
|
224 |
+ 'status_text' => $txt['shd_status_' . $row['status']], |
|
225 |
+ ); |
|
226 |
+ } |
|
227 |
+ |
|
228 |
+ $smcFunc['db_free_result']($query); |
|
229 |
+ |
|
230 |
+ if (empty($tickets) || $output_method != 'echo') |
|
231 |
+ return $tickets; |
|
232 |
+ |
|
233 |
+ // output this stuff |
|
234 |
+ echo ' |
|
235 |
+ <table border="0" class="ssi_table">'; |
|
236 |
+ foreach ($tickets as $ticket) |
|
237 |
+ echo ' |
|
238 |
+ <tr> |
|
239 |
+ <td align="right" valign="top" nowrap="nowrap"> |
|
240 |
+ [', $ticket['status_text'], '] |
|
241 |
+ </td> |
|
242 |
+ <td valign="top"> |
|
243 |
+ <a href="', $ticket['href'], '">', $ticket['subject'], '</a> |
|
244 |
+ ', $txt['by'], ' ', $ticket['replier']['link'], ' |
|
245 |
+ </td> |
|
246 |
+ <td align="right" nowrap="nowrap"> |
|
247 |
+ ', $ticket['last_time'], ' |
|
248 |
+ </td> |
|
249 |
+ </tr>'; |
|
250 |
+ echo ' |
|
251 |
+ </table>'; |
|
252 |
+} |
|
253 |
+ |
|
254 |
+/** |
|
255 |
+ * Gets a list of all staff members within the helpdesk. |
|
256 |
+ * |
|
257 |
+ * @param boolean $honour_admin_setting Within the administration panel is the option to exclude forum admins from being considered staff (so can't assign tickets to them). If true (default), assume the outcome of that should be applied here too. |
|
258 |
+ * @param string $output_method Leave as default or explicitly set to 'echo' for this function to output a list of helpdesk staff members, set to 'array' to block output, and have the standard contents back. |
|
259 |
+ * @return array The return is always an array of members that are staff; contains many details about members since SMF's member context is loaded (including avatar, personal text and so on) |
|
260 |
+ * @since 1.1 |
|
261 |
+*/ |
|
262 |
+function ssi_staffMembers($honour_admin_setting = true, $output_method = 'echo') |
|
263 |
+{ |
|
264 |
+ global $modSettings, $smcFunc, $memberContext; |
|
265 |
+ |
|
266 |
+ $staff = shd_members_allowed_to('shd_staff'); |
|
267 |
+ |
|
268 |
+ if ($honour_admin_setting && !empty($modSettings['shd_admins_not_assignable'])) |
|
269 |
+ { |
|
270 |
+ $admins = array(); |
|
271 |
+ $query = $smcFunc['db_query']('', ' |
|
272 |
+ SELECT id_member |
|
273 |
+ FROM {db_prefix}members |
|
274 |
+ WHERE id_group = {int:id_group} |
|
275 |
+ OR FIND_IN_SET({int:id_group}, additional_groups)', |
|
276 |
+ array( |
|
277 |
+ 'id_group' => 1, |
|
278 |
+ ) |
|
279 |
+ ); |
|
280 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
281 |
+ $admins[] = $row[0]; |
|
282 |
+ |
|
283 |
+ $staff = array_diff($staff, $admins); |
|
284 |
+ } |
|
285 |
+ |
|
286 |
+ if (empty($staff)) |
|
287 |
+ return array(); |
|
288 |
+ |
|
289 |
+ loadMemberData($staff); |
|
290 |
+ |
|
291 |
+ if ($output_method == 'echo') |
|
292 |
+ echo ' |
|
293 |
+ <table border="0" class="ssi_table">'; |
|
294 |
+ |
|
295 |
+ $query_members = array(); |
|
296 |
+ foreach ($staff as $member) |
|
297 |
+ { |
|
298 |
+ // Load their context data. |
|
299 |
+ if (!loadMemberContext($member)) |
|
300 |
+ continue; |
|
301 |
+ |
|
302 |
+ // Store this member's information. |
|
303 |
+ $query_members[$member] = $memberContext[$member]; |
|
304 |
+ |
|
305 |
+ // Only do something if we're echo'ing. |
|
306 |
+ if ($output_method == 'echo') |
|
307 |
+ echo ' |
|
308 |
+ <tr> |
|
309 |
+ <td align="right" valign="top" nowrap="nowrap"> |
|
310 |
+ ', $query_members[$member]['link'], ' |
|
311 |
+ <br />', $query_members[$member]['blurb'], ' |
|
312 |
+ <br />', $query_members[$member]['avatar']['image'], ' |
|
313 |
+ </td> |
|
314 |
+ </tr>'; |
|
315 |
+ } |
|
316 |
+ |
|
317 |
+ // End the table if appropriate. |
|
318 |
+ if ($output_method == 'echo') |
|
319 |
+ echo ' |
|
320 |
+ </table>'; |
|
321 |
+ |
|
322 |
+ // Send back the data. |
|
323 |
+ return $query_members; |
|
324 |
+} |
|
325 |
+ |
|
326 |
+?> |
|
0 | 327 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,148 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-Assign.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles the scheduled tasks that can come along. |
|
22 |
+ * |
|
23 |
+ * @package source |
|
24 |
+ * @since 1.0 |
|
25 |
+*/ |
|
26 |
+ |
|
27 |
+if (!defined('SMF')) |
|
28 |
+ die('Hacking attempt...'); |
|
29 |
+ |
|
30 |
+/** |
|
31 |
+ * Container task for all the scheduled maintenance that SD can be asked to do. |
|
32 |
+ * |
|
33 |
+ * - purge deleted tickets |
|
34 |
+ * |
|
35 |
+ * @since 1.1 |
|
36 |
+*/ |
|
37 |
+ |
|
38 |
+function shd_scheduled() |
|
39 |
+{ |
|
40 |
+ global $smcFunc, $modSettings; |
|
41 |
+ |
|
42 |
+ shd_scheduled_purge_tickets(); |
|
43 |
+ return true; |
|
44 |
+} |
|
45 |
+ |
|
46 |
+function shd_scheduled_purge_tickets() |
|
47 |
+{ |
|
48 |
+ global $smcFunc, $modSettings; |
|
49 |
+ |
|
50 |
+ if (empty($modSettings['shd_purge_tickets']) || empty($modSettings['shd_purge_tickets_days'])) |
|
51 |
+ return; |
|
52 |
+ |
|
53 |
+ @set_time_limit(600); // Ten minutes. Is a big job, possibly. |
|
54 |
+ |
|
55 |
+ // 1. Get the list of deleted tickets. |
|
56 |
+ $query = $smcFunc['db_query']('', ' |
|
57 |
+ SELECT hdt.id_ticket, hdt.subject |
|
58 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
59 |
+ WHERE hdt.status = {int:deleted}', |
|
60 |
+ array( |
|
61 |
+ 'deleted' => TICKET_STATUS_DELETED, |
|
62 |
+ ) |
|
63 |
+ ); |
|
64 |
+ $tickets = array(); |
|
65 |
+ $subjects = array(); |
|
66 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
67 |
+ { |
|
68 |
+ $tickets[$row[0]] = 0; |
|
69 |
+ $subjects[$row[0]] = $row['subject']; |
|
70 |
+ } |
|
71 |
+ $smcFunc['db_free_result']($query); |
|
72 |
+ |
|
73 |
+ // 1b. Any to do? If not, get lost. |
|
74 |
+ if (empty($tickets)) |
|
75 |
+ return; |
|
76 |
+ |
|
77 |
+ // 2. Get the real last post time from the real last message, not the 'last message' the ticket stores (which is the last message that isn't deleted) |
|
78 |
+ $query = $smcFunc['db_query']('', ' |
|
79 |
+ SELECT id_ticket, MAX(poster_time) AS max_time |
|
80 |
+ FROM {db_prefix}helpdesk_ticket_replies |
|
81 |
+ WHERE id_ticket IN ({array_int:tickets}) |
|
82 |
+ GROUP BY id_ticket', |
|
83 |
+ array( |
|
84 |
+ 'tickets' => array_keys($tickets), |
|
85 |
+ ) |
|
86 |
+ ); |
|
87 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
88 |
+ $tickets[$row['id_ticket']] = $row['max_time']; |
|
89 |
+ $smcFunc['db_free_result']($query); |
|
90 |
+ |
|
91 |
+ // 3. Purge that list of threads too new to be deleted |
|
92 |
+ $del_time = time() - (86400 * $modSettings['shd_purge_tickets_days']); |
|
93 |
+ foreach ($tickets as $k => $v) |
|
94 |
+ { |
|
95 |
+ if ($v == 0 || $v > $del_time) |
|
96 |
+ unset($tickets[$k], $subjects[$k]); |
|
97 |
+ } |
|
98 |
+ |
|
99 |
+ // Last chance to abort! |
|
100 |
+ if (empty($tickets)) |
|
101 |
+ return; |
|
102 |
+ |
|
103 |
+ // 4. OK, we have a nice list of tickets to purge. So, let's get to it. |
|
104 |
+ // 4.1. Delete the ticket records themselves. |
|
105 |
+ $smcFunc['db_query']('', ' |
|
106 |
+ DELETE FROM {db_prefix}helpdesk_tickets |
|
107 |
+ WHERE id_ticket IN ({array_int:tickets})', |
|
108 |
+ array( |
|
109 |
+ 'tickets' => array_keys($tickets), |
|
110 |
+ ) |
|
111 |
+ ); |
|
112 |
+ // 4.2. The replies. |
|
113 |
+ $smcFunc['db_query']('', ' |
|
114 |
+ DELETE FROM {db_prefix}helpdesk_ticket_replies |
|
115 |
+ WHERE id_ticket IN ({array_int:tickets})', |
|
116 |
+ array( |
|
117 |
+ 'tickets' => array_keys($tickets), |
|
118 |
+ ) |
|
119 |
+ ); |
|
120 |
+ // 4.3. Attachments. |
|
121 |
+ |
|
122 |
+ // 4.4. Relationships. |
|
123 |
+ $smcFunc['db_query']('', ' |
|
124 |
+ DELETE FROM {db_prefix}helpdesk_relationships |
|
125 |
+ WHERE primary_ticket IN ({array_int:tickets})', |
|
126 |
+ array( |
|
127 |
+ 'tickets' => array_keys($tickets), |
|
128 |
+ ) |
|
129 |
+ ); |
|
130 |
+ $smcFunc['db_query']('', ' |
|
131 |
+ DELETE FROM {db_prefix}helpdesk_relationships |
|
132 |
+ WHERE secondary_ticket IN ({array_int:tickets})', |
|
133 |
+ array( |
|
134 |
+ 'tickets' => array_keys($tickets), |
|
135 |
+ ) |
|
136 |
+ ); |
|
137 |
+ // 4.5. Read/unread log |
|
138 |
+ $smcFunc['db_query']('', ' |
|
139 |
+ DELETE FROM {db_prefix}helpdesk_log_read |
|
140 |
+ WHERE id_ticket IN ({array_int:tickets})', |
|
141 |
+ array( |
|
142 |
+ 'tickets' => array_keys($tickets), |
|
143 |
+ ) |
|
144 |
+ ); |
|
145 |
+ // 4.6. Log everything. |
|
146 |
+} |
|
147 |
+ |
|
148 |
+?> |
|
0 | 149 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,886 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk-TopicTicketMove.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles displaying the user options for, and subsequently enacting, tickets being moved |
|
22 |
+ * to/from the helpdesk, from/to forum threads. |
|
23 |
+ * |
|
24 |
+ * @package source |
|
25 |
+ * @since 1.0 |
|
26 |
+*/ |
|
27 |
+ |
|
28 |
+if (!defined('SMF')) |
|
29 |
+ die('Hacking attempt...'); |
|
30 |
+ |
|
31 |
+/** |
|
32 |
+ * Load the form up for asking users what board they want to go to. |
|
33 |
+ * |
|
34 |
+ * Validates the user permission and session, then displays a list of boards the user can create new topics in. |
|
35 |
+ * |
|
36 |
+ * Accessed through action=helpdesk;sa=tickettotopic;ticket=x;sessvar=sessid |
|
37 |
+ * |
|
38 |
+ * @see shd_tickettotopic2() |
|
39 |
+ * @since 1.0 |
|
40 |
+*/ |
|
41 |
+function shd_tickettotopic() |
|
42 |
+{ |
|
43 |
+ global $smcFunc, $context, $user_info, $sourcedir, $txt, $modSettings, $scripturl; |
|
44 |
+ |
|
45 |
+ checkSession('get'); |
|
46 |
+ |
|
47 |
+ if (!shd_allowed_to('shd_ticket_to_topic') || !empty($modSettings['shd_helpdesk_only']) || !empty($modSettings['shd_disable_tickettotopic'])) |
|
48 |
+ fatal_lang_error('shd_cannot_move_ticket', false); |
|
49 |
+ |
|
50 |
+ if (empty($context['ticket_id'])) |
|
51 |
+ fatal_lang_error('shd_no_ticket'); |
|
52 |
+ |
|
53 |
+ // Get ticket details - and kick it out if they shouldn't be able to see it. |
|
54 |
+ $query = shd_db_query('', ' |
|
55 |
+ SELECT id_member_started, id_member_assigned, private, subject, deleted_replies |
|
56 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
57 |
+ WHERE {query_see_ticket} AND id_ticket = {int:ticket}', |
|
58 |
+ array( |
|
59 |
+ 'ticket' => $context['ticket_id'], |
|
60 |
+ ) |
|
61 |
+ ); |
|
62 |
+ |
|
63 |
+ if ($row = $smcFunc['db_fetch_row']($query)) |
|
64 |
+ { |
|
65 |
+ list($ticket_starter, $ticket_owner, $private, $subject, $deleted_replies) = $row; |
|
66 |
+ $smcFunc['db_free_result']($query); |
|
67 |
+ } |
|
68 |
+ else |
|
69 |
+ { |
|
70 |
+ $smcFunc['db_free_result']($query); |
|
71 |
+ fatal_lang_error('shd_no_ticket'); |
|
72 |
+ } |
|
73 |
+ |
|
74 |
+ // Hang on... are there any deleted replies? |
|
75 |
+ if ($deleted_replies > 0) |
|
76 |
+ { |
|
77 |
+ if (shd_allowed_to('shd_access_recyclebin')) |
|
78 |
+ $context['deleted_prompt'] = true; |
|
79 |
+ else |
|
80 |
+ fatal_lang_error('shd_cannot_move_ticket_with_deleted'); |
|
81 |
+ } |
|
82 |
+ |
|
83 |
+ // Build the linktree |
|
84 |
+ $context['linktree'][] = array( |
|
85 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
86 |
+ 'name' => $txt['shd_linktree_move_ticket'], |
|
87 |
+ ); |
|
88 |
+ $context['linktree'][] = array( |
|
89 |
+ 'url' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'], |
|
90 |
+ 'name' => $subject, |
|
91 |
+ ); |
|
92 |
+ |
|
93 |
+ // They should only be able to move it to boards they are allowed to post in. |
|
94 |
+ $allowedboards = boardsAllowedTo('post_new'); |
|
95 |
+ if ($allowedboards[0] == 0) |
|
96 |
+ $allowedboards = ''; // They can access everything. |
|
97 |
+ |
|
98 |
+ // All good, now figure out what board(s) they can move it to. (MoveTopic.php style 0-:D) |
|
99 |
+ $request = shd_db_query('order_by_board_order', ' |
|
100 |
+ SELECT b.id_board, b.name, b.child_level, c.name AS cat_name, c.id_cat |
|
101 |
+ FROM {db_prefix}boards AS b |
|
102 |
+ LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat) |
|
103 |
+ WHERE {query_see_board} |
|
104 |
+ AND b.redirect = {string:blank_redirect} |
|
105 |
+ ' . (!empty($allowedboards) ? 'AND id_board IN({array_int:allowed_boards})' : ''), |
|
106 |
+ array( |
|
107 |
+ 'blank_redirect' => '', |
|
108 |
+ 'allowed_boards' => $allowedboards, |
|
109 |
+ ) |
|
110 |
+ ); |
|
111 |
+ $context['boards'] = array(); |
|
112 |
+ |
|
113 |
+ while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
114 |
+ { |
|
115 |
+ if (!isset($context['categories'][$row['id_cat']])) |
|
116 |
+ $context['categories'][$row['id_cat']] = array ( |
|
117 |
+ 'name' => strip_tags($row['cat_name']), |
|
118 |
+ 'boards' => array(), |
|
119 |
+ ); |
|
120 |
+ |
|
121 |
+ $context['categories'][$row['id_cat']]['boards'][] = array( |
|
122 |
+ 'id' => $row['id_board'], |
|
123 |
+ 'name' => strip_tags($row['name']), |
|
124 |
+ 'category' => strip_tags($row['cat_name']), |
|
125 |
+ 'child_level' => $row['child_level'], |
|
126 |
+ 'selected' => !empty($_SESSION['move_to_topic']) && $_SESSION['move_to_topic'] == $row['id_board'] && $row['id_board'] != $board, |
|
127 |
+ ); |
|
128 |
+ } |
|
129 |
+ |
|
130 |
+ $smcFunc['db_free_result']($request); |
|
131 |
+ |
|
132 |
+ if (empty($context['categories'])) |
|
133 |
+ fatal_lang_error('shd_moveticket_noboards', false); |
|
134 |
+ |
|
135 |
+ // Store the ticket subject for the template |
|
136 |
+ $context['ticket_subject'] = $subject; |
|
137 |
+ |
|
138 |
+ loadTemplate('sd_template/SimpleDesk-TicketTopicMove'); |
|
139 |
+ $context['sub_template'] = 'shd_tickettotopic'; |
|
140 |
+ $context['page_title'] = $txt['shd_move_ticket_to_topic']; |
|
141 |
+ checkSubmitOnce('register'); |
|
142 |
+} |
|
143 |
+ |
|
144 |
+/** |
|
145 |
+ * Receives the form for moving tickets to topics, and actually handles the move. |
|
146 |
+ * |
|
147 |
+ * After checking permissions, and so on, begin to actually move posts. |
|
148 |
+ * |
|
149 |
+ * This is done by invoking SMF's createPost function to make the new thread and repost all the ticket's posts as new thread posts |
|
150 |
+ * using defaults for some settings. |
|
151 |
+ * |
|
152 |
+ * Operations: |
|
153 |
+ * - check the user can see the board they are linking to |
|
154 |
+ * - move the ticket's text as the opening post |
|
155 |
+ * - update the ticket row if the post was modified before |
|
156 |
+ * - get the rest of the replies |
|
157 |
+ * - step through and post, updating for modified details |
|
158 |
+ * - send the notification PM if we're doing that |
|
159 |
+ * - update the attachments table |
|
160 |
+ * - update the action log |
|
161 |
+ * - remove the ticket from the DB |
|
162 |
+ * |
|
163 |
+ * @see shd_tickettotopic() |
|
164 |
+ * @since 1.0 |
|
165 |
+*/ |
|
166 |
+function shd_tickettotopic2() |
|
167 |
+{ |
|
168 |
+ global $smcFunc, $context, $txt, $modSettings, $scripturl, $sourcedir; |
|
169 |
+ |
|
170 |
+ checkSession(); |
|
171 |
+ checkSubmitOnce('check'); |
|
172 |
+ |
|
173 |
+ if (!shd_allowed_to('shd_ticket_to_topic') || !empty($modSettings['shd_helpdesk_only']) || !empty($modSettings['shd_disable_tickettotopic'])) |
|
174 |
+ fatal_lang_error('shd_cannot_move_ticket', false); |
|
175 |
+ |
|
176 |
+ if (empty($context['ticket_id'])) |
|
177 |
+ fatal_lang_error('shd_no_ticket'); |
|
178 |
+ |
|
179 |
+ if (isset($_POST['send_pm']) && (!isset($_POST['pm_content']) || trim($_POST['pm_content']) == '')) |
|
180 |
+ fatal_lang_error('shd_move_no_pm', false); |
|
181 |
+ |
|
182 |
+ // Just in case, are they cancelling? |
|
183 |
+ if (isset($_REQUEST['cancel'])) |
|
184 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); |
|
185 |
+ |
|
186 |
+ require_once($sourcedir . '/Subs-Post.php'); |
|
187 |
+ |
|
188 |
+ // The destination board must be numeric. |
|
189 |
+ $_POST['toboard'] = (int) $_POST['toboard']; |
|
190 |
+ |
|
191 |
+ $msg_assoc = array(); |
|
192 |
+ |
|
193 |
+ // This is complex, very complex. Hopefully 5 minutes will be enough... |
|
194 |
+ @set_time_limit(300); |
|
195 |
+ |
|
196 |
+ // Make sure they can see the board they are trying to move to (and get whether posts count in the target board). |
|
197 |
+ $request = shd_db_query('', ' |
|
198 |
+ SELECT b.count_posts, b.name, hdt.subject, hdt.id_member_started, hdtr.body, hdt.id_first_msg, hdtr.smileys_enabled, |
|
199 |
+ hdtr.modified_time, hdtr.modified_name, hdtr.poster_time, hdtr.id_msg, hdt.deleted_replies |
|
200 |
+ FROM {db_prefix}boards AS b |
|
201 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdt.id_ticket = {int:ticket}) |
|
202 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdtr.id_msg = hdt.id_first_msg) |
|
203 |
+ WHERE {query_see_board} |
|
204 |
+ AND {query_see_ticket} |
|
205 |
+ AND b.id_board = {int:to_board} |
|
206 |
+ AND b.redirect = {string:blank_redirect} |
|
207 |
+ LIMIT 1', |
|
208 |
+ array( |
|
209 |
+ 'ticket' => $context['ticket_id'], |
|
210 |
+ 'to_board' => $_POST['toboard'], |
|
211 |
+ 'blank_redirect' => '', |
|
212 |
+ ) |
|
213 |
+ ); |
|
214 |
+ if ($smcFunc['db_num_rows']($request) == 0) |
|
215 |
+ fatal_lang_error('no_board'); |
|
216 |
+ else |
|
217 |
+ list ($pcounter, $board_name, $subject, $owner, $body, $firstmsg, $smileys_enabled, $modified_time, $modified_name, $time, $shd_id_msg, $deleted_replies) = $smcFunc['db_fetch_row']($request); |
|
218 |
+ |
|
219 |
+ $smcFunc['db_free_result']($request); |
|
220 |
+ |
|
221 |
+ // Are we changing the subject? |
|
222 |
+ $old_subject = $subject; |
|
223 |
+ $subject = !empty($_POST['change_subject']) && !empty($_POST['subject']) ? $_POST['subject'] : $subject; |
|
224 |
+ |
|
225 |
+ $context['deleted_prompt'] = false; |
|
226 |
+ // Hang on... are there any deleted replies? |
|
227 |
+ if ($deleted_replies > 0) |
|
228 |
+ { |
|
229 |
+ if (shd_allowed_to('shd_access_recyclebin')) |
|
230 |
+ { |
|
231 |
+ $dr_opts = array('abort', 'delete', 'undelete'); |
|
232 |
+ |
|
233 |
+ $context['deleted_prompt'] = isset($_REQUEST['deleted_replies']) && in_array($_REQUEST['deleted_replies'], $dr_opts) ? $_REQUEST['deleted_replies'] : 'abort'; |
|
234 |
+ } |
|
235 |
+ else |
|
236 |
+ fatal_lang_error('shd_cannot_move_ticket_with_deleted'); |
|
237 |
+ } |
|
238 |
+ |
|
239 |
+ if (!empty($context['deleted_prompt']) && $context['deleted_prompt'] == 'abort') |
|
240 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . ';recycle'); |
|
241 |
+ |
|
242 |
+ // All okay, it seems. Let's go create the topic. |
|
243 |
+ $msgOptions = array( |
|
244 |
+ 'subject' => $subject, |
|
245 |
+ 'body' => $body, |
|
246 |
+ 'icon' => 'xx', |
|
247 |
+ 'smileys_enabled' => !empty($smileys_enabled) ? 1 : 0, |
|
248 |
+ ); |
|
249 |
+ $topicOptions = array( |
|
250 |
+ 'board' => $_POST['toboard'], |
|
251 |
+ 'lock_mode' => 0, |
|
252 |
+ 'mark_as_read' => false, |
|
253 |
+ ); |
|
254 |
+ $posterOptions = array( |
|
255 |
+ 'id' => $owner, |
|
256 |
+ 'update_post_count' => empty($pcounter), |
|
257 |
+ ); |
|
258 |
+ createPost($msgOptions, $topicOptions, $posterOptions); |
|
259 |
+ |
|
260 |
+ // Keep track of SHD msg id to SMF msg id |
|
261 |
+ $msg_assoc[$shd_id_msg] = $msgOptions['id']; |
|
262 |
+ |
|
263 |
+ // createPost() doesn't handle modified time and name, so we'll fix that here, along with the poster time. |
|
264 |
+ if (!empty($modified_time)) |
|
265 |
+ { |
|
266 |
+ shd_db_query('', ' |
|
267 |
+ UPDATE {db_prefix}messages |
|
268 |
+ SET |
|
269 |
+ modified_time = {int:modified_time}, |
|
270 |
+ modified_name = {string:modified_name}, |
|
271 |
+ poster_time = {int:poster_time} |
|
272 |
+ WHERE id_msg = {int:id_msg}', |
|
273 |
+ array( |
|
274 |
+ 'id_msg' => $firstmsg, |
|
275 |
+ 'modified_time' => $modified_time, |
|
276 |
+ 'modified_name' => $modified_name, |
|
277 |
+ 'poster_time' => $time, |
|
278 |
+ ) |
|
279 |
+ ); |
|
280 |
+ } |
|
281 |
+ |
|
282 |
+ // Topic created, let's dig out the replies and post them in the topic, if there are any. |
|
283 |
+ if (isset($topicOptions['id'])) |
|
284 |
+ { |
|
285 |
+ $request = shd_db_query('', ' |
|
286 |
+ SELECT body, id_member, poster_time, poster_name, poster_email, poster_ip, smileys_enabled, |
|
287 |
+ modified_time, modified_member, modified_name, poster_time, id_msg, message_status |
|
288 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
289 |
+ WHERE id_ticket = {int:ticket} |
|
290 |
+ AND id_msg > {int:ticket_msg}', |
|
291 |
+ array( |
|
292 |
+ 'ticket' => $context['ticket_id'], |
|
293 |
+ 'ticket_msg' => $firstmsg, |
|
294 |
+ ) |
|
295 |
+ ); |
|
296 |
+ |
|
297 |
+ // The ID of the topic we created |
|
298 |
+ $topic = $topicOptions['id']; |
|
299 |
+ |
|
300 |
+ if ($smcFunc['db_num_rows']($request) != 0) |
|
301 |
+ { |
|
302 |
+ // Now loop through each reply and post it. Hopefully there aren't too many. *looks at clock* |
|
303 |
+ while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
304 |
+ { |
|
305 |
+ if ($row['message_status'] == MSG_STATUS_DELETED && !empty($context['deleted_prompt']) && $context['deleted_prompt'] == 'delete') // we don't want these replies! |
|
306 |
+ continue; |
|
307 |
+ |
|
308 |
+ $msgOptions = array( |
|
309 |
+ 'subject' => $txt['response_prefix'] . $subject, |
|
310 |
+ 'body' => $row['body'], |
|
311 |
+ 'icon' => 'xx', |
|
312 |
+ 'smileys_enabled' => !empty($row['smileys_enabled']) ? 1 : 0, |
|
313 |
+ ); |
|
314 |
+ $topicOptions = array( |
|
315 |
+ 'id' => $topic, |
|
316 |
+ 'board' => $_POST['toboard'], |
|
317 |
+ 'lock_mode' => 0, |
|
318 |
+ 'mark_as_read' => false, |
|
319 |
+ ); |
|
320 |
+ $posterOptions = array( |
|
321 |
+ 'id' => $row['id_member'], |
|
322 |
+ 'name' => !empty($row['poster_name']) ? $row['poster_name'] : '', |
|
323 |
+ 'email' => !empty($row['poster_email']) ? $row['poster_email'] : '', |
|
324 |
+ 'ip' => !empty($row['poster_ip']) ? $row['poster_ip'] : '', |
|
325 |
+ 'update_post_count' => empty($pcounter), |
|
326 |
+ ); |
|
327 |
+ createPost($msgOptions, $topicOptions, $posterOptions); |
|
328 |
+ |
|
329 |
+ // Don't forget to note what id |
|
330 |
+ $msg_assoc[$row['id_msg']] = $msgOptions['id']; |
|
331 |
+ |
|
332 |
+ // Meh, createPost() doesn't have any hooks for modified time and user. Let's fix that now. |
|
333 |
+ if (!empty($row['modified_time'])) |
|
334 |
+ { |
|
335 |
+ shd_db_query('', ' |
|
336 |
+ UPDATE {db_prefix}messages |
|
337 |
+ SET |
|
338 |
+ modified_time = {int:modified_time}, |
|
339 |
+ modified_name = {string:modified_name}, |
|
340 |
+ poster_time = {int:poster_time} |
|
341 |
+ WHERE id_msg = {int:id_msg}', |
|
342 |
+ array( |
|
343 |
+ 'id_msg' => $msgOptions['id'], |
|
344 |
+ 'modified_time' => $row['modified_time'], |
|
345 |
+ 'modified_name' => $row['modified_name'], |
|
346 |
+ 'poster_time' => $row['poster_time'], |
|
347 |
+ ) |
|
348 |
+ ); |
|
349 |
+ } |
|
350 |
+ } |
|
351 |
+ } |
|
352 |
+ |
|
353 |
+ // Topic: check; Replies: check; Notfiy the ticket starter, if desired. |
|
354 |
+ if (isset($_POST['send_pm'])) |
|
355 |
+ { |
|
356 |
+ $request = shd_db_query('pm_find_username', ' |
|
357 |
+ SELECT id_member, real_name |
|
358 |
+ FROM {db_prefix}members |
|
359 |
+ WHERE id_member = {int:user} |
|
360 |
+ LIMIT 1', |
|
361 |
+ array( |
|
362 |
+ 'user' => $owner, |
|
363 |
+ ) |
|
364 |
+ ); |
|
365 |
+ list ($userid,$username) = $smcFunc['db_fetch_row']($request); |
|
366 |
+ $smcFunc['db_free_result']($request); |
|
367 |
+ |
|
368 |
+ // Fix the content |
|
369 |
+ $replacements = array( |
|
370 |
+ '{user}' => $username, |
|
371 |
+ '{subject}' => $old_subject, |
|
372 |
+ '{board}' => '[url=' . $scripturl . '?board=' . $_POST['toboard'] . '.0]' . $board_name . '[/url]', |
|
373 |
+ '{link}' => $scripturl . '?topic=' . $topic . '.0', |
|
374 |
+ ); |
|
375 |
+ $message = str_replace(array_keys($replacements), array_values($replacements), $_POST['pm_content']); |
|
376 |
+ |
|
377 |
+ $recipients = array( |
|
378 |
+ 'to' => array($owner), |
|
379 |
+ 'bcc' => array() |
|
380 |
+ ); |
|
381 |
+ |
|
382 |
+ sendpm($recipients, $txt['shd_ticket_moved_subject'], un_htmlspecialchars($message)); |
|
383 |
+ } |
|
384 |
+ |
|
385 |
+ // Right, time to do all the attachment fussing too |
|
386 |
+ if (!empty($msg_assoc)) |
|
387 |
+ { |
|
388 |
+ $attachIDs = array(); |
|
389 |
+ $query = shd_db_query('', ' |
|
390 |
+ SELECT id_attach, id_msg |
|
391 |
+ FROM {db_prefix}helpdesk_attachments |
|
392 |
+ WHERE id_msg IN ({array_int:msgs})', |
|
393 |
+ array( |
|
394 |
+ 'msgs' => array_keys($msg_assoc), |
|
395 |
+ ) |
|
396 |
+ ); |
|
397 |
+ |
|
398 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
399 |
+ $attachIDs[] = $row; |
|
400 |
+ |
|
401 |
+ $smcFunc['db_free_result']($query); |
|
402 |
+ |
|
403 |
+ if (!empty($attachIDs)) |
|
404 |
+ { |
|
405 |
+ // 1. Update all the attachments in the master table; this is the bit that hurts since it can't be done without |
|
406 |
+ // a query per row :( |
|
407 |
+ foreach ($attachIDs as $attach) |
|
408 |
+ { |
|
409 |
+ shd_db_query('', ' |
|
410 |
+ UPDATE {db_prefix}attachments |
|
411 |
+ SET id_msg = {int:new_msg} |
|
412 |
+ WHERE id_attach = {int:attach}', |
|
413 |
+ array( |
|
414 |
+ 'attach' => $attach['id_attach'], |
|
415 |
+ 'new_msg' => $msg_assoc[$attach['id_msg']], |
|
416 |
+ ) |
|
417 |
+ ); |
|
418 |
+ } |
|
419 |
+ |
|
420 |
+ // 2. Remove the entries from the SD table since we don't need them no more |
|
421 |
+ shd_db_query('', ' |
|
422 |
+ DELETE FROM {db_prefix}helpdesk_attachments |
|
423 |
+ WHERE id_msg IN ({array_int:msgs})', |
|
424 |
+ array( |
|
425 |
+ 'msgs' => array_keys($msg_assoc), |
|
426 |
+ ) |
|
427 |
+ ); |
|
428 |
+ } |
|
429 |
+ } |
|
430 |
+ |
|
431 |
+ // Well, it's possible there are some phantom attachments on deleted replies that need to disappear |
|
432 |
+ if (!empty($context['deleted_replies']) && $context['deleted_replies'] == 'delete') |
|
433 |
+ { |
|
434 |
+ $query = shd_db_query('', ' |
|
435 |
+ SELECT id_msg |
|
436 |
+ FROM {db_prefix}helpdesk_attachments AS hda |
|
437 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hda.id_msg = hdtr.id_msg) |
|
438 |
+ WHERE id_ticket = {int:ticket} |
|
439 |
+ AND hdtr.message_status = {int:deleted}', |
|
440 |
+ array( |
|
441 |
+ 'ticket' => $context['ticket_id'], |
|
442 |
+ 'deleted' => MSG_STATUS_DELETED, |
|
443 |
+ ) |
|
444 |
+ ); |
|
445 |
+ |
|
446 |
+ if ($smcFunc['db_num_rows']($query) > 0) |
|
447 |
+ { |
|
448 |
+ $msgs = array(); |
|
449 |
+ while ($row = $smcFunc['db_fetch_row']($query)) |
|
450 |
+ $msgs[] = $row[0]; |
|
451 |
+ |
|
452 |
+ if (!empty($msgs)) |
|
453 |
+ { |
|
454 |
+ // Get rid of the parents |
|
455 |
+ require_once($sourcedir . '/ManageAttachments.php'); |
|
456 |
+ $attachmentQuery = array( |
|
457 |
+ 'attachment_type' => 0, |
|
458 |
+ 'id_msg' => 0, |
|
459 |
+ 'id_attach' => $msgs, |
|
460 |
+ ); |
|
461 |
+ removeAttachments($attachmentQuery); |
|
462 |
+ |
|
463 |
+ // Get rid of the remainder in hda table |
|
464 |
+ shd_db_query('', ' |
|
465 |
+ DELETE FROM {db_prefix}helpdesk_attachments |
|
466 |
+ WHERE id_ticket = {int:ticket}', |
|
467 |
+ array( |
|
468 |
+ 'ticket' => $context['ticket_id'], |
|
469 |
+ ) |
|
470 |
+ ); |
|
471 |
+ } |
|
472 |
+ } |
|
473 |
+ |
|
474 |
+ $smcFunc['db_free_result']($query); |
|
475 |
+ } |
|
476 |
+ |
|
477 |
+ // Now we'll add this to the log. |
|
478 |
+ $log_params = array( |
|
479 |
+ 'subject' => $subject, |
|
480 |
+ 'board_id' => $_POST['toboard'], |
|
481 |
+ 'board_name' => $board_name, |
|
482 |
+ 'ticket' => $topic, |
|
483 |
+ ); |
|
484 |
+ shd_log_action('tickettotopic', $log_params); |
|
485 |
+ |
|
486 |
+ // Lastly, delete the ticket from the database. |
|
487 |
+ shd_db_query('', ' |
|
488 |
+ DELETE FROM {db_prefix}helpdesk_tickets |
|
489 |
+ WHERE id_ticket = {int:ticket} |
|
490 |
+ LIMIT 1', |
|
491 |
+ array( |
|
492 |
+ 'ticket' => $context['ticket_id'], |
|
493 |
+ ) |
|
494 |
+ ); |
|
495 |
+ // And the replies, too. |
|
496 |
+ shd_db_query('', ' |
|
497 |
+ DELETE FROM {db_prefix}helpdesk_ticket_replies |
|
498 |
+ WHERE id_ticket = {int:ticket}', |
|
499 |
+ array( |
|
500 |
+ 'ticket' => $context['ticket_id'], |
|
501 |
+ ) |
|
502 |
+ ); |
|
503 |
+ |
|
504 |
+ } |
|
505 |
+ else |
|
506 |
+ fatal_lang_error('shd_move_topic_not_created',false); |
|
507 |
+ |
|
508 |
+ // Clear our cache |
|
509 |
+ shd_clear_active_tickets($owner); |
|
510 |
+ |
|
511 |
+ // Send them to the topic. |
|
512 |
+ redirectexit('topic=' . $topic . '.0'); |
|
513 |
+ |
|
514 |
+} |
|
515 |
+ |
|
516 |
+/** |
|
517 |
+ * Load the form up for asking users whether to send a personal message (and what message) to the topic/ticket starter or not. Most of the rest of this function is about loading the data to make the page well-rounded (like the subject for breadcrumbs) |
|
518 |
+ * |
|
519 |
+ * Validates the user permission and session, of course. |
|
520 |
+ * |
|
521 |
+ * Accessed through action=helpdesk;sa=topictoticket;topic=x;sessvar=sessid |
|
522 |
+ * |
|
523 |
+ * @see shd_topictoticket2() |
|
524 |
+ * @since 1.0 |
|
525 |
+*/ |
|
526 |
+function shd_topictoticket() |
|
527 |
+{ |
|
528 |
+ global $smcFunc, $context, $user_info, $sourcedir, $txt, $modSettings, $scripturl; |
|
529 |
+ |
|
530 |
+ checkSession('get'); |
|
531 |
+ |
|
532 |
+ if (!shd_allowed_to('shd_topic_to_ticket') || !empty($modSettings['shd_helpdesk_only']) || !empty($modSettings['shd_disable_tickettotopic'])) |
|
533 |
+ fatal_lang_error('shd_cannot_move_topic', false); |
|
534 |
+ |
|
535 |
+ if (empty($_REQUEST['topic'])) |
|
536 |
+ fatal_lang_error('shd_no_topic'); |
|
537 |
+ |
|
538 |
+ $context['topic_id'] = (int) $_REQUEST['topic']; |
|
539 |
+ |
|
540 |
+ // Get topic details |
|
541 |
+ $query = shd_db_query('', ' |
|
542 |
+ SELECT m.subject |
|
543 |
+ FROM {db_prefix}topics AS t |
|
544 |
+ INNER JOIN {db_prefix}messages AS m ON (m.id_topic = {int:topic}) |
|
545 |
+ INNER JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board) |
|
546 |
+ WHERE {query_see_board} AND t.id_topic = {int:topic}', |
|
547 |
+ array( |
|
548 |
+ 'topic' => $context['topic_id'], |
|
549 |
+ ) |
|
550 |
+ ); |
|
551 |
+ |
|
552 |
+ if ($row = $smcFunc['db_fetch_row']($query)) |
|
553 |
+ { |
|
554 |
+ list($subject) = $row; |
|
555 |
+ $smcFunc['db_free_result']($query); |
|
556 |
+ } |
|
557 |
+ else |
|
558 |
+ { |
|
559 |
+ $smcFunc['db_free_result']($query); |
|
560 |
+ fatal_lang_error('shd_no_topic'); |
|
561 |
+ } |
|
562 |
+ |
|
563 |
+ // Build the linktree |
|
564 |
+ $context['linktree'][] = array( |
|
565 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
566 |
+ 'name' => $txt['shd_linktree_move_topic'], |
|
567 |
+ ); |
|
568 |
+ $context['linktree'][] = array( |
|
569 |
+ 'url' => $scripturl . '?topic=' . $context['topic_id'] . '.0', |
|
570 |
+ 'name' => $subject, |
|
571 |
+ ); |
|
572 |
+ |
|
573 |
+ // Store the subject for the template |
|
574 |
+ $context['topic_subject'] = $subject; |
|
575 |
+ |
|
576 |
+ loadTemplate('sd_template/SimpleDesk-TicketTopicMove'); |
|
577 |
+ $context['sub_template'] = 'shd_topictoticket'; |
|
578 |
+ $context['page_title'] = $txt['shd_move_topic_to_ticket']; |
|
579 |
+ checkSubmitOnce('register'); |
|
580 |
+} |
|
581 |
+ |
|
582 |
+/** |
|
583 |
+ * Handles moving a topic into the helpdesk. |
|
584 |
+ * |
|
585 |
+ * After checking permissions, and so on, begin to actually move posts. |
|
586 |
+ * |
|
587 |
+ * Broadly this is done using {@link shd_create_ticket_post()}, which has hooks specifically to deal with post modification times (written in specifically to ease this function's workload) |
|
588 |
+ * |
|
589 |
+ * Operations: |
|
590 |
+ * - get the topic information (and checking topic access permission in the process) |
|
591 |
+ * - identify the status of the topic (new/with staff/with user) |
|
592 |
+ * - create the new ticket from these details |
|
593 |
+ * - assuming there are replies, query for them |
|
594 |
+ * - step through and repost |
|
595 |
+ * - send the notification PM if we're doing that |
|
596 |
+ * - update the attachments table |
|
597 |
+ * - update the action log |
|
598 |
+ * - remove the topic from the forum |
|
599 |
+ * |
|
600 |
+ * @see shd_topictoticket() |
|
601 |
+ * @since 1.0 |
|
602 |
+*/ |
|
603 |
+function shd_topictoticket2() |
|
604 |
+{ |
|
605 |
+ global $smcFunc, $context, $txt, $modSettings, $scripturl, $sourcedir; |
|
606 |
+ |
|
607 |
+ checkSession(); |
|
608 |
+ checkSubmitOnce('check'); |
|
609 |
+ |
|
610 |
+ if (!shd_allowed_to('shd_topic_to_ticket') || !empty($modSettings['shd_helpdesk_only']) || !empty($modSettings['shd_disable_tickettotopic'])) |
|
611 |
+ fatal_lang_error('shd_cannot_move_topic', false); |
|
612 |
+ |
|
613 |
+ if (empty($_REQUEST['topic'])) |
|
614 |
+ fatal_lang_error('shd_no_topic'); |
|
615 |
+ |
|
616 |
+ $context['topic_id'] = (int) $_REQUEST['topic']; |
|
617 |
+ |
|
618 |
+ // Just in case, are they cancelling? |
|
619 |
+ if (isset($_REQUEST['cancel'])) |
|
620 |
+ redirectexit('topic=' . $context['topic_id']); |
|
621 |
+ |
|
622 |
+ if (isset($_POST['send_pm']) && (!isset($_POST['pm_content']) || trim($_POST['pm_content']) == '')) |
|
623 |
+ fatal_lang_error('shd_move_no_pm_topic', false); |
|
624 |
+ |
|
625 |
+ require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php'); |
|
626 |
+ |
|
627 |
+ // Fetch the topic information. |
|
628 |
+ $request = shd_db_query('', ' |
|
629 |
+ SELECT m.subject, t.id_board, t.id_member_started, m.body, t.id_first_msg, m.smileys_enabled, t.id_member_updated, t.num_replies, |
|
630 |
+ m.poster_email, m.poster_name, m.poster_ip, m.poster_time, m.modified_time, m.modified_name, m.id_msg |
|
631 |
+ FROM {db_prefix}topics AS t |
|
632 |
+ INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) |
|
633 |
+ INNER JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board) |
|
634 |
+ WHERE {query_see_board} AND t.id_topic = {int:topic} |
|
635 |
+ LIMIT 1', |
|
636 |
+ array( |
|
637 |
+ 'topic' => $context['topic_id'], |
|
638 |
+ ) |
|
639 |
+ ); |
|
640 |
+ if ($smcFunc['db_num_rows']($request) == 0) |
|
641 |
+ fatal_lang_error('shd_move_ticket_not_created'); |
|
642 |
+ else |
|
643 |
+ list ($subject, $board, $owner, $body, $firstmsg, $smileys_enabled, $memberupdated, $numreplies, $postername, $posteremail, $posterip, $postertime, $modified_time, $modified_name, $smf_id_msg) = $smcFunc['db_fetch_row']($request); |
|
644 |
+ |
|
645 |
+ $smcFunc['db_free_result']($request); |
|
646 |
+ |
|
647 |
+ // Figure out what the status of the ticket should be. |
|
648 |
+ $status = shd_determine_status('topictoticket', $owner, $memberupdated, $numreplies); |
|
649 |
+ |
|
650 |
+ // Are we changing the subject? |
|
651 |
+ $old_subject = $subject; |
|
652 |
+ $subject = !empty($_POST['change_subject']) && !empty($_POST['subject']) ? $_POST['subject'] : $subject; |
|
653 |
+ |
|
654 |
+ // All okay, it seems. Let's go create the ticket. |
|
655 |
+ $msg_assoc = array(); |
|
656 |
+ |
|
657 |
+ $msgOptions = array( |
|
658 |
+ 'body' => $body, |
|
659 |
+ 'smileys_enabled' => !empty($smileys_enabled) ? 1 : 0, |
|
660 |
+ 'modified' => array( |
|
661 |
+ 'time' => $modified_time, |
|
662 |
+ 'name' => $modified_name, |
|
663 |
+ ), |
|
664 |
+ 'time' => $postertime, |
|
665 |
+ ); |
|
666 |
+ $ticketOptions = array( |
|
667 |
+ 'subject' => $subject, |
|
668 |
+ 'mark_as_read' => false, |
|
669 |
+ 'private' => false, |
|
670 |
+ 'status' => $status, |
|
671 |
+ 'urgency' => 0, |
|
672 |
+ 'assigned' => 0, |
|
673 |
+ ); |
|
674 |
+ $posterOptions = array( |
|
675 |
+ 'id' => $owner, |
|
676 |
+ 'name' => $postername, |
|
677 |
+ 'email' => $posteremail, |
|
678 |
+ 'ip' => $posterip, |
|
679 |
+ ); |
|
680 |
+ shd_create_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
681 |
+ $msg_assoc[$smf_id_msg] = $msgOptions['id']; |
|
682 |
+ |
|
683 |
+ // Ticket created, let's dig out the replies and post them in the ticket, if there are any. |
|
684 |
+ if (isset($ticketOptions['id'])) |
|
685 |
+ { |
|
686 |
+ $request = shd_db_query('', ' |
|
687 |
+ SELECT body, id_member, poster_time, poster_name, poster_email, poster_ip, smileys_enabled, id_msg |
|
688 |
+ FROM {db_prefix}messages |
|
689 |
+ WHERE id_topic = {int:topic} |
|
690 |
+ AND id_msg != {int:topic_msg}', |
|
691 |
+ array( |
|
692 |
+ 'topic' => $context['topic_id'], |
|
693 |
+ 'topic_msg' => $firstmsg, |
|
694 |
+ ) |
|
695 |
+ ); |
|
696 |
+ |
|
697 |
+ $num_replies = $smcFunc['db_num_rows']($request) + 1; // Plus one since we want to count the main ticket post as well. |
|
698 |
+ |
|
699 |
+ // The ID of the ticket we created |
|
700 |
+ $ticket = $ticketOptions['id']; |
|
701 |
+ |
|
702 |
+ if ($smcFunc['db_num_rows']($request) != 0) |
|
703 |
+ { |
|
704 |
+ // Now loop through each reply and post it. Hopefully there aren't too many. *looks at clock* |
|
705 |
+ while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
706 |
+ { |
|
707 |
+ $msgOptions = array( |
|
708 |
+ 'body' => $row['body'], |
|
709 |
+ 'smileys_enabled' => !empty($row['smileys_enabled']) ? 1 : 0, |
|
710 |
+ ); |
|
711 |
+ $ticketOptions = array( |
|
712 |
+ 'id' => $ticket, |
|
713 |
+ 'mark_as_read' => false, |
|
714 |
+ ); |
|
715 |
+ $posterOptions = array( |
|
716 |
+ 'id' => $row['id_member'], |
|
717 |
+ 'name' => !empty($row['poster_name']) ? $row['poster_name'] : '', |
|
718 |
+ 'email' => !empty($row['poster_email']) ? $row['poster_email'] : '', |
|
719 |
+ 'ip' => !empty($row['poster_ip']) ? $row['poster_ip'] : '', |
|
720 |
+ ); |
|
721 |
+ shd_create_ticket_post($msgOptions, $ticketOptions, $posterOptions); |
|
722 |
+ $msg_assoc[$row['id_msg']] = $msgOptions['id']; |
|
723 |
+ } |
|
724 |
+ } |
|
725 |
+ |
|
726 |
+ // Ticket: check; Replies: check; Notfiy the topic starter, if desired. |
|
727 |
+ if (isset($_POST['send_pm'])) |
|
728 |
+ { |
|
729 |
+ require_once($sourcedir . '/Subs-Post.php'); |
|
730 |
+ |
|
731 |
+ $request = shd_db_query('pm_find_username', ' |
|
732 |
+ SELECT id_member, real_name |
|
733 |
+ FROM {db_prefix}members |
|
734 |
+ WHERE id_member = {int:user} |
|
735 |
+ LIMIT 1', |
|
736 |
+ array( |
|
737 |
+ 'user' => $owner, |
|
738 |
+ ) |
|
739 |
+ ); |
|
740 |
+ list ($userid,$username) = $smcFunc['db_fetch_row']($request); |
|
741 |
+ $smcFunc['db_free_result']($request); |
|
742 |
+ |
|
743 |
+ // Fix the content |
|
744 |
+ $replacements = array( |
|
745 |
+ '{user}' => $username, |
|
746 |
+ '{subject}' => $old_subject, |
|
747 |
+ '{link}' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticket, |
|
748 |
+ ); |
|
749 |
+ $message = str_replace(array_keys($replacements), array_values($replacements), $_POST['pm_content']); |
|
750 |
+ |
|
751 |
+ $recipients = array( |
|
752 |
+ 'to' => array($owner), |
|
753 |
+ 'bcc' => array() |
|
754 |
+ ); |
|
755 |
+ |
|
756 |
+ sendpm($recipients, $txt['shd_ticket_moved_subject_topic'], un_htmlspecialchars($message)); |
|
757 |
+ } |
|
758 |
+ |
|
759 |
+ // And now for something completely different: attachments |
|
760 |
+ |
|
761 |
+ if (!empty($msg_assoc)) |
|
762 |
+ { |
|
763 |
+ // 1. Get all the attachments for these messages from the attachments table |
|
764 |
+ $attachIDs = array(); |
|
765 |
+ $query = shd_db_query('', ' |
|
766 |
+ SELECT id_attach, id_msg |
|
767 |
+ FROM {db_prefix}attachments |
|
768 |
+ WHERE id_msg IN ({array_int:smf_msgs})', |
|
769 |
+ array( |
|
770 |
+ 'smf_msgs' => array_keys($msg_assoc), |
|
771 |
+ ) |
|
772 |
+ ); |
|
773 |
+ |
|
774 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
775 |
+ $attachIDs[] = $row; |
|
776 |
+ $smcFunc['db_free_result']($query); |
|
777 |
+ |
|
778 |
+ if (!empty($attachIDs)) |
|
779 |
+ { |
|
780 |
+ // 2. Do the switch |
|
781 |
+ // 2.1. Add them to SD's tables |
|
782 |
+ $array = array(); |
|
783 |
+ foreach ($attachIDs as $attach) |
|
784 |
+ $array[] = array($attach['id_attach'], $ticket, $msg_assoc[$attach['id_msg']]); |
|
785 |
+ |
|
786 |
+ $smcFunc['db_insert']('replace', |
|
787 |
+ '{db_prefix}helpdesk_attachments', |
|
788 |
+ array( |
|
789 |
+ 'id_attach' => 'int', 'id_ticket' => 'int', 'id_msg' => 'int', |
|
790 |
+ ), |
|
791 |
+ $array, |
|
792 |
+ array( |
|
793 |
+ 'id_attach', |
|
794 |
+ ) |
|
795 |
+ ); |
|
796 |
+ |
|
797 |
+ // 2.2. "Remove" them from SMF's table |
|
798 |
+ shd_db_query('', ' |
|
799 |
+ UPDATE {db_prefix}attachments |
|
800 |
+ SET id_msg = 0 |
|
801 |
+ WHERE id_msg IN ({array_int:smf_msgs})', |
|
802 |
+ array( |
|
803 |
+ 'smf_msgs' => array_keys($msg_assoc), |
|
804 |
+ ) |
|
805 |
+ ); |
|
806 |
+ } |
|
807 |
+ } |
|
808 |
+ |
|
809 |
+ // Now we'll add this to the log. |
|
810 |
+ $log_params = array( |
|
811 |
+ 'subject' => $subject, |
|
812 |
+ 'ticket' => $ticket, |
|
813 |
+ ); |
|
814 |
+ shd_log_action('topictoticket', $log_params); |
|
815 |
+ |
|
816 |
+ // Update post counts. |
|
817 |
+ $request = shd_db_query('', ' |
|
818 |
+ SELECT id_member |
|
819 |
+ FROM {db_prefix}messages |
|
820 |
+ WHERE id_topic = {int:topic}', |
|
821 |
+ array( |
|
822 |
+ 'topic' => $context['topic_id'], |
|
823 |
+ ) |
|
824 |
+ ); |
|
825 |
+ $posters = array(); |
|
826 |
+ while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
827 |
+ { |
|
828 |
+ if (!isset($posters[$row['id_member']])) |
|
829 |
+ $posters[$row['id_member']] = 0; |
|
830 |
+ |
|
831 |
+ $posters[$row['id_member']]++; |
|
832 |
+ } |
|
833 |
+ $smcFunc['db_free_result']($request); |
|
834 |
+ |
|
835 |
+ foreach ($posters as $id_member => $posts) |
|
836 |
+ { |
|
837 |
+ updateMemberData($id_member, array('posts' => 'posts - ' . $posts)); |
|
838 |
+ } |
|
839 |
+ |
|
840 |
+ // Lastly, delete the topic from the database. |
|
841 |
+ shd_db_query('', ' |
|
842 |
+ DELETE FROM {db_prefix}topics |
|
843 |
+ WHERE id_topic = {int:topic} |
|
844 |
+ LIMIT 1', |
|
845 |
+ array( |
|
846 |
+ 'topic' => $context['topic_id'], |
|
847 |
+ ) |
|
848 |
+ ); |
|
849 |
+ // And the replies, too. |
|
850 |
+ shd_db_query('', ' |
|
851 |
+ DELETE FROM {db_prefix}messages |
|
852 |
+ WHERE id_topic = {int:topic}', |
|
853 |
+ array( |
|
854 |
+ 'topic' => $context['topic_id'], |
|
855 |
+ ) |
|
856 |
+ ); |
|
857 |
+ |
|
858 |
+ // Update the stats. |
|
859 |
+ require_once($sourcedir . '/Subs-Post.php'); |
|
860 |
+ updateStats('message'); |
|
861 |
+ updateStats('topic'); |
|
862 |
+ updateLastMessages($board); |
|
863 |
+ |
|
864 |
+ // Update board post counts. |
|
865 |
+ shd_db_query('', ' |
|
866 |
+ UPDATE {db_prefix}boards |
|
867 |
+ SET num_topics = num_topics - 1, |
|
868 |
+ num_posts = num_posts - {int:num_posts} |
|
869 |
+ WHERE id_board = {int:board}', |
|
870 |
+ array( |
|
871 |
+ 'board' => $board, |
|
872 |
+ 'num_posts' => $num_replies, |
|
873 |
+ ) |
|
874 |
+ ); |
|
875 |
+ } |
|
876 |
+ else |
|
877 |
+ fatal_lang_error('shd_move_ticket_not_created',false); |
|
878 |
+ |
|
879 |
+ // Clear our cache |
|
880 |
+ shd_clear_active_tickets($owner); |
|
881 |
+ |
|
882 |
+ // Send them to the ticket. |
|
883 |
+ redirectexit('action=helpdesk;sa=ticket;ticket=' . $ticket); |
|
884 |
+} |
|
885 |
+ |
|
886 |
+?> |
|
0 | 887 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,1013 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: SimpleDesk.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file serves as the entry point for SimpleDesk generally, as well as the home of the ticket listing |
|
22 |
+ * code, for open, closed and deleted tickets. |
|
23 |
+ * |
|
24 |
+ * @package source |
|
25 |
+ * @since 1.0 |
|
26 |
+ */ |
|
27 |
+ |
|
28 |
+if (!defined('SMF')) |
|
29 |
+ die('Hacking attempt...'); |
|
30 |
+ |
|
31 |
+/** |
|
32 |
+ * Begins SimpleDesk general processing. |
|
33 |
+ * |
|
34 |
+ * Several things are done here, the results of which are unilaterally assumed by all other SimpleDesk functions. |
|
35 |
+ * - load standard constants for ticket status and urgency< |
|
36 |
+ * - set up general navigation |
|
37 |
+ * - see if the URL or POST data contains a ticket, if so sanitise and store that value |
|
38 |
+ * - see if a msg was specified in the URL, if so identify the relevant ticket |
|
39 |
+ * - add in the helpdesk CSS file |
|
40 |
+ * - identify the sub action to direct them to, then send them on their way. |
|
41 |
+ * |
|
42 |
+ * @since 1.0 |
|
43 |
+*/ |
|
44 |
+function shd_main() |
|
45 |
+{ |
|
46 |
+ global $context, $txt, $settings, $sourcedir, $modSettings, $scripturl, $user_profile, $user_info, $smcFunc; |
|
47 |
+ |
|
48 |
+ // Basic sanity stuff |
|
49 |
+ if (!$modSettings['helpdesk_active']) |
|
50 |
+ fatal_lang_error('shd_inactive', false); |
|
51 |
+ |
|
52 |
+ shd_is_allowed_to('access_helpdesk'); |
|
53 |
+ |
|
54 |
+ // Load stuff: preferences the core template - and any hook-required files |
|
55 |
+ $context['shd_preferences'] = shd_load_user_prefs(); |
|
56 |
+ loadTemplate('sd_template/SimpleDesk'); |
|
57 |
+ shd_load_plugin_files('helpdesk'); |
|
58 |
+ shd_load_plugin_langfiles('helpdesk'); |
|
59 |
+ |
|
60 |
+ // List of sub actions. |
|
61 |
+ $subactions = array( |
|
62 |
+ 'main' => array(null, 'shd_main_helpdesk'), |
|
63 |
+ 'viewblock' => array(null, 'shd_view_block'), |
|
64 |
+ 'ticket' => array('SimpleDesk-Display.php', 'shd_view_ticket'), |
|
65 |
+ 'newticket' => array('SimpleDesk-Post.php', 'shd_post_ticket'), |
|
66 |
+ 'editticket' => array('SimpleDesk-Post.php', 'shd_post_ticket'), |
|
67 |
+ 'saveticket' => array('SimpleDesk-Post.php', 'shd_save_post'), // this is the equivalent of post2 |
|
68 |
+ 'reply' => array('SimpleDesk-Post.php', 'shd_post_reply'), |
|
69 |
+ 'savereply' => array('SimpleDesk-Post.php', 'shd_save_post'), |
|
70 |
+ 'editreply' => array('SimpleDesk-Post.php', 'shd_post_reply'), |
|
71 |
+ 'markunread' => array('SimpleDesk-MiscActions.php', 'shd_ticket_unread'), |
|
72 |
+ 'assign' => array('SimpleDesk-Assign.php', 'shd_assign'), |
|
73 |
+ 'assign2' => array('SimpleDesk-Assign.php', 'shd_assign2'), |
|
74 |
+ 'resolveticket' => array('SimpleDesk-MiscActions.php', 'shd_ticket_resolve'), |
|
75 |
+ 'relation' => array('SimpleDesk-MiscActions.php', 'shd_ticket_relation'), |
|
76 |
+ 'ajax' => array('SimpleDesk-AjaxHandler.php', 'shd_ajax'), |
|
77 |
+ 'privacychange' => array('SimpleDesk-MiscActions.php', 'shd_privacy_change_noajax'), |
|
78 |
+ 'urgencychange' => array('SimpleDesk-MiscActions.php', 'shd_urgency_change_noajax'), |
|
79 |
+ 'closedtickets' => array(null, 'shd_closed_tickets'), |
|
80 |
+ 'recyclebin' => array(null, 'shd_recycle_bin'), |
|
81 |
+ 'tickettotopic' => array('SimpleDesk-TicketTopicMove.php', 'shd_tickettotopic'), |
|
82 |
+ 'tickettotopic2' => array('SimpleDesk-TicketTopicMove.php', 'shd_tickettotopic2'), |
|
83 |
+ 'topictoticket' => array('SimpleDesk-TicketTopicMove.php', 'shd_topictoticket'), |
|
84 |
+ 'topictoticket2' => array('SimpleDesk-TicketTopicMove.php', 'shd_topictoticket2'), |
|
85 |
+ 'permadelete' => array('SimpleDesk-Delete.php', 'shd_perma_delete'), |
|
86 |
+ 'deleteticket' => array('SimpleDesk-Delete.php', 'shd_ticket_delete'), |
|
87 |
+ 'deletereply' => array('SimpleDesk-Delete.php', 'shd_reply_delete'), |
|
88 |
+ 'restoreticket' => array('SimpleDesk-Delete.php', 'shd_ticket_restore'), |
|
89 |
+ 'restorereply' => array('SimpleDesk-Delete.php', 'shd_reply_restore'), |
|
90 |
+ 'mergeticket' => array('SimpleDesk-MergeSplit.php', 'shd_merge_ticket'), |
|
91 |
+ 'mergeticket2' => array('SimpleDesk-MergeSplit.php', 'shd_merge_ticket2'), |
|
92 |
+ 'splitticket' => array('SimpleDesk-MergeSplit.php', 'shd_split_ticket'), |
|
93 |
+ 'splitticket2' => array('SimpleDesk-MergeSplit.php', 'shd_split_ticket2'), |
|
94 |
+ ); |
|
95 |
+ |
|
96 |
+ // Navigation menu |
|
97 |
+ $context['navigation'] = array( |
|
98 |
+ 'main' => array( |
|
99 |
+ 'text' => 'shd_home', |
|
100 |
+ 'lang' => true, |
|
101 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
102 |
+ ), |
|
103 |
+ 'newticket' => array( |
|
104 |
+ 'text' => 'shd_new_ticket', |
|
105 |
+ 'test' => 'can_new_ticket', |
|
106 |
+ 'lang' => true, |
|
107 |
+ 'url' => $scripturl . '?action=helpdesk;sa=newticket', |
|
108 |
+ ), |
|
109 |
+ 'newticketproxy' => array( |
|
110 |
+ 'text' => 'shd_new_ticket_proxy', |
|
111 |
+ 'test' => 'can_proxy_ticket', |
|
112 |
+ 'lang' => true, |
|
113 |
+ 'url' => $scripturl . '?action=helpdesk;sa=newticket;proxy', |
|
114 |
+ ), |
|
115 |
+ 'closedtickets' => array( |
|
116 |
+ 'text' => 'shd_tickets_closed', |
|
117 |
+ 'test' => 'can_view_closed', |
|
118 |
+ 'lang' => true, |
|
119 |
+ 'url' => $scripturl . '?action=helpdesk;sa=closedtickets', |
|
120 |
+ ), |
|
121 |
+ 'recyclebin' => array( |
|
122 |
+ 'text' => 'shd_recycle_bin', |
|
123 |
+ 'test' => 'can_view_recycle', |
|
124 |
+ 'lang' => true, |
|
125 |
+ 'url' => $scripturl . '?action=helpdesk;sa=recyclebin', |
|
126 |
+ ), |
|
127 |
+ // Only for certain sub areas. |
|
128 |
+ 'back' => array( |
|
129 |
+ 'text' => 'shd_back_to_hd', |
|
130 |
+ 'test' => 'display_back_to_hd', |
|
131 |
+ 'lang' => true, |
|
132 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
133 |
+ ), |
|
134 |
+ ); |
|
135 |
+ |
|
136 |
+ // Build the link tree. |
|
137 |
+ $context['linktree'][] = array( |
|
138 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
139 |
+ 'name' => $txt['shd_helpdesk'], |
|
140 |
+ ); |
|
141 |
+ |
|
142 |
+ // See if a ticket has been specified, like $topic can be. |
|
143 |
+ if (!empty($_REQUEST['ticket'])) |
|
144 |
+ { |
|
145 |
+ if (strpos($_REQUEST['ticket'], '.') === false) |
|
146 |
+ { |
|
147 |
+ $context['ticket_id'] = (int) $_REQUEST['ticket']; |
|
148 |
+ $context['ticket_start'] = 0; |
|
149 |
+ } |
|
150 |
+ else |
|
151 |
+ { |
|
152 |
+ list ($context['ticket_id'], $context['ticket_start']) = explode('.', $_REQUEST['ticket']); |
|
153 |
+ $context['ticket_id'] = (int) $context['ticket_id']; |
|
154 |
+ if (!is_numeric($context['ticket_start'])) |
|
155 |
+ { |
|
156 |
+ // Let's see if it's 'new' first. If it is, great, we'll figure out the new point then throw it at the next one. |
|
157 |
+ if (substr($context['ticket_start'], 0, 3) == 'new') |
|
158 |
+ { |
|
159 |
+ $query = shd_db_query('', ' |
|
160 |
+ SELECT IFNULL(hdlr.id_msg, -1) + 1 AS new_from |
|
161 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
162 |
+ LEFT JOIN {db_prefix}helpdesk_log_read AS hdlr ON (hdlr.id_ticket = {int:ticket} AND hdlr.id_member = {int:member}) |
|
163 |
+ WHERE {query_see_ticket} |
|
164 |
+ AND hdt.id_ticket = {int:ticket} |
|
165 |
+ LIMIT 1', |
|
166 |
+ array( |
|
167 |
+ 'member' => $user_info['id'], |
|
168 |
+ 'ticket' => $context['ticket_id'], |
|
169 |
+ ) |
|
170 |
+ ); |
|
171 |
+ list ($new_from) = $smcFunc['db_fetch_row']($query); |
|
172 |
+ $smcFunc['db_free_result']($query); |
|
173 |
+ $context['ticket_start'] = 'msg' . $new_from; |
|
174 |
+ $context['ticket_start_newfrom'] = $new_from; |
|
175 |
+ } |
|
176 |
+ |
|
177 |
+ if (substr($context['ticket_start'], 0, 3) == 'msg') |
|
178 |
+ { |
|
179 |
+ $virtual_msg = (int) substr($context['ticket_start'], 3); |
|
180 |
+ $query = shd_db_query('', ' |
|
181 |
+ SELECT COUNT(hdtr.id_msg) |
|
182 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
183 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket) |
|
184 |
+ WHERE {query_see_ticket} |
|
185 |
+ AND hdtr.id_ticket = {int:ticket} |
|
186 |
+ AND hdtr.id_msg > hdt.id_first_msg |
|
187 |
+ AND hdtr.id_msg < {int:virtual_msg}' . (!isset($_GET['recycle']) ? ' |
|
188 |
+ AND hdtr.message_status = {int:message_notdel}' : ''), |
|
189 |
+ array( |
|
190 |
+ 'ticket' => $context['ticket_id'], |
|
191 |
+ 'virtual_msg' => $virtual_msg, |
|
192 |
+ 'message_notdel' => MSG_STATUS_NORMAL, |
|
193 |
+ ) |
|
194 |
+ ); |
|
195 |
+ list ($context['ticket_start']) = $smcFunc['db_fetch_row']($query); |
|
196 |
+ $smcFunc['db_free_result']($query); |
|
197 |
+ } |
|
198 |
+ } |
|
199 |
+ else |
|
200 |
+ $context['ticket_start'] = (int) $context['ticket_start']; // it IS numeric but let's make sure it's the right kind of number |
|
201 |
+ } |
|
202 |
+ } |
|
203 |
+ if (empty($context['ticket_start_newfrom'])) |
|
204 |
+ $context['ticket_start_newfrom'] = empty($context['ticket_start']) ? 0 : $context['ticket_start']; |
|
205 |
+ |
|
206 |
+ // Do we have just a message id? We can get the ticket from that - but only if we don't already have a ticket id! |
|
207 |
+ $_REQUEST['msg'] = !empty($_REQUEST['msg']) ? (int) $_REQUEST['msg'] : 0; |
|
208 |
+ if (!empty($_REQUEST['msg']) && empty($context['ticket_id'])) |
|
209 |
+ { |
|
210 |
+ $query = shd_db_query('', ' |
|
211 |
+ SELECT hdt.id_ticket, hdtr.id_msg |
|
212 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
213 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket) |
|
214 |
+ WHERE {query_see_ticket} |
|
215 |
+ AND hdtr.id_msg = {int:msg}', |
|
216 |
+ array( |
|
217 |
+ 'msg' => $_REQUEST['msg'], |
|
218 |
+ ) |
|
219 |
+ ); |
|
220 |
+ |
|
221 |
+ if ($row = $smcFunc['db_fetch_row']($query)) |
|
222 |
+ $context['ticket_id'] = (int) $row[0]; |
|
223 |
+ |
|
224 |
+ $smcFunc['db_free_result']($query); |
|
225 |
+ } |
|
226 |
+ |
|
227 |
+ $context['items_per_page'] = 10; |
|
228 |
+ $context['start'] = isset($_REQUEST['start']) ? $_REQUEST['start'] : 0; |
|
229 |
+ |
|
230 |
+ // Load the custom CSS. |
|
231 |
+ if (empty($context['html_headers'])) |
|
232 |
+ $context['html_headers'] = ''; |
|
233 |
+ |
|
234 |
+ $context['html_headers'] .= ' |
|
235 |
+ <link rel="stylesheet" type="text/css" href="' . (file_exists($settings['theme_dir'] . '/css/helpdesk.css') ? $settings['theme_url'] . '/css/helpdesk.css' : $settings['default_theme_url'] . '/css/helpdesk.css') . '" /> |
|
236 |
+ <script type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/helpdesk.js?rc2"></script>'; |
|
237 |
+ |
|
238 |
+ // Darn IE6. Die, already :( |
|
239 |
+ if ($context['browser']['is_ie6']) |
|
240 |
+ $context['html_headers'] .= ' |
|
241 |
+ <!-- Fall back, dark force, for we shall thou evil powers not endorse --> |
|
242 |
+ <link rel="stylesheet" type="text/css" href="' . $settings['default_theme_url'] . '/css/helpdesk_ie6.css" />'; |
|
243 |
+ |
|
244 |
+ // Int hooks - after we basically set everything up (so it's manipulatable by the hook, but before we do the last bits of finalisation) |
|
245 |
+ if (!empty($modSettings['shd_hook_helpdesk'])) |
|
246 |
+ { |
|
247 |
+ $functions = explode(',', $modSettings['shd_hook_helpdesk']); |
|
248 |
+ foreach ($functions as $function) |
|
249 |
+ { |
|
250 |
+ if (is_callable($function)) |
|
251 |
+ $function($subactions); // this should be picked up by reference in the called function or it won't do anything! (everything else is in $context) |
|
252 |
+ } |
|
253 |
+ } |
|
254 |
+ |
|
255 |
+ // What are we doing? |
|
256 |
+ $_REQUEST['sa'] = (!empty($_REQUEST['sa']) && isset($subactions[$_REQUEST['sa']])) ? $_REQUEST['sa'] : 'main'; |
|
257 |
+ $context['sub_action'] = $subactions[$_REQUEST['sa']]; |
|
258 |
+ |
|
259 |
+ $context['can_new_ticket'] = shd_allowed_to('shd_new_ticket'); |
|
260 |
+ $context['can_proxy_ticket'] = $context['can_new_ticket'] && shd_allowed_to('shd_post_proxy'); |
|
261 |
+ $context['can_view_closed'] = shd_allowed_to('shd_resolve_ticket_own') || shd_allowed_to('shd_resolve_ticket_any'); |
|
262 |
+ $context['can_view_recycle'] = shd_allowed_to('shd_access_recyclebin'); |
|
263 |
+ $context['display_back_to_hd'] = !in_array($_REQUEST['sa'], array('main', 'viewblock', 'recyclebin', 'closedtickets')); |
|
264 |
+ |
|
265 |
+ // Highlight the correct button. |
|
266 |
+ if (isset($context['navigation'][$_REQUEST['sa']])) |
|
267 |
+ $context['navigation'][$_REQUEST['sa']]['active'] = true; |
|
268 |
+ |
|
269 |
+ // Send them away. |
|
270 |
+ if ($context['sub_action'][0] !== null) |
|
271 |
+ require ($sourcedir . '/sd_source/' . $context['sub_action'][0]); |
|
272 |
+ |
|
273 |
+ $context['sub_action'][1](); |
|
274 |
+ |
|
275 |
+ // Maintenance mode? If it were, the helpdesk is considered inactive for the purposes of everything to all but those without admin-helpdesk rights - but we must have them if we're here! |
|
276 |
+ if (!empty($modSettings['shd_maintenance_mode']) && $_REQUEST['sa'] != 'ajax') |
|
277 |
+ $context['template_layers'][] = 'shd_maintenance'; |
|
278 |
+} |
|
279 |
+ |
|
280 |
+/** |
|
281 |
+ * Display the main front page, showing tickets waiting for staff, waiting for user feedback and so on. |
|
282 |
+ * |
|
283 |
+ * This function sets up multiple blocks to be shown to users, defines what columns these blocks should have and states |
|
284 |
+ * the rules to be used in getting the data. |
|
285 |
+ * |
|
286 |
+ * Each block has multiple parameters, and is stated in $context['ticket_blocks']: |
|
287 |
+ * <ul> |
|
288 |
+ * <li>block_icon: which image to use in Themes/default/images/simpledesk for denoting the type of block; filename plus extension</li> |
|
289 |
+ * <li>title: the text string to use as the block's heading</li> |
|
290 |
+ * <li>where: an SQL clause denoting the rule for obtaining the items in this block</li> |
|
291 |
+ * <li>display: whether the block should be processed and prepared for display</li> |
|
292 |
+ * <li>count: the number of items in this block, for pagination; generally should be a call to {@link shd_count_helpdesk_tickets()}</li> |
|
293 |
+ * <li>columns: an array of columns to display in this block, in the order they should be displayed, using the following options, derived from {@link shd_get_block_columns()}: |
|
294 |
+ * <ul> |
|
295 |
+ * <li>ticket_id: the ticket's read status, privacy icon, and id</li> |
|
296 |
+ * <li>ticket_name: name/link to the ticket</li> |
|
297 |
+ * <li>starting_user: profile link to the user who opened the ticket</li> |
|
298 |
+ * <li>replies: number of (visible) replies in the ticket</li> |
|
299 |
+ * <li>allreplies: number of (all) replies in the ticket (includes deleted replies, which 'replies' does not)</li> |
|
300 |
+ * <li>last_reply: the user who last replied</li> |
|
301 |
+ * <li>status: the current ticket's status</li> |
|
302 |
+ * <li>assigned: link to the profile of the user the ticket is assigned to, or 'Unassigned' if not assigned</li> |
|
303 |
+ * <li>urgency: the current ticket's urgency</li> |
|
304 |
+ * <li>updated: time of the last reply in the ticket; states Never if no replies</li> |
|
305 |
+ * <li>actions: icons that may or may not relate to a given ticket; buttons for recycle, delete, unresolve live in this column</li> |
|
306 |
+ * </ul> |
|
307 |
+ * <li>required: whether the block is required to be displayed even if empty</li> |
|
308 |
+ * <li>collapsed: whether the block should be compressed to a header with count of tickets or not (mostly for {@link shd_view_block()}'s benefit)</li> |
|
309 |
+ * </ul> |
|
310 |
+ * |
|
311 |
+ * This function declares the following blocks: |
|
312 |
+ * <ul> |
|
313 |
+ * <li>Assigned to me (staff only)</li> |
|
314 |
+ * <li>New tickets (staff only)</li> |
|
315 |
+ * <li>Pending with staff (for staff, this is just tickets with that status, for regular users this is both pending staff and new unreplied to tickets)</li> |
|
316 |
+ * <li>Pending with user (both)</li> |
|
317 |
+ * </ul> |
|
318 |
+ * |
|
319 |
+ * @see shd_count_helpdesk_tickets() |
|
320 |
+ * @since 1.0 |
|
321 |
+*/ |
|
322 |
+function shd_main_helpdesk() |
|
323 |
+{ |
|
324 |
+ global $context, $txt, $smcFunc, $user_profile, $scripturl, $user_info; |
|
325 |
+ |
|
326 |
+ $is_staff = shd_allowed_to('shd_staff'); |
|
327 |
+ // Stuff we need to add to $context, page title etc etc |
|
328 |
+ $context += array( |
|
329 |
+ 'page_title' => $txt['shd_helpdesk'], |
|
330 |
+ 'sub_template' => 'main', |
|
331 |
+ 'ticket_blocks' => array( // the numbers tie back to the master status idents |
|
332 |
+ 'assigned' => array( |
|
333 |
+ 'block_icon' => 'assign.png', |
|
334 |
+ 'title' => $txt['shd_status_assigned_heading'], |
|
335 |
+ 'where' => 'hdt.id_member_assigned = ' . $user_info['id'] . ' AND hdt.status NOT IN (' . TICKET_STATUS_CLOSED . ',' . TICKET_STATUS_DELETED . ')', |
|
336 |
+ 'display' => $is_staff, |
|
337 |
+ 'count' => shd_count_helpdesk_tickets('assigned'), |
|
338 |
+ 'columns' => shd_get_block_columns('assigned'), |
|
339 |
+ 'required' => $is_staff, |
|
340 |
+ 'collapsed' => false, |
|
341 |
+ ), |
|
342 |
+ 'new' => array( |
|
343 |
+ 'block_icon' => 'status.png', |
|
344 |
+ 'title' => $txt['shd_status_' . TICKET_STATUS_NEW . '_heading'], |
|
345 |
+ 'where' => 'hdt.id_member_assigned != ' . $user_info['id'] . ' AND hdt.status = ' . TICKET_STATUS_NEW, |
|
346 |
+ 'display' => $is_staff, |
|
347 |
+ 'count' => shd_count_helpdesk_tickets('new'), |
|
348 |
+ 'columns' => shd_get_block_columns('new'), |
|
349 |
+ 'required' => false, |
|
350 |
+ 'collapsed' => false, |
|
351 |
+ ), |
|
352 |
+ 'staff' => array( |
|
353 |
+ 'block_icon' => 'staff.png', |
|
354 |
+ 'title' => $txt['shd_status_' . TICKET_STATUS_PENDING_STAFF . '_heading'], |
|
355 |
+ 'where' => $is_staff ? ('hdt.id_member_assigned != ' . $user_info['id'] . ' AND hdt.status = ' . TICKET_STATUS_PENDING_STAFF) : ('hdt.status IN (' . TICKET_STATUS_NEW . ',' . TICKET_STATUS_PENDING_STAFF . ')'), // put new and with staff together in 'waiting for staff' for end user |
|
356 |
+ 'display' => true, |
|
357 |
+ 'count' => shd_count_helpdesk_tickets('staff', $is_staff), |
|
358 |
+ 'columns' => shd_get_block_columns('staff'), |
|
359 |
+ 'required' => true, |
|
360 |
+ 'collapsed' => false, |
|
361 |
+ ), |
|
362 |
+ 'user' => array( |
|
363 |
+ 'block_icon' => 'user.png', |
|
364 |
+ 'title' => $txt['shd_status_' . TICKET_STATUS_PENDING_USER . '_heading'], |
|
365 |
+ 'where' => $is_staff ? ('hdt.id_member_assigned != ' . $user_info['id'] . ' AND hdt.status = ' . TICKET_STATUS_PENDING_USER) : ('hdt.status = ' . TICKET_STATUS_PENDING_USER), |
|
366 |
+ 'display' => true, |
|
367 |
+ 'count' => shd_count_helpdesk_tickets('with_user'), |
|
368 |
+ 'columns' => shd_get_block_columns($is_staff ? 'user_staff' : 'user_user'), |
|
369 |
+ 'required' => true, |
|
370 |
+ 'collapsed' => false, |
|
371 |
+ ), |
|
372 |
+ ), |
|
373 |
+ 'shd_home_view' => shd_allowed_to('shd_staff') ? 'staff' : 'user', |
|
374 |
+ ); |
|
375 |
+ |
|
376 |
+ shd_helpdesk_listing(); |
|
377 |
+} |
|
378 |
+ |
|
379 |
+/** |
|
380 |
+ * Sets up viewing of a single block without any pagination. |
|
381 |
+ * |
|
382 |
+ * This provides the ability to see all of a given type of ticket at once without paging through them, which are all sortable. |
|
383 |
+ * |
|
384 |
+ * @see shd_main_helpdesk() |
|
385 |
+ * @since 1.0 |
|
386 |
+*/ |
|
387 |
+function shd_view_block() |
|
388 |
+{ |
|
389 |
+ global $context, $txt, $smcFunc, $user_profile, $scripturl, $user_info; |
|
390 |
+ |
|
391 |
+ $is_staff = shd_allowed_to('shd_staff'); |
|
392 |
+ // Stuff we need to add to $context, page title etc etc |
|
393 |
+ $context += array( |
|
394 |
+ 'page_title' => $txt['shd_helpdesk'], |
|
395 |
+ 'sub_template' => 'main', |
|
396 |
+ 'ticket_blocks' => array( // the numbers tie back to the master status idents |
|
397 |
+ 'assigned' => array( |
|
398 |
+ 'block_icon' => 'assign.png', |
|
399 |
+ 'title' => $txt['shd_status_assigned_heading'], |
|
400 |
+ 'where' => 'hdt.id_member_assigned = ' . $user_info['id'] . ' AND hdt.status NOT IN (' . TICKET_STATUS_CLOSED . ',' . TICKET_STATUS_DELETED . ')', |
|
401 |
+ 'display' => $is_staff, |
|
402 |
+ 'count' => shd_count_helpdesk_tickets('assigned'), |
|
403 |
+ 'columns' => shd_get_block_columns('assigned'), |
|
404 |
+ 'required' => $is_staff, |
|
405 |
+ 'collapsed' => false, |
|
406 |
+ ), |
|
407 |
+ 'new' => array( |
|
408 |
+ 'block_icon' => 'status.png', |
|
409 |
+ 'title' => $txt['shd_status_' . TICKET_STATUS_NEW . '_heading'], |
|
410 |
+ 'where' => 'hdt.id_member_assigned != ' . $user_info['id'] . ' AND hdt.status = ' . TICKET_STATUS_NEW, |
|
411 |
+ 'display' => $is_staff, |
|
412 |
+ 'count' => shd_count_helpdesk_tickets('new'), |
|
413 |
+ 'columns' => shd_get_block_columns('new'), |
|
414 |
+ 'required' => false, |
|
415 |
+ 'collapsed' => false, |
|
416 |
+ ), |
|
417 |
+ 'staff' => array( |
|
418 |
+ 'block_icon' => 'staff.png', |
|
419 |
+ 'title' => $txt['shd_status_' . TICKET_STATUS_PENDING_STAFF . '_heading'], |
|
420 |
+ 'where' => $is_staff ? ('hdt.id_member_assigned != ' . $user_info['id'] . ' AND hdt.status = ' . TICKET_STATUS_PENDING_STAFF) : ('hdt.status IN (' . TICKET_STATUS_NEW . ',' . TICKET_STATUS_PENDING_STAFF . ')'), // put new and with staff together in 'waiting for staff' for end user |
|
421 |
+ 'display' => true, |
|
422 |
+ 'count' => shd_count_helpdesk_tickets('staff', $is_staff), |
|
423 |
+ 'columns' => shd_get_block_columns('staff'), |
|
424 |
+ 'required' => true, |
|
425 |
+ 'collapsed' => false, |
|
426 |
+ ), |
|
427 |
+ 'user' => array( |
|
428 |
+ 'block_icon' => 'user.png', |
|
429 |
+ 'title' => $txt['shd_status_' . TICKET_STATUS_PENDING_USER . '_heading'], |
|
430 |
+ 'where' => $is_staff ? ('hdt.id_member_assigned != ' . $user_info['id'] . ' AND hdt.status = ' . TICKET_STATUS_PENDING_USER) : ('hdt.status = ' . TICKET_STATUS_PENDING_USER), |
|
431 |
+ 'display' => true, |
|
432 |
+ 'count' => shd_count_helpdesk_tickets('with_user'), |
|
433 |
+ 'columns' => shd_get_block_columns($is_staff ? 'user_staff' : 'user_user'), |
|
434 |
+ 'required' => true, |
|
435 |
+ 'collapsed' => false, |
|
436 |
+ ), |
|
437 |
+ ), |
|
438 |
+ 'shd_home_view' => shd_allowed_to('shd_staff') ? 'staff' : 'user', |
|
439 |
+ ); |
|
440 |
+ |
|
441 |
+ if (empty($_REQUEST['block']) || empty($context['ticket_blocks'][$_REQUEST['block']]) || empty($context['ticket_blocks'][$_REQUEST['block']]['count'])) |
|
442 |
+ redirectexit('action=helpdesk;sa=main'); |
|
443 |
+ |
|
444 |
+ $context['items_per_page'] = 10; |
|
445 |
+ foreach ($context['ticket_blocks'] as $block => $details) |
|
446 |
+ { |
|
447 |
+ if ($block == $_REQUEST['block']) |
|
448 |
+ $context['items_per_page'] = $details['count']; |
|
449 |
+ else |
|
450 |
+ $context['ticket_blocks'][$block]['collapsed'] = true; |
|
451 |
+ } |
|
452 |
+ |
|
453 |
+ shd_helpdesk_listing(); |
|
454 |
+} |
|
455 |
+ |
|
456 |
+/** |
|
457 |
+ * Set up the paginated lists of closed tickets. |
|
458 |
+ * |
|
459 |
+ * Much like the main helpdesk, this function prepares a list of all the closed/resolved tickets, with a more specific |
|
460 |
+ * list of columns that is better suited to resolved tickets. |
|
461 |
+ * |
|
462 |
+ * @see shd_main_helpdesk() |
|
463 |
+ * @since 1.0 |
|
464 |
+*/ |
|
465 |
+function shd_closed_tickets() |
|
466 |
+{ |
|
467 |
+ global $context, $txt, $smcFunc, $user_profile, $scripturl, $settings, $user_info; |
|
468 |
+ |
|
469 |
+ if (!shd_allowed_to('shd_resolve_ticket_own') && !shd_allowed_to('shd_resolve_ticket_any')) |
|
470 |
+ fatal_lang_error('shd_cannot_view_resolved', false); |
|
471 |
+ |
|
472 |
+ // Stuff we need to add to $context, the permission we want to use, page title etc etc |
|
473 |
+ $context += array( |
|
474 |
+ 'page_title' => $txt['shd_helpdesk'], |
|
475 |
+ 'sub_template' => 'closedtickets', |
|
476 |
+ 'ticket_blocks' => array( |
|
477 |
+ 'closed' => array( |
|
478 |
+ 'block_icon' => 'resolved.png', |
|
479 |
+ 'title' => $txt['shd_status_' . TICKET_STATUS_CLOSED . '_heading'], |
|
480 |
+ 'where' => 'hdt.status = ' . TICKET_STATUS_CLOSED, |
|
481 |
+ 'display' => true, |
|
482 |
+ 'count' => shd_count_helpdesk_tickets('closed'), |
|
483 |
+ 'columns' => shd_get_block_columns('closed'), |
|
484 |
+ 'required' => true, |
|
485 |
+ 'collapsed' => false, |
|
486 |
+ ), |
|
487 |
+ ), |
|
488 |
+ 'shd_home_view' => shd_allowed_to('shd_staff') ? 'staff' : 'user', // This might be removed in the future. We do this here to be able to re-use template_ticket_block() in the template. |
|
489 |
+ ); |
|
490 |
+ |
|
491 |
+ // Build the link tree. |
|
492 |
+ $context['linktree'][] = array( |
|
493 |
+ 'url' => $scripturl . '?action=helpdesk;sa=main', |
|
494 |
+ 'name' => $txt['shd_linktree_tickets'], |
|
495 |
+ ); |
|
496 |
+ $context['linktree'][] = array( |
|
497 |
+ 'url' => $scripturl . '?action=helpdesk;sa=closedtickets', |
|
498 |
+ 'name' => $txt['shd_tickets_closed'], |
|
499 |
+ ); |
|
500 |
+ |
|
501 |
+ shd_helpdesk_listing(); |
|
502 |
+} |
|
503 |
+ |
|
504 |
+/** |
|
505 |
+ * Set up the paginated lists of deleted/recyclebin tickets. |
|
506 |
+ * |
|
507 |
+ * Much like the main helpdesk, this function prepares a list of all the deleted tickets, with a more specific |
|
508 |
+ * list of columns that is better suited to recyclable or permadeletable tickets. |
|
509 |
+ * |
|
510 |
+ * @see shd_main_helpdesk() |
|
511 |
+ * @since 1.0 |
|
512 |
+*/ |
|
513 |
+function shd_recycle_bin() |
|
514 |
+{ |
|
515 |
+ global $context, $txt, $smcFunc, $user_profile, $scripturl, $settings, $user_info; |
|
516 |
+ |
|
517 |
+ // Stuff we need to add to $context, the permission we want to use, page title etc etc |
|
518 |
+ $context += array( |
|
519 |
+ 'shd_permission' => 'shd_access_recyclebin', |
|
520 |
+ 'page_title' => $txt['shd_helpdesk'], |
|
521 |
+ 'sub_template' => 'recyclebin', |
|
522 |
+ 'ticket_blocks' => array( |
|
523 |
+ 'recycle' => array( |
|
524 |
+ 'block_icon' => 'recycle.png', |
|
525 |
+ 'title' => $txt['shd_status_' . TICKET_STATUS_DELETED . '_heading'], |
|
526 |
+ 'tickets' => array(), |
|
527 |
+ 'where' => 'hdt.status = ' . TICKET_STATUS_DELETED, |
|
528 |
+ 'display' => true, |
|
529 |
+ 'count' => shd_count_helpdesk_tickets('recycled'), |
|
530 |
+ 'columns' => shd_get_block_columns('recycled'), |
|
531 |
+ 'required' => true, |
|
532 |
+ 'collapsed' => false, |
|
533 |
+ ), |
|
534 |
+ 'withdeleted' => array( |
|
535 |
+ 'block_icon' => 'recycle.png', |
|
536 |
+ 'title' => $txt['shd_status_withdeleted_heading'], |
|
537 |
+ 'tickets' => array(), |
|
538 |
+ 'where' => 'hdt.status != ' . TICKET_STATUS_DELETED . ' AND hdt.deleted_replies > 0', |
|
539 |
+ 'display' => true, |
|
540 |
+ 'count' => shd_count_helpdesk_tickets('withdeleted'), |
|
541 |
+ 'columns' => shd_get_block_columns('withdeleted'), |
|
542 |
+ 'required' => true, |
|
543 |
+ 'collapsed' => false, |
|
544 |
+ ), |
|
545 |
+ ), |
|
546 |
+ ); |
|
547 |
+ |
|
548 |
+ // Build the link tree. |
|
549 |
+ $context['linktree'][] = array( |
|
550 |
+ 'url' => $scripturl . '?action=helpdesk;sa=recyclebin', |
|
551 |
+ 'name' => $txt['shd_recycle_bin'], |
|
552 |
+ ); |
|
553 |
+ |
|
554 |
+ shd_helpdesk_listing(); |
|
555 |
+} |
|
556 |
+ |
|
557 |
+/** |
|
558 |
+ * Gather the data and prepare to display the ticket blocks. |
|
559 |
+ * |
|
560 |
+ * Actually performs the queries to get data for each block, subject to the parameters specified by the calling functions. |
|
561 |
+ * |
|
562 |
+ * It also sets up per-block pagination links, collects a variety of data (enough to populate all the columns as listed in shd_main_helpdesk, |
|
563 |
+ * even if not entirely applicable, and populates it all into $context['ticket_blocks']['tickets'], extending the array that was |
|
564 |
+ * already there. |
|
565 |
+ * |
|
566 |
+ * @see shd_main_helpdesk() |
|
567 |
+ * @see shd_closed_tickets() |
|
568 |
+ * @see shd_recycle_bin() |
|
569 |
+ * @since 1.0 |
|
570 |
+*/ |
|
571 |
+function shd_helpdesk_listing() |
|
572 |
+{ |
|
573 |
+ global $context, $txt, $smcFunc, $user_profile, $scripturl, $settings, $user_info, $modSettings, $language; |
|
574 |
+ |
|
575 |
+ if (!empty($context['shd_permission'])) |
|
576 |
+ shd_is_allowed_to($context['shd_permission']); |
|
577 |
+ |
|
578 |
+ // So, we want the [new] icon. Where is it? |
|
579 |
+ $newimgpaths = array( |
|
580 |
+ $settings['theme_dir'] . '/images/' . $language => $settings['lang_images_url'], |
|
581 |
+ $settings['theme_dir'] . '/images/english' => $settings['images_url'] . '/english', |
|
582 |
+ $settings['default_theme_dir'] . '/images/' . $language => $settings['default_images_url'] . '/' . $language, |
|
583 |
+ ); |
|
584 |
+ $files = array('new.gif', 'new.png'); |
|
585 |
+ $context['new_posts_image'] = $settings['default_images_url'] . '/english/new.gif'; // likely default, but we'll check the theme etc first just in case. |
|
586 |
+ foreach ($newimgpaths as $physicalpath => $urlpath) |
|
587 |
+ { |
|
588 |
+ foreach ($files as $file) |
|
589 |
+ { |
|
590 |
+ if (file_exists($physicalpath . '/' . $file)) |
|
591 |
+ { |
|
592 |
+ $context['new_posts_image'] = $urlpath . '/' . $file; |
|
593 |
+ break 2; |
|
594 |
+ } |
|
595 |
+ } |
|
596 |
+ } |
|
597 |
+ |
|
598 |
+ $num_per_page = $context['items_per_page']; |
|
599 |
+ $block_list = array_keys($context['ticket_blocks']); |
|
600 |
+ $primary_url = '?action=helpdesk;sa=' . $_REQUEST['sa']; |
|
601 |
+ |
|
602 |
+ // First figure out the start positions of each item and sanitise them |
|
603 |
+ foreach ($context['ticket_blocks'] as $block_key => $block) |
|
604 |
+ { |
|
605 |
+ $start = empty($_REQUEST['st_' . $block_key]) ? 0 : (int) $_REQUEST['st_' . $block_key]; |
|
606 |
+ $max_value = $block['count']; // easier to read |
|
607 |
+ |
|
608 |
+ if ($start < 0) |
|
609 |
+ $start = 0; |
|
610 |
+ elseif ($start >= $max_value) |
|
611 |
+ $start = max(0, (int) $max_value - (((int) $max_value % (int) $num_per_page) == 0 ? $num_per_page : ((int) $max_value % (int) $num_per_page))); |
|
612 |
+ else |
|
613 |
+ $start = max(0, (int) $start - ((int) $start % (int) $num_per_page)); |
|
614 |
+ |
|
615 |
+ $context['ticket_blocks'][$block_key]['start'] = $start; |
|
616 |
+ if ($start != 0) |
|
617 |
+ $_REQUEST['st_' . $block_key] = $start; // sanitise! |
|
618 |
+ elseif (isset($_REQUEST['st_' . $block_key])) |
|
619 |
+ unset($_REQUEST['st_' . $block_key]); |
|
620 |
+ } |
|
621 |
+ |
|
622 |
+ // Now ordering the columns, separate loop for breaking the two processes apart |
|
623 |
+ $sort_methods = array( |
|
624 |
+ 'ticketid' => array( |
|
625 |
+ 'sql' => 'hdt.id_ticket', |
|
626 |
+ ), |
|
627 |
+ 'ticketname' => array( |
|
628 |
+ 'sql' => 'hdt.subject', |
|
629 |
+ ), |
|
630 |
+ 'replies' => array( |
|
631 |
+ 'sql' => 'hdt.num_replies', |
|
632 |
+ ), |
|
633 |
+ 'allreplies' => array( |
|
634 |
+ 'sql' => '(hdt.num_replies + hdt.deleted_replies)', |
|
635 |
+ ), |
|
636 |
+ 'urgency' => array( |
|
637 |
+ 'sql' => 'hdt.urgency', |
|
638 |
+ ), |
|
639 |
+ 'updated' => array( |
|
640 |
+ 'sql' => 'hdt.id_last_msg', |
|
641 |
+ ), |
|
642 |
+ 'assigned' => array( |
|
643 |
+ 'sql' => 'assigned_name', |
|
644 |
+ 'sql_select' => 'IFNULL(mem.real_name, 0) AS assigned_name', |
|
645 |
+ 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdt.id_member_assigned = mem.id_member)', |
|
646 |
+ ), |
|
647 |
+ 'status' => array( |
|
648 |
+ 'sql' => 'hdt.status', |
|
649 |
+ ), |
|
650 |
+ 'starter' => array( |
|
651 |
+ 'sql' => 'starter_name', |
|
652 |
+ 'sql_select' => 'IFNULL(mem.real_name, 0) AS starter_name', |
|
653 |
+ 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdt.id_member_started = mem.id_member)', |
|
654 |
+ ), |
|
655 |
+ 'lastreply' => array( |
|
656 |
+ 'sql' => 'last_reply', |
|
657 |
+ 'sql_select' => 'IFNULL(mem.real_name, 0) AS last_reply', |
|
658 |
+ 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdtr_last.id_member = mem.id_member)', |
|
659 |
+ ), |
|
660 |
+ ); |
|
661 |
+ |
|
662 |
+ foreach ($context['ticket_blocks'] as $block_key => $block) |
|
663 |
+ { |
|
664 |
+ $sort = isset($_REQUEST['so_' . $block_key]) ? $_REQUEST['so_' . $block_key] : ''; |
|
665 |
+ |
|
666 |
+ if (strpos($sort, '_') > 0 && substr_count($sort, '_') == 1) |
|
667 |
+ { |
|
668 |
+ list($sort_item, $sort_dir) = explode('_', $sort); |
|
669 |
+ |
|
670 |
+ if (empty($sort_methods[$sort_item])) |
|
671 |
+ { |
|
672 |
+ $sort_item = 'updated'; |
|
673 |
+ $sort = ''; |
|
674 |
+ } |
|
675 |
+ |
|
676 |
+ if (!in_array($sort_dir, array('asc', 'desc'))) |
|
677 |
+ { |
|
678 |
+ $sort = ''; |
|
679 |
+ $sort_dir = 'asc'; |
|
680 |
+ } |
|
681 |
+ } |
|
682 |
+ else |
|
683 |
+ { |
|
684 |
+ $sort = ''; |
|
685 |
+ $sort_item = 'updated'; |
|
686 |
+ $sort_dir = $_REQUEST['sa'] == 'closedtickets' || $_REQUEST['sa'] == 'recyclebin' ? 'desc' : 'asc'; // default to newest first if on recyclebin or closed tickets, otherwise oldest first |
|
687 |
+ } |
|
688 |
+ |
|
689 |
+ if ($sort != '') |
|
690 |
+ $_REQUEST['so_' . $block_key] = $sort; // sanitise! |
|
691 |
+ elseif (isset($_REQUEST['so_' . $block_key])) |
|
692 |
+ unset($_REQUEST['so_' . $block_key]); |
|
693 |
+ |
|
694 |
+ $context['ticket_blocks'][$block_key]['sort'] = array( |
|
695 |
+ 'item' => $sort_item, |
|
696 |
+ 'direction' => $sort_dir, |
|
697 |
+ 'add_link' => ($sort != ''), |
|
698 |
+ 'sql' => array( |
|
699 |
+ 'select' => !empty($sort_methods[$sort_item]['sql_select']) ? $sort_methods[$sort_item]['sql_select'] : '', |
|
700 |
+ 'join' => !empty($sort_methods[$sort_item]['sql_join']) ? $sort_methods[$sort_item]['sql_join'] : '', |
|
701 |
+ 'sort' => $sort_methods[$sort_item]['sql'] . ' ' . strtoupper($sort_dir), |
|
702 |
+ ), |
|
703 |
+ 'link_bits' => array(), |
|
704 |
+ ); |
|
705 |
+ } |
|
706 |
+ |
|
707 |
+ // Having got all that, step through the blocks again to determine the full URL fragments |
|
708 |
+ foreach ($context['ticket_blocks'] as $block_key => $block) |
|
709 |
+ foreach ($sort_methods as $method => $sort_details) |
|
710 |
+ $context['ticket_blocks'][$block_key]['sort']['link_bits'][$method] = ';so_' . $block_key . '=' . $method . '_' . $block['sort']['direction']; |
|
711 |
+ |
|
712 |
+ // Now go actually do the whole block thang, setting up space for a list of users as we go along |
|
713 |
+ $users = array(); |
|
714 |
+ |
|
715 |
+ foreach ($context['ticket_blocks'] as $block_key => $block) |
|
716 |
+ { |
|
717 |
+ if (empty($block['display']) || !empty($block['collapsed'])) |
|
718 |
+ continue; |
|
719 |
+ |
|
720 |
+ $context['ticket_blocks'][$block_key]['tickets'] = array(); |
|
721 |
+ |
|
722 |
+ $query = shd_db_query('', ' |
|
723 |
+ SELECT hdt.id_ticket, hdt.id_last_msg, hdt.id_member_started, hdt.id_member_updated, hdt.id_member_assigned, |
|
724 |
+ hdt.subject, hdt.status, hdt.num_replies, hdt.deleted_replies, hdt.private, hdt.urgency, |
|
725 |
+ hdtr_first.poster_name AS ticket_opener, hdtr_last.poster_name AS respondent, hdtr_last.poster_time, |
|
726 |
+ IFNULL(hdlr.id_msg, 0) AS log_read' . (!empty($block['sort']['sql']['select']) ? ', ' . $block['sort']['sql']['select'] : '') . ' |
|
727 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
728 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdt.id_first_msg = hdtr_first.id_msg) |
|
729 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdt.id_last_msg = hdtr_last.id_msg) |
|
730 |
+ LEFT JOIN {db_prefix}helpdesk_log_read AS hdlr ON (hdt.id_ticket = hdlr.id_ticket AND hdlr.id_member = {int:user}) |
|
731 |
+ ' . (!empty($block['sort']['sql']['join']) ? $block['sort']['sql']['join'] : '') . ' |
|
732 |
+ WHERE {query_see_ticket}' . (!empty($block['where']) ? ' AND ' . $block['where'] : '') . ' |
|
733 |
+ ORDER BY ' . (!empty($block['sort']['sql']['sort']) ? $block['sort']['sql']['sort'] : 'hdt.id_last_msg ASC') . ' |
|
734 |
+ LIMIT {int:start}, {int:items_per_page}', |
|
735 |
+ array( |
|
736 |
+ 'user' => $context['user']['id'], |
|
737 |
+ 'start' => $block['start'], |
|
738 |
+ 'items_per_page' => $context['items_per_page'], |
|
739 |
+ ) |
|
740 |
+ ); |
|
741 |
+ |
|
742 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
743 |
+ { |
|
744 |
+ $is_own = $user_info['id'] == $row['id_member_started']; |
|
745 |
+ censorText($row['subject']); |
|
746 |
+ |
|
747 |
+ $new_block = array( |
|
748 |
+ 'id' => $row['id_ticket'], |
|
749 |
+ 'display_id' => str_pad($row['id_ticket'], 5, '0', STR_PAD_LEFT), |
|
750 |
+ 'link' => '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : '') . '">' . $row['subject'] . '</a>', |
|
751 |
+ 'subject' => $row['subject'], |
|
752 |
+ 'status' => array( |
|
753 |
+ 'level' => $row['status'], |
|
754 |
+ 'label' => $txt['shd_status_' . $row['status']], |
|
755 |
+ ), |
|
756 |
+ 'starter' => array( |
|
757 |
+ 'id' => $row['id_member_started'], |
|
758 |
+ 'name' => $row['ticket_opener'], |
|
759 |
+ ), |
|
760 |
+ 'last_update' => $row['status'] != TICKET_STATUS_NEW ? timeformat($row['poster_time']) : $txt['never'], |
|
761 |
+ 'assigned' => array( |
|
762 |
+ 'id' => $row['id_member_assigned'], |
|
763 |
+ ), |
|
764 |
+ 'respondent' => array( |
|
765 |
+ 'id' => $row['id_member_updated'], |
|
766 |
+ 'name' => $row['respondent'], |
|
767 |
+ ), |
|
768 |
+ 'urgency' => array( |
|
769 |
+ 'level' => $row['urgency'], |
|
770 |
+ 'label' => $row['urgency'] > TICKET_URGENCY_HIGH ? '<span class="error">' . $txt['shd_urgency_' . $row['urgency']] . '</span>' : $txt['shd_urgency_' . $row['urgency']], |
|
771 |
+ ), |
|
772 |
+ 'is_unread' => ($row['id_last_msg'] > $row['log_read']), |
|
773 |
+ 'new_href' => ($row['id_last_msg'] <= $row['log_read']) ? '' : ($scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . '.new' . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : '') . '#new'), |
|
774 |
+ 'private' => $row['private'], |
|
775 |
+ 'actions' => array(), |
|
776 |
+ 'num_replies' => $row['num_replies'], |
|
777 |
+ 'all_replies' => (int) $row['num_replies'] + (int) $row['deleted_replies'], |
|
778 |
+ ); |
|
779 |
+ |
|
780 |
+ if ($row['status'] == TICKET_STATUS_CLOSED) |
|
781 |
+ { |
|
782 |
+ $new_block['actions'] += array( |
|
783 |
+ 'resolve' => shd_allowed_to('shd_resolve_ticket_any') || ($is_own && shd_allowed_to('shd_resolve_ticket_own')) ? '<a href="' . $scripturl . '?action=helpdesk;sa=resolveticket;ticket=' . $row['id_ticket'] . ';home;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_unresolved'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/unresolved.png" alt="' . $txt['shd_ticket_unresolved'] . '" /></a>' : '', |
|
784 |
+ ); |
|
785 |
+ } |
|
786 |
+ elseif ($row['status'] == TICKET_STATUS_DELETED) // and thus, we're in the recycle bin |
|
787 |
+ { |
|
788 |
+ $new_block['actions'] += array( |
|
789 |
+ 'restore' => shd_allowed_to('shd_restore_ticket_any') || ($is_own && shd_allowed_to('shd_restore_ticket_own')) ? '<a href="' . $scripturl . '?action=helpdesk;sa=restoreticket;ticket=' . $row['id_ticket'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_restore'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/restore.png" alt="' . $txt['shd_ticket_restore'] . '" /></a>' : '', |
|
790 |
+ 'permadelete' => shd_allowed_to('shd_delete_recycling') ? '<a href="' . $scripturl . '?action=helpdesk;sa=permadelete;ticket=' . $row['id_ticket'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_delete_permanently'] . '" onclick="return confirm(' . JavaScriptEscape($txt['shd_delete_permanently_confirm']) . ');"><img src="' . $settings['default_images_url'] . '/simpledesk/delete.png" alt="' . $txt['shd_delete_permanently'] . '" /></a>' : '', |
|
791 |
+ ); |
|
792 |
+ } |
|
793 |
+ else |
|
794 |
+ { |
|
795 |
+ $langstring = ''; |
|
796 |
+ if (shd_allowed_to('shd_assign_ticket_any')) |
|
797 |
+ $langstring = empty($row['id_member_assigned']) ? $txt['shd_ticket_assign'] : $txt['shd_ticket_reassign']; |
|
798 |
+ elseif (shd_allowed_to('shd_assign_ticket_own') && (empty($row['id_member_assigned']) || $row['id_member_assigned'] == $context['user']['id'])) |
|
799 |
+ $langstring = $row['id_member_assigned'] == $context['user']['id'] ? $txt['shd_ticket_unassign'] : $txt['shd_ticket_assign_self']; |
|
800 |
+ |
|
801 |
+ if (!empty($langstring)) |
|
802 |
+ $new_block['actions']['assign'] = '<a href="' . $scripturl . '?action=helpdesk;sa=assign;ticket=' . $row['id_ticket'] . ';home;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $langstring . '"><img src="' . $settings['default_images_url'] . '/simpledesk/assign.png" alt="' . $langstring . '" /></a>'; |
|
803 |
+ |
|
804 |
+ $new_block['actions'] += array( |
|
805 |
+ 'resolve' => shd_allowed_to('shd_resolve_ticket_any') || ($is_own && shd_allowed_to('shd_resolve_ticket_own')) ? '<a href="' . $scripturl . '?action=helpdesk;sa=resolveticket;ticket=' . $row['id_ticket'] . ';home;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_resolved'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/resolved.png" alt="' . $txt['shd_ticket_resolved'] . '" /></a>' : '', |
|
806 |
+ 'tickettotopic' => empty($modSettings['shd_helpdesk_only']) && shd_allowed_to('shd_ticket_to_topic') && ($row['deleted_replies'] == 0 || shd_allowed_to('shd_access_recyclebin')) ? '<a href="' . $scripturl . '?action=helpdesk;sa=tickettotopic;ticket=' . $row['id_ticket'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_move_to_topic'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/tickettotopic.png" alt="' . $txt['shd_ticket_move_to_topic'] . '" /></a>' : '', |
|
807 |
+ 'delete' => shd_allowed_to('shd_delete_ticket_any') || ($is_own && shd_allowed_to('shd_delete_ticket_own')) ? '<a href="' . $scripturl . '?action=helpdesk;sa=deleteticket;ticket=' . $row['id_ticket'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_delete'] . '" onclick="return confirm(' . JavaScriptEscape($txt['shd_delete_confirm']) . ');"><img src="' . $settings['default_images_url'] . '/simpledesk/delete.png" alt="' . $txt['shd_ticket_delete'] . '" /></a>' : '', |
|
808 |
+ ); |
|
809 |
+ } |
|
810 |
+ |
|
811 |
+ $context['ticket_blocks'][$block_key]['tickets'][] = $new_block; |
|
812 |
+ |
|
813 |
+ $users[] = $row['id_member_started']; |
|
814 |
+ $users[] = $row['id_member_updated']; |
|
815 |
+ $users[] = $row['id_member_assigned']; |
|
816 |
+ } |
|
817 |
+ $smcFunc['db_free_result']($query); |
|
818 |
+ } |
|
819 |
+ |
|
820 |
+ $users = array_unique($users); |
|
821 |
+ if (!empty($users)) |
|
822 |
+ loadMemberData($users, false, 'minimal'); |
|
823 |
+ |
|
824 |
+ foreach ($context['ticket_blocks'] as $block_id => $block) |
|
825 |
+ { |
|
826 |
+ if (empty($block['tickets'])) |
|
827 |
+ continue; |
|
828 |
+ |
|
829 |
+ foreach ($block['tickets'] as $tid => $ticket) |
|
830 |
+ { |
|
831 |
+ // Set up names and profile links for topic starter |
|
832 |
+ if (!empty($user_profile[$ticket['starter']['id']])) |
|
833 |
+ { |
|
834 |
+ // We found the name, so let's use their current name and profile link |
|
835 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['name'] = $user_profile[$ticket['starter']['id']]['real_name']; |
|
836 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['link'] = shd_profile_link($user_profile[$ticket['starter']['id']]['real_name'], $ticket['starter']['id']); |
|
837 |
+ } |
|
838 |
+ else |
|
839 |
+ // We didn't, so keep using the name we found previously and don't make an actual link |
|
840 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['link'] = $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['name']; |
|
841 |
+ |
|
842 |
+ // Set up names and profile links for assigned user |
|
843 |
+ if ($ticket['assigned']['id'] == 0 || empty($user_profile[$ticket['assigned']['id']])) |
|
844 |
+ { |
|
845 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['name'] = $txt['shd_unassigned']; |
|
846 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['link'] = '<span class="error">' . $txt['shd_unassigned'] . '</span>'; |
|
847 |
+ } |
|
848 |
+ else |
|
849 |
+ { |
|
850 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['name'] = $user_profile[$ticket['assigned']['id']]['real_name']; |
|
851 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['link'] = shd_profile_link($user_profile[$ticket['assigned']['id']]['real_name'], $ticket['assigned']['id']); |
|
852 |
+ } |
|
853 |
+ |
|
854 |
+ // And last respondent |
|
855 |
+ if ($ticket['respondent']['id'] == 0 || empty($user_profile[$ticket['respondent']['id']])) |
|
856 |
+ { |
|
857 |
+ // Didn't find the name, so reuse what we have |
|
858 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['link'] = $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['name']; |
|
859 |
+ } |
|
860 |
+ else |
|
861 |
+ { |
|
862 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['name'] = $user_profile[$ticket['respondent']['id']]['real_name']; |
|
863 |
+ $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['link'] = shd_profile_link($user_profile[$ticket['respondent']['id']]['real_name'], $ticket['respondent']['id']); |
|
864 |
+ } |
|
865 |
+ } |
|
866 |
+ } |
|
867 |
+ |
|
868 |
+ foreach ($context['ticket_blocks'] as $block_id => $block) |
|
869 |
+ { |
|
870 |
+ if (empty($block['display']) || (empty($block['count']) && !$block['required'] && empty($block['collapsed']))) |
|
871 |
+ unset($context['ticket_blocks'][$block_id]); |
|
872 |
+ } |
|
873 |
+ |
|
874 |
+ $base_url = ''; |
|
875 |
+ foreach ($context['ticket_blocks'] as $block_id => $block) |
|
876 |
+ { |
|
877 |
+ if ($block['sort']['add_link']) |
|
878 |
+ $base_url .= $block['sort']['link_bits'][$block['sort']['item']]; |
|
879 |
+ } |
|
880 |
+ |
|
881 |
+ if ($_REQUEST['sa'] != 'viewblock') |
|
882 |
+ { |
|
883 |
+ foreach ($context['ticket_blocks'] as $block_id => $block) |
|
884 |
+ { |
|
885 |
+ $url_fragment = $base_url; |
|
886 |
+ |
|
887 |
+ foreach ($block_list as $block_item) |
|
888 |
+ { |
|
889 |
+ if ($block_item == $block_id) |
|
890 |
+ $url_fragment .= ';st_' . $block_item . '=%1$d'; |
|
891 |
+ elseif (!empty($context['ticket_blocks'][$block_item]['start'])) |
|
892 |
+ $url_fragment .= ';st_' . $block_item . '=' . $context['ticket_blocks'][$block_item]['start']; |
|
893 |
+ } |
|
894 |
+ |
|
895 |
+ $context['start'] = $context['ticket_blocks'][$block_id]['start']; |
|
896 |
+ $context['ticket_blocks'][$block_id]['page_index'] = shd_no_expand_pageindex($scripturl . $primary_url . $url_fragment . '#shd_block_' . $block_id, $context['start'], $block['count'], $context['items_per_page'], true); |
|
897 |
+ } |
|
898 |
+ } |
|
899 |
+} |
|
900 |
+ |
|
901 |
+/** |
|
902 |
+ * Return the list of columns that is applicable to a given block. |
|
903 |
+ * |
|
904 |
+ * In order to centralise the list of actions to be displayed in a block, and in its counterpart that displays all the values, |
|
905 |
+ * the lists of columns per block is kept here. |
|
906 |
+ * |
|
907 |
+ * @param string $block The block we are calling from: |
|
908 |
+ * - assigned: assigned to me |
|
909 |
+ * - new: new tickets |
|
910 |
+ * - staff: pending staff |
|
911 |
+ * - user_staff: pending with user (staff view) |
|
912 |
+ * - user_user: pending with user (user view) |
|
913 |
+ * - closed: resolved tickets |
|
914 |
+ * - recycled: deleted tickets |
|
915 |
+ * - withdeleted: tickets with deleted replies |
|
916 |
+ * |
|
917 |
+ * @return array An indexed array of the columns in the order they should be displayed. |
|
918 |
+ * @see shd_main_helpdesk() |
|
919 |
+ * @see shd_closed_tickets() |
|
920 |
+ * @see shd_recycle_bin() |
|
921 |
+ * @since 1.0 |
|
922 |
+*/ |
|
923 |
+function shd_get_block_columns($block) |
|
924 |
+{ |
|
925 |
+ switch ($block) |
|
926 |
+ { |
|
927 |
+ case 'assigned': |
|
928 |
+ return array( |
|
929 |
+ 'ticket_id', |
|
930 |
+ 'ticket_name', |
|
931 |
+ 'starting_user', |
|
932 |
+ 'replies', |
|
933 |
+ 'status', |
|
934 |
+ 'urgency', |
|
935 |
+ 'updated', |
|
936 |
+ 'actions', |
|
937 |
+ ); |
|
938 |
+ case 'new': |
|
939 |
+ return array( |
|
940 |
+ 'ticket_id', |
|
941 |
+ 'ticket_name', |
|
942 |
+ 'starting_user', |
|
943 |
+ 'assigned', |
|
944 |
+ 'urgency', |
|
945 |
+ 'updated', |
|
946 |
+ 'actions', |
|
947 |
+ ); |
|
948 |
+ case 'staff': |
|
949 |
+ return array( |
|
950 |
+ 'ticket_id', |
|
951 |
+ 'ticket_name', |
|
952 |
+ 'starting_user', |
|
953 |
+ 'replies', |
|
954 |
+ 'assigned', |
|
955 |
+ 'urgency', |
|
956 |
+ 'updated', |
|
957 |
+ 'actions', |
|
958 |
+ ); |
|
959 |
+ case 'user_staff': |
|
960 |
+ return array( |
|
961 |
+ 'ticket_id', |
|
962 |
+ 'ticket_name', |
|
963 |
+ 'starting_user', |
|
964 |
+ 'last_reply', |
|
965 |
+ 'replies', |
|
966 |
+ 'urgency', |
|
967 |
+ 'updated', |
|
968 |
+ 'actions', |
|
969 |
+ ); |
|
970 |
+ case 'user_user': |
|
971 |
+ return array( |
|
972 |
+ 'ticket_id', |
|
973 |
+ 'ticket_name', |
|
974 |
+ 'last_reply', |
|
975 |
+ 'replies', |
|
976 |
+ 'urgency', |
|
977 |
+ 'updated', |
|
978 |
+ 'actions', |
|
979 |
+ ); |
|
980 |
+ case 'closed': |
|
981 |
+ return array( |
|
982 |
+ 'ticket_id', |
|
983 |
+ 'ticket_name', |
|
984 |
+ 'starting_user', |
|
985 |
+ 'replies', |
|
986 |
+ 'updated', |
|
987 |
+ 'actions', |
|
988 |
+ ); |
|
989 |
+ case 'recycled': |
|
990 |
+ return array( |
|
991 |
+ 'ticket_id', |
|
992 |
+ 'ticket_name', |
|
993 |
+ 'starting_user', |
|
994 |
+ 'allreplies', |
|
995 |
+ 'assigned', |
|
996 |
+ 'updated', |
|
997 |
+ 'actions', |
|
998 |
+ ); |
|
999 |
+ case 'withdeleted': |
|
1000 |
+ return array( |
|
1001 |
+ 'ticket_id', |
|
1002 |
+ 'ticket_name', |
|
1003 |
+ 'starting_user', |
|
1004 |
+ 'allreplies', |
|
1005 |
+ 'assigned', |
|
1006 |
+ 'updated', |
|
1007 |
+ 'actions', |
|
1008 |
+ ); |
|
1009 |
+ default: |
|
1010 |
+ return array(); |
|
1011 |
+ } |
|
1012 |
+} |
|
1013 |
+?> |
|
0 | 1014 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,1120 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: Subs-SimpleDesk.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles key functions for SimpleDesk that can be called on every page load, such as the |
|
22 |
+ * custom query function to handle ticket visibility, the counter for active tickets in the menu header, or the action log. |
|
23 |
+ * |
|
24 |
+ * @package subs |
|
25 |
+ * @since 1.0 |
|
26 |
+ */ |
|
27 |
+ |
|
28 |
+if (!defined('SMF')) |
|
29 |
+ die('Hacking attempt...'); |
|
30 |
+ |
|
31 |
+/** |
|
32 |
+ * Initialises key values for SimpleDesk. |
|
33 |
+ * |
|
34 |
+ * This function initialises certain key constructs for SimpleDesk, such as constants, that are used throughout |
|
35 |
+ * SimpleDesk. It should be called first right up in Load.php anyway. |
|
36 |
+ * |
|
37 |
+ * Calling multiple times is not significantly detrimental to performance; the function is aware if it has been |
|
38 |
+ * called previously. |
|
39 |
+ * |
|
40 |
+ * @since 1.1 |
|
41 |
+*/ |
|
42 |
+function shd_init() |
|
43 |
+{ |
|
44 |
+ global $modSettings, $sourcedir, $user_info, $context; |
|
45 |
+ static $called = null; |
|
46 |
+ |
|
47 |
+ if (!empty($called)) |
|
48 |
+ return; |
|
49 |
+ |
|
50 |
+ $called = true; |
|
51 |
+ |
|
52 |
+ // What SD version are we on? It's now here! |
|
53 |
+ define('SHD_VERSION', 'SimpleDesk 1.0 Felidae'); |
|
54 |
+ |
|
55 |
+ // This isn't the SMF way. But for something like this, it's way way more logical and readable. |
|
56 |
+ define('TICKET_STATUS_NEW', 0); |
|
57 |
+ define('TICKET_STATUS_PENDING_STAFF', 1); |
|
58 |
+ define('TICKET_STATUS_PENDING_USER', 2); |
|
59 |
+ define('TICKET_STATUS_CLOSED', 3); |
|
60 |
+ define('TICKET_STATUS_WITH_SUPERVISOR', 4); |
|
61 |
+ define('TICKET_STATUS_ESCALATED', 5); |
|
62 |
+ define('TICKET_STATUS_DELETED', 6); |
|
63 |
+ |
|
64 |
+ define('TICKET_URGENCY_LOW', 0); |
|
65 |
+ define('TICKET_URGENCY_MEDIUM', 1); |
|
66 |
+ define('TICKET_URGENCY_HIGH', 2); |
|
67 |
+ define('TICKET_URGENCY_VHIGH', 3); |
|
68 |
+ define('TICKET_URGENCY_SEVERE', 4); |
|
69 |
+ define('TICKET_URGENCY_CRITICAL', 5); |
|
70 |
+ |
|
71 |
+ define('MSG_STATUS_NORMAL', 0); |
|
72 |
+ define('MSG_STATUS_DELETED', 1); |
|
73 |
+ |
|
74 |
+ define('RELATIONSHIP_LINKED', 0); |
|
75 |
+ define('RELATIONSHIP_DUPLICATED', 1); |
|
76 |
+ define('RELATIONSHIP_ISPARENT', 2); |
|
77 |
+ define('RELATIONSHIP_ISCHILD', 3); |
|
78 |
+ |
|
79 |
+ define('CFIELD_TICKET', 1); |
|
80 |
+ define('CFIELD_REPLY', 2); |
|
81 |
+ |
|
82 |
+ define('CFIELD_TYPE_TEXT', 1); |
|
83 |
+ define('CFIELD_TYPE_LARGETEXT', 2); |
|
84 |
+ define('CFIELD_TYPE_INT', 3); |
|
85 |
+ define('CFIELD_TYPE_FLOAT', 4); |
|
86 |
+ define('CFIELD_TYPE_SELECT', 5); |
|
87 |
+ define('CFIELD_TYPE_CHECKBOX', 6); |
|
88 |
+ define('CFIELD_TYPE_RADIO', 7); |
|
89 |
+ |
|
90 |
+ define('ROLE_USER', 1); |
|
91 |
+ define('ROLE_STAFF', 2); |
|
92 |
+ //define('ROLE_SUPERVISOR', 3); |
|
93 |
+ define('ROLE_ADMIN', 4); |
|
94 |
+ |
|
95 |
+ define('ROLEPERM_DISALLOW', 0); |
|
96 |
+ define('ROLEPERM_ALLOW', 1); |
|
97 |
+ define('ROLEPERM_DENY', 2); |
|
98 |
+ |
|
99 |
+ // Load some stuff |
|
100 |
+ shd_load_language('SimpleDesk'); |
|
101 |
+ require($sourcedir . '/sd_source/Subs-SimpleDeskPermissions.php'); |
|
102 |
+ |
|
103 |
+ // Set up defaults |
|
104 |
+ $defaults = array( |
|
105 |
+ 'shd_attachments_mode' => 'ticket', |
|
106 |
+ 'shd_ticketnav_style' => 'sd', |
|
107 |
+ 'shd_staff_badge' => 'nobadge', |
|
108 |
+ 'shd_privacy_display' => 'smart', |
|
109 |
+ ); |
|
110 |
+ |
|
111 |
+ foreach ($defaults as $var => $val) |
|
112 |
+ { |
|
113 |
+ if (empty($modSettings[$var])) |
|
114 |
+ $modSettings[$var] = $val; |
|
115 |
+ } |
|
116 |
+ |
|
117 |
+ $modSettings['helpdesk_active'] = isset($modSettings['admin_features']) ? in_array('shd', explode(',', $modSettings['admin_features'])) : false; |
|
118 |
+ |
|
119 |
+ shd_load_user_perms(); |
|
120 |
+ |
|
121 |
+ if (!empty($modSettings['shd_maintenance_mode'])) |
|
122 |
+ $modSettings['helpdesk_active'] &= ($user_info['is_admin'] || shd_allowed_to('admin_helpdesk')); |
|
123 |
+ |
|
124 |
+ // Call for any init level hooks |
|
125 |
+ if ($modSettings['helpdesk_active']) |
|
126 |
+ { |
|
127 |
+ shd_load_plugin_files('init'); |
|
128 |
+ shd_load_plugin_langfiles('init'); |
|
129 |
+ } |
|
130 |
+ |
|
131 |
+ $context['shd_plugins'] = empty($modSettings['shd_enabled_plugins']) || empty($modSettings['helpdesk_active']) ? array() : explode(',', $modSettings['shd_enabled_plugins']); |
|
132 |
+} |
|
133 |
+ |
|
134 |
+/** |
|
135 |
+ * Query wrapper around $smcFunc['db_query'] for helpdesk specific operations. |
|
136 |
+ * |
|
137 |
+ * This function provides a basic wrapper around SMF's internal $smcFunc['db_query'] function, adding the parameter {query_see_ticket} |
|
138 |
+ * to it, specifically so that ticket visibility can be enforced in a query without being aware of the specific rules for the user. |
|
139 |
+ * |
|
140 |
+ * If not previously loaded, user permissions are loaded with {@link shd_load_user_perms()}. |
|
141 |
+ * |
|
142 |
+ * @param string $identifier SMF-style query identifier for database backend-specific replacements |
|
143 |
+ * @param string $db_string Standard SMF 2.0 style database query, including {query_see_ticket} if appropriate |
|
144 |
+ * @param array $db_values Standard SMF 2.0 style hash map of parameters to inject into the query |
|
145 |
+ * @param resource $connection A database connection variable, if supplied, to override the one used by SMF by default |
|
146 |
+ * @return resource Standard database query resource, suitable for processing with other $smcFunc['db_*'] functions |
|
147 |
+ * |
|
148 |
+ * @see shd_load_user_perms() |
|
149 |
+ * @since 1.0 |
|
150 |
+*/ |
|
151 |
+function shd_db_query($identifier, $db_string, $db_values = array(), $connection = null) |
|
152 |
+{ |
|
153 |
+ global $user_info, $smcFunc; |
|
154 |
+ |
|
155 |
+ $replacements = array( |
|
156 |
+ '{query_see_ticket}' => $user_info['query_see_ticket'], |
|
157 |
+ ); |
|
158 |
+ |
|
159 |
+ $db_string = str_replace(array_keys($replacements), array_values($replacements), $db_string); |
|
160 |
+ $db_values['user_info_id'] = $user_info['id']; |
|
161 |
+ |
|
162 |
+ return $smcFunc['db_query']($identifier, $db_string, $db_values, $connection); |
|
163 |
+} |
|
164 |
+ |
|
165 |
+/** |
|
166 |
+ * Defines the helpdesk menu item, including the number of active tickets to be displayed to the user. |
|
167 |
+ * |
|
168 |
+ * Identifies the number of tickets that a user might be interested in, and generates the menu text for the main menu |
|
169 |
+ * to include this; note that the value should be cached through SMF's functions. The cache is also clearable, through |
|
170 |
+ * the {@link shd_clear_active_tickets()} function. |
|
171 |
+ * |
|
172 |
+ * @return string A formatted string containing the language-specific version of "Helpdesk [x]" menu item with the x in bold |
|
173 |
+ * @see shd_clear_active_tickets() |
|
174 |
+ * @since 1.0 |
|
175 |
+*/ |
|
176 |
+function shd_get_active_tickets() |
|
177 |
+{ |
|
178 |
+ global $modSettings, $user_info, $smcFunc, $context, $txt; |
|
179 |
+ |
|
180 |
+ if (empty($txt['shd_helpdesk'])) // provide a last-ditch fallback in the event we can't even find the file; SimpleDesk.{language}.php should be loaded by now (falling back to english if lang-specific doesn't exist) |
|
181 |
+ $txt['shd_helpdesk'] = 'Helpdesk'; |
|
182 |
+ |
|
183 |
+ if (!$modSettings['helpdesk_active'] || $context['user']['is_guest']) |
|
184 |
+ return $txt['shd_helpdesk']; |
|
185 |
+ |
|
186 |
+ // Have we already run on this page? If so we already have the answer. |
|
187 |
+ if (!empty($context['active_tickets'])) |
|
188 |
+ return $txt['shd_helpdesk'] . $context['active_tickets']; |
|
189 |
+ |
|
190 |
+ // Can we get it from the cache? |
|
191 |
+ $temp = cache_get_data('shd_active_tickets_' . $user_info['id'], 180); |
|
192 |
+ if ($temp !== null) |
|
193 |
+ { |
|
194 |
+ list($context['active_tickets'], $context['active_tickets_raw']) = $temp; |
|
195 |
+ $context['menu_buttons']['helpdesk']['alttitle'] = $txt['shd_helpdesk'] . !empty($context['active_tickets_raw']) ? (' [' . $context['active_tickets_raw'] . ']') : ''; |
|
196 |
+ return $txt['shd_helpdesk'] . $context['active_tickets']; |
|
197 |
+ } |
|
198 |
+ |
|
199 |
+ shd_init(); |
|
200 |
+ // Figure out the status(es) that the ticket could be. |
|
201 |
+ if (shd_allowed_to('shd_staff')) |
|
202 |
+ $status = array(TICKET_STATUS_NEW, TICKET_STATUS_PENDING_STAFF); // staff actually need to deal with these |
|
203 |
+ else |
|
204 |
+ $status = array(TICKET_STATUS_PENDING_USER); // user actually needs to deal with this |
|
205 |
+ |
|
206 |
+ $query = shd_db_query('', ' |
|
207 |
+ SELECT COUNT(id_ticket) |
|
208 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
209 |
+ WHERE {query_see_ticket} AND status IN ({array_int:status})', |
|
210 |
+ array( |
|
211 |
+ 'status' => $status, |
|
212 |
+ ) |
|
213 |
+ ); |
|
214 |
+ |
|
215 |
+ $context['active_tickets_raw'] = 0; |
|
216 |
+ |
|
217 |
+ $row = $smcFunc['db_fetch_row']($query); |
|
218 |
+ if (!empty($row[0])) |
|
219 |
+ { |
|
220 |
+ $context['menu_buttons']['helpdesk']['alttitle'] = $txt['shd_helpdesk'] . ' [' . $row[0] . ']'; |
|
221 |
+ $context['active_tickets'] = ' [<strong>' . $row[0] . '</strong>]'; |
|
222 |
+ $context['active_tickets_raw'] = $row[0]; // in case you want to do something funky in the theme later? |
|
223 |
+ } |
|
224 |
+ else |
|
225 |
+ $context['active_tickets'] = ''; |
|
226 |
+ |
|
227 |
+ cache_put_data('shd_active_tickets_' . $user_info['id'], array($context['active_tickets'], $context['active_tickets_raw']), 120); |
|
228 |
+ |
|
229 |
+ return $txt['shd_helpdesk'] . $context['active_tickets']; |
|
230 |
+} |
|
231 |
+ |
|
232 |
+/** |
|
233 |
+ * Clears the cache of active tickets for the menu item. |
|
234 |
+ * |
|
235 |
+ * {@link shd_get_active_tickets()} generates the number of active tickets for the user display, and caches it for 180 seconds |
|
236 |
+ * normally. This function clears the cache and should be called whenever any operation modifies the state of a ticket. |
|
237 |
+ * |
|
238 |
+ * @see shd_get_active_tickets() |
|
239 |
+ * @since 1.0 |
|
240 |
+*/ |
|
241 |
+function shd_clear_active_tickets($id = 0) |
|
242 |
+{ |
|
243 |
+ global $user_info; |
|
244 |
+ |
|
245 |
+ $members = shd_members_allowed_to('shd_staff'); |
|
246 |
+ if ($id != 0) |
|
247 |
+ $members[] = $id; |
|
248 |
+ |
|
249 |
+ $members[] = $user_info['id']; |
|
250 |
+ |
|
251 |
+ $members = array_unique($members); |
|
252 |
+ |
|
253 |
+ foreach ($members as $member) |
|
254 |
+ { |
|
255 |
+ cache_put_data('shd_active_tickets_' . $member, null, 0); |
|
256 |
+ cache_put_data('shd_ticket_count_' . $member, null, 0); |
|
257 |
+ } |
|
258 |
+} |
|
259 |
+ |
|
260 |
+/** |
|
261 |
+ * Adds an action to the helpdesk internal action log. |
|
262 |
+ * |
|
263 |
+ * This function deals with adding items to the action log maintained by the helpdesk. |
|
264 |
+ * |
|
265 |
+ * @param string $action Specifies the name of the action to log, which implies the image and language string (log_$action is the name of the image, and $txt['shd_log_$action'] is the string used to express the action, as listed in {@link SimpleDeskLogAction.english.php}. |
|
266 |
+ * Note that since 1.1, the list of actions is looked up against the options in Admin / Helpdesk / Options / Action Log Options as to whether they should be logged or not |
|
267 |
+ * @param array $params This is a list of named parameters in a hash array to be used in the language string later. |
|
268 |
+ * |
|
269 |
+ * @see shd_load_action_log_entries() |
|
270 |
+ * @since 1.0 |
|
271 |
+*/ |
|
272 |
+function shd_log_action($action, $params) |
|
273 |
+{ |
|
274 |
+ global $smcFunc, $context, $user_info, $modSettings; |
|
275 |
+ |
|
276 |
+ if (!empty($modSettings['shd_disable_action_log'])) |
|
277 |
+ return; |
|
278 |
+ |
|
279 |
+ // Check to see if we should actually log this action or not. |
|
280 |
+ $logopt = array( |
|
281 |
+ 'newticket' => 'shd_logopt_newposts', |
|
282 |
+ 'newticketproxy' => 'shd_logopt_newposts', |
|
283 |
+ 'editticket' => 'shd_logopt_editposts', |
|
284 |
+ 'newreply' => 'shd_logopt_newposts', |
|
285 |
+ 'editreply' => 'shd_logopt_editposts', |
|
286 |
+ 'resolve' => 'shd_logopt_resolve', |
|
287 |
+ 'unresolve' => 'shd_logopt_resolve', |
|
288 |
+ 'assign' => 'shd_logopt_assign', |
|
289 |
+ 'unassign' => 'shd_logopt_assign', |
|
290 |
+ 'markprivate' => 'shd_logopt_privacy', |
|
291 |
+ 'marknotprivate' => 'shd_logopt_privacy', |
|
292 |
+ 'urgency_increase' => 'shd_logopt_urgency', |
|
293 |
+ 'urgency_decrease' => 'shd_logopt_urgency', |
|
294 |
+ 'tickettotopic' => 'shd_logopt_tickettopicmove', |
|
295 |
+ 'topictoticket' => 'shd_logopt_tickettopicmove', |
|
296 |
+ 'delete' => 'shd_logopt_delete', |
|
297 |
+ 'delete_reply' => 'shd_logopt_delete', |
|
298 |
+ 'restore' => 'shd_logopt_restore', |
|
299 |
+ 'restore_reply' => 'shd_logopt_restore', |
|
300 |
+ 'permadelete' => 'shd_logopt_permadelete', |
|
301 |
+ 'permadelete_reply' => 'shd_logopt_permadelete', |
|
302 |
+ 'rel_linked' => 'shd_logopt_relationships', |
|
303 |
+ 'rel_duplicated' => 'shd_logopt_relationships', |
|
304 |
+ 'rel_parent' => 'shd_logopt_relationships', |
|
305 |
+ 'rel_child' => 'shd_logopt_relationships', |
|
306 |
+ 'rel_re_linked' => 'shd_logopt_relationships', |
|
307 |
+ 'rel_re_duplicated' => 'shd_logopt_relationships', |
|
308 |
+ 'rel_re_parent' => 'shd_logopt_relationships', |
|
309 |
+ 'rel_re_child' => 'shd_logopt_relationships', |
|
310 |
+ 'rel_delete' => 'shd_logopt_relationships', |
|
311 |
+ 'split_origin' => 'shd_logopt_split', |
|
312 |
+ 'split_new' => 'shd_logopt_split', |
|
313 |
+ ); |
|
314 |
+ |
|
315 |
+ if (empty($logopt[$action]) || empty($modSettings[$logopt[$action]])) |
|
316 |
+ return; |
|
317 |
+ |
|
318 |
+ // Some parts of $params we will want in the main row for sorting + lookups later. Let's see if they're here. |
|
319 |
+ if (!empty($params['ticket'])) |
|
320 |
+ { |
|
321 |
+ $ticket_id = (int) $params['ticket']; |
|
322 |
+ if ($ticket_id == 0) |
|
323 |
+ trigger_error('log_action(): received data with non-numeric ticket', E_USER_NOTICE); |
|
324 |
+ else |
|
325 |
+ unset($params['ticket']); |
|
326 |
+ } |
|
327 |
+ else |
|
328 |
+ $ticket_id = 0; |
|
329 |
+ |
|
330 |
+ if (!empty($params['msg'])) |
|
331 |
+ { |
|
332 |
+ $msg_id = (int) $params['msg']; |
|
333 |
+ if ($msg_id == 0) |
|
334 |
+ trigger_error('log_action(): received data with non-numeric msg', E_USER_NOTICE); |
|
335 |
+ else |
|
336 |
+ unset($params['msg']); |
|
337 |
+ } |
|
338 |
+ else |
|
339 |
+ $msg_id = 0; |
|
340 |
+ |
|
341 |
+ $smcFunc['db_insert']('', |
|
342 |
+ '{db_prefix}helpdesk_log_action', |
|
343 |
+ array( |
|
344 |
+ 'log_time' => 'int', 'id_member' => 'int', 'ip' => 'string-16', 'action' => 'string', 'id_ticket' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534', |
|
345 |
+ ), |
|
346 |
+ array( |
|
347 |
+ time(), $user_info['id'], $user_info['ip'], $action, $ticket_id, $msg_id, serialize($params), |
|
348 |
+ ), |
|
349 |
+ array('id_action') |
|
350 |
+ ); |
|
351 |
+} |
|
352 |
+ |
|
353 |
+/** |
|
354 |
+ * Determines if the current user can raise/lower the urgency of a ticket. |
|
355 |
+ * |
|
356 |
+ * This function identifies whether the current user can raise or lower the urgency of a ticket based on the current urgency |
|
357 |
+ * of the ticket and whether it is their ticket; this is used in the ticket display as well as the actions linked directly to |
|
358 |
+ * modifying urgency (both AJAXively and non AJAXively) |
|
359 |
+ * |
|
360 |
+ * @param int $urgency The current urgency of a ticket as an integer |
|
361 |
+ * @param bool $ticket_starter Whether the user in question is the starter of the ticket (instead of querying to establish that, |
|
362 |
+ * that detail should already be known to the calling function) |
|
363 |
+ * @param bool $closed Whether the ticket is currently closed or not |
|
364 |
+ * @param bool $deleted Whether the ticket is currently closed or not |
|
365 |
+ * |
|
366 |
+ * @see shd_urgency_change_noajax() |
|
367 |
+ * @since 1.0 |
|
368 |
+*/ |
|
369 |
+function shd_can_alter_urgency($urgency, $ticket_starter, $closed, $deleted) |
|
370 |
+{ |
|
371 |
+ global $user_info; |
|
372 |
+ |
|
373 |
+ $can_urgency = array( |
|
374 |
+ 'increase' => false, |
|
375 |
+ 'decrease' => false, |
|
376 |
+ ); |
|
377 |
+ |
|
378 |
+ if ($closed || $deleted) |
|
379 |
+ return $can_urgency; |
|
380 |
+ |
|
381 |
+ if (shd_allowed_to('shd_alter_urgency_any')) |
|
382 |
+ { |
|
383 |
+ if (shd_allowed_to('shd_alter_urgency_higher_any') || (shd_allowed_to('shd_alter_urgency_higher_own') && $ticket_starter == $user_info['id'])) |
|
384 |
+ $can_urgency = array( // can alter any urgency and can alter this one's higher urgency too |
|
385 |
+ 'increase' => ($urgency < TICKET_URGENCY_CRITICAL), |
|
386 |
+ 'decrease' => ($urgency > TICKET_URGENCY_LOW), |
|
387 |
+ ); |
|
388 |
+ else |
|
389 |
+ $can_urgency = array( // can alter any base urgency - just not this one's higher urgency |
|
390 |
+ 'increase' => ($urgency < TICKET_URGENCY_HIGH), |
|
391 |
+ 'decrease' => ($urgency > TICKET_URGENCY_LOW && $urgency < TICKET_URGENCY_VHIGH), |
|
392 |
+ ); |
|
393 |
+ } |
|
394 |
+ elseif (shd_allowed_to('shd_alter_urgency_own') && $ticket_starter == $user_info['id']) |
|
395 |
+ $can_urgency = array( // ok, so this is our ticket and we can change it |
|
396 |
+ 'increase' => ($urgency < (shd_allowed_to('shd_alter_urgency_higher_own') ? TICKET_URGENCY_CRITICAL : TICKET_URGENCY_HIGH)), |
|
397 |
+ 'decrease' => ($urgency > TICKET_URGENCY_LOW && $urgency <= (shd_allowed_to('shd_alter_urgency_higher_own') ? TICKET_URGENCY_CRITICAL : TICKET_URGENCY_VHIGH)), |
|
398 |
+ ); |
|
399 |
+ |
|
400 |
+ return $can_urgency; |
|
401 |
+} |
|
402 |
+ |
|
403 |
+/** |
|
404 |
+ * Queries the database to find the number of applicable tickets |
|
405 |
+ * |
|
406 |
+ * This function collects counts for the different states of tickets (new, with staff, with user, etc) of all the tickets |
|
407 |
+ * visible to the user, and returns a selection of that dataset based on the values provided to $status and $is_staff. |
|
408 |
+ * |
|
409 |
+ * @param string $status The relevant count of tickets to return: |
|
410 |
+ * <ul> |
|
411 |
+ * <li>'open': All tickets currently open that the user can see</li> |
|
412 |
+ * <li>'assigned': All tickets assigned to the current user</li> |
|
413 |
+ * <li>'new': All the new tickets that the user can see</li> |
|
414 |
+ * <li>'staff': All the tickets currently with staff (varies for staff vs user; user count here includes 'new' tickets)</li> |
|
415 |
+ * <li>'with_user': All the tickets pending user comment</li> |
|
416 |
+ * <li>'closed': All the tickets the user can see that are resolved</li> |
|
417 |
+ * <li>'recycled': All the tickets the user can see that are currently in the recycle bin</li> |
|
418 |
+ * <li>'withdeleted': All the tickets that have at least one deleted reply</li> |
|
419 |
+ * <li>'' or unspecified: Return the total of all tickets in the helpdesk (subject to visibility)</li> |
|
420 |
+ * </ul> |
|
421 |
+ * @param bool $is_staff If the user in question is staff or not. |
|
422 |
+ * |
|
423 |
+ * @return int Number of applicable tickets. |
|
424 |
+ * @since 1.0 |
|
425 |
+*/ |
|
426 |
+function shd_count_helpdesk_tickets($status = '', $is_staff = false) |
|
427 |
+{ |
|
428 |
+ global $smcFunc, $context, $user_info; |
|
429 |
+ |
|
430 |
+ if (empty($context['ticket_count'])) |
|
431 |
+ { |
|
432 |
+ $context['ticket_count'] = array(); |
|
433 |
+ for ($i = 0; $i <= 6; $i++) |
|
434 |
+ $context['ticket_count'][$i] = 0; // set the count to zero for all known states |
|
435 |
+ |
|
436 |
+ $temp = cache_get_data('shd_ticket_count_' . $user_info['id'], 180); |
|
437 |
+ if ($temp !== null) |
|
438 |
+ { |
|
439 |
+ $context['ticket_count'] = $temp; |
|
440 |
+ } |
|
441 |
+ else |
|
442 |
+ { |
|
443 |
+ $query = shd_db_query('', ' |
|
444 |
+ SELECT status, COUNT(status) AS tickets |
|
445 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
446 |
+ WHERE {query_see_ticket} |
|
447 |
+ GROUP BY status |
|
448 |
+ ORDER BY null', |
|
449 |
+ array() |
|
450 |
+ ); |
|
451 |
+ |
|
452 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
453 |
+ $context['ticket_count'][$row['status']] = $row['tickets']; |
|
454 |
+ |
|
455 |
+ $smcFunc['db_free_result']($query); |
|
456 |
+ |
|
457 |
+ $context['ticket_count']['assigned'] = 0; |
|
458 |
+ if (shd_allowed_to('shd_staff')) |
|
459 |
+ { |
|
460 |
+ $query = shd_db_query('', ' |
|
461 |
+ SELECT status, COUNT(status) AS tickets |
|
462 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
463 |
+ WHERE {query_see_ticket} |
|
464 |
+ AND id_member_assigned = {int:user} |
|
465 |
+ GROUP BY status |
|
466 |
+ ORDER BY null', |
|
467 |
+ array( |
|
468 |
+ 'user' => $context['user']['id'], |
|
469 |
+ ) |
|
470 |
+ ); |
|
471 |
+ |
|
472 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
473 |
+ { |
|
474 |
+ if (!in_array($row['status'], array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED))) |
|
475 |
+ { |
|
476 |
+ $context['ticket_count']['assigned'] += $row['tickets']; |
|
477 |
+ $context['ticket_count'][$row['status']] -= $row['tickets']; |
|
478 |
+ } |
|
479 |
+ } |
|
480 |
+ |
|
481 |
+ $smcFunc['db_free_result']($query); |
|
482 |
+ } |
|
483 |
+ |
|
484 |
+ if (shd_allowed_to('shd_access_recyclebin')) |
|
485 |
+ { |
|
486 |
+ $query = shd_db_query('', ' |
|
487 |
+ SELECT COUNT(id_ticket) AS tickets |
|
488 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
489 |
+ WHERE {query_see_ticket} |
|
490 |
+ AND hdt.withdeleted = {int:has_deleted} |
|
491 |
+ AND hdt.status != {int:ticket_deleted}', |
|
492 |
+ array( |
|
493 |
+ 'has_deleted' => MSG_STATUS_DELETED, |
|
494 |
+ 'ticket_deleted' => TICKET_STATUS_DELETED, // we want all non deleted tickets with deleted replies |
|
495 |
+ ) |
|
496 |
+ ); |
|
497 |
+ list($count) = $smcFunc['db_fetch_row']($query); |
|
498 |
+ $smcFunc['db_free_result']($query); |
|
499 |
+ |
|
500 |
+ $context['ticket_count']['withdeleted'] = $count; |
|
501 |
+ } |
|
502 |
+ else |
|
503 |
+ $context['ticket_count']['withdeleted'] = 0; |
|
504 |
+ |
|
505 |
+ cache_put_data('shd_ticket_count_' . $user_info['id'], $context['ticket_count'], 180); |
|
506 |
+ } |
|
507 |
+ } |
|
508 |
+ |
|
509 |
+ switch($status) |
|
510 |
+ { |
|
511 |
+ case 'open': |
|
512 |
+ return ( |
|
513 |
+ $context['ticket_count'][TICKET_STATUS_NEW] + |
|
514 |
+ $context['ticket_count'][TICKET_STATUS_PENDING_STAFF] + |
|
515 |
+ $context['ticket_count'][TICKET_STATUS_PENDING_USER] + |
|
516 |
+ $context['ticket_count'][TICKET_STATUS_WITH_SUPERVISOR] + |
|
517 |
+ $context['ticket_count'][TICKET_STATUS_ESCALATED] // _ESCALATED |
|
518 |
+ ); |
|
519 |
+ case 'assigned': |
|
520 |
+ return $context['ticket_count']['assigned']; |
|
521 |
+ case 'new': |
|
522 |
+ return $context['ticket_count'][TICKET_STATUS_NEW]; |
|
523 |
+ case 'staff': |
|
524 |
+ return $is_staff ? $context['ticket_count'][TICKET_STATUS_PENDING_STAFF] : ($context['ticket_count'][TICKET_STATUS_NEW] + $context['ticket_count'][TICKET_STATUS_PENDING_STAFF]); // both "new" and "with staff" should appear as 'with staff' to non staff |
|
525 |
+ case 'with_user': |
|
526 |
+ return $context['ticket_count'][TICKET_STATUS_PENDING_USER]; |
|
527 |
+ case 'closed': |
|
528 |
+ return $context['ticket_count'][TICKET_STATUS_CLOSED]; |
|
529 |
+ case 'recycled': |
|
530 |
+ return $context['ticket_count'][TICKET_STATUS_DELETED]; |
|
531 |
+ case 'withdeleted': |
|
532 |
+ return $context['ticket_count']['withdeleted']; |
|
533 |
+ default: |
|
534 |
+ return array_sum($context['ticket_count']) - $context['ticket_count']['assigned']; |
|
535 |
+ } |
|
536 |
+} |
|
537 |
+ |
|
538 |
+/** |
|
539 |
+ * Attempts to load a given ticket's data. |
|
540 |
+ * |
|
541 |
+ * This function permission-checks, and throws appropriate errors if no ticket is specified either directly or through URL, |
|
542 |
+ * or if the ticket is not accessible either through deletion or lack of permissions. |
|
543 |
+ * |
|
544 |
+ * @param int $ticket The ticket to use; if none is specified, use the one from $_REQUEST['ticket'], which will have been processed |
|
545 |
+ * into $context['ticket_id'] if it is available. |
|
546 |
+ * |
|
547 |
+ * @return array A large hash map stating many ticket details |
|
548 |
+ * @since 1.0 |
|
549 |
+*/ |
|
550 |
+function shd_load_ticket($ticket = 0) |
|
551 |
+{ |
|
552 |
+ global $context, $smcFunc, $scripturl; |
|
553 |
+ |
|
554 |
+ // Make sure they set a ticket ID. |
|
555 |
+ if ($ticket == 0 && empty($context['ticket_id'])) |
|
556 |
+ fatal_lang_error('shd_no_ticket', false); |
|
557 |
+ |
|
558 |
+ // Get the ticket data. Note this implicitly checks perms too. |
|
559 |
+ $query = shd_db_query('', ' |
|
560 |
+ SELECT hdt.id_first_msg, hdt.id_last_msg, hdt.id_member_started, hdt.subject, hdt.urgency, hdt.status, |
|
561 |
+ hdt.num_replies, hdt.deleted_replies, hdt.private, hdtr.body, hdtr.id_member, hdtr.poster_time, |
|
562 |
+ hdtr.modified_time, hdtr.smileys_enabled, |
|
563 |
+ IFNULL(mem.real_name, hdtr.poster_name) AS starter_name, IFNULL(mem.id_member, 0) AS starter_id, hdtr.poster_ip AS starter_ip, |
|
564 |
+ IFNULL(ma.real_name, 0) AS assigned_name, IFNULL(ma.id_member, 0) AS assigned_id, |
|
565 |
+ IFNULL(mm.real_name, hdtr.modified_name) AS modified_name, IFNULL(mm.id_member, 0) AS modified_id |
|
566 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
567 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdt.id_first_msg = hdtr.id_msg) |
|
568 |
+ LEFT JOIN {db_prefix}members AS mem ON (hdt.id_member_started = mem.id_member) |
|
569 |
+ LEFT JOIN {db_prefix}members AS ma ON (hdt.id_member_assigned = ma.id_member) |
|
570 |
+ LEFT JOIN {db_prefix}members AS mm ON (hdtr.modified_member = mm.id_member) |
|
571 |
+ WHERE {query_see_ticket} AND hdt.id_ticket = {int:ticket}', |
|
572 |
+ array( |
|
573 |
+ 'ticket' => $ticket == 0 ? $context['ticket_id'] : $ticket, |
|
574 |
+ ) |
|
575 |
+ ); |
|
576 |
+ |
|
577 |
+ if ($smcFunc['db_num_rows']($query) == 0) |
|
578 |
+ { |
|
579 |
+ $smcFunc['db_free_result']($query); |
|
580 |
+ fatal_lang_error('shd_no_ticket', false); |
|
581 |
+ } |
|
582 |
+ |
|
583 |
+ $ticketinfo = $smcFunc['db_fetch_assoc']($query); |
|
584 |
+ $smcFunc['db_free_result']($query); |
|
585 |
+ |
|
586 |
+ // Anything else we'll use a lot? |
|
587 |
+ $ticketinfo['is_own'] = ($context['user']['id'] == $ticketinfo['starter_id']); |
|
588 |
+ $ticketinfo['closed'] = $ticketinfo['status'] == TICKET_STATUS_CLOSED; |
|
589 |
+ $ticketinfo['deleted'] = $ticketinfo['status'] == TICKET_STATUS_DELETED; |
|
590 |
+ |
|
591 |
+ return $ticketinfo; |
|
592 |
+} |
|
593 |
+ |
|
594 |
+/** |
|
595 |
+ * Formats a string for bbcode and/or smileys. |
|
596 |
+ * |
|
597 |
+ * Formatting is done according to the supplied settings and the master administration settings. It also deals with conversion of wiki links to tickets. |
|
598 |
+ * |
|
599 |
+ * @param string $text Raw text with optional bbcode formatting |
|
600 |
+ * @param bool $smileys Whether smileys should be used; this is not an override to the master administration setting of |
|
601 |
+ * whether to use smileys or not, and that takes precedence. |
|
602 |
+ * @param string $cache If specified, this will provide the cache'd id that SMF should use to cache the output if it is suitably large. |
|
603 |
+ * |
|
604 |
+ * @return string Will return $text as processed for bbcode (if $modSettings['shd_allow_ticket_bbc'] permits) and smileys (if |
|
605 |
+ * $modSettings['shd_allow_ticket_smileys'] and $smileys permits) |
|
606 |
+ * @since 1.0 |
|
607 |
+*/ |
|
608 |
+function shd_format_text($text, $smileys = true, $cache = '') |
|
609 |
+{ |
|
610 |
+ global $modSettings, $scripturl, $smcFunc; |
|
611 |
+ static $wikilinks = array(); |
|
612 |
+ static $smf_disabled = false, $shd_disabled = false; |
|
613 |
+ |
|
614 |
+ if (empty($modSettings['shd_allow_ticket_bbc'])) |
|
615 |
+ { |
|
616 |
+ if (!empty($modSettings['shd_allow_ticket_smileys']) && $smileys) |
|
617 |
+ parsesmileys($text); |
|
618 |
+ } |
|
619 |
+ else |
|
620 |
+ { |
|
621 |
+ // Figure out what's disabled, if anything, and do a bait'n'switch |
|
622 |
+ if ($smf_disabled === false) |
|
623 |
+ { |
|
624 |
+ $original_tags = parse_bbc(false); |
|
625 |
+ $tags = array(); |
|
626 |
+ foreach ($original_tags as $smf_tag) |
|
627 |
+ { |
|
628 |
+ if (!isset($tags[$smf_tag['tag']])) |
|
629 |
+ $tags[$smf_tag['tag']] = true; |
|
630 |
+ } |
|
631 |
+ |
|
632 |
+ // See what tagz we can haz. |
|
633 |
+ if (!empty($modSettings['shd_enabled_bbc'])) |
|
634 |
+ $enabled_tags = explode(',', $modSettings['shd_enabled_bbc']); |
|
635 |
+ else |
|
636 |
+ $enabled_tags = array(false); |
|
637 |
+ |
|
638 |
+ $disabled_tags = array_diff(array_keys($tags), $enabled_tags); // this gets us what's present in SMF but not enabled by SD |
|
639 |
+ $disabled_tags[] = '_SHD_DUMMY_TAG'; |
|
640 |
+ $smf_disabled = isset($modSettings['disabledBBC']) ? $modSettings['disabledBBC'] . ',_SHD_DUMMY_TAG' : '_SHD_DUMMY_TAG'; |
|
641 |
+ $shd_disabled = implode(',', $disabled_tags); |
|
642 |
+ |
|
643 |
+ } |
|
644 |
+ |
|
645 |
+ // wecanhazbbc |
|
646 |
+ if ($shd_disabled == $smf_disabled) |
|
647 |
+ { |
|
648 |
+ // What SMF and SD have is the same, yay |
|
649 |
+ $text = parse_bbc($text, (!empty($modSettings['shd_allow_ticket_smileys']) ? $smileys : false), $cache); |
|
650 |
+ } |
|
651 |
+ else |
|
652 |
+ { |
|
653 |
+ // first override SMF's disabled set with ours |
|
654 |
+ $modSettings['disabledBBC'] = $shd_disabled; |
|
655 |
+ parse_bbc(false); |
|
656 |
+ |
|
657 |
+ $text = parse_bbc($text, (!empty($modSettings['shd_allow_ticket_smileys']) ? $smileys : false), $cache); |
|
658 |
+ // Now put it back |
|
659 |
+ $modSettings['disabledBBC'] = $smf_disabled; |
|
660 |
+ parse_bbc(false); |
|
661 |
+ } |
|
662 |
+ } |
|
663 |
+ |
|
664 |
+ if (!empty($modSettings['shd_allow_wikilinks'])) |
|
665 |
+ { |
|
666 |
+ // Check for wiki syntax links - first figure out what links match in this text |
|
667 |
+ preg_match_all('~\[\[ticket\:([0-9]+)\]\]~iU', $text, $matches, PREG_SET_ORDER); |
|
668 |
+ |
|
669 |
+ // Step through the matches, check if it's one we already had in $wikilinks (where persists through the life of this page) |
|
670 |
+ $ticketlist = array(); |
|
671 |
+ $ticketcount = count($matches); |
|
672 |
+ for ($i = 0; $i < $ticketcount; $i++) |
|
673 |
+ { |
|
674 |
+ $id = (int) $matches[$i][1]; |
|
675 |
+ if (!isset($wikilinks[$id])) |
|
676 |
+ $ticketlist[$id] = false; |
|
677 |
+ } |
|
678 |
+ |
|
679 |
+ // Anything we didn't get from $wikilinks we now need to look up |
|
680 |
+ if (!empty($ticketlist)) |
|
681 |
+ { |
|
682 |
+ $query = shd_db_query('', ' |
|
683 |
+ SELECT id_ticket, subject |
|
684 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
685 |
+ WHERE {query_see_ticket} |
|
686 |
+ AND id_ticket IN ({array_int:tickets})', |
|
687 |
+ array( |
|
688 |
+ 'tickets' => array_keys($ticketlist), |
|
689 |
+ ) |
|
690 |
+ ); |
|
691 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
692 |
+ { |
|
693 |
+ $row['id_ticket'] = (int) $row['id_ticket']; |
|
694 |
+ $ticketlist[$row['id_ticket']] = $row['subject']; |
|
695 |
+ } |
|
696 |
+ |
|
697 |
+ // Attach the list we've just made to the master list. |
|
698 |
+ $wikilinks += $ticketlist; |
|
699 |
+ } |
|
700 |
+ |
|
701 |
+ // Now, go back through the list of matches again, this time we've got all the tickets we can actually display, so build the final replacement list |
|
702 |
+ $replacements = array(); |
|
703 |
+ for ($i = 0; $i < $ticketcount; $i++) |
|
704 |
+ { |
|
705 |
+ $id = (int) $matches[$i][1]; |
|
706 |
+ if (!empty($wikilinks[$id])) |
|
707 |
+ $replacements[$matches[$i][0]] = '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $id . '.0">[' . str_pad($id, 5, '0', STR_PAD_LEFT) . '] ' . $wikilinks[$id] . '</a>'; |
|
708 |
+ } |
|
709 |
+ |
|
710 |
+ $text = str_replace(array_keys($replacements), array_values($replacements), $text); |
|
711 |
+ } |
|
712 |
+ |
|
713 |
+ return $text; |
|
714 |
+} |
|
715 |
+ |
|
716 |
+/** |
|
717 |
+ * Generates a profile link given user id and name. |
|
718 |
+ * |
|
719 |
+ * SMF itself has loadMemberData() and loadMemberContext to perform this act, however those two functions are much larger and more |
|
720 |
+ * complex than we need more often than not, especially when all we want/need is member name (and subsequently profile link) |
|
721 |
+ * |
|
722 |
+ * Since profile links should be based on the view profile permission, we will need to establish that. |
|
723 |
+ * |
|
724 |
+ * @param string $name The name to display. This should be a standard SMF type name, which means already sanitised for HTML. |
|
725 |
+ * @param int $id The numeric id of the user we are linking to. |
|
726 |
+ * |
|
727 |
+ * @return string Returns an HTML link to user profile if sufficient permission and both a name and id are supplied. Otherwise just the name is. |
|
728 |
+ * @since 1.0 |
|
729 |
+*/ |
|
730 |
+function shd_profile_link($name, $id = 0) |
|
731 |
+{ |
|
732 |
+ global $user_info, $scripturl; |
|
733 |
+ static $any = null; |
|
734 |
+ static $own = null; |
|
735 |
+ |
|
736 |
+ if ($any === null) |
|
737 |
+ { |
|
738 |
+ $any = allowedTo('profile_view_any') || shd_allowed_to('shd_view_profile_any'); // profile is visible either on SMF or SD permission. |
|
739 |
+ $own = allowedTo('profile_view_own') || shd_allowed_to('shd_view_profile_own'); |
|
740 |
+ } |
|
741 |
+ |
|
742 |
+ if (empty($id)) |
|
743 |
+ return $name; |
|
744 |
+ elseif ($any || ($own && $id == $user_info['id'])) |
|
745 |
+ return '<a href="' . $scripturl . '?action=profile;u=' . $id . '">' . $name . '</a>'; |
|
746 |
+ else |
|
747 |
+ return $name; |
|
748 |
+} |
|
749 |
+ |
|
750 |
+/** |
|
751 |
+ * Generate an image URL given the base filename. |
|
752 |
+ * |
|
753 |
+ * As of 1.1, images can live either in the main Themes/default/images/simpledesk folder, or additionally in Themes/default/images/sd_plugins, |
|
754 |
+ * the latter of which is intended for plugins (the former is removed on SD uninstall, the latter is not) |
|
755 |
+ * |
|
756 |
+ * It should only be used in cases where there is ambiguity over where the image may live, e.g. preferences, permissions UIs. If there is no |
|
757 |
+ * ambiguity (e.g. SD core, or plugins themselves, where they know where the image will be referenced from), it is recommended to avoid this function. |
|
758 |
+ * |
|
759 |
+ * @param string $filename An image filename, e.g. image.png |
|
760 |
+ * @return string A full URL to the image in question, e.g. http://www.example.com/Themes/default/images/sd_plugins/image.png |
|
761 |
+*/ |
|
762 |
+function shd_image_url($filename) |
|
763 |
+{ |
|
764 |
+ global $settings; |
|
765 |
+ if (file_exists($settings['default_theme_dir'] . '/images/sd_plugins/' . $filename)) |
|
766 |
+ return $settings['default_theme_url'] . '/images/sd_plugins/' . $filename; |
|
767 |
+ else |
|
768 |
+ return $settings['default_theme_url'] . '/images/simpledesk/' . $filename; |
|
769 |
+} |
|
770 |
+ |
|
771 |
+/** |
|
772 |
+ * Establishes the next change of status of a ticket. |
|
773 |
+ * |
|
774 |
+ * Tickets invariably have multiple changes of status during their life. All actions that could change |
|
775 |
+ * a ticket's status should call here, even if it is a straight forward, one-route-only change of status |
|
776 |
+ * since it is possible we could end up giving the user a choice one day over how statuses work, so |
|
777 |
+ * we should route everything through here all the time. |
|
778 |
+ * |
|
779 |
+ * @param string $action (required), represents the action carried out by the calling function |
|
780 |
+ * Known values: new, resolve, unresolve, deleteticket, restoreticket, deletereply, restorereply, reply, merge, topictoticket (new is default) |
|
781 |
+ * @param int $starter_id Numeric id of the ticket's starter (should be provided) |
|
782 |
+ * @param int $replier_id Numeric id of the ticket's last reply author (should be provided) |
|
783 |
+ * @param int $replies Number of replies in the ticket (should be provided) |
|
784 |
+ * |
|
785 |
+ * @return int Returns an integer value that corresponds to the ticket's status, relating to one of the TICKET_STATUS states. |
|
786 |
+ * @since 1.0 |
|
787 |
+*/ |
|
788 |
+function shd_determine_status($action, $starter_id = 0, $replier_id = 0, $replies = -1) |
|
789 |
+{ |
|
790 |
+ $known_states = array( |
|
791 |
+ 'new', |
|
792 |
+ 'resolve', |
|
793 |
+ 'unresolve', |
|
794 |
+ 'deleteticket', |
|
795 |
+ 'restoreticket', |
|
796 |
+ 'deletereply', |
|
797 |
+ 'restorereply', |
|
798 |
+ 'reply', |
|
799 |
+ 'topictoticket', |
|
800 |
+ 'mergesplit', |
|
801 |
+ ); |
|
802 |
+ |
|
803 |
+ if (!in_array($action, $known_states)) |
|
804 |
+ $action = 'new'; |
|
805 |
+ |
|
806 |
+ switch ($action) |
|
807 |
+ { |
|
808 |
+ case 'new': |
|
809 |
+ return TICKET_STATUS_NEW; // it's a new ticket, what more can I say? |
|
810 |
+ case 'resolve': |
|
811 |
+ return TICKET_STATUS_CLOSED; // yup, all done |
|
812 |
+ case 'deleteticket': |
|
813 |
+ return TICKET_STATUS_DELETED; // bye bye |
|
814 |
+ case 'mergesplit': // used in handling deleted replies |
|
815 |
+ case 'deletereply': |
|
816 |
+ case 'restorereply': |
|
817 |
+ case 'unresolve': |
|
818 |
+ case 'restoreticket': |
|
819 |
+ case 'reply': |
|
820 |
+ case 'topictoticket': |
|
821 |
+ if ($replies == 0) |
|
822 |
+ return TICKET_STATUS_NEW; |
|
823 |
+ else |
|
824 |
+ { |
|
825 |
+ $staff = shd_members_allowed_to('shd_staff'); |
|
826 |
+ if (in_array($replier_id, $staff)) |
|
827 |
+ $new_status = $starter_id == $replier_id ? TICKET_STATUS_PENDING_STAFF : TICKET_STATUS_PENDING_USER; // i.e. if they're staff but it's their own ticket they're replying to, it's not with user. |
|
828 |
+ else |
|
829 |
+ $new_status = TICKET_STATUS_PENDING_STAFF; |
|
830 |
+ |
|
831 |
+ return $new_status; |
|
832 |
+ } |
|
833 |
+ } |
|
834 |
+} |
|
835 |
+ |
|
836 |
+/** |
|
837 |
+ * Wrapper function for constructPageIndex to forcibly block the extensible ... item in page indexes |
|
838 |
+ * |
|
839 |
+ * SimpleDesk uses SMF's core page index function in numerous places, but unlike SMF, it often places it in containers |
|
840 |
+ * that have backgrounds driven by menu_block.png, meaning that they are often fixed in height. Under some circumstances |
|
841 |
+ * layout can be broken, so this function forcibly ensures the block can never expand to force wrapping. |
|
842 |
+ * |
|
843 |
+ * @param string $base_url Form of URL pageindex links should take, using $1%d to represent the start point identifier. |
|
844 |
+ * @param int &$start Position to start. If not a multiple of the number per page, it will be forced to become a multiple. |
|
845 |
+ * @param int $max_value Number of items in total to paginate for. |
|
846 |
+ * @param int $num_per_page Number of items to be shown on a page. |
|
847 |
+ * @param bool $flexible_start Whether a more flexible % option is to be used in the base URL. |
|
848 |
+ * |
|
849 |
+ * @return string The constructed page index, without Javascript expander(s). |
|
850 |
+ * @since 1.0 |
|
851 |
+*/ |
|
852 |
+function shd_no_expand_pageindex($base_url, &$start, $max_value, $num_per_page, $flexible_start = false) |
|
853 |
+{ |
|
854 |
+ return preg_replace('~<span([^<]+)~i', '<span style="font-weight: bold;"> ... ', constructPageIndex($base_url, $start, $max_value, $num_per_page, $flexible_start)); |
|
855 |
+} |
|
856 |
+ |
|
857 |
+/** |
|
858 |
+ * Wrapper for loadLanguage to ensure English language files are always loaded regardless of user language settings as a fallback |
|
859 |
+ * |
|
860 |
+ * As of 2.0 RC2, there is detection code in SMF to ensure the Modifications language file is always loaded, but the same detection is not applied to all language files. This ensures it will be for SD files. |
|
861 |
+ * |
|
862 |
+ * @param string $langfile Name of a language file to load, typically SimpleDesk prefixed, though could be used for any SMF language file. |
|
863 |
+ * @param string $override_lang Name of a language to load as an override, rather than just the user's default. |
|
864 |
+ * @since 1.1 |
|
865 |
+*/ |
|
866 |
+function shd_load_language($langfile, $override_lang = '') |
|
867 |
+{ |
|
868 |
+ global $modSettings, $user_info, $language; |
|
869 |
+ if (empty($modSettings['disable_language_fallback'])) |
|
870 |
+ { |
|
871 |
+ $cur_language = isset($user_info['language']) ? $user_info['language'] : ($override_lang == '' ? $language : $override_lang); |
|
872 |
+ if ($cur_language !== 'english') |
|
873 |
+ loadLanguage($langfile, 'english', false); |
|
874 |
+ } |
|
875 |
+ loadLanguage($langfile, $cur_language, false); |
|
876 |
+} |
|
877 |
+ |
|
878 |
+/** |
|
879 |
+ * Clean up tickets that have been modified by replies being altered through restore, delete, merge and split. |
|
880 |
+ * |
|
881 |
+ * Operations: |
|
882 |
+ * - Identify how many deleted and non deleted replies there are in the ticket. |
|
883 |
+ * - Identify the last non deleted reply in the ticket (if there are no undeleted replies, use the ticket post itself for cohesion) |
|
884 |
+ * - Update the ticket's record with the first and last posters, as well as the correct number of active and deleted replies, and whether there are any deleted replies on the ticket generally |
|
885 |
+ * |
|
886 |
+ * Prior to SimpleDesk 1.1, this function was located in Sources/SimpleDesk-Delete.php. |
|
887 |
+ * |
|
888 |
+ * @param int $ticket The ticket id to recalculate. |
|
889 |
+ * |
|
890 |
+ * @return array An array detailing the user id of the starter, the last replier and the number of active replies in a ticket. |
|
891 |
+ * |
|
892 |
+ * @since 1.0 |
|
893 |
+*/ |
|
894 |
+function shd_recalc_ids($ticket) |
|
895 |
+{ |
|
896 |
+ global $smcFunc; |
|
897 |
+ |
|
898 |
+ $query = shd_db_query('', ' |
|
899 |
+ SELECT hdt.id_first_msg |
|
900 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
901 |
+ WHERE hdt.id_ticket = {int:ticket}', |
|
902 |
+ array( |
|
903 |
+ 'ticket' => $ticket, |
|
904 |
+ ) |
|
905 |
+ ); |
|
906 |
+ list($first_msg) = $smcFunc['db_fetch_row']($query); |
|
907 |
+ $smcFunc['db_free_result']($query); |
|
908 |
+ |
|
909 |
+ $query = shd_db_query('', ' |
|
910 |
+ SELECT hdtr.message_status, COUNT(hdtr.message_status) AS messages, hdt.id_first_msg, MAX(hdtr.id_msg) AS id_last_msg |
|
911 |
+ FROM {db_prefix}helpdesk_ticket_replies AS hdtr |
|
912 |
+ INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdt.id_ticket = hdtr.id_ticket) |
|
913 |
+ WHERE hdtr.id_msg > hdt.id_first_msg |
|
914 |
+ AND hdt.id_ticket = {int:ticket} |
|
915 |
+ GROUP BY hdtr.message_status', |
|
916 |
+ array( |
|
917 |
+ 'ticket' => $ticket, |
|
918 |
+ ) |
|
919 |
+ ); |
|
920 |
+ |
|
921 |
+ $messages = array( |
|
922 |
+ MSG_STATUS_NORMAL => 0, // message_status = 0 |
|
923 |
+ MSG_STATUS_DELETED => 0, // message_status = 1 |
|
924 |
+ ); |
|
925 |
+ |
|
926 |
+ $last_msg = 0; |
|
927 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
928 |
+ { |
|
929 |
+ $first_msg = $row['id_first_msg']; |
|
930 |
+ $messages[$row['message_status']] = $row['messages']; |
|
931 |
+ if ($row['message_status'] == MSG_STATUS_NORMAL) |
|
932 |
+ $last_msg = $row['id_last_msg']; |
|
933 |
+ } |
|
934 |
+ |
|
935 |
+ $smcFunc['db_free_result']($query); |
|
936 |
+ |
|
937 |
+ if (empty($last_msg)) |
|
938 |
+ $last_msg = $first_msg; |
|
939 |
+ |
|
940 |
+ // OK, so we have the last message id and correct number of replies, which is awesome. Now we need to ensure user ids are right |
|
941 |
+ $query = shd_db_query('', ' |
|
942 |
+ SELECT hdtr_first.id_member, hdtr_last.id_member |
|
943 |
+ FROM {db_prefix}helpdesk_tickets AS hdt |
|
944 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdtr_first.id_msg = {int:first_msg}) |
|
945 |
+ INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdtr_last.id_msg = {int:last_msg}) |
|
946 |
+ WHERE hdt.id_ticket = {int:ticket}', |
|
947 |
+ array( |
|
948 |
+ 'first_msg' => $first_msg, |
|
949 |
+ 'last_msg' => $last_msg, |
|
950 |
+ 'ticket' => $ticket, |
|
951 |
+ ) |
|
952 |
+ ); |
|
953 |
+ list($starter, $replier) = $smcFunc['db_fetch_row']($query); |
|
954 |
+ $smcFunc['db_free_result']($query); |
|
955 |
+ |
|
956 |
+ shd_db_query('', ' |
|
957 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
958 |
+ SET num_replies = {int:num_replies}, |
|
959 |
+ deleted_replies = {int:deleted_replies}, |
|
960 |
+ id_last_msg = {int:last_msg}, |
|
961 |
+ id_member_started = {int:starter}, |
|
962 |
+ id_member_updated = {int:replier}, |
|
963 |
+ withdeleted = {int:has_deleted} |
|
964 |
+ WHERE id_ticket = {int:ticket}', |
|
965 |
+ array( |
|
966 |
+ 'num_replies' => $messages[MSG_STATUS_NORMAL], |
|
967 |
+ 'deleted_replies' => $messages[MSG_STATUS_DELETED], |
|
968 |
+ 'last_msg' => $last_msg, |
|
969 |
+ 'starter' => $starter, |
|
970 |
+ 'replier' => $replier, |
|
971 |
+ 'has_deleted' => ($messages[MSG_STATUS_DELETED] > 0) ? 1 : 0, |
|
972 |
+ 'ticket' => $ticket, |
|
973 |
+ ) |
|
974 |
+ ); |
|
975 |
+ |
|
976 |
+ return array($starter, $replier, $messages[MSG_STATUS_NORMAL]); |
|
977 |
+} |
|
978 |
+ |
|
979 |
+/** |
|
980 |
+ * Load the user preferences for the given user. |
|
981 |
+ * |
|
982 |
+ * @param mixed $user Normally, an int being the user id of the user whose preferences should be attempted to be loaded. If === false, return the list of default prefs (for the pref UI), or if 0 or omitted, load the current user. |
|
983 |
+ * |
|
984 |
+ * @return array If $user === false, the list of options, their types and default values is returned. Otherwise, return an array of prefs (adjusted for this user) |
|
985 |
+ * @since 1.1 |
|
986 |
+*/ |
|
987 |
+function shd_load_user_prefs($user = 0) |
|
988 |
+{ |
|
989 |
+ global $modSettings, $smcFunc, $user_info; |
|
990 |
+ |
|
991 |
+ $pref_groups = array(); |
|
992 |
+ |
|
993 |
+ $base_prefs = array(); |
|
994 |
+ |
|
995 |
+ // Now engage any hooks. |
|
996 |
+ if (!empty($modSettings['shd_hook_prefs'])) |
|
997 |
+ { |
|
998 |
+ $functions = explode(',', $modSettings['shd_hook_prefs']); |
|
999 |
+ foreach ($functions as $function) |
|
1000 |
+ { |
|
1001 |
+ if (is_callable($function)) |
|
1002 |
+ $function($pref_groups, $base_prefs); // these should be picked up by reference in the called function or they won't do anything! |
|
1003 |
+ } |
|
1004 |
+ } |
|
1005 |
+ |
|
1006 |
+ foreach ($base_prefs as $pref => $details) |
|
1007 |
+ { |
|
1008 |
+ if (empty($pref_groups[$details['group']]['enabled']) || empty($details['show'])) |
|
1009 |
+ unset($base_prefs[$pref]); |
|
1010 |
+ } |
|
1011 |
+ |
|
1012 |
+ // Do we just want the prefs list? |
|
1013 |
+ if ($user === false) |
|
1014 |
+ return array( |
|
1015 |
+ 'groups' => $pref_groups, |
|
1016 |
+ 'prefs' => $base_prefs, |
|
1017 |
+ ); |
|
1018 |
+ |
|
1019 |
+ $prefs = array(); |
|
1020 |
+ if ($user == 0 || $user == $user_info['id']) |
|
1021 |
+ { |
|
1022 |
+ $user = $user_info['id']; |
|
1023 |
+ |
|
1024 |
+ // Start with the defaults, but dealing with permissions as we go |
|
1025 |
+ foreach ($base_prefs as $pref => $details) |
|
1026 |
+ { |
|
1027 |
+ if (empty($details['permission']) || shd_allowed_to($details['permission'])) |
|
1028 |
+ $prefs[$pref] = $details['default']; |
|
1029 |
+ } |
|
1030 |
+ } |
|
1031 |
+ else |
|
1032 |
+ { |
|
1033 |
+ $pref_list = array(); |
|
1034 |
+ foreach ($base_prefs as $pref => $details) |
|
1035 |
+ { |
|
1036 |
+ if (empty($pref_groups[$details['group']]['enabled'])) |
|
1037 |
+ continue; |
|
1038 |
+ |
|
1039 |
+ if (!empty($details['permission'])) |
|
1040 |
+ { |
|
1041 |
+ if (!isset($pref_list[$details['permission']])) |
|
1042 |
+ $pref_list[$details['permission']] = in_array($user, shd_members_allowed_to($details['permission'])); |
|
1043 |
+ |
|
1044 |
+ if ($pref_list[$details['permission']]) |
|
1045 |
+ $prefs[$pref] = $details['default']; |
|
1046 |
+ } |
|
1047 |
+ } |
|
1048 |
+ } |
|
1049 |
+ |
|
1050 |
+ // Now, the database |
|
1051 |
+ $query = $smcFunc['db_query']('', ' |
|
1052 |
+ SELECT variable, value |
|
1053 |
+ FROM {db_prefix}helpdesk_preferences |
|
1054 |
+ WHERE id_member = {int:user}', |
|
1055 |
+ array( |
|
1056 |
+ 'user' => (int) $user, |
|
1057 |
+ ) |
|
1058 |
+ ); |
|
1059 |
+ |
|
1060 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
1061 |
+ { |
|
1062 |
+ if (isset($prefs[$row['variable']])) |
|
1063 |
+ $prefs[$row['variable']] = $row['value']; |
|
1064 |
+ } |
|
1065 |
+ |
|
1066 |
+ return $prefs; |
|
1067 |
+} |
|
1068 |
+ |
|
1069 |
+/** |
|
1070 |
+ * Loads any source files directed by integration hooks. |
|
1071 |
+ * |
|
1072 |
+ * @since 1.1 |
|
1073 |
+*/ |
|
1074 |
+function shd_load_plugin_files($hook = '') |
|
1075 |
+{ |
|
1076 |
+ global $sourcedir, $modSettings; |
|
1077 |
+ |
|
1078 |
+ if (empty($hook) || empty($modSettings['shd_include_' . $hook])) |
|
1079 |
+ return; |
|
1080 |
+ |
|
1081 |
+ $filelist = explode(',', $modSettings['shd_include_' . $hook]); |
|
1082 |
+ foreach ($filelist as $file) |
|
1083 |
+ { |
|
1084 |
+ if (file_exists($sourcedir . '/sd_plugins_source/' . $file)) |
|
1085 |
+ require_once($sourcedir . '/sd_plugins_source/' . $file); |
|
1086 |
+ } |
|
1087 |
+} |
|
1088 |
+ |
|
1089 |
+/** |
|
1090 |
+ * Loads any language files directed by integration hooks. |
|
1091 |
+ * |
|
1092 |
+ * @since 1.1 |
|
1093 |
+*/ |
|
1094 |
+function shd_load_plugin_langfiles($hook = '') |
|
1095 |
+{ |
|
1096 |
+ global $modSettings; |
|
1097 |
+ |
|
1098 |
+ if (empty($hook) || empty($modSettings['shd_includelang_' . $hook])) |
|
1099 |
+ return; |
|
1100 |
+ |
|
1101 |
+ $filelist = explode(',', $modSettings['shd_includelang_' . $hook]); |
|
1102 |
+ foreach ($filelist as $file) |
|
1103 |
+ shd_load_language($file); |
|
1104 |
+} |
|
1105 |
+ |
|
1106 |
+/** |
|
1107 |
+ * Placeholder for calling the scheduled maintenance functions. |
|
1108 |
+ * |
|
1109 |
+ * All scheduled tasks have to have the name prefix scheduled_ and must be defined by the time we get to running AutoTask() in Scheduled.php. Short of modifying that file, we can define a placeholder here (which will exist for AutoTask) and have that be called. |
|
1110 |
+ * |
|
1111 |
+ * @since 1.1 |
|
1112 |
+*/ |
|
1113 |
+function scheduled_simpledesk() |
|
1114 |
+{ |
|
1115 |
+ global $sourcedir; |
|
1116 |
+ |
|
1117 |
+ require($sourcedir . '/sd_source/SimpleDesk-Scheduled.php'); |
|
1118 |
+ return shd_scheduled(); |
|
1119 |
+} |
|
1120 |
+?> |
|
0 | 1121 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,207 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: Subs-SimpleDeskAdmin.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file deals with some of the items required by the helpdesk, but are primarily supporting |
|
22 |
+ * functions; they're not the principle functions that drive the admin area. |
|
23 |
+ * |
|
24 |
+ * @package subs |
|
25 |
+ * @since 1.0 |
|
26 |
+ */ |
|
27 |
+ |
|
28 |
+if (!defined('SMF')) |
|
29 |
+ die('Hacking attempt...'); |
|
30 |
+ |
|
31 |
+/** |
|
32 |
+ * Load the items from the helpdesk action log |
|
33 |
+ * |
|
34 |
+ * It is subject to given parameters (start, number of items, order/sorting), parses the language strings and adds the |
|
35 |
+ * parameter information provided. |
|
36 |
+ * |
|
37 |
+ * @param int $start Number of items into the log to start (for pagination). If nothing is given, fall back to 0, i.e the first log item. |
|
38 |
+ * @param int $items_per_page How many items to load. Default to 10 items. |
|
39 |
+ * @param string $sort SQL clause to state which column(s) to order the data by. By default it orders by log_time. |
|
40 |
+ * @param string $order SQL clause to state whether the order is ascending or descending. Defaults to descending. |
|
41 |
+ * @param string $clause An SQL fragment that forms a WHERE clause to limit log items, e.g. to load a specific ticket or specific member's log items. |
|
42 |
+ * |
|
43 |
+ * @return array A hash array of the log items, with the auto-incremented id being the key: |
|
44 |
+ * <ul> |
|
45 |
+ * <li>id: Numeric identifier of the log item</li> |
|
46 |
+ * <li>time: Formatted time of the event (as per usual for SMF, formatted for user's timezone)</li> |
|
47 |
+ * <li>member: hash array: |
|
48 |
+ * <ul> |
|
49 |
+ * <li>id: Id of the user that committed the action</li> |
|
50 |
+ * <li>name: Name of the user</li> |
|
51 |
+ * <li>link: Link to the profile of the user that committed the action</li> |
|
52 |
+ * <li>ip: User IP address recorded when the action was carried out</li> |
|
53 |
+ * <li>group: Name of the group of the user (uses primary group, failing that post count group)</li> |
|
54 |
+ * </ul> |
|
55 |
+ * </li> |
|
56 |
+ * <li>action: Raw name of the action (for use with collecting the image later)</li> |
|
57 |
+ * <li>id_ticket: Numeric id of the ticket this action refers to</li> |
|
58 |
+ * <li>id_msg: Numeric id of the individual reply this action refers to</li> |
|
59 |
+ * <li>extra: Array of extra parameters for the log action</li> |
|
60 |
+ * <li>action_text: Formatted text of the log item (parsed with parameters)</li> |
|
61 |
+ * </ul> |
|
62 |
+ * |
|
63 |
+ * @see shd_log_action() |
|
64 |
+ * @see shd_count_action_log_entries() |
|
65 |
+ * @since 1.0 |
|
66 |
+*/ |
|
67 |
+function shd_load_action_log_entries($start = 0, $items_per_page = 10, $sort = 'la.log_time', $order = 'DESC', $clause = '') |
|
68 |
+{ |
|
69 |
+ global $smcFunc, $txt, $scripturl, $context, $user_info; |
|
70 |
+ |
|
71 |
+ // Load languages incase they aren't there (Read: ticket-specific logs) |
|
72 |
+ shd_load_language('SimpleDeskLogAction'); |
|
73 |
+ shd_load_language('SimpleDeskAdmin'); |
|
74 |
+ |
|
75 |
+ // Without further screaming and waving, fetch the actions. |
|
76 |
+ $request = shd_db_query('',' |
|
77 |
+ SELECT la.id_action, la.log_time, la.id_member, la.ip, la.action, la.id_ticket, la.id_msg, la.extra, |
|
78 |
+ mem.real_name, mg.group_name |
|
79 |
+ FROM {db_prefix}helpdesk_log_action AS la |
|
80 |
+ LEFT JOIN {db_prefix}members AS mem ON(mem.id_member = la.id_member) |
|
81 |
+ LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_group_id} THEN mem.id_post_group ELSE mem.id_group END) |
|
82 |
+ {raw:clause} |
|
83 |
+ ORDER BY ' . ($sort != '' ? '{raw:sort} {raw:order}' : 'la.log_time DESC') . ' |
|
84 |
+ ' . ($start != 0 ? 'LIMIT {int:start}, {int:items_per_page})' : ''), |
|
85 |
+ array( |
|
86 |
+ 'reg_group_id' => 0, |
|
87 |
+ 'sort' => $sort, |
|
88 |
+ 'start' => $start, |
|
89 |
+ 'items_per_page' => $items_per_page, |
|
90 |
+ 'order' => $order, |
|
91 |
+ 'clause' => empty($clause) ? '' : 'WHERE ' . $clause, |
|
92 |
+ ) |
|
93 |
+ ); |
|
94 |
+ |
|
95 |
+ $actions = array(); |
|
96 |
+ |
|
97 |
+ while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
98 |
+ { |
|
99 |
+ $row['extra'] = @unserialize($row['extra']); |
|
100 |
+ $row['extra'] = is_array($row['extra']) ? $row['extra'] : array(); |
|
101 |
+ |
|
102 |
+ $actions[$row['id_action']] = array( |
|
103 |
+ 'id' => $row['id_action'], |
|
104 |
+ 'time' => timeformat($row['log_time']), |
|
105 |
+ 'member' => array( |
|
106 |
+ 'id' => $row['id_member'], |
|
107 |
+ 'name' => $row['real_name'], |
|
108 |
+ 'link' => shd_profile_link($row['real_name'], $row['id_member']), |
|
109 |
+ 'group' => $row['group_name'], |
|
110 |
+ ), |
|
111 |
+ 'action' => $row['action'], |
|
112 |
+ 'id_ticket' => $row['id_ticket'], |
|
113 |
+ 'id_msg' => $row['id_msg'], |
|
114 |
+ 'extra' => $row['extra'], |
|
115 |
+ 'action_text' => '', |
|
116 |
+ 'action_icon' => 'log_' . $row['action'] . '.png', |
|
117 |
+ 'can_remove' => empty($context['waittime']) ? false : ($row['log_time'] < $context['waittime']), |
|
118 |
+ ); |
|
119 |
+ |
|
120 |
+ if (shd_allowed_to('shd_view_ip_any') || ($row['id_member'] == $user_info['id'] && shd_allowed_to('shd_view_ip_own'))) |
|
121 |
+ $actions[$row['id_action']]['member']['ip'] = !empty($row['ip']) ? $row['ip'] : $txt['shd_admin_actionlog_unknown']; |
|
122 |
+ } |
|
123 |
+ |
|
124 |
+ $smcFunc['db_free_result']($request); |
|
125 |
+ |
|
126 |
+ // Do some formatting of the action string. |
|
127 |
+ foreach ($actions as $k => $action) |
|
128 |
+ { |
|
129 |
+ if (empty($actions[$k]['action_text'])) |
|
130 |
+ $actions[$k]['action_text'] = isset($txt['shd_log_' . $action['action']]) ? $txt['shd_log_' . $action['action']] : $action['action']; |
|
131 |
+ |
|
132 |
+ $actions[$k]['action_text'] = str_replace('{scripturl}', $scripturl, $actions[$k]['action_text']); |
|
133 |
+ |
|
134 |
+ if (isset($action['extra']['subject'])) |
|
135 |
+ { |
|
136 |
+ $actions[$k]['action_text'] = str_replace('{ticket}', $actions[$k]['id_ticket'], $actions[$k]['action_text']); |
|
137 |
+ $actions[$k]['action_text'] = str_replace('{msg}', $actions[$k]['id_msg'], $actions[$k]['action_text']); |
|
138 |
+ |
|
139 |
+ if (isset($actions[$k]['extra']['subject'])) |
|
140 |
+ $actions[$k]['action_text'] = str_replace('{subject}', $actions[$k]['extra']['subject'], $actions[$k]['action_text']); |
|
141 |
+ |
|
142 |
+ if (isset($actions[$k]['extra']['urgency'])) |
|
143 |
+ $actions[$k]['action_text'] = str_replace('{urgency}', $txt['shd_urgency_' . $actions[$k]['extra']['urgency']], $actions[$k]['action_text']); |
|
144 |
+ } |
|
145 |
+ if (isset($action['extra']['user_name'])) |
|
146 |
+ { |
|
147 |
+ $actions[$k]['action_text'] = str_replace('{profile_link}', shd_profile_link($actions[$k]['extra']['user_name'], (isset($actions[$k]['extra']['user_id']) ? $actions[$k]['extra']['user_id'] : 0)), $actions[$k]['action_text']); |
|
148 |
+ $actions[$k]['action_text'] = str_replace('{user_name}', $actions[$k]['extra']['user_name'], $actions[$k]['action_text']); |
|
149 |
+ } |
|
150 |
+ if (isset($action['extra']['user_id'])) |
|
151 |
+ $actions[$k]['action_text'] = str_replace('{user_id}', $actions[$k]['extra']['user_id'], $actions[$k]['action_text']); |
|
152 |
+ if (isset($actions[$k]['extra']['board_name'])) |
|
153 |
+ $actions[$k]['action_text'] = str_replace('{board_name}', $actions[$k]['extra']['board_name'], $actions[$k]['action_text']); |
|
154 |
+ if (isset($actions[$k]['extra']['board_id'])) |
|
155 |
+ $actions[$k]['action_text'] = str_replace('{board_id}', $actions[$k]['extra']['board_id'], $actions[$k]['action_text']); |
|
156 |
+ if (isset($action['extra']['othersubject'])) |
|
157 |
+ { |
|
158 |
+ $actions[$k]['action_text'] = str_replace('{othersubject}', $actions[$k]['extra']['othersubject'], $actions[$k]['action_text']); |
|
159 |
+ $actions[$k]['action_text'] = str_replace('{otherticket}', $actions[$k]['extra']['otherticket'], $actions[$k]['action_text']); |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ // This should be the last pair of ops - always. |
|
163 |
+ if (isset($action['extra']['att_added'])) |
|
164 |
+ $actions[$k]['action_text'] .= ' ' . $txt['shd_logpart_att_added'] . ': ' . implode(', ', $action['extra']['att_added']); |
|
165 |
+ if (isset($action['extra']['att_removed'])) |
|
166 |
+ $actions[$k]['action_text'] .= ' ' . $txt['shd_logpart_att_removed'] . ': ' . implode(', ', $action['extra']['att_removed']); |
|
167 |
+ |
|
168 |
+ } |
|
169 |
+ return $actions; |
|
170 |
+} |
|
171 |
+ |
|
172 |
+/** |
|
173 |
+ * Returns the total number of items in the helpdesk log. |
|
174 |
+ * |
|
175 |
+ * This function gets the total number of items logged in the helpdesk log, for the purposes of establishing the number of |
|
176 |
+ * pages there should be in the page-index. |
|
177 |
+ * |
|
178 |
+ * @param string $clause An SQL fragment that forms a WHERE clause to limit log items, e.g. to load a specific ticket or specific member's log items. |
|
179 |
+ * |
|
180 |
+ * @return int Number of entries in the helpdesk action log table. |
|
181 |
+ * @see shd_load_action_log_entries() |
|
182 |
+ * @since 1.0 |
|
183 |
+*/ |
|
184 |
+function shd_count_action_log_entries($clause = '') |
|
185 |
+{ |
|
186 |
+ global $smcFunc; |
|
187 |
+ |
|
188 |
+ // Without further screaming and waving, fetch the actions. |
|
189 |
+ $request = shd_db_query('',' |
|
190 |
+ SELECT COUNT(*) |
|
191 |
+ FROM {db_prefix}helpdesk_log_action AS la |
|
192 |
+ LEFT JOIN {db_prefix}members AS mem ON(mem.id_member = la.id_member) |
|
193 |
+ LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_group_id} THEN mem.id_post_group ELSE mem.id_group END) |
|
194 |
+ {raw:clause}', |
|
195 |
+ array( |
|
196 |
+ 'reg_group_id' => 0, |
|
197 |
+ 'clause' => empty($clause) ? '' : 'WHERE ' . $clause, |
|
198 |
+ ) |
|
199 |
+ ); |
|
200 |
+ |
|
201 |
+ list ($entry_count) = $smcFunc['db_fetch_row']($request); |
|
202 |
+ $smcFunc['db_free_result']($request); |
|
203 |
+ |
|
204 |
+ return $entry_count; |
|
205 |
+} |
|
206 |
+ |
|
207 |
+?> |
|
0 | 208 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,573 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: Subs-SimpleDeskPermissions.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles the core permissions systems for SimpleDesk, including the permissions templates, loading and checking permissions. |
|
22 |
+ * |
|
23 |
+ * @package subs |
|
24 |
+ * @since 1.1 |
|
25 |
+ */ |
|
26 |
+ |
|
27 |
+if (!defined('SMF')) |
|
28 |
+ die('Hacking attempt...'); |
|
29 |
+ |
|
30 |
+/** |
|
31 |
+ * This function stores the master list of permissions. |
|
32 |
+ * |
|
33 |
+ * @since 1.1 |
|
34 |
+*/ |
|
35 |
+function shd_load_all_permission_sets() |
|
36 |
+{ |
|
37 |
+ global $context, $modSettings; |
|
38 |
+ |
|
39 |
+ // We're actually going to display it in multiple columns, so break it down into groups |
|
40 |
+ $context['shd_permissions']['group_display'] = array( |
|
41 |
+ array( |
|
42 |
+ 'general' => 'status.png', |
|
43 |
+ 'posting' => 'log_newticket.png', |
|
44 |
+ 'deletion' => 'log_delete.png', |
|
45 |
+ 'profile' => 'profile.png', |
|
46 |
+ ), |
|
47 |
+ array( |
|
48 |
+ 'ticketactions' => 'assign.png', |
|
49 |
+ 'relationships' => 'relationships.png', |
|
50 |
+ 'moderation' => 'modification.png', |
|
51 |
+ ), |
|
52 |
+ ); |
|
53 |
+ |
|
54 |
+ // Each item = array(bool has-own/any, permission category, image file in Themes/default/images/simpledesk/) |
|
55 |
+ $context['shd_permissions']['permission_list'] = array( |
|
56 |
+ 'access_helpdesk' => array(false, 'general', ''), // These three won't have |
|
57 |
+ 'shd_staff' => array(false, 'general', ''), // anything to display |
|
58 |
+ 'admin_helpdesk' => array(false, 'general', ''), // because they'll be managed from parent roles instead |
|
59 |
+ 'shd_view_ticket' => array(true, 'general', 'ticket.png'), |
|
60 |
+ 'shd_view_ticket_private' => array(true, 'general', 'ticket_private.png'), |
|
61 |
+ 'shd_view_ip' => array(true, 'general', 'ip.png'), |
|
62 |
+ |
|
63 |
+ 'shd_new_ticket' => array(false, 'posting', 'log_newticket.png'), |
|
64 |
+ 'shd_edit_ticket' => array(true, 'posting', 'log_editticket.png'), |
|
65 |
+ 'shd_reply_ticket' => array(true, 'posting', 'log_newreply.png'), |
|
66 |
+ 'shd_edit_reply' => array(true, 'posting', 'log_editreply.png'), |
|
67 |
+ 'shd_post_attachment' => array(false, 'posting', 'attachments.png'), |
|
68 |
+ 'shd_post_proxy' => array(false, 'posting', 'proxy.png'), |
|
69 |
+ |
|
70 |
+ 'shd_resolve_ticket' => array(true, 'ticketactions', 'log_resolve.png'), |
|
71 |
+ 'shd_view_ticket_logs' => array(true, 'ticketactions', 'log.png'), |
|
72 |
+ 'shd_alter_urgency' => array(true, 'ticketactions', 'urgency.png'), |
|
73 |
+ 'shd_alter_urgency_higher' => array(true, 'ticketactions', 'log_urgency_increase.png'), |
|
74 |
+ 'shd_alter_privacy' => array(true, 'ticketactions', 'log_markprivate.png'), |
|
75 |
+ 'shd_assign_ticket' => array(true, 'ticketactions', 'log_assign.png'), |
|
76 |
+ |
|
77 |
+ 'shd_view_profile' => array(true, 'profile', 'profile.png'), |
|
78 |
+ 'shd_view_profile_log' => array(true, 'profile', 'log.png'), |
|
79 |
+ 'shd_view_preferences' => array(true, 'profile', 'preferences.png'), |
|
80 |
+ |
|
81 |
+ 'shd_view_relationships' => array(false, 'relationships', 'log_rel_linked.png'), |
|
82 |
+ 'shd_create_relationships' => array(false, 'relationships', 'new_relationship.png'), |
|
83 |
+ 'shd_delete_relationships' => array(false, 'relationships', 'log_rel_delete.png'), |
|
84 |
+ |
|
85 |
+ 'shd_access_recyclebin' => array(false, 'deletion', 'access_recyclebin.png'), |
|
86 |
+ 'shd_delete_ticket' => array(true, 'deletion', 'log_delete.png'), |
|
87 |
+ 'shd_delete_reply' => array(true, 'deletion', 'log_delete_reply.png'), |
|
88 |
+ 'shd_restore_ticket' => array(true, 'deletion', 'log_restore.png'), |
|
89 |
+ 'shd_restore_reply' => array(true, 'deletion', 'log_restore_reply.png'), |
|
90 |
+ 'shd_delete_recycling' => array(false, 'deletion', 'log_permadelete.png'), |
|
91 |
+ |
|
92 |
+ 'shd_ticket_to_topic' => array(false, 'moderation', 'log_tickettotopic.png'), |
|
93 |
+ 'shd_topic_to_ticket' => array(false, 'moderation', 'log_topictoticket.png'), |
|
94 |
+ 'shd_merge_ticket' => array(true, 'moderation', 'log_merge.png'), |
|
95 |
+ 'shd_split_ticket' => array(true, 'moderation', 'log_split_origin.png'), |
|
96 |
+ ); |
|
97 |
+ |
|
98 |
+ if (!empty($modSettings['shd_disable_tickettotopic'])) |
|
99 |
+ unset($context['shd_permissions']['permission_list']['shd_ticket_to_topic'], $context['shd_permissions']['permission_list']['shd_topic_to_ticket']); |
|
100 |
+ |
|
101 |
+ // And go get the list of templates |
|
102 |
+ shd_load_role_templates(); |
|
103 |
+ |
|
104 |
+ // Now engage any hooks. |
|
105 |
+ if (!empty($modSettings['shd_hook_perms'])) |
|
106 |
+ { |
|
107 |
+ $functions = explode(',', $modSettings['shd_hook_perms']); |
|
108 |
+ foreach ($functions as $function) |
|
109 |
+ { |
|
110 |
+ if (is_callable($function)) |
|
111 |
+ $function(); // this one doesn't pass anything, everything's in $context |
|
112 |
+ } |
|
113 |
+ } |
|
114 |
+} |
|
115 |
+ |
|
116 |
+/** |
|
117 |
+ * Provides a list of the known role/permission templates for the system. |
|
118 |
+ * |
|
119 |
+ * @since 1.1 |
|
120 |
+*/ |
|
121 |
+function shd_load_role_templates() |
|
122 |
+{ |
|
123 |
+ global $context, $modSettings; |
|
124 |
+ |
|
125 |
+ // UNDER PAIN OF DEATH |
|
126 |
+ // Do not add anything other than ROLEPERM_ALLOW rules here. |
|
127 |
+ $context['shd_permissions']['roles'] = array( |
|
128 |
+ ROLE_USER => array( |
|
129 |
+ 'description' => 'shd_permrole_user', |
|
130 |
+ 'icon' => 'user.png', |
|
131 |
+ 'permissions' => array( |
|
132 |
+ 'access_helpdesk' => ROLEPERM_ALLOW, |
|
133 |
+ 'shd_view_ticket_own' => ROLEPERM_ALLOW, |
|
134 |
+ 'shd_view_ticket_private_own' => ROLEPERM_ALLOW, |
|
135 |
+ 'shd_new_ticket' => ROLEPERM_ALLOW, |
|
136 |
+ 'shd_edit_ticket_own' => ROLEPERM_ALLOW, |
|
137 |
+ 'shd_reply_ticket_own' => ROLEPERM_ALLOW, |
|
138 |
+ 'shd_edit_reply_own' => ROLEPERM_ALLOW, |
|
139 |
+ 'shd_post_attachment' => ROLEPERM_ALLOW, |
|
140 |
+ 'shd_resolve_ticket_own' => ROLEPERM_ALLOW, |
|
141 |
+ 'shd_view_ticket_logs_own' => ROLEPERM_ALLOW, |
|
142 |
+ 'shd_view_profile_own' => ROLEPERM_ALLOW, |
|
143 |
+ 'shd_view_profile_log_own' => ROLEPERM_ALLOW, |
|
144 |
+ 'shd_view_preferences_own' => ROLEPERM_ALLOW, |
|
145 |
+ 'shd_view_relationships' => ROLEPERM_ALLOW, |
|
146 |
+ 'shd_delete_ticket_own' => ROLEPERM_ALLOW, |
|
147 |
+ 'shd_delete_reply_own' => ROLEPERM_ALLOW, |
|
148 |
+ ), |
|
149 |
+ ), |
|
150 |
+ ROLE_STAFF => array( |
|
151 |
+ 'description' => 'shd_permrole_staff', |
|
152 |
+ 'icon' => 'staff.png', |
|
153 |
+ 'permissions' => array( |
|
154 |
+ 'access_helpdesk' => ROLEPERM_ALLOW, |
|
155 |
+ 'shd_staff' => ROLEPERM_ALLOW, |
|
156 |
+ 'shd_view_ticket_any' => ROLEPERM_ALLOW, |
|
157 |
+ 'shd_view_ticket_private_any' => ROLEPERM_ALLOW, |
|
158 |
+ 'shd_view_ip_own' => ROLEPERM_ALLOW, |
|
159 |
+ 'shd_new_ticket' => ROLEPERM_ALLOW, |
|
160 |
+ 'shd_edit_ticket_any' => ROLEPERM_ALLOW, |
|
161 |
+ 'shd_reply_ticket_any' => ROLEPERM_ALLOW, |
|
162 |
+ 'shd_edit_reply_any' => ROLEPERM_ALLOW, |
|
163 |
+ 'shd_post_attachment' => ROLEPERM_ALLOW, |
|
164 |
+ 'shd_post_proxy' => ROLEPERM_ALLOW, |
|
165 |
+ 'shd_resolve_ticket_any' => ROLEPERM_ALLOW, |
|
166 |
+ 'shd_view_ticket_logs_any' => ROLEPERM_ALLOW, |
|
167 |
+ 'shd_alter_urgency_any' => ROLEPERM_ALLOW, |
|
168 |
+ 'shd_alter_privacy_any' => ROLEPERM_ALLOW, |
|
169 |
+ 'shd_assign_ticket_own' => ROLEPERM_ALLOW, |
|
170 |
+ 'shd_view_profile_any' => ROLEPERM_ALLOW, |
|
171 |
+ 'shd_view_profile_log_any' => ROLEPERM_ALLOW, |
|
172 |
+ 'shd_view_preferences_own' => ROLEPERM_ALLOW, |
|
173 |
+ 'shd_view_relationships' => ROLEPERM_ALLOW, |
|
174 |
+ 'shd_create_relationships' => ROLEPERM_ALLOW, |
|
175 |
+ 'shd_delete_relationships' => ROLEPERM_ALLOW, |
|
176 |
+ 'shd_access_recyclebin' => ROLEPERM_ALLOW, |
|
177 |
+ 'shd_delete_ticket_any' => ROLEPERM_ALLOW, |
|
178 |
+ 'shd_delete_reply_any' => ROLEPERM_ALLOW, |
|
179 |
+ 'shd_restore_ticket_any' => ROLEPERM_ALLOW, |
|
180 |
+ 'shd_restore_reply_any' => ROLEPERM_ALLOW, |
|
181 |
+ 'shd_ticket_to_topic' => ROLEPERM_ALLOW, |
|
182 |
+ 'shd_topic_to_ticket' => ROLEPERM_ALLOW, |
|
183 |
+ 'shd_merge_ticket_any' => ROLEPERM_ALLOW, |
|
184 |
+ 'shd_split_ticket_any' => ROLEPERM_ALLOW, |
|
185 |
+ ), |
|
186 |
+ ), |
|
187 |
+ ROLE_ADMIN => array( |
|
188 |
+ 'description' => 'shd_permrole_admin', |
|
189 |
+ 'icon' => 'admin.png', |
|
190 |
+ 'permissions' => array( |
|
191 |
+ 'access_helpdesk' => ROLEPERM_ALLOW, |
|
192 |
+ 'shd_staff' => ROLEPERM_ALLOW, |
|
193 |
+ 'admin_helpdesk' => ROLEPERM_ALLOW, |
|
194 |
+ 'shd_view_ticket_any' => ROLEPERM_ALLOW, |
|
195 |
+ 'shd_view_ticket_private_any' => ROLEPERM_ALLOW, |
|
196 |
+ 'shd_view_ip_any' => ROLEPERM_ALLOW, |
|
197 |
+ 'shd_new_ticket' => ROLEPERM_ALLOW, |
|
198 |
+ 'shd_edit_ticket_any' => ROLEPERM_ALLOW, |
|
199 |
+ 'shd_reply_ticket_any' => ROLEPERM_ALLOW, |
|
200 |
+ 'shd_edit_reply_any' => ROLEPERM_ALLOW, |
|
201 |
+ 'shd_post_attachment' => ROLEPERM_ALLOW, |
|
202 |
+ 'shd_post_proxy' => ROLEPERM_ALLOW, |
|
203 |
+ 'shd_resolve_ticket_any' => ROLEPERM_ALLOW, |
|
204 |
+ 'shd_view_ticket_logs_any' => ROLEPERM_ALLOW, |
|
205 |
+ 'shd_alter_urgency_any' => ROLEPERM_ALLOW, |
|
206 |
+ 'shd_alter_urgency_higher_any' => ROLEPERM_ALLOW, |
|
207 |
+ 'shd_alter_privacy_any' => ROLEPERM_ALLOW, |
|
208 |
+ 'shd_assign_ticket_any' => ROLEPERM_ALLOW, |
|
209 |
+ 'shd_view_profile_any' => ROLEPERM_ALLOW, |
|
210 |
+ 'shd_view_profile_log_any' => ROLEPERM_ALLOW, |
|
211 |
+ 'shd_view_preferences_any' => ROLEPERM_ALLOW, |
|
212 |
+ 'shd_view_relationships' => ROLEPERM_ALLOW, |
|
213 |
+ 'shd_create_relationships' => ROLEPERM_ALLOW, |
|
214 |
+ 'shd_delete_relationships' => ROLEPERM_ALLOW, |
|
215 |
+ 'shd_access_recyclebin' => ROLEPERM_ALLOW, |
|
216 |
+ 'shd_delete_ticket_any' => ROLEPERM_ALLOW, |
|
217 |
+ 'shd_delete_reply_any' => ROLEPERM_ALLOW, |
|
218 |
+ 'shd_restore_ticket_any' => ROLEPERM_ALLOW, |
|
219 |
+ 'shd_restore_reply_any' => ROLEPERM_ALLOW, |
|
220 |
+ 'shd_ticket_to_topic' => ROLEPERM_ALLOW, |
|
221 |
+ 'shd_topic_to_ticket' => ROLEPERM_ALLOW, |
|
222 |
+ 'shd_merge_ticket_any' => ROLEPERM_ALLOW, |
|
223 |
+ 'shd_split_ticket_any' => ROLEPERM_ALLOW, |
|
224 |
+ ), |
|
225 |
+ ), |
|
226 |
+ ); |
|
227 |
+ |
|
228 |
+ if (!empty($modSettings['shd_hook_permstemplate'])) |
|
229 |
+ { |
|
230 |
+ $functions = explode(',', $modSettings['shd_hook_permstemplate']); |
|
231 |
+ foreach ($functions as $function) |
|
232 |
+ { |
|
233 |
+ if (is_callable($function)) |
|
234 |
+ $function(); // this one doesn't pass anything, everything's in $context |
|
235 |
+ } |
|
236 |
+ } |
|
237 |
+} |
|
238 |
+ |
|
239 |
+/** |
|
240 |
+ * Defines user permissions, most importantly concerning ticket visibility |
|
241 |
+ * |
|
242 |
+ * Populates specific parameters in $user_info, mostly to add {} abstract variables in $smcFunc['db_query'] data calls. |
|
243 |
+ * The foremost one of these is {query_see_ticket}, an SQL clause constructed to ensure ticket visibility is maintained given the |
|
244 |
+ * active user's permission set. |
|
245 |
+ * |
|
246 |
+ * Prior to 1.1 this was in Subs-SimpleDesk.php |
|
247 |
+ * |
|
248 |
+ * @see shd_db_query() |
|
249 |
+ * @since 1.0 |
|
250 |
+*/ |
|
251 |
+function shd_load_user_perms() |
|
252 |
+{ |
|
253 |
+ global $user_info, $context, $smcFunc; |
|
254 |
+ |
|
255 |
+ // OK, have we been here before? If we have, we're done. |
|
256 |
+ if (!empty($user_info['query_see_ticket'])) |
|
257 |
+ return; |
|
258 |
+ |
|
259 |
+ // Right, we're loading the current user. |
|
260 |
+ shd_load_role_templates(); |
|
261 |
+ |
|
262 |
+ // If they're a guest, bail; if they're not a forum admin (who can do anything), figure out what permissions they have |
|
263 |
+ if (!empty($user_info['is_guest'])) |
|
264 |
+ { |
|
265 |
+ $user_info['shd_permissions'] = array(); |
|
266 |
+ $user_info['query_see_ticket'] = '1=0'; |
|
267 |
+ return; |
|
268 |
+ } |
|
269 |
+ elseif (empty($user_info['is_admin'])) |
|
270 |
+ { |
|
271 |
+ $permissions_cache = 'shd_permissions_' . implode('-', $user_info['groups']); |
|
272 |
+ $perm_cache_time = 300; |
|
273 |
+ $temp = cache_get_data($permissions_cache, $perm_cache_time); |
|
274 |
+ |
|
275 |
+ if ($temp === null || (time() - $perm_cache_time > $modSettings['settings_updated'])) |
|
276 |
+ { |
|
277 |
+ $role_permissions = array(); |
|
278 |
+ |
|
279 |
+ // 1. Get all the roles that conceivably apply to this user. |
|
280 |
+ $query = $smcFunc['db_query']('', ' |
|
281 |
+ SELECT hdrg.id_role, hdr.template |
|
282 |
+ FROM {db_prefix}helpdesk_role_groups AS hdrg |
|
283 |
+ INNER JOIN {db_prefix}helpdesk_roles AS hdr ON (hdrg.id_role = hdr.id_role) |
|
284 |
+ WHERE hdrg.id_group IN ({array_int:groups})', |
|
285 |
+ array( |
|
286 |
+ 'groups' => $user_info['groups'], |
|
287 |
+ ) |
|
288 |
+ ); |
|
289 |
+ |
|
290 |
+ $roles = array(); |
|
291 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
292 |
+ { |
|
293 |
+ $role_permissions[$row['id_role']] = $context['shd_permissions']['roles'][$row['template']]['permissions']; |
|
294 |
+ $roles[$row['id_role']] = true; |
|
295 |
+ } |
|
296 |
+ |
|
297 |
+ $smcFunc['db_free_result']($query); |
|
298 |
+ |
|
299 |
+ $denied = array(); |
|
300 |
+ |
|
301 |
+ // 2.1. Apply role specific rules against their parent templates |
|
302 |
+ if (!empty($roles)) |
|
303 |
+ { |
|
304 |
+ $query = $smcFunc['db_query']('', ' |
|
305 |
+ SELECT id_role, permission, add_type |
|
306 |
+ FROM {db_prefix}helpdesk_role_permissions |
|
307 |
+ WHERE id_role IN ({array_int:roles})', |
|
308 |
+ array( |
|
309 |
+ 'roles' => array_keys($roles), |
|
310 |
+ ) |
|
311 |
+ ); |
|
312 |
+ |
|
313 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
314 |
+ { |
|
315 |
+ if ($row['add_type'] == ROLEPERM_DENY) |
|
316 |
+ $denied[$row['permission']] = true; |
|
317 |
+ else |
|
318 |
+ $role_permissions[$row['id_role']][$row['permission']] = $row['add_type']; |
|
319 |
+ } |
|
320 |
+ $smcFunc['db_free_result']($query); |
|
321 |
+ } |
|
322 |
+ |
|
323 |
+ // 2.2 Having loaded all the roles, and applied role specific changes, fuse them all together |
|
324 |
+ $user_info['shd_permissions'] = array(); |
|
325 |
+ foreach ($role_permissions as $role => $perm_list) |
|
326 |
+ { |
|
327 |
+ foreach ($perm_list as $perm => $value) |
|
328 |
+ { |
|
329 |
+ if ($value == ROLEPERM_ALLOW) |
|
330 |
+ $user_info['shd_permissions'][$perm] = ROLEPERM_ALLOW; |
|
331 |
+ } |
|
332 |
+ } |
|
333 |
+ |
|
334 |
+ // 2.3 Apply any deny restrictions |
|
335 |
+ if (!empty($denied)) |
|
336 |
+ { |
|
337 |
+ foreach ($denied as $perm => $value) |
|
338 |
+ { |
|
339 |
+ if (isset($user_info['shd_permissions'][$perm])) |
|
340 |
+ unset($user_info['shd_permissions'][$perm]); |
|
341 |
+ } |
|
342 |
+ } |
|
343 |
+ } |
|
344 |
+ else |
|
345 |
+ $user_info['shd_permissions'] = $temp; |
|
346 |
+ |
|
347 |
+ cache_get_data($permissions_cache, $user_info['shd_permissions'], $perm_cache_time); |
|
348 |
+ } |
|
349 |
+ |
|
350 |
+ if ($user_info['is_admin']) |
|
351 |
+ $user_info['query_see_ticket'] = '1=1'; |
|
352 |
+ elseif (!shd_allowed_to('access_helpdesk')) |
|
353 |
+ $user_info['query_see_ticket'] = '1=0'; // no point going any further if they can't access the helpdesk |
|
354 |
+ elseif (shd_allowed_to('shd_view_ticket_any')) |
|
355 |
+ $user_info['query_see_ticket'] = shd_allowed_to('shd_view_ticket_private_any') ? '1=1' : ('(hdt.private = 0' . (shd_allowed_to('shd_view_ticket_private_own') ? ' OR (hdt.private = 1 AND hdt.id_member_started = {int:user_info_id}))' : ')')); |
|
356 |
+ elseif (shd_allowed_to('shd_view_ticket_own')) |
|
357 |
+ $user_info['query_see_ticket'] = 'hdt.id_member_started = {int:user_info_id}' . (shd_allowed_to('shd_view_ticket_private_own') ? '' : ' AND hdt.private = 0'); |
|
358 |
+ else |
|
359 |
+ $user_info['query_see_ticket'] = '1=0'; |
|
360 |
+ |
|
361 |
+ if (!shd_allowed_to('shd_access_recyclebin')) |
|
362 |
+ $user_info['query_see_ticket'] .= ' AND hdt.status != 6'; |
|
363 |
+} |
|
364 |
+ |
|
365 |
+/** |
|
366 |
+ * Determines if a user has a given permission within the system. |
|
367 |
+ * |
|
368 |
+ * All SimpleDesk-specific permissions should be checked with this function. Any other permission check that is not specifically |
|
369 |
+ * SimpleDesk-related should use allowedTo instead. |
|
370 |
+ * |
|
371 |
+ * Prior to 1.0, this function was in Subs-SimpleDesk.php |
|
372 |
+ * |
|
373 |
+ * @param mixed $permission A string or array of strings naming a permission or permissions that wish to be examined |
|
374 |
+ * @return bool True if any of the permission(s) outlined in $permission are true. |
|
375 |
+ * @see shd_is_allowed_to() |
|
376 |
+ * @since 1.0 |
|
377 |
+*/ |
|
378 |
+function shd_allowed_to($permission) |
|
379 |
+{ |
|
380 |
+ global $user_info; |
|
381 |
+ |
|
382 |
+ // Can always do nothing |
|
383 |
+ if (empty($permission)) |
|
384 |
+ return true; |
|
385 |
+ |
|
386 |
+ // WTH, permissions not loaded yet? |
|
387 |
+ if (empty($user_info)) |
|
388 |
+ return false; |
|
389 |
+ |
|
390 |
+ // Oh my, it's the admin, run cuz he can do anything! |
|
391 |
+ if ($user_info['is_admin']) |
|
392 |
+ return true; |
|
393 |
+ |
|
394 |
+ if (empty($user_info['shd_permissions'])) |
|
395 |
+ return false; |
|
396 |
+ |
|
397 |
+ if (!is_array($permission) && !empty($user_info['shd_permissions'][$permission])) |
|
398 |
+ return true; |
|
399 |
+ elseif (is_array($permission) && count(array_intersect(array_keys($user_info['shd_permissions']), $permission)) != 0) |
|
400 |
+ return true; |
|
401 |
+ else |
|
402 |
+ return false; |
|
403 |
+} |
|
404 |
+ |
|
405 |
+/** |
|
406 |
+ * Enforces a user having a given permission and returning to a fatal error message if not. |
|
407 |
+ * |
|
408 |
+ * All fatal-level SimpleDesk-specific permissions should be checked with this function. Any other permission check that is |
|
409 |
+ * not specifically SimpleDesk-related should use isAllowedTo instead. Note that this is a void function because should this |
|
410 |
+ * fail, SMF execution will be halted. |
|
411 |
+ * |
|
412 |
+ * Prior to 1.0, this function was in Subs-SimpleDesk.php |
|
413 |
+ * |
|
414 |
+ * @param mixed $permission A string or array of strings naming a permission or permissions that wish to be examined |
|
415 |
+ * @see shd_allowed_to() |
|
416 |
+ * @since 1.0 |
|
417 |
+*/ |
|
418 |
+function shd_is_allowed_to($permission) |
|
419 |
+{ |
|
420 |
+ global $user_info, $txt; |
|
421 |
+ |
|
422 |
+ $permission = is_array($permission) ? $permission : (array) $permission; |
|
423 |
+ |
|
424 |
+ if (!shd_allowed_to($permission)) |
|
425 |
+ { |
|
426 |
+ // Pick the last array entry as the permission shown as the error. |
|
427 |
+ $error_permission = array_shift($permission); |
|
428 |
+ |
|
429 |
+ // If they are a guest, show a login. (because the error might be gone if they do!) |
|
430 |
+ if ($user_info['is_guest']) |
|
431 |
+ { |
|
432 |
+ loadLanguage('Errors'); |
|
433 |
+ is_not_guest($txt['cannot_' . $error_permission]); |
|
434 |
+ } |
|
435 |
+ |
|
436 |
+ // Clear the action because they aren't really doing that! |
|
437 |
+ $_GET['action'] = ''; |
|
438 |
+ $_GET['board'] = ''; |
|
439 |
+ $_GET['topic'] = ''; |
|
440 |
+ writeLog(true); |
|
441 |
+ |
|
442 |
+ fatal_lang_error('cannot_' . $error_permission, false); |
|
443 |
+ |
|
444 |
+ // Getting this far is a really big problem, but let's try our best to prevent any cases... |
|
445 |
+ trigger_error('Hacking attempt...', E_USER_ERROR); |
|
446 |
+ } |
|
447 |
+} |
|
448 |
+ |
|
449 |
+/** |
|
450 |
+ * Identifies all members who hold a given permission. |
|
451 |
+ * |
|
452 |
+ * Currently lists of staff are generated by users who hold shd_staff permission. This function identifies those users through |
|
453 |
+ * an internal lookup provided by SMF. |
|
454 |
+ * |
|
455 |
+ * Prior to 1.0, this function was in Subs-SimpleDesk.php |
|
456 |
+ * |
|
457 |
+ * @param mixed $permission A string naming a permission that members should hold. |
|
458 |
+ * @return array Array of zero or more user ids who hold the stated permission. |
|
459 |
+ * @since 1.0 |
|
460 |
+*/ |
|
461 |
+function shd_members_allowed_to($permission) |
|
462 |
+{ |
|
463 |
+ global $smcFunc; |
|
464 |
+ |
|
465 |
+ $member_groups = shd_groups_allowed_to($permission); |
|
466 |
+ |
|
467 |
+ $request = $smcFunc['db_query']('', ' |
|
468 |
+ SELECT mem.id_member |
|
469 |
+ FROM {db_prefix}members AS mem |
|
470 |
+ WHERE (mem.id_group IN ({array_int:member_groups_allowed}) OR FIND_IN_SET({raw:member_group_allowed_implode}, mem.additional_groups) != 0)' . (empty($member_groups['denied']) ? '' : ' |
|
471 |
+ AND NOT (mem.id_group IN ({array_int:member_groups_denied}) OR FIND_IN_SET({raw:member_group_denied_implode}, mem.additional_groups) != 0)'), |
|
472 |
+ array( |
|
473 |
+ 'member_groups_allowed' => $member_groups['allowed'], |
|
474 |
+ 'member_groups_denied' => $member_groups['denied'], |
|
475 |
+ 'member_group_allowed_implode' => implode(', mem.additional_groups) != 0 OR FIND_IN_SET(', $member_groups['allowed']), |
|
476 |
+ 'member_group_denied_implode' => implode(', mem.additional_groups) != 0 OR FIND_IN_SET(', $member_groups['denied']), |
|
477 |
+ ) |
|
478 |
+ ); |
|
479 |
+ $members = array(); |
|
480 |
+ while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
481 |
+ $members[] = $row['id_member']; |
|
482 |
+ $smcFunc['db_free_result']($request); |
|
483 |
+ |
|
484 |
+ return $members; |
|
485 |
+} |
|
486 |
+ |
|
487 |
+/** |
|
488 |
+ * Identifies which SMF membergroups hold a given permission. |
|
489 |
+ * |
|
490 |
+ * @param string $permission A string naming a permission that members should hold. |
|
491 |
+ * @return array Array of arrays containing 'allowed' and 'denied', each of which can contain ids for zero or more membergroups that hold the relevant permission. |
|
492 |
+ * @since 1.1 |
|
493 |
+*/ |
|
494 |
+function shd_groups_allowed_to($permission) |
|
495 |
+{ |
|
496 |
+ global $smcFunc, $context; |
|
497 |
+ |
|
498 |
+ // Admins are allowed to do anything. |
|
499 |
+ $member_groups = array( |
|
500 |
+ 'allowed' => array(1), |
|
501 |
+ 'denied' => array(), |
|
502 |
+ ); |
|
503 |
+ |
|
504 |
+ // 1. Figure out what templates contain this permission, if any |
|
505 |
+ $templates = array(); |
|
506 |
+ $roles = array(); |
|
507 |
+ foreach ($context['shd_permissions']['roles'] as $role => $role_details) |
|
508 |
+ { |
|
509 |
+ if (!empty($role_details['permissions'][$permission])) |
|
510 |
+ $templates[] = $role; // We don't have any ROLEPERM_DISALLOW or ROLEPERM_DENY in the templates, so simply checking presence is enough. |
|
511 |
+ } |
|
512 |
+ |
|
513 |
+ // 1a. Load any roles using these templates, gives us a foundation to work with. |
|
514 |
+ if (!empty($templates)) |
|
515 |
+ { |
|
516 |
+ $query = $smcFunc['db_query']('', ' |
|
517 |
+ SELECT id_role |
|
518 |
+ FROM {db_prefix}helpdesk_roles |
|
519 |
+ WHERE template IN ({array_int:templates})', |
|
520 |
+ array( |
|
521 |
+ 'templates' => $templates, |
|
522 |
+ ) |
|
523 |
+ ); |
|
524 |
+ |
|
525 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
526 |
+ $roles[$row['id_role']] = ROLEPERM_ALLOW; // See above. We know we have the permission present if we find it here. |
|
527 |
+ |
|
528 |
+ $smcFunc['db_free_result']($query); |
|
529 |
+ } |
|
530 |
+ |
|
531 |
+ // 2. Figure out what roles add, remove or deny this permission, since they'll always override anything in the template |
|
532 |
+ $query = $smcFunc['db_query']('', ' |
|
533 |
+ SELECT id_role, add_type |
|
534 |
+ FROM {db_prefix}helpdesk_role_permissions |
|
535 |
+ WHERE permission = {string:permission}', |
|
536 |
+ array( |
|
537 |
+ 'permission' => $permission, |
|
538 |
+ ) |
|
539 |
+ ); |
|
540 |
+ |
|
541 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
542 |
+ $roles[$row['id_role']] = $row['add_type']; |
|
543 |
+ |
|
544 |
+ $smcFunc['db_free_result']($query); |
|
545 |
+ |
|
546 |
+ // 3. Tie roles to groups |
|
547 |
+ if (!empty($roles)) |
|
548 |
+ { |
|
549 |
+ $query = $smcFunc['db_query']('', ' |
|
550 |
+ SELECT id_role, id_group |
|
551 |
+ FROM {db_prefix}helpdesk_role_groups |
|
552 |
+ WHERE id_role IN ({array_int:roles})', |
|
553 |
+ array( |
|
554 |
+ 'roles' => array_keys($roles), |
|
555 |
+ ) |
|
556 |
+ ); |
|
557 |
+ |
|
558 |
+ while ($row = $smcFunc['db_fetch_assoc']($query)) |
|
559 |
+ { |
|
560 |
+ if ($roles[$row['id_role']] == ROLEPERM_ALLOW) |
|
561 |
+ $member_groups['allowed'][] = $row['id_group']; |
|
562 |
+ elseif ($roles[$row['id_role']] == ROLEPERM_DENY) |
|
563 |
+ $member_groups['denied'][] = $row['id_group']; |
|
564 |
+ // We don't have to do anything for ROLEPERM_DISALLOW |
|
565 |
+ } |
|
566 |
+ } |
|
567 |
+ |
|
568 |
+ // 4. All done, just clear up groups and send 'em home |
|
569 |
+ $member_groups['allowed'] = array_diff($member_groups['allowed'], array_diff($member_groups['denied'], array(1))); |
|
570 |
+ |
|
571 |
+ return $member_groups; |
|
572 |
+} |
|
573 |
+?> |
|
0 | 574 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,559 @@ |
1 |
+<?php |
|
2 |
+############################################################### |
|
3 |
+# Simple Desk Project - www.simpledesk.net # |
|
4 |
+############################################################### |
|
5 |
+# An advanced help desk modifcation built on SMF # |
|
6 |
+############################################################### |
|
7 |
+# # |
|
8 |
+# * Copyright 2010 - SimpleDesk.net # |
|
9 |
+# # |
|
10 |
+# This file and its contents are subject to the license # |
|
11 |
+# included with this distribution, license.txt, which # |
|
12 |
+# states that this software is New BSD Licensed. # |
|
13 |
+# Any questions, please contact SimpleDesk.net # |
|
14 |
+# # |
|
15 |
+############################################################### |
|
16 |
+# SimpleDesk Version: 1.0 Felidae # |
|
17 |
+# File Info: Subs-SimpleDeskPost.php / 1.0 Felidae # |
|
18 |
+############################################################### |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * This file handles probably the two most critical functions in SimpleDesk: the one that adds new posts to the database |
|
22 |
+ * and one that saves updated posts; also contains miscellaneous code that applies generally in posting. |
|
23 |
+ * |
|
24 |
+ * @package subs |
|
25 |
+ * @since 1.0 |
|
26 |
+ */ |
|
27 |
+ |
|
28 |
+if (!defined('SMF')) |
|
29 |
+ die('Hacking attempt...'); |
|
30 |
+ |
|
31 |
+ |
|
32 |
+/** |
|
33 |
+ * Creates a new ticket or reply in the database. |
|
34 |
+ * |
|
35 |
+ * This function handles all of the creation of posts and tickets within SimpleDesk, even with respect to managing tickets spawned |
|
36 |
+ * from forum topics being moved, as well as newly deleted tickets (formed as a split when replies are deleted). New tickets' contents |
|
37 |
+ * as well as replies to tickets generally hold the same format. |
|
38 |
+ * |
|
39 |
+ * All three parameters are by <b>reference</b> meaning they WILL be updated if things change. Note that this function |
|
40 |
+ * is not validating that they are sensible values; it is up to the calling function to ascertain that. |
|
41 |
+ * |
|
42 |
+ * @param array &$msgOptions A hash array by reference, containing details of the post you wish to add. |
|
43 |
+ * <ul> |
|
44 |
+ * <li>id: Not required on input (and is ignored) - and will be overwritten with the new message id when the function completes.</li> |
|
45 |
+ * <li>body: Required string, the principle body content of the message to post. Assumed to have been cleaned already (with $smcFunc['htmlspecialchars'] and preparsecode)</li> |
|
46 |
+ * <li>smileys_enabled: Optional, boolean denoting whether smileys should be active on this post; defaults to false</li> |
|
47 |
+ * <li>time: Optional, timestamp of the post. If omitted, time() will be used instead (for "now" based on server clock)</li> |
|
48 |
+ * <li>modified: Optional, hash array containing items relating to modification (if 'modified' key exists, all of these should be set) |
|
49 |
+ * <ul> |
|
50 |
+ * <li> time: Unsigned int timestamp of the change</li> |
|
51 |
+ * <li> name: String; user name of the user making the change; if omitted, modified will be ignored</li> |
|
52 |
+ * <li> id: Unsigned int user id of the user making the change; if not provided, id MUST be. If id isn't, or it doesn't exist, modified will be ignored entirely</li> |
|
53 |
+ * </ul> |
|
54 |
+ * </li> |
|
55 |
+ * <li> attachments: Optional, array of attachment ids that need attaching to this message; if omitted no changes will occur |
|
56 |
+ * </ul> |
|
57 |
+ * |
|
58 |
+ * @param array &$ticketOptions A hash array by reference, containing details of the ticket as a whole. |
|
59 |
+ * <ul> |
|
60 |
+ * <li>id: Required if replying to a ticket, 0 if a new ticket (will default to 0 if not specified)</li> |
|
61 |
+ * <li>mark_as_read: Optional boolean, whether to mark the ticket as read by the person posting it ($posterOptions['id'] is required to use this)</li> |
|
62 |
+ * <li>mark_as_read_proxy: Optional integer for proxy tickets, if $ticketOptions['mark_as_read'] is true. Mark the ticket as read for the user with this id.</li> |
|
63 |
+ * <li>subject: Semi-optional string with the new subject in; required for a new ticket, ignored if adding a reply. If set, assumed to have been cleaned already (with $smcFunc['htmlspecialchars'] and strtr)</li> |
|
64 |
+ * <li>private: Semi-optional boolean with ticket privacy (true = private); required for a new ticket, ignored if adding a reply.</li> |
|
65 |
+ * <li>status: Integer to denote new status of the ticket, defaults to TICKET_STATUS_NEW. Calling function to determine new status.</li> |
|
66 |
+ * <li>urgency: Semi-optional integer with the ticket urgency; required for a new ticket, ignored if adding a reply. If not stated on a new ticket, TICKET_URGENCY_LOW will be used.</li> |
|
67 |
+ * <li>assigned: Optional integer of user id, used to create a ticket with assignment, ignored if not a new ticket.</li> |
|
68 |
+ * </ul> |
|
69 |
+ * |
|
70 |
+ * @param array &$posterOptions A hash array by reference, containing details of the person the reply is written by. |
|
71 |
+ * <ul> |
|
72 |
+ * <li>id: User id to credit the post to. Uses 0 if not specified.</li> |
|
73 |
+ * <li>ip: IP address the post came from. Uses the current user's IP address if not specified.</li> |
|
74 |
+ * <li>name: Name to credit against the post. If not specified, and a user id was supplied, look that up in the member table, otherwise just use 'Guest'.</li> |
|
75 |
+ * <li>email: Email address to list against the post. If not specified, and a user id was supplied, look that up in the member table, otherwise just use ''.</li> |
|
76 |
+ * </ul> |
|
77 |
+ * @return bool True on success, false on failure. |
|
78 |
+ * @since 1.0 |
|
79 |
+ */ |
|
80 |
+function shd_create_ticket_post(&$msgOptions, &$ticketOptions, &$posterOptions) |
|
81 |
+{ |
|
82 |
+ global $user_info, $txt, $modSettings, $smcFunc, $context, $user_profile; |
|
83 |
+ |
|
84 |
+ // Clean them incoming vars up good 'n' proper |
|
85 |
+ $msgOptions['smileys_enabled'] = !empty($msgOptions['smileys_enabled']); |
|
86 |
+ $msgOptions['attachments'] = empty($msgOptions['attachments']) ? array() : $msgOptions['attachments']; |
|
87 |
+ $msgOptions['time'] = empty($msgOptions['time']) ? time() : (int) $msgOptions['time']; |
|
88 |
+ $ticketOptions['id'] = empty($ticketOptions['id']) ? 0 : (int) $ticketOptions['id']; |
|
89 |
+ $ticketOptions['private'] = !empty($ticketOptions['private']); |
|
90 |
+ $ticketOptions['urgency'] = empty($ticketOptions['urgency']) ? TICKET_URGENCY_LOW : (int) $ticketOptions['urgency']; |
|
91 |
+ $ticketOptions['assigned'] = empty($ticketOptions['assigned']) ? 0 : (int) $ticketOptions['assigned']; |
|
92 |
+ $ticketOptions['status'] = empty($ticketOptions['status']) ? TICKET_STATUS_NEW : (int) $ticketOptions['status']; |
|
93 |
+ $posterOptions['id'] = empty($posterOptions['id']) ? 0 : (int) $posterOptions['id']; |
|
94 |
+ $posterOptions['ip'] = empty($posterOptions['ip']) ? $user_info['ip'] : $posterOptions['ip']; |
|
95 |
+ |
|
96 |
+ // If nothing was filled in as name/e-mail address, try the member table. |
|
97 |
+ if (!isset($posterOptions['name']) || $posterOptions['name'] == '' || (empty($posterOptions['email']) && !empty($posterOptions['id']))) |
|
98 |
+ { |
|
99 |
+ if (empty($posterOptions['id'])) |
|
100 |
+ { |
|
101 |
+ $posterOptions['id'] = 0; |
|
102 |
+ $posterOptions['name'] = $txt['guest_title']; |
|
103 |
+ $posterOptions['email'] = ''; |
|
104 |
+ } |
|
105 |
+ elseif ($posterOptions['id'] != $user_info['id']) |
|
106 |
+ { |
|
107 |
+ if (empty($user_profile[$posterOptions['id']])) |
|
108 |
+ loadMemberData($posterOptions['id'], false, 'minimal'); |
|
109 |
+ |
|
110 |
+ // Couldn't find the current poster? |
|
111 |
+ if (empty($user_profile[$posterOptions['id']])) |
|
112 |
+ { |
|
113 |
+ trigger_error('shd_create_ticket_post(): Invalid member id ' . $posterOptions['id'], E_USER_NOTICE); |
|
114 |
+ $posterOptions['id'] = 0; |
|
115 |
+ $posterOptions['name'] = $txt['guest_title']; |
|
116 |
+ $posterOptions['email'] = ''; |
|
117 |
+ } |
|
118 |
+ else |
|
119 |
+ { |
|
120 |
+ $posterOptions['name'] = $user_profile[$posterOptions['id']]['real_name']; |
|
121 |
+ $posterOptions['email'] = $user_profile[$posterOptions['id']]['email_address']; |
|
122 |
+ } |
|
123 |
+ } |
|
124 |
+ else |
|
125 |
+ { |
|
126 |
+ $posterOptions['name'] = $user_info['name']; |
|
127 |
+ $posterOptions['email'] = $user_info['email']; |
|
128 |
+ } |
|
129 |
+ } |
|
130 |
+ |
|
131 |
+ // Is there modified name data? (For topic->ticket) |
|
132 |
+ $modified = true; |
|
133 |
+ if (isset($msgOptions['modified'])) |
|
134 |
+ { |
|
135 |
+ $msgOptions['modified']['time'] = empty($msgOptions['modified']['time']) ? 0 : (int) $msgOptions['modified']['time']; |
|
136 |
+ $msgOptions['modified']['id'] = empty($msgOptions['modified']['id']) ? 0 : (int) $msgOptions['modified']['id']; |
|
137 |
+ $msgOptions['modified']['name'] = empty($msgOptions['modified']['name']) ? '' : $msgOptions['modified']['name']; |
|
138 |
+ |
|
139 |
+ $cancel = false; |
|
140 |
+ if (empty($msgOptions['modified']['time']) || (empty($msgOptions['modified']['name']) && empty($msgOptions['modified']['id']))) |
|
141 |
+ $modified = false; |
|
142 |
+ |
|
143 |
+ if ($modified) |
|
144 |
+ { |
|
145 |
+ // So they have a time, and name or id (or even both). Let's see what we need. |
|
146 |
+ if (empty($msgOptions['modified']['name'])) |
|
147 |
+ { |
|
148 |
+ loadMemberData($msgOptions['modified']['id'], false, 'minimal'); |
|
149 |
+ if (empty($user_profile[$msgOptions['modified']['id']])) |
|
150 |
+ $modified = false; // oops, they gave us a user id that doesn't exist -- and we don't have a name |
|
151 |
+ } |
|
152 |
+ // Otherwise, we have a name and no id, which is fine. Can't be doing with trying to figure out usernames. |
|
153 |
+ } |
|
154 |
+ } |
|
155 |
+ else |
|
156 |
+ $modified = false; |
|
157 |
+ |
|
158 |
+ if (!$modified) |
|
159 |
+ $msgOptions['modified'] = array( |
|
160 |
+ 'id' => 0, |
|
161 |
+ 'name' => '', |
|
162 |
+ 'time' => 0, |
|
163 |
+ ); |
|
164 |
+ |
|
165 |
+ // It's do or die time: forget any user aborts! |
|
166 |
+ $previous_ignore_user_abort = ignore_user_abort(true); |
|
167 |
+ |
|
168 |
+ $new_ticket = empty($ticketOptions['id']); |
|
169 |
+ |
|
170 |
+ // OK, so let's add the reply. Even if it's a new ticket and stuff, let's still add the msg first so we have our friendly msg id |
|
171 |
+ $smcFunc['db_insert']('', |
|
172 |
+ '{db_prefix}helpdesk_ticket_replies', |
|
173 |
+ array( |
|
174 |
+ 'id_ticket' => 'int', 'id_member' => 'int', 'body' => 'string-65534', |
|
175 |
+ 'poster_name' => 'string-255', 'poster_email' => 'string-255', 'poster_time' => 'int', 'poster_ip' => 'string-255', |
|
176 |
+ 'smileys_enabled' => 'int', 'modified_member' => 'int', 'modified_name' => 'string', 'modified_time' => 'int', |
|
177 |
+ ), |
|
178 |
+ array( |
|
179 |
+ $ticketOptions['id'], $posterOptions['id'], $msgOptions['body'], |
|
180 |
+ $posterOptions['name'], $posterOptions['email'], $msgOptions['time'], $posterOptions['ip'], |
|
181 |
+ $msgOptions['smileys_enabled'] ? 1 : 0, $msgOptions['modified']['id'], $msgOptions['modified']['name'], $msgOptions['modified']['time'], |
|
182 |
+ ), |
|
183 |
+ array('id_msg') |
|
184 |
+ ); |
|
185 |
+ $msgOptions['id'] = $smcFunc['db_insert_id']('{db_prefix}messages', 'id_msg'); |
|
186 |
+ |
|
187 |
+ // Something went wrong creating the message... |
|
188 |
+ if (empty($msgOptions['id'])) |
|
189 |
+ return false; |
|
190 |
+ |
|
191 |
+ // Insert a new ticket (if the ID was left empty) |
|
192 |
+ if ($new_ticket) |
|
193 |
+ { |
|
194 |
+ $smcFunc['db_insert']('', |
|
195 |
+ '{db_prefix}helpdesk_tickets', |
|
196 |
+ array( |
|
197 |
+ 'id_first_msg' => 'int', 'id_member_started' => 'int', 'id_last_msg' => 'int', 'id_member_updated' => 'int', |
|
198 |
+ 'id_member_assigned' => 'int', 'subject' => 'string-100', 'urgency' => 'int', 'status' => 'int', |
|
199 |
+ 'private' => 'int', |
|
200 |
+ ), |
|
201 |
+ array( |
|
202 |
+ $msgOptions['id'], $posterOptions['id'], $msgOptions['id'], $posterOptions['id'], |
|
203 |
+ $ticketOptions['assigned'], $ticketOptions['subject'], $ticketOptions['urgency'], $ticketOptions['status'], |
|
204 |
+ $ticketOptions['private'] ? 1 : 0, |
|
205 |
+ ), |
|
206 |
+ array('id_ticket') |
|
207 |
+ ); |
|
208 |
+ $ticketOptions['id'] = $smcFunc['db_insert_id']('{db_prefix}helpdesk_tickets', 'id_ticket'); |
|
209 |
+ |
|
210 |
+ // The ticket couldn't be created for some reason. |
|
211 |
+ if (empty($ticketOptions['id'])) |
|
212 |
+ { |
|
213 |
+ // We should delete the post that did work, though... |
|
214 |
+ shd_db_query('', ' |
|
215 |
+ DELETE FROM {db_prefix}helpdesk_ticket_replies |
|
216 |
+ WHERE id_msg = {int:id_msg}', |
|
217 |
+ array( |
|
218 |
+ 'id_msg' => $msgOptions['id'], |
|
219 |
+ ) |
|
220 |
+ ); |
|
221 |
+ |
|
222 |
+ return false; |
|
223 |
+ } |
|
224 |
+ |
|
225 |
+ // Fix the message with the ticket. |
|
226 |
+ shd_db_query('', ' |
|
227 |
+ UPDATE {db_prefix}helpdesk_ticket_replies |
|
228 |
+ SET id_ticket = {int:id_ticket} |
|
229 |
+ WHERE id_msg = {int:id_msg}', |
|
230 |
+ array( |
|
231 |
+ 'id_ticket' => $ticketOptions['id'], |
|
232 |
+ 'id_msg' => $msgOptions['id'], |
|
233 |
+ ) |
|
234 |
+ ); |
|
235 |
+ } |
|
236 |
+ // The ticket already exists, it only needs a little updating. |
|
237 |
+ else |
|
238 |
+ { |
|
239 |
+ shd_db_query('', ' |
|
240 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
241 |
+ SET |
|
242 |
+ id_member_updated = {int:poster_id}, |
|
243 |
+ id_last_msg = {int:id_msg}, |
|
244 |
+ num_replies = num_replies + 1, |
|
245 |
+ status = {int:status} |
|
246 |
+ WHERE id_ticket = {int:id_ticket}', |
|
247 |
+ array( |
|
248 |
+ 'poster_id' => $posterOptions['id'], |
|
249 |
+ 'id_msg' => $msgOptions['id'], |
|
250 |
+ 'status' => $ticketOptions['status'], |
|
251 |
+ 'id_ticket' => $ticketOptions['id'], |
|
252 |
+ ) |
|
253 |
+ ); |
|
254 |
+ } |
|
255 |
+ |
|
256 |
+ // Fix the attachments. |
|
257 |
+ if (!empty($msgOptions['attachments'])) |
|
258 |
+ { |
|
259 |
+ $array = array(); |
|
260 |
+ foreach ($msgOptions['attachments'] as $attach) |
|
261 |
+ $array[] = array($attach, $msgOptions['id'], $ticketOptions['id']); |
|
262 |
+ |
|
263 |
+ $smcFunc['db_insert']('replace', |
|
264 |
+ '{db_prefix}helpdesk_attachments', |
|
265 |
+ array( |
|
266 |
+ 'id_attach' => 'int', 'id_msg' => 'int', 'id_ticket' => 'int', |
|
267 |
+ ), |
|
268 |
+ $array, |
|
269 |
+ array('id_attach') |
|
270 |
+ ); |
|
271 |
+ } |
|
272 |
+ |
|
273 |
+ // Mark inserted ticket as read (only for the user listed as the author -- oftentimes will be the current user though) |
|
274 |
+ if (!empty($ticketOptions['mark_as_read']) && !empty($posterOptions['id'])) |
|
275 |
+ { |
|
276 |
+ // Since it's likely they *read* it before replying, let's try an UPDATE first. |
|
277 |
+ if (!$new_ticket) |
|
278 |
+ { |
|
279 |
+ shd_db_query('', ' |
|
280 |
+ UPDATE {db_prefix}helpdesk_log_read |
|
281 |
+ SET id_msg = {int:id_msg} |
|
282 |
+ WHERE id_member = {int:current_member} |
|
283 |
+ AND id_ticket = {int:id_ticket}', |
|
284 |
+ array( |
|
285 |
+ 'current_member' => $posterOptions['id'], |
|
286 |
+ 'id_msg' => $msgOptions['id'], |
|
287 |
+ 'id_ticket' => $ticketOptions['id'], |
|
288 |
+ ) |
|
289 |
+ ); |
|
290 |
+ |
|
291 |
+ $flag = $smcFunc['db_affected_rows']() != 0; |
|
292 |
+ } |
|
293 |
+ |
|
294 |
+ if (empty($flag)) // such as, say, a new ticket? |
|
295 |
+ { |
|
296 |
+ // Hold on a second... If this is a proxy ticket... We'll want to mark it read for the staff member, not the member for whom it was posted. |
|
297 |
+ if(!empty($ticketOptions['mark_as_read_proxy'])) |
|
298 |
+ $mark_read_user = $ticketOptions['mark_as_read_proxy']; |
|
299 |
+ else |
|
300 |
+ $mark_read_user = $posterOptions['id']; |
|
301 |
+ |
|
302 |
+ $smcFunc['db_insert']('replace', |
|
303 |
+ '{db_prefix}helpdesk_log_read', |
|
304 |
+ array('id_ticket' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), |
|
305 |
+ array($ticketOptions['id'], $mark_read_user, $msgOptions['id']), |
|
306 |
+ array('id_ticket', 'id_member') |
|
307 |
+ ); |
|
308 |
+ } |
|
309 |
+ } |
|
310 |
+ |
|
311 |
+ // Int hooks |
|
312 |
+ $hook = $new_ticket ? 'shd_hook_newticket' : 'shd_hook_newreply'; |
|
313 |
+ if (!empty($modSettings[$hook])) |
|
314 |
+ { |
|
315 |
+ $functions = explode(',', $modSettings[$hook]); |
|
316 |
+ foreach ($functions as $function) |
|
317 |
+ { |
|
318 |
+ if (is_callable($function)) |
|
319 |
+ $function($msgOptions, $ticketOptions, $posterOptions); // this should be picked up by reference in the called function or it won't do anything! |
|
320 |
+ } |
|
321 |
+ } |
|
322 |
+ |
|
323 |
+ ignore_user_abort($previous_ignore_user_abort); |
|
324 |
+ |
|
325 |
+ // Success. |
|
326 |
+ return true; |
|
327 |
+} |
|
328 |
+ |
|
329 |
+/** |
|
330 |
+ * Updates a ticket/reply item in the database. |
|
331 |
+ * |
|
332 |
+ * This function allows modification of all post/ticket details - and can be used independently; it is possible (and even done |
|
333 |
+ * in SimpleDesk) to update just a ticket or just a post from this function. All three parameters are by <b>reference</b> |
|
334 |
+ * meaning they WILL be updated if things change. Note that this function is not validating that they are sensible values; it is |
|
335 |
+ * up to the calling function to ascertain that. |
|
336 |
+ * |
|
337 |
+ * @param array &$msgOptions - a hash array by reference, stating zero or more details to change on a message (if the change is strictly ticket-only, the entire $msgOptions array can be an empty array): |
|
338 |
+ * <ul> |
|
339 |
+ * <li>id: Required if changing a message; the principle numeric id of the message to modify</li> |
|
340 |
+ * <li>body: Optional, the principle body content of the message to change; if omitted, no change will occur. If set, assumed to have been cleaned already (with $smcFunc['htmlspecialchars'] and preparsecode)</li> |
|
341 |
+ * <li>modified: Optional, hash array containing items relating to modification (if 'modified' key exists, all of these should be set) |
|
342 |
+ * <ul> |
|
343 |
+ * <li>time: Unsigned int timestamp of the change</li> |
|
344 |
+ * <li>name: String; user name of the user making the change</li> |
|
345 |
+ * <li>id: Unsigned int user id of the user making the change</li> |
|
346 |
+ * </ul> |
|
347 |
+ * </li> |
|
348 |
+ * <li>smileys_enabled: Optional, boolean denoting whether smileys should be active on this post; if omitted no change will occur</li> |
|
349 |
+ * <li>attachments: Optional, array of attachment ids that need attaching to this message; if omitted no changes will occur</li> |
|
350 |
+ * </ul> |
|
351 |
+ * |
|
352 |
+ * @param array &$ticketOptions - a hash array by reference, stating one or more details necessary to change on a ticket: |
|
353 |
+ * <ul> |
|
354 |
+ * <li>id: Required in all cases, numeric ticket id that the edit relates to</li> |
|
355 |
+ * <li>subject: Optional string with the new subject in; if omitted no change will occur. If set, assumed to have been cleaned already (with $smcFunc['htmlspecialchars'] and strtr)</li> |
|
356 |
+ * <li>urgency: Optional integer with the new urgency in; if omitted no change will occur</li> |
|
357 |
+ * <li>status: Optional integer with the new status in; if omitted no change will occur</li> |
|
358 |
+ * <li>ssigned: Optional integer with the user id of assigned user; if omitted no change will occur (note, you would declare this as 0 to unassign a ticket - set to 0 is not omitted)</li> |
|
359 |
+ * <li>private: Optional boolean as to privacy of ticket: true = private, false = not private (note, you still declare this to change it)</li> |
|
360 |
+ * </ul> |
|
361 |
+ * |
|
362 |
+ * @param array &$posterOptions - a hash array by reference of details to change on the poster of a message: |
|
363 |
+ * <ul> |
|
364 |
+ * <li>name: Optional string, name of credited poster (in absence of id, this will be used); if omitted no change will occur</li> |
|
365 |
+ * <li>email: Optional string, email address of poster; if omitted no change will occur</li> |
|
366 |
+ * </ul> |
|
367 |
+ * |
|
368 |
+ * @return bool True on success, false on failure. |
|
369 |
+ * @since 1.0 |
|
370 |
+*/ |
|
371 |
+function shd_modify_ticket_post(&$msgOptions, &$ticketOptions, &$posterOptions) |
|
372 |
+{ |
|
373 |
+ global $user_info, $txt, $modSettings, $smcFunc, $context; |
|
374 |
+ |
|
375 |
+ $messages_columns = array(); |
|
376 |
+ $ticket_columns = array(); |
|
377 |
+ |
|
378 |
+ $ticketOptions['id'] = !empty($ticketOptions['id']) ? (int) $ticketOptions['id'] : 0; |
|
379 |
+ if ($ticketOptions['id'] == 0) |
|
380 |
+ return false; |
|
381 |
+ |
|
382 |
+ if (isset($posterOptions['name'])) |
|
383 |
+ $messages_columns['poster_name'] = $posterOptions['name']; |
|
384 |
+ if (isset($posterOptions['email'])) |
|
385 |
+ $messages_columns['poster_email'] = $posterOptions['email']; |
|
386 |
+ if (isset($msgOptions['body'])) |
|
387 |
+ $messages_columns['body'] = $msgOptions['body']; |
|
388 |
+ if (!empty($msgOptions['modified'])) |
|
389 |
+ { |
|
390 |
+ $messages_columns['modified_time'] = $msgOptions['modified']['time']; |
|
391 |
+ $messages_columns['modified_name'] = $msgOptions['modified']['name']; |
|
392 |
+ $messages_columns['modified_member'] = $msgOptions['modified']['id']; |
|
393 |
+ } |
|
394 |
+ if (isset($msgOptions['smileys_enabled'])) |
|
395 |
+ $messages_columns['smileys_enabled'] = empty($msgOptions['smileys_enabled']) ? 0 : 1; |
|
396 |
+ if (isset($ticketOptions['subject'])) |
|
397 |
+ $ticket_columns['subject'] = $ticketOptions['subject']; |
|
398 |
+ if (isset($ticketOptions['status'])) |
|
399 |
+ $ticket_columns['status'] = $ticketOptions['status']; |
|
400 |
+ if (isset($ticketOptions['urgency'])) |
|
401 |
+ $ticket_columns['urgency'] = $ticketOptions['urgency']; |
|
402 |
+ if (isset($ticketOptions['assigned'])) |
|
403 |
+ $ticket_columns['id_member_assigned'] = $ticketOptions['assigned']; |
|
404 |
+ if (isset($ticketOptions['private'])) |
|
405 |
+ $ticket_columns['private'] = empty($ticketOptions['private']) ? 0 : 1; |
|
406 |
+ |
|
407 |
+ // Fix the attachments. |
|
408 |
+ if (!empty($msgOptions['attachments'])) |
|
409 |
+ { |
|
410 |
+ $array = array(); |
|
411 |
+ foreach ($msgOptions['attachments'] as $attach) |
|
412 |
+ $array[] = array($attach, $msgOptions['id'], $ticketOptions['id']); |
|
413 |
+ |
|
414 |
+ $smcFunc['db_insert']('replace', |
|
415 |
+ '{db_prefix}helpdesk_attachments', |
|
416 |
+ array( |
|
417 |
+ 'id_attach' => 'int', 'id_msg' => 'int', 'id_ticket' => 'int', |
|
418 |
+ ), |
|
419 |
+ $array, |
|
420 |
+ array('id_attach') |
|
421 |
+ ); |
|
422 |
+ } |
|
423 |
+ |
|
424 |
+ if (empty($messages_columns) && empty($ticket_columns)) |
|
425 |
+ return true; |
|
426 |
+ |
|
427 |
+ // It's do or die time: forget any user aborts! |
|
428 |
+ $previous_ignore_user_abort = ignore_user_abort(true); |
|
429 |
+ |
|
430 |
+ // OK, let's get all this set up ready for SQL magic |
|
431 |
+ // Which columns need to be ints? |
|
432 |
+ $messageInts = array('modified_time', 'modified_member', 'smileys_enabled'); |
|
433 |
+ $msg_update_parameters = array( |
|
434 |
+ 'id_msg' => empty($msgOptions['id']) ? 0 : (int) $msgOptions['id'], |
|
435 |
+ ); |
|
436 |
+ |
|
437 |
+ foreach ($messages_columns as $var => $val) |
|
438 |
+ { |
|
439 |
+ $messages_columns[$var] = $var . ' = {' . (in_array($var, $messageInts) ? 'int' : 'string') . ':var_' . $var . '}'; |
|
440 |
+ $msg_update_parameters['var_' . $var] = $val; |
|
441 |
+ } |
|
442 |
+ |
|
443 |
+ $ticketInts = array('status', 'urgency'); |
|
444 |
+ $ticket_update_parameters = array( |
|
445 |
+ 'id_ticket' => $ticketOptions['id'], |
|
446 |
+ ); |
|
447 |
+ |
|
448 |
+ foreach ($ticket_columns as $var => $val) |
|
449 |
+ { |
|
450 |
+ $ticket_columns[$var] = $var . ' = {' . (in_array($var, $ticketInts) ? 'int' : 'string') . ':var_' . $var . '}'; |
|
451 |
+ $ticket_update_parameters['var_' . $var] = $val; |
|
452 |
+ } |
|
453 |
+ |
|
454 |
+ // GO GO GO! (message first) |
|
455 |
+ if (!empty($messages_columns)) |
|
456 |
+ { |
|
457 |
+ shd_db_query('', ' |
|
458 |
+ UPDATE {db_prefix}helpdesk_ticket_replies |
|
459 |
+ SET ' . implode(', ', $messages_columns) . ' |
|
460 |
+ WHERE id_msg = {int:id_msg}', |
|
461 |
+ $msg_update_parameters |
|
462 |
+ ); |
|
463 |
+ } |
|
464 |
+ |
|
465 |
+ if (!empty($ticket_columns)) |
|
466 |
+ { |
|
467 |
+ shd_db_query('', ' |
|
468 |
+ UPDATE {db_prefix}helpdesk_tickets |
|
469 |
+ SET ' . implode(', ', $ticket_columns) . ' |
|
470 |
+ WHERE id_ticket = {int:id_ticket}', |
|
471 |
+ $ticket_update_parameters |
|
472 |
+ ); |
|
473 |
+ } |
|
474 |
+ |
|
475 |
+ // And fix unread list |
|
476 |
+ if (!empty($msgOptions['modified'])) |
|
477 |
+ { |
|
478 |
+ shd_db_query('', ' |
|
479 |
+ UPDATE {db_prefix}helpdesk_log_read |
|
480 |
+ SET id_msg = {int:last_msg} |
|
481 |
+ WHERE id_member != {int:modified_member} |
|
482 |
+ AND id_ticket = {int:ticket} |
|
483 |
+ AND id_msg >= {int:edited_msg}', |
|
484 |
+ array( |
|
485 |
+ 'last_msg' => $msg_update_parameters['id_msg'] - 1, |
|
486 |
+ 'modified_member' => $msgOptions['modified']['id'], |
|
487 |
+ 'ticket' => $ticketOptions['id'], |
|
488 |
+ 'edited_msg' => $msg_update_parameters['id_msg'], |
|
489 |
+ ) |
|
490 |
+ ); |
|
491 |
+ } |
|
492 |
+ |
|
493 |
+ // Int hook |
|
494 |
+ if (!empty($modSettings['shd_hook_modpost'])) |
|
495 |
+ { |
|
496 |
+ $functions = explode(',', $modSettings['shd_hook_modpost']); |
|
497 |
+ foreach ($functions as $function) |
|
498 |
+ { |
|
499 |
+ if (is_callable($function)) |
|
500 |
+ $function($msgOptions, $ticketOptions, $posterOptions); // this should be picked up by reference in the called function or it won't do anything! |
|
501 |
+ } |
|
502 |
+ } |
|
503 |
+ |
|
504 |
+ ignore_user_abort($previous_ignore_user_abort); |
|
505 |
+ |
|
506 |
+ // Success. |
|
507 |
+ return true; |
|
508 |
+} |
|
509 |
+ |
|
510 |
+/** |
|
511 |
+ * Identifies the range of options that a user could have for ticket urgency and updates $context['ticket_form'] accordingly. |
|
512 |
+ * |
|
513 |
+ * Ticket urgency permissions are checked, and an array is built suitable for $context['ticket_form'], which is the principle |
|
514 |
+ * format used in the ticket posting/reply posting functions in SimpleDesk-Post.php. |
|
515 |
+ * |
|
516 |
+ * There is no return function; $context['ticket_form']['urgency'] is updated, both the ['options'] and ['can_change'] keys |
|
517 |
+ * may be modified. |
|
518 |
+ * |
|
519 |
+ * @param bool $self_ticket (default false) Permissions will be different for many users depending on whether it is one |
|
520 |
+ * of their own tickets or not. This allows the code to state whether it is a ticket owned by the current user or not. |
|
521 |
+ * |
|
522 |
+ * @see SimpleDesk-Display.php |
|
523 |
+ * @since 1.0 |
|
524 |
+*/ |
|
525 |
+function shd_get_urgency_options($self_ticket = false) |
|
526 |
+{ |
|
527 |
+ global $context; |
|
528 |
+ $context['ticket_form']['urgency']['options'] = array( |
|
529 |
+ TICKET_URGENCY_LOW => 'shd_urgency_0', |
|
530 |
+ TICKET_URGENCY_MEDIUM => 'shd_urgency_1', |
|
531 |
+ TICKET_URGENCY_HIGH => 'shd_urgency_2', |
|
532 |
+ TICKET_URGENCY_VHIGH => 'shd_urgency_3', |
|
533 |
+ TICKET_URGENCY_SEVERE => 'shd_urgency_4', |
|
534 |
+ TICKET_URGENCY_CRITICAL => 'shd_urgency_5', |
|
535 |
+ ); |
|
536 |
+ |
|
537 |
+ if (shd_allowed_to('shd_alter_urgency_higher_any') || ($self_ticket && shd_allowed_to('shd_alter_urgency_higher_own'))) |
|
538 |
+ { |
|
539 |
+ $context['ticket_form']['urgency']['can_change'] = true; |
|
540 |
+ } |
|
541 |
+ elseif (shd_allowed_to('shd_alter_urgency_any') || ($self_ticket && shd_allowed_to('shd_alter_urgency_own'))) |
|
542 |
+ { |
|
543 |
+ if (!empty($context['ticket_form']['urgency']['setting']) && $context['ticket_form']['urgency']['setting'] > TICKET_URGENCY_HIGH) |
|
544 |
+ $context['ticket_form']['urgency']['can_change'] = false; |
|
545 |
+ else |
|
546 |
+ { |
|
547 |
+ $context['ticket_form']['urgency']['can_change'] = true; |
|
548 |
+ unset( |
|
549 |
+ $context['ticket_form']['urgency']['options'][TICKET_URGENCY_VHIGH], |
|
550 |
+ $context['ticket_form']['urgency']['options'][TICKET_URGENCY_SEVERE], |
|
551 |
+ $context['ticket_form']['urgency']['options'][TICKET_URGENCY_CRITICAL] |
|
552 |
+ ); |
|
553 |
+ } |
|
554 |
+ } |
|
555 |
+ else |
|
556 |
+ $context['ticket_form']['urgency']['can_change'] = false; |
|
557 |
+} |
|
558 |
+ |
|
559 |
+?> |
|
0 | 560 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,16 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+// This file is here solely to protect your SimpleDesk sources directory. |
|
4 |
+ |
|
5 |
+// Look for Settings.php.... |
|
6 |
+if (file_exists(dirname(dirname(dirname(__FILE__))) . '/Settings.php')) |
|
7 |
+{ |
|
8 |
+ // Found it! |
|
9 |
+ require(dirname(dirname(dirname(__FILE__))) . '/Settings.php'); |
|
10 |
+ header('Location: ' . $boardurl); |
|
11 |
+} |
|
12 |
+// Can't find it... just forget it. |
|
13 |
+else |
|
14 |
+ exit; |
|
15 |
+ |
|
16 |
+?> |
|
0 | 17 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,683 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk's administration area |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * Displays SimpleDesk's administration panel, options pages, action log and the get-support page. |
|
6 |
+ * |
|
7 |
+ * @package template |
|
8 |
+ * @since 1.0 |
|
9 |
+*/ |
|
10 |
+ |
|
11 |
+/** |
|
12 |
+ * Display the main information center for the administration panel. |
|
13 |
+ * |
|
14 |
+ * This function handles output of data populated by {@link shd_admin_info()}: |
|
15 |
+ * - upgraded SD version advisory |
|
16 |
+ * - latest news from SimpleDesk.net |
|
17 |
+ * - basic version check |
|
18 |
+ * - count of open/closed/recycled tickets in the helpdesk in total |
|
19 |
+ * - list of current helpdesk staff |
|
20 |
+ * - credits |
|
21 |
+ * |
|
22 |
+ * @see shd_admin_info() |
|
23 |
+ * @since 1.0 |
|
24 |
+*/ |
|
25 |
+function template_shd_admin() |
|
26 |
+{ |
|
27 |
+ global $context, $settings, $options, $scripturl, $txt, $modSettings; |
|
28 |
+ |
|
29 |
+ // Make our admin feel welcome |
|
30 |
+ echo ' |
|
31 |
+ <div id="admincenter">'; |
|
32 |
+ |
|
33 |
+ // Update? |
|
34 |
+ echo ' |
|
35 |
+ <div id="sd_update_section" class="tborder" style="display: none;"></div>'; |
|
36 |
+ |
|
37 |
+ echo ' |
|
38 |
+ <div id="admin_main_section">'; |
|
39 |
+ |
|
40 |
+ // Display the "live news" from simpledesk.net |
|
41 |
+ echo ' |
|
42 |
+ <div id="sd_live_news" class="align_left"> |
|
43 |
+ <div class="tborder"> |
|
44 |
+ <div class="cat_bar"> |
|
45 |
+ <h3 class="catbg grid_header"> |
|
46 |
+ <img src="', $settings['default_images_url'], '/simpledesk/live.png" alt="*" /> |
|
47 |
+ ', $txt['shd_live_from'], ' |
|
48 |
+ <span class="righttext"><a href="', $scripturl, '?action=helpadmin;help=shd_admin_help_live" onclick="return reqWin(this.href);"><img src="', $settings['images_url'], '/helptopics.gif" alt="', $txt['help'], '" /></a></span> |
|
49 |
+ </h3> |
|
50 |
+ </div> |
|
51 |
+ <div class="windowbg"> |
|
52 |
+ <div class="content"> |
|
53 |
+ <div id="sdAnnouncements">', $txt['shd_no_connect'], '</div> |
|
54 |
+ </div> |
|
55 |
+ <span class="botslice"><span></span></span> |
|
56 |
+ </div> |
|
57 |
+ </div> |
|
58 |
+ </div>'; |
|
59 |
+ |
|
60 |
+ // Show the user version information from their server. |
|
61 |
+ echo ' |
|
62 |
+ <div id="sd_supportVersionsTable" class="align_right"> |
|
63 |
+ <div class="tborder"> |
|
64 |
+ <div class="cat_bar"> |
|
65 |
+ <h3 class="catbg grid_header"> |
|
66 |
+ <img src="', $settings['default_images_url'], '/simpledesk/modification.png" alt="*" /> |
|
67 |
+ ', $txt['shd_mod_information'], ' |
|
68 |
+ <span class="righttext"><a href="', $scripturl, '?action=helpadmin;help=shd_admin_help_modification" onclick="return reqWin(this.href);"><img src="', $settings['images_url'], '/helptopics.gif" alt="', $txt['help'], '" /></a></span> |
|
69 |
+ </h3> |
|
70 |
+ </div> |
|
71 |
+ <div class="windowbg"> |
|
72 |
+ <div class="content"> |
|
73 |
+ <div id="sd_version_details"> |
|
74 |
+ <img src="', $settings['default_images_url'], '/simpledesk/support.png" alt="*" class="shd_icon_minihead" /> <strong>', $txt['shd_need_support'], '</strong><br /> |
|
75 |
+ ', sprintf($txt['shd_support_start_here'], $scripturl . '?action=admin;area=helpdesk_info;sa=support'), '<br /> |
|
76 |
+ <br /> |
|
77 |
+ <img src="', $settings['default_images_url'], '/simpledesk/versions.png" alt="*" class="shd_icon_minihead" /> <strong>', $txt['support_versions'], ':</strong><br /> |
|
78 |
+ ', $txt['shd_your_version'], ': |
|
79 |
+ <em id="yourVersion" class="shd_nowrap">', SHD_VERSION, '</em><br /> |
|
80 |
+ ', $txt['shd_current_version'], ': |
|
81 |
+ <em id="sdVersion" class="shd_nowrap">??</em><br /><br /> |
|
82 |
+ <img src="', $settings['default_images_url'], '/simpledesk/ticket.png" alt="*" class="shd_icon_minihead" /> <strong>', $txt['shd_ticket_information'], ':</strong><br /> |
|
83 |
+ ', $txt['shd_total_tickets'], ': |
|
84 |
+ <em id="totalTickets" class="shd_nowrap"> |
|
85 |
+ <a href="javascript: shd_ticket_total_information();" >', $context['total_tickets'], '</a> |
|
86 |
+ </em> |
|
87 |
+ <div id="shd_ticket_total_information" style="display: none;"> |
|
88 |
+ ', $txt['shd_open_tickets'], ': <em>', $context['open_tickets'], '</em><br /> |
|
89 |
+ ', $txt['shd_closed_tickets'], ': <em>', $context['closed_tickets'], '</em><br /> |
|
90 |
+ ', $txt['shd_recycled_tickets'], ': <em>', $context['recycled_tickets'], '</em><br /> |
|
91 |
+ </div> |
|
92 |
+ <br />'; |
|
93 |
+ |
|
94 |
+ // Display all the members who can manage the helpdesk. |
|
95 |
+ // NOTE: This is currently (15/1/10) uncapped, meaning it's just the full list direct from SimpleDesk-Admin.php. |
|
96 |
+ // That gets the data. Up to here how it should be displayed. |
|
97 |
+ echo ' |
|
98 |
+ <br /> |
|
99 |
+ <img src="', $settings['default_images_url'], '/simpledesk/staff.png" alt="*" class="shd_icon_minihead" /> <strong>', $txt['shd_staff_list'], ':</strong> |
|
100 |
+ ', implode(', ', $context['staff']); |
|
101 |
+ |
|
102 |
+ echo ' |
|
103 |
+ </div> |
|
104 |
+ </div> |
|
105 |
+ <span class="botslice"><span></span></span> |
|
106 |
+ </div> |
|
107 |
+ </div> |
|
108 |
+ </div> |
|
109 |
+ </div> |
|
110 |
+ <div class="shd_credits_break"> </div>'; |
|
111 |
+ |
|
112 |
+ |
|
113 |
+ echo ' |
|
114 |
+ <div id="sd_credits"> |
|
115 |
+ <div class="tborder"> |
|
116 |
+ <div class="title_bar"> |
|
117 |
+ <h3 class="titlebg sd_no_margin grid_header"> |
|
118 |
+ <img src="', $settings['default_images_url'], '/simpledesk/credits.png" alt="*" /> |
|
119 |
+ ', $txt['shd_credits'], ' |
|
120 |
+ <span class="righttext"><a href="', $scripturl, '?action=helpadmin;help=shd_admin_help_credits" onclick="return reqWin(this.href);"><img src="', $settings['images_url'], '/helptopics.gif" alt="', $txt['help'], '" /></a></span> |
|
121 |
+ </h3> |
|
122 |
+ </div>'; |
|
123 |
+ |
|
124 |
+ foreach ($context['shd_credits'] as $section) |
|
125 |
+ { |
|
126 |
+ echo ' |
|
127 |
+ <div class="roundframe"> |
|
128 |
+ <div class="content"> |
|
129 |
+ ', $section['pretext'], ' |
|
130 |
+ <hr />'; |
|
131 |
+ |
|
132 |
+ foreach ($section['groups'] as $group) |
|
133 |
+ { |
|
134 |
+ echo ' |
|
135 |
+ <div class="description">'; |
|
136 |
+ |
|
137 |
+ // Pretty icons! :D |
|
138 |
+ if (isset($group['icon'])) |
|
139 |
+ echo' |
|
140 |
+ <img src="', $settings['default_images_url'], '/simpledesk/credits/', $group['icon'], '" alt="" class="floatleft" /> |
|
141 |
+ <div class="shd_credits_names">'; |
|
142 |
+ |
|
143 |
+ |
|
144 |
+ if (isset($group['title'])) |
|
145 |
+ echo ' |
|
146 |
+ <strong>', $group['title'], '</strong>', !empty($group['desc']) ? ' - <em class="smalltext">' . $group['desc'] . '</em>' : '', '<hr />'; |
|
147 |
+ |
|
148 |
+ // Try to make this read nicely. |
|
149 |
+ if (count($group['members']) <= 2) |
|
150 |
+ echo implode(' ' . $txt['shd_credits_and'] . ' ', $group['members']); |
|
151 |
+ else |
|
152 |
+ { |
|
153 |
+ $last_peep = array_pop($group['members']); |
|
154 |
+ echo implode(', ', $group['members']), ', ', $txt['shd_credits_and'], ' ', $last_peep; |
|
155 |
+ } |
|
156 |
+ |
|
157 |
+ if (isset($group['icon'])) |
|
158 |
+ echo' |
|
159 |
+ </div>'; |
|
160 |
+ |
|
161 |
+ echo ' |
|
162 |
+ </div>'; |
|
163 |
+ } |
|
164 |
+ |
|
165 |
+ echo ' |
|
166 |
+ </div> |
|
167 |
+ </div> |
|
168 |
+ <span class="lowerframe"><span></span></span> |
|
169 |
+ </div> |
|
170 |
+ </div>'; |
|
171 |
+ } |
|
172 |
+ |
|
173 |
+ echo ' |
|
174 |
+ </div> |
|
175 |
+ <br class="clear" />'; |
|
176 |
+ |
|
177 |
+ // The below functions include all the scripts needed from the simpledesk.net site. The language and format are passed for internationalization. |
|
178 |
+ if (empty($modSettings['disable_smf_js'])) |
|
179 |
+ echo ' |
|
180 |
+ <script type="text/javascript" src="http://www.simpledesk.net/sd/current-version.js"></script> |
|
181 |
+ <script type="text/javascript" src="http://www.simpledesk.net/sd/latest-news.js"></script>'; |
|
182 |
+ |
|
183 |
+ // This sets the announcements and current versions themselves ;). |
|
184 |
+ echo ' |
|
185 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
186 |
+ |
|
187 |
+ var oAdminIndex = new sd_AdminIndex({ |
|
188 |
+ sSelf: \'oAdminCenter\', |
|
189 |
+ |
|
190 |
+ bLoadAnnouncements: true, |
|
191 |
+ sAnnouncementTemplate: ', JavaScriptEscape(' |
|
192 |
+ <dl> |
|
193 |
+ %content% |
|
194 |
+ </dl> |
|
195 |
+ '), ', |
|
196 |
+ sAnnouncementMessageTemplate: ', JavaScriptEscape(' |
|
197 |
+ <dt><a href="%href%" target="_blank">%subject%</a> ' . $txt['on'] . ' %time% ' . $txt['by'] . ' %author%</dt> |
|
198 |
+ <dd> |
|
199 |
+ %message%<br /> |
|
200 |
+ <a href="%readmore%" class="smalltext" target="_blank">' . $txt['shd_admin_readmore'] . '</a> |
|
201 |
+ </dd> |
|
202 |
+ '), ', |
|
203 |
+ sAnnouncementContainerId: \'sdAnnouncements\', |
|
204 |
+ |
|
205 |
+ bLoadVersions: true, |
|
206 |
+ sSdVersionContainerId: \'sdVersion\', |
|
207 |
+ sYourVersionContainerId: \'yourVersion\', |
|
208 |
+ sVersionOutdatedTemplate: ', JavaScriptEscape(' |
|
209 |
+ <span class="alert">%currentVersion%</span> |
|
210 |
+ '), ', |
|
211 |
+ |
|
212 |
+ bLoadUpdateNotification: true, |
|
213 |
+ sUpdateNotificationContainerId: \'sd_update_section\', |
|
214 |
+ sUpdateNotificationDefaultTitle: ', JavaScriptEscape($txt['shd_update_available']), ', |
|
215 |
+ sUpdateNotificationDefaultMessage: ', JavaScriptEscape($txt['shd_update_message']), ', |
|
216 |
+ sUpdateNotificationTemplate: ', JavaScriptEscape(' |
|
217 |
+ <div class="cat_bar"> |
|
218 |
+ <h3 id="update_title" class="catbg grid_header"><span class="right"></span> |
|
219 |
+ <img src="' . $settings['default_images_url'] . '/simpledesk/update.png" alt="" /> |
|
220 |
+ %title% |
|
221 |
+ <span class="righttext"><a href="' . $scripturl . '?action=helpadmin;help=shd_admin_help_update" onclick="return reqWin(this.href);"><img src="'. $settings['images_url'] . '/helptopics.gif" alt="' . $txt['help'] . '" /></a></span> |
|
222 |
+ </h3> |
|
223 |
+ </div> |
|
224 |
+ <div class="windowbg" id="update_container"> |
|
225 |
+ <div class="content" id="update_content"> |
|
226 |
+ <p id="update_critical_alert" class="alert" style="display: none;">!!</p> |
|
227 |
+ <h3 id="update_critical_title" style="display: none;">%criticaltitle%</h3> |
|
228 |
+ <div id="update_message" class="smalltext"> |
|
229 |
+ <p> |
|
230 |
+ %message% |
|
231 |
+ </p> |
|
232 |
+ </div> |
|
233 |
+ </div> |
|
234 |
+ <span class="botslice"><span></span></span> |
|
235 |
+ </div> |
|
236 |
+ '), ', |
|
237 |
+ sUpdateNotificationLink: ', JavaScriptEscape($scripturl . '?action=admin;area=packages;pgdownload;auto;package=%package%;' . $context['session_var'] . '=' . $context['session_id']), ', |
|
238 |
+ sUpdateInformationLink: \'%information%\', |
|
239 |
+ }); |
|
240 |
+ // ]]></script>'; |
|
241 |
+} |
|
242 |
+ |
|
243 |
+/** |
|
244 |
+ * Display options as set up by the options functions. |
|
245 |
+ * |
|
246 |
+ * This is a modified version of the standard SMF template for displaying settings, mostly so we have access to a custom BBC template. |
|
247 |
+ * |
|
248 |
+ * In short, SMF's functions call the relevant function in {@link SimpleDesk-Admin.php} to gather which options should be displayed, store in $context, then pass it here. |
|
249 |
+ * |
|
250 |
+ * The same template services all of the defined areas inside Admin: SimpleDesk: Options. |
|
251 |
+ * |
|
252 |
+ * @see shd_admin_options() |
|
253 |
+ * @since 1.0 |
|
254 |
+*/ |
|
255 |
+function template_shd_show_settings() |
|
256 |
+{ |
|
257 |
+ global $context, $txt, $settings, $scripturl; |
|
258 |
+ |
|
259 |
+ echo ' |
|
260 |
+ <script type="text/javascript"><!-- // --><![CDATA['; |
|
261 |
+ |
|
262 |
+ if (!empty($context['settings_pre_javascript'])) |
|
263 |
+ echo $context['settings_pre_javascript']; |
|
264 |
+ |
|
265 |
+ // If we have BBC selection we have a bit of JS. |
|
266 |
+ if (!empty($context['bbc_sections'])) |
|
267 |
+ { |
|
268 |
+ echo ' |
|
269 |
+ function toggleBBCDisabled(section, disable) |
|
270 |
+ { |
|
271 |
+ for (var i = 0; i < document.forms.bbcForm.length; i++) |
|
272 |
+ { |
|
273 |
+ if (typeof(document.forms.bbcForm[i].name) == "undefined" || (document.forms.bbcForm[i].name.substr(0, 11) != "enabledTags") || (document.forms.bbcForm[i].name.indexOf(section) != 11)) |
|
274 |
+ continue; |
|
275 |
+ |
|
276 |
+ document.forms.bbcForm[i].disabled = disable; |
|
277 |
+ } |
|
278 |
+ document.getElementById("bbc_" + section + "_select_all").disabled = disable; |
|
279 |
+ }'; |
|
280 |
+ } |
|
281 |
+ echo ' |
|
282 |
+ // ]]></script>'; |
|
283 |
+ |
|
284 |
+ if (!empty($context['settings_insert_above'])) |
|
285 |
+ echo $context['settings_insert_above']; |
|
286 |
+ |
|
287 |
+ echo ' |
|
288 |
+ <div id="admincenter"> |
|
289 |
+ <form name="adminform" action="', $context['post_url'], '" method="post" accept-charset="', $context['character_set'], '"', !empty($context['force_form_onsubmit']) ? ' onsubmit="' . $context['force_form_onsubmit'] . '"' : '', '>'; |
|
290 |
+ |
|
291 |
+ // Is there a custom title? |
|
292 |
+ if (isset($context['settings_title'])) |
|
293 |
+ echo ' |
|
294 |
+ <div class="tborder"> |
|
295 |
+ <div class="cat_bar"> |
|
296 |
+ <h3 class="catbg grid_header"> |
|
297 |
+ <img src="', shd_image_url($context['settings_icon']), '" class="icon" alt="*" /> ', $context['settings_title'], ' |
|
298 |
+ </h3> |
|
299 |
+ </div>'; |
|
300 |
+ |
|
301 |
+ // Have we got some custom code to insert? |
|
302 |
+ if (!empty($context['settings_message'])) |
|
303 |
+ echo ' |
|
304 |
+ <div class="information">', $context['settings_message'], '</div>'; |
|
305 |
+ |
|
306 |
+ // Now actually loop through all the variables. |
|
307 |
+ $is_open = false; |
|
308 |
+ foreach ($context['config_vars'] as $config_var) |
|
309 |
+ { |
|
310 |
+ // Is it a title or a description? |
|
311 |
+ if (is_array($config_var) && ($config_var['type'] == 'title' || $config_var['type'] == 'desc')) |
|
312 |
+ { |
|
313 |
+ // Not a list yet? |
|
314 |
+ if ($is_open) |
|
315 |
+ { |
|
316 |
+ $is_open = false; |
|
317 |
+ echo ' |
|
318 |
+ </dl> |
|
319 |
+ </div> |
|
320 |
+ <span class="botslice"><span></span></span> |
|
321 |
+ </div> |
|
322 |
+ </div>'; |
|
323 |
+ } |
|
324 |
+ |
|
325 |
+ // A title? |
|
326 |
+ if ($config_var['type'] == 'title') |
|
327 |
+ { |
|
328 |
+ echo ' |
|
329 |
+ <div class="cat_bar"> |
|
330 |
+ <h3 class="', !empty($config_var['class']) ? $config_var['class'] : 'catbg', '"', !empty($config_var['force_div_id']) ? ' id="' . $config_var['force_div_id'] . '"' : '', '> |
|
331 |
+ ', ($config_var['help'] ? '<a href="' . $scripturl . '?action=helpadmin;help=' . $config_var['help'] . '" onclick="return reqWin(this.href);" class="help"><img src="' . $settings['images_url'] . '/helptopics.gif" alt="' . $txt['help'] . '" /></a>' : ''), ' |
|
332 |
+ ', $config_var['label'], ' |
|
333 |
+ </h3> |
|
334 |
+ </div>'; |
|
335 |
+ } |
|
336 |
+ // A description? |
|
337 |
+ else |
|
338 |
+ { |
|
339 |
+ echo ' |
|
340 |
+ <p class="description"> |
|
341 |
+ ', $config_var['label'], ' |
|
342 |
+ </p>'; |
|
343 |
+ } |
|
344 |
+ |
|
345 |
+ continue; |
|
346 |
+ } |
|
347 |
+ |
|
348 |
+ // Not a list yet? |
|
349 |
+ if (!$is_open) |
|
350 |
+ { |
|
351 |
+ $is_open = true; |
|
352 |
+ |
|
353 |
+ if (!isset($context['settings_title'])) |
|
354 |
+ echo '<div class="tborder">'; |
|
355 |
+ |
|
356 |
+ echo ' |
|
357 |
+ <div class="windowbg2"> |
|
358 |
+ <div class="content"> |
|
359 |
+ <dl class="permsettings">'; |
|
360 |
+ } |
|
361 |
+ |
|
362 |
+ // Hang about? Are you pulling my leg - a callback?! |
|
363 |
+ if (is_array($config_var) && $config_var['type'] == 'callback') |
|
364 |
+ { |
|
365 |
+ if (function_exists('template_callback_' . $config_var['name'])) |
|
366 |
+ call_user_func('template_callback_' . $config_var['name']); |
|
367 |
+ |
|
368 |
+ continue; |
|
369 |
+ } |
|
370 |
+ |
|
371 |
+ if (is_array($config_var)) |
|
372 |
+ { |
|
373 |
+ // Sometimes we just gotta have some hidden stuff passed back |
|
374 |
+ if ($config_var['type'] == 'hidden') |
|
375 |
+ { |
|
376 |
+ echo ' |
|
377 |
+ <input type="hidden" name="', $config_var['name'], '" value="', $config_var['value'], '" />'; |
|
378 |
+ } |
|
379 |
+ // Is this a span like a message? |
|
380 |
+ elseif (in_array($config_var['type'], array('message', 'warning'))) |
|
381 |
+ { |
|
382 |
+ echo ' |
|
383 |
+ <dd', $config_var['type'] == 'warning' ? ' class="alert"' : '', (!empty($config_var['force_div_id']) ? ' id="' . $config_var['force_div_id'] . '_dd"' : ''), '> |
|
384 |
+ ', $config_var['label'], ' |
|
385 |
+ </dd>'; |
|
386 |
+ } |
|
387 |
+ // Otherwise it's an input box of some kind. |
|
388 |
+ else |
|
389 |
+ { |
|
390 |
+ echo ' |
|
391 |
+ <dt', is_array($config_var) && !empty($config_var['force_div_id']) ? ' id="' . $config_var['force_div_id'] . '"' : '', is_array($config_var) && !empty($config_var['invisible']) ? ' style="display:none;"' : '', '>'; |
|
392 |
+ |
|
393 |
+ // Some quick helpers... |
|
394 |
+ $javascript = $config_var['javascript']; |
|
395 |
+ $disabled = !empty($config_var['disabled']) ? ' disabled="disabled"' : ''; |
|
396 |
+ $subtext = !empty($config_var['subtext']) ? '<br /><span class="smalltext"> ' . $config_var['subtext'] . '</span>' : ''; |
|
397 |
+ |
|
398 |
+ // Show the [?] button. |
|
399 |
+ if ($config_var['help']) |
|
400 |
+ echo ' |
|
401 |
+ <a id="setting_', $config_var['name'], '" href="', $scripturl, '?action=helpadmin;help=', $config_var['help'], '" onclick="return reqWin(this.href);" class="help"><img src="', $settings['images_url'], '/helptopics.gif" alt="', $txt['help'], '" border="0" /></a><span', ($config_var['disabled'] ? ' class="disabled"' : ($config_var['invalid'] ? ' class="error"' : '')), '><label id="label_', $config_var['name'], '" for="', $config_var['name'], '">', $config_var['label'], '</label>', $subtext, ($config_var['type'] == 'password' ? '<br /><em>' . $txt['admin_confirm_password'] . '</em>' : ''), '</span> |
|
402 |
+ </dt>'; |
|
403 |
+ else |
|
404 |
+ echo ' |
|
405 |
+ <a id="setting_', $config_var['name'], '"></a> <span', ($config_var['disabled'] ? ' class="disabled"' : ($config_var['invalid'] ? ' class="error"' : '')), '><label id="label_', $config_var['name'], '" for="', $config_var['name'], '">', $config_var['label'], '</label>', $subtext, ($config_var['type'] == 'password' ? '<br /><em>' . $txt['admin_confirm_password'] . '</em>' : ''), '</span> |
|
406 |
+ </dt>'; |
|
407 |
+ |
|
408 |
+ echo ' |
|
409 |
+ <dd', (!empty($config_var['force_div_id']) ? ' id="' . $config_var['force_div_id'] . '_dd"' : ''), (is_array($config_var) && !empty($config_var['invisible']) ? ' style="display:none;"' : ''), '>', |
|
410 |
+ $config_var['preinput']; |
|
411 |
+ |
|
412 |
+ // Show a check box. |
|
413 |
+ if ($config_var['type'] == 'check') |
|
414 |
+ echo ' |
|
415 |
+ <input type="checkbox"', $javascript, $disabled, ' name="', $config_var['name'], '" id="', $config_var['name'], '"', ($config_var['value'] ? ' checked="checked"' : ''), ' value="1" class="input_check" />'; |
|
416 |
+ // Escape (via htmlspecialchars.) the text box. |
|
417 |
+ elseif ($config_var['type'] == 'password') |
|
418 |
+ echo ' |
|
419 |
+ <input type="password"', $disabled, $javascript, ' name="', $config_var['name'], '[0]"', ($config_var['size'] ? ' size="' . $config_var['size'] . '"' : ''), ' value="*#fakepass#*" onfocus="this.value = \'\'; this.form.', $config_var['name'], '.disabled = false;" class="input_password" /><br /> |
|
420 |
+ <input type="password" disabled="disabled" id="', $config_var['name'], '" name="', $config_var['name'], '[1]"', ($config_var['size'] ? ' size="' . $config_var['size'] . '"' : ''), ' class="input_password" />'; |
|
421 |
+ // Show a selection box. |
|
422 |
+ elseif ($config_var['type'] == 'select') |
|
423 |
+ { |
|
424 |
+ echo ' |
|
425 |
+ <select name="', $config_var['name'], '" id="', $config_var['name'], '" ', $javascript, $disabled, (!empty($config_var['multiple']) ? ' multiple="multiple"' : ''), '>'; |
|
426 |
+ foreach ($config_var['data'] as $option) |
|
427 |
+ echo ' |
|
428 |
+ <option value="', $option[0], '"', (($option[0] == $config_var['value'] || (!empty($config_var['multiple']) && in_array($option[0], $config_var['value']))) ? ' selected="selected"' : ''), '>', $option[1], '</option>'; |
|
429 |
+ echo ' |
|
430 |
+ </select>'; |
|
431 |
+ } |
|
432 |
+ // Text area? |
|
433 |
+ elseif ($config_var['type'] == 'large_text') |
|
434 |
+ { |
|
435 |
+ echo ' |
|
436 |
+ <textarea rows="', ($config_var['size'] ? $config_var['size'] : 4), '" cols="40" ', $javascript, $disabled, ' name="', $config_var['name'], '" id="', $config_var['name'], '">', $config_var['value'], '</textarea>'; |
|
437 |
+ } |
|
438 |
+ // Permission group? |
|
439 |
+ elseif ($config_var['type'] == 'permissions') |
|
440 |
+ { |
|
441 |
+ theme_inline_permissions($config_var['name']); |
|
442 |
+ } |
|
443 |
+ // BBC selection? |
|
444 |
+ elseif ($config_var['type'] == 'bbc') |
|
445 |
+ { |
|
446 |
+ echo ' |
|
447 |
+ <fieldset id="', $config_var['name'], '"> |
|
448 |
+ <legend><strong>', $txt['bbcTagsToUse_select'], '</strong></legend> |
|
449 |
+ <ul class="reset">'; |
|
450 |
+ |
|
451 |
+ foreach ($context['bbc_columns'] as $bbcColumn) |
|
452 |
+ { |
|
453 |
+ foreach ($bbcColumn as $bbcTag) |
|
454 |
+ echo ' |
|
455 |
+ <li class="list_bbc align_left shd_bbc_list"> |
|
456 |
+ <input type="checkbox" name="', $config_var['name'], '_enabledTags[]" id="tag_', $config_var['name'], '_', $bbcTag['tag'], '" value="', $bbcTag['tag'], '"', in_array($bbcTag['tag'], $context['enabled_tags'][$config_var['name']]) ? ' checked="checked"' : '', ' class="input_check" /> <label for="tag_', $config_var['name'], '_', $bbcTag['tag'], '">', $bbcTag['tag'], '</label>', $bbcTag['show_help'] ? ' (<a href="' . $scripturl . '?action=helpadmin;help=tag_' . $bbcTag['tag'] . '" onclick="return reqWin(this.href);">?</a>)' : '', ' |
|
457 |
+ </li>'; |
|
458 |
+ } |
|
459 |
+ echo ' </ul> |
|
460 |
+ <br class="clear" /><input type="checkbox" id="select_all" onclick="invertAll(this, this.form, \'', $config_var['name'], '_enabledTags\');"', $context['all_enabled'][$config_var['name']] ? ' checked="checked"' : '', ' class="input_check" /> <label for="select_all"><em>', $txt['bbcTagsToUse_select_all'], '</em></label> |
|
461 |
+ </fieldset>'; |
|
462 |
+ } |
|
463 |
+ // A simple message? |
|
464 |
+ elseif ($config_var['type'] == 'var_message') |
|
465 |
+ echo ' |
|
466 |
+ <div', !empty($config_var['name']) ? ' id="' . $config_var['name'] . '"' : '', '>', $config_var['var_message'], '</div>'; |
|
467 |
+ // Assume it must be a text box. |
|
468 |
+ else |
|
469 |
+ echo ' |
|
470 |
+ <input type="text"', $javascript, $disabled, ' name="', $config_var['name'], '" id="', $config_var['name'], '" value="', $config_var['value'], '"', ($config_var['size'] ? ' size="' . $config_var['size'] . '"' : ''), ' class="input_text" />'; |
|
471 |
+ |
|
472 |
+ echo isset($config_var['postinput']) ? ' |
|
473 |
+ ' . $config_var['postinput'] : '', |
|
474 |
+ '</dd>'; |
|
475 |
+ } |
|
476 |
+ } |
|
477 |
+ |
|
478 |
+ else |
|
479 |
+ { |
|
480 |
+ // Just show a separator. |
|
481 |
+ if ($config_var == '') |
|
482 |
+ echo ' |
|
483 |
+ </dl> |
|
484 |
+ <hr class="hrcolor" /> |
|
485 |
+ <dl class="permsettings">'; |
|
486 |
+ else |
|
487 |
+ echo ' |
|
488 |
+ <dd> |
|
489 |
+ <strong>' . $config_var . '</strong> |
|
490 |
+ </dd>'; |
|
491 |
+ } |
|
492 |
+ } |
|
493 |
+ |
|
494 |
+ if ($is_open) |
|
495 |
+ echo ' |
|
496 |
+ </dl>'; |
|
497 |
+ |
|
498 |
+ if (empty($context['settings_save_dont_show'])) |
|
499 |
+ echo ' |
|
500 |
+ <hr class="hrcolor" /> |
|
501 |
+ <div class="righttext"> |
|
502 |
+ <input type="submit" value="', $txt['save'], '"', (!empty($context['save_disabled']) ? ' disabled="disabled"' : ''), (!empty($context['settings_save_onclick']) ? ' onclick="' . $context['settings_save_onclick'] . '"' : ''), ' class="button_submit" /> |
|
503 |
+ </div>'; |
|
504 |
+ |
|
505 |
+ if ($is_open) |
|
506 |
+ echo ' |
|
507 |
+ </div> |
|
508 |
+ <span class="botslice"><span></span></span> |
|
509 |
+ </div> |
|
510 |
+ </div>'; |
|
511 |
+ |
|
512 |
+ echo ' |
|
513 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
514 |
+ </form> |
|
515 |
+ </div> |
|
516 |
+ <br class="clear" />'; |
|
517 |
+ |
|
518 |
+ if (!empty($context['settings_post_javascript'])) |
|
519 |
+ echo ' |
|
520 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
521 |
+ ', $context['settings_post_javascript'], ' |
|
522 |
+ // ]]></script>'; |
|
523 |
+ |
|
524 |
+ if (!empty($context['settings_insert_below'])) |
|
525 |
+ echo $context['settings_insert_below']; |
|
526 |
+ |
|
527 |
+} |
|
528 |
+ |
|
529 |
+/** |
|
530 |
+ * Display the action log. |
|
531 |
+ * |
|
532 |
+ * Little real work is done in this template; mostly is just iterating through the already-processed contents of the action log as done by {@link shd_admin_action_log()}. |
|
533 |
+ * |
|
534 |
+ * @see shd_admin_action_log() |
|
535 |
+ * @since 1.0 |
|
536 |
+*/ |
|
537 |
+function template_shd_action_log() |
|
538 |
+{ |
|
539 |
+ global $settings, $txt, $context, $scripturl, $sort_types, $modSettings; |
|
540 |
+ |
|
541 |
+ // The sort stuff here is huge. |
|
542 |
+ echo ' |
|
543 |
+ <div class="tborder"> |
|
544 |
+ <div class="cat_bar"> |
|
545 |
+ <h3 class="catbg grid_header"> |
|
546 |
+ <span class="floatright smalltext">', $txt['pages'], ': ', $context['page_index'], '</span> |
|
547 |
+ <img src="', $settings['default_images_url'], '/simpledesk/log.png" class="icon" alt="*" /> |
|
548 |
+ ', $txt['shd_admin_actionlog_title'], ' |
|
549 |
+ </h3> |
|
550 |
+ </div> |
|
551 |
+ <table class="shd_ticketlist" cellspacing="0" width="100%"> |
|
552 |
+ <tr class="titlebg"> |
|
553 |
+ <td width="24%" colspan="2"> |
|
554 |
+ <img src="', $settings['default_images_url'], '/simpledesk/action.png" class="shd_smallicon" alt="" /> |
|
555 |
+ <a href="', $scripturl, '?action=admin;area=helpdesk_info;sa=actionlog', $context['sort'] == $sort_types['action'] && !isset($_REQUEST['asc']) ? ';sort=action;asc' : ';sort=action', '"> |
|
556 |
+ ', $txt['shd_admin_actionlog_action'], ' |
|
557 |
+ </a> |
|
558 |
+ ', ($context['sort'] == $sort_types['action'] ? '<img src="' . $settings['default_images_url'] . '/' . (isset($_REQUEST['asc']) ? 'sort_up.gif' : 'sort_down.gif' ). '" alt="" />' : ''), ' |
|
559 |
+ </td> |
|
560 |
+ <td width="20%"> |
|
561 |
+ <img src="', $settings['default_images_url'], '/simpledesk/time.png" class="shd_smallicon" alt="" /> |
|
562 |
+ <a href="', $scripturl, '?action=admin;area=helpdesk_info;sa=actionlog', $context['sort'] == $sort_types['time'] && !isset($_REQUEST['asc']) ? ';sort=time;asc' : ';sort=time', '"> |
|
563 |
+ ', $txt['shd_admin_actionlog_date'], ' |
|
564 |
+ </a> |
|
565 |
+ ', ($context['sort'] == $sort_types['time'] ? '<img src="' . $settings['default_images_url'] . '/' . (isset($_REQUEST['asc']) ? 'sort_up.gif' : 'sort_down.gif' ). '" alt="" />' : ''), ' |
|
566 |
+ </td> |
|
567 |
+ <td width="20%"> |
|
568 |
+ <img src="', $settings['default_images_url'], '/simpledesk/user.png" class="shd_smallicon" alt="" /> |
|
569 |
+ <a href="', $scripturl, '?action=admin;area=helpdesk_info;sa=actionlog', $context['sort'] == $sort_types['member'] && !isset($_REQUEST['asc']) ? ';sort=member;asc' : ';sort=member', '"> |
|
570 |
+ ', $txt['shd_admin_actionlog_member'], ' |
|
571 |
+ </a> |
|
572 |
+ ', ($context['sort'] == $sort_types['member'] ? '<img src="' . $settings['default_images_url'] . '/' . (isset($_REQUEST['asc']) ? 'sort_up.gif' : 'sort_down.gif' ). '" alt="" />' : ''), ' |
|
573 |
+ </td> |
|
574 |
+ <td width="16%"> |
|
575 |
+ <img src="', $settings['default_images_url'], '/simpledesk/position.png" class="shd_smallicon" alt="" /> |
|
576 |
+ <a href="', $scripturl, '?action=admin;area=helpdesk_info;sa=actionlog', $context['sort'] == $sort_types['position'] && !isset($_REQUEST['asc']) ? ';sort=position;asc' : ';sort=position', '"> |
|
577 |
+ ', $txt['shd_admin_actionlog_position'], ' |
|
578 |
+ </a> |
|
579 |
+ ', ($context['sort'] == $sort_types['position'] ? '<img src="' . $settings['default_images_url'] . '/' . (isset($_REQUEST['asc']) ? 'sort_up.gif' : 'sort_down.gif' ). '" alt="" />' : ''), ' |
|
580 |
+ </td> |
|
581 |
+ <td width="20%"> |
|
582 |
+ <img src="', $settings['default_images_url'], '/simpledesk/ip.png" class="shd_smallicon" alt="" /> |
|
583 |
+ <a href="', $scripturl, '?action=admin;area=helpdesk_info;sa=actionlog', $context['sort'] == $sort_types['ip'] && !isset($_REQUEST['asc']) ? ';sort=ip;asc' : ';sort=ip', '"> |
|
584 |
+ ', $txt['shd_admin_actionlog_ip'], ' |
|
585 |
+ </a> |
|
586 |
+ ', ($context['sort'] == $sort_types['ip'] ? '<img src="' . $settings['default_images_url'] . '/' . (isset($_REQUEST['asc']) ? 'sort_up.gif' : 'sort_down.gif' ). '" alt="" />' : ''), ' |
|
587 |
+ </td> |
|
588 |
+ <td width="2%"> </td> |
|
589 |
+ </tr>'; |
|
590 |
+ |
|
591 |
+ if (empty($context['actions'])) |
|
592 |
+ echo ' |
|
593 |
+ <tr class="windowbg2"> |
|
594 |
+ <td colspan="7" class="shd_noticket">', $txt['shd_admin_actionlog_none'], '</td> |
|
595 |
+ </tr>'; |
|
596 |
+ else |
|
597 |
+ { |
|
598 |
+ $use_bg2 = true; // start with windowbg2 to differentiate between that and windowbg2 |
|
599 |
+ foreach ($context['actions'] AS $action) |
|
600 |
+ { |
|
601 |
+ echo ' |
|
602 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
603 |
+ <td width="1%" class="shd_nowrap"> |
|
604 |
+ <img src="', shd_image_url($action['action_icon']), '" alt="" class="shd_smallicon" /> |
|
605 |
+ </td> |
|
606 |
+ <td class="smalltext">', $action['action_text'], '</td> |
|
607 |
+ <td>', $action['time'], '</td> |
|
608 |
+ <td>', $action['member']['link'], '</td> |
|
609 |
+ <td>', $action['member']['group'], '</td> |
|
610 |
+ <td>', !empty($action['member']['ip']) ? $action['member']['ip'] : $txt['shd_admin_actionlog_hidden'], '</td> |
|
611 |
+ <td>', $action['can_remove'] && $context['can_delete'] ? '<a href="' . $scripturl . '?action=admin;area=helpdesk_info;sa=actionlog;remove='. $action['id'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/delete.png" alt="' . $txt['shd_delete_item'] . '" /></a>' : '', '</td> |
|
612 |
+ </tr>'; |
|
613 |
+ |
|
614 |
+ $use_bg2 = !$use_bg2; |
|
615 |
+ } |
|
616 |
+ } |
|
617 |
+ |
|
618 |
+ echo ' |
|
619 |
+ <tr class="titlebg"> |
|
620 |
+ <td colspan="7"> |
|
621 |
+ <span class="floatright smalltext">', $txt['pages'], ': ', $context['page_index'], '</span> |
|
622 |
+ <span class="smalltext shd_empty_log"><img src="', $settings['default_images_url'], '/simpledesk/delete.png" alt="X" /> <a href="', $scripturl, '?action=admin;area=helpdesk_info;sa=actionlog', $context['url_sort'], $context['url_order'], ';removeall" onclick="return confirm(', JavaScriptEscape(sprintf($txt['shd_admin_actionlog_removeall_confirm'],$context['hoursdisable'])), ');">', $txt['shd_admin_actionlog_removeall'], '</a></span> |
|
623 |
+ </td> |
|
624 |
+ </tr> |
|
625 |
+ </table> |
|
626 |
+ </div>'; |
|
627 |
+} |
|
628 |
+ |
|
629 |
+/** |
|
630 |
+ * Displays the get-support form for posting directly to the SimpleDesk support board. |
|
631 |
+ * |
|
632 |
+ * This is little more than a simple HTML form, most of the real work is hidden behind the scenes in SimpleDesk's own site. |
|
633 |
+ * |
|
634 |
+ * @see shd_admin_support() |
|
635 |
+ * @since 1.0 |
|
636 |
+*/ |
|
637 |
+function template_shd_support() |
|
638 |
+{ |
|
639 |
+ global $context, $settings, $txt, $forum_version; |
|
640 |
+ |
|
641 |
+ echo ' |
|
642 |
+ <div class="shd_admin_leftcolumn floatleft"> |
|
643 |
+ <div class="tborder"> |
|
644 |
+ <div class="cat_bar"> |
|
645 |
+ <h3 class="catbg grid_header"> |
|
646 |
+ <img src="', $settings['default_images_url'], '/simpledesk/edit.png" alt="*" /> ', $txt['shd_admin_support_form_title'], ' |
|
647 |
+ </h3> |
|
648 |
+ </div> |
|
649 |
+ <div class="roundframe"> |
|
650 |
+ <form action="', $context['shd_support_url'], '" method="post" class="content"> |
|
651 |
+ <dl id="post_header"> |
|
652 |
+ <dt><span id="caption_subject">', $txt['subject'], '</span></dt> |
|
653 |
+ <dd><input type="text" name="subject" tabindex="1" size="80" maxlength="80" class="input_text" /></dd> |
|
654 |
+ </dl> |
|
655 |
+ <textarea class="editor" name="message" rows="12" cols="60" tabindex="2" style="width: 90%; height: 150px;"></textarea> |
|
656 |
+ <br /><br /> |
|
657 |
+ <input type="hidden" value="', $forum_version, '" name="smf_version" /> |
|
658 |
+ <input type="hidden" value="', SHD_VERSION, '" name="shd_version" /> |
|
659 |
+ <input type="submit" value="', $txt['shd_admin_support_send'], '" tabindex="3" accesskey="s" class="button_submit" /> |
|
660 |
+ </form> |
|
661 |
+ </div> |
|
662 |
+ <span class="lowerframe"><span></span></span> |
|
663 |
+ </div> |
|
664 |
+ </div> |
|
665 |
+ <div class="shd_admin_rightcolumn floatleft"> |
|
666 |
+ <div class="tborder"> |
|
667 |
+ <div class="title_bar"> |
|
668 |
+ <h3 class="titlebg sd_no_margin grid_header"> |
|
669 |
+ <img src="', $settings['images_url'], '/helptopics.gif" alt="?" /> ', $txt['shd_admin_support_what_is_this'], ' |
|
670 |
+ </h3> |
|
671 |
+ </div> |
|
672 |
+ <div class="windowbg2"> |
|
673 |
+ <div class="content smalltext"> |
|
674 |
+ ', $txt['shd_admin_support_explanation'], ' |
|
675 |
+ </div> |
|
676 |
+ <span class="botslice"><span></span></span> |
|
677 |
+ </div> |
|
678 |
+ </div> |
|
679 |
+ </div> |
|
680 |
+ <br class="clear" />'; |
|
681 |
+} |
|
682 |
+ |
|
683 |
+?> |
|
0 | 684 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,193 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk's administration/custom fields area |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * Displays SimpleDesk's administration for custom fields. |
|
6 |
+ * |
|
7 |
+ * @package template |
|
8 |
+ * @since 1.0 |
|
9 |
+*/ |
|
10 |
+ |
|
11 |
+function template_shd_custom_field_home() |
|
12 |
+{ |
|
13 |
+ global $context, $settings, $txt, $modSettings, $scripturl; |
|
14 |
+ |
|
15 |
+ echo ' |
|
16 |
+ <div class="tborder"> |
|
17 |
+ <div class="cat_bar"> |
|
18 |
+ <h3 class="catbg grid_header"> |
|
19 |
+ <img src="', $settings['default_images_url'], '/simpledesk/custom_fields.png" class="icon" alt="*" /> |
|
20 |
+ ', $txt['shd_admin_custom_fields_long'], ' |
|
21 |
+ </h3> |
|
22 |
+ </div> |
|
23 |
+ <p class="description shd_actionloginfo"> |
|
24 |
+ ', $txt['shd_admin_custom_fields_desc'], ' |
|
25 |
+ </p> |
|
26 |
+ <table class="shd_ticketlist" cellspacing="0" width="100%"> |
|
27 |
+ <tr class="titlebg"> |
|
28 |
+ <td width="30%" colspan="2"> |
|
29 |
+ <img src="', $settings['default_images_url'], '/simpledesk/custom_fields.png" class="icon" alt="*" /> |
|
30 |
+ ', $txt['shd_admin_custom_fields_fieldname'], ' |
|
31 |
+ </td> |
|
32 |
+ <td colspan="2"> |
|
33 |
+ <img src="', $settings['default_images_url'], '/simpledesk/fieldtype.png" class="icon" alt="*" /> |
|
34 |
+ ', $txt['shd_admin_custom_fields_fieldtype'], ' |
|
35 |
+ </td> |
|
36 |
+ <td>', $txt['shd_admin_custom_fields_active'], '</td> |
|
37 |
+ <td>', $txt['shd_admin_custom_fields_visible'], '</td> |
|
38 |
+ <td colspan="2" width="1%" class="shd_nowrap">', $txt['shd_admin_custom_fields_move'], '</td> |
|
39 |
+ <td class="shd_nowrap"> |
|
40 |
+ <img src="', $settings['default_images_url'], '/simpledesk/edit.png" class="icon" alt="*" /> |
|
41 |
+ ', $txt['shd_ticket_edit'], ' |
|
42 |
+ </td> |
|
43 |
+ </tr>'; |
|
44 |
+ |
|
45 |
+ if (empty($context['custom_fields'])) |
|
46 |
+ echo ' |
|
47 |
+ <tr class="windowbg2"> |
|
48 |
+ <td colspan="9">', $txt['shd_admin_no_custom_fields'], '</td> |
|
49 |
+ </tr>'; |
|
50 |
+ else |
|
51 |
+ { |
|
52 |
+ $use_bg2 = true; |
|
53 |
+ foreach ($context['custom_fields'] as $field) |
|
54 |
+ { |
|
55 |
+ echo ' |
|
56 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
57 |
+ <td>', empty($field['icon']) ? '' : '<img src="' . $settings['default_images_url'] . '/simpledesk/cf/' . $field['icon'] . '.png" class="icon" alt="*" />', '</td> |
|
58 |
+ <td>', $field['field_name'], '</td> |
|
59 |
+ <td><img src="' . $settings['default_images_url'] . '/simpledesk/cf_ui_' . $field['field_type'] . '.png" class="icon" alt="', $txt['shd_admin_custom_fields_ui_' . $field['field_type']], '" /></td> |
|
60 |
+ <td>', $txt['shd_admin_custom_fields_ui_' . $field['field_type']], '</td> |
|
61 |
+ <td><img src="', $settings['default_images_url'], '/simpledesk/cf_', $field['active_string'], '.png" alt="', $txt['shd_admin_custom_fields_' . $field['active_string']], '" title="', $txt['shd_admin_custom_fields_' . $field['active_string']], '" /></td> |
|
62 |
+ <td class="shd_nowrap"> |
|
63 |
+ ', ($field['field_loc'] & CFIELD_TICKET) !== 0 ? ('<img src="' . $settings['default_images_url'] . '/simpledesk/ticket.png" alt="' . $txt['shd_admin_custom_fields_inticket'] . '" title="' . $txt['shd_admin_custom_fields_inticket'] . '" />') : '', ' |
|
64 |
+ ', ($field['field_loc'] & CFIELD_REPLY) !== 0 ? ('<img src="' . $settings['default_images_url'] . '/simpledesk/replies.png" alt="' . $txt['shd_admin_custom_fields_inreply'] . '" title="' . $txt['shd_admin_custom_fields_inreply'] . '" />') : '', ' |
|
65 |
+ </td> |
|
66 |
+ <td>', empty($field['is_first']) ? ('<a href="' . $scripturl . '?action=admin;area=helpdesk_customfield;sa=move;field=' . $field['id_field'] . ';direction=up;' . $context['session_var'] . '=' . $context['session_id'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/move_up.png" alt="' . $txt['shd_admin_move_up'] . '" title="' . $txt['shd_admin_move_up'] . '" /></a>') : '', '</td> |
|
67 |
+ <td>', empty($field['is_last']) ? ('<a href="' . $scripturl . '?action=admin;area=helpdesk_customfield;sa=move;field=' . $field['id_field'] . ';direction=down;' . $context['session_var'] . '=' . $context['session_id'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/move_down.png" alt="' . $txt['shd_admin_move_down'] . '" title="' . $txt['shd_admin_move_down'] . '" /></a>') : '', '</td> |
|
68 |
+ <td><a href="', $scripturl, '?action=admin;area=helpdesk_customfield;sa=edit;field=', $field['id_field'], ';', $context['session_var'], ';', $context['session_id'], '">', $txt['shd_ticket_edit'], '</a></td> |
|
69 |
+ </tr>'; |
|
70 |
+ |
|
71 |
+ $use_bg2 = !$use_bg2; |
|
72 |
+ } |
|
73 |
+ } |
|
74 |
+ |
|
75 |
+ echo ' |
|
76 |
+ </table> |
|
77 |
+ <div class="flow_auto"> |
|
78 |
+ <div class="floatright"> |
|
79 |
+ <div class="additional_row">[<a href="', $scripturl, '?action=admin;area=helpdesk_customfield;sa=new">', $txt['shd_admin_new_custom_field'], '</a>]</div> |
|
80 |
+ </div> |
|
81 |
+ </div> |
|
82 |
+ </div>'; |
|
83 |
+} |
|
84 |
+ |
|
85 |
+function template_shd_custom_field_edit() |
|
86 |
+{ |
|
87 |
+ global $context, $settings, $txt, $modSettings, $scripturl; |
|
88 |
+ |
|
89 |
+ echo ' |
|
90 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
91 |
+ function set_fieldicon(filename) |
|
92 |
+ { |
|
93 |
+ document.getElementById("cf_fieldicon_icon").style.background = "url(" + ', JavaScriptEscape($settings['default_images_url'] . '/simpledesk/'), ' + filename + ") no-repeat left"; |
|
94 |
+ } |
|
95 |
+ function set_fieldtype_icon(ftype) |
|
96 |
+ { |
|
97 |
+ var icons = new Array();'; |
|
98 |
+ foreach ($context['field_types'] as $field => $details) |
|
99 |
+ { |
|
100 |
+ list($field_desc, $class) = $details; |
|
101 |
+ echo ' |
|
102 |
+ icons[', $field, '] = ', JavaScriptEscape('cf_ui_' . $class), ';'; |
|
103 |
+ } |
|
104 |
+ |
|
105 |
+ echo ' |
|
106 |
+ document.getElementById("cf_fieldtype_icon").setAttribute("class", icons[ftype]); |
|
107 |
+ } |
|
108 |
+ // ]', ']></script> |
|
109 |
+ <div class="tborder"> |
|
110 |
+ <div class="cat_bar"> |
|
111 |
+ <h3 class="catbg"> |
|
112 |
+ <img src="', $settings['default_images_url'], '/simpledesk/custom_fields.png" class="icon" alt="*" /> |
|
113 |
+ ', $context['page_title'], ' |
|
114 |
+ </h3> |
|
115 |
+ </div> |
|
116 |
+ <p class="description"> |
|
117 |
+ ', $txt['shd_admin_custom_fields_desc'], ' |
|
118 |
+ </p> |
|
119 |
+ </div> |
|
120 |
+ <div class="cat_bar"> |
|
121 |
+ <h3 class="catbg grid_header"> |
|
122 |
+ <img src="', $settings['default_images_url'], '/simpledesk/description.png" alt="*" /> |
|
123 |
+ ', $txt['shd_admin_custom_fields_general'], ' |
|
124 |
+ </h3> |
|
125 |
+ </div> |
|
126 |
+ <div class="roundframe"> |
|
127 |
+ <div class="content"> |
|
128 |
+ <dl class="settings"> |
|
129 |
+ <dt><strong>', $txt['shd_admin_custom_fields_fieldname'], ':</strong></dt> |
|
130 |
+ <dd><input type="text" name="fieldname" id="cf_fieldname" value="" class="input_text" size="30" /></dd> |
|
131 |
+ <dt><strong>', $txt['shd_admin_custom_fields_active'], ':</strong></dt> |
|
132 |
+ <dd><input type="checkbox" name="active" id="cf_active" value="1" class="input_check" /></dd> |
|
133 |
+ <dt><strong>', $txt['shd_admin_custom_fields_icon'], ':</strong></dt> |
|
134 |
+ <dd class="nowrap"> |
|
135 |
+ <span id="cf_fieldicon_icon"></span> |
|
136 |
+ <select name="cf_fieldicon" id="cf_fieldicon" onchange="javascript:set_fieldicon(this.value);">'; |
|
137 |
+ |
|
138 |
+ foreach ($context['field_icons'] as $icon) |
|
139 |
+ { |
|
140 |
+ list($file, $desc) = $icon; |
|
141 |
+ $path = $settings['default_theme_dir'] . '/images/simpledesk/' . $file; |
|
142 |
+ echo ' |
|
143 |
+ <option value="', $file, '">', $desc, '</option>'; |
|
144 |
+ } |
|
145 |
+ |
|
146 |
+ echo ' |
|
147 |
+ </select> |
|
148 |
+ </dd> |
|
149 |
+ <dt><strong>', $txt['shd_admin_custom_fields_visible'], ':</strong></dt> |
|
150 |
+ <dd> |
|
151 |
+ <span id="cf_fieldvisible_icon"></span> |
|
152 |
+ <select name="cf_fieldvisible" id="cf_fieldvisible"> |
|
153 |
+ <option value="', CFIELD_TICKET, '">', $txt['shd_admin_custom_fields_visible_ticket'], '</option> |
|
154 |
+ <option value="', CFIELD_REPLY, '">', $txt['shd_admin_custom_fields_visible_field'], '</option> |
|
155 |
+ <option value="', (CFIELD_TICKET | CFIELD_REPLY), '">', $txt['shd_admin_custom_fields_visible_both'], '</option> |
|
156 |
+ </select> |
|
157 |
+ </dd> |
|
158 |
+ </dl> |
|
159 |
+ </div> |
|
160 |
+ </div> |
|
161 |
+ <span class="lowerframe"><span></span></span> |
|
162 |
+ <br /> |
|
163 |
+ <div class="cat_bar"> |
|
164 |
+ <h3 class="catbg grid_header"> |
|
165 |
+ <img src="', $settings['default_images_url'], '/simpledesk/fieldtype.png" alt="*" /> |
|
166 |
+ ', $txt['shd_admin_custom_fields_fieldtype'], ' |
|
167 |
+ </h3> |
|
168 |
+ </div> |
|
169 |
+ <div class="roundframe"> |
|
170 |
+ <div class="content"> |
|
171 |
+ <dl class="settings"> |
|
172 |
+ <dt><strong>', $txt['shd_admin_custom_fields_fieldtype'], ':</strong></dt> |
|
173 |
+ <dd class="shd_nowrap"> |
|
174 |
+ <span id="cf_fieldtype_icon" class="cf_ui_', $context['field_types'][$context['field_type_value']][1], '"></span> |
|
175 |
+ <select name="cf_fieldtype" id="cf_fieldtype" onchange="javascript:set_fieldtype_icon(this.value);">'; |
|
176 |
+ |
|
177 |
+ foreach ($context['field_types'] as $field => $details) |
|
178 |
+ { |
|
179 |
+ list($field_desc, $class) = $details; |
|
180 |
+ echo ' |
|
181 |
+ <option value="', $field, '"', ($context['field_type_value'] == $field ? ' selected="selected"' : ''), '>', $field_desc, '</option>'; |
|
182 |
+ } |
|
183 |
+ |
|
184 |
+ echo ' |
|
185 |
+ </select> |
|
186 |
+ </dd> |
|
187 |
+ </dl> |
|
188 |
+ </div> |
|
189 |
+ </div> |
|
190 |
+ <span class="lowerframe"><span></span></span>'; |
|
191 |
+} |
|
192 |
+ |
|
193 |
+?> |
|
0 | 194 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,525 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk's administration/permissions area |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * Displays SimpleDesk's administration for permissions - front page, listing the templates and known defined roles. |
|
6 |
+ * |
|
7 |
+ * @package template |
|
8 |
+ * @since 1.1 |
|
9 |
+*/ |
|
10 |
+ |
|
11 |
+/** |
|
12 |
+ * Display the front page of the SimpleDesk permissions area. |
|
13 |
+ * |
|
14 |
+ * @since 1.1 |
|
15 |
+*/ |
|
16 |
+function template_shd_permissions_home() |
|
17 |
+{ |
|
18 |
+ global $context, $settings, $txt, $modSettings, $scripturl; |
|
19 |
+ |
|
20 |
+ echo ' |
|
21 |
+ <div class="tborder"> |
|
22 |
+ <div class="cat_bar"> |
|
23 |
+ <h3 class="catbg"> |
|
24 |
+ <img src="', $settings['default_images_url'], '/simpledesk/permissions.png" class="icon" alt="*" /> |
|
25 |
+ ', $txt['shd_admin_permissions'], ' |
|
26 |
+ </h3> |
|
27 |
+ </div> |
|
28 |
+ <p class="description"> |
|
29 |
+ ', $txt['shd_admin_permissions_homedesc'], ' |
|
30 |
+ </p> |
|
31 |
+ </div> |
|
32 |
+ <div class="tborder"> |
|
33 |
+ <div class="title_bar"> |
|
34 |
+ <h3 class="titlebg sd_no_margin grid_header"> |
|
35 |
+ <img src="', $settings['default_images_url'], '/simpledesk/position.png" alt="*" /> |
|
36 |
+ ', $txt['shd_role_templates'], ' |
|
37 |
+ </h3> |
|
38 |
+ </div> |
|
39 |
+ <p class="description shd_actionloginfo"> |
|
40 |
+ ', $txt['shd_role_templates_desc'], ' |
|
41 |
+ </p> |
|
42 |
+ <table class="shd_ticketlist" cellspacing="0" width="100%"> |
|
43 |
+ <tr class="titlebg"> |
|
44 |
+ <td colspan="2" width="30%">', $txt['shd_role'], '</td> |
|
45 |
+ <td colspan="', count($context['shd_permissions']['group_display']), '">', $txt['shd_permissions'], '</td> |
|
46 |
+ </tr>'; |
|
47 |
+ |
|
48 |
+ $use_bg2 = true; |
|
49 |
+ foreach ($context['shd_permissions']['roles'] as $role_id => $role_details) |
|
50 |
+ { |
|
51 |
+ echo ' |
|
52 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
53 |
+ <td>', !empty($role_details['icon']) ? ('<img src="' . $settings['default_images_url'] . '/simpledesk/' . $role_details['icon'] . '" alt="" />') : '', '</td> |
|
54 |
+ <td> |
|
55 |
+ ', $txt[$role_details['description']], ' |
|
56 |
+ <div class="smalltext">[<a href="', $scripturl, '?action=admin;area=helpdesk_permissions;sa=createrole;template=', $role_id, '">', $txt['shd_create_role'], '</a>]</div> |
|
57 |
+ </td> |
|
58 |
+ ', template_shd_display_permission_list($role_details['permissions']), ' |
|
59 |
+ </tr>'; |
|
60 |
+ |
|
61 |
+ $use_bg2 = !$use_bg2; |
|
62 |
+ } |
|
63 |
+ |
|
64 |
+ echo ' |
|
65 |
+ </table> |
|
66 |
+ </div> |
|
67 |
+ <br /><br /> |
|
68 |
+ <div class="tborder"> |
|
69 |
+ <div class="title_bar"> |
|
70 |
+ <h3 class="titlebg sd_no_margin grid_header"> |
|
71 |
+ <img src="', $settings['default_images_url'], '/simpledesk/roles.png" alt="*" /> |
|
72 |
+ ', $txt['shd_roles'], ' |
|
73 |
+ </h3> |
|
74 |
+ </div> |
|
75 |
+ <p class="description shd_actionloginfo"> |
|
76 |
+ ', $txt['shd_roles_desc'], ' |
|
77 |
+ </p> |
|
78 |
+ <table class="shd_ticketlist" cellspacing="0" width="100%"> |
|
79 |
+ <tr class="titlebg"> |
|
80 |
+ <td colspan="2" width="20%">', $txt['shd_role'], '</td> |
|
81 |
+ <td colspan="', count($context['shd_permissions']['group_display']), '">', $txt['shd_permissions'], '</td> |
|
82 |
+ <td width="20%">', $txt['shd_membergroups'], '</td> |
|
83 |
+ </tr>'; |
|
84 |
+ |
|
85 |
+ if (empty($context['shd_permissions']['user_defined_roles'])) |
|
86 |
+ { |
|
87 |
+ echo ' |
|
88 |
+ <tr class="windowbg"> |
|
89 |
+ <td colspan="', count($context['shd_permissions']['group_display']) + 3, '" class="centertext">', $txt['shd_no_defined_roles'], '</td> |
|
90 |
+ </tr>'; |
|
91 |
+ } |
|
92 |
+ else |
|
93 |
+ { |
|
94 |
+ $use_bg2 = true; |
|
95 |
+ foreach ($context['shd_permissions']['user_defined_roles'] as $role => $role_details) |
|
96 |
+ { |
|
97 |
+ echo ' |
|
98 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
99 |
+ <td>', !empty($role_details['template_icon']) ? ('<img src="' . $settings['default_images_url'] . '/simpledesk/' . $role_details['template_icon'] . '" alt="" title="' . sprintf($txt['shd_based_on'], $role_details['template_name']) . '" />') : '', '</td> |
|
100 |
+ <td> |
|
101 |
+ ', $role_details['name'], ' |
|
102 |
+ <div class="smalltext"> |
|
103 |
+ [<a href="', $scripturl, '?action=admin;area=helpdesk_permissions;sa=editrole;role=', $role, '">', $txt['shd_edit_role'], '</a>] |
|
104 |
+ [<a href="', $scripturl, '?action=admin;area=helpdesk_permissions;sa=copyrole;role=', $role, '">', $txt['shd_copy_role'], '</a>] |
|
105 |
+ </div> |
|
106 |
+ </td> |
|
107 |
+ ', template_shd_display_permission_list($role_details['permissions']); |
|
108 |
+ if (empty($role_details['groups'])) |
|
109 |
+ echo ' |
|
110 |
+ <td>', $txt['shd_none'], '</td>'; |
|
111 |
+ else |
|
112 |
+ { |
|
113 |
+ $array = array(); |
|
114 |
+ foreach ($role_details['groups'] as $group => $group_details) |
|
115 |
+ $array[] = $group_details['link']; |
|
116 |
+ echo ' |
|
117 |
+ <td>', implode(', ', $array), '</td>'; |
|
118 |
+ } |
|
119 |
+ |
|
120 |
+ echo ' |
|
121 |
+ </tr>'; |
|
122 |
+ $use_bg2 = !$use_bg2; |
|
123 |
+ } |
|
124 |
+ } |
|
125 |
+ |
|
126 |
+ echo ' |
|
127 |
+ </table> |
|
128 |
+ </div>'; |
|
129 |
+} |
|
130 |
+ |
|
131 |
+/** |
|
132 |
+ * Display the list of icons for a role's permissions. |
|
133 |
+ * |
|
134 |
+ * @param array $permissions An array listing the permissions a given role has. |
|
135 |
+ * @since 1.1 |
|
136 |
+*/ |
|
137 |
+function template_shd_display_permission_list($permissions) |
|
138 |
+{ |
|
139 |
+ global $context, $txt, $settings; |
|
140 |
+ $permission_set = array(); |
|
141 |
+ |
|
142 |
+ foreach ($context['shd_permissions']['permission_list'] as $permission => $details) |
|
143 |
+ { |
|
144 |
+ list($ownany, $group, $icon) = $details; |
|
145 |
+ if (empty($icon)) |
|
146 |
+ continue; |
|
147 |
+ |
|
148 |
+ if (empty($permission_set[$group])) |
|
149 |
+ $permission_set[$group] = array(); |
|
150 |
+ |
|
151 |
+ $permtitle = ''; |
|
152 |
+ |
|
153 |
+ if($ownany) |
|
154 |
+ { |
|
155 |
+ if ((!empty($permissions[$permission . '_any']) && ($permissions[$permission . '_any'] == ROLEPERM_ALLOW)) || (!empty($permissions[$permission . '_own']) && ($permissions[$permission . '_own'] == ROLEPERM_ALLOW))) |
|
156 |
+ { |
|
157 |
+ $permtitle = empty($txt['permissionname_' . $permission]) ? '' : $txt['permissionname_' . $permission] . ' ('; |
|
158 |
+ if (!empty($permissions[$permission . '_any']) && $permissions[$permission . '_any'] == ROLEPERM_ALLOW) |
|
159 |
+ $permtitle .= $txt['permissionname_' . $permission . '_any']; |
|
160 |
+ elseif (!empty($permissions[$permission . '_own']) && $permissions[$permission . '_own'] == ROLEPERM_ALLOW) |
|
161 |
+ $permtitle .= $txt['permissionname_' . $permission . '_own']; |
|
162 |
+ |
|
163 |
+ $permtitle .= ')'; |
|
164 |
+ } |
|
165 |
+ } |
|
166 |
+ else |
|
167 |
+ { |
|
168 |
+ if (!empty($permissions[$permission]) && $permissions[$permission] == ROLEPERM_ALLOW) |
|
169 |
+ $permtitle = empty($txt['permissionname_' . $permission]) ? '' : $txt['permissionname_' . $permission]; |
|
170 |
+ } |
|
171 |
+ |
|
172 |
+ if (!empty($permtitle)) |
|
173 |
+ $permission_set[$group][] = '<img src="' . shd_image_url($icon) . '" alt="" title="' . $permtitle . '" />'; |
|
174 |
+ } |
|
175 |
+ |
|
176 |
+ foreach ($context['shd_permissions']['group_display'] as $cell => $rows) |
|
177 |
+ { |
|
178 |
+ echo ' |
|
179 |
+ <td class="shd_valign_top">'; |
|
180 |
+ |
|
181 |
+ foreach ($rows as $rowitem => $rowicon) |
|
182 |
+ { |
|
183 |
+ if (!empty($permission_set[$rowitem])) |
|
184 |
+ echo $txt['shd_permgroup_short_' . $rowitem], ': ', implode(' ', $permission_set[$rowitem]), '<br />'; |
|
185 |
+ } |
|
186 |
+ |
|
187 |
+ echo '</td>'; |
|
188 |
+ } |
|
189 |
+} |
|
190 |
+ |
|
191 |
+/** |
|
192 |
+ * Display the form to create a new role. |
|
193 |
+ * |
|
194 |
+ * @since 1.1 |
|
195 |
+*/ |
|
196 |
+function template_shd_create_role() |
|
197 |
+{ |
|
198 |
+ global $context, $settings, $txt, $modSettings, $scripturl; |
|
199 |
+ |
|
200 |
+ echo ' |
|
201 |
+ <div class="tborder"> |
|
202 |
+ <div class="cat_bar"> |
|
203 |
+ <h3 class="catbg"> |
|
204 |
+ <img src="', $settings['default_images_url'], '/simpledesk/permissions.png" class="icon" alt="*" /> |
|
205 |
+ ', $txt['shd_admin_permissions'], ' |
|
206 |
+ </h3> |
|
207 |
+ </div> |
|
208 |
+ <p class="description"> |
|
209 |
+ ', $txt['shd_admin_permissions_homedesc'], ' |
|
210 |
+ </p> |
|
211 |
+ </div> |
|
212 |
+ <div class="cat_bar"> |
|
213 |
+ <h3 class="catbg grid_header"> |
|
214 |
+ <img src="', $settings['default_images_url'], '/simpledesk/position.png" alt="*" /> |
|
215 |
+ ', $txt['shd_create_role'], ' |
|
216 |
+ </h3> |
|
217 |
+ </div> |
|
218 |
+ <div class="roundframe"> |
|
219 |
+ <form action="', $scripturl, '?action=admin;area=helpdesk_permissions;sa=createrole;part=2" method="post"> |
|
220 |
+ <div class="content"> |
|
221 |
+ <dl class="settings"> |
|
222 |
+ <dt><strong>', $txt['shd_create_based_on'], ':</strong></dt> |
|
223 |
+ <dd> |
|
224 |
+ <img alt="*" src="', $settings['default_images_url'], '/simpledesk/', $context['shd_permissions']['roles'][$_REQUEST['template']]['icon'], '" /> |
|
225 |
+ ', $txt[$context['shd_permissions']['roles'][$_REQUEST['template']]['description']], ' |
|
226 |
+ </dd> |
|
227 |
+ <dt><strong>', $txt['shd_create_name'], '</strong></dt> |
|
228 |
+ <dd><input type="text" name="rolename" id="rolename" value="" class="input_text" size="30" /></dd> |
|
229 |
+ </dl> |
|
230 |
+ </div> |
|
231 |
+ <input type="submit" value="', $txt['shd_create_role'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" /> |
|
232 |
+ <input type="hidden" name="template" value="', $_REQUEST['template'], '" /> |
|
233 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
234 |
+ <input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" /> |
|
235 |
+ </form> |
|
236 |
+ </div> |
|
237 |
+ <span class="lowerframe"><span></span></span>'; |
|
238 |
+} |
|
239 |
+ |
|
240 |
+/** |
|
241 |
+ * Display the form to edit a role's permissions and settings. |
|
242 |
+ * |
|
243 |
+ * @since 1.1 |
|
244 |
+*/ |
|
245 |
+function template_shd_edit_role() |
|
246 |
+{ |
|
247 |
+ global $context, $settings, $txt, $modSettings, $scripturl; |
|
248 |
+ |
|
249 |
+ // This is to shortcut settings for the role we want. |
|
250 |
+ $role = &$context['shd_permissions']['user_defined_roles'][$_REQUEST['role']]; |
|
251 |
+ |
|
252 |
+ // Start the page off, including the rename-role bit. |
|
253 |
+ echo ' |
|
254 |
+ <div class="tborder"> |
|
255 |
+ <div class="cat_bar"> |
|
256 |
+ <h3 class="catbg"> |
|
257 |
+ <img src="', $settings['default_images_url'], '/simpledesk/permissions.png" class="icon" alt="*" /> |
|
258 |
+ ', $txt['shd_admin_permissions'], ' |
|
259 |
+ </h3> |
|
260 |
+ </div> |
|
261 |
+ <p class="description"> |
|
262 |
+ ', $txt['shd_admin_permissions_homedesc'], ' |
|
263 |
+ </p> |
|
264 |
+ </div> |
|
265 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
266 |
+ function shd_chicon(obj) |
|
267 |
+ { |
|
268 |
+ var sSelect = document.getElementById(obj.id).value; |
|
269 |
+ var newClass = ""; |
|
270 |
+ switch(sSelect) |
|
271 |
+ { |
|
272 |
+ case "disallow": |
|
273 |
+ newClass = "shd_no"; break; |
|
274 |
+ case "allow": |
|
275 |
+ newClass = "shd_yes"; break; |
|
276 |
+ case "allow_own": |
|
277 |
+ newClass = "shd_own"; break; |
|
278 |
+ case "allow_any": |
|
279 |
+ newClass = "shd_any"; break; |
|
280 |
+ default: |
|
281 |
+ newClass = ""; break; |
|
282 |
+ } |
|
283 |
+ document.getElementById(obj.id + "_icon").setAttribute("class", newClass); |
|
284 |
+ } |
|
285 |
+ |
|
286 |
+ function shd_toggleblock(block) |
|
287 |
+ { |
|
288 |
+ var collapsed = (document.getElementById("permheader_" + block).getAttribute("class") == "catbg"); |
|
289 |
+ if (collapsed) |
|
290 |
+ { |
|
291 |
+ document.getElementById("permheader_" + block).setAttribute("class", "catbg grid_header"); |
|
292 |
+ document.getElementById("permcontent_" + block).style.display = ""; |
|
293 |
+ document.getElementById("permfooter_" + block).style.display = ""; |
|
294 |
+ document.getElementById("permexpandicon_" + block).src = ', JavaScriptEscape($settings['images_url'] . '/collapse.gif'), '; |
|
295 |
+ } |
|
296 |
+ else |
|
297 |
+ { |
|
298 |
+ document.getElementById("permheader_" + block).setAttribute("class", "catbg"); |
|
299 |
+ document.getElementById("permcontent_" + block).style.display = "none"; |
|
300 |
+ document.getElementById("permfooter_" + block).style.display = "none"; |
|
301 |
+ document.getElementById("permexpandicon_" + block).src = ', JavaScriptEscape($settings['images_url'] . '/expand.gif'), '; |
|
302 |
+ } |
|
303 |
+ } |
|
304 |
+ |
|
305 |
+ // ]', ']></script> |
|
306 |
+ <form action="', $scripturl, '?action=admin;area=helpdesk_permissions;sa=saverole" method="post"> |
|
307 |
+ <div class="cat_bar"> |
|
308 |
+ <h3 class="catbg grid_header"> |
|
309 |
+ <img src="', $settings['default_images_url'], '/simpledesk/position.png" alt="*" /> |
|
310 |
+ ', $txt['shd_edit_role'], ' |
|
311 |
+ </h3> |
|
312 |
+ </div> |
|
313 |
+ <div class="roundframe"> |
|
314 |
+ <div class="content"> |
|
315 |
+ <dl class="settings"> |
|
316 |
+ <dt><strong>', $txt['shd_is_based_on'], ':</strong></dt> |
|
317 |
+ <dd> |
|
318 |
+ <img alt="*" src="', $settings['default_images_url'], '/simpledesk/', $role['template_icon'], '" /> |
|
319 |
+ ', $role['template_name'], ' |
|
320 |
+ </dd> |
|
321 |
+ <dt><strong>', $txt['shd_role_name'], ':</strong></dt> |
|
322 |
+ <dd><input type="text" name="rolename" id="rolename" value="', $role['name'], '" class="input_text" size="30" /></dd> |
|
323 |
+ </dl> |
|
324 |
+ </div> |
|
325 |
+ </div> |
|
326 |
+ <span class="lowerframe"><span></span></span> |
|
327 |
+ <br />'; |
|
328 |
+ |
|
329 |
+ // Get ready to display the actual permissions |
|
330 |
+ $permission_set = array(); |
|
331 |
+ foreach ($context['shd_permissions']['permission_list'] as $permission => $details) |
|
332 |
+ { |
|
333 |
+ if (!empty($details[2])) |
|
334 |
+ $permission_set[$details[1]][] = $permission; |
|
335 |
+ } |
|
336 |
+ |
|
337 |
+ foreach ($context['shd_permissions']['group_display'] as $cell => $rows) |
|
338 |
+ { |
|
339 |
+ echo ' |
|
340 |
+ <div class="', ($cell == 0 ? 'floatleft' : 'floatright'), '" style="width: 49%">'; |
|
341 |
+ |
|
342 |
+ foreach ($rows as $rowitem => $rowicon) |
|
343 |
+ { |
|
344 |
+ if (empty($permission_set[$rowitem])) |
|
345 |
+ continue; |
|
346 |
+ |
|
347 |
+ echo ' |
|
348 |
+ <div class="cat_bar"> |
|
349 |
+ <h3 class="catbg" id="permheader_', $rowitem, '"> |
|
350 |
+ <span class="floatright"> |
|
351 |
+ <a class="permcollapse" href="javascript:shd_toggleblock(\'', $rowitem, '\');"> |
|
352 |
+ <img src="', $settings['images_url'], '/expand.gif" id="permexpandicon_', $rowitem, '" /> |
|
353 |
+ </a> |
|
354 |
+ </span> |
|
355 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $rowicon, '" alt="*" /> |
|
356 |
+ <a href="javascript:shd_toggleblock(\'', $rowitem, '\');">', $txt['shd_permgroup_' . $rowitem], '</a> |
|
357 |
+ </h3> |
|
358 |
+ </div> |
|
359 |
+ <div class="roundframe" id="permcontent_', $rowitem, '" style="display:none;"> |
|
360 |
+ <div class="content"> |
|
361 |
+ <dl class="permsettings">'; |
|
362 |
+ |
|
363 |
+ foreach ($permission_set[$rowitem] as $permission) |
|
364 |
+ { |
|
365 |
+ list($ownany, $group, $icon) = $context['shd_permissions']['permission_list'][$permission]; |
|
366 |
+ |
|
367 |
+ // And what exactly are we displaying as the current? |
|
368 |
+ if ($ownany) |
|
369 |
+ { |
|
370 |
+ if (!empty($role['permissions'][$permission . '_any']) && $role['permissions'][$permission . '_any'] == ROLEPERM_ALLOW) |
|
371 |
+ list($perm_class, $perm_value) = array('shd_any', 'allow_any'); |
|
372 |
+ elseif (!empty($role['permissions'][$permission . '_own']) && $role['permissions'][$permission . '_own'] == ROLEPERM_ALLOW) |
|
373 |
+ list($perm_class, $perm_value) = array('shd_own', 'allow_own'); |
|
374 |
+ else |
|
375 |
+ list($perm_class, $perm_value) = array('shd_no', 'disallow'); |
|
376 |
+ } |
|
377 |
+ else |
|
378 |
+ { |
|
379 |
+ if (empty($role['permissions'][$permission])) |
|
380 |
+ list($perm_class, $perm_value) = array('shd_no', 'disallow'); |
|
381 |
+ elseif ($role['permissions'][$permission] == ROLEPERM_ALLOW) |
|
382 |
+ list($perm_class, $perm_value) = array('shd_yes', 'allow'); |
|
383 |
+ } |
|
384 |
+ |
|
385 |
+ echo ' |
|
386 |
+ <dt', (empty($txt['permissionhelp_' . $permission]) ? '' : ' title="' . $txt['permissionhelp_' . $permission] . '"') . '><img src="', shd_image_url($icon), '" alt="*" />', $txt['permissionname_' . $permission], '</dt> |
|
387 |
+ <dd class="shd_nowrap"> |
|
388 |
+ <span id="perm_', $permission, '_icon" class="', $perm_class, '"></span> |
|
389 |
+ <select name="perm_', $permission, '" id="perm_', $permission, '" onchange="javascript:shd_chicon(this);"> |
|
390 |
+ <option value="disallow"', ($perm_value == 'disallow' ? ' selected="selected"' : ''), '>', (empty($txt['permissionname_' . $permission . '_no']) ? $txt['shd_roleperm_disallow'] : $txt['permissionname_' . $permission . '_no']), ' </option>'; |
|
391 |
+ |
|
392 |
+ if ($ownany) |
|
393 |
+ { |
|
394 |
+ echo ' |
|
395 |
+ <option value="allow_own"', ($perm_value == 'allow_own' ? ' selected="selected"' : ''), '>', $txt['permissionname_' . $permission . '_own'], ' </option> |
|
396 |
+ <option value="allow_any"', ($perm_value == 'allow_any' ? ' selected="selected"' : ''), '>', $txt['permissionname_' . $permission . '_any'], ' </option>'; |
|
397 |
+ } |
|
398 |
+ else |
|
399 |
+ { |
|
400 |
+ echo ' |
|
401 |
+ <option value="allow"', ($perm_value == 'allow' ? ' selected="selected"' : ''), '>', (empty($txt['permissionname_' . $permission . '_yes']) ? $txt['shd_roleperm_allow'] : $txt['permissionname_' . $permission . '_yes']), ' </option>'; |
|
402 |
+ } |
|
403 |
+ |
|
404 |
+ echo ' |
|
405 |
+ </select> |
|
406 |
+ </dd>'; |
|
407 |
+ } |
|
408 |
+ |
|
409 |
+ echo ' |
|
410 |
+ </dl> |
|
411 |
+ </div> |
|
412 |
+ </div> |
|
413 |
+ <span class="lowerframe" id="permfooter_', $rowitem, '" style="display:none;"><span></span></span> |
|
414 |
+ <br />'; |
|
415 |
+ } |
|
416 |
+ |
|
417 |
+ echo ' |
|
418 |
+ </div>'; |
|
419 |
+ } |
|
420 |
+ |
|
421 |
+ echo ' |
|
422 |
+ <div class="tborder floatleft"> |
|
423 |
+ <div class="cat_bar"> |
|
424 |
+ <h3 class="catbg sd_no_margin grid_header"> |
|
425 |
+ <img src="', $settings['default_images_url'], '/simpledesk/roles.png" alt="*" /> |
|
426 |
+ ', $txt['shd_role_membergroups'], ' |
|
427 |
+ </h3> |
|
428 |
+ </div> |
|
429 |
+ <p class="description shd_actionloginfo"> |
|
430 |
+ ', $txt['shd_role_membergroups_desc'], ' |
|
431 |
+ </p> |
|
432 |
+ <table class="shd_ticketlist" cellspacing="0" width="100%"> |
|
433 |
+ <tr class="titlebg"> |
|
434 |
+ <td width="30%">', $txt['shd_role'], '</td> |
|
435 |
+ <td width="30%">', $txt['shd_badge_stars'], '</td> |
|
436 |
+ <td>', $txt['shd_assign_group'], '</td> |
|
437 |
+ </tr>'; |
|
438 |
+ |
|
439 |
+ $use_bg2 = true; |
|
440 |
+ foreach ($context['membergroups'] as $id_group => $group) |
|
441 |
+ { |
|
442 |
+ echo ' |
|
443 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
444 |
+ <td>', $group['link'], '</td> |
|
445 |
+ <td>'; |
|
446 |
+ |
|
447 |
+ if (!empty($group['stars'])) |
|
448 |
+ { |
|
449 |
+ $stars = explode('#', $group['stars']); |
|
450 |
+ if (!empty($stars[0]) && !empty($stars[1])) |
|
451 |
+ echo str_repeat('<img src="' . $settings['images_url'] . '/' . $stars[1] . '" alt="" />', $stars[0]); |
|
452 |
+ } |
|
453 |
+ |
|
454 |
+ echo '</td> |
|
455 |
+ <td><input type="checkbox" class="input_check" name="group', $id_group, '"', (in_array($id_group, $context['role_groups']) ? ' checked="checked"' : ''), ' /></td> |
|
456 |
+ </tr>'; |
|
457 |
+ |
|
458 |
+ $use_bg2 = !$use_bg2; |
|
459 |
+ } |
|
460 |
+ |
|
461 |
+ echo ' |
|
462 |
+ </table> |
|
463 |
+ <br /> |
|
464 |
+ </div> |
|
465 |
+ <div class="floatleft"> |
|
466 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
467 |
+ <input type="hidden" name="role" value="', $_REQUEST['role'], '" /> |
|
468 |
+ <input type="submit" value="', $txt['shd_edit_role'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" /> |
|
469 |
+ <input type="submit" value="', $txt['shd_delete_role'], '" onclick="return confirm(' . JavaScriptEscape($txt['shd_delete_role_confirm']) . ');" name="delete" class="button_submit" /> |
|
470 |
+ </div> |
|
471 |
+ </form> |
|
472 |
+ <br class="clear" />'; |
|
473 |
+} |
|
474 |
+ |
|
475 |
+/** |
|
476 |
+ * Display the form to clone an existing role. |
|
477 |
+ * |
|
478 |
+ * @since 1.1 |
|
479 |
+*/ |
|
480 |
+function template_shd_copy_role() |
|
481 |
+{ |
|
482 |
+ global $context, $settings, $txt, $modSettings, $scripturl; |
|
483 |
+ |
|
484 |
+ echo ' |
|
485 |
+ <div class="tborder"> |
|
486 |
+ <div class="cat_bar"> |
|
487 |
+ <h3 class="catbg"> |
|
488 |
+ <img src="', $settings['default_images_url'], '/simpledesk/permissions.png" class="icon" alt="*" /> |
|
489 |
+ ', $txt['shd_admin_permissions'], ' |
|
490 |
+ </h3> |
|
491 |
+ </div> |
|
492 |
+ <p class="description"> |
|
493 |
+ ', $txt['shd_admin_permissions_homedesc'], ' |
|
494 |
+ </p> |
|
495 |
+ </div> |
|
496 |
+ <div class="cat_bar"> |
|
497 |
+ <h3 class="catbg grid_header"> |
|
498 |
+ <img src="', $settings['default_images_url'], '/simpledesk/position.png" alt="*" /> |
|
499 |
+ ', $txt['shd_copy_role'], ' |
|
500 |
+ </h3> |
|
501 |
+ </div> |
|
502 |
+ <div class="roundframe"> |
|
503 |
+ <form action="', $scripturl, '?action=admin;area=helpdesk_permissions;sa=copyrole;part=2" method="post"> |
|
504 |
+ <div class="content"> |
|
505 |
+ <dl class="settings"> |
|
506 |
+ <dt><strong>', $txt['shd_create_based_on'], ':</strong></dt> |
|
507 |
+ <dd> |
|
508 |
+ <img alt="*" src="', $settings['default_images_url'], '/simpledesk/', $context['shd_permissions']['user_defined_roles'][$_REQUEST['role']]['template_icon'], '" /> |
|
509 |
+ ', $context['shd_permissions']['user_defined_roles'][$_REQUEST['role']]['name'], ' |
|
510 |
+ </dd> |
|
511 |
+ <dt><strong>', $txt['shd_create_name'], '</strong></dt> |
|
512 |
+ <dd><input type="text" name="rolename" id="rolename" value="" class="input_text" size="30" /></dd> |
|
513 |
+ <dt><strong>', $txt['shd_copy_role_groups'], '</strong></dt> |
|
514 |
+ <dd><input type="checkbox" name="copygroups" id="copygroups" value="1" class="input_check" /></dd> |
|
515 |
+ </dl> |
|
516 |
+ </div> |
|
517 |
+ <input type="submit" value="', $txt['shd_copy_role'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" /> |
|
518 |
+ <input type="hidden" name="role" value="', $_REQUEST['role'], '" /> |
|
519 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
520 |
+ <input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" /> |
|
521 |
+ </form> |
|
522 |
+ </div> |
|
523 |
+ <span class="lowerframe"><span></span></span>'; |
|
524 |
+} |
|
525 |
+?> |
... | ... |
@@ -0,0 +1,141 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk's administration/plugins area |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * Displays SimpleDesk's administration for plugins. |
|
6 |
+ * |
|
7 |
+ * @package template |
|
8 |
+ * @since 1.1 |
|
9 |
+*/ |
|
10 |
+ |
|
11 |
+/** |
|
12 |
+ * Display the front page of the SimpleDesk plugins area. |
|
13 |
+ * |
|
14 |
+ * @since 1.1 |
|
15 |
+*/ |
|
16 |
+function template_shd_plugin_listing() |
|
17 |
+{ |
|
18 |
+ global $context, $settings, $txt, $modSettings, $scripturl; |
|
19 |
+ |
|
20 |
+ echo ' |
|
21 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
22 |
+ function toggleItem(itemID) |
|
23 |
+ { |
|
24 |
+ // Toggle the hidden item. |
|
25 |
+ var itemValueHandle = document.getElementById("feature_" + itemID); |
|
26 |
+ itemValueHandle.value = itemValueHandle.value == 1 ? 0 : 1; |
|
27 |
+ |
|
28 |
+ // Change the image, alternative text and the title. |
|
29 |
+ document.getElementById("switch_" + itemID).src = \'', $settings['images_url'], '/admin/switch_\' + (itemValueHandle.value == 1 ? \'on\' : \'off\') + \'.png\'; |
|
30 |
+ document.getElementById("switch_" + itemID).alt = itemValueHandle.value == 1 ? \'', $txt['core_settings_switch_off'], '\' : \'', $txt['core_settings_switch_on'], '\'; |
|
31 |
+ document.getElementById("switch_" + itemID).title = itemValueHandle.value == 1 ? \'', $txt['core_settings_switch_off'], '\' : \'', $txt['core_settings_switch_on'], '\'; |
|
32 |
+ |
|
33 |
+ // Don\'t reload. |
|
34 |
+ return false; |
|
35 |
+ } |
|
36 |
+ // ]]></script>'; |
|
37 |
+ |
|
38 |
+ echo ' |
|
39 |
+ <div id="admincenter"> |
|
40 |
+ <form action="', $scripturl, '?action=admin;area=helpdesk_plugins;save;" method="post" accept-charset="', $context['character_set'], '"> |
|
41 |
+ <div class="tborder"> |
|
42 |
+ <div class="cat_bar"> |
|
43 |
+ <h3 class="catbg"> |
|
44 |
+ <img src="', $settings['default_images_url'], '/simpledesk/plugins.png" class="icon" alt="*" /> |
|
45 |
+ ', $txt['shd_admin_plugins'], ' |
|
46 |
+ </h3> |
|
47 |
+ </div> |
|
48 |
+ <p class="description"> |
|
49 |
+ ', $txt['shd_admin_plugins_homedesc'], ' |
|
50 |
+ </p> |
|
51 |
+ </div>'; |
|
52 |
+ |
|
53 |
+ $use_bg2 = true; |
|
54 |
+ foreach ($context['plugins'] as $id => $plugin) |
|
55 |
+ { |
|
56 |
+ echo ' |
|
57 |
+ <div class="windowbg', $use_bg2 ? '2' : '', '"> |
|
58 |
+ <span class="topslice"><span></span></span> |
|
59 |
+ <div class="content features">'; |
|
60 |
+ |
|
61 |
+ if (!empty($plugin['installable'])) |
|
62 |
+ echo ' |
|
63 |
+ <div class="features_switch" id="js_feature_', $id, '" style="display: none;"> |
|
64 |
+ <a href="', $scripturl, '?action=admin;area=helpdesk_plugins;save;', $context['session_var'], '=', $context['session_id'], ';toggle=', $id, ';state=', $plugin['enabled'] ? 0 : 1, '" onclick="return toggleItem(\'', $id, '\');"> |
|
65 |
+ <input type="hidden" name="feature_', $id, '" id="feature_', $id, '" value="', $plugin['enabled'] ? 1 : 0, '" /><img src="', $settings['images_url'], '/admin/switch_', $plugin['enabled'] ? 'on' : 'off', '.png" id="switch_', $id, '" style="margin-top: 1.3em;" alt="', $txt['core_settings_switch_' . ($plugin['enabled'] ? 'off' : 'on')], '" title="', $txt['core_settings_switch_' . ($plugin['enabled'] ? 'off' : 'on')], '" /> |
|
66 |
+ </a> |
|
67 |
+ </div>'; |
|
68 |
+ else |
|
69 |
+ { |
|
70 |
+ echo ' |
|
71 |
+ <div class="features_switch" id="js_feature_', $id, '"> |
|
72 |
+ <div class="error">', $txt['shd_admin_plugins_wrong_version'], '</div> |
|
73 |
+ <div>', $txt['shd_admin_plugins_versions_avail'], ':</div> |
|
74 |
+ <ul class="smalltext"> |
|
75 |
+ <li>', implode('</li><li>', $plugin['details']['compatibility']), '</li> |
|
76 |
+ </ul> |
|
77 |
+ </div>'; |
|
78 |
+ } |
|
79 |
+ |
|
80 |
+ if (!empty($plugin['languages'])) |
|
81 |
+ { |
|
82 |
+ echo ' |
|
83 |
+ <div class="langblock">', $txt['shd_admin_plugins_languages'], ':<br />'; |
|
84 |
+ foreach ($plugin['languages'] as $language) |
|
85 |
+ { |
|
86 |
+ if (!empty($txt['shd_admin_plugins_lang_' . $language])) |
|
87 |
+ echo ' |
|
88 |
+ <img src="', $settings['default_images_url'], '/simpledesk/flags/', $language, '.png" alt="', $txt['shd_admin_plugins_lang_' . $language], '" title="', $txt['shd_admin_plugins_lang_' . $language], '" />'; |
|
89 |
+ } |
|
90 |
+ echo ' |
|
91 |
+ </div>'; |
|
92 |
+ } |
|
93 |
+ |
|
94 |
+ echo ' |
|
95 |
+ <h4>', (!empty($plugin['details']['acp_url']) ? '<a href="' . $scripturl . '?' . $plugin['details']['acp_url'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '">' . $plugin['details']['title'] . '</a>' : $plugin['details']['title']), '</h4> |
|
96 |
+ <p>'; |
|
97 |
+ if (!empty($plugin['details']['description'])) |
|
98 |
+ echo ' |
|
99 |
+ ', $plugin['details']['description'], '<br />'; |
|
100 |
+ |
|
101 |
+ echo ' ', $txt['shd_admin_plugins_writtenby'], ': ', (empty($plugin['details']['website']) ? $plugin['details']['author'] : '<a href="' . $plugin['details']['website'] . '" target="_blank" title="' . $txt['shd_admin_plugins_website'] . ' - ' . $plugin['details']['website'] . '">' . $plugin['details']['author'] . '</a>'), ' |
|
102 |
+ </p>'; |
|
103 |
+ |
|
104 |
+ if (!empty($plugin['installable'])) |
|
105 |
+ echo ' |
|
106 |
+ <div id="plain_feature_', $id, '"> |
|
107 |
+ <label for="plain_feature_', $id, '_radio_on"><input type="radio" name="feature_plain_', $id, '" id="plain_feature_', $id, '_radio_on" value="1"', $plugin['enabled'] ? ' checked="checked"' : '', ' class="input_radio" />', $txt['core_settings_enabled'], '</label> |
|
108 |
+ <label for="plain_feature_', $id, '_radio_off"><input type="radio" name="feature_plain_', $id, '" id="plain_feature_', $id, '_radio_off" value="0"', !$plugin['enabled'] ? ' checked="checked"' : '', ' class="input_radio" />', $txt['core_settings_disabled'], '</label> |
|
109 |
+ </div>'; |
|
110 |
+ |
|
111 |
+ echo ' |
|
112 |
+ </div> |
|
113 |
+ <span class="botslice clear_right"><span></span></span> |
|
114 |
+ </div>'; |
|
115 |
+ |
|
116 |
+ $use_bg2 = !$use_bg2; |
|
117 |
+ } |
|
118 |
+ |
|
119 |
+ echo ' |
|
120 |
+ <div class="righttext"> |
|
121 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
122 |
+ <input type="hidden" value="0" name="js_worked" id="js_worked" /> |
|
123 |
+ <input type="submit" value="', $txt['save'], '" name="save" class="button_submit" /> |
|
124 |
+ </div> |
|
125 |
+ </form> |
|
126 |
+ </div> |
|
127 |
+ <br class="clear" /> |
|
128 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
129 |
+ document.getElementById(\'js_worked\').value = "1";'; |
|
130 |
+ foreach ($context['plugins'] as $id => $plugin) |
|
131 |
+ { |
|
132 |
+ if (!empty($plugin['installable'])) |
|
133 |
+ echo ' |
|
134 |
+ document.getElementById(\'js_feature_', $id, '\').style.display = ""; |
|
135 |
+ document.getElementById(\'plain_feature_', $id, '\').style.display = "none";'; |
|
136 |
+ } |
|
137 |
+ echo ' |
|
138 |
+ // ]]></script>'; |
|
139 |
+} |
|
140 |
+ |
|
141 |
+?> |
|
0 | 142 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,81 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk ticket assignment |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * Handles ticket assignment. |
|
6 |
+ * |
|
7 |
+ * @package template |
|
8 |
+ * @since 1.0 |
|
9 |
+*/ |
|
10 |
+ |
|
11 |
+/** |
|
12 |
+ * Displays the list of possible users a ticket can have assigned. |
|
13 |
+ * |
|
14 |
+ * Will have been populated by shd_assign() in SimpleDesk-Assign.php, adding into $context['member_list']. |
|
15 |
+ * |
|
16 |
+ * This allows users to assign tickets to other users, or themselves, or to unassign a previously assigned ticket. Future versions will |
|
17 |
+ * likely add further options here. |
|
18 |
+ * |
|
19 |
+ * @see shd_assign() |
|
20 |
+ * @since 1.0 |
|
21 |
+*/ |
|
22 |
+function template_assign() |
|
23 |
+{ |
|
24 |
+ global $context, $txt, $scripturl, $settings; |
|
25 |
+ |
|
26 |
+ if (empty($context['shd_return_to'])) |
|
27 |
+ $context['shd_return_to'] = 'ticket'; |
|
28 |
+ |
|
29 |
+ // Back to the helpdesk. |
|
30 |
+ echo ' |
|
31 |
+ <div class="floatleft"> |
|
32 |
+ ', template_button_strip(array($context['navigation']['back']), 'bottom'), ' |
|
33 |
+ </div><br class="clear" />'; |
|
34 |
+ |
|
35 |
+ echo ' |
|
36 |
+ <div class="cat_bar"> |
|
37 |
+ <h3 class="catbg grid_header"> |
|
38 |
+ <img src="', $settings['default_images_url'], '/simpledesk/assign.png" alt="*" /> |
|
39 |
+ ', $txt['shd_ticket_assign_ticket'], ' |
|
40 |
+ </h3> |
|
41 |
+ </div> |
|
42 |
+ <div class="roundframe"> |
|
43 |
+ <form action="', $scripturl, '?action=helpdesk;sa=assign2;ticket=', $context['ticket_id'], '" method="post" onsubmit="submitonce(this);"> |
|
44 |
+ <div class="content"> |
|
45 |
+ <dl class="settings"> |
|
46 |
+ <dt> |
|
47 |
+ <strong>', $txt['shd_ticket_assignedto'], ':</strong> |
|
48 |
+ </dt> |
|
49 |
+ <dd> |
|
50 |
+ ', $context['member_list'][$context['ticket_assigned']], ' |
|
51 |
+ </dd> |
|
52 |
+ <dt> |
|
53 |
+ <strong>', $txt['shd_ticket_assign_to'], ':</strong> |
|
54 |
+ </dt> |
|
55 |
+ <dd> |
|
56 |
+ <select name="to_user">'; |
|
57 |
+ |
|
58 |
+ foreach ($context['member_list'] as $id => $name) |
|
59 |
+ echo ' |
|
60 |
+ <option value="', $id, '"', ($id == $context['ticket_assigned'] ? ' selected="selected"' : ''), '>', $name, '</option>'; |
|
61 |
+ |
|
62 |
+ echo ' |
|
63 |
+ </select> |
|
64 |
+ </dd> |
|
65 |
+ </dl> |
|
66 |
+ <input type="submit" value="', $txt['shd_ticket_assign_ticket'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" /> |
|
67 |
+ <input type="submit" name="cancel" value="', ($context['shd_return_to'] == 'home' ? $txt['shd_cancel_home'] : $txt['shd_cancel_ticket']), '" accesskey="c" class="button_submit" /> |
|
68 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />'; |
|
69 |
+ |
|
70 |
+ if ($context['shd_return_to'] == 'home') |
|
71 |
+ echo ' |
|
72 |
+ <input type="hidden" name="home" value="1" />'; |
|
73 |
+ |
|
74 |
+ echo ' |
|
75 |
+ </div> |
|
76 |
+ </form> |
|
77 |
+ </div> |
|
78 |
+ <span class="lowerframe"><span></span></span>'; |
|
79 |
+} |
|
80 |
+ |
|
81 |
+?> |
|
0 | 82 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,663 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk ticket display |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * This file handles just displaying a ticket, its replies and working with SimpleDesk-Post.template.php to arrange the quick reply area. |
|
6 |
+ * |
|
7 |
+ * @package template |
|
8 |
+ * @since 1.0 |
|
9 |
+*/ |
|
10 |
+ |
|
11 |
+/** |
|
12 |
+ * Display the main view of a ticket. |
|
13 |
+ * |
|
14 |
+ * It is responsible for all the processing and display of the data gathered in {@link shd_view_ticket()} to the user, and in fact there |
|
15 |
+ * is little to discuss other than simply displaying the ticket in given HTML. |
|
16 |
+ * |
|
17 |
+ * It is also responsible for displaying attachments either to the ticket (in attachments-in-ticket mode) or to the first post |
|
18 |
+ * (in attachments-in-replies mode), and calling upon the posting routines to set up display of 'advanced' mode in quick reply. |
|
19 |
+ * |
|
20 |
+ * @see shd_view_ticket() |
|
21 |
+ * @see template_ticket_postbox() |
|
22 |
+ * @see template_ticket_meta() |
|
23 |
+ * @since 1.0 |
|
24 |
+*/ |
|
25 |
+function template_viewticket() |
|
26 |
+{ |
|
27 |
+ global $context, $txt, $scripturl, $settings, $modSettings, $options; |
|
28 |
+ |
|
29 |
+ // Back to the helpdesk. |
|
30 |
+ echo '<div class="floatleft">', template_button_strip(array($context['navigation']['back']), 'bottom'), '</div>', ($modSettings['shd_ticketnav_style'] != 'smf' ? '<br class="clear" />' : ''), ''; |
|
31 |
+ |
|
32 |
+ if ($modSettings['shd_ticketnav_style'] == 'smf') |
|
33 |
+ { |
|
34 |
+ template_button_strip($context['ticket_navigation'], 'right'); |
|
35 |
+ echo '<br class="clear" />'; |
|
36 |
+ } |
|
37 |
+ |
|
38 |
+ echo ' |
|
39 |
+ <div class="tborder"> |
|
40 |
+ <div class="cat_bar"> |
|
41 |
+ <h3 class="catbg grid_header ticketheader"> |
|
42 |
+ <span class="floatright smalltext shd_ticketlinks" id="ticket">'; |
|
43 |
+ |
|
44 |
+ if ($modSettings['shd_ticketnav_style'] == 'sd') |
|
45 |
+ { |
|
46 |
+ foreach ($context['ticket_navigation'] as $button) |
|
47 |
+ if (!empty($button['display'])) |
|
48 |
+ echo ' |
|
49 |
+ <a href="', $button['url'], '"', (!empty($button['is_last']) ? ' id="last"' : ''), '', (!empty($button['onclick']) ? ' onclick="' . $button['onclick'] . '"' : ''), '><img src="', $settings['default_images_url'], '/simpledesk/', $button['icon'], '.png" alt="', $button['alt'], '" title="', $txt[$button['text']], '" /> ', $txt[$button['text']], '</a>'; |
|
50 |
+ } |
|
51 |
+ elseif ($modSettings['shd_ticketnav_style'] == 'sdcompact') |
|
52 |
+ { |
|
53 |
+ foreach ($context['ticket_navigation'] as $button) |
|
54 |
+ if (!empty($button['display'])) |
|
55 |
+ echo ' |
|
56 |
+ <a href="', $button['url'], '"', (!empty($button['is_last']) ? ' id="last"' : ''), '', (!empty($button['onclick']) ? ' onclick="' . $button['onclick'] . '"' : ''), '><img src="', $settings['default_images_url'], '/simpledesk/', $button['icon'], '.png" alt="', $button['alt'], '" title="', $txt[$button['text']], '" /></a>'; |
|
57 |
+ } |
|
58 |
+ |
|
59 |
+ echo ' |
|
60 |
+ </span> |
|
61 |
+ <img src="', $settings['default_images_url'], '/simpledesk/ticket.png" alt="x" /> ', $txt['shd_ticket'], ' [', $context['ticket']['display_id'], '] |
|
62 |
+ </h3> |
|
63 |
+ </div> |
|
64 |
+ <div class="windowbg"> |
|
65 |
+ <div class="content shd_ticket">'; |
|
66 |
+ |
|
67 |
+ // General ticket details |
|
68 |
+ echo ' |
|
69 |
+ <div class="information shd_ticketdetails"> |
|
70 |
+ <strong><img src="', $settings['default_images_url'], '/simpledesk/details.png" alt="" class="shd_smallicon shd_icon_minihead" /> ', $txt['shd_ticket_details'], '</strong> |
|
71 |
+ <hr /> |
|
72 |
+ <ul> |
|
73 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/id.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_id'], ': ', $context['ticket']['display_id'], '</li> |
|
74 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/user.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_user'], ': ', $context['ticket']['member']['link'], '</li> |
|
75 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/time.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_date'], ': ', $context['ticket']['poster_time'], '</li> |
|
76 |
+ <li> |
|
77 |
+ <img src="', $settings['default_images_url'], '/simpledesk/urgency.png" alt="" class="shd_smallicon" /> |
|
78 |
+ ', $txt['shd_ticket_urgency'], ': <span id="urgency">', $context['ticket']['urgency']['label'], '</span> |
|
79 |
+ <span id="urgency_increase">', (!empty($context['ticket']['urgency']['increase']) ? '<a id="urglink_increase" href="' . $scripturl . '?action=helpdesk;sa=urgencychange;ticket=' . $context['ticket']['id'] . ';change=increase;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_urgency_increase'] . '"><img src="' . $settings['images_url'] . '/sort_up.gif" width="9px" alt="' . $txt['shd_urgency_increase'] . '" /></a>' : ''), '</span> |
|
80 |
+ <span id="urgency_decrease">', (!empty($context['ticket']['urgency']['decrease']) ? '<a id="urglink_decrease" href="' . $scripturl . '?action=helpdesk;sa=urgencychange;ticket=' . $context['ticket']['id'] . ';change=decrease;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_urgency_decrease'] . '"><img src="' . $settings['images_url'] . '/sort_down.gif" width="9px" alt="' . $txt['shd_urgency_decrease'] . '" /></a>' : ''), '</span> |
|
81 |
+ </li> |
|
82 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/staff.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_assignedto'], ': ', $context['ticket']['assigned']['link'], '</li> |
|
83 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/status.png" alt="" class="shd_smallicon"/> ', $txt['shd_ticket_status'], ': ', $context['ticket']['status']['label'], '</li> |
|
84 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/replies.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_num_replies'], ': <a href="#replies">', (empty($context['ticket']['display_recycle']) ? $context['ticket']['num_replies'] : (int) $context['ticket']['num_replies'] + (int) $context['ticket']['deleted_replies']), '</a></li>'; |
|
85 |
+ |
|
86 |
+ if (!empty($context['display_private'])) |
|
87 |
+ echo ' |
|
88 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/private.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_privacy'], ': <span id="privacy">', $context['ticket']['privacy']['label'], '</span>', ($context['ticket']['privacy']['can_change'] ? ' (<a id="privlink" href="' . $scripturl . '?action=helpdesk;sa=privacychange;ticket=' . $context['ticket']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '">' . $txt['shd_ticket_change'] . '</a>)' : ''), '</li>'; |
|
89 |
+ |
|
90 |
+ if (!empty($context['ticket']['ip_address'])) |
|
91 |
+ echo ' |
|
92 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/ip.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_ip'], ': ', $context['ticket']['ip_address'], '</li>'; |
|
93 |
+ |
|
94 |
+ echo ' |
|
95 |
+ </ul>'; |
|
96 |
+ |
|
97 |
+ // Display ticket poster avatar? |
|
98 |
+ if (!empty($modSettings['shd_display_avatar']) && empty($options['show_no_avatars']) && !empty($context['ticket']['poster_avatar']['image'])) |
|
99 |
+ echo ' |
|
100 |
+ <div class="shd_ticket_avatar"> |
|
101 |
+ ', shd_profile_link($context['ticket']['poster_avatar']['image'], $context['ticket']['member']['id']), ' |
|
102 |
+ </div>'; |
|
103 |
+ |
|
104 |
+ echo ' |
|
105 |
+ </div>'; |
|
106 |
+ |
|
107 |
+ echo ' |
|
108 |
+ <div class="shd_ticket_description">'; |
|
109 |
+ |
|
110 |
+ if (!empty($context['ticket']['display_recycle'])) |
|
111 |
+ echo ' |
|
112 |
+ <div class="errorbox" id="recycle_warning"> |
|
113 |
+ <img src="', $settings['default_images_url'], '/simpledesk/delete.png" alt="" /> ', $context['ticket']['display_recycle'], ' |
|
114 |
+ </div>'; |
|
115 |
+ |
|
116 |
+ echo ' |
|
117 |
+ <img src="', $settings['default_images_url'], '/simpledesk/name.png" alt="" class="shd_smallicon shd_icon_minihead" /> <strong>', $context['ticket']['subject'], '</strong><hr /><br /> |
|
118 |
+ <div id="shd_ticket_text"> |
|
119 |
+ ', $context['ticket']['body']; |
|
120 |
+ |
|
121 |
+ if ($settings['show_modify'] && !empty($context['ticket']['modified'])) |
|
122 |
+ { |
|
123 |
+ echo ' |
|
124 |
+ <div class="smalltext shd_modified"> |
|
125 |
+ « <em>', $txt['last_edit'], ': ', $context['ticket']['modified']['time'], ' ', $txt['by'], ' ', $context['ticket']['modified']['link'], '</em> » |
|
126 |
+ </div>'; |
|
127 |
+ } |
|
128 |
+ |
|
129 |
+ echo' |
|
130 |
+ </div>'; |
|
131 |
+ |
|
132 |
+ if ($context['can_reply']) |
|
133 |
+ echo ' |
|
134 |
+ <br /> |
|
135 |
+ <div class="description shd_replybutton floatright" id="shd_replybutton"> |
|
136 |
+ <a href="', $scripturl, '?action=helpdesk;sa=reply;ticket=', $context['ticket_id'], ';num_replies=', $context['ticket']['num_replies'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['shd_ticket_reply'], '</a><br /> |
|
137 |
+ </div>'; |
|
138 |
+ |
|
139 |
+ if ($context['can_quote']) |
|
140 |
+ echo ' |
|
141 |
+ <div class="description shd_quotebutton floatright" id="shd_quotebutton"> |
|
142 |
+ <a onclick="return oQuickReply.quote(', $context['ticket']['first_msg'], ', \'', $context['session_id'], '\', \'', $context['session_var'], '\', true);" href="', $scripturl, '?action=helpdesk;sa=reply;ticket=', $context['ticket_id'], ';quote=', $context['ticket']['first_msg'], ';num_replies=', $context['ticket']['num_replies'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['shd_ticket_quote'], '</a><br /> |
|
143 |
+ </div>'; |
|
144 |
+ |
|
145 |
+ /*if (!empty($context['ticket_attach']['reply'][$context['ticket']['first_msg']])) |
|
146 |
+ { |
|
147 |
+ echo ' |
|
148 |
+ <div class="information shd_reply_attachments"> |
|
149 |
+ <dl id="postAttachment"> |
|
150 |
+ <dt> |
|
151 |
+ ', $txt['attached'], ': |
|
152 |
+ </dt>'; |
|
153 |
+ foreach ($context['ticket_attach']['reply'][$context['ticket']['first_msg']] as $attachment) |
|
154 |
+ echo ' |
|
155 |
+ <dd class="smalltext"> |
|
156 |
+ ', $attachment['link'], ' |
|
157 |
+ </dd>'; |
|
158 |
+ echo ' |
|
159 |
+ </dl> |
|
160 |
+ </div>'; |
|
161 |
+ }*/ |
|
162 |
+ |
|
163 |
+ template_inline_attachments($context['ticket']['first_msg']); |
|
164 |
+ |
|
165 |
+ echo ' |
|
166 |
+ </div> |
|
167 |
+ </div> |
|
168 |
+ <br class="clear" /> |
|
169 |
+ <span class="botslice"><span></span></span> |
|
170 |
+ </div> |
|
171 |
+ </div> |
|
172 |
+ <br />'; |
|
173 |
+ |
|
174 |
+ // Left column (ticket relationships, attachments) |
|
175 |
+ template_ticket_leftcolumn(); |
|
176 |
+ |
|
177 |
+ // The replies column |
|
178 |
+ template_viewreplies(); |
|
179 |
+ |
|
180 |
+ // Our mighty quick reply box :D |
|
181 |
+ template_quickreply(); |
|
182 |
+ |
|
183 |
+ // The ticket action log, lastly. |
|
184 |
+ template_ticketactionlog(); |
|
185 |
+} |
|
186 |
+ |
|
187 |
+/** |
|
188 |
+ * Displays the left area next to replies in the ticket view. |
|
189 |
+ * |
|
190 |
+ * We pull the content into a single column this way to ensure floatleft items are handled properly. |
|
191 |
+ * |
|
192 |
+ * @since 1.1 |
|
193 |
+*/ |
|
194 |
+function template_ticket_leftcolumn() |
|
195 |
+{ |
|
196 |
+ global $context; |
|
197 |
+ |
|
198 |
+ if (empty($context['ticket_attach']['ticket']) && empty($context['display_relationships'])) |
|
199 |
+ return; // nothing to do |
|
200 |
+ |
|
201 |
+ $context['leftcolumndone'] = true; // for the rest of the template later |
|
202 |
+ |
|
203 |
+ echo ' |
|
204 |
+ <div class="shd_ticket_leftcolumn floatleft"> |
|
205 |
+ <div class="tborder shd_attachmentcolumn">'; |
|
206 |
+ |
|
207 |
+ // Related tickets |
|
208 |
+ template_viewrelationships(); |
|
209 |
+ |
|
210 |
+ // The attachments column |
|
211 |
+ template_viewticketattach(); |
|
212 |
+ |
|
213 |
+ echo ' |
|
214 |
+ </div> |
|
215 |
+ </div>'; |
|
216 |
+} |
|
217 |
+ |
|
218 |
+/** |
|
219 |
+ * Display all the attachments to a ticket (in ticket view) |
|
220 |
+ * |
|
221 |
+ * This function displays all the attachments in the current ticket while in ticket view, rather than when in replies view (which is handled by {@link template_viewreplies()} instead; this function was previously was part of {@link template_viewticket()}. |
|
222 |
+ * |
|
223 |
+ * @since 1.1 |
|
224 |
+*/ |
|
225 |
+function template_viewticketattach() |
|
226 |
+{ |
|
227 |
+ global $context, $settings, $txt; |
|
228 |
+ |
|
229 |
+ if (!empty($context['ticket_attach']['ticket'])) |
|
230 |
+ { |
|
231 |
+ echo ' |
|
232 |
+ <div class="title_bar"> |
|
233 |
+ <h3 class="titlebg grid_header"> |
|
234 |
+ <img src="', $settings['default_images_url'], '/simpledesk/attachments.png" alt="x" />', $txt['shd_ticket_attachments'], ' (', count($context['ticket_attach']['ticket']), ') |
|
235 |
+ </h3> |
|
236 |
+ </div> |
|
237 |
+ <div class="windowbg2"> |
|
238 |
+ <div class="shd_attachmentbox">'; |
|
239 |
+ |
|
240 |
+ foreach ($context['ticket_attach']['ticket'] as $attachment) |
|
241 |
+ { |
|
242 |
+ echo ' |
|
243 |
+ <div class="description shd_attachment" id="attach', $attachment['id'], '">'; |
|
244 |
+ |
|
245 |
+ if ($attachment['is_image']) |
|
246 |
+ { |
|
247 |
+ if ($attachment['thumbnail']['has_thumb']) |
|
248 |
+ echo ' |
|
249 |
+ <a href="', $attachment['href'], ';image" id="link_', $attachment['id'], '" onclick="', $attachment['thumbnail']['javascript'], '"><img src="', $attachment['thumbnail']['href'], '" alt="" id="thumb_', $attachment['id'], '" class="shd_thumb" /></a><br />'; |
|
250 |
+ else |
|
251 |
+ echo ' |
|
252 |
+ <img src="' . $attachment['href'] . ';image" alt="" width="' . $attachment['width'] . '" height="' . $attachment['height'] . '" class="shd_thumb" /><br />'; |
|
253 |
+ } |
|
254 |
+ |
|
255 |
+ echo ' |
|
256 |
+ <strong>', $attachment['link'], '</strong> |
|
257 |
+ <span class="smalltext"> |
|
258 |
+ (', $attachment['size'], ') |
|
259 |
+ </span> |
|
260 |
+ </div>'; |
|
261 |
+ } |
|
262 |
+ |
|
263 |
+ echo ' |
|
264 |
+ </div> |
|
265 |
+ <span class="botslice"><span></span></span> |
|
266 |
+ </div>'; |
|
267 |
+ } |
|
268 |
+} |
|
269 |
+ |
|
270 |
+/** |
|
271 |
+ * Displays the quick reply/go advanced box |
|
272 |
+ * |
|
273 |
+ * This function handles displaying of the templates that make up the Quick Reply / Go Advanced area, drawing on {@link SimpleDesk-Post.template.php} for core posting templates. |
|
274 |
+ * |
|
275 |
+ * Prior to 1.1 this was part of {@link template_viewticket()} |
|
276 |
+ * |
|
277 |
+ * @since 1.1 |
|
278 |
+*/ |
|
279 |
+function template_quickreply() |
|
280 |
+{ |
|
281 |
+ global $context, $scripturl, $options, $txt, $settings; |
|
282 |
+ |
|
283 |
+ if ($context['can_reply'] && !empty($options['display_quick_reply'])) |
|
284 |
+ { |
|
285 |
+ echo ' |
|
286 |
+ <br /> |
|
287 |
+ <div class="tborder"> |
|
288 |
+ <div class="title_bar"> |
|
289 |
+ <h3 id="quickreplyheader" class="titlebg', $options['display_quick_reply'] == 2 ? ' grid_header' : '', '"> |
|
290 |
+ <span class="floatright"><a href="javascript:oQuickReply.swap();"><img src="', $settings['images_url'], '/', $options['display_quick_reply'] == 2 ? 'collapse' : 'expand', '.gif" alt="+" id="quickReplyExpand" class="icon" /></a></span> |
|
291 |
+ <img src="', $settings['default_images_url'], '/simpledesk/respond.png" alt="x" /> |
|
292 |
+ <a href="javascript:oQuickReply.swap();">', $txt['shd_reply_ticket'], '</a> |
|
293 |
+ </h3> |
|
294 |
+ </div> |
|
295 |
+ <div class="roundframe" id="quickReplyOptions"', $options['display_quick_reply'] == 2 ? '' : ' style="display: none"', '> |
|
296 |
+ <div class="content"> |
|
297 |
+ <form action="', $scripturl, '?action=helpdesk;sa=savereply" method="post" accept-charset="', $context['character_set'], '" name="postreply" id="postreply" onsubmit="submitonce(this);smc_saveEntities(\'postreply\', [\'shd_reply\'], \'options\');" enctype="multipart/form-data" style="margin: 0;">'; |
|
298 |
+ |
|
299 |
+ if ($context['can_go_advanced']) |
|
300 |
+ { |
|
301 |
+ echo ' |
|
302 |
+ <div class="description shd_advancedbutton floatright" id="shd_goadvancedbutton"> |
|
303 |
+ <a onclick="goAdvanced(); return false;" href="', $scripturl, '?action=helpdesk;sa=reply;ticket=', $context['ticket_id'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['shd_go_advanced'], '</a><br /> |
|
304 |
+ </div>'; |
|
305 |
+ } |
|
306 |
+ |
|
307 |
+ template_ticket_postbox(); |
|
308 |
+ template_ticket_meta(); |
|
309 |
+ |
|
310 |
+ echo ' |
|
311 |
+ </form> |
|
312 |
+ </div> |
|
313 |
+ </div> |
|
314 |
+ <span id="quickreplyfooter" class="lowerframe"', $options['display_quick_reply'] == 2 ? '' : ' style="display: none"', '><span></span></span> |
|
315 |
+ </div>'; |
|
316 |
+ } |
|
317 |
+} |
|
318 |
+ |
|
319 |
+/** |
|
320 |
+ * Display the attachments for a given message. |
|
321 |
+ * |
|
322 |
+ * This function outputs the HTML necessary to display attachments with thumbnails inline with each reply. |
|
323 |
+ * |
|
324 |
+ * @param int $msg The message id to look in $context['ticket_attach']['reply'] for attachments. |
|
325 |
+ * |
|
326 |
+ * @since 1.1 |
|
327 |
+ * @todo See if it's possible to do a sane CSS replacement instead of using tables. |
|
328 |
+*/ |
|
329 |
+// Arantor: I swear I spent more time farting around with this trying to make it not look like crap than I did the rest of the thumbnail code. |
|
330 |
+function template_inline_attachments($msg) |
|
331 |
+{ |
|
332 |
+ global $context, $txt; |
|
333 |
+ |
|
334 |
+ if (!empty($context['ticket_attach']['reply'][$msg])) |
|
335 |
+ { |
|
336 |
+ echo ' |
|
337 |
+ <table width="90%">'; |
|
338 |
+ /*echo ' |
|
339 |
+ <div class="smalltext"> |
|
340 |
+ <strong>', $txt['shd_ticket_attachments'], '</strong><br /> |
|
341 |
+ <ul class="shd_replyattachments">';*/ |
|
342 |
+ |
|
343 |
+ $count = 0; |
|
344 |
+ $firstrow = true; |
|
345 |
+ foreach ($context['ticket_attach']['reply'][$msg] as $attachment) |
|
346 |
+ { |
|
347 |
+ if ($count == 0) |
|
348 |
+ { |
|
349 |
+ if (!$firstrow) |
|
350 |
+ echo ' |
|
351 |
+ </tr>'; |
|
352 |
+ |
|
353 |
+ echo ' |
|
354 |
+ <tr>'; |
|
355 |
+ } |
|
356 |
+ |
|
357 |
+ echo ' |
|
358 |
+ <td class="description">'; |
|
359 |
+ |
|
360 |
+ if ($attachment['is_image']) |
|
361 |
+ { |
|
362 |
+ if ($attachment['thumbnail']['has_thumb']) |
|
363 |
+ echo ' |
|
364 |
+ <a href="', $attachment['href'], ';image" id="link_', $attachment['id'], '" onclick="', $attachment['thumbnail']['javascript'], '"><img src="', $attachment['thumbnail']['href'], '" alt="" id="thumb_', $attachment['id'], '" class="shd_thumb" /></a><br />'; |
|
365 |
+ else |
|
366 |
+ echo ' |
|
367 |
+ <img src="' . $attachment['href'] . ';image" alt="" width="' . $attachment['width'] . '" height="' . $attachment['height'] . '" class="shd_thumb" /><br />'; |
|
368 |
+ } |
|
369 |
+ |
|
370 |
+ echo ' |
|
371 |
+ ', $attachment['link'], ' |
|
372 |
+ </td>'; |
|
373 |
+ |
|
374 |
+ $count++; |
|
375 |
+ if ($count == 3) |
|
376 |
+ $count = 0; |
|
377 |
+ |
|
378 |
+ $firstrow = false; |
|
379 |
+ } |
|
380 |
+ |
|
381 |
+ /*echo ' |
|
382 |
+ </ul> |
|
383 |
+ </div>';*/ |
|
384 |
+ echo ' |
|
385 |
+ </table>'; |
|
386 |
+ } |
|
387 |
+} |
|
388 |
+ |
|
389 |
+/** |
|
390 |
+ * Display all the replies to a ticket. |
|
391 |
+ * |
|
392 |
+ * This function deals simply with viewing of replies in a ticket, including deleted replies, which is initialised in {@link shd_view_ticket()} |
|
393 |
+ * and data gathered through the {@link shd_prepare_ticket_context()} call back, which simply deals with a single reply at a time. |
|
394 |
+ * |
|
395 |
+ * @see shd_view_ticket() |
|
396 |
+ * @see template_viewticket() |
|
397 |
+ * @since 1.0 |
|
398 |
+*/ |
|
399 |
+function template_viewreplies() |
|
400 |
+{ |
|
401 |
+ global $context, $settings, $txt, $scripturl, $options, $modSettings, $reply_request; |
|
402 |
+ |
|
403 |
+ echo ' |
|
404 |
+ <div class="shd_ticket_rightcolumn floatleft"', empty($context['leftcolumndone']) ? ' style="width: 100%;"' : '', '> |
|
405 |
+ <div class="tborder"> |
|
406 |
+ <div class="title_bar"> |
|
407 |
+ <h3 class="titlebg grid_header"> |
|
408 |
+ <span class="floatright smalltext">', $txt['pages'], ': ', $context['page_index'], '</span> |
|
409 |
+ <img src="', $settings['default_images_url'], '/simpledesk/replies.png" alt="x" /> ', $txt['shd_ticket_replies'], ' |
|
410 |
+ </h3> |
|
411 |
+ </div> |
|
412 |
+ <div class="roundframe" id="replies"> |
|
413 |
+ <div class="content">'; |
|
414 |
+ |
|
415 |
+ if (empty($reply_request)) |
|
416 |
+ { |
|
417 |
+ echo $txt['shd_no_replies']; |
|
418 |
+ } |
|
419 |
+ else |
|
420 |
+ { |
|
421 |
+ while ($reply = $context['get_replies']()) |
|
422 |
+ { |
|
423 |
+ if (!empty($reply['is_new'])) |
|
424 |
+ echo ' |
|
425 |
+ <a id="new"></a>'; |
|
426 |
+ |
|
427 |
+ echo ' |
|
428 |
+ <div class="description shd_reply', (!empty($context['ticket']['display_recycle']) && $reply['message_status'] == MSG_STATUS_DELETED ? ' errorbox' : ''), '" id="msg', $reply['id'], '"> |
|
429 |
+ <span class="floatleft shd_posterinfo"> |
|
430 |
+ <strong class="shd_postername"> |
|
431 |
+ ', $reply['member']['link'], ' |
|
432 |
+ </strong> |
|
433 |
+ <br /> |
|
434 |
+ ', $reply['member']['group'], '<br class="shd_groupmargin" />'; |
|
435 |
+ |
|
436 |
+ if (!empty($modSettings['shd_display_avatar']) && empty($options['show_no_avatars']) && !empty($reply['member']['avatar']['image'])) |
|
437 |
+ echo ' |
|
438 |
+ <span class="shd_posteravatar"> |
|
439 |
+ ', shd_profile_link($reply['member']['avatar']['image'], $reply['member']['id']), ' |
|
440 |
+ </span>'; |
|
441 |
+ |
|
442 |
+ if ($modSettings['shd_staff_badge'] == (!empty($reply['is_team']) ? 'staffbadge' : 'userbadge') || $modSettings['shd_staff_badge'] == 'bothbadge') |
|
443 |
+ echo '<br /> |
|
444 |
+ ', $reply['member']['group_stars']; |
|
445 |
+ elseif (!empty($reply['is_team']) && $modSettings['shd_staff_badge'] == 'nobadge') |
|
446 |
+ echo '<br /> |
|
447 |
+ <img src="', $settings['default_images_url'] . '/simpledesk/staff.png" class="shd_smallicon" title="', $txt['shd_ticket_staff'], '" alt="', $txt['shd_ticket_staff'], '" />'; |
|
448 |
+ |
|
449 |
+ echo ' |
|
450 |
+ </span> |
|
451 |
+ <div class="shd_replyarea"> |
|
452 |
+ <div class="smalltext"> |
|
453 |
+ <span class="floatright shd_ticketlinks">'; |
|
454 |
+ if ($context['can_quote']) |
|
455 |
+ echo ' |
|
456 |
+ <img src="', $settings['default_images_url'], '/simpledesk/quote.png" class="shd_smallicon" alt="*" /><a onclick="return oQuickReply.quote(', $reply['id'], ', \'', $context['session_id'], '\', \'', $context['session_var'], '\', true);" href="', $scripturl, '?action=helpdesk;sa=reply;ticket=', $context['ticket_id'], ';quote=', $reply['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['shd_ticket_quote_short'], '</a>'; |
|
457 |
+ if ($reply['can_edit']) |
|
458 |
+ echo ' |
|
459 |
+ <img src="', $settings['default_images_url'], '/simpledesk/edit.png" class="shd_smallicon" alt="*" /><a href="', $scripturl, '?action=helpdesk;sa=editreply;ticket=', $context['ticket_id'], ';msg=', $reply['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['shd_ticket_edit'], '</a>'; |
|
460 |
+ if ($reply['can_delete']) |
|
461 |
+ echo ' |
|
462 |
+ <img src="', $settings['default_images_url'], '/simpledesk/delete.png" class="shd_smallicon" alt="*" /><a href="', $scripturl, '?action=helpdesk;sa=deletereply;reply=', $reply['id'], ';ticket=', $context['ticket']['id'], ';', $context['session_var'], '=', $context['session_id'], '" onclick="return confirm(', JavaScriptEscape($txt['shd_delete_reply_confirm']), ');">', $txt['shd_ticket_delete'], '</a>'; |
|
463 |
+ if ($reply['can_restore']) |
|
464 |
+ echo ' |
|
465 |
+ <img src="', $settings['default_images_url'], '/simpledesk/restore.png" class="shd_smallicon" alt="*" /><a href="', $scripturl, '?action=helpdesk;sa=restorereply;reply=', $reply['id'], ';ticket=', $context['ticket']['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['shd_ticket_restore'], '</a>'; |
|
466 |
+ if ($reply['can_permadelete']) |
|
467 |
+ echo ' |
|
468 |
+ <img src="', $settings['default_images_url'], '/simpledesk/delete.png" class="shd_smallicon" alt="*" /><a href="', $scripturl, '?action=helpdesk;sa=permadelete;reply=', $reply['id'], ';ticket=', $context['ticket']['id'], ';', $context['session_var'], '=', $context['session_id'], '" onclick="return confirm(', JavaScriptEscape($txt['shd_delete_permanently_confirm']), ');">', $txt['shd_delete_permanently'], '</a>'; |
|
469 |
+ if ($reply['can_split']) |
|
470 |
+ echo ' |
|
471 |
+ <img src="', $settings['default_images_url'], '/simpledesk/split.png" class="shd_smallicon" alt="*" /><a href="', $scripturl, '?action=helpdesk;sa=splitticket;at_msg=', $reply['id'], ';ticket=', $context['ticket']['id'], '">', $txt['shd_ticket_split_ticket'], '</a>'; |
|
472 |
+ |
|
473 |
+ echo ' |
|
474 |
+ </span> |
|
475 |
+ <a href="', $reply['link'], '">', sprintf($txt['shd_reply_written'], $reply['time']), '</a> |
|
476 |
+ </div> |
|
477 |
+ <hr class="clearfix" /> |
|
478 |
+ ', $reply['body'], ' |
|
479 |
+ <br /><br />'; |
|
480 |
+ |
|
481 |
+ if ($settings['show_modify'] && !empty($reply['modified'])) |
|
482 |
+ { |
|
483 |
+ echo ' |
|
484 |
+ <div class="smalltext shd_modified" style="margin-top:20px;"> |
|
485 |
+ « <em>', $txt['last_edit'], ': ', $reply['modified']['time'], ' ', $txt['by'], ' ', $reply['modified']['link'], '</em> » |
|
486 |
+ </div>'; |
|
487 |
+ } |
|
488 |
+ |
|
489 |
+ template_inline_attachments($reply['id']); |
|
490 |
+ |
|
491 |
+ echo ' |
|
492 |
+ </div>'; |
|
493 |
+ |
|
494 |
+ if (!empty($reply['ip_address'])) |
|
495 |
+ echo ' |
|
496 |
+ <span class="floatright"><img src="', $settings['default_images_url'], '/simpledesk/ip.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_ip'], ': ', $reply['ip_address'], '</span>'; |
|
497 |
+ |
|
498 |
+ echo ' |
|
499 |
+ <br class="clear" /> |
|
500 |
+ </div>'; |
|
501 |
+ } |
|
502 |
+ } |
|
503 |
+ |
|
504 |
+ echo ' |
|
505 |
+ </div> |
|
506 |
+ <span class="floatright smalltext">', $txt['pages'], ': ', $context['page_index'], '</span> |
|
507 |
+ <br class="clear" /> |
|
508 |
+ </div> |
|
509 |
+ <span class="lowerframe"><span></span></span> |
|
510 |
+ </div> |
|
511 |
+ </div><br class="clear" />'; |
|
512 |
+} |
|
513 |
+ |
|
514 |
+/** |
|
515 |
+ * Display related tickets. |
|
516 |
+ * |
|
517 |
+ * Displays the block of tickets that have a relationship to this one. |
|
518 |
+ * |
|
519 |
+ * @since 1.1 |
|
520 |
+*/ |
|
521 |
+function template_viewrelationships() |
|
522 |
+{ |
|
523 |
+ global $context, $settings, $txt, $scripturl; |
|
524 |
+ |
|
525 |
+ if (!empty($context['display_relationships'])) |
|
526 |
+ { |
|
527 |
+ echo ' |
|
528 |
+ <div class="title_bar"> |
|
529 |
+ <h3 class="titlebg grid_header"> |
|
530 |
+ <img src="', $settings['default_images_url'], '/simpledesk/relationships.png" alt="x" />', $txt['shd_ticket_relationships'], ' (', $context['relationships_count'], ') |
|
531 |
+ </h3> |
|
532 |
+ </div> |
|
533 |
+ <div class="windowbg2"> |
|
534 |
+ <div class="shd_attachmentbox">'; |
|
535 |
+ |
|
536 |
+ foreach ($context['ticket_relationships'] as $rel_type => $relationships) |
|
537 |
+ { |
|
538 |
+ if (empty($relationships)) |
|
539 |
+ continue; |
|
540 |
+ |
|
541 |
+ echo ' |
|
542 |
+ <img src="', $settings['default_images_url'], '/simpledesk/rel_', $rel_type, '.png" alt="" /> <strong>', $txt['shd_ticket_reltype_' . $rel_type], ':</strong><br />'; |
|
543 |
+ |
|
544 |
+ foreach ($relationships as $rel) |
|
545 |
+ { |
|
546 |
+ echo ' |
|
547 |
+ '; |
|
548 |
+ |
|
549 |
+ if (!empty($context['delete_relationships'])) |
|
550 |
+ echo '<a href="', $scripturl, '?action=helpdesk;sa=relation;ticket=', $context['ticket_id'], ';otherticket=', $rel['id'], ';relation=delete;', $context['session_var'], '=', $context['session_id'], '"><img class="shd_smallicon" src="', $settings['default_images_url'], '/simpledesk/delete.png" alt="', $txt['shd_ticket_delete_relationship'], '" title="', $txt['shd_ticket_delete_relationship'], '" /></a>'; |
|
551 |
+ |
|
552 |
+ echo '<span class="smalltext">[', $rel['display_id'], '] <a href="', $scripturl, '?action=helpdesk;sa=ticket;ticket=', $rel['id'], '">', $rel['subject'], '</a> (', $rel['status_txt'], ')</span><br />'; |
|
553 |
+ } |
|
554 |
+ } |
|
555 |
+ |
|
556 |
+ if (!empty($context['create_relationships'])) |
|
557 |
+ { |
|
558 |
+ if ($context['relationships_count'] > 0) |
|
559 |
+ echo ' |
|
560 |
+ <hr />'; |
|
561 |
+ |
|
562 |
+ echo ' |
|
563 |
+ ', $txt['shd_ticket_create_relationship'], ': |
|
564 |
+ <form action="', $scripturl, '?action=helpdesk;sa=relation" method="post"> |
|
565 |
+ <select name="relation"> |
|
566 |
+ <option value="">', $txt['shd_ticket_reltype'], '</option>'; |
|
567 |
+ |
|
568 |
+ $rel_type_list = array('parent', 'child', 'linked', 'duplicated'); |
|
569 |
+ foreach ($rel_type_list as $type) |
|
570 |
+ echo ' |
|
571 |
+ <option value="', $type, '">', $txt['shd_ticket_reltype_' . $type], '</option>'; |
|
572 |
+ |
|
573 |
+ echo ' |
|
574 |
+ </select> |
|
575 |
+ <input type="text" class="input_text" name="otherticket" value="" size="5" /> |
|
576 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
577 |
+ <input type="hidden" name="ticket" value="', $context['ticket_id'], '" /> |
|
578 |
+ <input type="submit" class="button_submit" value="', $txt['shd_go'], '" /> |
|
579 |
+ </form>'; |
|
580 |
+ } |
|
581 |
+ |
|
582 |
+ echo ' |
|
583 |
+ </div> |
|
584 |
+ <span class="botslice"><span></span></span> |
|
585 |
+ </div> |
|
586 |
+ <br />'; |
|
587 |
+ } |
|
588 |
+} |
|
589 |
+ |
|
590 |
+/** |
|
591 |
+ * Display the events on a ticket. |
|
592 |
+ * |
|
593 |
+ * Displays all the non-post type events that apply to the current ticket, as a subset of the master action log. Data is gathered from {@link shd_load_action_log_entries()} |
|
594 |
+ * |
|
595 |
+ * @since 1.1 |
|
596 |
+*/ |
|
597 |
+function template_ticketactionlog() |
|
598 |
+{ |
|
599 |
+ global $context, $settings, $txt, $scripturl; |
|
600 |
+ if (!empty($context['display_ticket_log'])) |
|
601 |
+ { |
|
602 |
+ echo ' |
|
603 |
+ <br /> |
|
604 |
+ <div class="tborder"> |
|
605 |
+ <div class="cat_bar"> |
|
606 |
+ <h3 class="catbg" id="ticket_log_header"> |
|
607 |
+ <span class="floatright shd_ticket_log_expand_container"><a href="javascript:ActionLog.swap();"><img src="', $settings['images_url'], '/expand.gif" alt="+" id="shd_ticket_log_expand" class="icon" /></a></span> |
|
608 |
+ <img src="', $settings['default_images_url'], '/simpledesk/log.png" class="icon" alt="*" /> |
|
609 |
+ <a href="javascript:ActionLog.swap();">', $txt['shd_ticket_log'], '</a> |
|
610 |
+ <span class="smalltext">(', $context['ticket_log_count'] == 1 ? $txt['shd_ticket_log_count_one'] : sprintf($txt['shd_ticket_log_count_more'],$context['ticket_log_count']) , ')</span> |
|
611 |
+ </h3> |
|
612 |
+ </div> |
|
613 |
+ <table class="shd_ticketlist" id="ticket_log" cellspacing="0" width="100%" style="display: none;"> |
|
614 |
+ <tr class="titlebg"> |
|
615 |
+ <td width="15%"> |
|
616 |
+ <img src="', $settings['default_images_url'], '/simpledesk/time.png" class="shd_smallicon" alt="" /> |
|
617 |
+ ', $txt['shd_ticket_log_date'], ' |
|
618 |
+ </td> |
|
619 |
+ <td width="15%"> |
|
620 |
+ <img src="', $settings['default_images_url'], '/simpledesk/user.png" class="shd_smallicon" alt="" /> |
|
621 |
+ ', $txt['shd_ticket_log_member'], ' |
|
622 |
+ </td> |
|
623 |
+ <td width="50%"> |
|
624 |
+ <img src="', $settings['default_images_url'], '/simpledesk/action.png" class="shd_smallicon" alt="" /> |
|
625 |
+ ', $txt['shd_ticket_log_action'], ' |
|
626 |
+ </td> |
|
627 |
+ </tr>'; |
|
628 |
+ |
|
629 |
+ if (empty($context['ticket_log'])) |
|
630 |
+ echo ' |
|
631 |
+ <tr class="windowbg2"> |
|
632 |
+ <td colspan="3" class="shd_noticket">', $txt['shd_ticket_log_none'], '</td> |
|
633 |
+ </tr>'; |
|
634 |
+ else |
|
635 |
+ { |
|
636 |
+ $use_bg2 = true; // start with windowbg2 to differentiate between that and windowbg2 |
|
637 |
+ foreach ($context['ticket_log'] as $action) |
|
638 |
+ { |
|
639 |
+ echo ' |
|
640 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
641 |
+ <td class="smalltext">', $action['time'], '</td> |
|
642 |
+ <td', !empty($action['member']['ip']) ? ' title="' . $txt['shd_ticket_log_ip'] . ' ' . $action['member']['ip'] . '"' : '', '>', $action['member']['link'], ' <span class="smalltext">(', $action['member']['group'], ')</span></td> |
|
643 |
+ <td class="smalltext"> |
|
644 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $action['action_icon'], '" alt="" class="shd_smallicon" /> |
|
645 |
+ ', $action['action_text'], ' |
|
646 |
+ </td> |
|
647 |
+ </tr>'; |
|
648 |
+ |
|
649 |
+ $use_bg2 = !$use_bg2; |
|
650 |
+ } |
|
651 |
+ } |
|
652 |
+ |
|
653 |
+ echo ' |
|
654 |
+ <tr class="titlebg"> |
|
655 |
+ <td colspan="3"> |
|
656 |
+ ', !empty($context['ticket_full_log']) ? '<span class="smalltext shd_main_log"><img src="' . $settings['default_images_url'] . '/simpledesk/browse.png" alt="" /> <a href="' . $scripturl . '?action=admin;area=helpdesk_info;sa=actionlog">' . $txt['shd_ticket_log_full'] . '</a></span>' : '', ' |
|
657 |
+ </td> |
|
658 |
+ </tr> |
|
659 |
+ </table> |
|
660 |
+ </div>'; |
|
661 |
+ } |
|
662 |
+} |
|
663 |
+?> |
|
0 | 664 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,182 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk merge/split template |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * This file handles gathering information from users for splitting and merging topics. |
|
6 |
+ * |
|
7 |
+ * @package template |
|
8 |
+ * @since 1.1 |
|
9 |
+*/ |
|
10 |
+ |
|
11 |
+/** |
|
12 |
+ * Display a list of requirements for merging tickets |
|
13 |
+ * |
|
14 |
+ * @see shd_merge_ticket() |
|
15 |
+ * @see shd_merge_ticket2() |
|
16 |
+ * |
|
17 |
+ * @since 1.1 |
|
18 |
+*/ |
|
19 |
+function template_shd_merge_ticket() |
|
20 |
+{ |
|
21 |
+ global $txt, $settings, $context, $scripturl, $modSettings; |
|
22 |
+ |
|
23 |
+ // Back to the helpdesk. |
|
24 |
+ echo ' |
|
25 |
+ <div class="floatleft"> |
|
26 |
+ ', template_button_strip(array($context['navigation']['back']), 'bottom'), ' |
|
27 |
+ </div><br class="clear" />'; |
|
28 |
+ |
|
29 |
+ echo ' |
|
30 |
+ <div class="cat_bar"> |
|
31 |
+ <h3 class="catbg grid_header"> |
|
32 |
+ <img src="', $settings['default_images_url'] , '/simpledesk/merge.png" alt="*" /> |
|
33 |
+ ', $txt['shd_ticket_merge_tickets'], ' |
|
34 |
+ </h3> |
|
35 |
+ </div> |
|
36 |
+ <div class="roundframe"> |
|
37 |
+ <form action="', $scripturl, '?action=helpdesk;sa=mergeticket2;ticket=', $context['ticket_id'], '" method="post" onsubmit="submitonce(this);"> |
|
38 |
+ <div class="content"> |
|
39 |
+ <dl class="settings"> |
|
40 |
+ <dt> |
|
41 |
+ <strong>', $txt['shd_ticket_to_merge'], ':</strong> |
|
42 |
+ </dt> |
|
43 |
+ <dd> |
|
44 |
+ ', $context['current_ticket']['subject'], ' |
|
45 |
+ </dd> |
|
46 |
+ <dt> |
|
47 |
+ <strong>', $txt['shd_merge_send_pm'], ':</strong> |
|
48 |
+ </dt> |
|
49 |
+ <dd> |
|
50 |
+ <input type="checkbox" name="send_pm" id="send_pm" checked="checked" onclick="document.getElementById(\'pm_message\').style.display = this.checked ? \'block\' : \'none\';" class="input_check" /> |
|
51 |
+ </dd> |
|
52 |
+ </dl> |
|
53 |
+ <fieldset id="pm_message"> |
|
54 |
+ <dl class="settings"> |
|
55 |
+ <dt> |
|
56 |
+ ', $txt['shd_merge_why'], ' |
|
57 |
+ </dt> |
|
58 |
+ <dd> |
|
59 |
+ <textarea name="pm_content" rows="9" cols="70">', $txt['shd_merge_default_msg'], '</textarea> |
|
60 |
+ </dd> |
|
61 |
+ </dl> |
|
62 |
+ </fieldset>'; |
|
63 |
+ |
|
64 |
+ echo ' |
|
65 |
+ <input type="submit" value="', $txt['shd_merge_ticket'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" /> |
|
66 |
+ <input type="submit" name="cancel" value="', $txt['shd_cancel_ticket'], '" accesskey="c" class="button_submit" /> |
|
67 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
68 |
+ <input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" /> |
|
69 |
+ </div> |
|
70 |
+ </form> |
|
71 |
+ </div> |
|
72 |
+ <span class="lowerframe"><span></span></span>'; |
|
73 |
+} |
|
74 |
+ |
|
75 |
+/** |
|
76 |
+ * Display the information requirements for splitting tickets. |
|
77 |
+ * |
|
78 |
+ * @see shd_split_ticket() |
|
79 |
+ * @see shd_split_ticket2() |
|
80 |
+ * |
|
81 |
+ * @since 1.1 |
|
82 |
+*/ |
|
83 |
+function template_shd_split_ticket() |
|
84 |
+{ |
|
85 |
+ global $context, $txt, $scripturl, $settings; |
|
86 |
+ |
|
87 |
+ // Back to the helpdesk. |
|
88 |
+ echo ' |
|
89 |
+ <div class="floatleft"> |
|
90 |
+ ', template_button_strip(array($context['navigation']['back']), 'bottom'), ' |
|
91 |
+ </div><br class="clear" />'; |
|
92 |
+ |
|
93 |
+ echo ' |
|
94 |
+ <div class="cat_bar"> |
|
95 |
+ <h3 class="catbg grid_header"> |
|
96 |
+ <img src="', $settings['default_images_url'], '/simpledesk/split.png" alt="*" /> |
|
97 |
+ ', $txt['shd_split_ticket'], ' |
|
98 |
+ </h3> |
|
99 |
+ </div> |
|
100 |
+ <div class="roundframe"> |
|
101 |
+ <form action="', $scripturl, '?action=helpdesk;sa=splitticket2;ticket=', $context['ticket_id'], '" method="post" onsubmit="submitonce(this);"> |
|
102 |
+ <div class="content"> |
|
103 |
+ <dl class="settings"> |
|
104 |
+ <dt> |
|
105 |
+ <strong>', $txt['shd_split_new_subject'], ':</strong> |
|
106 |
+ </dt> |
|
107 |
+ <dd> |
|
108 |
+ <input type="text" size="50" name="new_subject" value="', $context['ticket_title'], '" /> |
|
109 |
+ </dd> |
|
110 |
+ <dt> |
|
111 |
+ <strong>', $txt['shd_split_type'], '</strong> |
|
112 |
+ </dt> |
|
113 |
+ <dd> |
|
114 |
+ <input type="radio" name="split_type" id="onlythis" value="onlythis" checked="checked" class="input_radio" /><label for="onlythis">', $txt['shd_split_only_this'], '</label><br /> |
|
115 |
+ <input type="radio" name="split_type" id="afterthis" value="afterthis" class="input_radio" /><label for="afterthis">', $txt['shd_split_after_this'], '</label> |
|
116 |
+ </dd> |
|
117 |
+ <dt> |
|
118 |
+ <strong>', $txt['shd_split_send_pm'], ':</strong> |
|
119 |
+ <div class="smalltext">', $txt['shd_split_why_note'], '</div> |
|
120 |
+ </dt> |
|
121 |
+ <dd> |
|
122 |
+ <input type="checkbox" name="send_pm" id="send_pm" checked="checked" onclick="document.getElementById(\'pm_message\').style.display = this.checked ? \'block\' : \'none\';" class="input_check" /> |
|
123 |
+ </dd> |
|
124 |
+ </dl> |
|
125 |
+ <fieldset id="pm_message"> |
|
126 |
+ <dl class="settings"> |
|
127 |
+ <dt> |
|
128 |
+ ', $txt['shd_split_why'], ' |
|
129 |
+ </dt> |
|
130 |
+ <dd> |
|
131 |
+ <textarea name="pm_content" rows="9" cols="70">', $txt['shd_split_default_msg'], '</textarea> |
|
132 |
+ </dd> |
|
133 |
+ </dl> |
|
134 |
+ </fieldset> |
|
135 |
+ <div style="margin-top:5px;"> |
|
136 |
+ <input type="submit" class="button_submit" value="', $txt['shd_split_ticket'], '" /> |
|
137 |
+ </div> |
|
138 |
+ </div> |
|
139 |
+ <input type="hidden" name="at_msg" value="', $_REQUEST['at_msg'], '" /> |
|
140 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
141 |
+ </form> |
|
142 |
+ </div> |
|
143 |
+ <span class="lowerframe"><span></span></span>'; |
|
144 |
+} |
|
145 |
+ |
|
146 |
+/** |
|
147 |
+ * Display a choice of options to the user of where to go once a ticket has been split. |
|
148 |
+ * |
|
149 |
+ * @see shd_split_ticket2() |
|
150 |
+ * |
|
151 |
+ * @since 1.1 |
|
152 |
+*/ |
|
153 |
+function template_shd_split_ticket2() |
|
154 |
+{ |
|
155 |
+ global $context, $txt, $scripturl, $settings; |
|
156 |
+ |
|
157 |
+ // Back to the helpdesk. |
|
158 |
+ echo ' |
|
159 |
+ <div class="floatleft"> |
|
160 |
+ ', template_button_strip(array($context['navigation']['back']), 'bottom'), ' |
|
161 |
+ </div><br class="clear" />'; |
|
162 |
+ |
|
163 |
+ echo ' |
|
164 |
+ <div class="cat_bar"> |
|
165 |
+ <h3 class="catbg grid_header"> |
|
166 |
+ <img src="', $settings['default_images_url'], '/simpledesk/split.png" alt="*" /> |
|
167 |
+ ', $txt['shd_split_ticket'], ' |
|
168 |
+ </h3> |
|
169 |
+ </div> |
|
170 |
+ <div class="roundframe"> |
|
171 |
+ <div class="content"> |
|
172 |
+ <p class="split_topics"><strong>', $txt['shd_split_done'], '</strong></p> |
|
173 |
+ <ul class="reset split_topics"> |
|
174 |
+ <li><a href="', $scripturl, '?action=helpdesk;sa=main">', $txt['shd_home'], '</a></li> |
|
175 |
+ <li><a href="', $scripturl, '?action=helpdesk;sa=ticket;ticket=', $context['split_info']['ticket'], '">', $txt['shd_split_origin_ticket'], '</a> (', $context['split_info']['subject'], ')</li> |
|
176 |
+ <li><a href="', $scripturl, '?action=helpdesk;sa=ticket;ticket=', $context['split_info']['otherticket'], '">', $txt['shd_split_new_ticket'], '</a> (', $context['split_info']['othersubject'], ')</li> |
|
177 |
+ </ul> |
|
178 |
+ </div> |
|
179 |
+ </div> |
|
180 |
+ <span class="lowerframe"><span></span></span>'; |
|
181 |
+} |
|
182 |
+?> |
|
0 | 183 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,615 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk posting and replying |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * This file handles everything concerning posting, including displaying the display of ticket facia |
|
6 |
+ * around a post box, display of replies with insert-quote links, the postbox, attachments, errors etc. |
|
7 |
+ * |
|
8 |
+ * @package template |
|
9 |
+ * @todo Finish documenting this file. |
|
10 |
+ * @since 1.0 |
|
11 |
+*/ |
|
12 |
+ |
|
13 |
+/** |
|
14 |
+ * Entry point for displaying the post new ticket/edit ticket UI. |
|
15 |
+ * |
|
16 |
+ * @since 1.0 |
|
17 |
+*/ |
|
18 |
+ |
|
19 |
+function template_ticket_post() |
|
20 |
+{ |
|
21 |
+ global $context; |
|
22 |
+ |
|
23 |
+ // Back to the helpdesk. |
|
24 |
+ echo ' |
|
25 |
+ <div class="floatleft"> |
|
26 |
+ ', template_button_strip(array($context['navigation']['back']), 'bottom'), ' |
|
27 |
+ </div><br class="clear" />'; |
|
28 |
+ |
|
29 |
+ template_preview(); |
|
30 |
+ template_ticket_info(); |
|
31 |
+ template_ticket_subjectbox(); |
|
32 |
+ template_ticket_meta(); |
|
33 |
+ template_ticket_postbox(); |
|
34 |
+ template_ticket_footer(); |
|
35 |
+ if (!empty($context['ticket_form']['do_replies'])) |
|
36 |
+ { |
|
37 |
+ template_ticket_begin_replies(); |
|
38 |
+ template_ticket_do_replies(); |
|
39 |
+ template_ticket_end_replies(); |
|
40 |
+ } |
|
41 |
+ template_ticket_pageend(); |
|
42 |
+ template_ticket_proxy_js(); |
|
43 |
+} |
|
44 |
+ |
|
45 |
+function template_reply_post() |
|
46 |
+{ |
|
47 |
+ global $context; |
|
48 |
+ |
|
49 |
+ template_ticket_info(); |
|
50 |
+ template_ticket_content(); |
|
51 |
+ template_ticket_meta(); |
|
52 |
+ template_ticket_footer(); |
|
53 |
+ template_preview(); |
|
54 |
+ template_ticket_shd_replyarea(); |
|
55 |
+ if (!empty($context['ticket_form']['do_replies'])) |
|
56 |
+ { |
|
57 |
+ template_ticket_begin_replies(); |
|
58 |
+ template_ticket_do_replies(); |
|
59 |
+ template_ticket_end_replies(); |
|
60 |
+ } |
|
61 |
+ template_ticket_pageend(); |
|
62 |
+} |
|
63 |
+ |
|
64 |
+// yes, this isn't strictly conventional SMF style |
|
65 |
+function template_ticket_option($option) |
|
66 |
+{ |
|
67 |
+ global $context, $txt; |
|
68 |
+ |
|
69 |
+ if (!empty($context['ticket_form'][$option]['can_change'])) |
|
70 |
+ { |
|
71 |
+ echo ' |
|
72 |
+ <select name="shd_' . $option . '">'; |
|
73 |
+ foreach ($context['ticket_form'][$option]['options'] as $value => $caption) |
|
74 |
+ { |
|
75 |
+ echo ' |
|
76 |
+ <option value="', $value, '"', ($value == $context['ticket_form'][$option]['setting'] ? ' selected="selected"' : ''), '>', $txt[$caption], '</option>'; |
|
77 |
+ } |
|
78 |
+ echo ' |
|
79 |
+ </select>'; |
|
80 |
+ } |
|
81 |
+ else |
|
82 |
+ echo $txt[$context['ticket_form'][$option]['options'][$context['ticket_form'][$option]['setting']]]; |
|
83 |
+} |
|
84 |
+ |
|
85 |
+function template_ticket_info() |
|
86 |
+{ |
|
87 |
+ global $context, $txt, $scripturl, $settings, $modSettings, $options; |
|
88 |
+ |
|
89 |
+ echo ' |
|
90 |
+ <form action="', $context['ticket_form']['form_action'], '" method="post" accept-charset="', $context['character_set'], '" name="postmodify" id="postmodify" onsubmit="', 'submitonce(this);smc_saveEntities(\'postmodify\', [\'subject\', \'', $context['post_box_name'], '\'], \'options\');" enctype="multipart/form-data" style="margin: 0;"> |
|
91 |
+ <div class="tborder"> |
|
92 |
+ <div class="cat_bar"> |
|
93 |
+ <h3 class="catbg grid_header"> |
|
94 |
+ <img src="', $settings['default_images_url'], '/simpledesk/ticket.png" alt="x" /> ', $context['ticket_form']['form_title'], ' |
|
95 |
+ </h3> |
|
96 |
+ </div> |
|
97 |
+ <div class="windowbg"> |
|
98 |
+ <div class="content shd_ticket">'; |
|
99 |
+ |
|
100 |
+ // General ticket details |
|
101 |
+ echo ' |
|
102 |
+ <div class="information shd_ticketdetails"> |
|
103 |
+ <strong><img src="', $settings['default_images_url'], '/simpledesk/details.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_details'], '</strong> |
|
104 |
+ <hr /> |
|
105 |
+ <ul>'; |
|
106 |
+ |
|
107 |
+ if (!empty($context['ticket_form']['display_id'])) |
|
108 |
+ echo ' |
|
109 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/id.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_id'], ': ', $context['ticket_form']['display_id'], '</li>'; |
|
110 |
+ |
|
111 |
+ if (!empty($context['ticket_form']['member']['link'])) |
|
112 |
+ echo ' |
|
113 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/user.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_user'], ': ', $context['ticket_form']['member']['link'], '</li>'; |
|
114 |
+ |
|
115 |
+ echo ' |
|
116 |
+ <li> |
|
117 |
+ <img src="', $settings['default_images_url'], '/simpledesk/urgency.png" alt="" class="shd_smallicon" /> |
|
118 |
+ ', $txt['shd_ticket_urgency'], ': ', template_ticket_option('urgency'), ' |
|
119 |
+ </li>'; |
|
120 |
+ |
|
121 |
+ // New tickets aren't assigned - ever - but existing ones might be |
|
122 |
+ if (!empty($context['ticket_form']['ticket'])) |
|
123 |
+ echo ' |
|
124 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/staff.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_assignedto'], ': ', !empty($context['ticket_form']['assigned']['link']) ? $context['ticket_form']['assigned']['link'] : '<span class="error">' . $txt['shd_unassigned'] . '</span>', '</li>'; |
|
125 |
+ |
|
126 |
+ echo ' |
|
127 |
+ <li><img src="', $settings['default_images_url'], '/simpledesk/status.png" alt="" class="shd_smallicon"/> ', $txt['shd_ticket_status'], ': ', $txt['shd_status_' . $context['ticket_form']['status']], '</li>'; |
|
128 |
+ |
|
129 |
+ if (!empty($context['display_private'])) |
|
130 |
+ echo ' |
|
131 |
+ <li> |
|
132 |
+ <img src="', $settings['default_images_url'], '/simpledesk/private.png" alt="" class="shd_smallicon" /> |
|
133 |
+ ', $txt['shd_ticket_privacy'], ': ', template_ticket_option('private'), ' |
|
134 |
+ </li> |
|
135 |
+ </ul>'; |
|
136 |
+ |
|
137 |
+ // Display ticket poster avatar? |
|
138 |
+ if (!empty($modSettings['shd_display_avatar']) && empty($options['show_no_avatars']) && !empty($context['ticket_form']['member']['avatar']['image'])) |
|
139 |
+ echo ' |
|
140 |
+ <div class="shd_ticket_avatar"> |
|
141 |
+ ', shd_profile_link($context['ticket_form']['member']['avatar']['image'], $context['ticket_form']['member']['id']), ' |
|
142 |
+ </div>'; |
|
143 |
+ |
|
144 |
+ echo ' |
|
145 |
+ </div>'; |
|
146 |
+} |
|
147 |
+ |
|
148 |
+function template_ticket_posterrors() |
|
149 |
+{ |
|
150 |
+ global $context, $txt; |
|
151 |
+ |
|
152 |
+ // Did anything go wrong? |
|
153 |
+ if (!empty($context['shd_errors'])) |
|
154 |
+ { |
|
155 |
+ echo ' |
|
156 |
+ <div class="errorbox" id="errors"> |
|
157 |
+ <dl> |
|
158 |
+ <dt> |
|
159 |
+ <strong style="" id="error_serious">', $txt['shd_ticket_post_error'], ':</strong> |
|
160 |
+ </dt> |
|
161 |
+ <dt class="error" id="error_list">'; |
|
162 |
+ |
|
163 |
+ foreach ($context['shd_errors'] as $error) |
|
164 |
+ echo ' |
|
165 |
+ ', $txt['error_' . $error], '<br />'; |
|
166 |
+ |
|
167 |
+ echo ' |
|
168 |
+ </dt> |
|
169 |
+ </dl> |
|
170 |
+ </div>'; |
|
171 |
+ } |
|
172 |
+} |
|
173 |
+ |
|
174 |
+function template_ticket_subjectbox() |
|
175 |
+{ |
|
176 |
+ global $context, $txt, $scripturl, $settings, $modSettings; |
|
177 |
+ |
|
178 |
+ echo ' |
|
179 |
+ <div class="shd_ticket_description">'; |
|
180 |
+ |
|
181 |
+ template_ticket_posterrors(); |
|
182 |
+ echo ' |
|
183 |
+ <img src="', $settings['default_images_url'], '/simpledesk/description.png" alt="" class="shd_smallicon" /> <strong>', $txt['shd_ticket_subject'], ':</strong> |
|
184 |
+ <input type="text" name="subject" size="50" maxlength="100" class="input_text" value="', $context['ticket_form']['subject'], '" tabindex="', $context['tabindex']++, '" />'; |
|
185 |
+ |
|
186 |
+ // Are we dealing with proxy tickets? |
|
187 |
+ if (!empty($context['can_post_proxy'])) |
|
188 |
+ { |
|
189 |
+ echo ' |
|
190 |
+ <br /> |
|
191 |
+ <input type="hidden" name="proxy" value="" /> |
|
192 |
+ <img src="', $settings['default_images_url'], '/simpledesk/proxy.png" alt="" class="shd_smallicon" /> <strong>', $txt['shd_ticket_proxy'], ':</strong> |
|
193 |
+ <input type="text" name="proxy_author" id="proxy_author" size="50" maxlength="100" class="input_text" value="', (empty($context['ticket_form']['proxy']) ? '' : $context['ticket_form']['proxy']), '" tabindex="', $context['tabindex']++, '" />'; |
|
194 |
+ } |
|
195 |
+ |
|
196 |
+ echo ' |
|
197 |
+ <hr /><br /> |
|
198 |
+ '; |
|
199 |
+} |
|
200 |
+ |
|
201 |
+function template_ticket_proxy_js() |
|
202 |
+{ |
|
203 |
+ global $context, $txt, $scripturl, $settings, $modSettings; |
|
204 |
+ if (empty($context['can_post_proxy'])) |
|
205 |
+ return; |
|
206 |
+ |
|
207 |
+ echo ' |
|
208 |
+ <script type="text/javascript" src="', $settings['default_theme_url'], '/scripts/suggest.js?rc3"></script> |
|
209 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
210 |
+ var oProxyAutoSuggest = new smc_AutoSuggest({ |
|
211 |
+ sSelf: \'oProxyAutoSuggest\', |
|
212 |
+ sSessionId: \'', $context['session_id'], '\', |
|
213 |
+ sSessionVar: \'', $context['session_var'], '\', |
|
214 |
+ sControlId: \'proxy_author\', |
|
215 |
+ sSearchType: \'member\', |
|
216 |
+ sPostName: \'proxy_author_form\', |
|
217 |
+ sURLMask: \'action=profile;u=%item_id%\', |
|
218 |
+ bItemList: false, |
|
219 |
+ iMaxDisplayQuantity: 1 |
|
220 |
+ }); |
|
221 |
+ // ]', ']></script>'; |
|
222 |
+} |
|
223 |
+ |
|
224 |
+function template_ticket_content() |
|
225 |
+{ |
|
226 |
+ global $context, $txt, $scripturl, $settings, $modSettings; |
|
227 |
+ |
|
228 |
+ echo ' |
|
229 |
+ <div class="shd_ticket_description">'; |
|
230 |
+ |
|
231 |
+ template_ticket_posterrors(); |
|
232 |
+ echo ' |
|
233 |
+ <img src="', $settings['default_images_url'], '/simpledesk/description.png" alt="" class="shd_smallicon" /> <strong>', $context['ticket_form']['subject'], '</strong> |
|
234 |
+ <hr /><br /> |
|
235 |
+ ', $context['ticket_form']['message']; |
|
236 |
+ |
|
237 |
+ if ($settings['show_modify'] && !empty($context['ticket']['modified'])) |
|
238 |
+ { |
|
239 |
+ echo ' |
|
240 |
+ <div class="smalltext shd_modified" style="margin-top:20px;"> |
|
241 |
+ « <em>', $txt['last_edit'], ': ', $context['ticket']['modified']['time'], ' ', $txt['by'], ' ', $context['ticket']['modified']['link'], '</em> » |
|
242 |
+ </div>'; |
|
243 |
+ } |
|
244 |
+} |
|
245 |
+ |
|
246 |
+function template_ticket_meta() |
|
247 |
+{ |
|
248 |
+ global $context; |
|
249 |
+ |
|
250 |
+ // Management/meta information |
|
251 |
+ echo ' |
|
252 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
253 |
+ <input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" />'; |
|
254 |
+ |
|
255 |
+ if (!empty($context['ticket_form']['ticket'])) |
|
256 |
+ echo ' |
|
257 |
+ <input type="hidden" name="ticket" value="', $context['ticket_form']['ticket'], '" />'; |
|
258 |
+ |
|
259 |
+ if (!empty($context['ticket_form']['msg'])) |
|
260 |
+ echo ' |
|
261 |
+ <input type="hidden" name="msg" value="', $context['ticket_form']['msg'], '" />'; |
|
262 |
+ |
|
263 |
+ if (!empty($context['ticket_form']['num_replies'])) |
|
264 |
+ echo ' |
|
265 |
+ <input type="hidden" name="num_replies" value="', $context['ticket_form']['num_replies'], '" />'; |
|
266 |
+} |
|
267 |
+ |
|
268 |
+function template_ticket_shd_replyarea() |
|
269 |
+{ |
|
270 |
+ global $context, $settings, $scripturl, $txt; |
|
271 |
+ echo ' |
|
272 |
+ <div class="tborder"> |
|
273 |
+ <div class="title_bar"> |
|
274 |
+ <h3 class="titlebg grid_header"> |
|
275 |
+ <img src="', $settings['default_images_url'], '/simpledesk/respond.png" alt="x" /> |
|
276 |
+ ', !empty($context['ticket_form']['form_title']) ? $context['ticket_form']['form_title'] : $txt['shd_reply_ticket'], ' |
|
277 |
+ </h3> |
|
278 |
+ </div> |
|
279 |
+ <div class="roundframe"> |
|
280 |
+ <div class="content">'; |
|
281 |
+ |
|
282 |
+ template_ticket_postbox(); |
|
283 |
+ |
|
284 |
+ echo ' |
|
285 |
+ </div> |
|
286 |
+ </div> |
|
287 |
+ <span class="lowerframe"><span></span></span> |
|
288 |
+ </div> |
|
289 |
+ <br />'; |
|
290 |
+} |
|
291 |
+ |
|
292 |
+function template_ticket_postbox() |
|
293 |
+{ |
|
294 |
+ global $modSettings, $context, $txt; |
|
295 |
+ $editor_context = &$context['controls']['richedit'][$context['post_box_name']]; |
|
296 |
+ |
|
297 |
+ // The postbox |
|
298 |
+ echo ' |
|
299 |
+ <div id="shd_bbcbox"', ((empty($modSettings['shd_allow_ticket_bbc']) || !empty($context['shd_display'])) ? ' style="display:none;"' : ''), '></div> |
|
300 |
+ <div id="shd_smileybox"', ((empty($modSettings['shd_allow_ticket_smileys']) || !empty($context['shd_display'])) ? ' style="display:none;"' : ''), '></div>'; |
|
301 |
+ |
|
302 |
+ echo template_control_richedit($context['post_box_name'], 'shd_smileybox', 'shd_bbcbox'); |
|
303 |
+ |
|
304 |
+ template_ticket_attachments(); |
|
305 |
+ |
|
306 |
+ echo ' |
|
307 |
+ <br class="clear" /> |
|
308 |
+ <span class="smalltext"><br />', $context['browser']['is_firefox'] ? $txt['shortcuts_firefox'] : $txt['shortcuts'], '</span><br /> |
|
309 |
+ <input type="submit" value="', isset($editor_context['labels']['post_button']) ? $editor_context['labels']['post_button'] : $txt['post'], '" tabindex="', $context['tabindex']++, '" accesskey="s" class="button_submit" /> |
|
310 |
+ <input class="button_submit" type="submit" name="preview" value="', $txt['preview'], '" accesskey="p" tabindex="', $context['tabindex']++, '" />'; |
|
311 |
+ |
|
312 |
+ template_ticket_additional_options(); |
|
313 |
+} |
|
314 |
+ |
|
315 |
+function template_ticket_footer() |
|
316 |
+{ |
|
317 |
+ global $settings, $context, $txt; |
|
318 |
+ |
|
319 |
+ if ($settings['show_modify'] && !empty($context['ticket_form']['modified'])) |
|
320 |
+ { |
|
321 |
+ echo ' |
|
322 |
+ <div class="smalltext shd_modified" style="margin-top:20px;"> |
|
323 |
+ « <em>', $txt['last_edit'], ': ', $context['ticket_form']['modified']['time'], ' ', $txt['by'], ' ', $context['ticket_form']['modified']['link'], '</em> » |
|
324 |
+ </div>'; |
|
325 |
+ } |
|
326 |
+ |
|
327 |
+ echo ' |
|
328 |
+ </div> |
|
329 |
+ </div> |
|
330 |
+ <span class="botslice"><span></span></span> |
|
331 |
+ </div> |
|
332 |
+ </div> |
|
333 |
+ <br />'; |
|
334 |
+} |
|
335 |
+ |
|
336 |
+function template_preview() |
|
337 |
+{ |
|
338 |
+ global $context, $txt, $settings; |
|
339 |
+ |
|
340 |
+ if (!empty($context['ticket_form']['preview'])) |
|
341 |
+ { |
|
342 |
+ echo ' |
|
343 |
+ <div class="tborder"> |
|
344 |
+ <div class="title_bar"> |
|
345 |
+ <h3 class="titlebg grid_header"> |
|
346 |
+ <img src="', $settings['default_images_url'], '/simpledesk/preview.png" alt="x" /> |
|
347 |
+ ', !empty($context['ticket_form']['preview']['title']) ? $context['ticket_form']['preview']['title'] : $txt['preview'], ' |
|
348 |
+ </h3> |
|
349 |
+ </div> |
|
350 |
+ <div class="roundframe"> |
|
351 |
+ <div class="content"> |
|
352 |
+ ', $context['ticket_form']['preview']['body'], ' |
|
353 |
+ </div> |
|
354 |
+ </div> |
|
355 |
+ <span class="lowerframe"><span></span></span> |
|
356 |
+ </div> |
|
357 |
+ <br />'; |
|
358 |
+ } |
|
359 |
+} |
|
360 |
+ |
|
361 |
+function template_ticket_attachments() |
|
362 |
+{ |
|
363 |
+ global $context, $modSettings, $txt; |
|
364 |
+ if (empty($context['current_attachments']) && empty($context['ticket_form']['do_attach'])) |
|
365 |
+ return; |
|
366 |
+ |
|
367 |
+ echo ' |
|
368 |
+ <div class="information shd_reply_attachments" id="shd_attach_container"', !empty($context['shd_display']) ? ' style="display:none;"' : '', '>'; |
|
369 |
+ |
|
370 |
+ if (!empty($context['current_attachments'])) |
|
371 |
+ { |
|
372 |
+ echo ' |
|
373 |
+ <dl id="postAttachment"> |
|
374 |
+ <dt> |
|
375 |
+ ', $txt['attached'], ': |
|
376 |
+ </dt> |
|
377 |
+ <dd class="smalltext"> |
|
378 |
+ <input type="hidden" name="attach_del[]" value="0" /> |
|
379 |
+ ', $txt['uncheck_unwatchd_attach'], ': |
|
380 |
+ </dd>'; |
|
381 |
+ foreach ($context['current_attachments'] as $attachment) |
|
382 |
+ echo ' |
|
383 |
+ <dd class="smalltext"> |
|
384 |
+ <label for="attachment_', $attachment['id'], '"><input type="checkbox" id="attachment_', $attachment['id'], '" name="attach_del[]" value="', $attachment['id'], '"', empty($attachment['unchecked']) ? ' checked="checked"' : '', ' class="input_check" onclick="javascript:oAttach.checkActive();" /> ', $attachment['name'], '</label> |
|
385 |
+ </dd>'; |
|
386 |
+ echo ' |
|
387 |
+ </dl>'; |
|
388 |
+ } |
|
389 |
+ |
|
390 |
+ if (!empty($context['ticket_form']['do_attach'])) |
|
391 |
+ { |
|
392 |
+ // JS for our pretty widget |
|
393 |
+ echo ' |
|
394 |
+ <dl id="postAttachment2"> |
|
395 |
+ <dt> |
|
396 |
+ ', $txt['attach'], ': |
|
397 |
+ </dt> |
|
398 |
+ <dd class="smalltext"> |
|
399 |
+ <input type="file" size="60" name="attachment" id="shd_attach" class="input_file" /> |
|
400 |
+ <div id="shd_attachlist_container"></div> |
|
401 |
+ </dd>'; |
|
402 |
+ |
|
403 |
+ echo ' |
|
404 |
+ <dd class="smalltext">'; |
|
405 |
+ |
|
406 |
+ // Show some useful information such as allowed extensions, maximum size and amount of attachments allowed. |
|
407 |
+ if (!empty($modSettings['attachmentCheckExtensions'])) |
|
408 |
+ echo ' |
|
409 |
+ ', $txt['allowed_types'], ': ', $context['allowed_extensions'], '<br />'; |
|
410 |
+ |
|
411 |
+ if (!empty($context['attachment_restrictions'])) |
|
412 |
+ echo ' |
|
413 |
+ ', $txt['attach_restrictions'], ' ', implode(', ', $context['attachment_restrictions']), '<br />'; |
|
414 |
+ |
|
415 |
+ echo ' |
|
416 |
+ </dd> |
|
417 |
+ </dl> |
|
418 |
+ <script type="text/javascript"><!-- // --><![CDATA[ |
|
419 |
+ var oAttach = new shd_attach_select({ |
|
420 |
+ file_item: "shd_attach", |
|
421 |
+ file_container: "shd_attachlist_container", |
|
422 |
+ max: ', $context['ticket_form']['num_allowed_attachments'], ', |
|
423 |
+ message_txt_delete: ', JavaScriptEscape($txt['remove']); |
|
424 |
+ |
|
425 |
+ if (!empty($modSettings['attachmentExtensions']) && !empty($modSettings['attachmentCheckExtensions'])) |
|
426 |
+ { |
|
427 |
+ $ext = explode(',', $modSettings['attachmentExtensions']); |
|
428 |
+ foreach ($ext as $k => $v) |
|
429 |
+ $ext[$k] = JavaScriptEscape($v); |
|
430 |
+ |
|
431 |
+ echo ', |
|
432 |
+ message_ext_error: ', JavaScriptEscape(str_replace('{attach_exts}', $context['allowed_extensions'], $txt['shd_cannot_attach_ext'])), ', |
|
433 |
+ attachment_ext: [', implode(',', $ext), ']'; |
|
434 |
+ } |
|
435 |
+ |
|
436 |
+ echo ' |
|
437 |
+ }); |
|
438 |
+ // ]]></script>'; |
|
439 |
+ } |
|
440 |
+ |
|
441 |
+ echo ' |
|
442 |
+ </div>'; |
|
443 |
+} |
|
444 |
+ |
|
445 |
+function template_ticket_additional_options() |
|
446 |
+{ |
|
447 |
+ global $context, $options, $txt, $modSettings; |
|
448 |
+ echo ' |
|
449 |
+ <div id="postMoreOptions" class="smalltext"> |
|
450 |
+ <ul class="post_options">'; |
|
451 |
+ |
|
452 |
+ foreach ($context['ticket_form']['additional_opts'] as $key => $details) |
|
453 |
+ { |
|
454 |
+ if (!empty($details['show'])) |
|
455 |
+ echo ' |
|
456 |
+ <li><label for="', $key, '"><input type="checkbox" name="', $key, '" id="', $key, '"', (!empty($details['checked']) ? ' checked="checked"' : ''), ' value="1" class="input_check" /> ', $details['text'], '</label></li>'; |
|
457 |
+ } |
|
458 |
+ |
|
459 |
+ echo ' |
|
460 |
+ </ul> |
|
461 |
+ </div>'; |
|
462 |
+} |
|
463 |
+ |
|
464 |
+function template_ticket_begin_replies() |
|
465 |
+{ |
|
466 |
+ global $context, $settings, $txt, $modSettings; |
|
467 |
+ |
|
468 |
+ // The replies column |
|
469 |
+ echo ' |
|
470 |
+ <div class="shd_ticket_rightcolumn floatleft" style="width: 100%;">'; |
|
471 |
+} |
|
472 |
+ |
|
473 |
+function template_ticket_do_replies() |
|
474 |
+{ |
|
475 |
+ global $context, $settings, $txt, $scripturl, $options, $modSettings, $reply_request; |
|
476 |
+ |
|
477 |
+ echo ' |
|
478 |
+ <div class="tborder"> |
|
479 |
+ <div class="title_bar"> |
|
480 |
+ <h3 class="titlebg grid_header"> |
|
481 |
+ <img src="', $settings['default_images_url'], '/simpledesk/replies.png" alt="x" /> ', $txt['shd_ticket_replies'], ' |
|
482 |
+ </h3> |
|
483 |
+ </div> |
|
484 |
+ <div class="roundframe" id="replies"> |
|
485 |
+ <div class="content">'; |
|
486 |
+ |
|
487 |
+ if (!empty($reply_request)) |
|
488 |
+ { |
|
489 |
+ while ($reply = $context['get_replies']()) |
|
490 |
+ { |
|
491 |
+ echo ' |
|
492 |
+ <div class="description shd_reply" id="reply', $reply['id'], '"> |
|
493 |
+ <span class="floatleft shd_posterinfo"> |
|
494 |
+ <strong class="shd_postername"> |
|
495 |
+ ', $reply['member']['link'], ' |
|
496 |
+ </strong> |
|
497 |
+ <br /> |
|
498 |
+ ', $reply['member']['group'], '<br class="shd_groupmargin" />'; |
|
499 |
+ |
|
500 |
+ if (!empty($modSettings['shd_display_avatar']) && empty($options['show_no_avatars']) && !empty($reply['member']['avatar']['image'])) |
|
501 |
+ echo ' |
|
502 |
+ ', shd_profile_link($reply['member']['avatar']['image'], $reply['member']['id']); |
|
503 |
+ |
|
504 |
+ if ($modSettings['shd_staff_badge'] == (!empty($reply['is_team']) ? 'staffbadge' : 'userbadge') || $modSettings['shd_staff_badge'] == 'bothbadge') |
|
505 |
+ echo '<br /> |
|
506 |
+ ', $reply['member']['group_stars']; |
|
507 |
+ elseif (!empty($reply['is_team']) && $modSettings['shd_staff_badge'] == 'nobadge') |
|
508 |
+ echo '<br /> |
|
509 |
+ <img src="', $settings['default_images_url'] . '/simpledesk/staff.png" class="shd_smallicon" title="', $txt['shd_ticket_staff'], '" alt="', $txt['shd_ticket_staff'], '" />'; |
|
510 |
+ |
|
511 |
+ echo ' |
|
512 |
+ </span> |
|
513 |
+ <div class="shd_replyarea"> |
|
514 |
+ <div class="smalltext"> |
|
515 |
+ <span class="floatright shd_ticketlinks">'; |
|
516 |
+ |
|
517 |
+ if ($context['can_quote']) |
|
518 |
+ echo ' |
|
519 |
+ <img src="', $settings['default_images_url'], '/simpledesk/quote.png" class="shd_smallicon" alt="*" /><a onclick="return oQuickReply.quote(', $reply['id'], ', \'', $context['session_id'], '\', \'', $context['session_var'], '\', true);" href="', $scripturl, '?action=helpdesk;sa=reply;ticket=', $context['ticket_id'], ';quote=', $reply['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['shd_ticket_quote_short'], '</a>'; |
|
520 |
+ |
|
521 |
+ echo ' |
|
522 |
+ </span> |
|
523 |
+ ', sprintf($txt['shd_reply_written'], $reply['time']), ' |
|
524 |
+ </div> |
|
525 |
+ <hr class="clearfix" /> |
|
526 |
+ ', $reply['body'], ' |
|
527 |
+ <br /><br />'; |
|
528 |
+ |
|
529 |
+ if ($settings['show_modify'] && !empty($reply['modified'])) |
|
530 |
+ { |
|
531 |
+ echo ' |
|
532 |
+ <div class="smalltext shd_modified" style="margin-top:20px;"> |
|
533 |
+ « <em>', $txt['last_edit'], ': ', $reply['modified']['time'], ' ', $txt['by'], ' ', $reply['modified']['link'], '</em> » |
|
534 |
+ </div>'; |
|
535 |
+ } |
|
536 |
+ |
|
537 |
+ if (!empty($context['ticket_attach']['reply'][$reply['id']])) |
|
538 |
+ { |
|
539 |
+ echo ' |
|
540 |
+ <div class="smalltext"> |
|
541 |
+ <strong>', $txt['shd_ticket_attachments'], '</strong><br /> |
|
542 |
+ <ul class="shd_replyattachments">'; |
|
543 |
+ |
|
544 |
+ foreach ($context['ticket_attach']['reply'][$reply['id']] as $attach) |
|
545 |
+ echo ' |
|
546 |
+ <li>', $attach['link'], '</li>'; |
|
547 |
+ |
|
548 |
+ echo ' |
|
549 |
+ </ul> |
|
550 |
+ </div>'; |
|
551 |
+ } |
|
552 |
+ |
|
553 |
+ echo ' |
|
554 |
+ </div>'; |
|
555 |
+ |
|
556 |
+ if (!empty($context['can_see_ip']) && !empty($reply['ip_address'])) |
|
557 |
+ echo ' |
|
558 |
+ <span class="floatright"><img src="', $settings['default_images_url'], '/simpledesk/ip.png" alt="" class="shd_smallicon" /> ', $txt['shd_ticket_ip'], ': ', $reply['ip_address'], '</span>'; |
|
559 |
+ |
|
560 |
+ echo ' |
|
561 |
+ <br class="clear" /> |
|
562 |
+ </div>'; |
|
563 |
+ } |
|
564 |
+ } |
|
565 |
+ |
|
566 |
+ echo ' |
|
567 |
+ </div> |
|
568 |
+ </div> |
|
569 |
+ <span class="lowerframe"><span></span></span> |
|
570 |
+ </div>'; |
|
571 |
+} |
|
572 |
+ |
|
573 |
+function template_ticket_end_replies() |
|
574 |
+{ |
|
575 |
+ |
|
576 |
+ // Close the table |
|
577 |
+ echo ' |
|
578 |
+ </div> |
|
579 |
+ <br class="clear" />'; |
|
580 |
+} |
|
581 |
+ |
|
582 |
+function template_ticket_pageend() |
|
583 |
+{ |
|
584 |
+ // And finally, good night, sweet form |
|
585 |
+ echo ' |
|
586 |
+ </form>'; |
|
587 |
+} |
|
588 |
+ |
|
589 |
+/** |
|
590 |
+ * Display the message thanking the user for posting. |
|
591 |
+ * |
|
592 |
+ * @see shd_done_posting() |
|
593 |
+ * @since 1.1 |
|
594 |
+*/ |
|
595 |
+function template_shd_thank_posting() |
|
596 |
+{ |
|
597 |
+ global $context, $settings, $options, $txt; |
|
598 |
+ |
|
599 |
+ echo ' |
|
600 |
+ <div id="fatal_error"> |
|
601 |
+ <div class="cat_bar"> |
|
602 |
+ <h3 class="catbg"> |
|
603 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $context['page_icon'], '" alt="x" class="shd_icon_minihead" /> ', $context['page_title'], ' |
|
604 |
+ </h3> |
|
605 |
+ </div> |
|
606 |
+ <div class="windowbg"> |
|
607 |
+ <span class="topslice"><span></span></span> |
|
608 |
+ <div class="padding">', $context['page_body'], '</div> |
|
609 |
+ <span class="botslice"><span></span></span> |
|
610 |
+ </div> |
|
611 |
+ </div> |
|
612 |
+ <br class="clear" />'; |
|
613 |
+} |
|
614 |
+ |
|
615 |
+?> |
|
0 | 616 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,526 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.1; SimpleDesk profile page template |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * This file handles displaying the blocks of the profile area for SimpleDesk. |
|
6 |
+ * |
|
7 |
+ * @package template |
|
8 |
+ * @since 1.1 |
|
9 |
+*/ |
|
10 |
+ |
|
11 |
+/** |
|
12 |
+ * Display the profile section. |
|
13 |
+ * |
|
14 |
+ * @since 1.1 |
|
15 |
+*/ |
|
16 |
+function template_shd_profile_main() |
|
17 |
+{ |
|
18 |
+ global $context, $txt, $settings, $scripturl; |
|
19 |
+ |
|
20 |
+ echo ' |
|
21 |
+ <div class="tborder shd_profile_navigation"> |
|
22 |
+ <div class="cat_bar"> |
|
23 |
+ <h3 class="catbg grid_header"> |
|
24 |
+ <img src="', $settings['default_images_url'], '/simpledesk/user.png" alt="" class="shd_icon_minihead" /> |
|
25 |
+ ', sprintf($txt['shd_profile_heading'], $context['member']['name']), ' |
|
26 |
+ </h3> |
|
27 |
+ </div> |
|
28 |
+ <div class="windowbg"> |
|
29 |
+ <div class="content"> |
|
30 |
+ <img src="', $settings['default_images_url'], '/simpledesk/ticket.png" alt="" class="shd_icon_minihead" /> <strong>', $txt['shd_profile_tickets'], '</strong><hr /> |
|
31 |
+ ', $txt['shd_profile_tickets_created'], ': <a href="', $scripturl, '?action=profile;u=', $context['member']['id'], ';area=hd_showtickets">', $context['shd_numtickets'], '</a>'; |
|
32 |
+ if (!empty($context['shd_numopentickets'])) |
|
33 |
+ echo ' <span class="smalltext">(', $context['shd_numopentickets'], ' ', $txt['shd_profile_currently_open'], ')</span>'; |
|
34 |
+ |
|
35 |
+ echo '<br /> |
|
36 |
+ ', $txt['shd_profile_tickets_assigned'], ': <a href="', $scripturl, '?action=profile;u=', $context['member']['id'], ';area=hd_showtickets">', $context['shd_numassigned'], '</a> |
|
37 |
+ |
|
38 |
+ <div class="description shd_showtickets floatright" id="shd_showtickets"> |
|
39 |
+ <a href="', $scripturl, '?action=profile;u=', $context['member']['id'], ';area=hd_showtickets">', $txt['shd_profile_view_tickets'], '</a><br /> |
|
40 |
+ </div>'; |
|
41 |
+ |
|
42 |
+ if (!empty($context['can_post_proxy'])) |
|
43 |
+ echo ' |
|
44 |
+ <div class="description shd_showtickets floatright" id="shd_post_proxy"> |
|
45 |
+ <a href="', $scripturl, '?action=helpdesk;sa=newticket;proxy=', $context['member']['id'], '">', $txt['shd_profile_proxy'], '</a><br /> |
|
46 |
+ </div>'; |
|
47 |
+ |
|
48 |
+ echo ' |
|
49 |
+ <br /><br /><br /> |
|
50 |
+ </div> |
|
51 |
+ <span class="botslice"><span></span></span> |
|
52 |
+ </div> |
|
53 |
+ </div>'; |
|
54 |
+} |
|
55 |
+ |
|
56 |
+function template_shd_profile_preferences() |
|
57 |
+{ |
|
58 |
+ global $context, $txt, $settings, $scripturl; |
|
59 |
+ |
|
60 |
+ if (isset($_GET['save'])) |
|
61 |
+ echo ' |
|
62 |
+ <div class="tborder"> |
|
63 |
+ <div class="windowbg" id="profile_success"> |
|
64 |
+ ', $txt['shd_prefs_updated'], ' |
|
65 |
+ </div> |
|
66 |
+ </div>'; |
|
67 |
+ |
|
68 |
+ echo ' |
|
69 |
+ <div class="tborder"> |
|
70 |
+ <div class="cat_bar"> |
|
71 |
+ <h3 class="catbg"> |
|
72 |
+ <img src="', $settings['default_images_url'], '/simpledesk/preferences.png" class="icon" alt="*" /> |
|
73 |
+ ', sprintf($txt['shd_profile_preferences_header'], $context['member']['name']), ' |
|
74 |
+ </h3> |
|
75 |
+ </div> |
|
76 |
+ </div> |
|
77 |
+ <form action="', $scripturl, '?action=profile;area=hd_prefs;u=', $context['member']['id'], ';save" method="post">'; |
|
78 |
+ |
|
79 |
+ $display_save = false; |
|
80 |
+ |
|
81 |
+ foreach ($context['shd_preferences_options']['groups'] as $group => $details) |
|
82 |
+ { |
|
83 |
+ if (empty($details['groups'])) |
|
84 |
+ continue; |
|
85 |
+ |
|
86 |
+ $display_save = true; |
|
87 |
+ |
|
88 |
+ echo ' |
|
89 |
+ <br /> |
|
90 |
+ <div class="tborder"> |
|
91 |
+ <div class="cat_bar"> |
|
92 |
+ <h3 class="catbg grid_header"> |
|
93 |
+ <img src="', shd_image_url($details['icon']), '" class="icon" alt="*" /> |
|
94 |
+ ', $txt['shd_pref_group_' . $group], ' |
|
95 |
+ </h3> |
|
96 |
+ </div> |
|
97 |
+ <div class="roundframe"> |
|
98 |
+ <div class="content"> |
|
99 |
+ <dl class="permsettings">'; |
|
100 |
+ |
|
101 |
+ foreach ($details['groups'] as $pref) |
|
102 |
+ { |
|
103 |
+ $thispref = $context['shd_preferences_options']['prefs'][$pref]; |
|
104 |
+ echo ' |
|
105 |
+ <dt> |
|
106 |
+ ', empty($thispref['icon']) ? '' : ('<img src="' . shd_image_url($thispref['icon']) . '" class="icon" alt="*" /> '), ' |
|
107 |
+ ', $txt['shd_pref_' . $pref], ' |
|
108 |
+ </dt> |
|
109 |
+ <dd>'; |
|
110 |
+ |
|
111 |
+ switch ($thispref['type']) |
|
112 |
+ { |
|
113 |
+ case 'check': |
|
114 |
+ echo ' |
|
115 |
+ <input type="checkbox" value="1" name="', $pref, '"', (empty($context['member']['shd_preferences'][$pref]) ? '' : ' checked="checked"'), ' />'; |
|
116 |
+ break; |
|
117 |
+ } |
|
118 |
+ |
|
119 |
+ echo ' |
|
120 |
+ </dd>'; |
|
121 |
+ } |
|
122 |
+ |
|
123 |
+ echo ' |
|
124 |
+ </dl> |
|
125 |
+ </div> |
|
126 |
+ </div> |
|
127 |
+ <span class="lowerframe"><span></span></span> |
|
128 |
+ </div>'; |
|
129 |
+ } |
|
130 |
+ |
|
131 |
+ if ($display_save) |
|
132 |
+ echo ' |
|
133 |
+ <br /> |
|
134 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
135 |
+ <input type="submit" value="', $txt['shd_profile_save_prefs'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" />'; |
|
136 |
+ else |
|
137 |
+ echo ' |
|
138 |
+ <br /> |
|
139 |
+ <div class="tborder"> |
|
140 |
+ <div class="cat_bar"> |
|
141 |
+ <h3 class="catbg grid_header"> |
|
142 |
+ ', $txt['shd_profile_preferences_none_header'], ' |
|
143 |
+ </h3> |
|
144 |
+ </div> |
|
145 |
+ <div class="roundframe"> |
|
146 |
+ <div class="content"> |
|
147 |
+ ', $txt['shd_profile_preferences_none_desc'], ' |
|
148 |
+ </div> |
|
149 |
+ </div> |
|
150 |
+ <span class="lowerframe"><span></span></span> |
|
151 |
+ </div>'; |
|
152 |
+ |
|
153 |
+ echo ' |
|
154 |
+ </form>'; |
|
155 |
+} |
|
156 |
+ |
|
157 |
+function template_shd_profile_show_tickets() |
|
158 |
+{ |
|
159 |
+ global $context, $txt, $settings, $scripturl, $options, $modSettings; |
|
160 |
+ |
|
161 |
+ echo ' |
|
162 |
+ <div class="tborder"> |
|
163 |
+ <div class="cat_bar"> |
|
164 |
+ <h3 class="catbg"> |
|
165 |
+ <img src="', $settings['default_images_url'], '/simpledesk/ticket.png" class="icon" alt="*" /> |
|
166 |
+ ', sprintf($txt['shd_profile_show_tickets_header'], $context['member']['name']), ' |
|
167 |
+ </h3> |
|
168 |
+ </div> |
|
169 |
+ <p class="description">', $txt['shd_profile_show_tickets_description'], '</p> |
|
170 |
+ </div>'; |
|
171 |
+ |
|
172 |
+ // The navigation. |
|
173 |
+ echo '<div class="shd_profile_show_tickets_nav">', template_button_strip($context['show_tickets_navigation']), '<br class="clear" /></div>'; |
|
174 |
+ |
|
175 |
+ // Pagination |
|
176 |
+ echo ' |
|
177 |
+ <div class="tborder"> |
|
178 |
+ <div class="title_bar"> |
|
179 |
+ <h3 class="titlebg"> |
|
180 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $context['can_haz_replies'] ? 'replies' : 'ticket', '.png" class="floatright shd_icon_fullhead" alt=""/> |
|
181 |
+ <span class="smalltext">', $txt['pages'], ': ', $context['page_index'], '</span> |
|
182 |
+ </h3> |
|
183 |
+ </div>'; |
|
184 |
+ |
|
185 |
+ // Loop through all the stuff |
|
186 |
+ foreach ($context['items'] as $item) |
|
187 |
+ { |
|
188 |
+ // Just so we won't have to write the same thing twice. We're lazy here, y'know? |
|
189 |
+ $item_link = '"<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $item['ticket'] . '.' . ($item['is_ticket'] ? '0' : ($item['start'] . '#msg' . $item['msg'])) . '">' . $item['subject'] . '</a>"'; |
|
190 |
+ |
|
191 |
+ echo ' |
|
192 |
+ <div class="topic"> |
|
193 |
+ <div class="', $item['alternate'] == 0 ? 'windowbg2' : 'windowbg', ' core_posts"> |
|
194 |
+ <span class="topslice"><span></span></span> |
|
195 |
+ <div class="content"> |
|
196 |
+ <div class="counter">', $item['counter'], '</div> |
|
197 |
+ <div class="topic_details"> |
|
198 |
+ <h5><strong>', !$item['is_ticket'] ? sprintf($txt['shd_profile_reply_to_ticket'], $item_link) : sprintf($txt['shd_profile_a_ticket'], $item_link), '</strong></h5> |
|
199 |
+ <span class="smalltext">« <strong>', $txt['on'], ':</strong> ', $item['time'], ' »</span> |
|
200 |
+ </div> |
|
201 |
+ <div class="list_posts"> |
|
202 |
+ ', $item['body'], ' |
|
203 |
+ <div class="description shd_replybutton floatright" id="shd_replybutton"> |
|
204 |
+ <a href="', $scripturl, '?action=helpdesk;sa=ticket;ticket=', $item['ticket'], '.0">', $txt['shd_profile_view_full_ticket'], '</a><br /> |
|
205 |
+ </div> |
|
206 |
+ </div> |
|
207 |
+ </div> |
|
208 |
+ <br class="clear" /> |
|
209 |
+ <span class="botslice"><span></span></span> |
|
210 |
+ </div> |
|
211 |
+ </div>'; |
|
212 |
+ } |
|
213 |
+ |
|
214 |
+ // Some more pagination. |
|
215 |
+ echo ' |
|
216 |
+ <div class="title_bar"> |
|
217 |
+ <h3 class="titlebg"> |
|
218 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $context['can_haz_replies'] ? 'replies' : 'ticket', '.png" class="floatright shd_icon_fullhead" alt=""/> |
|
219 |
+ <span class="smalltext">', $txt['pages'], ': ', $context['page_index'], '</span> |
|
220 |
+ </h3> |
|
221 |
+ </div> |
|
222 |
+ </div>'; |
|
223 |
+} |
|
224 |
+ |
|
225 |
+function template_shd_profile_permissions() |
|
226 |
+{ |
|
227 |
+ global $context, $txt, $settings, $scripturl; |
|
228 |
+ |
|
229 |
+ echo ' |
|
230 |
+ <div class="tborder"> |
|
231 |
+ <div class="cat_bar"> |
|
232 |
+ <h3 class="catbg"> |
|
233 |
+ <img src="', $settings['default_images_url'], '/simpledesk/permissions.png" class="icon" alt="*" /> |
|
234 |
+ ', sprintf($txt['shd_profile_permissions_header'], $context['member']['name']), ' |
|
235 |
+ </h3> |
|
236 |
+ </div>'; |
|
237 |
+ |
|
238 |
+ if (!empty($context['member']['has_all_permissions'])) |
|
239 |
+ { |
|
240 |
+ // Whoa, this dude's special. Tidy up and BAIL! |
|
241 |
+ echo ' |
|
242 |
+ <p class="description"> |
|
243 |
+ ', $txt['shd_profile_permissions_all_admin'], ' |
|
244 |
+ </p> |
|
245 |
+ </div>'; |
|
246 |
+ return; |
|
247 |
+ } |
|
248 |
+ |
|
249 |
+ // Regular user: carry on, sergeant. |
|
250 |
+ echo ' |
|
251 |
+ <p class="description"> |
|
252 |
+ ', $txt['shd_profile_permissions_description'], ' |
|
253 |
+ </p> |
|
254 |
+ </div>'; |
|
255 |
+ |
|
256 |
+ // Now, display the roles that are attached to this user, and display the groups that make that link. |
|
257 |
+ echo ' |
|
258 |
+ <div class="tborder"> |
|
259 |
+ <div class="cat_bar"> |
|
260 |
+ <h3 class="catbg sd_no_margin grid_header"> |
|
261 |
+ <img src="', $settings['default_images_url'], '/simpledesk/roles.png" alt="*" /> |
|
262 |
+ ', $txt['shd_roles'], ' |
|
263 |
+ </h3> |
|
264 |
+ </div> |
|
265 |
+ <p class="description shd_actionloginfo"> |
|
266 |
+ ', $txt['shd_profile_roles_assigned'], ' |
|
267 |
+ </p> |
|
268 |
+ <table class="shd_ticketlist" cellspacing="0" width="100%"> |
|
269 |
+ <tr class="titlebg"> |
|
270 |
+ <td colspan="2" width="30%">', $txt['shd_role'], '</td> |
|
271 |
+ <td>', $txt['shd_profile_role_membergroups'], '</td> |
|
272 |
+ </tr>'; |
|
273 |
+ |
|
274 |
+ if (empty($context['member_roles'])) |
|
275 |
+ { |
|
276 |
+ echo ' |
|
277 |
+ <tr class="windowbg"> |
|
278 |
+ <td colspan="3" class="centertext">', $txt['shd_profile_no_roles'], '</td> |
|
279 |
+ </tr>'; |
|
280 |
+ } |
|
281 |
+ else |
|
282 |
+ { |
|
283 |
+ $use_bg2 = true; |
|
284 |
+ foreach ($context['member_roles'] as $role) |
|
285 |
+ { |
|
286 |
+ echo ' |
|
287 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
288 |
+ <td>', !empty($context['shd_permissions']['roles'][$role['template']]['icon']) ? ('<img src="' . $settings['default_images_url'] . '/simpledesk/' . $context['shd_permissions']['roles'][$role['template']]['icon'] . '" alt="" />') : '', '</td> |
|
289 |
+ <td>', $role['name'], '</td> |
|
290 |
+ <td>'; |
|
291 |
+ |
|
292 |
+ $done_group = false; |
|
293 |
+ foreach ($role['groups'] as $group) |
|
294 |
+ { |
|
295 |
+ if ($done_group) |
|
296 |
+ echo ', '; |
|
297 |
+ |
|
298 |
+ echo $context['membergroups'][$group]['link']; |
|
299 |
+ $done_group = true; |
|
300 |
+ } |
|
301 |
+ |
|
302 |
+ echo '</td> |
|
303 |
+ </tr>'; |
|
304 |
+ $use_bg2 = !$use_bg2; |
|
305 |
+ } |
|
306 |
+ } |
|
307 |
+ |
|
308 |
+ echo ' |
|
309 |
+ </table> |
|
310 |
+ </div>'; |
|
311 |
+ |
|
312 |
+ // Now display their permissions! |
|
313 |
+ if (!empty($context['member_permissions']['allowed'])) |
|
314 |
+ { |
|
315 |
+ echo ' |
|
316 |
+ <br /> |
|
317 |
+ <div class="tborder"> |
|
318 |
+ <div class="cat_bar"> |
|
319 |
+ <h3 class="catbg sd_no_margin grid_header"> |
|
320 |
+ <img src="', $settings['default_images_url'], '/simpledesk/perm_yes.png" alt="*" /> |
|
321 |
+ ', $txt['shd_profile_granted'], ' |
|
322 |
+ </h3> |
|
323 |
+ </div> |
|
324 |
+ <p class="description shd_actionloginfo"> |
|
325 |
+ ', $txt['shd_profile_granted_desc'], ' |
|
326 |
+ </p> |
|
327 |
+ <table class="shd_ticketlist" cellspacing="0" width="100%"> |
|
328 |
+ <tr class="titlebg"> |
|
329 |
+ <td colspan="2" width="60%">', $txt['shd_permissions'], '</td> |
|
330 |
+ <td>', $txt['shd_roles'], '</td> |
|
331 |
+ </tr>'; |
|
332 |
+ |
|
333 |
+ // Right, we're going to go by what's in the master list first. |
|
334 |
+ $use_bg2 = true; |
|
335 |
+ $last_permission_cat = ''; |
|
336 |
+ |
|
337 |
+ foreach ($context['shd_permissions']['permission_list'] as $permission => $details) |
|
338 |
+ { |
|
339 |
+ list($ownany, $category, $icon) = $details; |
|
340 |
+ if (empty($icon)) |
|
341 |
+ continue; // don't display it here at all if it's a denied permission or no icon (which means, access to helpdesk / is staff / admin helpdesk permissions are excluded here) |
|
342 |
+ |
|
343 |
+ // Well, are we displaying it? |
|
344 |
+ if ($ownany) |
|
345 |
+ { |
|
346 |
+ if (!empty($context['member_permissions']['denied'][$permission . '_any']) || (empty($context['member_permissions']['allowed'][$permission . '_any']) && empty($context['member_permissions']['allowed'][$permission . '_own']))) |
|
347 |
+ continue; // deny hits both _any and _own when being saved |
|
348 |
+ } |
|
349 |
+ else |
|
350 |
+ { |
|
351 |
+ if (!empty($context['member_permissions']['denied'][$permission]) || empty($context['member_permissions']['allowed'][$permission])) |
|
352 |
+ continue; |
|
353 |
+ } |
|
354 |
+ |
|
355 |
+ if ($category != $last_permission_cat) |
|
356 |
+ { |
|
357 |
+ $thisicon = ''; |
|
358 |
+ foreach ($context['shd_permissions']['group_display'] as $group => $permgroups) |
|
359 |
+ { |
|
360 |
+ if (!isset($permgroups[$category])) |
|
361 |
+ continue; |
|
362 |
+ else |
|
363 |
+ $thisicon = $permgroups[$category]; |
|
364 |
+ } |
|
365 |
+ echo ' |
|
366 |
+ <tr class="catbg"> |
|
367 |
+ <td colspan="3">', (empty($thisicon) ? '' : '<img src="' . shd_image_url($thisicon) . '" alt="" />'), ' ', $txt['shd_permgroup_' . $category], '</td> |
|
368 |
+ </tr>'; |
|
369 |
+ $last_permission_cat = $category; |
|
370 |
+ } |
|
371 |
+ |
|
372 |
+ echo ' |
|
373 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
374 |
+ <td><img src="', shd_image_url($icon), '" alt="" /></td>'; |
|
375 |
+ |
|
376 |
+ if ($ownany) |
|
377 |
+ { |
|
378 |
+ echo ' |
|
379 |
+ <td>', $txt['permissionname_' . $permission], ' - '; |
|
380 |
+ if (!empty($context['member_permissions']['allowed'][$permission . '_any'])) |
|
381 |
+ { |
|
382 |
+ $roles = $context['member_permissions']['allowed'][$permission . '_any']; |
|
383 |
+ echo $txt['permissionname_' . $permission . '_any']; |
|
384 |
+ } |
|
385 |
+ elseif (!empty($context['member_permissions']['allowed'][$permission . '_own'])) |
|
386 |
+ { |
|
387 |
+ $roles = $context['member_permissions']['allowed'][$permission . '_own']; |
|
388 |
+ echo $txt['permissionname_' . $permission . '_own']; |
|
389 |
+ } |
|
390 |
+ |
|
391 |
+ echo '</td>'; |
|
392 |
+ } |
|
393 |
+ else |
|
394 |
+ { |
|
395 |
+ $roles = $context['member_permissions']['allowed'][$permission]; |
|
396 |
+ echo ' |
|
397 |
+ <td>', $txt['permissionname_' . $permission], '</td>'; |
|
398 |
+ } |
|
399 |
+ |
|
400 |
+ echo ' |
|
401 |
+ <td>'; |
|
402 |
+ $done_first = false; |
|
403 |
+ foreach ($roles as $role) |
|
404 |
+ { |
|
405 |
+ if ($done_first) |
|
406 |
+ echo ', '; |
|
407 |
+ |
|
408 |
+ echo '<span class="shd_nowrap"><img src="', $settings['default_images_url'], '/simpledesk/', $context['shd_permissions']['roles'][$context['member_roles'][$role]['template']]['icon'], '" alt="" /> ', $context['member_roles'][$role]['name'], '</span>'; |
|
409 |
+ $done_first = true; |
|
410 |
+ } |
|
411 |
+ |
|
412 |
+ echo ' |
|
413 |
+ </td> |
|
414 |
+ </tr>'; |
|
415 |
+ |
|
416 |
+ $use_bg2 = !$use_bg2; |
|
417 |
+ } |
|
418 |
+ |
|
419 |
+ echo ' |
|
420 |
+ </table> |
|
421 |
+ </div>'; |
|
422 |
+ } |
|
423 |
+ |
|
424 |
+ // Display of denied permissions goes here. |
|
425 |
+} |
|
426 |
+ |
|
427 |
+function template_shd_profile_actionlog() |
|
428 |
+{ |
|
429 |
+ global $context, $settings, $txt, $scripturl; |
|
430 |
+ |
|
431 |
+ echo ' |
|
432 |
+ <div class="tborder"> |
|
433 |
+ <div class="cat_bar"> |
|
434 |
+ <h3 class="catbg grid_header" id="ticket_log_header"> |
|
435 |
+ <img src="', $settings['default_images_url'], '/simpledesk/log.png" class="icon" alt="*" /> |
|
436 |
+ ', sprintf($txt['shd_profile_log'], $context['member']['name']), ' |
|
437 |
+ <span class="smalltext">(', $context['action_log_count'] == 1 ? $txt['shd_profile_log_count_one'] : sprintf($txt['shd_profile_log_count_more'], $context['action_log_count']) , ')</span> |
|
438 |
+ </h3> |
|
439 |
+ </div> |
|
440 |
+ <table class="shd_ticketlist" id="ticket_log" cellspacing="0" width="100%"> |
|
441 |
+ <tr class="titlebg"> |
|
442 |
+ <td width="15%"> |
|
443 |
+ <img src="', $settings['default_images_url'], '/simpledesk/time.png" class="shd_smallicon" alt="" /> |
|
444 |
+ ', $txt['shd_ticket_log_date'], ' |
|
445 |
+ </td> |
|
446 |
+ <td width="50%"> |
|
447 |
+ <img src="', $settings['default_images_url'], '/simpledesk/action.png" class="shd_smallicon" alt="" /> |
|
448 |
+ ', $txt['shd_ticket_log_action'], ' |
|
449 |
+ </td> |
|
450 |
+ </tr>'; |
|
451 |
+ |
|
452 |
+ if (empty($context['action_log'])) |
|
453 |
+ echo ' |
|
454 |
+ <tr class="windowbg2"> |
|
455 |
+ <td colspan="2" class="shd_noticket">', $txt['shd_profile_log_none'], '</td> |
|
456 |
+ </tr>'; |
|
457 |
+ else |
|
458 |
+ { |
|
459 |
+ $use_bg2 = true; // start with windowbg2 to differentiate between that and windowbg2 |
|
460 |
+ foreach ($context['action_log'] as $action) |
|
461 |
+ { |
|
462 |
+ echo ' |
|
463 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '"> |
|
464 |
+ <td class="smalltext">', $action['time'], '</td> |
|
465 |
+ <td class="smalltext"> |
|
466 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $action['action_icon'], '" alt="" class="shd_smallicon" /> |
|
467 |
+ ', $action['action_text'], ' |
|
468 |
+ </td> |
|
469 |
+ </tr>'; |
|
470 |
+ |
|
471 |
+ $use_bg2 = !$use_bg2; |
|
472 |
+ } |
|
473 |
+ } |
|
474 |
+ |
|
475 |
+ echo ' |
|
476 |
+ <tr class="titlebg"> |
|
477 |
+ <td colspan="2"> |
|
478 |
+ ', !empty($context['action_full_log']) ? '<span class="smalltext shd_main_log"><img src="' . $settings['default_images_url'] . '/simpledesk/browse.png" alt="" /> <a href="' . $scripturl . '?action=admin;area=helpdesk_info;sa=actionlog">' . $txt['shd_profile_log_full'] . '</a></span>' : '', ' |
|
479 |
+ </td> |
|
480 |
+ </tr> |
|
481 |
+ </table> |
|
482 |
+ </div>'; |
|
483 |
+} |
|
484 |
+ |
|
485 |
+function template_shd_profile_navigation_above() |
|
486 |
+{ |
|
487 |
+ global $settings, $scripturl, $context, $txt, $options; |
|
488 |
+ |
|
489 |
+ echo ' |
|
490 |
+ <div class="', empty($options['use_sidebar_menu']) ? 'shd_ticket_leftcolumn floatleft' : '', '"> |
|
491 |
+ <div class="tborder shd_profile_navigation"> |
|
492 |
+ <span class="upperframe"><span></span></span> |
|
493 |
+ <div class="roundframe"> |
|
494 |
+ <ul class="', !empty($options['use_sidebar_menu']) ? 'shd_profile_nav_inline' : 'shd_profile_nav_list', '">'; |
|
495 |
+ foreach ($context['shd_profile_menu'] as $menuitem) |
|
496 |
+ { |
|
497 |
+ if (!empty($menuitem['show'])) |
|
498 |
+ { |
|
499 |
+ echo ' |
|
500 |
+ <li', (!empty($menuitem['is_last']) ? ' class="shd_inline_last"' : ''), '> |
|
501 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $menuitem['image'], '" alt="x" class="floatright" /> |
|
502 |
+ <a href="', $menuitem['link'], '"><strong>', $menuitem['text'], '</strong></a> |
|
503 |
+ ', (empty($options['use_sidebar_menu']) && empty($menuitem['is_last'])) ? '<hr />' : '', ' |
|
504 |
+ </li>'; |
|
505 |
+ } |
|
506 |
+ } |
|
507 |
+ |
|
508 |
+ echo ' |
|
509 |
+ </ul> |
|
510 |
+ ', !empty($options['use_sidebar_menu']) ? '<br />' : '', ' |
|
511 |
+ </div> |
|
512 |
+ <span class="lowerframe"><span></span></span> |
|
513 |
+ </div> |
|
514 |
+ </div> |
|
515 |
+ ', !empty($options['use_sidebar_menu']) ? '<br />' : '', ' |
|
516 |
+ <div class="', empty($options['use_sidebar_menu']) ? 'shd_ticket_rightcolumn floatleft' : '', '">'; |
|
517 |
+} |
|
518 |
+ |
|
519 |
+function template_shd_profile_navigation_below() |
|
520 |
+{ |
|
521 |
+ echo' |
|
522 |
+ </div> |
|
523 |
+ <br class="clear" />'; |
|
524 |
+} |
|
525 |
+ |
|
526 |
+?> |
|
0 | 527 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,200 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk ticket <-> topic template |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * This file handles gathering user options when moving a ticket to/from the helpdesk, from/to |
|
6 |
+ * a forum thread, specifically getting details like whether to send a PM to the user (including the PM contents), as well as if sending |
|
7 |
+ * to a board, which board. |
|
8 |
+ * |
|
9 |
+ * @package template |
|
10 |
+ * @since 1.0 |
|
11 |
+*/ |
|
12 |
+ |
|
13 |
+/** |
|
14 |
+ * Display a list of requirements for moving a ticket to a topic. |
|
15 |
+ * |
|
16 |
+ * When moving a ticket to the forum, certain information is required: the board to move to, whether to send the ticket starter a |
|
17 |
+ * personal message (and if so, the contents of the message) and what to do in the event there are deleted replies to deal with. |
|
18 |
+ * This function handles showing the form to the user. |
|
19 |
+ * |
|
20 |
+ * @see shd_tickettotopic() |
|
21 |
+ * @see shd_tickettotopic2() |
|
22 |
+ * |
|
23 |
+ * @since 1.0 |
|
24 |
+*/ |
|
25 |
+function template_shd_tickettotopic() |
|
26 |
+{ |
|
27 |
+ global $txt, $settings, $context, $scripturl, $modSettings; |
|
28 |
+ |
|
29 |
+ // Back to the helpdesk. |
|
30 |
+ echo ' |
|
31 |
+ <div class="floatleft"> |
|
32 |
+ ', template_button_strip(array($context['navigation']['back']), 'bottom'), ' |
|
33 |
+ </div><br class="clear" />'; |
|
34 |
+ |
|
35 |
+ echo ' |
|
36 |
+ <div class="cat_bar"> |
|
37 |
+ <h3 class="catbg grid_header"> |
|
38 |
+ <img src="', $settings['default_images_url'] , '/simpledesk/tickettotopic.png" alt="*" /> |
|
39 |
+ ', $txt['shd_move_ticket_to_topic'], ' |
|
40 |
+ </h3> |
|
41 |
+ </div> |
|
42 |
+ <div class="roundframe"> |
|
43 |
+ <form action="', $scripturl, '?action=helpdesk;sa=tickettotopic2;ticket=', $context['ticket_id'], '" method="post" onsubmit="submitonce(this);"> |
|
44 |
+ <div class="content"> |
|
45 |
+ <dl class="settings"> |
|
46 |
+ <dt> |
|
47 |
+ <strong>', $txt['shd_ticket_board'], ':</strong> |
|
48 |
+ </dt> |
|
49 |
+ <dd> |
|
50 |
+ <select name="toboard">'; |
|
51 |
+ |
|
52 |
+ foreach ($context['categories'] as $category) |
|
53 |
+ { |
|
54 |
+ echo ' |
|
55 |
+ <optgroup label="', $category['name'], '">'; |
|
56 |
+ |
|
57 |
+ foreach ($category['boards'] as $board) |
|
58 |
+ echo ' |
|
59 |
+ <option value="', $board['id'], '"', $board['selected'] ? ' selected="selected"' : '', '>', $board['child_level'] > 0 ? str_repeat('==', $board['child_level']-1) . '=> ' : '', $board['name'], '</option>'; |
|
60 |
+ echo ' |
|
61 |
+ </optgroup>'; |
|
62 |
+ } |
|
63 |
+ |
|
64 |
+ echo ' |
|
65 |
+ </select> |
|
66 |
+ </dd> |
|
67 |
+ <dt> |
|
68 |
+ <strong>', $txt['shd_change_ticket_subject'], ':</strong> |
|
69 |
+ </dt> |
|
70 |
+ <dd> |
|
71 |
+ <input type="checkbox" name="change_subject" id="change_subject" onclick="document.getElementById(\'new_subject\').style.display = this.checked ? \'block\' : \'none\';" class="input_check" /> |
|
72 |
+ </dd> |
|
73 |
+ </dl> |
|
74 |
+ <dl class="settings" style="display: none;" id="new_subject"> |
|
75 |
+ <dt> |
|
76 |
+ <strong>', $txt['shd_new_subject'], ':</strong> |
|
77 |
+ </dt> |
|
78 |
+ <dd> |
|
79 |
+ <input type="text" name="subject" id="subject" value="', $context['ticket_subject'], '" /> |
|
80 |
+ </dd> |
|
81 |
+ </dl> |
|
82 |
+ <dl class="settings"> |
|
83 |
+ <dt> |
|
84 |
+ <strong>', $txt['shd_move_send_pm'], ':</strong> |
|
85 |
+ </dt> |
|
86 |
+ <dd> |
|
87 |
+ <input type="checkbox" name="send_pm" id="send_pm" checked="checked" onclick="document.getElementById(\'pm_message\').style.display = this.checked ? \'block\' : \'none\';" class="input_check" /> |
|
88 |
+ </dd> |
|
89 |
+ </dl> |
|
90 |
+ <fieldset id="pm_message"> |
|
91 |
+ <dl class="settings"> |
|
92 |
+ <dt> |
|
93 |
+ ', $txt['shd_move_why'], ' |
|
94 |
+ </dt> |
|
95 |
+ <dd> |
|
96 |
+ <textarea name="pm_content" rows="9" cols="70">', $txt['shd_move_default'], '</textarea> |
|
97 |
+ </dd> |
|
98 |
+ </dl> |
|
99 |
+ </fieldset>'; |
|
100 |
+ |
|
101 |
+ if (!empty($context['deleted_prompt'])) |
|
102 |
+ { |
|
103 |
+ echo ' |
|
104 |
+ <br /> |
|
105 |
+ <fieldset id="deleted_replies"> |
|
106 |
+ <dl class="settings"> |
|
107 |
+ <dt> |
|
108 |
+ ', $txt['shd_ticket_move_deleted'], ' |
|
109 |
+ </dt> |
|
110 |
+ <dd> |
|
111 |
+ <select name="deleted_replies"> |
|
112 |
+ <option value="abort">', $txt['shd_ticket_move_deleted_abort'], '</option> |
|
113 |
+ <option value="delete">', $txt['shd_ticket_move_deleted_delete'], '</option> |
|
114 |
+ <option value="undelete">', $txt['shd_ticket_move_deleted_undelete'], '</option> |
|
115 |
+ </select> |
|
116 |
+ </dd> |
|
117 |
+ </dl> |
|
118 |
+ </fieldset>'; |
|
119 |
+ } |
|
120 |
+ |
|
121 |
+ echo ' |
|
122 |
+ <input type="submit" value="', $txt['shd_move_ticket'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" /> |
|
123 |
+ <input type="submit" name="cancel" value="', $txt['shd_cancel_ticket'], '" accesskey="c" class="button_submit" /> |
|
124 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
125 |
+ <input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" /> |
|
126 |
+ </div> |
|
127 |
+ </form> |
|
128 |
+ </div> |
|
129 |
+ <span class="lowerframe"><span></span></span>'; |
|
130 |
+} |
|
131 |
+ |
|
132 |
+/** |
|
133 |
+ * Display a list of requirements for moving a topic to a ticket. |
|
134 |
+ * |
|
135 |
+ * When moving a ticket from the forum, only a little information is required; basically, whether to send a personal message (and what message) |
|
136 |
+ * to the topic/ticket starter or not. |
|
137 |
+ * |
|
138 |
+ * @see shd_topictoticket() |
|
139 |
+ * @see shd_topictoticket2() |
|
140 |
+ * |
|
141 |
+ * @since 1.0 |
|
142 |
+*/ |
|
143 |
+function template_shd_topictoticket() |
|
144 |
+{ |
|
145 |
+ global $txt, $settings, $context, $scripturl; |
|
146 |
+ echo ' |
|
147 |
+ <div class="cat_bar"> |
|
148 |
+ <h3 class="catbg grid_header"> |
|
149 |
+ <img src="', $settings['default_images_url'] , '/simpledesk/topictoticket.png" alt="*" /> |
|
150 |
+ ', $txt['shd_move_topic_to_ticket'], ' |
|
151 |
+ </h3> |
|
152 |
+ </div> |
|
153 |
+ <div class="roundframe"> |
|
154 |
+ <form action="', $scripturl, '?action=helpdesk;sa=topictoticket2;topic=', $context['topic_id'], '" method="post" onsubmit="submitonce(this);"> |
|
155 |
+ <div class="content"> |
|
156 |
+ <dl class="settings"> |
|
157 |
+ <dt> |
|
158 |
+ <strong>', $txt['shd_change_topic_subject'], ':</strong> |
|
159 |
+ </dt> |
|
160 |
+ <dd> |
|
161 |
+ <input type="checkbox" name="change_subject" id="change_subject" onclick="document.getElementById(\'new_subject\').style.display = this.checked ? \'block\' : \'none\';" class="input_check" /> |
|
162 |
+ </dd> |
|
163 |
+ </dl> |
|
164 |
+ <dl class="settings" style="display: none;" id="new_subject"> |
|
165 |
+ <dt> |
|
166 |
+ <strong>', $txt['shd_new_subject'], ':</strong> |
|
167 |
+ </dt> |
|
168 |
+ <dd> |
|
169 |
+ <input type="text" name="subject" id="subject" value="', $context['topic_subject'], '" /> |
|
170 |
+ </dd> |
|
171 |
+ </dl> |
|
172 |
+ <dl class="settings"> |
|
173 |
+ <dt> |
|
174 |
+ <strong>', $txt['shd_move_send_pm_topic'], ':</strong> |
|
175 |
+ </dt> |
|
176 |
+ <dd> |
|
177 |
+ <input type="checkbox" name="send_pm" id="send_pm" checked="checked" onclick="document.getElementById(\'pm_message\').style.display = this.checked ? \'block\' : \'none\';" class="input_check" /> |
|
178 |
+ </dd> |
|
179 |
+ </dl> |
|
180 |
+ <fieldset id="pm_message"> |
|
181 |
+ <dl class="settings"> |
|
182 |
+ <dt> |
|
183 |
+ ', $txt['shd_move_why_topic'], ' |
|
184 |
+ </dt> |
|
185 |
+ <dd> |
|
186 |
+ <textarea name="pm_content" rows="9" cols="70">', $txt['shd_move_default_topic'], '</textarea> |
|
187 |
+ </dd> |
|
188 |
+ </dl> |
|
189 |
+ </fieldset> |
|
190 |
+ <input type="submit" value="', $txt['shd_move_topic'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" /> |
|
191 |
+ <input type="submit" name="cancel" value="', $txt['shd_cancel_topic'], '" accesskey="c" class="button_submit" /> |
|
192 |
+ <input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" /> |
|
193 |
+ <input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" /> |
|
194 |
+ </div> |
|
195 |
+ </form> |
|
196 |
+ </div> |
|
197 |
+ <span class="lowerframe"><span></span></span>'; |
|
198 |
+} |
|
199 |
+ |
|
200 |
+?> |
|
0 | 201 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,522 @@ |
1 |
+<?php |
|
2 |
+// Version: 1.0 Felidae; SimpleDesk front page template |
|
3 |
+ |
|
4 |
+/** |
|
5 |
+ * This file handles displaying the blocks of tickets for the front page, as well as the slightly |
|
6 |
+ * customised views for the recycle bin and the list of resolved tickets. |
|
7 |
+ * |
|
8 |
+ * @package template |
|
9 |
+ * @since 1.0 |
|
10 |
+*/ |
|
11 |
+ |
|
12 |
+/** |
|
13 |
+ * Display the main helpdesk view of active tickets. |
|
14 |
+ * |
|
15 |
+ * This function steps through the blocks defined in SimpleDesk.php to display all the blocks that potentially would be visible, noting whether blocks have been collapsed or not, and calling to the sub-subtemplates to output collapsed and noncollapsed blocks. |
|
16 |
+ * |
|
17 |
+ * All the blocks here are defined in {@link shd_main_helpdesk()} (or {@link shd_view_block()} if viewing a single block) and data gathered in {@link shd_helpdesk_listing()}. |
|
18 |
+ * |
|
19 |
+ * @see template_collapsed_ticket_block() |
|
20 |
+ * @see template_ticket_block() |
|
21 |
+ * @since 1.0 |
|
22 |
+*/ |
|
23 |
+function template_main() |
|
24 |
+{ |
|
25 |
+ global $context, $txt, $settings, $scripturl; |
|
26 |
+ |
|
27 |
+ echo ' |
|
28 |
+ <div class="modbuttons clearfix margintop">'; |
|
29 |
+ |
|
30 |
+ template_button_strip($context['navigation'], 'bottom'); |
|
31 |
+ |
|
32 |
+ echo ' |
|
33 |
+ </div> |
|
34 |
+ <div id="admin_content"> |
|
35 |
+ <table width="100%" class="shd_main_hd"> |
|
36 |
+ <tr> |
|
37 |
+ <td valign="top"> |
|
38 |
+ <div class="title_bar"> |
|
39 |
+ <h3 class="titlebg"> |
|
40 |
+ ', $txt['shd_helpdesk'], ' |
|
41 |
+ </h3> |
|
42 |
+ </div> |
|
43 |
+ <span class="upperframe"><span></span></span> |
|
44 |
+ <div class="roundframe"> |
|
45 |
+ <div class="shd_gototicket smalltext"> |
|
46 |
+ <form action="', $scripturl, '?action=helpdesk;sa=ticket" method="get"> |
|
47 |
+ ', $txt['shd_go_to_ticket'], ': |
|
48 |
+ <input type="hidden" name="action" value="helpdesk" /> |
|
49 |
+ <input type="hidden" name="sa" value="ticket" /> |
|
50 |
+ <input type="text" class="input_text" id="ticketJump" name="ticket" size="4" /> |
|
51 |
+ <input type="submit" class="button_submit" value="', $txt['shd_go'], '" onclick="shd_quickTicketJump(this.parentNode.ticketJump.value);" /> |
|
52 |
+ </form> |
|
53 |
+ </div> |
|
54 |
+ <div id="welcome"> |
|
55 |
+ <strong>', sprintf($txt['shd_welcome'], $context['user']['name']), '</strong><br /> |
|
56 |
+ ', $txt['shd_' . $context['shd_home_view'] . '_greeting'], ' |
|
57 |
+ </div> |
|
58 |
+ </div> |
|
59 |
+ <span class="lowerframe"><span></span></span> |
|
60 |
+ <br />'; |
|
61 |
+ |
|
62 |
+ // Start the ticket listing |
|
63 |
+ $blocks = array_keys($context['ticket_blocks']); |
|
64 |
+ foreach ($blocks as $block) |
|
65 |
+ { |
|
66 |
+ $context['current_block'] = $block; |
|
67 |
+ if (!empty($context['ticket_blocks'][$block]['count']) && $context['ticket_blocks'][$block]['count'] > 10) |
|
68 |
+ $context['block_link'] = $_REQUEST['sa'] == 'viewblock' ? $scripturl . '?action=helpdesk;sa=main' : $scripturl . '?action=helpdesk;sa=viewblock;block=' . $block . '#shd_block_' . $block; |
|
69 |
+ else |
|
70 |
+ $context['block_link'] = ''; |
|
71 |
+ |
|
72 |
+ if ($context['ticket_blocks'][$block]['collapsed']) |
|
73 |
+ template_collapsed_ticket_block(); |
|
74 |
+ else |
|
75 |
+ template_ticket_block(); |
|
76 |
+ } |
|
77 |
+ |
|
78 |
+ echo ' |
|
79 |
+ </td> |
|
80 |
+ </tr> |
|
81 |
+ </table> |
|
82 |
+ </div>'; |
|
83 |
+ |
|
84 |
+ //echo 'I\'m alive!!!!!!!!!!1111oneone'; - I had to save this :P |
|
85 |
+} |
|
86 |
+ |
|
87 |
+/** |
|
88 |
+ * Display the helpdesk view of resolved tickets. |
|
89 |
+ * |
|
90 |
+ * This function steps through the blocks defined in SimpleDesk.php to display all the block of closed items. |
|
91 |
+ * |
|
92 |
+ * All the blocks here are defined in {@link shd_closed_tickets()} and data gathered in {@link shd_helpdesk_listing()}. |
|
93 |
+ * |
|
94 |
+ * @see template_ticket_block() |
|
95 |
+ * @since 1.0 |
|
96 |
+*/ |
|
97 |
+function template_closedtickets() |
|
98 |
+{ |
|
99 |
+ global $context, $txt, $settings, $scripturl; |
|
100 |
+ |
|
101 |
+ echo ' |
|
102 |
+ <div class="modbuttons clearfix margintop">'; |
|
103 |
+ |
|
104 |
+ template_button_strip($context['navigation'], 'bottom'); |
|
105 |
+ |
|
106 |
+ echo ' |
|
107 |
+ </div> |
|
108 |
+ <div id="admin_content"> |
|
109 |
+ <table width="100%" class="shd_main_hd"> |
|
110 |
+ <tr>'; |
|
111 |
+ |
|
112 |
+ echo ' |
|
113 |
+ <td valign="top"> |
|
114 |
+ <div class="title_bar"> |
|
115 |
+ <h3 class="titlebg"> |
|
116 |
+ ', $txt['shd_helpdesk'], ' |
|
117 |
+ </h3> |
|
118 |
+ </div> |
|
119 |
+ <span class="upperframe"><span></span></span> |
|
120 |
+ <div class="roundframe"> |
|
121 |
+ <div class="shd_gototicket smalltext"> |
|
122 |
+ <form action="', $scripturl, '?action=helpdesk" method="post"> |
|
123 |
+ ', $txt['shd_go_to_ticket'], ': |
|
124 |
+ <input type="text" name="ticket" size="4" /> |
|
125 |
+ <input type="submit" value="', $txt['shd_go'], '" /> |
|
126 |
+ <input type="hidden" name="sa" value="ticket" /> |
|
127 |
+ </form> |
|
128 |
+ </div> |
|
129 |
+ <div id="welcome"> |
|
130 |
+ <strong>', sprintf($txt['shd_welcome'], $context['user']['name']), '</strong><br /> |
|
131 |
+ ', $txt['shd_closed_' . $context['shd_home_view'] . '_greeting'], ' |
|
132 |
+ </div> |
|
133 |
+ </div> |
|
134 |
+ <span class="lowerframe"><span></span></span> |
|
135 |
+ <br />'; |
|
136 |
+ |
|
137 |
+ // Start the ticket listing |
|
138 |
+ $blocks = array_keys($context['ticket_blocks']); |
|
139 |
+ foreach ($blocks as $block) |
|
140 |
+ { |
|
141 |
+ $context['current_block'] = $block; |
|
142 |
+ template_ticket_block(); |
|
143 |
+ } |
|
144 |
+ |
|
145 |
+ echo ' |
|
146 |
+ </td> |
|
147 |
+ </tr> |
|
148 |
+ </table> |
|
149 |
+ </div>'; |
|
150 |
+} |
|
151 |
+ |
|
152 |
+/** |
|
153 |
+ * Display the helpdesk view of recycled and partly recycled tickets. |
|
154 |
+ * |
|
155 |
+ * This function steps through the blocks defined in SimpleDesk.php to display all the blocks that would be related; the list of deleted tickets, and the list of tickets with deleted replies in. |
|
156 |
+ * |
|
157 |
+ * All the blocks here are defined in {@link shd_recycle_bin()} and data gathered in {@link shd_helpdesk_listing()}. |
|
158 |
+ * |
|
159 |
+ * @see template_ticket_block() |
|
160 |
+ * @since 1.0 |
|
161 |
+*/ |
|
162 |
+function template_recyclebin() |
|
163 |
+{ |
|
164 |
+ global $context, $txt, $settings, $scripturl; |
|
165 |
+ |
|
166 |
+ echo ' |
|
167 |
+ <div class="modbuttons clearfix margintop">'; |
|
168 |
+ |
|
169 |
+ template_button_strip($context['navigation'], 'bottom'); |
|
170 |
+ |
|
171 |
+ echo ' |
|
172 |
+ </div> |
|
173 |
+ <div id="admin_content"> |
|
174 |
+ <table width="100%" class="shd_main_hd"> |
|
175 |
+ <tr>'; |
|
176 |
+ |
|
177 |
+ echo ' |
|
178 |
+ <td valign="top"> |
|
179 |
+ <div class="title_bar"> |
|
180 |
+ <h3 class="titlebg"> |
|
181 |
+ ', $txt['shd_helpdesk'], ' |
|
182 |
+ </h3> |
|
183 |
+ </div> |
|
184 |
+ <span class="upperframe"><span></span></span> |
|
185 |
+ <div class="roundframe"> |
|
186 |
+ <div class="shd_gototicket smalltext"> |
|
187 |
+ <form action="', $scripturl, '?action=helpdesk" method="post"> |
|
188 |
+ ', $txt['shd_go_to_ticket'], ': |
|
189 |
+ <input type="text" name="ticket" size="4" /> |
|
190 |
+ <input type="submit" value="', $txt['shd_go'], '" /> |
|
191 |
+ <input type="hidden" name="sa" value="ticket" /> |
|
192 |
+ </form> |
|
193 |
+ </div> |
|
194 |
+ <div id="welcome"> |
|
195 |
+ <strong>', sprintf($txt['shd_welcome'], $context['user']['name']), '</strong><br /> |
|
196 |
+ ', $txt['shd_recycle_greeting'], ' |
|
197 |
+ </div> |
|
198 |
+ </div> |
|
199 |
+ <span class="lowerframe"><span></span></span> |
|
200 |
+ <br />'; |
|
201 |
+ |
|
202 |
+ // Loop through the crap... Uh, I mean the tickets! :) |
|
203 |
+ $blocks = array_keys($context['ticket_blocks']); |
|
204 |
+ foreach ($blocks as $block) |
|
205 |
+ { |
|
206 |
+ $context['current_block'] = $block; |
|
207 |
+ template_ticket_block(); |
|
208 |
+ } |
|
209 |
+ |
|
210 |
+ echo ' |
|
211 |
+ </td> |
|
212 |
+ </tr> |
|
213 |
+ </table> |
|
214 |
+ </div>'; |
|
215 |
+} |
|
216 |
+ |
|
217 |
+/** |
|
218 |
+ * Display a collapsed block. |
|
219 |
+ * |
|
220 |
+ * In the front page, you are able to force a given block to be displayed in its entirety. When that happens, the other blocks are collapsed, so that they are present but their principle content is not. |
|
221 |
+ * |
|
222 |
+ * @see template_ticket_block() |
|
223 |
+ * @since 1.0 |
|
224 |
+*/ |
|
225 |
+function template_collapsed_ticket_block() |
|
226 |
+{ |
|
227 |
+ global $context, $txt, $settings, $scripturl; |
|
228 |
+ |
|
229 |
+ echo ' |
|
230 |
+ <div class="tborder"> |
|
231 |
+ <div class="cat_bar"> |
|
232 |
+ <h3 class="catbg"> |
|
233 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $context['ticket_blocks'][$context['current_block']]['block_icon'], '" alt="*" /> |
|
234 |
+ ', (empty($context['block_link']) ? '' : '<a href="' . $context['block_link'] . '">'), $context['ticket_blocks'][$context['current_block']]['title'], ' |
|
235 |
+ <span class="smalltext">(', $context['ticket_blocks'][$context['current_block']]['count'], ' ', ($context['ticket_blocks'][$context['current_block']]['count'] == 1 ? $txt['shd_count_ticket_1'] : $txt['shd_count_tickets']), ')</span>', (empty($context['block_link']) ? '' : '</a>'), ' |
|
236 |
+ </h3> |
|
237 |
+ </div> |
|
238 |
+ </div> |
|
239 |
+ <br /> |
|
240 |
+ <br />'; |
|
241 |
+} |
|
242 |
+ |
|
243 |
+/** |
|
244 |
+ * Display an individual, non-collapsed block. |
|
245 |
+ * |
|
246 |
+ * Each front-page template uses this function to display a given block of tickets. It handles displaying the menu header, including ticket count, followed by all the different column types as listed in {@link shd_main_helpdesk()}, then to iterate through the ticket details to display each row (provided by {@link shd_helpdesk_listing()}. |
|
247 |
+ * |
|
248 |
+ * @see shd_main_helpdesk() |
|
249 |
+ * @see shd_helpdesk_listing() |
|
250 |
+ * @since 1.0 |
|
251 |
+*/ |
|
252 |
+function template_ticket_block() |
|
253 |
+{ |
|
254 |
+ global $context, $txt, $settings; |
|
255 |
+ // $context['ticket_blocks'] = array of arrays of ticket data |
|
256 |
+ // $context['current_block'] = the block to display now |
|
257 |
+ |
|
258 |
+ echo ' |
|
259 |
+ <div class="tborder"> |
|
260 |
+ <div class="cat_bar"> |
|
261 |
+ <h3 id="shd_block_', $context['current_block'], '" class="catbg grid_header"> |
|
262 |
+ ', !empty($context['ticket_blocks'][$context['current_block']]['page_index']) ? '<span class="floatright smalltext">'. $txt['pages'] . ': ' . $context['ticket_blocks'][$context['current_block']]['page_index'] . '</span>' : '', ' |
|
263 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $context['ticket_blocks'][$context['current_block']]['block_icon'], '" alt="*" /> |
|
264 |
+ ', (empty($context['block_link']) ? '' : '<a href="' . $context['block_link'] . '">'), $context['ticket_blocks'][$context['current_block']]['title'], ' |
|
265 |
+ <span class="smalltext">(', $context['ticket_blocks'][$context['current_block']]['count'], ' ', ($context['ticket_blocks'][$context['current_block']]['count'] == 1 ? $txt['shd_count_ticket_1'] : $txt['shd_count_tickets']), ')</span>', (empty($context['block_link']) ? '' : '</a>'), ' |
|
266 |
+ </h3> |
|
267 |
+ </div> |
|
268 |
+ |
|
269 |
+ <table class="shd_ticketlist" cellspacing="0" width="100%"> |
|
270 |
+ <tr class="titlebg">'; |
|
271 |
+ |
|
272 |
+ $block_width = 0; |
|
273 |
+ foreach ($context['ticket_blocks'][$context['current_block']]['columns'] as $column) |
|
274 |
+ { |
|
275 |
+ $block_width++; |
|
276 |
+ switch ($column) |
|
277 |
+ { |
|
278 |
+ case 'ticket_id': |
|
279 |
+ echo ' |
|
280 |
+ <td width="8%" colspan="2" class="shd_nowrap"><img src="', $settings['default_images_url'], '/simpledesk/ticket.png" class="shd_smallicon" alt="" /> ', template_shd_menu_header('ticketid', $txt['shd_ticket']), '</td>'; |
|
281 |
+ $block_width++; // is 2 blocks wide |
|
282 |
+ break; |
|
283 |
+ case 'ticket_name': |
|
284 |
+ echo ' |
|
285 |
+ <td width="15%" class="shd_nowrap">', template_shd_menu_header('ticketname', $txt['shd_ticket_name']), '</td>'; |
|
286 |
+ break; |
|
287 |
+ case 'starting_user': |
|
288 |
+ echo ' |
|
289 |
+ <td width="12%" class="shd_nowrap"><img src="', $settings['default_images_url'], '/simpledesk/user.png" class="shd_smallicon" alt="" /> ', template_shd_menu_header('starter', $txt['shd_ticket_started_by']), '</td>'; |
|
290 |
+ break; |
|
291 |
+ case 'last_reply': |
|
292 |
+ echo ' |
|
293 |
+ <td width="20%" class="shd_nowrap"><img src="', $settings['default_images_url'], '/simpledesk/staff.png" class="shd_smallicon" alt="" /> ', template_shd_menu_header('lastreply', $txt['shd_ticket_updated_by']), '</td>'; |
|
294 |
+ break; |
|
295 |
+ case 'assigned': |
|
296 |
+ echo ' |
|
297 |
+ <td width="12%" class="shd_nowrap"><img src="', $settings['default_images_url'], '/simpledesk/staff.png" class="shd_smallicon" alt="" /> ', template_shd_menu_header('assigned', $txt['shd_ticket_assigned']), '</td>'; |
|
298 |
+ break; |
|
299 |
+ case 'status': |
|
300 |
+ echo ' |
|
301 |
+ <td width="17%" class="shd_nowrap"><img src="', $settings['default_images_url'], '/simpledesk/status.png" class="shd_smallicon" alt="" /> ', template_shd_menu_header('starter', $txt['shd_ticket_status']), '</td>'; |
|
302 |
+ break; |
|
303 |
+ case 'urgency': |
|
304 |
+ echo ' |
|
305 |
+ <td width="8%" class="shd_nowrap"><img src="', $settings['default_images_url'], '/simpledesk/urgency.png" class="shd_smallicon" alt="" /> ', template_shd_menu_header('urgency', $txt['shd_ticket_urgency']), '</td>'; |
|
306 |
+ break; |
|
307 |
+ case 'updated': |
|
308 |
+ echo ' |
|
309 |
+ <td width="22%" class="shd_nowrap"><img src="', $settings['default_images_url'], '/simpledesk/time.png" class="shd_smallicon" alt="" /> ', template_shd_menu_header('updated', $txt['shd_ticket_updated']), '</td>'; |
|
310 |
+ break; |
|
311 |
+ case 'replies': |
|
312 |
+ echo ' |
|
313 |
+ <td width="7%" class="shd_nowrap">', template_shd_menu_header('replies', $txt['shd_ticket_num_replies']), '</td>'; |
|
314 |
+ break; |
|
315 |
+ case 'allreplies': |
|
316 |
+ echo ' |
|
317 |
+ <td width="7%" class="shd_nowrap">', template_shd_menu_header('allreplies', $txt['shd_ticket_num_replies']), '</td>'; |
|
318 |
+ break; |
|
319 |
+ case 'actions': |
|
320 |
+ echo ' |
|
321 |
+ <td width="5%" class="shd_nowrap">', $txt['shd_actions'] , '</td>'; |
|
322 |
+ break; |
|
323 |
+ default: |
|
324 |
+ echo ' |
|
325 |
+ <td><td>'; |
|
326 |
+ break; |
|
327 |
+ } |
|
328 |
+ } |
|
329 |
+ |
|
330 |
+ echo ' |
|
331 |
+ </tr>'; |
|
332 |
+ |
|
333 |
+ if (empty($context['ticket_blocks'][$context['current_block']]['tickets'])) |
|
334 |
+ { |
|
335 |
+ echo ' |
|
336 |
+ <tr class="windowbg2"> |
|
337 |
+ <td colspan="', $block_width, '" class="shd_noticket">', $txt['shd_error_no_tickets'], '</td> |
|
338 |
+ </tr>'; |
|
339 |
+ } |
|
340 |
+ else |
|
341 |
+ { |
|
342 |
+ $use_bg2 = true; // start with windowbg2 to differentiate between that and titlebg |
|
343 |
+ foreach ($context['ticket_blocks'][$context['current_block']]['tickets'] as $ticket) |
|
344 |
+ { |
|
345 |
+ echo ' |
|
346 |
+ <tr class="', ($use_bg2 ? 'windowbg2' : 'windowbg'), '">'; |
|
347 |
+ |
|
348 |
+ foreach ($context['ticket_blocks'][$context['current_block']]['columns'] as $column) |
|
349 |
+ { |
|
350 |
+ switch ($column) |
|
351 |
+ { |
|
352 |
+ case 'ticket_id': |
|
353 |
+ $private_image = $ticket['private'] ? 'private.png' : 'public.png'; |
|
354 |
+ $private_txt = $ticket['private'] ? $txt['shd_ticket_private'] : $txt['shd_ticket_notprivate']; |
|
355 |
+ $unread_image = $ticket['is_unread'] ? 'unread.png' : 'read.png'; |
|
356 |
+ $unread_txt = $ticket['is_unread'] ? $txt['shd_ticket_new'] : $txt['shd_ticket_notnew']; |
|
357 |
+ echo ' |
|
358 |
+ <td width="1%" class="shd_nowrap"> |
|
359 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $unread_image, '" alt="', $unread_txt, '" title="', $unread_txt, '" /> |
|
360 |
+ <img src="', $settings['default_images_url'], '/simpledesk/', $private_image, '" alt="', $private_txt, '" title="', $private_txt, '" /> |
|
361 |
+ </td> |
|
362 |
+ <td width="4%" class="smalltext">', $ticket['display_id'], '</td>'; |
|
363 |
+ break; |
|
364 |
+ case 'ticket_name': |
|
365 |
+ echo ' |
|
366 |
+ <td class="smalltext">', $ticket['link']; |
|
367 |
+ |
|
368 |
+ if ($ticket['is_unread'] && !empty($ticket['new_href'])) |
|
369 |
+ echo ' <a href="', $ticket['new_href'], '"><img src="', $context['new_posts_image'], '" class="new_posts" alt="', $txt['new'], '" /></a>'; |
|
370 |
+ |
|
371 |
+ echo '</td>'; |
|
372 |
+ break; |
|
373 |
+ case 'starting_user': |
|
374 |
+ echo ' |
|
375 |
+ <td class="smalltext">', $ticket['starter']['link'], '</td>'; |
|
376 |
+ break; |
|
377 |
+ case 'last_reply': |
|
378 |
+ echo ' |
|
379 |
+ <td class="smalltext">', $ticket['respondent']['link'], '</td>'; |
|
380 |
+ break; |
|
381 |
+ case 'assigned': |
|
382 |
+ echo ' |
|
383 |
+ <td class="smalltext">' . $ticket['assigned']['link'] . '</td>'; |
|
384 |
+ break; |
|
385 |
+ case 'status': |
|
386 |
+ echo ' |
|
387 |
+ <td class="smalltext">', $ticket['status']['label'], '</td>'; |
|
388 |
+ break; |
|
389 |
+ case 'urgency': |
|
390 |
+ echo ' |
|
391 |
+ <td class="smalltext">' . $ticket['urgency']['label'] . '</td>'; |
|
392 |
+ break; |
|
393 |
+ case 'updated': |
|
394 |
+ echo ' |
|
395 |
+ <td class="smalltext">', $ticket['last_update'], '</td>'; |
|
396 |
+ break; |
|
397 |
+ case 'replies': |
|
398 |
+ echo ' |
|
399 |
+ <td class="smalltext">', $ticket['num_replies'], '</td>'; |
|
400 |
+ break; |
|
401 |
+ case 'allreplies': |
|
402 |
+ echo ' |
|
403 |
+ <td class="smalltext">', $ticket['all_replies'], '</td>'; |
|
404 |
+ break; |
|
405 |
+ case 'actions': |
|
406 |
+ echo ' |
|
407 |
+ <td class="shd_nowrap">'; |
|
408 |
+ |
|
409 |
+ foreach ($ticket['actions'] as $action) |
|
410 |
+ echo ' |
|
411 |
+ ', $action; |
|
412 |
+ |
|
413 |
+ echo ' |
|
414 |
+ </td>'; |
|
415 |
+ |
|
416 |
+ break; |
|
417 |
+ default: |
|
418 |
+ echo ' |
|
419 |
+ <td><td>'; |
|
420 |
+ break; |
|
421 |
+ } |
|
422 |
+ } |
|
423 |
+ |
|
424 |
+ echo ' |
|
425 |
+ </tr>'; |
|
426 |
+ |
|
427 |
+ $use_bg2 = !$use_bg2; |
|
428 |
+ } |
|
429 |
+ } |
|
430 |
+ |
|
431 |
+ if (!empty($context['ticket_blocks'][$context['current_block']]['page_index'])) |
|
432 |
+ echo ' |
|
433 |
+ <tr class="titlebg"> |
|
434 |
+ <td colspan="', $block_width, '"><span class="floatright smalltext">', $txt['pages'], ': ', $context['ticket_blocks'][$context['current_block']]['page_index'], '</span></td> |
|
435 |
+ </tr>'; |
|
436 |
+ |
|
437 |
+ echo ' |
|
438 |
+ </table> |
|
439 |
+ </div> |
|
440 |
+ <br /><br />'; |
|
441 |
+} |
|
442 |
+ |
|
443 |
+/** |
|
444 |
+ * Makes a menu header clickable/sortable. |
|
445 |
+ * |
|
446 |
+ * Within the ticket blocks, it is possible to sort the blocks by column, and do so in a way that is retained as you manipulate individual blocks. Since this is transient (not pushed to the database) it needs to be recorded in the URL over time. |
|
447 |
+ * |
|
448 |
+ * @param string $header The identifier of the header to use here; related to {@link shd_helpdesk_listing()} |
|
449 |
+ * @param string $string The text string to use as the header text |
|
450 |
+ * |
|
451 |
+ * @return string The fully formed HTML fragment for the link, text and hint image |
|
452 |
+ * @see template_ticket_block() |
|
453 |
+ * @since 1.0 |
|
454 |
+*/ |
|
455 |
+function template_shd_menu_header($header, $string) |
|
456 |
+{ |
|
457 |
+ global $context, $scripturl, $settings; |
|
458 |
+ |
|
459 |
+ if (empty($context['ticket_blocks'][$context['current_block']]['tickets'])) |
|
460 |
+ return $string; // no sense doing any work if it's an empty block and thus not sortable! |
|
461 |
+ |
|
462 |
+ $link = ''; |
|
463 |
+ // Get the pages of existing items first |
|
464 |
+ foreach ($context['ticket_blocks'] as $block_key => $block) |
|
465 |
+ { |
|
466 |
+ if (isset($_REQUEST['st_' . $block_key])) |
|
467 |
+ $link .= ';st_' . $block_key . '=' . $block['start']; |
|
468 |
+ } |
|
469 |
+ |
|
470 |
+ $direction = 'down'; |
|
471 |
+ // Now for sorting direction per block |
|
472 |
+ foreach ($context['ticket_blocks'] as $block_key => $block) |
|
473 |
+ { |
|
474 |
+ if (!$block['sort']['add_link'] && $block_key != $context['current_block']) |
|
475 |
+ continue; |
|
476 |
+ |
|
477 |
+ $link_direction = ($block_key == $context['current_block']) ? ($block['sort']['direction'] == 'asc' ? 'desc' : 'asc') : $block['sort']['direction']; |
|
478 |
+ |
|
479 |
+ $link .= ';so_' . $block_key . '=' . ($block_key != $context['current_block'] ? $block['sort']['item'] : $header) . '_' . $link_direction; |
|
480 |
+ } |
|
481 |
+ |
|
482 |
+ $html = '<a href="' . $scripturl . '?action=helpdesk;sa=' . $_REQUEST['sa'] . ($_REQUEST['sa'] == 'viewblock' ? ';block=' . $_REQUEST['block'] : '') . $link . '">' . $string . '</a> '; |
|
483 |
+ |
|
484 |
+ if ($context['ticket_blocks'][$context['current_block']]['sort']['item'] == $header) |
|
485 |
+ { |
|
486 |
+ $html .= '<img src="' . $settings['images_url'] . '/sort_' . ($context['ticket_blocks'][$context['current_block']]['sort']['direction'] == 'asc' ? 'down' : 'up') . '.gif" alt="" />'; |
|
487 |
+ } |
|
488 |
+ |
|
489 |
+ return $html; |
|
490 |
+} |
|
491 |
+ |
|
492 |
+/** |
|
493 |
+ * Displays a header to admins while the helpdesk is in maintenance mode. |
|
494 |
+ * |
|
495 |
+ * The helpdesk is disabled to non admins while in maintenance mode, but this template is added to the template layers if the user is an admin and it's in maintenance mode. |
|
496 |
+ * @since 1.1 |
|
497 |
+*/ |
|
498 |
+function template_shd_maintenance_above() |
|
499 |
+{ |
|
500 |
+ global $txt, $settings; |
|
501 |
+ echo '<div class="errorbox"><img src="', $settings['default_images_url'], '/simpledesk/update.png" alt="*" class="shd_icon_minihead" /> ', $txt['shd_helpdesk_maintenance'], '</div>'; |
|
502 |
+} |
|
503 |
+ |
|
504 |
+/** |
|
505 |
+ * Displays a footer to admins while the helpdesk is in maintenance mode. |
|
506 |
+ * |
|
507 |
+ * The helpdesk is disabled to non admins while in maintenance mode, but this template is added to the template layers if the user is an admin and it's in maintenance mode. |
|
508 |
+ * @since 1.1 |
|
509 |
+*/ |
|
510 |
+function template_shd_maintenance_below() |
|
511 |
+{ |
|
512 |
+ |
|
513 |
+} |
|
514 |
+ |
|
515 |
+// Provide a placeholder in the event template_button_strip isn't defined (like in the mobile templates) |
|
516 |
+if (!function_exists('template_button_strip')) |
|
517 |
+{ |
|
518 |
+ function template_button_strip($navigation, $direction) |
|
519 |
+ { |
|
520 |
+ } |
|
521 |
+} |
|
522 |
+?> |
|
0 | 523 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,16 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+// This file is here solely to protect your SimpleDesk templates directory. |
|
4 |
+ |
|
5 |
+// Look for Settings.php.... |
|
6 |
+if (file_exists(dirname(dirname(dirname(__FILE__))) . '/Settings.php')) |
|
7 |
+{ |
|
8 |
+ // Found it! |
|
9 |
+ require(dirname(dirname(dirname(__FILE__))) . '/Settings.php'); |
|
10 |
+ header('Location: ' . $boardurl); |
|
11 |
+} |
|
12 |
+// Can't find it... just forget it. |
|
13 |
+else |
|
14 |
+ exit; |
|
15 |
+ |
|
16 |
+?> |
|
0 | 17 |
\ No newline at end of file |
1 | 18 |