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