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

document-gallery.php in Document Gallery 2.2.2, at document-gallery.php

362 lines 11.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined('WPINC') OR exit;
3
4 /*
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.1
9 Author: Dan Rossiter
10 Author URI: http://danrossiter.org/
11 License: GPLv2
12 Text Domain: document-gallery
13 */
14
15 define('DG_VERSION', '2.2.1');
16
17 // define helper paths & URLs
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/');
23
24 // init DG options for use throughout plugin
25 global $dg_options;
26 define('DG_OPTION_NAME', 'document_gallery');
27 $dg_options = get_option(DG_OPTION_NAME, null);
28
29 // logging functionality
30 include_once DG_PATH . 'inc/class-logger.php';
31
32 // handle activation, updates, and uninstallation
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'));
37 DG_Setup::maybeUpdate();
38
39 // validate options if desired
40 if ($dg_options['validation']) {
41 add_action('init', array('DocumentGallery', 'addValidation'));
42 }
43
44 // I18n
45 add_action('plugins_loaded', array('DocumentGallery', 'loadTextDomain'));
46
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 }
72 }
73
74 // adds 'dg' shortcode
75 add_shortcode('dg', array('DocumentGallery', 'doShortcode'));
76
77 /**
78 * DocumentGallery wraps basic functionality to setup the plugin.
79 *
80 * @author drossiter
81 */
82 class DocumentGallery {
83
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';
88
89 /*==========================================================================
90 * THE SHORTCODE
91 *=========================================================================*/
92
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';
102
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');
106
107 return $gallery;
108 }
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 }
116
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 }
126
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 }
137
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 }
360 }
361
362 ?>