Document Gallery - Version 1.4.3

Version Description

  • Bug Fix: Resolves minor bug introduced in version 1.4.2. Thanks, tkokholm!
Download this release

Release Info

Developer dan.rossiter
Plugin Icon 128x128 Document Gallery
Version 1.4.3
Comparing to
See all releases

Code changes from version 1.3.1 to 1.4.3

document-gallery.php CHANGED
@@ -1,318 +1,43 @@
1
  <?php
2
- /*
3
- Plugin Name: Document Gallery
4
- Description: Display non-images (and images) in gallery format on a page or post with the [dg] shortcode.
5
- Version: 1.3.1
6
- Author: Dan Rossiter
7
- Author URI: http://danrossiter.org/
8
- License: GPL2
9
- */
10
-
11
- define( 'DG_URL', plugin_dir_url( __FILE__ ) );
12
- define( 'DG_IMG_STRING', '<img src="%s" title="%s" alt="%s" />' );
13
- define( 'DG_DOC_ICON',
14
- ' <div class="document-icon">'.PHP_EOL.
15
- ' <a href="%s">%s<br>%s</a>'.PHP_EOL.
16
- ' </div>'.PHP_EOL );
17
 
18
- // CREATE GALLERY STRING //
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  function dg_get_attachment_icons($atts) {
20
- extract( shortcode_atts( array(
21
- 'descriptions' => FALSE,
22
- 'orderby' => 'menu_order',
23
- 'order' => 'ASC',
24
- 'attachment_pg' => FALSE, // default: link directly to file (true to link to attachment pg)
25
- 'images' => FALSE, // if enabled, all images attached to current page will be included also
26
- 'ids' => FALSE // comma-separated list of attachment ids
27
- ), $atts) );
28
-
29
- // INIT
30
- $attachments = array();
31
- $count = 0;
32
- $errs = array();
33
-
34
-
35
- // ATTRIBUTE VALIDATION
36
- $order = strtoupper( $order );
37
- if($order != 'ASC' && $order != 'DEC')
38
- $errs[] = "The order attribute must be either ASC or DEC. You entered $order.";
39
-
40
- if( strtolower($ids) == "false" ) $ids = FALSE;
41
-
42
- $descriptions = !$descriptions || strtolower($descriptions) == "false" ? FALSE : TRUE;
43
- $attachment_pg = !$attachment_pg || strtolower($attachment_pg) == "false" ? FALSE : TRUE;
44
- $images = !$images || strtolower($images) == "false" ? FALSE : TRUE;
45
-
46
- // http://www.youtube.com/watch?v=ClnSMCdw6E8
47
- if( $errs ) return implode(' ', $errs);
48
- // END VALIDATION (WE MADE IT!)
49
-
50
-
51
- // LET'S GET SOME DOCUMENTS!
52
- if( $ids && ( $ids = explode( ',', $ids ) ) )
53
- $attachments = dg_get_attachments_by_ids( $ids );
54
-
55
- // if 'ids' was used, skip this
56
- if( !$attachments ){
57
- $args = array(
58
- 'numberposts' => -1,
59
- 'orderby' => $orderby,
60
- 'order' => $order,
61
- 'post_type' => 'attachment',
62
- 'post_mime_type' => 'application,video,text,audio',
63
- 'post_parent' => get_the_ID() );
64
- if( $images ) $args['post_mime_type'] .= ',image';
65
-
66
- $attachments = get_posts($args);
67
- }
68
-
69
- if ( $attachments ) {
70
- $attachment_str = PHP_EOL.'<!-- Generated using Document Gallery. Get yours here: '.
71
- 'http://wordpress.org/extend/plugins/document-gallery -->'.PHP_EOL;
72
-
73
- // DOCUMENT LOOP
74
- foreach( $attachments as $attachment ) {
75
- // INIT ATTACHMENT-SPECIFIC VARS
76
- $url = $attachment->guid;
77
- $filename = basename( $url );
78
-
79
- if( $attachment_pg ) // link to attachment page
80
- $url = get_attachment_link( $attachment->ID );
81
-
82
- $title = get_the_title( $attachment->ID );
83
- $icon = dg_get_attachment_image( $attachment->ID, $title, $filename );
84
-
85
- // GENERATE OUTPUT
86
- if($descriptions) { // start description wrapper
87
- $attachment_str .= '<div class="document-icon-wrapper descriptions">'.PHP_EOL;
88
 
89
- } elseif( $count % 4 == 0 ) { // no description
90
- $attachment_str .= '<div id="document-icon-wrapper">'.PHP_EOL;
91
- }
92
-
93
- // insert filtered document-icon
94
- $attachment_str .= apply_filters( 'dg_doc_icon',
95
- sprintf( DG_DOC_ICON, $url, $icon, $title ), $attachment->ID );
96
-
97
- if($descriptions) { // add description
98
- $attachment_str .= " <p>$attachment->post_content</p>".
99
- PHP_EOL.'</div>'.PHP_EOL;
100
-
101
- } elseif( ++$count % 4 == 0 ) { // end wrapper
102
- $attachment_str .= '</div>'.PHP_EOL;
103
- }
104
- } // END DOCUMENT LOOP
105
-
106
- // for galleries w/ number of docs != mult of 4
107
- if( $count % 4 != 0 && !$descriptions ) // end wrapper
108
- $attachment_str .= '</div>'.PHP_EOL;
109
-
110
- return $attachment_str;
111
- } // END IF
112
-
113
- // NO DOCUMENTS
114
- return PHP_EOL.'<!-- Document Gallery: No attachments to display. How boring... -->'.PHP_EOL;
115
  }
116
- add_shortcode('dg', 'dg_get_attachment_icons');
117
-
118
- // 'document gallery' shortcode depreciated as of v1.0. left for backward compatibility
119
- add_shortcode('document gallery', 'dg_get_attachment_icons');
120
-
121
 
122
- // HELPERS //
123
- function dg_get_attachments_by_ids( $ids ){
124
- $attachments = array();
125
- foreach( $ids as $id ){
126
- $attachment = get_post( $id );
127
- if( $attachment->post_type == 'attachment' )
128
- $attachments[] = $attachment;
129
- // else: not an attachment so skip
130
- }
131
- return $attachments;
132
- }
133
-
134
- // pass in $title & $filename to avoid mult function calls
135
- function dg_get_attachment_image( $id, $title, $filename ) {
136
- $filetype = wp_check_filetype( $filename );
137
-
138
- // identify extension
139
- switch( $filetype['ext'] ) {
140
- // Most Common First
141
- case 'pdf':
142
- $icon = DG_URL.'icons/pdf.png';
143
- break;
144
- // MS Office
145
- case 'doc':
146
- case 'docx':
147
- case 'docm':
148
- case 'dotx':
149
- case 'dotm':
150
- $icon = DG_URL.'icons/msdoc.png';
151
- break;
152
- case 'ppt':
153
- case 'pot':
154
- case 'pps':
155
- case 'pptx':
156
- case 'pptm':
157
- case 'ppsx':
158
- case 'ppsm':
159
- case 'potx':
160
- case 'potm':
161
- case 'ppam':
162
- case 'sldx':
163
- case 'sldm':
164
- $icon = DG_URL.'icons/msppt.png';
165
- break;
166
- case 'xla':
167
- case 'xls':
168
- case 'xlt':
169
- case 'xlw':
170
- case 'xlsx':
171
- case 'xlsm':
172
- case 'xlsb':
173
- case 'xltx':
174
- case 'xltm':
175
- case 'xlam':
176
- $icon = DG_URL.'icons/msxls.png';
177
- break;
178
- case 'mdb':
179
- $icon = DG_URL.'icons/msaccess.png';
180
- break;
181
- // Video formats
182
- case 'avi':
183
- $icon = DG_URL.'icons/avi.png';
184
- break;
185
- case 'divx':
186
- $icon = DG_URL.'icons/divx.png';
187
- break;
188
- case 'flv':
189
- $icon = DG_URL.'icons/flv.png';
190
- break;
191
- case 'qt':
192
- case 'mov':
193
- $icon = DG_URL.'icons/mov.png';
194
- break;
195
- case 'asf':
196
- case 'asx':
197
- case 'wax':
198
- case 'wmv':
199
- case 'wmx':
200
- $icon = DG_URL.'icons/wmv.png';
201
- break;
202
- case 'mkv':
203
- $icon = DG_URL.'icons/mkv.png';
204
- break;
205
- // Audio formats
206
- case 'mp3':
207
- $icon = DG_URL.'icons/mp3.png';
208
- break;
209
- case 'wav':
210
- $icon = DG_URL.'icons/wav.png';
211
- break;
212
- case 'ogg':
213
- case 'oga':
214
- $icon = DG_URL.'icons/ogg.png';
215
- break;
216
- case 'midi':
217
- case 'mid':
218
- $icon = DG_URL.'icons/midi.png';
219
- break;
220
- case 'wma':
221
- $icon = DG_URL.'icons/wma.png';
222
- break;
223
- // Text formats
224
- case 'rtx':
225
- $icon = DG_URL.'icons/rtx.png';
226
- break;
227
- case 'ics':
228
- $icon = DG_URL.'icons/ics.png';
229
- break;
230
- case 'csv':
231
- $icon = DG_URL.'icons/csv.png';
232
- break;
233
- // Msc application formats
234
- case 'html':
235
- case 'htm': // death to all who use this!
236
- $icon = DG_URL.'icons/html.png';
237
- break;
238
- case 'css':
239
- $icon = DG_URL.'icons/css.png';
240
- break;
241
- case 'js':
242
- $icon = DG_URL.'icons/javascript.png';
243
- break;
244
- case 'class':
245
- $icon = DG_URL.'icons/java.png';
246
- break;
247
- case 'zip':
248
- $icon = DG_URL.'icons/zip.png';
249
- break;
250
- case 'tar':
251
- case 'gzip':
252
- case 'gz':
253
- case 'bz2': // not yet WP-supported
254
- case 'tgz': // not yet WP-supported
255
- $icon = DG_URL.'icons/compressed.png';
256
- break;
257
- case 'rar': // RAWR!!!
258
- $icon = DG_URL.'icons/rar.png';
259
- break;
260
- case '7z':
261
- $icon = DG_URL.'icons/7zip.png';
262
- break;
263
- case 'exec':
264
- $icon = DG_URL.'icons/exec.png';
265
- break;
266
- case 'rtf':
267
- $icon = DG_URL.'icons/rtf.png';
268
- break;
269
- case 'swf':
270
- $icon = DG_URL.'icons/shockwave.png';
271
- break;
272
- // OpenOffice formats
273
- case 'odt':
274
- $icon = DG_URL.'icons/opendocument-text.png';
275
- break;
276
- case 'odp':
277
- $icon = DG_URL.'icons/opendocument-presentation.png';
278
- break;
279
- case 'ods':
280
- $icon = DG_URL.'icons/opendocument-spreadsheet.png';
281
- break;
282
- case 'odg':
283
- $icon = DG_URL.'icons/opendocument-graphics.png';
284
- break;
285
- case 'odb':
286
- $icon = DG_URL.'icons/opendocument-database.png';
287
- break;
288
- case 'odf':
289
- $icon = DG_URL.'icons/opendocument-formula.png';
290
- break;
291
- default:
292
- // handle images
293
- if( strpos( $filetype['type'], 'image' ) === 0 &&
294
- ( $icon = wp_get_attachment_image_src( $id, 'thumbnail', false ) ) ){
295
- $icon = $icon[0];
296
- break;
297
- }
298
-
299
- // fallback to default icons if not recognized
300
- if( $icon = wp_get_attachment_image_src( $id, null, true ) ){
301
- $icon = $icon[0];
302
- break;
303
- }
304
-
305
- // everything failed. This is bad...
306
- return "<!-- Failed to retrive icon for attachment #$id -->";
307
- }
308
-
309
- return sprintf( DG_IMG_STRING, $icon, $title, $title );
310
- }
311
 
