PluginProbe
Document Gallery / 4.0
Document Gallery v4.0
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 4.0, at admin/class-admin.php

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