PluginProbe
Document Gallery / 2.2.4
Document Gallery v2.2.4
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 | document-gallery.php +328 -122 trunk2.2.4 View file →
@@ -1,156 +1,362 @@
1 1 <?php
2 -defined( 'WPINC' ) OR exit;
2 +defined('WPINC') OR exit;
3 3
4 -/**
5 - * Plugin Name: Document Gallery
6 - * Plugin URI: https://wordpress.org/plugins/document-gallery/
7 - * Description: Display non-images (and images) in gallery format on a page or post.
8 - * Version: 5.1.1
9 - * Requires at least: 6.1
10 - * Requires PHP: 5.6
11 - * Author: Dan Rossiter
12 - * Author URI: https://www.linkedin.com/in/danrossiter/
13 - * License: GPLv3
14 - * License URI: https://www.gnu.org/licenses/gpl-3.0.html
15 - * Text Domain: document-gallery
16 - *
17 - * @package create-block
4 +/*
5 + Plugin Name: Document Gallery
6 + Plugin URI: http://wordpress.org/extend/plugins/document-gallery/
7 + Description: Display non-images (and images) in gallery format on a page or post with the [dg] shortcode.
8 + Version: 2.2.4
9 + Author: Dan Rossiter
10 + Author URI: http://danrossiter.org/
11 + License: GPLv2
12 + Text Domain: document-gallery
18 13 */
19 14
20 -define( 'DG_VERSION', '5.1.1' );
15 +define('DG_VERSION', '2.2.4');
21 16
22 -if ( version_compare( PHP_VERSION, '5.6', '<' ) ) {
23 - add_action( 'admin_notices', 'dg_php_lt_five_six' );
24 - function dg_php_lt_five_six() { ?>
25 - <div class="error"><p>
26 - <?php printf( __( 'Document Gallery requires PHP &ge; 5.6. Your server is running version %s.', 'document-gallery' ), PHP_VERSION ); ?>
27 - </p></div>
28 - <?php }
29 -
30 - return;
31 -}
32 -
33 17 // define helper paths & URLs
34 -define( 'DG_BASENAME', plugin_basename( __FILE__ ) );
35 -define( 'DG_URL', plugin_dir_url( __FILE__ ) . 'src/' );
36 -define( 'DG_PATH', plugin_dir_path( __FILE__ ) . 'src/' );
37 -define( 'DG_WPINC_PATH', ABSPATH . WPINC . '/' );
38 -define( 'DG_WPADMIN_PATH', ABSPATH . 'wp-admin/' );
18 +define('DG_BASENAME', plugin_basename(__FILE__));
19 +define('DG_URL', plugin_dir_url(__FILE__));
20 +define('DG_PATH', plugin_dir_path(__FILE__));
21 +define('DG_WPINC_PATH', ABSPATH . WPINC . '/');
22 +define('DG_WPADMIN_PATH', ABSPATH . 'wp-admin/');
39 23
40 24 // init DG options for use throughout plugin
41 25 global $dg_options;
42 -define( 'DG_OPTION_NAME', 'document_gallery' );
43 -$dg_options = get_option( DG_OPTION_NAME, null );
26 +define('DG_OPTION_NAME', 'document_gallery');
27 +$dg_options = get_option(DG_OPTION_NAME, null);
44 28
45 -// core functionality
46 -include_once DG_PATH . 'inc/class-document-gallery.php';
47 -include_once DG_PATH . 'inc/class-thumb.php';
48 -include_once DG_PATH . 'inc/class-util.php';
49 -
50 29 // logging functionality
51 30 include_once DG_PATH . 'inc/class-logger.php';
52 -add_action( DG_Logger::PurgeLogsAction, array( 'DG_Logger', 'purgeExpiredEntries' ) );
53 31
54 32 // handle activation, updates, and uninstallation
55 33 include_once DG_PATH . 'inc/class-setup.php';
56 -register_activation_hook( __FILE__, array( 'DG_Setup', 'activate' ) );
57 -add_action( 'wpmu_new_blog', array( 'DG_Setup', 'activateNewBlog' ) );
58 -register_uninstall_hook( __FILE__, array( 'DG_Setup', 'uninstall' ) );
34 +register_activation_hook(__FILE__, array('DG_Setup', 'activate'));
35 +add_action('wpmu_new_blog', array('DG_Setup','activateNewBlog'));
36 +register_uninstall_hook(__FILE__, array('DG_Setup', 'uninstall'));
59 37 DG_Setup::maybeUpdate();
60 38
61 -// ensure we don't allow invalid option structure
62 -add_action( 'init', array( 'DocumentGallery', 'addValidation' ) );
39 +// validate options if desired
40 +if ($dg_options['validation']) {
41 + add_action('init', array('DocumentGallery', 'addValidation'));
42 +}
63 43
64 44 // I18n
65 -add_action( 'plugins_loaded', array( 'DocumentGallery', 'loadTextDomain' ) );
45 +add_action('plugins_loaded', array('DocumentGallery', 'loadTextDomain'));
66 46
67 -if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
68 - add_action( ( is_admin() ? 'admin' : 'wp' ) . '_footer', 'dg_debug_data' );
69 - function dg_debug_data() {
70 - echo '<!-- ' . PHP_EOL;
71 - echo 'Document Gallery Count: ' . ( class_exists( 'DG_Gallery' ) ? count( DG_Gallery::getGalleries() ) : 0 ) . PHP_EOL;
72 - echo ' -->' . PHP_EOL;
73 - }
47 +// cleanup cached data when thumbed attachment deleted
48 +include_once DG_PATH . 'inc/class-thumber.php';
49 +add_action('delete_attachment', array('DG_Thumber', 'deleteThumbMeta'));
50 +
51 +if (is_admin()) {
52 + // admin house keeping
53 + include_once DG_PATH . 'admin/class-admin.php';
54 +
55 + // add settings link
56 + add_filter('plugin_action_links_' . DG_BASENAME, array('DG_Admin', 'addSettingsLink'));
57 +
58 + // build options page
59 + add_action('admin_menu', array('DG_Admin', 'addAdminPage'));
60 + if (DG_Admin::doRegisterSettings()) {
61 + add_action('admin_init', array('DG_Admin', 'registerSettings'));
62 + }
63 +} else {
64 + // styling for gallery
65 + if (empty($dg_options['css']['text'])) {
66 + add_action('wp_enqueue_scripts', array('DocumentGallery', 'enqueueGalleryStyle'));
67 + } else {
68 + add_action('template_redirect', array('DocumentGallery', 'buildCustomCss'));
69 + add_action('wp_enqueue_scripts', array('DocumentGallery', 'enqueueCustomStyle'));
70 + add_filter('query_vars', array('DocumentGallery', 'addCustomStyleQueryVar'));
71 + }
74 72 }
75 73
76 -// cleanup cached data when thumbed attachment deleted
77 -include_once DG_PATH . 'inc/class-thumber.php';
78 -add_action( 'delete_attachment', array( 'DG_Thumb', 'cleanupAttachmentMeta' ) );
74 +// adds 'dg' shortcode
75 +add_shortcode('dg', array('DocumentGallery', 'doShortcode'));
79 76
80 -if ( is_admin() ) {
81 - // admin house keeping
82 - include_once DG_PATH . 'admin/class-admin.php';
77 +/**
78 + * DocumentGallery wraps basic functionality to setup the plugin.
79 + *
80 + * @author drossiter
81 + */
82 +class DocumentGallery {
83 83
84 - // AJAX handling
85 - include_once DG_PATH . 'admin/class-ajax-handler.php';
84 + /**
85 + * @var str Name of the query var used to check whether we should print custom CSS.
86 + */
87 + private static $query_var = 'document-gallery-css';
86 88
87 - // add links to plugin index
88 - add_filter( 'plugin_action_links_' . DG_BASENAME, array( 'DG_Admin', 'addSettingsLink' ) );
89 - add_filter( 'plugin_row_meta', array( 'DG_Admin', 'addDonateLink' ), 10, 2 );
89 + /*==========================================================================
90 + * THE SHORTCODE
91 + *=========================================================================*/
90 92
91 - // build options page
92 - add_action( 'admin_menu', array( 'DG_Admin', 'addAdminPage' ) );
93 + /**
94 + * Takes values passed from attributes and returns sutable HTML to represent
95 + * all valid attachments requested.
96 + *
97 + * @param multitype:string $atts Arguments from the user.
98 + * @return string HTML for the Document Gallery.
99 + */
100 + public static function doShortcode($atts) {
101 + include_once 'inc/class-gallery.php';
93 102
94 - // add meta box for managing thumbnail generation to attachment Edit Media page
95 - add_action( 'add_meta_boxes', array( 'DG_Admin', 'addMetaBox' ) );
96 - add_action( 'wp_ajax_dg_upload_thumb', array( 'DG_Admin', 'saveMetaBox' ) );
103 + $start = microtime(true);
104 + $gallery = (string)new DG_Gallery($atts);
105 + DG_Logger::writeLog(DG_LogLevel::Detail, 'Generation Time: ' . sprintf('%.2f', (microtime(true) - $start)) . ' s');
97 106
98 - if ( DG_Admin::doRegisterSettings() ) {
99 - add_action( 'admin_init', array( 'DG_Admin', 'registerSettings' ) );
100 - }
101 -} else {
102 - // styling for gallery
103 - if ( apply_filters( 'dg_use_default_gallery_style', true ) ) {
104 - add_action( 'wp_enqueue_scripts', array( 'DocumentGallery', 'enqueueGalleryStyle' ) );
105 - }
106 - add_action( 'wp_print_scripts', array( 'DocumentGallery', 'printCustomStyle' ) );
107 + return $gallery;
108 + }
107 109
108 - add_action( 'wp_enqueue_scripts', array( 'DocumentGallery', 'enqueueGalleryScript' ) );
109 -}
110 + /**
111 + * Enqueue standard DG CSS.
112 + */
113 + public static function enqueueGalleryStyle() {
114 + wp_enqueue_style('document-gallery', DG_URL . 'assets/css/style.css', null, DG_VERSION);
115 + }
110 116
111 -/**
112 - * Registers the block using the metadata loaded from the `block.json` file.
113 - * Behind the scenes, it registers also all assets so they can be enqueued
114 - * through the block editor in the corresponding context.
115 - *
116 - * @see https://developer.wordpress.org/reference/functions/register_block_type/
117 - */
118 -function document_gallery_block_init() {
119 - register_block_type(
120 - __DIR__ . '/build/block',
121 - array( 'render_callback' => 'document_gallery_block_render_callback' )
122 - );
123 -}
124 -add_action( 'init', 'document_gallery_block_init' );
117 + /**
118 + * Enqueue user's custom DG CSS.
119 + */
120 + public static function enqueueCustomStyle() {
121 + global $dg_options;
122 + wp_register_style('document-gallery', add_query_arg(self::$query_var, 1, home_url('/')),
123 + null, DG_VERSION . ':' . $dg_options['css']['version']);
124 + wp_enqueue_style('document-gallery');
125 + }
125 126
126 -/**
127 - * Pass default options to block editor script.
128 - */
129 -function document_gallery_block_localize() {
130 - global $dg_options;
131 -
132 - // Script handle is auto-generated: {namespace}-{block-name}-editor-script
133 - wp_localize_script(
134 - 'document-gallery-document-gallery-block-editor-script',
135 - 'dgBlockConfig',
136 - array( 'dgDefaults' => $dg_options['gallery'] )
137 - );
138 -}
139 -add_action( 'enqueue_block_editor_assets', 'document_gallery_block_localize' );
127 + /**
128 + * Add query custom CSS query string.
129 + * Taken from here: http://ottopress.com/2010/dont-include-wp-load-please/
130 + * @param multitype:string $vars Variables to be added.
131 + * @return multitype:string All variables to be included in query string.
132 + */
133 + public static function addCustomStyleQueryVar($vars) {
134 + $vars[] = self::$query_var;
135 + return $vars;
136 + }
140 137
141 -/**
142 - * This function is called when the block is being rendered on the front end of the site
143 - *
144 - * @param array $attributes The array of attributes for this block.
145 - * @param string $content Rendered block output. ie. <InnerBlocks.Content />.
146 - * @param WP_Block $block_instance The instance of the WP_Block class that represents the block being rendered.
147 - */
148 -function document_gallery_block_render_callback( $attributes, $content, $block_instance ) {
149 - return DocumentGallery::doShortcode( $attributes );
138 + /**
139 + * Constructs user's custom CSS dynamically, then instructs
140 + * browser to cache for a year. Cache is busted by versioning
141 + * CSS any time the user makes a change.
142 + */
143 + public static function buildCustomCss() {
144 + if (1 == intval(get_query_var(self::$query_var))) {
145 + global $dg_options;
146 +
147 + header('Content-type: text/css');
148 + header('Cache-Control: no-transform,public,maxage=' . 31536000);
149 + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
150 + header('Last-Modified: ' . $dg_options['css']['last-modified']);
151 + header('ETag: ' . $dg_options['css']['etag']);
152 +
153 + echo $dg_options['css']['minified'];
154 + exit;
155 + }
156 + }
157 +
158 + /*==========================================================================
159 + * I18n
160 + *=========================================================================*/
161 +
162 + /**
163 + * Loads language files into WP core.
164 + */
165 + public static function loadTextDomain() {
166 + load_plugin_textdomain('document-gallery', false, dirname(DG_BASENAME) . '/languages/');
167 + }
168 +
169 + /*==========================================================================
170 + * HELPER FUNCTIONS
171 + *=========================================================================*/
172 +
173 + /**
174 + * @param int $blog ID of the blog to be retrieved in multisite env.
175 + * @return multitype:unknown Options for the blog.
176 + */
177 + public static function getOptions($blog = null) {
178 + global $dg_options;
179 + return is_null($blog)
180 + ? $dg_options
181 + : get_blog_option($blog, DG_OPTION_NAME, null);
182 + }
183 +
184 + /**
185 + * @param multitype:unknown $options
186 + * @param int $blog ID of the blog to be set in multisite env.
187 + */
188 + public static function setOptions($options, $blog = null) {
189 + if (is_null($blog)) {
190 + global $dg_options;
191 + update_option(DG_OPTION_NAME, $options);
192 + $dg_options = $options;
193 + } else {
194 + update_blog_option($blog, DG_OPTION_NAME, $options);
195 + }
196 + }
197 +
198 + /**
199 + * @param int $blog ID of the blog to be deleted in multisite env.
200 + */
201 + public static function deleteOptions($blog = null) {
202 + if (is_null($blog)) {
203 + delete_option(DG_OPTION_NAME);
204 + } else {
205 + delete_blog_option($blog, DG_OPTION_NAME);
206 + }
207 + }
208 +
209 + /**
210 + * Adds hook to validate DG options every time save is attempted.
211 + */
212 + public static function addValidation() {
213 + add_filter('pre_update_option_' . DG_OPTION_NAME, array('DocumentGallery', 'validateOptionsStructure'), 10, 2);
214 + }
215 +
216 + /**
217 + * Checks whether the given options match the option schema.
218 + * @param multivar $new The new options to be validated.
219 + * @param multivar $old The old options.
220 + * @return array The options to be saved.
221 + */
222 + public static function validateOptionsStructure($new, $old) {
223 + if (self::isValidOptionsStructure($new)) {
224 + $ret = $new;
225 + } else {
226 + $ret = $old;
227 + DG_Logger::writeLog(DG_LogLevel::Error, 'Attempted to save invalid options.' . PHP_EOL . print_r($new, true), true, true);
228 + }
229 +
230 + return $ret;
231 + }
232 +
233 + /**
234 + * @param multivar|unknown $o The options structure to validate.
235 + * @param multivar $schema The schema to validate against (note that only keys matter -- non-array values are ignored).
236 + * @return bool Whether the given options structure matches the schema.
237 + */
238 + private static function isValidOptionsStructure($o, $schema = null) {
239 + if (is_null($schema)) {
240 + include_once DG_PATH . 'inc/class-setup.php';
241 + $schema = DG_Setup::getDefaultOptions(true);
242 + }
243 +
244 + // simple checks first
245 + $valid = is_array($o) && (count($schema) === count($o));
246 +
247 + if ($valid) {
248 + foreach ($schema as $sk => $sv) {
249 + $valid = array_key_exists($sk, $o);
250 + if (is_array($sv) && !empty($sv)) {
251 + $valid = $valid && self::isValidOptionsStructure($o[$sk], $sv);
252 + }
253 +
254 + if (!$valid) {
255 + break;
256 + }
257 + }
258 + }
259 +
260 + return $valid;
261 + }
262 +
263 + /**
264 + * Function takes a GMT timestamp and returns a date/time string in the
265 + * current timezone and WP format.
266 + * @param int $timestamp The GMT timestamp to translate.
267 + * @return string The local time in the WP date/time format.
268 + */
269 + public static function localDateTimeFromTimestamp($timestamp) {
270 + static $gmt_offet = null;
271 + static $wp_format = null;
272 + if (is_null($gmt_offet)) {
273 + $gmt_offet = get_option('gmt_offset');
274 + $wp_format = get_option('date_format').' '.get_option('time_format');
275 + }
276 +
277 + return date($wp_format, $timestamp + $gmt_offet * 3600);
278 + }
279 +
280 + /**
281 + * Compiles any custom CSS plus the default CSS together,
282 + * minifying in the process.
283 + * @param string $custom The custom CSS to compile.
284 + * @return string Compiled CSS, including both standard and any custom.
285 + */
286 + public static function compileCustomCss($custom) {
287 + $css = file_get_contents(DG_PATH . 'assets/css/style.css');
288 + $css .= str_replace('&gt;', '>', esc_html($custom));
289 +
290 + return $css;
291 + }
292 +
293 + /**
294 + * Removes all comments & space from CSS string.
295 + * Source: http://stackoverflow.com/a/15195752/866618
296 + */
297 + private static function minifyCss($css) {
298 + # remove comments first (simplifies the other regex)
299 + $re1 = <<<EOS
300 +(?sx)
301 + # quotes
302 + (
303 + "(?:[^"\\]++|\\.)*+"
304 + | '(?:[^'\\]++|\\.)*+'
305 + )
306 +|
307 + # comments
308 + /\* (?> .*? \*/ )
309 +EOS;
310 +
311 + $re2 = <<<EOS
312 +(?six)
313 + # quotes
314 + (
315 + "(?:[^"\\]++|\\.)*+"
316 + | '(?:[^'\\]++|\\.)*+'
317 + )
318 +|
319 + # ; before } (and the spaces after it while we're here)
320 + \s*+ ; \s*+ ( } ) \s*+
321 +|
322 + # all spaces around meta chars/operators
323 + \s*+ ( [*$~^|]?+= | [{};,>~+-] | !important\b ) \s*+
324 +|
325 + # spaces right of ( [ :
326 + ( [[(:] ) \s++
327 +|
328 + # spaces left of ) ]
329 + \s++ ( [])] )
330 +|
331 + # spaces left (and right) of :
332 + \s++ ( : ) \s*+
333 + # but not in selectors: not followed by a {
334 + (?!
335 + (?>
336 + [^{}"']++
337 + | "(?:[^"\\]++|\\.)*+"
338 + | '(?:[^'\\]++|\\.)*+'
339 + )*+
340 + {
341 + )
342 +|
343 + # spaces at beginning/end of string
344 + ^ \s++ | \s++ \z
345 +|
346 + # double spaces to single
347 + (\s)\s+
348 +EOS;
349 +
350 + $css = preg_replace("%$re1%", '$1', $css);
351 + return preg_replace("%$re2%", '$1$2$3$4$5$6$7', $css);
352 + }
353 +
354 + /**
355 + * Blocks instantiation. All functions are static.
356 + */
357 + private function __construct() {
358 +
359 + }
150 360 }
151 361
152 -// adds 'dg' shortcode
153 -add_shortcode( 'dg', array( 'DocumentGallery', 'doShortcode' ) );
154 -
155 -// public API for developers
156 -include_once DG_PATH . 'inc/class-api.php';
362 +?>