PluginProbe
Document Gallery / 3.0.2
Document Gallery v3.0.2
trunk 0.8 0.8.5 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1 1.2 1.2.1 1.3 1.3.1 1.4 1.4.1 1.4.2 1.4.3 2.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 94 releases
document-gallery / admin / class-admin.php

class-admin.php in Document Gallery 3.0.2, at admin/class-admin.php

1,234 lines 51.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined('WPINC') OR exit;
3
4 class DG_Admin {
5 /**
6 * @var string The hook for the Document Gallery settings page.
7 */
8 private static $hook;
9
10 /**
11 * @var string The current tab being rendered.
12 */
13 private static $current;
14
15 /**
16 * NOTE: This should only ever be accessed through getTabs().
17 *
18 * @var multitype:string Associative array containing all tab names, keyed by tab slug.
19 */
20 private static $tabs;
21
22 /**
23 * Returns reference to tabs array, initializing if needed.
24 *
25 * NOTE: This cannot be done in a static constructor due to timing with i18n.
26 */
27 public static function &getTabs() {
28 if (!isset(self::$tabs)) {
29 self::$tabs = array(
30 'General' => __('General', 'document-gallery'),
31 'Thumbnail' => __('Thumbnail Management', 'document-gallery'),
32 'Logging' => __('Logging', 'document-gallery'),
33 'Advanced' => __('Advanced', 'document-gallery'));
34 }
35
36 return self::$tabs;
37 }
38
39 /**
40 * Renders Document Gallery options page.
41 */
42 public static function renderOptions() { ?>
43 <div class="wrap">
44 <h2><?php echo __('Document Gallery Settings', 'document-gallery'); ?></h2>
45
46 <h2 class="nav-tab-wrapper">
47 <?php foreach (self::getTabs() as $tab => $name) {
48 $class = ($tab == self::$current) ? ' nav-tab-active' : '';
49 echo '<a class="nav-tab '.$tab.'-tab'.$class.'" href="?page=' . DG_OPTION_NAME . '&tab='.$tab.'">'.$name.'</a>';
50 } ?>
51 </h2>
52
53 <form method="post" action="options.php" id="tab-<?php echo self::$current?>">
54 <input type="hidden" name="<?php echo DG_OPTION_NAME; ?>[tab]" value="<?php echo self::$current; ?>" />
55 <?php
56 settings_fields(DG_OPTION_NAME);
57 do_settings_sections(DG_OPTION_NAME);
58 if (self::$current != 'Thumbnail' && self::$current != 'Logging') {
59 submit_button();
60 }
61 ?>
62 </form>
63
64 </div>
65 <?php }
66
67 /**
68 * Adds settings link to main plugin view.
69 */
70 public static function addSettingsLink($links) {
71 $settings = '<a href="options-general.php?page=' . DG_OPTION_NAME . '">' .
72 __('Settings', 'document-gallery') . '</a>';
73 array_unshift($links, $settings);
74
75 return $links;
76 }
77
78 /**
79 * Adds donate link to main plugin view.
80 */
81 public static function addDonateLink($links, $file) {
82 if ($file === DG_BASENAME) {
83 global $dg_options;
84
85 $donate = '<strong><a href="' . $dg_options['meta']['donate_link'] . '">' .
86 __('Donate', 'document-gallery') . '</a></strong>';
87 $links[] = $donate;
88 }
89
90 return $links;
91 }
92
93 /**
94 * Adds Document Gallery settings page to admin navigation.
95 */
96 public static function addAdminPage() {
97 DG_Admin::$hook = add_options_page(
98 __('Document Gallery Settings', 'document-gallery'),
99 __('Document Gallery', 'document-gallery'),
100 'manage_options', DG_OPTION_NAME, array(__CLASS__, 'renderOptions'));
101 add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueueScriptsAndStyles'));
102 }
103
104 /**
105 * Enqueues styles and scripts for the admin settings page.
106 */
107 public static function enqueueScriptsAndStyles($hook) {
108 if ($hook !== DG_Admin::$hook) return;
109
110 wp_enqueue_style('document-gallery-admin', DG_URL . 'assets/css/admin.css', null, DG_VERSION);
111 wp_enqueue_script('document-gallery-admin', DG_URL . 'assets/js/admin.js', array('jquery'), DG_VERSION, true);
112 wp_localize_script('document-gallery-admin', 'dg_admin_vars', array('upload_limit' => wp_max_upload_size()));
113 if ($hook == 'post.php') {
114 wp_localize_script('document-gallery-admin', 'ajax_object', array('ajax_url' => admin_url('admin-ajax.php')));
115 }
116 }
117
118 /**
119 * Registers settings for the Document Gallery options page.
120 */
121 public static function registerSettings() {
122 if (empty($_REQUEST['tab']) || !array_key_exists($_REQUEST['tab'], self::getTabs())) {
123 reset(self::getTabs());
124 self::$current = key(self::getTabs());
125 } else {
126 self::$current = $_REQUEST['tab'];
127 }
128
129 register_setting(DG_OPTION_NAME, DG_OPTION_NAME, array(__CLASS__, 'validateSettings'));
130
131 $funct = 'register' . self::$current . 'Settings';
132 DG_Admin::$funct();
133 }
134
135 /**
136 * Registers settings for the general tab.
137 */
138 private static function registerGeneralSettings() {
139 global $dg_options;
140
141 include_once DG_PATH . 'inc/class-gallery.php';
142 include_once DG_PATH . 'inc/class-thumber.php';
143
144 $defaults = $dg_options['gallery'];
145 $active = $dg_options['thumber']['active'];
146
147 add_settings_section(
148 'gallery_defaults', __('Default Settings', 'document-gallery'),
149 array(__CLASS__, 'renderDefaultSettingsSection'), DG_OPTION_NAME);
150
151 add_settings_section(
152 'thumbnail_generation', __('Thumbnail Generation', 'document-gallery'),
153 array(__CLASS__, 'renderThumberSection'), DG_OPTION_NAME);
154
155 add_settings_section(
156 'css', __('Custom CSS', 'document-gallery'),
157 array(__CLASS__, 'renderCssSection'), DG_OPTION_NAME);
158
159 add_settings_field(
160 'gallery_defaults_attachment_pg', 'attachment_pg',
161 array(__CLASS__, 'renderCheckboxField'),
162 DG_OPTION_NAME, 'gallery_defaults',
163 array (
164 'label_for' => 'label_gallery_defaults_attachment_pg',
165 'name' => 'gallery_defaults][attachment_pg',
166 'value' => esc_attr($defaults['attachment_pg']),
167 'option_name' => DG_OPTION_NAME,
168 'description' => __('Link to attachment page rather than to file', 'document-gallery')
169 ));
170
171 add_settings_field(
172 'gallery_defaults_columns', 'columns',
173 array(__CLASS__, 'renderTextField'),
174 DG_OPTION_NAME, 'gallery_defaults',
175 array (
176 'label_for' => 'label_gallery_defaults_columns',
177 'name' => 'gallery_defaults][columns',
178 'value' => esc_attr($defaults['columns']),
179 'type' => 'number" min="1" step="1',
180 'option_name' => DG_OPTION_NAME,
181 'description' => __('The number of columns to display when not rendering descriptions.', 'document-gallery')
182 ));
183
184 add_settings_field(
185 'gallery_defaults_descriptions', 'descriptions',
186 array(__CLASS__, 'renderCheckboxField'),
187 DG_OPTION_NAME, 'gallery_defaults',
188 array (
189 'label_for' => 'label_gallery_defaults_descriptions',
190 'name' => 'gallery_defaults][descriptions',
191 'value' => esc_attr($defaults['descriptions']),
192 'option_name' => DG_OPTION_NAME,
193 'description' => __('Include document descriptions', 'document-gallery')
194 ));
195
196 add_settings_field(
197 'gallery_defaults_fancy', 'fancy',
198 array(__CLASS__, 'renderCheckboxField'),
199 DG_OPTION_NAME, 'gallery_defaults',
200 array (
201 'label_for' => 'label_gallery_defaults_fancy',
202 'name' => 'gallery_defaults][fancy',
203 'value' => esc_attr($defaults['fancy']),
204 'option_name' => DG_OPTION_NAME,
205 'description' => __('Use auto-generated document thumbnails', 'document-gallery')
206 ));
207
208 add_settings_field(
209 'gallery_defaults_order', 'order',
210 array(__CLASS__, 'renderSelectField'),
211 DG_OPTION_NAME, 'gallery_defaults',
212 array (
213 'label_for' => 'label_gallery_defaults_order',
214 'name' => 'gallery_defaults][order',
215 'value' => esc_attr($defaults['order']),
216 'options' => DG_Gallery::getOrderOptions(),
217 'option_name' => DG_OPTION_NAME,
218 'description' => __('Ascending or descending sorting of documents', 'document-gallery')
219 ));
220
221 add_settings_field(
222 'gallery_defaults_orderby', 'orderby',
223 array(__CLASS__, 'renderSelectField'),
224 DG_OPTION_NAME, 'gallery_defaults',
225 array (
226 'label_for' => 'label_gallery_defaults_orderby',
227 'name' => 'gallery_defaults][orderby',
228 'value' => esc_attr($defaults['orderby']),
229 'options' => DG_Gallery::getOrderbyOptions(),
230 'option_name' => DG_OPTION_NAME,
231 'description' => __('Which field to order documents by', 'document-gallery')
232 ));
233
234 add_settings_field(
235 'gallery_defaults_relation', 'relation',
236 array(__CLASS__, 'renderSelectField'),
237 DG_OPTION_NAME, 'gallery_defaults',
238 array (
239 'label_for' => 'label_gallery_defaults_relation',
240 'name' => 'gallery_defaults][relation',
241 'value' => esc_attr($defaults['relation']),
242 'options' => DG_Gallery::getRelationOptions(),
243 'option_name' => DG_OPTION_NAME,
244 'description' => __('Whether matched documents must have all taxa_names (AND) or at least one (OR)', 'document-gallery')
245 ));
246
247 add_settings_field(
248 'gallery_defaults_limit', 'limit',
249 array(__CLASS__, 'renderTextField'),
250 DG_OPTION_NAME, 'gallery_defaults',
251 array (
252 'label_for' => 'label_gallery_defaults_limit',
253 'name' => 'gallery_defaults][limit',
254 'value' => esc_attr($defaults['limit']),
255 'type' => 'number" min="-1" step="1',
256 'option_name' => DG_OPTION_NAME,
257 'description' => __('Limit the number of documents included. -1 means no limit.', 'document-gallery')
258 ));
259
260 add_settings_field(
261 'gallery_defaults_mime_types', 'mime_types',
262 array(__CLASS__, 'renderTextField'),
263 DG_OPTION_NAME, 'gallery_defaults',
264 array (
265 'label_for' => 'label_gallery_defaults_mime_types',
266 'name' => 'gallery_defaults][mime_types',
267 'value' => esc_attr($defaults['mime_types']),
268 'type' => 'text',
269 'option_name' => DG_OPTION_NAME,
270 'description' => __('Comma-delimited list of <a href="http://en.wikipedia.org/wiki/Internet_media_type#List_of_common_media_types">MIME types</a>.', 'document-gallery')
271 ));
272
273 add_settings_field(
274 'gallery_defaults_post_status', 'post_status',
275 array(__CLASS__, 'renderSelectField'),
276 DG_OPTION_NAME, 'gallery_defaults',
277 array (
278 'label_for' => 'label_gallery_defaults_post_status',
279 'name' => 'gallery_defaults][post_status',
280 'value' => esc_attr($defaults['post_status']),
281 'options' => DG_Gallery::getPostStatuses(),
282 'option_name' => DG_OPTION_NAME,
283 'description' => __('Which post status to look for when querying documents.', 'document-gallery')
284 ));
285
286 add_settings_field(
287 'gallery_defaults_post_type', 'post_type',
288 array(__CLASS__, 'renderSelectField'),
289 DG_OPTION_NAME, 'gallery_defaults',
290 array (
291 'label_for' => 'label_gallery_defaults_post_type',
292 'name' => 'gallery_defaults][post_type',
293 'value' => esc_attr($defaults['post_type']),
294 'options' => DG_Gallery::getPostTypes(),
295 'option_name' => DG_OPTION_NAME,
296 'description' => __('Which post type to look for when querying documents.', 'document-gallery')
297 ));
298
299 add_settings_field(
300 'thumbnail_generation_av', 'Audio/Video',
301 array(__CLASS__, 'renderCheckboxField'),
302 DG_OPTION_NAME, 'thumbnail_generation',
303 array (
304 'label_for' => 'label_thumbnail_generation_av',
305 'name' => 'thumbnail_generation][av',
306 'value' => esc_attr($active['av']),
307 'option_name' => DG_OPTION_NAME,
308 'description' => esc_html__('Locally generate thumbnails for audio & video files.', 'document-gallery')
309 ));
310
311 add_settings_field(
312 'thumbnail_generation_gs', 'Ghostscript',
313 array(__CLASS__, 'renderCheckboxField'),
314 DG_OPTION_NAME, 'thumbnail_generation',
315 array (
316 'label_for' => 'label_thumbnail_generation_gs',
317 'name' => 'thumbnail_generation][gs',
318 'value' => esc_attr($active['gs']),
319 'option_name' => DG_OPTION_NAME,
320 'description' => DG_Thumber::isGhostscriptAvailable()
321 ? __('Use <a href="http://www.ghostscript.com/" target="_blank">Ghostscript</a> for faster local PDF processing (compared to Imagick).', 'document-gallery')
322 : __('Your server is not configured to run <a href="http://www.ghostscript.com/" target="_blank">Ghostscript</a>.', 'document-gallery'),
323 'disabled' => !DG_Thumber::isGhostscriptAvailable()
324 ));
325
326 add_settings_field(
327 'thumbnail_generation_imagick', 'Imagick',
328 array(__CLASS__, 'renderCheckboxField'),
329 DG_OPTION_NAME, 'thumbnail_generation',
330 array (
331 'label_for' => 'label_thumbnail_generation_imagick',
332 'name' => 'thumbnail_generation][imagick',
333 'value' => esc_attr($active['imagick']),
334 'option_name' => DG_OPTION_NAME,
335 'description' => DG_Thumber::isImagickAvailable()
336 ? __('Use <a href="http://www.php.net/manual/en/book.imagick.php" target="_blank">Imagick</a> to handle lots of filetypes locally.', 'document-gallery')
337 : __('Your server is not configured to run <a href="http://www.php.net/manual/en/book.imagick.php" target="_blank">Imagick</a>.', 'document-gallery'),
338 'disabled' => !DG_Thumber::isImagickAvailable()
339 ));
340
341 add_settings_field(
342 'thumbnail_generation_width', 'Max Thumbnail Dimensions',
343 array(__CLASS__, 'renderMultiTextField'),
344 DG_OPTION_NAME, 'thumbnail_generation',
345 array (
346 array (
347 'label_for' => 'label_advanced_width',
348 'name' => 'thumbnail_generation][width',
349 'value' => esc_attr($dg_options['thumber']['width']),
350 'type' => 'number" min="1" step="1',
351 'option_name' => DG_OPTION_NAME,
352 'description' => ' x '),
353 array (
354 'label_for' => 'label_advanced_height',
355 'name' => 'thumbnail_generation][height',
356 'value' => esc_attr($dg_options['thumber']['height']),
357 'type' => 'number" min="1" step="1',
358 'option_name' => DG_OPTION_NAME,
359 'description' => __('The max width and height (in pixels) that thumbnails will be generated.', 'document-gallery'))
360 ));
361 }
362
363 /**
364 * Registers settings for the thumbnail management tab.
365 */
366 private static function registerThumbnailSettings() {
367 add_settings_section(
368 'thumbnail_table', '',
369 array(__CLASS__, 'renderThumbnailSection'), DG_OPTION_NAME);
370 }
371
372 /**
373 * Registers settings for the logging tab.
374 */
375 private static function registerLoggingSettings() {
376 add_settings_section(
377 'logging_table', '',
378 array(__CLASS__, 'renderLoggingSection'), DG_OPTION_NAME);
379 }
380
381 /**
382 * Registers settings for the advanced tab.
383 */
384 private static function registerAdvancedSettings() {
385 global $dg_options;
386
387 add_settings_section(
388 'advanced', __('Advanced Thumbnail Generation', 'document-gallery'),
389 array(__CLASS__, 'renderAdvancedSection'), DG_OPTION_NAME);
390
391 add_settings_field(
392 'advanced_logging', 'Logging',
393 array(__CLASS__, 'renderCheckboxField'),
394 DG_OPTION_NAME, 'advanced',
395 array (
396 'label_for' => 'label_advanced_logging',
397 'name' => 'logging',
398 'value' => esc_attr($dg_options['logging']),
399 'option_name' => DG_OPTION_NAME,
400 'description' => __('Whether to log debug and error information related to Document Gallery.', 'document-gallery')
401 ));
402
403 add_settings_field(
404 'advanced_validation', 'Option Validation',
405 array(__CLASS__, 'renderCheckboxField'),
406 DG_OPTION_NAME, 'advanced',
407 array (
408 'label_for' => 'label_advanced_validation',
409 'name' => 'validation',
410 'value' => esc_attr($dg_options['validation']),
411 'option_name' => DG_OPTION_NAME,
412 'description' => __('Whether option structure should be validated before save. This is not generally necessary.', 'document-gallery')
413 ));
414
415 add_settings_field(
416 'advanced_thumb_timeout', 'Thumbnail Generation Timeout',
417 array(__CLASS__, 'renderTextField'),
418 DG_OPTION_NAME, 'advanced',
419 array (
420 'label_for' => 'label_advanced_thumb_timeout',
421 'name' => 'timeout',
422 'value' => esc_attr($dg_options['thumber']['timeout']),
423 'type' => 'number" min="1" step="1',
424 'option_name' => DG_OPTION_NAME,
425 'description' => __('Max number of seconds to wait for thumbnail generation before defaulting to filetype icons.', 'document-gallery') .
426 ' <em>' . __('Note that generation will continue where timeout happened next time the gallery is loaded.', 'document-gallery') . '</em>'));
427
428 add_settings_field(
429 'advanced_gs', 'Ghostscript Absolute Path',
430 array(__CLASS__, 'renderTextField'),
431 DG_OPTION_NAME, 'advanced',
432 array (
433 'label_for' => 'label_advanced_gs',
434 'name' => 'gs',
435 'value' => esc_attr($dg_options['thumber']['gs']),
436 'option_name' => DG_OPTION_NAME,
437 'description' => $dg_options['thumber']['gs']
438 ? __('Successfully auto-detected the location of Ghostscript.', 'document-gallery')
439 : __('Failed to auto-detect the location of Ghostscript.', 'document-gallery')
440 ));
441
442 add_settings_section(
443 'advanced_options_dump', __('Options Array Dump', 'document-gallery'),
444 array(__CLASS__, 'renderOptionsDumpSection'), DG_OPTION_NAME);
445 }
446
447 /**
448 * Validates submitted options, sanitizing any invalid options.
449 * @param array $values User-submitted new options.
450 * @return array Sanitized new options.
451 */
452 public static function validateSettings($values) {
453 if (empty($values['tab']) || !array_key_exists($values['tab'], self::getTabs())) {
454 reset(self::getTabs());
455 $values['tab'] = key(self::getTabs());
456 }
457 $funct = 'validate'.$values['tab'].'Settings';
458 unset($values['tab']);
459 return DG_Admin::$funct($values);
460 }
461
462 /**
463 * Validates general settings, sanitizing any invalid options.
464 * @param array $values User-submitted new options.
465 * @return array Sanitized new options.
466 */
467 private static function validateGeneralSettings($values) {
468 global $dg_options;
469 $ret = $dg_options;
470
471 include_once DG_PATH . 'inc/class-gallery.php';
472
473 $thumbs_cleared = false;
474
475 // handle gallery shortcode defaults
476 $errs = array();
477 $ret['gallery'] = DG_Gallery::sanitizeDefaults(null, $values['gallery_defaults'], $errs);
478
479 foreach ($errs as $k => $v) {
480 add_settings_error(DG_OPTION_NAME, str_replace('_', '-', $k), $v);
481 }
482
483 // handle setting width
484 if (isset($values['thumbnail_generation']['width'])) {
485 $width = (int)$values['thumbnail_generation']['width'];
486 if ($width > 0) {
487 $ret['thumber']['width'] = $width;
488 } else {
489 add_settings_error(DG_OPTION_NAME, 'thumber-width',
490 __('Invalid width given: ', 'document-gallery') . $values['thumbnail_generation']['width']);
491 }
492
493 unset($values['thumbnail_generation']['width']);
494 }
495
496 // handle setting height
497 if (isset($values['thumbnail_generation']['height'])) {
498 $height = (int)$values['thumbnail_generation']['height'];
499 if ($height > 0) {
500 $ret['thumber']['height'] = $height;
501 } else {
502 add_settings_error(DG_OPTION_NAME, 'thumber-height',
503 __('Invalid height given: ', 'document-gallery') . $values['thumbnail_generation']['height']);
504 }
505
506 unset($values['thumbnail_generation']['width']);
507 }
508
509 // delete thumb cache to force regeneration if max dimensions changed
510 if ($ret['thumber']['width'] !== $dg_options['thumber']['width'] ||
511 $ret['thumber']['height'] !== $dg_options['thumber']['height']) {
512 foreach ($ret['thumber']['thumbs'] as $v) {
513 if (isset($v['thumber'])) {
514 @unlink($v['thumb_path']);
515 }
516 }
517
518 $ret['thumber']['thumbs'] = array();
519 $thumbs_cleared = true;
520 }
521
522 // handle setting the active thumbers
523 foreach (array_keys($ret['thumber']['active']) as $k) {
524 $ret['thumber']['active'][$k] = isset($values['thumbnail_generation'][$k]);
525 }
526
527 // if new thumbers available, clear failed thumbnails for retry
528 if (!$thumbs_cleared) {
529 foreach ($dg_options['thumber']['active'] as $k => $v) {
530 if (!$v && $ret['thumber']['active'][$k]) {
531 foreach ($dg_options['thumber']['thumbs'] as $k => $v) {
532 if (empty($v['thumber'])) {
533 unset($ret['thumber']['thumbs'][$k]);
534 }
535 }
536 break;
537 }
538 }
539 }
540
541 // handle modified CSS
542 if (trim($ret['css']['text']) !== trim($values['css'])) {
543 $ret['css']['text'] = trim($values['css']);
544 $ret['css']['minified'] = DocumentGallery::compileCustomCss($ret['css']['text']);
545 }
546
547 return $ret;
548 }
549
550 /**
551 * Validates thumbnail management settings, sanitizing any invalid options.
552 * @param array $values User-submitted new options.
553 * @return array Sanitized new options.
554 */
555 private static function validateThumbnailSettings($values) {
556 global $dg_options;
557 $ret = $dg_options;
558 $responseArr = array('result' => false);
559
560 if (isset($values['entry'])) {
561 $ID = intval($values['entry']);
562 } else {
563 $ID = -1;
564 }
565
566 // Thumbnail(s) cleanup;
567 // cleanup value is a marker
568 if ( isset($values['cleanup']) && isset($values['ids']) ) {
569 $deleted = array_values(array_intersect(array_keys($dg_options['thumber']['thumbs']), $values['ids']));
570
571 foreach ($deleted as $k) {
572 if (isset($ret['thumber']['thumbs'][$k]['thumber'])) {
573 @unlink($ret['thumber']['thumbs'][$k]['thumb_path']);
574 }
575
576 unset($ret['thumber']['thumbs'][$k]);
577 }
578
579 $responseArr['result'] = true;
580 $responseArr['deleted'] = $deleted;
581 }
582
583 // Attachment title update
584 // title value is a marker
585 elseif ( isset($values['title']) && $ID != -1 ) {
586 $attachment = array(
587 'ID' => $ID,
588 'post_title' => rawurldecode(addslashes($values['title']))
589 );
590 if ( wp_update_post( $attachment ) ) {
591 $responseArr['result'] = true;
592 }
593 }
594
595 // Attachment description update
596 // description value is a marker
597 elseif ( isset($values['description']) && $ID != -1 ) {
598 $attachment = array(
599 'ID' => $ID,
600 'post_content' => rawurldecode(addslashes($values['description']))
601 );
602 if ( wp_update_post( $attachment ) ) {
603 $responseArr['result'] = true;
604 }
605 }
606
607 // Thumbnail file manual refresh (one at a time)
608 // upload value is a marker
609 elseif ( isset($values['upload']) && isset($_FILES['file']) && isset($ret['thumber']['thumbs'][$ID]) ) {
610 $old_path = $ret['thumber']['thumbs'][$ID]['thumb_path'];
611 $uploaded_filename = self::validateUploadedFile();
612 if ($uploaded_filename && DG_Thumber::setThumbnail($ID, $uploaded_filename)) {
613 if ($dg_options['thumber']['thumbs'][$ID]['thumb_path'] !== $old_path) {
614 @unlink($old_path);
615 }
616 $responseArr['result'] = true;
617 $responseArr['url'] = $dg_options['thumber']['thumbs'][$ID]['thumb_url'];
618 $ret['thumber']['thumbs'][$ID] = $dg_options['thumber']['thumbs'][$ID];
619 }
620 }
621
622 if (isset($values['ajax'])) {
623 echo DG_Util::jsonEncode($responseArr);
624 add_filter('wp_redirect', array(__CLASS__, '_exit'), 1, 0);
625 }
626
627 return $ret;
628 }
629
630 /**
631 * Validates uploaded file as a semi for potential thumbnail.
632 * @param str $var File field name.
633 * @return bool|str False on failure, path to temp file on success.
634 */
635 public static function validateUploadedFile($var = 'file') {
636 // checking if any file was delivered
637 if (!isset($_FILES[$var]))
638 return false;
639 // we gonna process only first one
640 if ( !is_array($_FILES[$var]['error']) ) {
641 $upload_err = $_FILES[$var]['error'];
642 $upload_path = $_FILES[$var]['tmp_name'];
643 $upload_size = $_FILES[$var]['size'];
644 $upload_type = $_FILES[$var]['type'];
645 $upload_name = $_FILES[$var]['name'];
646 } else {
647 $upload_err = $_FILES[$var]['error'][0];
648 $upload_path = $_FILES[$var]['tmp_name'][0];
649 $upload_size = $_FILES[$var]['size'][0];
650 $upload_type = $_FILES[$var]['type'][0];
651 $upload_name = $_FILES[$var]['name'][0];
652 }
653 $info = getimagesize($upload_path);
654 if ($info) {
655 if ($info['mime']!=$upload_type) {// in DG_Thumber::getExt() we'll define and set appropriate extension
656 DG_Logger::writeLog(
657 DG_LogLevel::Warning,
658 __('File extension doesn\'t match the MIME type of the image: ', 'document-gallery') .
659 $upload_name.' - '.$info['mime']);
660 }
661 if ($upload_size>wp_max_upload_size()) {
662 DG_Logger::writeLog(
663 DG_LogLevel::Warning,
664 __('Uploaded file size exceeds the allowable limit: ', 'document-gallery') .
665 $upload_name.' - '.$upload_size.'b');
666 return false;
667 }
668 } else {
669 DG_Logger::writeLog(
670 DG_LogLevel::Warning,
671 __('Uploaded file is not an image: ', 'document-gallery') .
672 $upload_name);
673 return false;
674 }
675 if ($upload_err == UPLOAD_ERR_OK && $upload_size > 0) {
676 $temp_file = $upload_path;
677 } else {
678 DG_Logger::writeLog(
679 DG_LogLevel::Error,
680 __('Failed to get uploaded file: ', 'document-gallery') .
681 $upload_err);
682 return false;
683 }
684
685 return $temp_file;
686 }
687
688 /**
689 * Validates logging settings, sanitizing any invalid options.
690 * @param array $values User-submitted new options.
691 * @return array Sanitized new options.
692 */
693 private static function validateLoggingSettings($values) {
694 global $dg_options;
695 if (isset($values['clearLog'])) {
696 DG_Logger::clearLog();
697 }
698 return $dg_options;
699 }
700
701 /**
702 * Validates advanced settings, sanitizing any invalid options.
703 * @param array $values User-submitted new options.
704 * @return array Sanitized new options.
705 */
706 private static function validateAdvancedSettings($values) {
707 global $dg_options;
708 $ret = $dg_options;
709
710 // handle setting the Ghostscript path
711 if (isset($values['gs']) &&
712 0 != strcmp($values['gs'], $ret['thumber']['gs'])) {
713 if (false === strpos($values['gs'], ';')) {
714 $ret['thumber']['gs'] = $values['gs'];
715 } else {
716 add_settings_error(DG_OPTION_NAME, 'thumber-gs',
717 __('Invalid Ghostscript path given: ', 'document-gallery') . $values['gs']);
718 }
719 }
720
721 // handle setting timeout
722 if (isset($values['timeout'])) {
723 $timeout = (int)$values['timeout'];
724 if ($timeout > 0) {
725 $ret['thumber']['timeout'] = $timeout;
726 } else {
727 add_settings_error(DG_OPTION_NAME, 'thumber-timeout',
728 __('Invalid timeout given: ', 'document-gallery') . $values['timeout']);
729 }
730 }
731
732 // validation checkbox
733 $ret['validation'] = isset($values['validation']);
734
735 // logging checkbox
736 $ret['logging'] = isset($values['logging']);
737
738 return $ret;
739 }
740
741 /**
742 * @return bool Whether to register settings.
743 */
744 public static function doRegisterSettings() {
745 if (!is_multisite()) {
746 $script = !empty($GLOBALS['pagenow']) ? $GLOBALS['pagenow'] : null;
747 } else {
748 $script = parse_url($_SERVER['REQUEST_URI']);
749 $script = basename($script['path']);
750 }
751
752 return !empty($script) && ('options-general.php' === $script || 'options.php' === $script);
753 }
754
755 /**
756 * Render the Default Settings section.
757 */
758 public static function renderDefaultSettingsSection() { ?>
759 <p><?php _e('The following values will be used by default in the shortcode. You can still manually set each of these values in each individual shortcode.', 'document-gallery'); ?></p>
760 <?php }
761
762 /**
763 * Render the Thumber section.
764 */
765 public static function renderThumberSection() { ?>
766 <p><?php _e('Select which tools to use when generating thumbnails.', 'document-gallery'); ?></p>
767 <?php }
768
769 /**
770 * Renders a text field for use when modifying the CSS to be printed in addition to the default CSS.
771 */
772 public static function renderCssSection() {
773 global $dg_options; ?>
774 <p><?php printf(
775 __('Enter custom CSS styling for use with document galleries. To see which ids and classes you can style, take a look at <a href="%s" target="_blank">style.css</a>.'),
776 DG_URL . 'assets/css/style.css'); ?></p>
777 <table class="form-table">
778 <tbody>
779 <tr valign="top">
780 <td>
781 <textarea name="<?php echo DG_OPTION_NAME; ?>[css]" rows="10" cols="50" class="large-text code"><?php echo $dg_options['css']['text']; ?></textarea>
782 </td>
783 </tr>
784 </tbody>
785 </table>
786 <?php }
787
788 /**
789 * Render the Thumber Advanced section.
790 */
791 public static function renderAdvancedSection() {
792 include_once DG_PATH . 'inc/class-thumber.php';?>
793 <p><?php _e('Unless you <em>really</em> know what you\'re doing, you should not touch these values.', 'document-gallery'); ?></p>
794 <?php if (!DG_Thumber::isExecAvailable()) : ?>
795 <p>
796 <em><?php _e('NOTE: <code>exec()</code> is not accessible. Ghostscript will not function.', 'document-gallery'); ?></em>
797 </p>
798 <?php endif; ?>
799 <?php }
800
801 /**
802 * Renders a readonly textfield containing a dump of current DG options.
803 */
804 public static function renderOptionsDumpSection() {
805 global $dg_options; ?>
806 <p><?php
807 _e('The following <em>readonly text</em> should be provided when <a href="http://wordpress.org/support/plugin/document-gallery" target="_blank">reporting a bug</a>:', 'documet-gallery');
808 ?></p>
809 <table class="form-table">
810 <tbody>
811 <tr valign="top">
812 <td>
813 <textarea readonly="true" rows="10" cols="50" id="options-dump" class="large-text code"><?php print_r($dg_options); ?></textarea>
814 </td>
815 </tr>
816 </tbody>
817 </table>
818 <?php }
819
820 /**
821 * Render the Thumbnail table.
822 */
823 public static function renderThumbnailSection() {
824 include_once DG_PATH . 'inc/class-thumber.php';
825 $options = DG_Thumber::getOptions();
826
827 $URL_params = array('page' => DG_OPTION_NAME, 'tab' => 'Thumbnail');
828 $att_ids = array();
829
830 if (isset($_REQUEST['orderby']) && in_array(strtolower($_REQUEST['orderby']), array('title', 'date'))) {
831 $orderby = strtolower($_REQUEST['orderby']);
832 $URL_params['orderby'] = $orderby;
833
834 switch ($orderby) {
835 case 'date':
836 foreach ($options['thumbs'] as $key => $node) {
837 $keyArray[$key] = $node['timestamp'];
838 $options['thumbs'][$key]['thumb_id'] = $att_ids[] = $key;
839 }
840 break;
841
842 case 'title':
843 foreach ($options['thumbs'] as $key => $node) {
844 $keyArray[$key] = basename($node['thumb_path']);
845 $options['thumbs'][$key]['thumb_id'] = $att_ids[] = $key;
846 }
847 break;
848 }
849
850 $order = strtolower($_REQUEST['order']);
851 if (!isset($_REQUEST['order']) || !in_array($order, array('asc', 'desc'))) {
852 $order = 'asc';
853 }
854 $URL_params['order'] = $order;
855
856 if ($order == 'asc') {
857 array_multisort($keyArray, SORT_ASC, $options['thumbs']);
858 } else {
859 array_multisort($keyArray, SORT_DESC, $options['thumbs']);
860 }
861 } else {
862 $orderby = '';
863 foreach ($options['thumbs'] as $key => $node) {
864 $options['thumbs'][$key]['thumb_id'] = $att_ids[] = $key;
865 }
866 }
867
868 static $limit_options = array(10, 25, 75);
869 if (!isset($_REQUEST['limit']) || !in_array(intval($_REQUEST['limit']), $limit_options)) {
870 $limit = $limit_options[0];
871 } else {
872 $limit = intval($_REQUEST['limit']);
873 }
874
875 $URL_params['limit'] = $limit;
876 $select_limit = '';
877 foreach ($limit_options as $l_o) {
878 $select_limit .= '<option value="'.$l_o.'"'.selected($limit, $l_o, false).'>'.$l_o.'</option>'.PHP_EOL;
879 }
880 $thumbs_number = count($options['thumbs']);
881 $lastsheet = ceil($thumbs_number/$limit);
882 $sheet = isset($_REQUEST['sheet']) ? intval($_REQUEST['sheet']) : 1;
883 if ($sheet <= 0 || $sheet > $lastsheet) {
884 $sheet = 1;
885 }
886
887 $offset = ($sheet - 1) * $limit;
888
889 $att_ids = array_slice($att_ids, $offset, $limit);
890
891 // https://core.trac.wordpress.org/ticket/12212
892 $atts = array();
893 if (!empty($att_ids)) {
894 $atts = get_posts(
895 array(
896 'post_type' => 'any',
897 'post_status' => 'any',
898 'numberposts' => -1,
899 'post__in' => $att_ids,
900 'orderby' => 'post__in'
901 ));
902 }
903
904 $titles = array();
905 $contents = array();
906 foreach ($atts as $att) {
907 $path_parts = pathinfo($att->guid);
908 $titles[$att->ID] = $att->post_title;
909 $types[$att->ID] = $path_parts['extension'];
910 $contents[$att->ID] = $att->post_content;
911 }
912 unset($atts);
913
914 $thead = '<tr>'.
915 '<th scope="col" class="manage-column column-cb check-column">'.
916 '<label class="screen-reader-text" for="cb-select-all-%1$d">'.__('Select All', 'document-gallery').'</label>'.
917 '<input id="cb-select-all-%1$d" type="checkbox">'.
918 '</th>'.
919 '<th scope="col" class="manage-column column-icon">'.__('Thumbnail', 'document-gallery').'</th>'.
920 '<th scope="col" class="manage-column column-title '.(($orderby != 'title')?'sortable desc':'sorted '.$order).'"><a href="?'.http_build_query(array_merge($URL_params, array('orderby'=>'title','order'=>(($orderby != 'title')?'asc':(($order == 'asc')?'desc':'asc'))))).'"><span>'.__('File name', 'document-gallery').'</span><span class="sorting-indicator"></span></th>'.
921 '<th scope="col" class="manage-column column-description">'.__('Description', 'document-gallery').'</th>'.
922 '<th scope="col" class="manage-column column-thumbupload"></th>'.
923 '<th scope="col" class="manage-column column-date '.(($orderby != 'date')?'sortable asc':'sorted '.$order).'"><a href="?'.http_build_query(array_merge($URL_params, array('orderby'=>'date','order'=>(($orderby != 'date')?'desc':(($order == 'asc')?'desc':'asc'))))).'"><span>'.__('Date', 'document-gallery').'</span><span class="sorting-indicator"></span></th>'.
924 '</tr>';
925
926 $pagination = '<div class="alignleft bulkactions"><button class="button action deleteSelected">'.__('Delete Selected', 'document-gallery').'</button></div><div class="tablenav-pages">'.
927 '<span class="displaying-num">'.
928 $thumbs_number.' '._n('item', 'items', $thumbs_number).
929 '</span>'.($lastsheet>1?
930 '<span class="pagination-links">'.
931 '<a class="first-page'.( $sheet==1 ? ' disabled' : '').'" title="'.__('Go to the first page', 'document-gallery').'"'.( $sheet==1 ? '' : ' href="?'.http_build_query($URL_params).'"').'>«</a>'.
932 '<a class="prev-page'.( $sheet==1 ? ' disabled' : '').'" title="'.__('Go to the previous page', 'document-gallery').'"'.( $sheet==1 ? '' : ' href="?'.http_build_query(array_merge($URL_params, array('sheet'=>$sheet-1))).'"').'>‹</a>'.
933 '<span class="paging-input">'.
934 '<input class="current-page" title="'.__('Current page', 'document-gallery').'" type="text" name="paged" value="'.$sheet.'" size="'.strlen($sheet).'" maxlength="'.strlen($sheet).'"> '.__('of', 'document-gallery').' <span class="total-pages">'.$lastsheet.'</span></span>'.
935 '<a class="next-page'.( $sheet==$lastsheet ? ' disabled' : '').'" title="'.__('Go to the next page', 'document-gallery').'"'.( $sheet==$lastsheet ? '' : ' href="?'.http_build_query(array_merge($URL_params, array('sheet'=>$sheet+1))).'"').'>›</a>'.
936 '<a class="last-page'.( $sheet==$lastsheet ? ' disabled' : '').'" title="'.__('Go to the last page', 'document-gallery').'"'.( $sheet==$lastsheet ? '' : ' href="?'.http_build_query(array_merge($URL_params, array('sheet'=>$lastsheet))).'"').'>»</a>'.
937 '</span>':' <b>|</b> ').
938 '<span class="displaying-num"><select dir="rtl" class="limit_per_page">'.$select_limit.'</select> '.__('items per page', 'document-gallery').'</span>'.
939 '</div>'.
940 '<br class="clear" />';
941 ?>
942
943 <script type="text/javascript">
944 var URL_params = <?php echo DG_Util::jsonEncode($URL_params); ?>;
945 </script>
946 <div class="thumbs-list-wrapper">
947 <div>
948 <div class="tablenav top"><?php echo $pagination; ?></div>
949 <table id="ThumbsTable" class="wp-list-table widefat fixed media"
950 cellpadding="0" cellspacing="0">
951 <thead>
952 <?php printf($thead, 1); ?>
953 </thead>
954 <tfoot>
955 <?php printf($thead, 2); ?>
956 </tfoot>
957 <tbody><?php
958 $i = 0;
959 foreach ($options['thumbs'] as $v) {
960 if ($i < $offset) { $i++; continue; }
961 if (++$i > $offset + $limit) { break; }
962
963 $icon = isset($v['thumb_url']) ? $v['thumb_url'] : DG_Thumber::getDefaultThumbnail($v['thumb_id']);
964 $title = isset($titles[$v['thumb_id']]) ? $titles[$v['thumb_id']] : '';
965 $type = $types[$v['thumb_id']];
966 $description = $contents[$v['thumb_id']];
967 $date = DocumentGallery::localDateTimeFromTimestamp($v['timestamp']);
968
969 echo '<tr data-entry="'.$v['thumb_id'].'"><td scope="row" class="check-column"><input type="checkbox" class="cb-ids" name="' . DG_OPTION_NAME . '[ids][]" value="' .
970 $v['thumb_id'].'"></td><td class="column-icon media-icon"><img src="' .
971 $icon.'" />'.'</td><td class="title column-title">' .
972 ($title ? '<strong><a href="' . home_url('/?attachment_id='.$v['thumb_id']).'" target="_blank" title="'.__('View', 'document-gallery').' \'' .
973 $title.'\' '.__('attachment page', 'document-gallery').'"><span class="editable-title">'.$title.'</span> <sup>'.$type.'</sup></a></strong>' : __('Attachment not found', 'document-gallery')) .
974 '<span class="dashicons dashicons-edit"></span><span class="edit-controls"><span class="dashicons dashicons-yes"></span> <span class="dashicons dashicons-no"></span></span></td><td class="column-description"><div class="editable-description">'.$description.'</div><span class="dashicons dashicons-edit"></span><span class="edit-controls"><span class="dashicons dashicons-yes"></span> <span class="dashicons dashicons-no"></span></span>'. '</td><td class="column-thumbupload">' .
975 '<span class="manual-download">' .
976 '<span class="dashicons dashicons-upload"></span>' .
977 '<span class="html5dndmarker">Drop file here<span> or </span></span>' .
978 '<span class="buttons-area">' .
979 '<input id="upload-button'.$v['thumb_id'].'" type="file" />' .
980 '<input id="trigger-button'.$v['thumb_id'].'" type="button" value="Select File" class="button" />' .
981 '</span>' .
982 '</span>' .
983 '</td><td class="date column-date">'.$date.'</td></tr>'.PHP_EOL;
984 } ?>
985 </tbody>
986 </table>
987 <div class="tablenav bottom"><?php echo $pagination; ?></div>
988 </div>
989 </div>
990 <?php }
991
992 /**
993 * Adds meta box to the attchements' edit pages.
994 */
995 public static function addMetaBox() {
996 $screens = array( 'attachment' );
997 foreach ( $screens as $screen ) {
998 add_meta_box(
999 DG_OPTION_NAME.'_gen_box',
1000 __( '<b>Thumbnail</b> for <i><b>Document Gallery</b></i>', 'document-gallery' ),
1001 array(__CLASS__, 'renderMetaBox'),
1002 $screen,
1003 'normal'
1004 );
1005 }
1006 DG_Admin::$hook = 'post.php';
1007 add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueueScriptsAndStyles'));
1008 }
1009
1010 /**
1011 * Render a Meta Box.
1012 */
1013 public static function renderMetaBox($post) {
1014 global $dg_options;
1015 wp_nonce_field( DG_OPTION_NAME.'_meta_box', DG_OPTION_NAME.'_meta_box_nonce' );
1016 $ID = $post->ID;
1017 $icon = isset($dg_options['thumber']['thumbs'][$ID]['thumb_url']) ? $dg_options['thumber']['thumbs'][$ID]['thumb_url'] : DG_Thumber::getDefaultThumbnail($ID);
1018
1019 echo '<table id="ThumbsTable" class="wp-list-table widefat fixed media" cellpadding="0" cellspacing="0">'.
1020 '<tbody><tr data-entry="'.$ID.'"><td class="column-icon media-icon"><img src="' .
1021 $icon.'" />'.'</td><td class="column-thumbupload">' .
1022 '<span class="manual-download">' .
1023 '<span class="dashicons dashicons-upload"></span>' .
1024 '<span class="html5dndmarker">Drop file here<span> or </span></span>' .
1025 '<span class="buttons-area">' .
1026 '<input id="upload-button'.$ID.'" type="file" />' .
1027 '<input id="trigger-button'.$ID.'" type="button" value="Select File" class="button" />' .
1028 '</span>' .
1029 '</span>' .
1030 '</td></tr></tbody></table>'.
1031 (empty($dg_options['thumber']['thumbs'][$ID]) ? '<span class="dashicons dashicons-info"></span><span class="">Please note this attachment hasn&#39;t been used in any Document Gallery instance and so there is no autogenerated thumbnail, in the meantime default one is used instead.</span>' : '').PHP_EOL;
1032 }
1033
1034 /**
1035 * Save a Meta Box.
1036 */
1037 public static function saveMetaBox($post_id) {
1038 // Check if our nonce is set.
1039 // Verify that the nonce is valid.
1040 // If this is an autosave, our form has not been submitted, so we don't want to do anything.
1041 if ( !isset($_POST[DG_OPTION_NAME.'_meta_box_nonce']) || !wp_verify_nonce($_POST[DG_OPTION_NAME.'_meta_box_nonce'], DG_OPTION_NAME.'_meta_box') || (defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE) ) {
1042 return;
1043 }
1044
1045 global $dg_options;
1046 $responseArr = array('result' => false);
1047 if (isset($_POST[DG_OPTION_NAME]['entry'])) {
1048 $ID = intval($_POST[DG_OPTION_NAME]['entry']);
1049 } else {
1050 $ID = -1;
1051 }
1052 if ( isset($_POST[DG_OPTION_NAME]['upload']) && isset($_FILES['file']) && isset($dg_options['thumber']['thumbs'][$ID]) ) {
1053 $old_path = $dg_options['thumber']['thumbs'][$ID]['thumb_path'];
1054 $uploaded_filename = self::validateUploadedFile();
1055 if ($uploaded_filename && DG_Thumber::setThumbnail($ID, $uploaded_filename)) {
1056 if ($dg_options['thumber']['thumbs'][$ID]['thumb_path'] !== $old_path) {
1057 @unlink($old_path);
1058 }
1059 $responseArr['result'] = true;
1060 $responseArr['url'] = $dg_options['thumber']['thumbs'][$ID]['thumb_url'];
1061 }
1062 }
1063 if (isset($_POST[DG_OPTION_NAME]['ajax'])) {
1064 echo DG_Util::jsonEncode($responseArr);
1065 wp_die();
1066 }
1067 }
1068
1069 /**
1070 * Render the Logging table.
1071 */
1072 public static function renderLoggingSection() {
1073 $log_list = DG_Logger::readLog();
1074 if ($log_list) {
1075 $levels = array_map(array(__CLASS__, 'getLogLabelSpan'), array_keys(DG_LogLevel::getLogLevels()));
1076
1077 $thead = '<tr>'.
1078 '<th scope="col" class="manage-column column-date"><span>'.__('Date', 'document-gallery').'</span></th>'.
1079 '<th scope="col" class="manage-column column-level"><span>'.__('Level', 'document-gallery').'</span></th>'.
1080 '<th scope="col" class="manage-column column-message"><span>'.__('Message', 'document-gallery').'</span></th>'.
1081 '</tr>';
1082
1083 ?>
1084 <div class="log-list-wrapper">
1085 <div>
1086 <div class="tablenav top">
1087 <div class="alignleft bulkactions">
1088 <button class="action expandAll">
1089 <?php echo __('Expand All', 'document-gallery'); ?>
1090 </button>
1091 <button class="action collapseAll">
1092 <?php echo __('Collapse All', 'document-gallery'); ?>
1093 </button>
1094 </div>
1095 <div class="levelSelector">
1096 <input type="checkbox" id="allLevels" name="lswitch" value="all" checked />
1097 <label for="allLevels" class="allLevels">ALL</label>
1098 <?php
1099 foreach (array_keys(DG_LogLevel::getLogLevels()) as $k) { ?>
1100 <?php
1101 $lower = strtolower($k);
1102 $upper = strtoupper($k);
1103 ?>
1104 <input type="checkbox" id="<?php echo $lower; ?>Level" name="lswitch" value="<?php echo $lower; ?>" checked />
1105 <label for="<?php echo $lower; ?>Level" class="<?php echo $lower; ?>Level"><?php echo $upper; ?></label>
1106 <?php }
1107 ?>
1108 </div>
1109 </div>
1110 <table id="LogTable" class="wp-list-table widefat fixed media" cellpadding="0" cellspacing="0">
1111 <thead>
1112 <?php echo $thead; ?>
1113 </thead>
1114 <tfoot>
1115 <?php echo $thead; ?>
1116 </tfoot>
1117 <tbody><?php
1118 $i = 0;
1119 foreach ($log_list as $v) {
1120 $date = DocumentGallery::localDateTimeFromTimestamp($v[0]);
1121
1122 // convert attachment names to links
1123 $v[2] = preg_replace('/[ ^](attachment #)(\d+)[., ]/i', ' <a href="' . home_url() . '/?attachment_id=\2" target="_blank">\1<strong>\2</strong></a> ', $v[2]);
1124
1125 // bold the place where log entry was submitted
1126 $v[2] = preg_replace('/^(\(\w+::\w+\)) /', '<strong>\1</strong> ', $v[2]);
1127
1128 // italicize any function references within log entry
1129 $v[2] = preg_replace('/(\(?\w+::\w+\)?)/m', '<i>\1</i>', $v[2]);
1130
1131 echo '<tr><td class="date column-date" data-sort-value="'.$v[0].'"><span class="logLabel date">'.$date.'</span></td>' .
1132 '<td class="column-level">'.$levels[$v[1]].'</td>' .
1133 '<td class="column-entry">'.(empty($v[3]) ? '<pre>'.$v[2].'</pre>' : '<div class="expander" title="Click to Expand"><pre>'.$v[2].'</pre><div><span class="dashicons dashicons-arrow-down-alt2"></span></div></div><div class="spoiler-body"><pre>'.$v[3].'</pre></div>').'</td>' .
1134 '</tr>'.PHP_EOL;
1135 } ?>
1136 </tbody>
1137 </table>
1138 <div class="tablenav bottom">
1139 <div class="alignright bulkactions">
1140 <button class="button action clearLog" name = '<?php echo DG_OPTION_NAME; ?>[clearLog]' value = 'true'>
1141 <?php echo __('Clear Log', 'document-gallery'); ?>
1142 </button>
1143 </div>
1144 </div>
1145 </div>
1146 </div>
1147 <?php } else {
1148 echo '<div class="noLog">'.__('There are no log entries at this time.', 'document-gallery').'<br />'.__('For Your information:', 'document-gallery').' <strong><i>'.__('Logging', 'document-gallery').'</i></strong> '.(DG_Logger::logEnabled()?'<span class="loggingON">'.__('is turned ON', 'document-gallery').'!</span>':'<span class="loggingOFF">'.__('is turned OFF', 'document-gallery').'!</span>').'</div>';
1149 }
1150 }
1151
1152 /**
1153 * Takes label name and returns SPAN tag.
1154 * @param string $e label name.
1155 * @return string SPAN tag
1156 */
1157 private static function getLogLabelSpan($e) {
1158 return '<span class="logLabel ' . strtolower($e) . '">' . strtoupper($e) . '</span>';
1159 }
1160
1161 /**
1162 * Render a checkbox field.
1163 * @param array $args
1164 */
1165 public static function renderCheckboxField($args) {
1166 $args['disabled'] = isset($args['disabled']) ? $args['disabled'] : false;
1167 printf('<label><input type="checkbox" value="1" name="%1$s[%2$s]" id="%3$s" %4$s %5$s/> %6$s</label>',
1168 $args['option_name'],
1169 $args['name'],
1170 $args['label_for'],
1171 checked($args['value'], 1, false),
1172 disabled($args['disabled'], true, false),
1173 $args['description']);
1174 }
1175
1176 /**
1177 * Render a text field.
1178 * @param array $args
1179 */
1180 public static function renderTextField($args) {
1181 printf('<input type="%1$s" value="%2$s" name="%3$s[%4$s]" id="%5$s" /> %6$s',
1182 isset($args['type']) ? $args['type'] : 'text',
1183 $args['value'],
1184 $args['option_name'],
1185 $args['name'],
1186 $args['label_for'],
1187 $args['description']);
1188 }
1189
1190 /**
1191 * Accepts a two-dimensional array where each inner array consists of valid arguments for renderTextField.
1192 * @param array $args
1193 */
1194 public static function renderMultiTextField($args) {
1195 foreach ($args as $arg) {
1196 self::renderTextField($arg);
1197 }
1198 }
1199
1200 /**
1201 * Render a select field.
1202 * @param array $args
1203 */
1204 public static function renderSelectField($args) {
1205 printf('<select name="%1$s[%2$s]" id="%3$s">',
1206 $args['option_name'],
1207 $args['name'],
1208 $args['label_for']);
1209
1210 foreach ($args['options'] as $val) {
1211 printf('<option value="%1$s" %2$s>%3$s</option>',
1212 $val,
1213 selected($val, $args['value'], false),
1214 $val,
1215 $args['description']);
1216 }
1217
1218 print '</select> ' . $args['description'];
1219 }
1220
1221 /**
1222 * Wraps the PHP exit language construct.
1223 */
1224 public static function _exit() {
1225 exit;
1226 }
1227
1228 /**
1229 * Blocks instantiation. All functions are static.
1230 */
1231 private function __construct() {
1232
1233 }
1234 }