312
- // ADD SOME STYLING
 
 
313
  function dg_add_header_css() {
314
- wp_enqueue_style( 'document-gallery-css', plugins_url('style.css', __FILE__) );
315
  }
316
- add_action( 'wp_print_styles', 'dg_add_header_css');
317
 
318
- ?>
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
+ /*
4
+ Plugin Name: Document Gallery
5
+ Description: Display non-images (and images) in gallery format on a page or post with the [dg] shortcode.
6
+ Version: 1.4.3
7
+ Author: Dan Rossiter
8
+ Author URI: http://danrossiter.org/
9
+ License: GPLv2
10
+ */
11
+
12
+ define('DG_URL', plugin_dir_url(__FILE__));
13
+ define('DG_PATH', trailingslashit(dirname(__FILE__)));
14
+
15
+ /**
16
+ * Takes values passed from attributes and returns sutable HTML to represent
17
+ * all valid attachments requested.
18
+ *
19
+ * @param array $atts Arguments from the user.
20
+ * @return string HTML for the Document Gallery.
21
+ */
22
  function dg_get_attachment_icons($atts) {
23
+ include_once(DG_PATH . 'models/class-gallery.php');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ // empty string is passed when no arguments are given, but constructor expects an array
26
+ return (string)(new DG_Gallery(empty($atts) ? array() : $atts));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  }
 
 
 
 
 
28
 
29
+ /**
30
+ * 'document gallery' shortcode depreciated as of v1.0. left for backward compatibility
31
+ */
32
+ add_shortcode('document gallery', 'dg_get_attachment_icons');
33
+ add_shortcode('dg', 'dg_get_attachment_icons');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
+ /**
36
+ * Include stylesheet for some basic design.
37
+ */
38
  function dg_add_header_css() {
39
+ wp_enqueue_style('document-gallery-css', DG_URL . 'style.css');
40
  }
41
+ add_action('wp_print_styles', 'dg_add_header_css');
42
 
