PluginProbe
Document Gallery / 2.2.6
Document Gallery v2.2.6
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 +221 -57 2.0.32.2.6 View file →
@@ -4,9 +4,9 @@
4 4 /*
5 5 Plugin Name: Document Gallery
6 6 Plugin URI: http://wordpress.org/extend/plugins/document-gallery/
7 7 Description: Display non-images (and images) in gallery format on a page or post with the [dg] shortcode.
8 - Version: 2.0.3
8 + Version: 2.2.6
9 9 Author: Dan Rossiter
10 10 Author URI: http://danrossiter.org/
11 11 License: GPLv2
12 12 Text Domain: document-gallery
@@ -11,18 +11,16 @@
11 11 License: GPLv2
12 12 Text Domain: document-gallery
13 13 */
14 14
15 +define('DG_VERSION', '2.2.6');
16 +
15 17 // define helper paths & URLs
16 -define('DG_VERSION', '2.0.3');
18 +define('DG_BASENAME', plugin_basename(__FILE__));
17 19 define('DG_URL', plugin_dir_url(__FILE__));
18 20 define('DG_PATH', plugin_dir_path(__FILE__));
19 -if(!defined('WP_INCLUDE_DIR')) {
20 - define('WP_INCLUDE_DIR', preg_replace('/wp-content$/', 'wp-includes', WP_CONTENT_DIR));
21 -}
22 -if(!defined('WP_ADMIN_DIR')) {
23 - define('WP_ADMIN_DIR', preg_replace('/wp-content$/', 'wp-admin', WP_CONTENT_DIR));
24 -}
21 +define('DG_WPINC_PATH', ABSPATH . WPINC . '/');
22 +define('DG_WPADMIN_PATH', ABSPATH . 'wp-admin/');
25 23
26 24 // init DG options for use throughout plugin
27 25 global $dg_options;
28 26 define('DG_OPTION_NAME', 'document_gallery');
@@ -27,13 +25,23 @@
27 25 global $dg_options;
28 26 define('DG_OPTION_NAME', 'document_gallery');
29 27 $dg_options = get_option(DG_OPTION_NAME, null);
30 28
31 -// handle activation and uninstallation
29 +// logging functionality
30 +include_once DG_PATH . 'inc/class-logger.php';
31 +
32 +// handle activation, updates, and uninstallation
32 33 include_once DG_PATH . 'inc/class-setup.php';
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'));
33 37 DG_Setup::maybeUpdate();
34 -register_uninstall_hook(__FILE__, array('DG_Setup', 'uninstall'));
35 38
39 +// validate options if desired
40 +if ($dg_options['validation']) {
41 + add_action('init', array('DocumentGallery', 'addValidation'));
42 +}
43 +
36 44 // I18n
37 45 add_action('plugins_loaded', array('DocumentGallery', 'loadTextDomain'));
38 46
39 47 // cleanup cached data when thumbed attachment deleted
@@ -44,17 +52,14 @@
44 52 // admin house keeping
45 53 include_once DG_PATH . 'admin/class-admin.php';
46 54
47 55 // add settings link
48 - add_filter('plugin_action_links_' . plugin_basename(__FILE__),
49 - array('DG_Admin', 'addSettingsLink'));
50 -
56 + add_filter('plugin_action_links_' . DG_BASENAME, array('DG_Admin', 'addSettingsLink'));
57 +
51 58 // build options page
52 59 add_action('admin_menu', array('DG_Admin', 'addAdminPage'));
53 - if (!empty($GLOBALS['pagenow'])
54 - && ('options-general.php' === $GLOBALS['pagenow'] // output
55 - || 'options.php' === $GLOBALS['pagenow'])) { // validation
56 - add_action('admin_init', array('DG_Admin', 'registerSettings'));
60 + if (DG_Admin::doRegisterSettings()) {
61 + add_action('admin_init', array('DG_Admin', 'registerSettings'));
57 62 }
58 63 } else {
59 64 // styling for gallery
60 65 if (empty($dg_options['css']['text'])) {
@@ -79,9 +84,9 @@
79 84 /**
80 85 * @var str Name of the query var used to check whether we should print custom CSS.
81 86 */
82 87 private static $query_var = 'document-gallery-css';
83 -
88 +
84 89 /*==========================================================================
85 90 * THE SHORTCODE
86 91 *=========================================================================*/
87 92
@@ -88,18 +93,18 @@
88 93 /**
89 94 * Takes values passed from attributes and returns sutable HTML to represent
90 95 * all valid attachments requested.
91 96 *
92 - * @param array $atts Arguments from the user.
93 - * @return string HTML for the Document Gallery.
97 + * @param multitype:string $atts Arguments from the user.
98 + * @return string HTML for the Document Gallery.
94 99 */
95 100 public static function doShortcode($atts) {
96 101 include_once 'inc/class-gallery.php';
97 -
102 +
98 103 $start = microtime(true);
99 104 $gallery = (string)new DG_Gallery($atts);
100 - DocumentGallery::writeLog('Generation Time: ' . (microtime(true) - $start) . ' s');
101 -
105 + DG_Logger::writeLog(DG_LogLevel::Detail, 'Generation Time: ' . sprintf('%.2f', (microtime(true) - $start)) . ' s');
106 +
102 107 return $gallery;
103 108 }
104 109
105 110 /**
@@ -105,12 +110,11 @@
105 110 /**
106 111 * Enqueue standard DG CSS.
107 112 */
108 113 public static function enqueueGalleryStyle() {
109 - wp_register_style('document-gallery', DG_URL . 'assets/css/style.css', null, DG_VERSION);
110 - wp_enqueue_style('document-gallery');
114 + wp_enqueue_style('document-gallery', DG_URL . 'assets/css/style.css', null, DG_VERSION);
111 115 }
112 -
116 +
113 117 /**
114 118 * Enqueue user's custom DG CSS.
115 119 */
116 120 public static function enqueueCustomStyle() {
@@ -118,20 +122,20 @@
118 122 wp_register_style('document-gallery', add_query_arg(self::$query_var, 1, home_url('/')),
119 123 null, DG_VERSION . ':' . $dg_options['css']['version']);
120 124 wp_enqueue_style('document-gallery');
121 125 }
122 -
126 +
123 127 /**
124 128 * Add query custom CSS query string.
125 129 * Taken from here: http://ottopress.com/2010/dont-include-wp-load-please/
126 - * @param array $vars
127 - * @return array
130 + * @param multitype:string $vars Variables to be added.
131 + * @return multitype:string All variables to be included in query string.
128 132 */
129 133 public static function addCustomStyleQueryVar($vars) {
130 134 $vars[] = self::$query_var;
131 135 return $vars;
132 136 }
133 -
137 +
134 138 /**
135 139 * Constructs user's custom CSS dynamically, then instructs
136 140 * browser to cache for a year. Cache is busted by versioning
137 141 * CSS any time the user makes a change.
@@ -139,54 +143,214 @@
139 143 public static function buildCustomCss() {
140 144 if (1 == intval(get_query_var(self::$query_var))) {
141 145 global $dg_options;
142 146
143 - header('Content-type: text/css; charset=UTF-8');
147 + header('Content-type: text/css');
144 148 header('Cache-Control: no-transform,public,maxage=' . 31536000);
145 149 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
146 150 header('Last-Modified: ' . $dg_options['css']['last-modified']);
147 151 header('ETag: ' . $dg_options['css']['etag']);
148 -
149 - // standard CSS
150 - echo file_get_contents(DG_PATH . 'assets/css/style.css') . PHP_EOL;
151 -
152 - // custom CSS
153 - echo str_replace('>', '>', esc_html($dg_options['css']['text']));
152 +
153 + echo $dg_options['css']['minified'];
154 154 exit;
155 155 }
156 156 }
157 157
158 158 /*==========================================================================
159 - * Logging
159 + * I18n
160 160 *=========================================================================*/
161 161
162 162 /**
163 - * Appends error log with $entry if WordPress is in debug mode.
164 - *
165 - * @param str $entry
163 + * Loads language files into WP core.
166 164 */
167 - public static function writeLog($entry) {
168 - if (defined('WP_DEBUG') && WP_DEBUG) {
169 - $err = 'DG: ' . print_r($entry, true) . PHP_EOL;
170 - if (defined('ERRORLOGFILE')) {
171 - error_log($err, 3, ERRORLOGFILE);
172 - } else {
173 - error_log($err);
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 + }
174 257 }
175 258 }
259 +
260 + return $valid;
176 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('>', '>', 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;
177 310
178 - /*==========================================================================
179 - * I18n
180 - *=========================================================================*/
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;
181 349
182 - public static function loadTextDomain() {
183 - load_plugin_textdomain('document-gallery', false, dirname(plugin_basename(__FILE__ )) . '/languages/');
350 + $css = preg_replace("%$re1%", '$1', $css);
351 + return preg_replace("%$re2%", '$1$2$3$4$5$6$7', $css);
184 352 }
185 -
186 - /*==========================================================================
187 - * HELPER FUNCTIONS
188 - *=========================================================================*/
189 353
190 354 /**
191 355 * Blocks instantiation. All functions are static.
192 356 */