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
document-gallery / inc / class-gallery.php

class-gallery.php in Document Gallery 3.5.3, at inc/class-gallery.php

863 lines 25.4 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 DG_Gallery::init();
5
6 /**
7 * Holds data specific to a given document gallery.
8 *
9 * @author drossiter
10 */
11 class DG_Gallery {
12
13 /*==========================================================================
14 * PRIVATE FIELDS
15 *=========================================================================*/
16
17 private $atts, $taxa;
18 private $docs = array();
19 private $errs = array();
20
21 // templates for HTML output
22 private static $no_docs, $comment, $unary_err, $binary_err;
23
24 /*==========================================================================
25 * PUBLIC FUNCTIONS
26 *=========================================================================*/
27
28 /**
29 * @return bool Whether to link to attachment pg.
30 */
31 public function linkToAttachmentPg() {
32 return $this->atts['attachment_pg'];
33 }
34
35 /**
36 * @return bool Whether to open thumb links in new window.
37 */
38 public function openLinkInNewWindow() {
39 return $this->atts['new_window'];
40 }
41
42 /**
43 * @return bool Whether to use "fancy" thumbnails.
44 */
45 public function useFancyThumbs() {
46 return $this->atts['fancy'];
47 }
48
49 /**
50 * @return bool Whether descriptions should be included in output.
51 */
52 public function useDescriptions() {
53 return $this->atts['descriptions'];
54 }
55
56 /*==========================================================================
57 * GET AND SET OPTIONS
58 *=========================================================================*/
59
60 /**
61 * @param int $blog The blog we're retrieving options for (null => current blog).
62 *
63 * @return array Gets gallery branch of DG options array.
64 */
65 public static function getOptions( $blog = null ) {
66 $options = DocumentGallery::getOptions( $blog );
67
68 return $options['gallery'];
69 }
70
71 /**
72 * @param array $options New value for gallery branch of DG options array.
73 * @param int $blog The blog we're retrieving options for (null => current blog).
74 */
75 public static function setOptions( $options, $blog = null ) {
76 $dg_options = DocumentGallery::getOptions( $blog );
77 $dg_options['gallery'] = $options;
78 DocumentGallery::setOptions( $dg_options, $blog );
79 }
80
81 /*==========================================================================
82 * INIT GALLERY
83 *=========================================================================*/
84
85 /**
86 * Initializes static values for this class.
87 */
88 public static function init() {
89 if ( ! isset( self::$comment ) ) {
90 self::$comment =
91 PHP_EOL . '<!-- ' . __( 'Generated using Document Gallery. Get yours here: ', 'document-gallery' ) .
92 'http://wordpress.org/extend/plugins/document-gallery -->' . PHP_EOL;
93 self::$no_docs = '<!-- ' . __( 'No attachments to display. How boring! :(', 'document-gallery' ) . ' -->';
94 self::$unary_err = __( 'The %s value entered, "%s", is not valid.', 'document-gallery' );
95 self::$binary_err = __( 'The %s parameter may only be "%s" or "%s." You entered "%s."', 'document-gallery' );
96 }
97 }
98
99 /**
100 * Builds a gallery object with attributes passed.
101 *
102 * @param array $atts Array of attributes used in shortcode.
103 */
104 public function __construct( $atts ) {
105 include_once DG_PATH . 'inc/class-document.php';
106
107 $post = get_post();
108
109 // empty string is passed when no arguments are given, but constructor expects an array
110 $atts = empty( $atts ) ? array() : $atts;
111
112 if ( ! empty( $atts['ids'] ) ) {
113 // 'ids' is explicitly ordered, unless you specify otherwise.
114 if ( empty( $atts['orderby'] ) ) {
115 $atts['orderby'] = 'post__in';
116 }
117
118 $atts['include'] = $atts['ids'];
119 unset( $atts['ids'] );
120 }
121
122 // allow abbreviated columns attribute
123 if ( ! empty( $atts['cols'] ) ) {
124 $atts['columns'] = $atts['cols'];
125 unset( $atts['cols'] );
126 }
127
128 if ( ! empty( $atts['images'] ) ) {
129 if ( DG_Util::toBool( $atts['images'], false ) ) {
130 $options = self::getOptions();
131 $mimes = trim( isset( $atts['mime_types'] ) ? $atts['mime_types'] : $options['mime_types'] );
132 if ( ! preg_match( '/[,^]image[,$]/', $mimes ) ) {
133 $atts['mime_types'] = empty( $mimes ) ? 'image' : ( $mimes . ',image' );
134 }
135 }
136
137 unset( $atts['images'] );
138 }
139
140 /**
141 * @deprecated localpost will be removed at some point.
142 */
143 if ( ! empty( $atts['localpost'] ) ) {
144 $atts['id'] = - 1;
145 unset( $atts['localpost'] );
146 }
147
148 // merge options w/ default values not stored in options
149 $defaults = array_merge(
150 array( 'id' => $post->ID, 'include' => '', 'exclude' => '' ),
151 self::getOptions() );
152
153 // values used to construct tax query (may be empty)
154 $this->taxa = array_diff_key( $atts, $defaults );
155
156 // all recognized attributes go here
157 $this->atts = shortcode_atts( $defaults, $atts );
158
159 // goes through all values in atts, setting errs as needed
160 $this->atts = self::sanitizeDefaults( $defaults, $this->atts, $this->errs );
161
162 // query DB for all documents requested
163 try {
164 foreach ( $this->getDocuments() as $doc ) {
165 $this->docs[] = new DG_Document( $doc, $this );
166 }
167 } catch ( InvalidArgumentException $e ) {
168 // errors will be printed in __toString()
169 }
170 }
171
172 /**
173 * Cleans up user input, making sure we don't pass crap on to WP core.
174 *
175 * @param array $old_defaults The previous set of defaults.
176 * @param array $defaults The defaults array to sanitize.
177 * @param array &$errs The array of errors, which will be appended with any errors found.
178 *
179 * @return array The sanitized defaults.
180 */
181 public static function sanitizeDefaults( $old_defaults, $defaults, &$errs ) {
182 if ( is_null( $old_defaults ) ) {
183 $old_defaults = self::getOptions();
184 }
185
186 // remove invalid keys
187 $sanitized = is_array( $defaults )
188 ? array_intersect_key( $defaults, $old_defaults )
189 : array();
190
191 // add any missing keys & sanitize each new value
192 foreach ( $old_defaults as $k => $v ) {
193 if ( ! isset( $sanitized[ $k ] ) ) {
194 if ( is_bool( $v ) ) {
195 // checkbox
196 $sanitized[ $k ] = false;
197 } else {
198 // missing value
199 $sanitized[ $k ] = $v;
200 }
201 } else if ( $sanitized[ $k ] !== $v ) { //Sometimes we get boolean in the string form for checkboxes
202 // sanitize value if different from old value
203 $sanitized[ $k ] = self::sanitizeParameter( $k, $sanitized[ $k ], $errs );
204 }
205 }
206
207 return $sanitized;
208 }
209
210 /**
211 *
212 * @param string $key The key to reference the current value in the defaults array.
213 * @param mixed $value The value to be sanitized.
214 * @param array $errs The array of errors, which will be appended with any errors found.
215 *
216 * @return mixed The sanitized value, falling back to the current default value when invalid value given.
217 */
218 private static function sanitizeParameter( $key, $value, &$errs ) {
219 // all sanitize methods must be in the following form: sanitize<UpperCammelCaseKey>
220 $funct = $key;
221 $funct[0] = strtoupper( $funct[0] );
222 $funct = 'sanitize' . preg_replace_callback( '/_([a-z])/', array( __CLASS__, 'secondCharToUpper' ), $funct );
223
224 $callable = array( __CLASS__, $funct );
225
226 // avoid looking for method beforehand unless we're running in debug mode -- expensive call
227 if ( DG_Logger::logEnabled() && ! method_exists( __CLASS__, $funct ) ) {
228 DG_Logger::writeLog(
229 DG_LogLevel::Error,
230 __( 'Attempted to call invalid function: ', 'document-gallery' ) . implode( '::', $callable ),
231 true );
232 }
233
234 // call param-specific sanitization
235 $ret = call_user_func_array( $callable, array( $value, &$err ) );
236
237 // check for error and return default
238 if ( isset( $err ) ) {
239 $defaults = self::getOptions();
240 $ret = $defaults[ $key ];
241
242 $errs[ $key ] = $err;
243 }
244
245 return $ret;
246 }
247
248 /**
249 * Takes the provided value and returns a sanitized value.
250 *
251 * @param string $value The attachment_pg value to be sanitized.
252 * @param string &$err String to be initialized with error, if any.
253 *
254 * @return bool The sanitized attachment_pg value.
255 */
256 private static function sanitizeAttachmentPg( $value, &$err ) {
257 $ret = DG_Util::toBool( $value );
258
259 if ( is_null( $ret ) ) {
260 $err = sprintf( self::$binary_err, 'attachment_pg', 'true', 'false', $value );
261 }
262
263 return $ret;
264 }
265
266 /**
267 * Takes the provided value and returns a sanitized value.
268 *
269 * @param string $value The columns value to be sanitized.
270 * @param string &$err String to be initialized with error, if any.
271 *
272 * @return int The sanitized columns value.
273 */
274 public static function sanitizeColumns( $value, &$err ) {
275 return $value != - 1 ? absint( $value ) : null;
276 }
277
278 /**
279 * Takes the provided value and returns a sanitized value.
280 *
281 * @param string $value The descriptions value to be sanitized.
282 * @param string &$err String to be initialized with error, if any.
283 *
284 * @return bool The sanitized descriptions value.
285 */
286 private static function sanitizeDescriptions( $value, &$err ) {
287 $ret = DG_Util::toBool( $value );
288
289 if ( is_null( $ret ) ) {
290 $err = sprintf( self::$binary_err, 'descriptions', 'true', 'false', $value );
291 }
292
293 return $ret;
294 }
295
296 /**
297 * Takes the provided value and returns a sanitized value.
298 *
299 * @param string $value The exclude value to be sanitized.
300 * @param string &$err String to be initialized with error, if any.
301 *
302 * @return bool The sanitized exclude value.
303 */
304 private static function sanitizeExclude( $value, &$err ) {
305 return self::sanitizeIdList( 'Exclude', $value, $err );
306 }
307
308 /**
309 * Takes the provided value and returns a sanitized value.
310 *
311 * @param string $value The fancy value to be sanitized.
312 * @param string &$err String to be initialized with error, if any.
313 *
314 * @return bool The sanitized fancy value.
315 */
316 private static function sanitizeFancy( $value, &$err ) {
317 $ret = DG_Util::toBool( $value );
318
319 if ( is_null( $ret ) ) {
320 $err = sprintf( self::$binary_err, 'fancy', 'true', 'false', $value );
321 }
322
323 return $ret;
324 }
325
326 /**
327 * Takes the provided value and returns a sanitized value.
328 *
329 * @param string $value The id value to be sanitized.
330 * @param string &$err String to be initialized with error, if any.
331 *
332 * @return int The sanitized id value.
333 */
334 private static function sanitizeId( $value, &$err ) {
335 return $value != - 1 ? absint( $value ) : null;
336 }
337
338 /**
339 * Takes the provided comma-delimited list of IDs and returns null if it is invalid.
340 *
341 * @param string $name Name of the value being sanitized. Used in error string when needed.
342 * @param string $value The ids value to be sanitized.
343 * @param string &$err String to be initialized with error, if any.
344 *
345 * @return bool|multitype:int The sanitized comma-delimited list of IDs value.
346 */
347 private static function sanitizeIdList( $name, $value, &$err ) {
348 static $regex = '/(?:|\d+(?:,\d+)*)/';
349
350 $ret = $value;
351
352 if ( ! preg_match( $regex, $value ) ) {
353 $err = sprintf( __( '%s may only be a comma-delimited list of integers.', 'document-gallery' ), $name );
354 $ret = null;
355 }
356
357 return $ret;
358 }
359
360 /**
361 * Takes the provided value and returns a sanitized value.
362 *
363 * @param string $value The ids value to be sanitized.
364 * @param string &$err String to be initialized with error, if any.
365 *
366 * @return bool|multitype:int The sanitized ids value.
367 */
368 private static function sanitizeInclude( $value, &$err ) {
369 return self::sanitizeIdList( 'Include', $value, $err );
370 }
371
372 /**
373 * Takes the provided value and returns a sanitized value.
374 *
375 * @param string $value The limit value to be sanitized.
376 * @param string &$err String to be initialized with error, if any.
377 *
378 * @return int The sanitized limit value.
379 */
380 private static function sanitizeLimit( $value, &$err ) {
381 $ret = intval( $value );
382
383 if ( is_null( $ret ) || $ret < - 1 ) {
384 $err = sprintf( self::$unary_err, 'limit', '>= -1' );
385 $ret = null;
386 }
387
388 return $ret;
389 }
390
391 /**
392 * Takes the provided value and returns a sanitized value.
393 *
394 * @param string $value The mime_types value to be sanitized.
395 * @param string &$err String to be initialized with error, if any.
396 *
397 * @return string The sanitized mime_types value.
398 */
399 private static function sanitizeMimeTypes( $value, &$err ) {
400 // TODO: do some actual sanitization...
401 return $value;
402 }
403
404 /**
405 * Takes the provided value and returns a sanitized value.
406 *
407 * @param string $value The new_window value to be sanitized.
408 * @param string &$err String to be initialized with error, if any.
409 *
410 * @return bool The sanitized new_window value.
411 */
412 private static function sanitizeNewWindow( $value, &$err ) {
413 $ret = DG_Util::toBool( $value );
414
415 if ( is_null( $ret ) ) {
416 $err = sprintf( self::$binary_err, 'new_window', 'true', 'false', $value );
417 }
418
419 return $ret;
420 }
421
422 /**
423 * Takes the provided value and returns a sanitized value.
424 *
425 * @param string $value The order value to be sanitized.
426 * @param string &$err String to be initialized with error, if any.
427 *
428 * @return string The sanitized order value.
429 */
430 private static function sanitizeOrder( $value, &$err ) {
431 $ret = strtoupper( $value );
432
433 if ( ! in_array( $ret, self::getOrderOptions() ) ) {
434 $err = sprintf( self::$binary_err, 'order', 'ASC', 'DESC', $value );
435 $ret = null;
436 }
437
438 return $ret;
439 }
440
441 /**
442 * @return array The valid options for order parameter.
443 */
444 public static function getOrderOptions() {
445 return array( 'ASC', 'DESC' );
446 }
447
448 /**
449 * Takes the provided value and returns a sanitized value.
450 *
451 * @param string $value The orderby value to be sanitized.
452 * @param string &$err String to be initialized with error, if any.
453 *
454 * @return string The sanitized orderby value.
455 */
456 private static function sanitizeOrderby( $value, &$err ) {
457 $ret = ( 'ID' === strtoupper( $value ) ) ? 'ID' : strtolower( $value );
458
459 if ( ! in_array( $ret, self::getOrderbyOptions() ) ) {
460 $err = sprintf( self::$unary_err, 'orderby', $value );
461 $ret = null;
462 }
463
464 return $ret;
465 }
466
467 /**
468 * @return array The valid options for orderby parameter.
469 */
470 public static function getOrderbyOptions() {
471 return array(
472 'author',
473 'comment_count',
474 'date',
475 'ID',
476 'menu_order',
477 'modified',
478 'name',
479 'none',
480 'parent',
481 'post__in',
482 'rand',
483 'title'
484 );
485 }
486
487 /**
488 * Takes the provided value and returns a sanitized value.
489 *
490 * @param string $value The post_status value to be sanitized.
491 * @param string &$err String to be initialized with error, if any.
492 *
493 * @return string The sanitized post_status value.
494 */
495 private static function sanitizePostStatus( $value, &$err ) {
496 $ret = preg_grep( '/^' . preg_quote( $value ) . '$/i', self::getPostStatuses() );
497 $ret = reset( $ret );
498
499 if ( $ret === false ) {
500 $err = sprintf( self::$unary_err, 'post_status', $value );
501 }
502
503 return $ret;
504 }
505
506 /**
507 * @return array All registered post statuses.
508 */
509 public static function getPostStatuses() {
510 static $statuses;
511 if ( ! isset( $statuses ) ) {
512 $statuses = get_post_stati();
513 $statuses[] = 'any';
514 asort( $statuses );
515 }
516
517 return $statuses;
518 }
519
520 /**
521 * Takes the provided value and returns a sanitized value.
522 *
523 * @param string $value The post_type value to be sanitized.
524 * @param string &$err String to be initialized with error, if any.
525 *
526 * @return string The sanitized post_type value.
527 */
528 private static function sanitizePostType( $value, &$err ) {
529 $ret = preg_grep( '/^' . preg_quote( $value ) . '$/i', self::getPostTypes() );
530 $ret = reset( $ret );
531
532 if ( $ret === false ) {
533 $err = sprintf( self::$unary_err, 'post_type', $value );
534 }
535
536 return $ret;
537 }
538
539 /**
540 * @return array All registered post types.
541 */
542 public static function getPostTypes() {
543 static $types;
544 if ( ! isset( $types ) ) {
545 $types = get_post_types();
546 $types[] = 'any';
547 asort( $types );
548 }
549
550 return $types;
551 }
552
553 /**
554 * Takes the provided value and returns a sanitized value.
555 *
556 * @param string $value The relation value to be sanitized.
557 * @param string &$err String to be initialized with error, if any.
558 *
559 * @return string The sanitized relation value.
560 */
561 private static function sanitizeRelation( $value, &$err ) {
562 $ret = strtoupper( $value );
563
564 if ( ! in_array( $ret, self::getRelationOptions() ) ) {
565 $err = sprintf( self::$binary_err, 'relation', 'AND', 'OR', $value );
566 $ret = null;
567 }
568
569 return $ret;
570 }
571
572 /**
573 * @return array The valid options for relation parameter.
574 */
575 public static function getRelationOptions() {
576 return array( 'AND', 'OR' );
577 }
578
579 /**
580 * Takes the provided value and returns a sanitized value.
581 *
582 * @param string $operator The operator value to be sanitized.
583 *
584 * @return string The sanitized operator value.
585 */
586 private function sanitizeOperator( $operator ) {
587 $ret = strtoupper( $operator );
588
589 if ( ! in_array( $ret, self::getOperatorOptions() ) ) {
590 $this->errs[] = sprintf( self::$binary_err, 'IN", "NOT IN", "OR', 'AND', $operator );
591 $ret = null;
592 } else if ( $ret === 'OR' ) {
593 $ret = 'IN';
594 }
595
596 return $ret;
597 }
598
599 /**
600 * @return array The valid options for *_relation/*_operator parameter.
601 */
602 public static function getOperatorOptions() {
603 return array( 'IN', 'NOT IN', 'AND', 'OR' );
604 }
605
606 /**
607 * Gets all valid Documents based on the attributes passed by the user.
608 * NOTE: Keys in returned array are arbitrary and will vary. They should be ignored.
609 * @return array Contains all documents matching the query.
610 * @throws InvalidArgumentException Thrown when $this->errs is not empty.
611 */
612 private function getDocuments() {
613 $query = array(
614 'numberposts' => $this->atts['limit'],
615 'orderby' => $this->atts['orderby'],
616 'order' => $this->atts['order'],
617 'post_status' => $this->atts['post_status'],
618 'post_type' => $this->atts['post_type'],
619 'post_mime_type' => $this->atts['mime_types']
620 );
621
622 $this->setTaxa( $query );
623
624 if ( ! empty( $this->errs ) ) {
625 throw new InvalidArgumentException();
626 }
627
628 // NOTE: Derived from gallery shortcode
629 if ( ! empty( $this->atts['include'] ) ) {
630 $query['include'] = $this->atts['include'];
631 $attachments = get_posts( $query );
632 } else {
633 // id == 0 => all attachments w/o a parent
634 // id == null => all matched attachments
635 $query['post_parent'] = $this->atts['id'];
636 if ( ! empty( $exclude ) ) {
637 $query['exclude'] = $this->atts['exclude'];
638 }
639
640 $attachments = get_children( $query );
641 }
642
643 return $attachments;
644 }
645
646 /**
647 * Function loops through all attributes passed that did not match
648 * self::$defaults. If they are the name of a taxonomy, they are plugged
649 * into the query, otherwise $this->errs is appended with an error string.
650 *
651 * @param array $query Query to insert tax query into.
652 */
653 private function setTaxa( &$query ) {
654 if ( ! empty( $this->taxa ) ) {
655 $taxa = array( 'relation' => $this->atts['relation'] );
656 $operator = array();
657 $suffix = array( 'relation', 'operator' );
658 $pattern = '/(.+)_(?:' . implode( '|', $suffix ) . ')$/i';
659
660 // find any relations for taxa
661 $iterable = $this->taxa;
662 foreach ( $iterable as $key => $value ) {
663 if ( preg_match( $pattern, $key, $matches ) ) {
664 $base = $matches[1];
665 if ( array_key_exists( $base, $this->taxa ) ) {
666 $operator[ $base ] = self::sanitizeOperator( $value );
667 unset( $this->taxa[ $key ] );
668 }
669 }
670 }
671
672 // build tax query
673 foreach ( $this->taxa as $taxon => $terms ) {
674 $terms = $this->getTermIdsByNames( $taxon, explode( ',', $terms ) );
675
676 $taxa[] = array(
677 'taxonomy' => $taxon,
678 'field' => 'id',
679 'terms' => $terms,
680 'operator' => isset( $operator[ $taxon ] ) ? $operator[ $taxon ] : 'IN'
681 );
682 }
683
684 // create nested structure
685 $query['tax_query'] = $taxa;
686 }
687 }
688
689 /*==========================================================================
690 * HELPER FUNCTIONS
691 *=========================================================================*/
692
693 /**
694 * Returns an array of term ids when provided with a list of term names.
695 * Also appends an entry onto $errs if any invalid names are found.
696 *
697 * @param string $taxon The taxon these terms are a member of.
698 * @param array $term_names Terms to retrieve.
699 *
700 * @return array All matched terms.
701 */
702 private function getTermIdsByNames( $taxon, $term_names ) {
703 return $this->getTermXByNames( 'term_id', $taxon, $term_names );
704 }
705
706 /**
707 * Returns an array of term slugs when provided with a list of term names.
708 * Also appends an entry onto $errs if any invalid names are found.
709 *
710 * @param string $taxon The taxon these terms are a member of.
711 * @param array $term_names Terms to retrieve.
712 *
713 * @return array All matched terms.
714 */
715 private function getTermSlugsByNames( $taxon, $term_names ) {
716 return $this->getTermXByNames( 'slug', $taxon, $term_names );
717 }
718
719 /**
720 * Returns a list of x, where x may be any of the fields within a
721 * term object, when provided with a list of term names (not slugs).
722 * (http://codex.wordpress.org/Function_Reference/get_term_by#Return_Values)
723 *
724 * Also appends an entry onto $errs if any invalid names are found.
725 *
726 * @param string $x Field to retrieve from matched term.
727 * @param string $taxon The taxon these terms are a member of.
728 * @param array $term_names Terms to retrieve.
729 *
730 * @return array All matched terms.
731 */
732 private function getTermXByNames( $x, $taxon, $term_names ) {
733 $ret = array();
734 $valid = true;
735
736 // taxons may optionally be prefixed by 'tax_' --
737 // this is only useful when avoiding collisions with other attributes
738 if ( ! taxonomy_exists( $taxon ) ) {
739 $tmp = preg_replace( '/^tax_(.*)/', '$1', $taxon, 1, $count );
740 if ( $count > 0 && taxonomy_exists( $tmp ) ) {
741 $taxon = $tmp;
742 } else {
743 $this->errs[] = sprintf( self::$unary_err, 'taxon', $taxon );
744 $valid = false;
745 }
746 }
747
748 // only check terms if we first have a valid taxon
749 if ( $valid ) {
750 foreach ( $term_names as $name ) {
751 if ( ( $term = get_term_by( 'name', $name, $taxon ) ) ) {
752 $ret[] = $term->{$x};
753 } else {
754 $this->errs[] = sprintf( __( '%s is not a valid term name in %s.',
755 'document-gallery' ), $name, $taxon );
756 }
757 }
758 }
759
760 return $ret;
761 }
762
763 /**
764 * @param string $string To take second char from.
765 *
766 * @return string Capitalized second char of given string.
767 */
768 private static function secondCharToUpper( $string ) {
769 return strtoupper( $string[1] );
770 }
771
772 /**
773 * Function returns false for positive ints, true otherwise.
774 *
775 * @param string $var could be anything.
776 *
777 * @return boolean indicating whether $var is not a positive int.
778 */
779 private static function negativeInt( $var ) {
780 return ! is_numeric( $var ) // isn't numeric
781 || (int) $var != $var // isn't int
782 || (int) $var < 0; // isn't positive
783 }
784
785 /*==========================================================================
786 * OUTPUT HTML STRING
787 *=========================================================================*/
788
789 /**
790 * @filter dg_gallery_template Allows the user to filter anything content surrounding the generated gallery.
791 * @filter dg_row_template Filters the outer DG wrapper HTML. Passes a single
792 * bool value indicating whether the gallery is using descriptions or not.
793 * @return string HTML representing this Gallery.
794 */
795 public function __toString() {
796 static $instance = 0;
797 $instance ++;
798
799 static $find = null;
800 if ( is_null( $find ) ) {
801 $find = array( '%class%', '%icons%' );
802 }
803
804 if ( ! empty( $this->errs ) ) {
805 return '<p>' . implode( '</p><p>', $this->errs ) . '</p>';
806 }
807
808 if ( empty( $this->docs ) ) {
809 return self::$no_docs;
810 }
811
812 $selector = "document-gallery-$instance";
813 $template =
814 "<div id='$selector' class='%class%'>" . PHP_EOL .
815 '%icons%' . PHP_EOL .
816 '</div>' . PHP_EOL;
817
818 $icon_wrapper = apply_filters(
819 'dg_row_template',
820 $template,
821 $this->useDescriptions() );
822
823 $core = '';
824 $classes = array( 'document-icon-wrapper' );
825 if ( $this->useDescriptions() ) {
826 $classes[] = 'descriptions';
827 }
828
829 $repl = array( implode( ' ', $classes ) );
830 if ( $this->useDescriptions() ) {
831 foreach ( $this->docs as $doc ) {
832 $repl[1] = $doc;
833 $core .= str_replace( $find, $repl, $icon_wrapper );
834 }
835 } else {
836 $count = count( $this->docs );
837 $cols = ! is_null( $this->atts['columns'] ) ? $this->atts['columns'] : $count;
838
839 // TODO: Invalid HTML. WP Core does it this way for [gallery], but consider setting width for each
840 // .document-icon as style attribute in element.
841 if ( apply_filters( 'dg_use_default_gallery_style', true ) ) {
842 $itemwidth = $cols > 0 ? ( floor( 100 / $cols ) - 1 ) : 100;
843 $core .= "<style type='text/css'>#$selector .document-icon{width:$itemwidth%}</style>";
844 }
845
846 for ( $i = 0; $i < $count; $i += $cols ) {
847 $repl[1] = '';
848
849 $min = min( $i + $cols, $count );
850 for ( $x = $i; $x < $min; $x ++ ) {
851 $repl[1] .= $this->docs[ $x ];
852 }
853
854 $core .= str_replace( $find, $repl, $icon_wrapper );
855 }
856 }
857
858 // allow user to wrap gallery output
859 $gallery = apply_filters( 'dg_gallery_template', '%rows%', $this->useDescriptions() );
860
861 return self::$comment . str_replace( '%rows%', $core, $gallery );
862 }
863 }