43
+ ?>
icons/7zip.png DELETED
Binary file
icons/asc.png ADDED
Binary file
icons/audio.png ADDED
Binary file
icons/avi.png DELETED
Binary file
icons/c.png ADDED
Binary file
icons/cpp.png ADDED
Binary file
icons/csv.png DELETED
Binary file
icons/divx.png DELETED
Binary file
icons/flv.png DELETED
Binary file
icons/h.png ADDED
Binary file
icons/image.png ADDED
Binary file
icons/key.png ADDED
Binary file
icons/missing.png ADDED
Binary file
icons/mkv.png DELETED
Binary file
icons/mov.png DELETED
Binary file
icons/mp3.png DELETED
Binary file
icons/numbers.png ADDED
Binary file
icons/ogg.png DELETED
Binary file
icons/pages.png ADDED
Binary file
icons/rar.png DELETED
Binary file
icons/text.png ADDED
Binary file
icons/video.png ADDED
Binary file
icons/wav.png DELETED
Binary file
icons/wma.png DELETED
Binary file
icons/wmv.png DELETED
Binary file
icons/wordperfect.png ADDED
Binary file
icons/zip.png DELETED
Binary file
license.txt ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Public
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Public License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Lesser General Public License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Public Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Public License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+ Thus, it is not the intent of this section to claim rights or contest
125
+ your rights to work written entirely by you; rather, the intent is to
126
+ exercise the right to control the distribution of derivative or
127
+ collective works based on the Program.
128
+
129
+ In addition, mere aggregation of another work not based on the Program
130
+ with the Program (or with a work based on the Program) on a volume of
131
+ a storage or distribution medium does not bring the other work under
132
+ the scope of this License.
133
+
134
+ 3. You may copy and distribute the Program (or a work based on it,
135
+ under Section 2) in object code or executable form under the terms of
136
+ Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+ a) Accompany it with the complete corresponding machine-readable
139
+ source code, which must be distributed under the terms of Sections
140
+ 1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+ b) Accompany it with a written offer, valid for at least three
143
+ years, to give any third party, for a charge no more than your
144
+ cost of physically performing source distribution, a complete
145
+ machine-readable copy of the corresponding source code, to be
146
+ distributed under the terms of Sections 1 and 2 above on a medium
147
+ customarily used for software interchange; or,
148
+
149
+ c) Accompany it with the information you received as to the offer
150
+ to distribute corresponding source code. (This alternative is
151
+ allowed only for noncommercial distribution and only if you
152
+ received the program in object code or executable form with such
153
+ an offer, in accord with Subsection b above.)
154
+
155
+ The source code for a work means the preferred form of the work for
156
+ making modifications to it. For an executable work, complete source
157
+ code means all the source code for all modules it contains, plus any
158
+ associated interface definition files, plus the scripts used to
159
+ control compilation and installation of the executable. However, as a
160
+ special exception, the source code distributed need not include
161
+ anything that is normally distributed (in either source or binary
162
+ form) with the major components (compiler, kernel, and so on) of the
163
+ operating system on which the executable runs, unless that component
164
+ itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering
167
+ access to copy from a designated place, then offering equivalent
168
+ access to copy the source code from the same place counts as
169
+ distribution of the source code, even though third parties are not
170
+ compelled to copy the source along with the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program
173
+ except as expressly provided under this License. Any attempt
174
+ otherwise to copy, modify, sublicense or distribute the Program is
175
+ void, and will automatically terminate your rights under this License.
176
+ However, parties who have received copies, or rights, from you under
177
+ this License will not have their licenses terminated so long as such
178
+ parties remain in full compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not
181
+ signed it. However, nothing else grants you permission to modify or
182
+ distribute the Program or its derivative works. These actions are
183
+ prohibited by law if you do not accept this License. Therefore, by
184
+ modifying or distributing the Program (or any work based on the
185
+ Program), you indicate your acceptance of this License to do so, and
186
+ all its terms and conditions for copying, distributing or modifying
187
+ the Program or works based on it.
188
+
189
+ 6. Each time you redistribute the Program (or any work based on the
190
+ Program), the recipient automatically receives a license from the
191
+ original licensor to copy, distribute or modify the Program subject to
192
+ these terms and conditions. You may not impose any further
193
+ restrictions on the recipients' exercise of the rights granted herein.
194
+ You are not responsible for enforcing compliance by third parties to
195
+ this License.
196
+
197
+ 7. If, as a consequence of a court judgment or allegation of patent
198
+ infringement or for any other reason (not limited to patent issues),
199
+ conditions are imposed on you (whether by court order, agreement or
200
+ otherwise) that contradict the conditions of this License, they do not
201
+ excuse you from the conditions of this License. If you cannot
202
+ distribute so as to satisfy simultaneously your obligations under this
203
+ License and any other pertinent obligations, then as a consequence you
204
+ may not distribute the Program at all. For example, if a patent
205
+ license would not permit royalty-free redistribution of the Program by
206
+ all those who receive copies directly or indirectly through you, then
207
+ the only way you could satisfy both it and this License would be to
208
+ refrain entirely from distribution of the Program.
209
+
210
+ If any portion of this section is held invalid or unenforceable under
211
+ any particular circumstance, the balance of the section is intended to
212
+ apply and the section as a whole is intended to apply in other
213
+ circumstances.
214
+
215
+ It is not the purpose of this section to induce you to infringe any
216
+ patents or other property right claims or to contest validity of any
217
+ such claims; this section has the sole purpose of protecting the
218
+ integrity of the free software distribution system, which is
219
+ implemented by public license practices. Many people have made
220
+ generous contributions to the wide range of software distributed
221
+ through that system in reliance on consistent application of that
222
+ system; it is up to the author/donor to decide if he or she is willing
223
+ to distribute software through any other system and a licensee cannot
224
+ impose that choice.
225
+
226
+ This section is intended to make thoroughly clear what is believed to
227
+ be a consequence of the rest of this License.
228
+
229
+ 8. If the distribution and/or use of the Program is restricted in
230
+ certain countries either by patents or by copyrighted interfaces, the
231
+ original copyright holder who places the Program under this License
232
+ may add an explicit geographical distribution limitation excluding
233
+ those countries, so that distribution is permitted only in or among
234
+ countries not thus excluded. In such case, this License incorporates
235
+ the limitation as if written in the body of this License.
236
+
237
+ 9. The Free Software Foundation may publish revised and/or new versions
238
+ of the General Public License from time to time. Such new versions will
239
+ be similar in spirit to the present version, but may differ in detail to
240
+ address new problems or concerns.
241
+
242
+ Each version is given a distinguishing version number. If the Program
243
+ specifies a version number of this License which applies to it and "any
244
+ later version", you have the option of following the terms and conditions
245
+ either of that version or of any later version published by the Free
246
+ Software Foundation. If the Program does not specify a version number of
247
+ this License, you may choose any version ever published by the Free Software
248
+ Foundation.
249
+
250
+ 10. If you wish to incorporate parts of the Program into other free
251
+ programs whose distribution conditions are different, write to the author
252
+ to ask for permission. For software which is copyrighted by the Free
253
+ Software Foundation, write to the Free Software Foundation; we sometimes
254
+ make exceptions for this. Our decision will be guided by the two goals
255
+ of preserving the free status of all derivatives of our free software and
256
+ of promoting the sharing and reuse of software generally.
257
+
258
+ NO WARRANTY
259
+
260
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+ REPAIR OR CORRECTION.
269
+
270
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+ POSSIBILITY OF SUCH DAMAGES.
279
+
280
+ END OF TERMS AND CONDITIONS
281
+
282
+ How to Apply These Terms to Your New Programs
283
+
284
+ If you develop a new program, and you want it to be of the greatest
285
+ possible use to the public, the best way to achieve this is to make it
286
+ free software which everyone can redistribute and change under these terms.
287
+
288
+ To do so, attach the following notices to the program. It is safest
289
+ to attach them to the start of each source file to most effectively
290
+ convey the exclusion of warranty; and each file should have at least
291
+ the "copyright" line and a pointer to where the full notice is found.
292
+
293
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Public License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Public License for more details.
305
+
306
+ You should have received a copy of the GNU General Public License along
307
+ with this program; if not, write to the Free Software Foundation, Inc.,
308
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
+
310
+ Also add information on how to contact you by electronic and paper mail.
311
+
312
+ If the program is interactive, make it output a short notice like this
313
+ when it starts in an interactive mode:
314
+
315
+ Gnomovision version 69, Copyright (C) year name of author
316
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
+ This is free software, and you are welcome to redistribute it
318
+ under certain conditions; type `show c' for details.
319
+
320
+ The hypothetical commands `show w' and `show c' should show the appropriate
321
+ parts of the General Public License. Of course, the commands you use may
322
+ be called something other than `show w' and `show c'; they could even be
323
+ mouse-clicks or menu items--whatever suits your program.
324
+
325
+ You should also get your employer (if you work as a programmer) or your
326
+ school, if any, to sign a "copyright disclaimer" for the program, if
327
+ necessary. Here is a sample; alter the names:
328
+
329
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
+
332
+ <signature of Ty Coon>, 1 April 1989
333
+ Ty Coon, President of Vice
334
+
335
+ This General Public License does not permit incorporating your program into
336
+ proprietary programs. If your program is a subroutine library, you may
337
+ consider it more useful to permit linking proprietary applications with the
338
+ library. If this is what you want to do, use the GNU Lesser General
339
+ Public License instead of this License.
models/class-document.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Description of Document
5
+ *
6
+ * @author drossiter
7
+ */
8
+ class DG_Document {
9
+ // templates for HTML output
10
+ private static $doc_icon = false;
11
+ private static $img_string = '<img src="%s" title="%s" alt="%s" />';
12
+
13
+ // general document data
14
+ private $description, $gallery, $ID, $link, $title, $title_attribute;
15
+
16
+ /**
17
+ * Constructs instance of Document.
18
+ * @param type $attachment Attachment object used to initalize fields.
19
+ * @param type $gallery Instance of Gallery class.
20
+ */
21
+ public function __construct($attachment, $gallery) {
22
+ include_once(DG_PATH . 'util/class-thumber.php');
23
+
24
+ // init template for HTML output
25
+ if(self::$doc_icon === false)
26
+ {
27
+ self::$doc_icon =
28
+ ' <div class="document-icon">' . PHP_EOL .
29
+ ' <a href="%s">%s<br>%s</a>' . PHP_EOL .
30
+ ' </div>' . PHP_EOL;
31
+ }
32
+
33
+ // init general document data
34
+ $this->gallery = $gallery;
35
+ $this->description = $attachment->post_content;
36
+ $this->ID = $attachment->ID;
37
+ $this->link = $gallery->linkToAttachmentPg()
38
+ ? get_attachment_link($attachment->ID)
39
+ : wp_get_attachment_url($attachment->ID);
40
+ $this->title = get_the_title($attachment->ID);
41
+ $this->title_attribute = esc_attr(strip_tags($this->title));
42
+ }
43
+
44
+ /**
45
+ * Returns associative array of filetype to icon mapping.
46
+ * @return array
47
+ */
48
+ public static function getFiletypeMapping() {
49
+ return self::$exts;
50
+ }
51
+
52
+ /**
53
+ * Takes associative array of filetype to icon mapping.
54
+ *
55
+ * NOTE: This is foundation work for allowing users to add their own
56
+ * filetypes in the future.
57
+ * @param array $new
58
+ */
59
+ public static function setFiletypeMapping($new) {
60
+ self::$exts = $new;
61
+ }
62
+
63
+ /**
64
+ * Returns HTML representing this Document.
65
+ * @return string
66
+ */
67
+ public function __toString() {
68
+ $icon = sprintf(self::$img_string, DG_Thumber::getDefaultThumbnail($this->ID),
69
+ $this->title_attribute, $this->title_attribute);
70
+ $core = sprintf(self::$doc_icon, $this->link, $icon, $this->title);
71
+
72
+ if($this->gallery->useDescriptions()) {
73
+ $core .= " <p>$this->description</p>" . PHP_EOL;
74
+ }
75
+
76
+ // users may filter icon here
77
+ return apply_filters('dg_doc_icon', $core, $this->ID);
78
+ }
79
+ }
80
+
81
+ ?>
models/class-gallery.php ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Description of Gallery
5
+ *
6
+ * @author drossiter
7
+ */
8
+ class DG_Gallery {
9
+ private $atts, $taxa;
10
+ private $docs = array();
11
+ private $errs = array();
12
+
13
+ private static $defaults = array(
14
+ // default: link directly to file (true to link to attachment pg)
15
+ 'attachment_pg' => FALSE,
16
+ 'descriptions' => FALSE,
17
+ // include thumbnail of actual document in gallery display
18
+ //'fancy_thumbs' => FALSE,
19
+ // comma-separated list of attachment ids
20
+ 'ids' => FALSE,
21
+ // if true, all images attached to current page will be included also
22
+ 'images' => FALSE,
23
+ 'localpost' => TRUE,
24
+ 'order' => 'ASC',
25
+ 'orderby' => 'menu_order',
26
+ // only relevant if tax_query used (WP >= 3.1)
27
+ 'relation' => 'AND'
28
+ );
29
+
30
+ // templates for HTML output
31
+ private static $no_docs = '<!-- No attachments to display. How boring! :( -->';
32
+ private static $icon_wrapper = false;
33
+ private static $comment = false;
34
+
35
+ /**
36
+ * Builds a gallery object with attributes passed.
37
+ * @param array $atts Array of attributes used in shortcode.
38
+ */
39
+ public function __construct($atts) {
40
+ // init templates for HTML output
41
+ if(self::$comment === false)
42
+ {
43
+ self::$comment =
44
+ PHP_EOL . '<!-- Generated using Document Gallery. Get yours here: ' .
45
+ 'http://wordpress.org/extend/plugins/document-gallery -->' . PHP_EOL;
46
+ self::$icon_wrapper = '<div class="%s">'. PHP_EOL . '%s</div>' . PHP_EOL;
47
+ }
48
+
49
+ // values used to construct tax query (may be empty)
50
+ $this->taxa = array_diff_key($atts, self::$defaults);
51
+
52
+ // all recognized attributes go here
53
+ $this->atts = shortcode_atts(self::$defaults, $atts);
54
+
55
+ // goes through all values in $this->atts, setting $this->errs as needed
56
+ $this->sanitizeDefaults();
57
+
58
+ // query DB for all documents requested
59
+ try {
60
+ $docs = $this->getDocuments();
61
+ include_once(DG_PATH . 'models/class-document.php');
62
+ foreach($docs as $doc) {
63
+ $this->docs[] = new DG_Document($doc, $this);
64
+ }
65
+ } catch(InvalidArgumentException $e) {
66
+ // errors will be printed in __toString()
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Gets all valid Documents based on the attributes passed by the user.
72
+ * @return array Contains all documents matching the query.
73
+ * @throws InvalidArgumentException Thrown when $this->errs is not empty.
74
+ */
75
+ private function getDocuments() {
76
+ $mime_types = array('application', 'video', 'text', 'audio');
77
+ if ($this->atts['images']) {
78
+ $mime_types[] = 'image';
79
+ }
80
+
81
+ $query = array(
82
+ 'numberposts' => -1,
83
+ 'orderby' => $this->atts['orderby'],
84
+ 'order' => $this->atts['order'],
85
+ 'post_status' => 'any',
86
+ 'post_type' => 'attachment',
87
+ 'post_mime_type' => implode(',', $mime_types));
88
+
89
+ $query['post_parent'] =
90
+ $this->atts['localpost']
91
+ && ($post = get_post()) ? $post->ID : '';
92
+
93
+ $this->setTaxa($query);
94
+
95
+ if(!empty($this->errs)) {
96
+ throw new InvalidArgumentException();
97
+ }
98
+
99
+ return ($this->atts['ids'] !== FALSE)
100
+ ? $this->getAttachmentsByIds()
101
+ : get_posts($query);
102
+ }
103
+
104
+ /**
105
+ * Cleans up user input, making sure we don't pass crap on to WP core.
106
+ * @global string $wp_version
107
+ */
108
+ private function sanitizeDefaults() {
109
+ global $wp_version;
110
+
111
+ if($this->atts['attachment_pg'] !== self::$defaults['attachment_pg']) {
112
+ $attachment_pg =
113
+ filter_var($this->atts['attachment_pg'],
114
+ FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
115
+
116
+ if($attachment_pg === null) {
117
+ $this->errs[] =
118
+ 'The attachment_pg parameter may only be \'true\' or \'false.\' ' .
119
+ "You entered {$this->atts['attachment_pg']}.";
120
+ } else {
121
+ $this->atts['attachment_pg'] = $attachment_pg;
122
+ }
123
+ }
124
+
125
+ if($this->atts['descriptions'] !== self::$defaults['descriptions']) {
126
+ $descriptions =
127
+ filter_var($this->atts['descriptions'],
128
+ FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
129
+
130
+ if($descriptions === null) {
131
+ $this->errs[] =
132
+ 'The descriptions parameter may only be \'true\' or \'false.\' ' .
133
+ "You entered {$this->atts['descriptions']}.";
134
+ } else {
135
+ $this->atts['descriptions'] = $descriptions;
136
+ }
137
+ }
138
+
139
+ if($this->atts['ids'] !== self::$defaults['ids']) {
140
+ if(strcasecmp('false', $this->atts['ids']) == 0) {
141
+ $this->atts['ids'] = FALSE;
142
+ } else {
143
+ $ids = explode(',', $this->atts['ids']);
144
+ $bad = array_filter($ids, array(__CLASS__, 'negativeInt'));
145
+
146
+ if(!empty($bad)) {
147
+ $this->errs[] =
148
+ 'The following ID(s) are not valid: ' .
149
+ implode(', ', $bad) . '.';
150
+ } else {
151
+ $this->atts['ids'] = $ids;
152
+ }
153
+ }
154
+ }
155
+
156
+ if($this->atts['images'] !== self::$defaults['images']) {
157
+ $images =
158
+ filter_var($this->atts['images'],
159
+ FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
160
+
161
+ if($images === null) {
162
+ $this->errs[] =
163
+ 'The images parameter may only be \'true\' or \'false.\' ' .
164
+ "You entered {$this->atts['images']}.";
165
+ } else {
166
+ $this->atts['images'] = $images;
167
+ }
168
+ }
169
+
170
+ if($this->atts['localpost'] !== self::$defaults['localpost']) {
171
+ $localpost =
172
+ filter_var($this->atts['localpost'],
173
+ FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
174
+ if($localpost === null) {
175
+ $this->errs[] =
176
+ 'The localpost parameter may only be \'true\' or \'false.\' ' .
177
+ "You entered {$this->atts['localpost']}.";
178
+ } else {
179
+ $this->atts['localpost'] = $localpost;
180
+ }
181
+ }
182
+
183
+ $order = strtoupper($this->atts['order']);
184
+ if('ASC' !== $order && 'DEC' !== $order) {
185
+ $this->errs[] =
186
+ 'The order parameter must be either \'ASC\' or \'DEC.\' '.
187
+ "You entered {$this->atts['order']}.";
188
+ }
189
+
190
+ $orderby = strtoupper($this->atts['orderby']) === 'ID'
191
+ ? 'ID' : strtolower($this->atts['orderby']);
192
+ if ($orderby !== 'ID' && $orderby !== 'menu_order'
193
+ && $orderby !== 'author' && $orderby !== 'title'
194
+ && $orderby !== 'name' && $orderby !== 'date'
195
+ && $orderby !== 'modified' && $orderby !== 'parent'
196
+ && $orderby !== 'rand' /* && $orderby !== 'meta_value' */
197
+ // check version-specific parameters
198
+ && version_compare($wp_version, '2.8', '>=') && $orderby !== 'none' /* && $orderby !== 'meta_value_num' */
199
+ && version_compare($wp_version, '2.9', '>=') && $orderby !== 'comment_count'
200
+ && version_compare($wp_version, '3.5', '>=') && $orderby !== 'post__in') {
201
+ $this->errs[] =
202
+ "The orderby parameter value entered, {$this->atts['orderby']}, " .
203
+ "is not valid in WP $wp_version.";
204
+ } else {
205
+ $this->atts['orderby'] = $orderby;
206
+ }
207
+
208
+ $relation = strtoupper($this->atts['relation']);
209
+ if ('AND' !== $relation && 'OR' !== $relation) {
210
+ $this->errs[] =
211
+ 'The relation parameter must be either \'AND\' or \'OR.\' ' .
212
+ "You entered {$this->atts['relation']}.";
213
+ } else {
214
+ $this->atts['relation'] = $relation;
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Returns whether to link to attachment pg.
220
+ * @return bool
221
+ */
222
+ public function linkToAttachmentPg() {
223
+ return $this->atts['attachment_pg'];
224
+ }
225
+
226
+ /**
227
+ * Returns whether descriptions should be included in output.
228
+ * @return bool
229
+ */
230
+ public function useDescriptions() {
231
+ return $this->atts['descriptions'];
232
+ }
233
+
234
+ /**
235
+ * Function loops through all attributes passed that did not match
236
+ * self::$defaults. If they are the name of a taxonomy, they are plugged
237
+ * into the query, otherwise $this->errs is appended with an error string.
238
+ * @global string $wp_version Determines which tax query to use.
239
+ * @param array $query Query to insert tax query into.
240
+ */
241
+ private function setTaxa(&$query) {
242
+ if(!empty($this->taxa)) {
243
+ global $wp_version;
244
+ $taxa = array();
245
+
246
+ // use preferred tax_query if supported
247
+ if (version_compare($wp_version, '3.1', '>=')) {
248
+ // only include relation if we have multiple taxa
249
+ if(count($this->taxa) > 1) {
250
+ $taxa['relation'] = $this->atts['relation'];
251
+ }
252
+
253
+ foreach ($this->taxa as $taxon => $terms) {
254
+ $terms = $this->getTermIdsByNames($taxon, explode(',', $terms));
255
+
256
+ $taxa[] = array(
257
+ 'taxonomy' => $taxon,
258
+ 'field' => 'id',
259
+ 'terms' => $terms
260
+ );
261
+ }
262
+
263
+ // create nested structure
264
+ $query['tax_query'] = $taxa;
265
+ } // fallback to deprecated {tax_name} => {term_slug} construct
266
+ elseif (version_compare($wp_version, '2.3', '>=')) {
267
+ foreach ($this->taxa as $taxon => $terms) {
268
+ $taxa[$taxon] = ($taxon == 'category')
269
+ ? implode(',', $this->getTermIdsByNames($taxon, explode(',', $terms)))
270
+ : implode(',', $this->getTermSlugsByNames($taxon, explode(',', $terms)));
271
+ }
272
+
273
+ $query = array_merge($taxa, $query);
274
+ } // WP < 2.3 not supported for category/custom taxa
275
+ else {
276
+ $this->errs[] = 'The following attributes are invalid: ' .
277
+ implode(', ', array_keys($this->taxa));
278
+ }
279
+ }
280
+ }
281
+
282
+
283
+ /**
284
+ * Returns an array of term ids when provided with a list of term names.
285
+ * Also appends an entry onto $errs if any invalid names are found.
286
+ * @param string $taxon
287
+ * @param array $term_names
288
+ * @param &array $errs
289
+ * @return array
290
+ */
291
+ private function getTermIdsByNames($taxon, $term_names) {
292
+ return $this->getTermXByNames('term_id', $taxon, $term_names);
293
+ }
294
+
295
+ /**
296
+ * Returns an array of term slugs when provided with a list of term names.
297
+ * Also appends an entry onto $errs if any invalid names are found.
298
+ * @param string $taxon
299
+ * @param array $term_names
300
+ * @param &array $errs
301
+ * @return array
302
+ */
303
+ private function getTermSlugsByNames($taxon, $term_names) {
304
+ return $this->getTermXByNames('slug', $taxon, $term_names);
305
+ }
306
+
307
+ /**
308
+ * (WP >= 2.3) Returns a list of x, where x may be any of the fields within a
309
+ * term object, when provided with a list of term names (not slugs).
310
+ * (http://codex.wordpress.org/Function_Reference/get_term_by#Return_Values)
311
+ *
312
+ * Also appends an entry onto $errs if any invalid names are found.
313
+ * @param string $x
314
+ * @param string $taxon
315
+ * @param array $term_names
316
+ * @param &array $errs
317
+ * @return array
318
+ */
319
+ private function getTermXByNames($x, $taxon, $term_names) {
320
+ $ret = array();
321
+
322
+ foreach ($term_names as $name) {
323
+ if (($term = get_term_by('name', $name, $taxon))) {
324
+ $ret[] = $term->{$x};
325
+ }
326
+ else {
327
+ $this->errs[] = "$name is not a valid term name in $taxon.";
328
+ }
329
+ }
330
+
331
+ return $ret;
332
+ }
333
+
334
+ /**
335
+ * Given a list of IDs, all attachments represented by these IDs are returned.
336
+ * @return array post objects
337
+ */
338
+ private function getAttachmentsByIds() {
339
+ $attachments = array();
340
+ foreach ($this->atts['ids'] as $id) {
341
+ $attachment = get_post($id);
342
+ if ($attachment->post_type === 'attachment')
343
+ $attachments[] = $attachment;
344
+ // else: not an attachment so skip
345
+ }
346
+
347
+ return $attachments;
348
+ }
349
+
350
+ /**
351
+ * Function returns false for positive ints, true otherwise.
352
+ * @param var $var could be anything.
353
+ * @return boolean indicating whether $var is not a positive int.
354
+ */
355
+ private static function negativeInt($var) {
356
+ return !is_numeric($var) // isn't numeric
357
+ || (int)$var != $var // isn't int
358
+ || (int)$var < 0; // isn't positive
359
+ }
360
+
361
+
362
+ /**
363
+ * Returns HTML representing this Gallery.
364
+ * @return string
365
+ */
366
+ public function __toString() {
367
+ if(!empty($this->errs)) {
368
+ return '<p>' . implode('</p><p>', $this->errs) . '</p>';
369
+ }
370
+
371
+ if(empty($this->docs)) {
372
+ return self::$no_docs;
373
+ }
374
+
375
+ $core = '';
376
+ $classes = array('document-icon-wrapper');
377
+ if($this->useDescriptions()) {
378
+ $classes[] = 'descriptions';
379
+ }
380
+
381
+ $icon_wrapper = sprintf(self::$icon_wrapper, implode(' ', $classes), '%s');
382
+
383
+ if($this->useDescriptions()) {
384
+ foreach($this->docs as $doc) {
385
+ $core .= sprintf($icon_wrapper, (string)$doc);
386
+ }
387
+ } else {
388
+ for($i = 0; $i < count($this->docs); $i+=4) {
389
+ $row = '';
390
+
391
+ $min = min($i+4, count($this->docs));
392
+ for($x = $i; $x < $min; $x++) {
393
+ $row .= (string)$this->docs[$x];
394
+ }
395
+
396
+ $core .= sprintf($icon_wrapper, $row);
397
+ }
398
+ }
399
+
400
+ return self::$comment . $core;
401
+ }
402
+ }
403
+
404
+ ?>
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Document Gallery ===
2
  Contributors: dan.rossiter
3
- Tags: attachments, icons, documents, gallery, ms office, doc, ppt, xls, docx, pptx, xlsx, pdf,openoffice
4
- Requires at least: 2.6
5
- Tested up to: 3.5.1
6
- Stable tag: 1.3.1
7
- License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
10
  This plugin allows the user to easily create a "gallery" of all non-image
@@ -12,19 +12,21 @@ attachments on a given post/page, making them easy to share.
12
 
13
  == Description ==
14
 
15
- This plugin allows the user to effortlessly include a gallery, much like a
16
- photo gallery, of all your non-image attachments anywhere within your post.
 
17
 
18
  The plugin will, by default, inherit the styling within your active theme, but
19
- with a little CSS knowledge it is easily modified to meet your specific needs.
 
20
 
21
  Read more in the **Installation** tab!
22
 
23
  = Developers =
24
 
25
- Document Gallery includes features intended to make integrating the plugin into
26
- the core of your theme or plugin very convenient. See the bottom of the
27
- **Installation** tab for specific documentation on the various features included.
28
 
29
  *If this plugin has helped you, please take a moment to [rate
30
  it](http://wordpress.org/support/view/plugin-reviews/document-gallery#postform)!*
@@ -33,23 +35,48 @@ it](http://wordpress.org/support/view/plugin-reviews/document-gallery#postform)!
33
 
34
  1. Upload `document-gallery` to the `/wp-content/plugins/` directory
35
  1. Activate the plugin through the 'Plugins' menu in WordPress
36
- 1. Place `[dg]` in any posts or pages you want a document gallery included. See
37
  below for additional display options.
38
 
39
  = Document Gallery Options =
40
 
41
- In order to include all compatible docuements from a given page or post, you
42
- must include the following shortcode in the post:
43
 
44
- `[dg descriptions=[true/false] orderby=[menu_order, title, date, author, rand]
45
- order=[ASC/DEC] attachment_pg=[true/false] images=[true/false]
46
- ids=[false/comma-separated list of id #s]]`
 
 
 
 
 
 
 
 
47
 
48
  **Default Values**
49
 
50
- By default, document gallery will use `descriptions=false`
51
- , `orderby=menu_order`, `order=ASC` , `attachment_pg=false`, `images=false`
52
- , and `ids=false` if you do not specify otherwise.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  **Descriptions Option**
55
 
@@ -59,45 +86,69 @@ alongside it.
59
  *Note: this will use the `description` field, **not** the `caption`. Be
60
  careful when entering your document data.*
61
 
62
- **Orderby Option**
63
-
64
- * `menu_order` - This is probably the one you want to use. Order by the
65
- integer fields in the Insert / Upload Media Gallery dialog. (Note that
66
- these fields may be blank by default. If this is the case, you must
67
- populate the fields before this option will work.
68
- * `title` - Alphabetical order based on title.
69
- * `date` - Order by date of document upload.
70
- * `author` - Order by the owner of the upload (username).
71
- * `rand` - Pseudo-random order.
72
-
73
  **Order Option**
74
 
75
- This option works alongsied the `orderby` option to determine whether the
76
- documents are displayed in ascending or decending order.
77
-
78
- **Attachment Page Option** *(New in Version 1.1)*
79
 
80
- This option determines whether each document icon will link to the actual file
81
- or to its attachment page. If you want the user to be able to click on the
82
- icon and directly rective the option to download then use
83
- `attachment_pg=false` (the default). If you have information on the attachment
84
- page that you want the link to go to, use `attachment_pg=true`.
85
-
86
- **Images** *(New in Version 1.2)*
87
 
88
- This option will tell the plugin to pull all images attached to to a page or
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  post in addition to all documents.
90
 
91
- **Ids** *(New in Version 1.2)*
92
 
93
  This is an advanced option intended for experienced WordPress users. If this
94
  option is used, the plugin will ignore attached documents, instead including
95
- all attachments defined by the ids attribute (e.g.: `ids=10,2,4,42`).
96
 
97
- *Note: If this attribute is used, the `order`, `orderby`, and `images`
98
- attributes will be ignored. Order is defined by the order the ids are
 
99
  provided.*
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  = Customize Appearance =
102
 
103
  By default, the document gallery will use the styles within your active theme
@@ -108,7 +159,7 @@ for an idea of what will select different elements within the gallery display.
108
 
109
  **Example**
110
 
111
- Say I would like to include a border for the right and bottom of thedocument
112
  icon, but only when descriptions are shown (to deliniate the icon from the
113
  description text). To do this, I would need to add the following CSS to my
114
  theme stylesheet:
@@ -129,7 +180,8 @@ be lost when a new version is released.*
129
 
130
  = Developers =
131
 
132
- **Filter document-icon Content**
 
133
  For those unfamiliar with content filters, [here is some
134
  documentation](http://codex.wordpress.org/Plugin_API/Filter_Reference) that you
135
  should read before continuing.
@@ -143,12 +195,12 @@ modify any of this content before it reaches your users.
143
  Any function using this filter will receive two parameters, the content to be
144
  filtered and the ID number of the file represented by the icon in question.
145
  If you are implementing something to override the plugin default functionality,
146
- it may be useful to be able to query various attributes of the attachment with
147
  this value.
148
 
149
  One example use for this filter, which I have personally used in a project I
150
- am working on, will add a query parameter to the end of each attachment url.
151
- This parameter, `rid`, specifies the refering page and allows the page
152
  receiving the URL to dynamically detect which page ID the link came from.
153
 
154
  `function dg_doc_icon( $icon, $id ){
@@ -159,14 +211,14 @@ receiving the URL to dynamically detect which page ID the link came from.
159
 
160
  if( strpos( $matches[2], '?' ) !== false )
161
  return "{$matches[1]}{$matches[2]}&rid=".get_the_ID().$matches[3];
162
-
163
  return "{$matches[1]}{$matches[2]}?rid=".get_the_ID().$matches[3];
164
  }
165
  add_filter( 'dg_doc_icon', 'dg_doc_icon', null, 2 );`
166
 
167
  Obviously this is just one very specific example, but anything that requires
168
  modifying the image tag, the anchor tag, or the title can be handled with this
169
- filter. Note that this function does not use the $id value it receives, which
170
  is perfectly alright.
171
 
172
  == Screenshots ==
@@ -174,11 +226,11 @@ is perfectly alright.
174
  1. This is an example of multiple Document Galleries on a single page (using
175
  the `ids` attribute). It also shows how images will appear in a Document
176
  Gallery. Note that the description field supports HTML markup, so the
177
- possibilites are endless!
178
- 2. This is how the Document Gallery looks with `descriptions=true`. The
179
- descriptions are auto-populated using the description field from when you
180
  upload the document.
181
- 3. This is how the Document Gallery looks with `descriptions=false` (default).
182
  Note that the display inherits styling from your active theme.
183
 
184
  == Changelog ==
@@ -187,14 +239,48 @@ Note that the display inherits styling from your active theme.
187
 
188
  * Full integration with the new [Wordpress 3.5 Media
189
  Manager](http://codex.wordpress.org/Version_3.5#Highlights).
190
- * Option to include player for any music or video attachments uploaded to page.
191
- * Option to open documents directly within your browser (&#224; la [Google Drive
192
  Viewer](https://drive.google.com/viewer)).
193
  * Support for adding your own filetypes/icons.
194
  * Whatever else **you** would like (post on the [support
195
  forum](http://wordpress.org/support/plugin/document-gallery) if you have
196
  ideas)!
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  = 1.3.1 =
199
 
200
  * **Bug Fix:** This resolves a bug introduced in version `1.3`. (Thanks to JKChad
@@ -204,14 +290,14 @@ Note that the display inherits styling from your active theme.
204
 
205
  * **New Feature:** It is now possible to filter the HTML produced to represent
206
  each individual icon, making it possible to add extra attributes and other
207
- modifications on the fly as document icons are generated. This will probably
208
- only be of use to developers and people who don't mind getting their hands
209
  dirty. *(See bottom **Installation** tab for more details.)*
210
  * **Enhancement:** There have been a lot of optimizations to the underlying
211
  plugin code to make it run more efficiently and be easier to read, if you
212
  are so inclined.
213
- * **Enhancement:** Changed how images, when included within the gallery, are
214
- generated so that the format of the icon returned now matches the rest of
215
  the icons.
216
 
217
  = 1.2.1 =
@@ -225,7 +311,7 @@ Note that the display inherits styling from your active theme.
225
  document gallery (using `images=true` attribute).
226
  (Thanks for the suggestion, Luca!)
227
  * **New Feature:** Attachment ids can now be explicitly listed, allowing for
228
- documents not attached to a post or page to be included in a document
229
  gallery (e.g.: `ids=2,42,57,1`). Note that no spaces should be included.
230
  * **Enhancement:** The CSS stylesheet has been enhanced for more flexibility
231
  in sizing icons.
@@ -235,7 +321,7 @@ Note that the display inherits styling from your active theme.
235
  * **New Feature:** Included option to link to the attachment page as well as
236
  to the actual document.
237
  * **Enhancement:** Added documentation for customizing the appearance of the plugin.
238
- * **Enhancement:** Many improvements to the backend, including pretty HTML output
239
  and best practice implementation in calls to WordPress core functions.
240
 
241
  = 1.0.4 =
@@ -258,16 +344,15 @@ Note that the display inherits styling from your active theme.
258
 
259
  = 1.0.1 =
260
 
261
- * **Bug Fix:** Resolved issue with long document titles being cut off in some
262
- * themes.
263
 
264
  = 1.0 =
265
 
266
  * **New Feature:** Plugin now has **36 icons** representing **72 filetypes**!
267
  * **Enhancement:** Optimized gallery generation (faster!)
268
- * **Enhancement:** Added fallback to WordPress default icons if you happen to
269
  include one of the few filetypes not yet supported.
270
- * **Enhancement:** Changed shortcode to `[dg]` (`[document gallery]` will still
271
  work for backward compatibility).
272
  * **Enhancement:** Gave documentation some **much needed** revisions.
273
 
@@ -279,6 +364,7 @@ Note that the display inherits styling from your active theme.
279
  = 0.8 =
280
 
281
  * **Release:** First public release of Document Gallery.
282
- * **Feature:** Displays PDF, Word, PowerPoint, Excel, and ZIP documents from a
283
- given page or post. **Feature:** Documents can be ordered by a number of
284
- different factors.
 
1
  === Document Gallery ===
2
  Contributors: dan.rossiter
3
+ Tags: attachments, icons, documents, gallery, MS office, pdf
4
+ Requires at least: 3.5
5
+ Tested up to: 3.8
6
+ Stable tag: 1.4.3
7
+ License: GPLv2
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
10
  This plugin allows the user to easily create a "gallery" of all non-image
12
 
13
  == Description ==
14
 
15
+ This plugin allows the user to effortlessly create a gallery of documents and
16
+ other attached media, much like the gallery option already available for image
17
+ attachments.
18
 
19
  The plugin will, by default, inherit the styling within your active theme, but
20
+ with a little CSS knowledge it is possible to customize the appearance to meet
21
+ your specific needs.
22
 
23
  Read more in the **Installation** tab!
24
 
25
  = Developers =
26
 
27
+ Document Gallery includes features intended to make integration with other plugins
28
+ simple. See the bottom of the **Installation** tab for specific documentation on
29
+ the various features provided.
30
 
31
  *If this plugin has helped you, please take a moment to [rate
32
  it](http://wordpress.org/support/view/plugin-reviews/document-gallery#postform)!*
35
 
36
  1. Upload `document-gallery` to the `/wp-content/plugins/` directory
37
  1. Activate the plugin through the 'Plugins' menu in WordPress
38
+ 1. Place `[dg]` in any posts or pages you want a document gallery included. See
39
  below for additional display options.
40
 
41
  = Document Gallery Options =
42
 
43
+ In order to include all compatible documents from a given page or post, you
44
+ must include the following shortcode in the post: `[dg]`.
45
 
46
+ In addition to the default behavior, the plugin provides many options to
47
+ customize behavior with various attributes, seen below:
48
+
49
+ `[dg [attachment_pg=<true/false>]
50
+ [category/custom_taxon_name=<**comma-separated list of taxon values**> [relation=<AND/OR>]]
51
+ [descriptions=<true/false>] [ids=<**comma-separated list of ID #s**>]
52
+ [images=<true/false>] [localpost=<true/false>] [order=<ASC/DEC>] [orderby=<**see below**>]]`
53
+
54
+ Though the shortcode above may seem far from "short," none of the attributes are
55
+ required and most users will find that the plugin meets your needs "out of the box"
56
+ without any added attributes.
57
 
58
  **Default Values**
59
 
60
+ By default, document gallery will use `no descriptions`, `orderby menu_order`
61
+ , `ASC order`, `no attachment_pg links`, and `no images` from the `local post`
62
+ if you do not specify otherwise.
63
+
64
+ **Attachment Page Option** *(New in Version 1.1)*
65
+
66
+ This option determines whether each document icon will link to the actual file
67
+ or to its attachment page. If you want the user to be able to click on the
68
+ icon and directly rective the option to download then use `attachment_pg=false`
69
+ (the default). If you have information on the attachment page that you want the
70
+ link to go to, use `attachment_pg=true`.
71
+
72
+ **Categories/Custom Taxonomy Option** *(New in Version 1.4)*
73
+
74
+ With the `categories` option you are able to select attachments based on
75
+ their assigned category or any other
76
+ [custom taxon](http://codex.wordpress.org/Taxonomies). Categories
77
+ or any custom taxon can be referenced simply by including `category=category_value`
78
+ or `taxon_name=taxon_value`. Multiple values for a single taxon may be separated
79
+ by commas.
80
 
81
  **Descriptions Option**
82
 
86
  *Note: this will use the `description` field, **not** the `caption`. Be
87
  careful when entering your document data.*
88
 
 
 
 
 
 
 
 
 
 
 
 
89
  **Order Option**
90
 
91
+ This option works alongside the `orderby` option to determine whether the
92
+ documents are displayed in ascending or descending order.
 
 
93
 
94
+ **Orderby Option**
 
 
 
 
 
 
95
 
96
+ * `menu_order` - This is probably the one you want to use. Menu order is
97
+ the order that icons appear when seen in the Insert / Upload Media Gallery
98
+ dialog. To change this order, you simply drag the icons around until they
99
+ are where you want them. In earlier versions of WordPress, menu_order was
100
+ modified by the integer fields in the Insert / Upload Media Gallery dialog.
101
+ These fields no longer exist in recent releases.
102
+ * `title` - Order by title.
103
+ * `date` - Order by upload date.
104
+ * `modified` - Order by last modified date.
105
+ * `rand` - Random order.
106
+ * `ID` - Order by post id.
107
+ * `author` - Order by author.
108
+ * `name` - Order by attachment slug.
109
+ * `parent` - Order by post/page parent id.
110
+ (Only useful in conjunction with `localpost=false` option.)
111
+ * `comment_count` - Order by number of comments (available with WP >= 2.9).
112
+ * `none` - No order (available with Version 2.8).
113
+ * `post__in` - Preserve post ID order given in the post__in array (available
114
+ with WP >= 3.5).
115
+
116
+ **Images Option** *(New in Version 1.2)*
117
+
118
+ This option will tell the plugin to include all images attached to to a page or
119
  post in addition to all documents.
120
 
121
+ **IDs Option** *(New in Version 1.2)*
122
 
123
  This is an advanced option intended for experienced WordPress users. If this
124
  option is used, the plugin will ignore attached documents, instead including
125
+ all attachments defined by the `ids` attribute (e.g.: `ids=10,2,4,42`).
126
 
127
+ *Note: If this attribute is used, the `order`, `orderby`, `images` and other
128
+ attributes which generally determine which attachments to include or how to
129
+ order them will be ignored. Order is defined by the order the ids are
130
  provided.*
131
 
132
+ **Localpost Option** *(New in Version 1.4)*
133
+
134
+ By default a document gallery only looks at attachments of the page/post where
135
+ the `[dg]` shortcode is used. If you would like to search beyond that local scope,
136
+ you must set `localpost=false`.
137
+
138
+ This option would probably be useful especially when querying with the *category
139
+ or taxonomy* option, though it can be used with any options you chose.
140
+
141
+ **Relation Option** *(New in Version 1.4)*
142
+
143
+ The relation option should only be used when also using the *category or custom
144
+ taxonomy* option (see above). Additionally, this option is only effective in
145
+ WordPress installs version 3.1 or higher. Older versions cannot use this value
146
+ and will ignore it.
147
+
148
+ When using multiple taxa, this option allows you to decide whether the attachments
149
+ returned must meet all of the taxa_names specified (AND) or a minimum of one
150
+ match (OR).
151
+
152
  = Customize Appearance =
153
 
154
  By default, the document gallery will use the styles within your active theme
159
 
160
  **Example**
161
 
162
+ Say I would like to include a border for the right and bottom of the document
163
  icon, but only when descriptions are shown (to deliniate the icon from the
164
  description text). To do this, I would need to add the following CSS to my
165
  theme stylesheet:
180
 
181
  = Developers =
182
 
183
+ **Filter .document-icon Content**
184
+
185
  For those unfamiliar with content filters, [here is some
186
  documentation](http://codex.wordpress.org/Plugin_API/Filter_Reference) that you
187
  should read before continuing.
195
  Any function using this filter will receive two parameters, the content to be
196
  filtered and the ID number of the file represented by the icon in question.
197
  If you are implementing something to override the plugin default functionality,
198
+ it may be useful to be able to query various attributes of the attachment with
199
  this value.
200
 
201
  One example use for this filter, which I have personally used in a project I
202
+ am working on, will add a query parameter to the end of each attachment URL.
203
+ This parameter, `rid`, specifies the referring page and allows the page
204
  receiving the URL to dynamically detect which page ID the link came from.
205
 
206
  `function dg_doc_icon( $icon, $id ){
211
 
212
  if( strpos( $matches[2], '?' ) !== false )
213
  return "{$matches[1]}{$matches[2]}&rid=".get_the_ID().$matches[3];
214
+
215
  return "{$matches[1]}{$matches[2]}?rid=".get_the_ID().$matches[3];
216
  }
217
  add_filter( 'dg_doc_icon', 'dg_doc_icon', null, 2 );`
218
 
219
  Obviously this is just one very specific example, but anything that requires
220
  modifying the image tag, the anchor tag, or the title can be handled with this
221
+ filter. Note that this function does not use the $id value it receives, which
222
  is perfectly alright.
223
 
224
  == Screenshots ==
226
  1. This is an example of multiple Document Galleries on a single page (using
227
  the `ids` attribute). It also shows how images will appear in a Document
228
  Gallery. Note that the description field supports HTML markup, so the
229
+ possibilities are endless!
230
+ 2. This is how the Document Gallery looks with `descriptions=true`. The
231
+ descriptions are auto-populated using the description field from when you
232
  upload the document.
233
+ 3. This is how the Document Gallery looks with `descriptions=false` (default).
234
  Note that the display inherits styling from your active theme.
235
 
236
  == Changelog ==
239
 
240
  * Full integration with the new [Wordpress 3.5 Media
241
  Manager](http://codex.wordpress.org/Version_3.5#Highlights).
242
+ * Option to open music or video files directly from your gallery.
243
+ * Option to open documents directly from your gallery (&#224; la [Google Drive
244
  Viewer](https://drive.google.com/viewer)).
245
  * Support for adding your own filetypes/icons.
246
  * Whatever else **you** would like (post on the [support
247
  forum](http://wordpress.org/support/plugin/document-gallery) if you have
248
  ideas)!
249
 
250
+ = 1.4.3 =
251
+ * **Bug Fix:** Resolves minor bug introduced in version 1.4.2. Thanks, tkokholm!
252
+
253
+ = 1.4.2 =
254
+ * **Note:** This release includes an increase in the minimum WP version to 3.5.
255
+ If you have not yet upgraded to at least this version, you should consider doing
256
+ so as future releases include a number of *fantastic* new features as well as
257
+ many security improvements. If you chose not to upgrade, you must stay with
258
+ Document Gallery 1.4.1 or lower until you do. Sorry for the inconvenience!
259
+ * **Bug Fix:** Resolved icons being displayed differently depending on which
260
+ user was currently logged in. (Thanks to
261
+ [Sean](http://wordpress.org/support/topic/error-after-update-19?replies=12#post-5041251)
262
+ for reporting the issue.)
263
+ * **Enhancement:** A number of new icons were added (mainly for the iWork suite
264
+ and source code filetypes) and a number of pre-existing icons were removed if
265
+ they were very similar to another icon.
266
+ * **Under The Hood:** Many, many cool things. Stay tuned for a big reveal in the
267
+ coming weeks!
268
+ PS: If you're really curious, there are some clues in the source code ;)
269
+
270
+ = 1.4.1 =
271
+ * **Bug Fix:** This resolves a bug introduced in `1.4`, which caused a warning
272
+ to be thrown when no attributes were used (i.e.: `[dg]`). (Thanks to
273
+ [wtfbingo](http://wordpress.org/support/topic/error-after-update-19) for
274
+ pointing this out!)
275
+
276
+ = 1.4 =
277
+
278
+ * **New Feature:** This release features the addition of *category/taxonomy* support,
279
+ [as suggested by Pyo](http://wordpress.org/support/topic/sorting-documents-by-categorytag-or-other-taxonomy).
280
+ * **Under The Hood:** The plugin was completely rewritten for this release. Logic
281
+ was cleaned up to make maintenance easier and facilitate some *big* changes
282
+ planned for version 2.0 of Document Gallery.
283
+
284
  = 1.3.1 =
285
 
286
  * **Bug Fix:** This resolves a bug introduced in version `1.3`. (Thanks to JKChad
290
 
291
  * **New Feature:** It is now possible to filter the HTML produced to represent
292
  each individual icon, making it possible to add extra attributes and other
293
+ modifications on the fly as document icons are generated. This will probably
294
+ only be of use to developers and people who don't mind getting their hands
295
  dirty. *(See bottom **Installation** tab for more details.)*
296
  * **Enhancement:** There have been a lot of optimizations to the underlying
297
  plugin code to make it run more efficiently and be easier to read, if you
298
  are so inclined.
299
+ * **Enhancement:** Changed how images, when included within the gallery, are
300
+ generated so that the format of the icon returned now matches the rest of
301
  the icons.
302
 
303
  = 1.2.1 =
311
  document gallery (using `images=true` attribute).
312
  (Thanks for the suggestion, Luca!)
313
  * **New Feature:** Attachment ids can now be explicitly listed, allowing for
314
+ documents not attached to a post or page to be included in a document
315
  gallery (e.g.: `ids=2,42,57,1`). Note that no spaces should be included.
316
  * **Enhancement:** The CSS stylesheet has been enhanced for more flexibility
317
  in sizing icons.
321
  * **New Feature:** Included option to link to the attachment page as well as
322
  to the actual document.
323
  * **Enhancement:** Added documentation for customizing the appearance of the plugin.
324
+ * **Enhancement:** Many improvements to the backend, including pretty HTML output
325
  and best practice implementation in calls to WordPress core functions.
326
 
327
  = 1.0.4 =
344
 
345
  = 1.0.1 =
346
 
347
+ * **Bug Fix:** Resolved issue with long document titles being cut off in some themes.
 
348
 
349
  = 1.0 =
350
 
351
  * **New Feature:** Plugin now has **36 icons** representing **72 filetypes**!
352
  * **Enhancement:** Optimized gallery generation (faster!)
353
+ * **Enhancement:** Added fallback to WordPress default icons if you happen to
354
  include one of the few filetypes not yet supported.
355
+ * **Enhancement:** Changed shortcode to `[dg]` (`[document gallery]` will still
356
  work for backward compatibility).
357
  * **Enhancement:** Gave documentation some **much needed** revisions.
358
 
364
  = 0.8 =
365
 
366
  * **Release:** First public release of Document Gallery.
367
+ * **Feature:** Displays PDF, Word, PowerPoint, Excel, and ZIP documents from a
368
+ given page or post.
369
+ * **Feature:** Documents can be ordered by a number of
370
+ different factors.
style.css CHANGED
@@ -25,7 +25,7 @@ div.document-icon{
25
  div.document-icon-wrapper{
26
  width: 100%;
27
  padding: 0;
28
- text-align: center;
29
  }
30
  /* END WITHOUT DESCRIPTION */
31
 
25
  div.document-icon-wrapper{
26
  width: 100%;
27
  padding: 0;
28
+ text-align: left;
29
  }
30
  /* END WITHOUT DESCRIPTION */
31
 
util/class-thumber.php ADDED
@@ -0,0 +1,604 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Thumber wraps the functionality required to
5
+ * generate thumbnails for arbitrary documents.
6
+ *
7
+ * @author drossiter
8
+ */
9
+ class DG_Thumber {
10
+ /**
11
+ * Blocks instantiation. All functionality is static.
12
+ */
13
+ private function __construct() {
14
+
15
+ }
16
+
17
+ /**
18
+ * Wraps generation of thumbnails for various attachment filetypes.
19
+ *
20
+ * @filter dg_thumbers Allows developers to filter the Thumbers used
21
+ * for specific filetypes. Index is the regex to match file extensions
22
+ * supported and the value is anything that can be accepted by call_user_func().
23
+ * The function must take two parameters, 1st is the int ID of the attachment
24
+ * to get a thumbnail for, 2nd is the page to take a thumbnail of
25
+ * (may not be relevant for some filetypes).
26
+ *
27
+ * NOTE: Last thumber in array *must* match ALL extensions (i.e.: ".*")
28
+ *
29
+ * @param type $ID Document ID
30
+ * @return string URL to the thumbnail.
31
+ */
32
+ public static function getThumbnail($ID, $pg = 1) {
33
+ static $thumbers = array();
34
+
35
+ if (!$thumbers) {
36
+ global $wp_version;
37
+
38
+ // Audio/Video embedded images
39
+ if (version_compare($wp_version, '3.6', '>=')) {
40
+ $exts = implode('|', self::getAudioVideoExts());
41
+ $thumbers[$exts] = array('Thumber', 'getAudioVideoThumbnail');
42
+ }
43
+
44
+ // Ghostscript
45
+ if (self::isGhostscriptAvailable()) {
46
+ $exts = implode('|', self::getGhostscriptExts());
47
+ $thumbers[$exts] = array('Thumber', 'getGhostscriptThumbnail');
48
+ }
49
+
50
+ // Imagick
51
+ if (call_user_func(array( 'WP_Image_Editor_Imagick', 'test'))) {
52
+ try {
53
+ $exts = @Imagick::queryFormats();
54
+ if($exts) {
55
+ $exts = implode('|', $exts);
56
+ $thumbers[$exts] = array('Thumber', 'getImagickThumbnail');
57
+ }
58
+ }
59
+ catch (Exception $e) {
60
+
61
+ }
62
+ }
63
+
64
+ // Google Drive Viewer
65
+ $exts = implode('|', self::getGoogleDriveExts());
66
+ $thumbers[$exts] = array('Thumber', 'getGoogleDriveThumbnail');
67
+
68
+ // match everything that falls through to the end
69
+ $thumbers['.*'] = array('Thumber', 'getDefaultThumbnail');
70
+
71
+ // allow users to filter thumbers used
72
+ $thumbers = apply_filter('dg_thumbers', $thumbers);
73
+
74
+ // strip out anything that can't be called
75
+ $thumbers = array_filter($thumbers, 'is_callable');
76
+ }
77
+
78
+ // if we haven't saved a thumb, generate one
79
+ if(!($url = wp_get_attachment_thumb_url($ID))) {
80
+ $file = get_attached_file($ID);
81
+
82
+ foreach ($thumbers as $ext_preg => $thumber) {
83
+ $ext_preg = '!\.(\.' . $ext_preg . ')$!i';
84
+
85
+ if (preg_match($ext_preg, $file) // can handle ext
86
+ && ($url = call_user_func($thumber, $ID, $pg))) { // is vaild return
87
+ break;
88
+ }
89
+ }
90
+ }
91
+
92
+ return $url;
93
+ }
94
+
95
+ /**
96
+ * Uses wp_read_video_metadata() and wp_read_audio_metadata() to retrieve
97
+ * an embedded image to use as a thumbnail.
98
+ *
99
+ * NOTE: Caller must verify that WP version >= 3.6.
100
+ *
101
+ * @param string $ID The attachment ID to retrieve thumbnail from.
102
+ * @param int $pg Unused.
103
+ * @return bool|string False on failure, URL to thumb on success.
104
+ */
105
+ public static function getAudioVideoThumbnail($ID, $pg = 1) {
106
+ $attachment = get_post($ID);
107
+ $doc_path = get_attached_file($ID);
108
+
109
+ if (preg_match('#^video/#', get_post_mime_type($attachment))) {
110
+ $metadata = wp_read_video_metadata($doc_path);
111
+ }
112
+ elseif (preg_match('#^audio/#', get_post_mime_type($attachment))) {
113
+ $metadata = wp_read_audio_metadata($doc_path);
114
+ }
115
+
116
+ // unsupported mime type || no embedded image present
117
+ if(!isset($metadata) || empty($metadata['image']['data'])) {
118
+ return false;
119
+ }
120
+
121
+ self::deleteExistingThumb($ID);
122
+
123
+ $ext = '.jpg';
124
+ switch ($metadata['image']['mime']) {
125
+ case 'image/gif':
126
+ $ext = '.gif';
127
+ break;
128
+ case 'image/png':
129
+ $ext = '.png';
130
+ break;
131
+ }
132
+
133
+ $dirname = dirname($doc_path);
134
+ $basename = basename($doc_path);
135
+
136
+ $thumb_name = self::getUniqueThumbName(
137
+ $dirname, substr($basename, 0, strrpos($basename, '.')), $ext);
138
+ $thumb_path = $dirname . DIRECTORY_SEPARATOR . $thumb_name;
139
+
140
+ // TODO: This doesn't work... Need alternate to wp_upload_bits()
141
+ $uploaded = wp_upload_bits($thumb_path, null, $metadata['image']['data']);
142
+
143
+ if (false !== $uploaded['error']) {
144
+ if (WP_DEBUG) {
145
+ error_log("DG: Failed to save AV thumbnail: " . $uploaded['error']);
146
+ }
147
+
148
+ return false;
149
+ }
150
+
151
+ self::fixNewThumb($uploaded['file']);
152
+
153
+ // store reference to new thumbnail
154
+ wp_update_attachment_metadata($ID, array('thumb' => $thumb_name));
155
+
156
+ return $uploaded['url'];
157
+ }
158
+
159
+ /**
160
+ * Uses WP_Image_Editor_Imagick to generate thumbnails.
161
+ *
162
+ * NOTE: Caller must verify that Imagick is present and that the extension is supported.
163
+ *
164
+ * @param string $ID The attachment ID to retrieve thumbnail from.
165
+ * @param int $pg Unused.
166
+ * @return bool|string False on failure, URL to thumb on success.
167
+ */
168
+ public static function getImagickThumbnail($ID, $pg = 1) {
169
+ $doc_path = get_attached_file($ID);
170
+
171
+ $img = wp_get_image_editor($doc_path);
172
+ if(is_wp_error($img)) {
173
+ return false;
174
+ }
175
+
176
+ $doc_url = wp_get_attachment_url($ID);
177
+ $dirname = dirname($doc_path);
178
+ $basename = basename($doc_path);
179
+
180
+ self::deleteExistingThumb($ID);
181
+
182
+ $thumb_name = self::getUniqueThumbName(
183
+ $dirname, substr($basename, 0, strrpos($basename, '.')));
184
+ $thumb_path = $dirname . DIRECTORY_SEPARATOR . $thumb_name;
185
+
186
+ $img->resize(150, 150, false);
187
+ $img->save($thumb_path);
188
+
189
+ // ensure perms are correct
190
+ $stat = stat($dirname);
191
+ $perms = $stat['mode'] & 0000666;
192
+ @chmod($thumb_path, $perms);
193
+
194
+ // store reference to new thumbnail
195
+ wp_update_attachment_metadata($ID, array('thumb' => $thumb_name));
196
+
197
+ // return URL pointing to new thumbnail
198
+ return preg_replace('#'.preg_quote($basename).'$#', $thumb_name, $doc_url);
199
+ }
200
+
201
+ /**
202
+ * Get thumbnail for document with given ID using Ghostscript. Imagick could
203
+ * also handle this, but is *much* slower.
204
+ *
205
+ * NOTE: Caller must verify that exec and gs are available and that extension is supported.
206
+ *
207
+ * @param string $ID The attachment ID to retrieve thumbnail from.
208
+ * @param int $pg The page number to make thumbnail of -- index starts at 1.
209
+ * @return bool|string False on failure, URL to thumb on success.
210
+ */
211
+ public static function getGhostscriptThumbnail($ID, $pg = 1) {
212
+ static $gs = false;
213
+ if (!$gs) {
214
+ // I don't understand why anyone would run a Windows server...
215
+ $gs = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? 'gswin32c' : 'gs')
216
+ . ' -sDEVICE=png16m -dFirstPage=%d -dLastPage=%d -dBATCH'
217
+ . ' -dNOPAUSE -dPDFFitPage -sOutputFile=%s %s';
218
+ }
219
+
220
+ $doc_path = get_attached_file($ID);
221
+ $doc_url = wp_get_attachment_url($ID);
222
+ $dirname = dirname($doc_path);
223
+ $basename = basename($doc_path);
224
+
225
+ self::deleteExistingThumb($ID);
226
+
227
+ $thumb_name = self::getUniqueThumbName(
228
+ $dirname, substr($basename, 0, strrpos($basename, '.')));
229
+ $thumb_path = $dirname . DIRECTORY_SEPARATOR . $thumb_name;
230
+
231
+ exec(sprintf($gs, $pg, $pg, $thumb_path, $doc_path), $out, $ret);
232
+
233
+ if ($ret != 0) {
234
+ error_log('DG: Ghostscript failed: ' . $out);
235
+ @unlink($thumb_path);
236
+ return false;
237
+ }
238
+
239
+ self::fixNewThumb($thumb_path);
240
+
241
+ // store reference to new thumbnail
242
+ wp_update_attachment_metadata($ID, array('thumb' => $thumb_name));
243
+
244
+ // return URL pointing to new thumbnail
245
+ return preg_replace('#'.preg_quote($basename).'$#', $thumb_name, $doc_url);
246
+ }
247
+
248
+ /**
249
+ * Get thumbnail for document with given ID from Google Drive Viewer.
250
+ *
251
+ * NOTE: Caller must verify that extension is supported.
252
+ *
253
+ * @param string $ID The attachment ID to retrieve thumbnail from.
254
+ * @param int $pg The page number to make thumbnail of -- index starts at 1.
255
+ * @return bool|string False on failure, URL to thumb on success.
256
+ */
257
+ public static function getGoogleDriveThumbnail($ID, $pg = 1) {
258
+ // User agent for Lynx 2.8.7rel.2 -- Why? Because I can.
259
+ static $user_agent = "Lynx/2.8.7rel.2 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/1.0.0a";
260
+ static $timeout = 90;
261
+
262
+ $exts = self::getGoogleDriveExts();
263
+ $google_viewer = "https://docs.google.com/viewer?url=%s&a=bi&pagenumber=%d&w=%d";
264
+ $doc_path = get_attached_file($ID);
265
+ $doc_url = wp_get_attachment_url($ID);
266
+ $basename = basename($doc_path);
267
+ $dirname = dirname($doc_path);
268
+
269
+ // check whether filetype supported by Google Drive Viewer
270
+ if (!in_array(strtolower(self::getExt($basename)), $exts))
271
+ return false;
272
+
273
+ self::deleteExistingThumb($ID);
274
+
275
+ $thumb_name = self::getUniqueThumbName(
276
+ $dirname, substr($basename, 0, strrpos($basename, '.')));
277
+ $thumb_path = $dirname . DIRECTORY_SEPARATOR . $thumb_name;
278
+
279
+ // args for use in HTTP request
280
+ $args = array(
281
+ 'timeout' => $timeout, // these requests can take a LONG time
282
+ 'redirection' => 5,
283
+ 'httpversion' => '1.0',
284
+ 'user-agent' => self::$user_agent,
285
+ 'blocking' => true,
286
+ 'headers' => array(),
287
+ 'cookies' => array(),
288
+ 'body' => null,
289
+ 'compress' => false,
290
+ 'decompress' => true,
291
+ 'sslverify' => true,
292
+ 'stream' => true,
293
+ 'filename' => $thumb_path
294
+ );
295
+
296
+ // prevent PHP timeout before HTTP completes
297
+ set_time_limit($timeout);
298
+
299
+ $google_viewer = sprintf($google_viewer, urlencode($doc_url), (int) $pg, 150);
300
+
301
+ // get thumbnail from Google Drive Viewer & check for error on return
302
+ $response = wp_remote_get($google_viewer, $args);
303
+
304
+ if (is_wp_error($response) || $response['response']['code'] != 200) {
305
+ error_log('DG: Failed to retrieve thumbnail from Google: ' .
306
+ (is_wp_error($response)
307
+ ? $response->get_error_message()
308
+ : $response['response']['message']));
309
+
310
+ @unlink($thumb_path);
311
+ return false;
312
+ }
313
+
314
+ self::fixNewThumb($thumb_path);
315
+
316
+ // store reference to new thumbnail
317
+ wp_update_attachment_metadata($ID, array('thumb' => $thumb_name));
318
+
319
+ // return URL pointing to new thumbnail
320
+ return preg_replace('#'.preg_quote($basename).'$#', $thumb_name, $doc_url);
321
+ }
322
+
323
+ /**
324
+ * Get thumbnail for document with given ID from default images.
325
+ *
326
+ * @param string $ID The attachment ID to retrieve thumbnail from.
327
+ * @param int $pg Unused.
328
+ * @return string URL to thumbnail.
329
+ */
330
+ public static function getDefaultThumbnail($ID, $pg = 1) {
331
+ $icon_url = DG_URL . 'icons/';
332
+
333
+ $url = wp_get_attachment_url($ID);
334
+ $ext = self::getExt(basename($url));
335
+
336
+ // handle images
337
+ if (wp_attachment_is_image($ID) &&
338
+ ($icon = wp_get_attachment_image_src($ID, 'thumbnail', false))) {
339
+ $icon = $icon[0];
340
+ }
341
+ // default extension icon
342
+ elseif ($name = self::getDefaultIcon($ext)) {
343
+ $icon = $icon_url . $name;
344
+ }
345
+ // fallback to standard WP icons
346
+ elseif ($icon = wp_get_attachment_image_src($ID, null, true)) {
347
+ $icon = $icon[0];
348
+ }
349
+ // everything failed. This is bad...
350
+ else {
351
+ $icon = $icon_url . 'missing.png';
352
+ }
353
+
354
+ return $icon;
355
+ }
356
+
357
+ /**
358
+ * @return array All extensions supported by Google Drive Viewer.
359
+ */
360
+ private static function getGoogleDriveExts() {
361
+ return array(
362
+ 'tiff', 'bmp', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx',
363
+ 'pdf', 'pages', 'ai', 'psd', 'dxf', 'svg', 'eps', 'ps', 'ttf'
364
+ );
365
+ }
366
+
367
+ /**
368
+ * @return array All extensions supported by Ghostscript.
369
+ */
370
+ private static function getGhostscriptExts() {
371
+ return array('pdf');
372
+ }
373
+
374
+ /**
375
+ * @return array All extensions supported by WP Audio Video Media metadata.
376
+ */
377
+ private static function getAudioVideoExts() {
378
+ return array_merge(wp_get_audio_extensions(), wp_get_video_extensions());
379
+ }
380
+
381
+ /**
382
+ * @param string $dirname Directory where the document is located.
383
+ * @param string $basename Filename of document minue the extension.
384
+ * @param string $ext The extension of the image to be created.
385
+ * @return string Name unique within the directory given, derived from the basename given.
386
+ */
387
+ private static function getUniqueThumbName($dirname, $basename, $ext = '.png') {
388
+ return wp_unique_filename($dirname, str_replace('.', '-', $basename) . '-thumb' . $ext);
389
+ }
390
+
391
+ /**
392
+ * Removes the existing thumbnail for the attachment
393
+ * with $ID, if such a thumbnail exists.
394
+ *
395
+ * Substantially borrowed from wp_delete_attachment() in wp-includes/post.php
396
+ *
397
+ * @filter wp_delete_file Filter the path of the file to delete.
398
+ * @global type $wpdb
399
+ * @param type $ID
400
+ */
401
+ private static function deleteExistingThumb($ID) {
402
+ global $wpdb;
403
+
404
+ $meta = wp_get_attachment_metadata($ID);
405
+
406
+ if (empty($meta['thumb']))
407
+ return;
408
+
409
+ $doc_path = get_attached_file($ID);
410
+
411
+ // Don't delete the thumb if another attachment uses it
412
+ $SQL = 'SELECT meta_id '
413
+ . "FROM $wpdb->postmeta "
414
+ . 'WHERE meta_key = \'_wp_attachment_metadata\' '
415
+ . 'AND meta_value LIKE %s '
416
+ . 'AND post_id <> %d';
417
+
418
+ if (!$wpdb->get_row($wpdb->prepare($SQL, '%' . $meta['thumb'] . '%', $ID))) {
419
+ $thumb_path = str_replace(basename($doc_path), $meta['thumb'], $doc_path);
420
+ // This filter is documented in wp-admin/custom-header.php
421
+ $thumb_path = apply_filters('wp_delete_file', $thumb_path);
422
+ @unlink($thumb_path);
423
+ }
424
+ }
425
+
426
+ /**
427
+ * Cleans up dimensions and permissions for a newly-created thumbnail.
428
+ * @param type $thumb_path
429
+ * @return type
430
+ */
431
+ private static function fixNewThumb($thumb_path) {
432
+ // ensure perms are correct
433
+ $stat = stat(dirname($thumb_path));
434
+ $perms = $stat['mode'] & 0000666;
435
+ @chmod($thumb_path, $perms);
436
+
437
+ // scae to no larger than 150x150px
438
+ $img = wp_get_image_editor($thumb_path);
439
+
440
+ if (is_wp_error($img)) {
441
+ error_log('DG: Failed to get image editor. Can\'t resize thumbnail.');
442
+ return;
443
+ }
444
+
445
+ $img->resize(150, 150, false);
446
+ $img->save($thumb_path);
447
+ }
448
+
449
+ /**
450
+ * Checks whether we may call gs through exec().
451
+ * @staticvar bool $available
452
+ * @return bool
453
+ */
454
+ private static function isGhostscriptAvailable() {
455
+ static $available;
456
+
457
+ if (!isset($available)) {
458
+ $is_win = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
459
+ $gs = $is_win ? 'gswin32c' : 'gs';
460
+
461
+ $available = self::isExecAvailable();
462
+ $exec = exec($is_win ? "where $gs" : "which $gs");
463
+ $available = $available && !empty($exec);
464
+
465
+ if (WP_DEBUG && $available) {
466
+ error_log("DG: Found the $gs executable.");
467
+ }
468
+ else if (WP_DEBUG) {
469
+ error_log("DG: Didn\'t find the $gs executable.");
470
+ }
471
+ }
472
+
473
+ return $available;
474
+ }
475
+
476
+ /**
477
+ * Checks whether exec() may be used.
478
+ * Source: http://stackoverflow.com/a/12980534/866618
479
+ * @staticvar bool $available
480
+ * @return bool
481
+ */
482
+ private static function isExecAvailable() {
483
+ static $available;
484
+
485
+ if (!isset($available)) {
486
+ $available = true;
487
+
488
+ if (ini_get('safe_mode')) {
489
+ $available = false;
490
+ }
491
+ else {
492
+ $d = ini_get('disable_functions');
493
+ $s = ini_get('suhosin.executor.func.blacklist');
494
+ if ("$d$s") {
495
+ $array = preg_split('/,\s*/', "$d,$s");
496
+ if (in_array('exec', $array)) {
497
+ $available = false;
498
+ }
499
+ }
500
+ }
501
+
502
+ if (WP_DEBUG) {
503
+ error_log('DG: exec() ' . ($available ? 'is' : 'isn\'t') . ' available.');
504
+ }
505
+ }
506
+
507
+ return $available;
508
+ }
509
+
510
+ /**
511
+ * Formerly achieved with wp_check_filetype(), but it was only returning
512
+ * valid results if the active user had permission to upload the given filetype.
513
+ *
514
+ * @param type $filename Name of the file to get extension from.
515
+ * @return str|bool Returns the file extension on success, false on failure.
516
+ */
517
+ private static function getExt($filename) {
518
+ foreach (wp_get_mime_types() as $ext_preg => $unused) {
519
+ $ext_preg = '!\.(' . $ext_preg . ')$!i';
520
+ if (preg_match($ext_preg, $filename, $ext_matches)) {
521
+ return $ext_matches[1];
522
+ }
523
+ }
524
+
525
+ return false;
526
+ }
527
+
528
+ /**
529
+ * Returns the name of the image to represent the filetype given.
530
+ * @staticvar array $exts
531
+ * @param type $filename
532
+ * @return boolean
533
+ */
534
+ private static function getDefaultIcon($ext) {
535
+ // Maps file ext to default image name.
536
+ static $exts = array(
537
+ // Most Common First
538
+ 'pdf' => 'pdf.png',
539
+
540
+ // MS Office
541
+ 'doc|docx|docm|dotx|dotm' => 'msdoc.png',
542
+ 'ppt|pot|pps|pptx|pptm|ppsx|ppsm|potx|potm|ppam|sldx|sldm' => 'msppt.png',
543
+ 'xla|xls|xlt|xlw|xlsx|xlsm|xlsb|xltx|xltm|xlam' => 'msxls.png',
544
+ 'mdb' => 'msaccess.png',
545
+
546
+ // iWork
547
+ 'key' => 'key.png',
548
+ 'numbers' => 'numbers.png',
549
+ 'pages' => 'pages.png',
550
+
551
+ // Images
552
+ 'jpg|jpeg|jpe|gif|png|bmp|tif|tiff|ico' => 'image.png',
553
+
554
+ // Video formats
555
+ 'asf|asx|wmv|wmx|wm|avi|divx|flv|mov' => 'video.png',
556
+ 'qt|mpeg|mpg|mpe|mp4|m4v|ogv|webm|mkv' => 'video.png',
557
+
558
+ // Audio formats
559
+ 'mp3|m4a|m4b|ra|ram|wav|ogg|oga|wma|wax|mka' => 'audio.png',
560
+ 'midi|mid' => 'midi.png',
561
+
562
+ // Text formats
563
+ 'txt|tsv|csv' => 'text.png',
564
+ 'rtx' => 'rtx.png',
565
+ 'rtf' => 'rtf.png',
566
+ 'ics' => 'ics.png',
567
+ 'wp|wpd' => 'wordperfect.png',
568
+
569
+ // Programming
570
+ 'html|htm' => 'html.png',
571
+ 'css' => 'css.png',
572
+ 'js' => 'javascript.png',
573
+ 'class' => 'java.png',
574
+ 'asc' => 'asc.png',
575
+ 'c' => 'c.png',
576
+ 'cc|cpp' => 'cpp.png',
577
+ 'h' => 'h.png',
578
+
579
+ // Msc application formats
580
+ 'zip|tar|gzip|gz|bz2|tgz|7z|rar' => 'compressed.png',
581
+ 'exe' => 'exec.png',
582
+ 'swf' => 'shockwave.png',
583
+
584
+ // OpenDocument formats
585
+ 'odt' => 'opendocument-text.png',
586
+ 'odp' => 'opendocument-presentation.png',
587
+ 'ods' => 'opendocument-spreadsheet.png',
588
+ 'odg' => 'opendocument-graphics.png',
589
+ 'odb' => 'opendocument-database.png',
590
+ 'odf' => 'opendocument-formula.png'
591
+ );
592
+
593
+ foreach ($exts as $ext_preg => $icon) {
594
+ $ext_preg = '!(' . $ext_preg . ')$!i';
595
+ if (preg_match($ext_preg, $ext)) {
596
+ return $icon;
597
+ }
598
+ }
599
+
600
+ return false;
601
+ }
602
+ }
603
+
604
+ ?>