Attachments - Version 3.3

Version Description

  • Added a search() method to allow searching for Attachments based on their attributes (e.g. attachment ID, post ID, post type, field values, etc.)
  • Improved the 'Remove' animation
  • New field: select
  • New parameter for Attachments attributes methods. You can pass the index (int) of the Attachment you'd like to utilize when firing the method.
Download this release

Release Info

Developer jchristopher
Plugin Icon wp plugin Attachments
Version 3.3
Comparing to
See all releases

Code changes from version 3.2 to 3.3

README.md CHANGED
@@ -8,6 +8,16 @@ Attachments allows you to simply append any number of items from your WordPress
8
  * [Installation](#installation)
9
  * **[Upgrade Notice](#upgrade-notice)** *Pay specific attention if upgrading from a version before 3.0*
10
  * [Usage](#usage)
 
 
 
 
 
 
 
 
 
 
11
  * [Screenshots](#screenshots)
12
  * [Frequently Asked Questions](#frequently-asked-questions)
13
  * [Changelog](#changelog)
@@ -74,23 +84,31 @@ Version 3 is a **major** rewrite. While I've taken precautions in ensuring you w
74
 
75
  ## Usage
76
 
 
 
77
  Attachments ships with a `Settings` screen (found under the `Settings` menu in the main WordPress admin navigation) that facilitates data migration from version 1.x and also offers some code snippets. If you would like to **disable the Settings screen** add the following to your theme's `functions.php`:
78
 
79
  ```php
80
  define( 'ATTACHMENTS_SETTINGS_SCREEN', false ); // disable the Settings screen
81
  ```
82
 
 
 
83
  When Attachments is first activated, a default instance is created titled Attachments. It has two fields:
84
 
85
  1. Title
86
  1. Caption
87
 
 
 
88
  If you would like to *disable the default instance* (meta box titled 'Attachments' with a 'Title' and 'Caption' field) add the following to your `wp-config.php`:
89
 
90
  ```php
91
  define( 'ATTACHMENTS_DEFAULT_INSTANCE', false );
92
  ```
93
 
 
 
94
  You may create instances with your own custom fields by using the `attachments_register` action. To create your own instance add the following to your theme's `functions.php` or your own plugin:
95
 
96
  ```php
@@ -98,6 +116,21 @@ You may create instances with your own custom fields by using the `attachments_r
98
 
99
  function my_attachments( $attachments )
100
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  $args = array(
102
 
103
  // title of the meta box (string)
@@ -118,32 +151,8 @@ function my_attachments( $attachments )
118
  // text for modal 'Attach' button (string)
119
  'modal_text' => __( 'Attach', 'attachments' ),
120
 
121
- /**
122
- * Fields for the instance are stored in an array. Each field consists of
123
- * an array with three keys: name, type, label.
124
- *
125
- * name - (string) The field name used. No special characters.
126
- * type - (string) The registered field type.
127
- * Fields available: text, textarea, wysiwyg
128
- * label - (string) The label displayed for the field.
129
- * caption - (string) The default WordPress metadata to use when initially adding the Attachment
130
- * Defaults available: title, caption, alt, description
131
- */
132
-
133
- 'fields' => array(
134
- array(
135
- 'name' => 'title', // unique field name
136
- 'type' => 'text', // registered field type
137
- 'label' => __( 'Title', 'attachments' ), // label to display
138
- 'default' => 'title', // default value upon selection
139
- ),
140
- array(
141
- 'name' => 'caption', // unique field name
142
- 'type' => 'textarea', // registered field type
143
- 'label' => __( 'Caption', 'attachments' ), // label to display
144
- 'default' => 'caption', // default value upon selection
145
- )
146
- ),
147
 
148
  );
149
 
@@ -153,6 +162,69 @@ function my_attachments( $attachments )
153
  add_action( 'attachments_register', 'my_attachments' );
154
  ```
155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  Once your instances are set up and working, you'll also need to edit your theme's template files to pull the data to the front end. To retrieve the Attachments for the current post, add this within The Loop:
157
 
158
  ```php
@@ -169,6 +241,8 @@ Once your instances are set up and working, you'll also need to edit your theme'
169
  <?php endif; ?>
170
  ```
171
 
 
 
172
  If you want to get the Attachments for a post **outside The Loop**, add a second parameter with the post ID when instantiating Attachments:
173
 
174
  ```php
@@ -188,6 +262,8 @@ If you want to get the Attachments for a post **outside The Loop**, add a second
188
  <?php endif; ?>
189
  ```
190
 
 
 
191
  You can also retrieve various attributes of the current Attachment directly using these utility functions:
192
 
193
  ```php
@@ -213,18 +289,80 @@ You can also retrieve various attributes of the current Attachment directly usin
213
  <?php endif; ?>
214
  ```
215
 
 
 
216
  If you don't want to use the above implementation to loop through your Attachments, can also retrieve them explicitly:
217
 
218
  ```php
219
  <?php $attachments = new Attachments( 'attachments' ); ?>
220
  <?php if( $attachments->exist() ) : ?>
221
- <?php if( $attachment = $attachments->get_single( 0 ) ) : ?>
 
222
  <h3>Attachment at index 0:</h3>
223
  <pre><?php print_r( $attachment ); ?></pre>
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  <?php endif; ?>
225
  <?php endif; ?>
226
  ```
227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  ## Screenshots
229
 
230
  ##### An Attachments meta box sitting below the content editor
@@ -272,10 +410,16 @@ Attachments uses WordPress' built in Media library for uploads and storage.
272
 
273
  <dl>
274
 
 
 
 
 
 
 
275
  <dt>3.2</dt>
276
  <dd>Added option to disable the Settings screen</dd>
277
  <dd>Added the ability to set a default for fields using the metadata that exists in WordPress. Available defaults include: title, caption, alt, and description. If set, the metadata for the correlating field will be used as the field default when initially adding an Attachment from the Media modal. Only applies to text, textarea, and wysiwyg fields.</dd>
278
- <dd>Added a `get_single()` method that allows you to specifically retrieve a single Attachment</dd>
279
  <dd>Clarified some documentation</dd>
280
 
281
  <dt>3.1.4</dt>
@@ -316,9 +460,9 @@ Attachments uses WordPress' built in Media library for uploads and storage.
316
 
317
  <dt>3.0.6</dt>
318
  <dd>Fixed a possible JavaScript error if an Attachment that's an image doesn't have a proper thumbnail URL</dd>
319
- <dd>Added a total() method that will return the number of Attachments for the current instance</dd>
320
- <dd>When requesting the image() for a non-image Attachment, the WordPress-defined icon will be returned</dd>
321
- <dd>Added an icon() method that will return the WordPress-defined icon for the Attachment</dd>
322
  <dd>Cleaned up a PHP Warning when trying to save for an undefined field type</dd>
323
  <dd>Fixed an issue where template tags would be output for non-image Attachments after saving</dd>
324
 
@@ -360,7 +504,6 @@ Planned feature additions include:
360
 
361
  * Additional field type: checkbox
362
  * Additional field type: radio
363
- * Additional field type: select
364
  * User-defined limiting the number of Attachments per instance
365
  * User-defined custom field types
366
  * Additional hooks/actions from top to bottom
8
  * [Installation](#installation)
9
  * **[Upgrade Notice](#upgrade-notice)** *Pay specific attention if upgrading from a version before 3.0*
10
  * [Usage](#usage)
11
+ * [Disable Settings Screen](#disable-settings-screen)
12
+ * [Setting Up Instances](#setting-up-instances)
13
+ * [Disable the Default Instance](#disable-the-default-instance)
14
+ * [Create Custom Instances](#create-custom-instances)
15
+ * [Fields Reference](#fields-reference)
16
+ * [Pulling Attachments to your Theme](#pulling-attachments-to-your-theme)
17
+ * [Retrieve Attachments Outside The Loop](#retrieve-attachments-outside-the-loop)
18
+ * [Retrieve Attachment Attributes](#retrieve-attachment-attributes)
19
+ * [Retrieve Single Attachments](#retrieve-single-attachments)
20
+ * [Search](#search)
21
  * [Screenshots](#screenshots)
22
  * [Frequently Asked Questions](#frequently-asked-questions)
23
  * [Changelog](#changelog)
84
 
85
  ## Usage
86
 
87
+ ### Disable Settings Screen
88
+
89
  Attachments ships with a `Settings` screen (found under the `Settings` menu in the main WordPress admin navigation) that facilitates data migration from version 1.x and also offers some code snippets. If you would like to **disable the Settings screen** add the following to your theme's `functions.php`:
90
 
91
  ```php
92
  define( 'ATTACHMENTS_SETTINGS_SCREEN', false ); // disable the Settings screen
93
  ```
94
 
95
+ ### Setting Up Instances
96
+
97
  When Attachments is first activated, a default instance is created titled Attachments. It has two fields:
98
 
99
  1. Title
100
  1. Caption
101
 
102
+ #### Disable the Default Instance
103
+
104
  If you would like to *disable the default instance* (meta box titled 'Attachments' with a 'Title' and 'Caption' field) add the following to your `wp-config.php`:
105
 
106
  ```php
107
  define( 'ATTACHMENTS_DEFAULT_INSTANCE', false );
108
  ```
109
 
110
+ #### Create Custom Instances
111
+
112
  You may create instances with your own custom fields by using the `attachments_register` action. To create your own instance add the following to your theme's `functions.php` or your own plugin:
113
 
114
  ```php
116
 
117
  function my_attachments( $attachments )
118
  {
119
+ $fields => array(
120
+ array(
121
+ 'name' => 'title', // unique field name
122
+ 'type' => 'text', // registered field type
123
+ 'label' => __( 'Title', 'attachments' ), // label to display
124
+ 'default' => 'title', // default value upon selection
125
+ ),
126
+ array(
127
+ 'name' => 'caption', // unique field name
128
+ 'type' => 'textarea', // registered field type
129
+ 'label' => __( 'Caption', 'attachments' ), // label to display
130
+ 'default' => 'caption', // default value upon selection
131
+ ),
132
+ );
133
+
134
  $args = array(
135
 
136
  // title of the meta box (string)
151
  // text for modal 'Attach' button (string)
152
  'modal_text' => __( 'Attach', 'attachments' ),
153
 
154
+ // fields array
155
+ 'fields' => $fields,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
  );
158
 
162
  add_action( 'attachments_register', 'my_attachments' );
163
  ```
164
 
165
+ #### Fields Reference
166
+
167
+ At this time there are **four** field types available:
168
+
169
+ 1. `text`
170
+ 1. `textarea`
171
+ 1. `select`
172
+ 1. `wysiwyg`
173
+
174
+ When declaring fields for your instance, you'll be composing an array of fields, each with an array of parameters that set the various attributes of each field. Here is a full example of all available parameters for all available fields:
175
+
176
+ ```php
177
+ /**
178
+ * Fields for the instance are stored in an array. Each field consists of
179
+ * an array with three required keys: name, type, label
180
+ * and one optional key: meta
181
+ *
182
+ * name - (string) The field name used. No special characters.
183
+ * type - (string) The registered field type.
184
+ * Fields available: text, textarea, wysiwyg, select
185
+ * label - (string) The label displayed for the field.
186
+ * default - (string) The default WordPress metadata to use when initially adding the Attachment
187
+ * Defaults available: title, caption, alt, description
188
+ * meta - (array) The field-specific parameters that apply only to that field type
189
+ */
190
+
191
+ $fields => array(
192
+ array(
193
+ 'name' => 'title', // unique field name
194
+ 'type' => 'text', // registered field type
195
+ 'label' => __( 'Title', 'attachments' ), // label to display
196
+ 'default' => 'title', // default value upon selection
197
+ ),
198
+ array(
199
+ 'name' => 'caption', // unique field name
200
+ 'type' => 'textarea', // registered field type
201
+ 'label' => __( 'Caption', 'attachments' ), // label to display
202
+ 'default' => 'caption', // default value upon selection
203
+ ),
204
+ array(
205
+ 'name' => 'option', // unique field name
206
+ 'type' => 'select', // registered field type
207
+ 'label' => __( 'Option', 'attachments' ), // label to display
208
+ 'meta' => array( // field-specific meta as defined by field class
209
+ 'allow_null' => true, // allow null value? (adds 'empty' <option>)
210
+ 'multiple' => true, // multiple <select>?
211
+ 'options' => array( // the <option>s to use
212
+ '1' => 'Option 1',
213
+ '2' => 'Option 2',
214
+ )
215
+ ),
216
+ ),
217
+ array(
218
+ 'name' => 'description', // unique field name
219
+ 'type' => 'wysiwyg', // registered field type
220
+ 'label' => __( 'Description', 'attachments' ), // label to display
221
+ 'default' => 'description', // default value upon selection
222
+ ),
223
+ );
224
+ ```
225
+
226
+ ### Pulling Attachments to your Theme
227
+
228
  Once your instances are set up and working, you'll also need to edit your theme's template files to pull the data to the front end. To retrieve the Attachments for the current post, add this within The Loop:
229
 
230
  ```php
241
  <?php endif; ?>
242
  ```
243
 
244
+ #### Retrieve Attachments Outside The Loop
245
+
246
  If you want to get the Attachments for a post **outside The Loop**, add a second parameter with the post ID when instantiating Attachments:
247
 
248
  ```php
262
  <?php endif; ?>
263
  ```
264
 
265
+ #### Retrieve Attachment Attributes
266
+
267
  You can also retrieve various attributes of the current Attachment directly using these utility functions:
268
 
269
  ```php
289
  <?php endif; ?>
290
  ```
291
 
292
+ #### Retrieve Single Attachments
293
+
294
  If you don't want to use the above implementation to loop through your Attachments, can also retrieve them explicitly:
295
 
296
  ```php
297
  <?php $attachments = new Attachments( 'attachments' ); ?>
298
  <?php if( $attachments->exist() ) : ?>
299
+ <?php $my_index = 0; ?>
300
+ <?php if( $attachment = $attachments->get_single( $my_index ) ) : ?>
301
  <h3>Attachment at index 0:</h3>
302
  <pre><?php print_r( $attachment ); ?></pre>
303
+ <ul>
304
+ <li>
305
+ ID: <?php echo $attachments->id( $my_index ); ?><br />
306
+ Type: <?php echo $attachments->type( $my_index ); ?><br />
307
+ Subtype: <?php echo $attachments->subtype( $my_index ); ?><br />
308
+ URL: <?php echo $attachments->url( $my_index ); ?><br />
309
+ Image: <?php echo $attachments->image( 'thumbnail', $my_index ); ?><br />
310
+ Source: <?php echo $attachments->src( 'full', $my_index ); ?><br />
311
+ Size: <?php echo $attachments->filesize( $my_index ); ?><br />
312
+ Title Field: <?php echo $attachments->field( 'title', $my_index ); ?><br />
313
+ Caption Field: Name: <?php echo $attachments->field( 'caption', $my_index ); ?>
314
+ </li>
315
+ </ul>
316
  <?php endif; ?>
317
  <?php endif; ?>
318
  ```
319
 
320
+ ### Search
321
+
322
+ Attachments provides a method of searching it's own data using a number of attributes. This faciliates a search to be as widespread or as specific as you'd like.
323
+
324
+ ```php
325
+ <?php
326
+ $attachments = new Attachments();
327
+
328
+ $search_args = array(
329
+ 'instance' => 'attachments', // search all instances
330
+ 'fields' => array( 'caption' ), // search the 'caption' field only
331
+ );
332
+
333
+ $attachments->search( 'lorem ipsum', $search_args ); // search for 'lorem ipsum'
334
+
335
+ if( $attachments->exist() ) : ?>
336
+ <h3>Attachments</h3>
337
+ <ul>
338
+ <?php while( $attachments->get() ) : ?>
339
+ <li>
340
+ Attachment ID: <?php echo $attachments->id(); ?><br />
341
+ Post ID: <?php echo $attachments->post_id(); ?><br />
342
+ Title Field: <?php echo $attachments->field( 'title' ); ?><br />
343
+ Caption Field: <?php echo $attachments->field( 'caption' ); ?>
344
+ </li>
345
+ <?php endwhile; ?>
346
+ </ul>
347
+ <?php endif;
348
+ ?>
349
+ ```
350
+
351
+ The full list of available search arguments (and their defaults) is as follows:
352
+
353
+ ```php
354
+ $defaults = array(
355
+ 'attachment_id' => null, // (int) not searching for a single attachment ID
356
+ 'instance' => 'attachments', // (string) the instance you want to search
357
+ 'post_type' => null, // (string) search 'any' post type
358
+ 'post_id' => null, // (int) searching all posts
359
+ 'post_status' => 'publish', // (string) search only published posts
360
+ 'fields' => null, // (string|array) search all fields
361
+ );
362
+ ```
363
+
364
+ Once you've performed your search, you can loop through the returned Attachments as you normally would.
365
+
366
  ## Screenshots
367
 
368
  ##### An Attachments meta box sitting below the content editor
410
 
411
  <dl>
412
 
413
+ <dt>3.3</dt>
414
+ <dd>Added a <code>search()</code> method to allow searching for Attachments based on their attributes (e.g. attachment ID, post ID, post type, field values, etc.)</dd>
415
+ <dd>Improved the 'Remove' animation</dd>
416
+ <dd>New field: select</dd>
417
+ <dd>New parameter for Attachments attributes methods. You can pass the index (<code>int</code>) of the Attachment you'd like to utilize when firing the method.</dd>
418
+
419
  <dt>3.2</dt>
420
  <dd>Added option to disable the Settings screen</dd>
421
  <dd>Added the ability to set a default for fields using the metadata that exists in WordPress. Available defaults include: title, caption, alt, and description. If set, the metadata for the correlating field will be used as the field default when initially adding an Attachment from the Media modal. Only applies to text, textarea, and wysiwyg fields.</dd>
422
+ <dd>Added a <code>get_single()</code> method that allows you to specifically retrieve a single Attachment</dd>
423
  <dd>Clarified some documentation</dd>
424
 
425
  <dt>3.1.4</dt>
460
 
461
  <dt>3.0.6</dt>
462
  <dd>Fixed a possible JavaScript error if an Attachment that's an image doesn't have a proper thumbnail URL</dd>
463
+ <dd>Added a <code>total()</code> method that will return the number of Attachments for the current instance</dd>
464
+ <dd>When requesting the </code>image()</code> for a non-image Attachment, the WordPress-defined icon will be returned</dd>
465
+ <dd>Added an <code>icon()</code> method that will return the WordPress-defined icon for the Attachment</dd>
466
  <dd>Cleaned up a PHP Warning when trying to save for an undefined field type</dd>
467
  <dd>Fixed an issue where template tags would be output for non-image Attachments after saving</dd>
468
 
504
 
505
  * Additional field type: checkbox
506
  * Additional field type: radio
 
507
  * User-defined limiting the number of Attachments per instance
508
  * User-defined custom field types
509
  * Additional hooks/actions from top to bottom
classes/class.attachments.php CHANGED
@@ -59,7 +59,7 @@ if ( !class_exists( 'Attachments' ) ) :
59
 
60
  // establish our environment variables
61
 
62
- $this->version = '3.2';
63
  $this->url = ATTACHMENTS_URL;
64
  $this->dir = ATTACHMENTS_DIR;
65
 
@@ -160,6 +160,136 @@ if ( !class_exists( 'Attachments' ) ) :
160
 
161
 
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  /**
164
  * Returns whether or not the current object has any Attachments
165
  *
@@ -218,18 +348,20 @@ if ( !class_exists( 'Attachments' ) ) :
218
  *
219
  * @since 3.0.6
220
  */
221
- function asset( $size = 'thumbnail' )
222
  {
 
 
223
  // do we have our meta yet?
224
- if( !isset( $this->attachments[$this->attachments_ref]->meta ) )
225
- $this->attachments[$this->attachments_ref]->meta = wp_get_attachment_metadata( $this->attachments[$this->attachments_ref]->id );
226
 
227
  // is it an image?
228
  if(
229
- isset( $this->attachments[$this->attachments_ref]->meta['sizes'] ) && // is it an image?
230
  in_array( $size, $this->image_sizes ) ) // do we have the right size?
231
  {
232
- $asset = wp_get_attachment_image_src( $this->attachments[$this->attachments_ref]->id, $size );
233
  }
234
  else
235
  {
@@ -247,9 +379,10 @@ if ( !class_exists( 'Attachments' ) ) :
247
  *
248
  * @since 3.0.6
249
  */
250
- function icon()
251
  {
252
- $asset = wp_get_attachment_image_src( $this->attachments[$this->attachments_ref]->id, null, true );
 
253
  return $asset;
254
  }
255
 
@@ -260,14 +393,15 @@ if ( !class_exists( 'Attachments' ) ) :
260
  *
261
  * @since 3.0
262
  */
263
- function image( $size = 'thumbnail' )
264
  {
265
  $asset = $this->asset( $size );
266
 
267
  $image_src = $asset[0];
268
  $image_width = $asset[1];
269
  $image_height = $asset[2];
270
- $image_alt = get_post_meta( $this->attachments[$this->attachments_ref]->id, '_wp_attachment_image_alt', true );
 
271
 
272
  $image = '<img src="' . $image_src . '" width="' . $image_width . '" height="' . $image_height . '" alt="' . $image_alt . '" />';
273
 
@@ -281,7 +415,7 @@ if ( !class_exists( 'Attachments' ) ) :
281
  *
282
  * @since 3.0
283
  */
284
- function src( $size = 'thumbnail' )
285
  {
286
  $asset = $this->asset( $size );
287
  return $asset[0];
@@ -294,12 +428,14 @@ if ( !class_exists( 'Attachments' ) ) :
294
  *
295
  * @since 3.0
296
  */
297
- function filesize()
298
  {
299
- if( !isset( $this->attachments[$this->attachments_ref]->id ) )
 
 
300
  return false;
301
 
302
- $url = wp_get_attachment_url( $this->attachments[$this->attachments_ref]->id );
303
  $uploads = wp_upload_dir();
304
  $file_path = str_replace( $uploads['baseurl'], $uploads['basedir'], $url );
305
 
@@ -318,13 +454,15 @@ if ( !class_exists( 'Attachments' ) ) :
318
  *
319
  * @since 3.0
320
  */
321
- function type()
322
  {
323
- if( !isset( $this->attachments[$this->attachments_ref]->id ) )
 
 
324
  return false;
325
 
326
- $attachment_mime = explode( '/', get_post_mime_type( $this->attachments[$this->attachments_ref]->id ) );
327
- return isset( $attachment_mime[0] ) ? $attachment_mime[0] : null;
328
  }
329
 
330
 
@@ -334,13 +472,15 @@ if ( !class_exists( 'Attachments' ) ) :
334
  *
335
  * @since 3.0
336
  */
337
- function subtype()
338
  {
339
- if( !isset( $this->attachments[$this->attachments_ref]->id ) )
 
 
340
  return false;
341
 
342
- $attachment_mime = explode( '/', get_post_mime_type( $this->attachments[$this->attachments_ref]->id ) );
343
- return isset( $attachment_mime[1] ) ? $attachment_mime[1] : null;
344
  }
345
 
346
 
@@ -350,9 +490,25 @@ if ( !class_exists( 'Attachments' ) ) :
350
  *
351
  * @since 3.0
352
  */
353
- function id()
354
  {
355
- return isset( $this->attachments[$this->attachments_ref]->id ) ? $this->attachments[$this->attachments_ref]->id : null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  }
357
 
358
 
@@ -362,12 +518,11 @@ if ( !class_exists( 'Attachments' ) ) :
362
  *
363
  * @since 3.0
364
  */
365
- function url()
366
  {
367
- if( !isset( $this->attachments[$this->attachments_ref]->id ) )
368
- return false;
369
 
370
- return wp_get_attachment_url( $this->attachments[$this->attachments_ref]->id );
371
  }
372
 
373
 
@@ -377,9 +532,11 @@ if ( !class_exists( 'Attachments' ) ) :
377
  *
378
  * @since 3.0
379
  */
380
- function field( $name = 'title' )
381
  {
382
- return isset( $this->attachments[$this->attachments_ref]->fields->$name ) ? $this->attachments[$this->attachments_ref]->fields->$name : false;
 
 
383
  }
384
 
385
 
@@ -606,9 +763,18 @@ if ( !class_exists( 'Attachments' ) ) :
606
 
607
  targetAttachment = $(this).parents('.attachments-attachment');
608
 
609
- targetAttachment.slideUp(function(){
610
- targetAttachment.remove();
611
- });
 
 
 
 
 
 
 
 
 
612
 
613
  } );
614
 
@@ -630,6 +796,7 @@ if ( !class_exists( 'Attachments' ) ) :
630
  $field_types = array(
631
  'text' => ATTACHMENTS_DIR . 'classes/fields/class.field.text.php',
632
  'textarea' => ATTACHMENTS_DIR . 'classes/fields/class.field.textarea.php',
 
633
  'wysiwyg' => ATTACHMENTS_DIR . 'classes/fields/class.field.wysiwyg.php',
634
  );
635
 
@@ -683,6 +850,7 @@ if ( !class_exists( 'Attachments' ) ) :
683
  'name' => 'title',
684
  'type' => 'text',
685
  'label' => __( 'Title', 'attachments' ),
 
686
  );
687
 
688
  $params = array_merge( $defaults, $params );
@@ -698,8 +866,11 @@ if ( !class_exists( 'Attachments' ) ) :
698
  if( isset( $params['label'] ) )
699
  $params['label'] = __( esc_html( $params['label'] ) );
700
 
 
 
 
701
  // instantiate the class for this field and send it back
702
- return new $this->fields[ $params['type'] ]( $params['name'], $params['label'] );
703
  }
704
 
705
 
@@ -897,10 +1068,10 @@ if ( !class_exists( 'Attachments' ) ) :
897
  $name = sanitize_title( $field['name'] );
898
  $label = esc_html( $field['label'] );
899
  $default = isset( $field['default'] ) ? $field['default'] : false; // validated in the class
 
 
900
 
901
- $value = ( isset( $attachment->fields->$name ) ) ? $attachment->fields->$name : null;
902
-
903
- $field = new $this->fields[$type]( $name, $label, $value );
904
  $field->value = $field->format_value_for_input( $field->value );
905
 
906
  // does this field already have a unique ID?
@@ -1160,13 +1331,13 @@ if ( !class_exists( 'Attachments' ) ) :
1160
  $field_value = str_replace("\n", "%%ATTACHMENTS_NEWLINE%%", $field_value );
1161
 
1162
  // slashes were already added so we're going to strip them
1163
- $field_value = stripslashes( $field_value );
1164
 
1165
  // put back our newlines
1166
  $field_value = str_replace("%%ATTACHMENTS_NEWLINE%%", "\\n", $field_value );
1167
 
1168
  // encode the whole thing
1169
- $field_value = htmlentities( $field_value, ENT_QUOTES, 'UTF-8' );
1170
 
1171
  // encode things properly
1172
  $attachment['fields'][$key] = $field_value;
@@ -1196,12 +1367,105 @@ if ( !class_exists( 'Attachments' ) ) :
1196
 
1197
 
1198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1199
  /**
1200
  * Retrieves all Attachments for the submitted instance and post ID
1201
  *
1202
  * @since 3.0
1203
  */
1204
- function get_attachments( $instance = '', $post_id = null )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1205
  {
1206
  global $post;
1207
 
@@ -1221,63 +1485,95 @@ if ( !class_exists( 'Attachments' ) ) :
1221
  else
1222
  {
1223
  // no post ID, nothing to do...
1224
- return;
1225
  }
1226
 
 
 
 
1227
 
1228
- // grab our JSON and decode it
1229
- $attachments_json = get_post_meta( $post_id, $this->meta_key, true );
1230
- $attachments_raw = is_string( $attachments_json ) ? json_decode( $attachments_json ) : false;
1231
 
1232
- // we need to decode the fields (that were encoded during save) and run them through
1233
- // their format_value_for_input as defined in it's class
1234
- if( isset( $attachments_raw->$instance ) )
 
 
 
 
 
 
 
 
 
 
1235
  {
1236
- foreach( $attachments_raw->$instance as $attachment )
1237
  {
1238
- if( is_object( $attachment->fields ) )
 
1239
  {
1240
- foreach( $attachment->fields as $key => $value )
 
1241
  {
1242
- // loop through the instance fields to get the type
1243
- if( isset( $this->instances[$instance]['fields'] ) )
1244
- {
1245
- $type = '';
1246
- foreach( $this->instances[$instance]['fields'] as $field )
1247
- {
1248
- if( isset( $field['name'] ) && $field['name'] == $key )
1249
- {
1250
- $type = isset( $field['type'] ) ? $field['type'] : false;
1251
- break;
1252
- }
1253
- }
1254
- if( isset( $this->fields[$type] ) )
1255
- {
1256
- // we need to decode the html entities that were encoded for the save
1257
- $attachment->fields->$key = html_entity_decode( $attachment->fields->$key, ENT_QUOTES, 'UTF-8' );
1258
- }
1259
- else
1260
- {
1261
- // the type doesn't exist
1262
- $attachment->fields->$key = false;
1263
- }
1264
- }
1265
- else
1266
  {
1267
- // this was a theme file request, just grab it
1268
- $attachment->fields->$key = html_entity_decode( $attachment->fields->$key, ENT_QUOTES, 'UTF-8' );
1269
  }
1270
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1271
  }
1272
- $attachments[] = $attachment;
1273
  }
1274
  }
1275
- else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1276
  {
1277
- $attachments = false;
 
1278
  }
 
 
1279
 
1280
- return $attachments;
1281
  }
1282
 
1283
 
59
 
60
  // establish our environment variables
61
 
62
+ $this->version = '3.3';
63
  $this->url = ATTACHMENTS_URL;
64
  $this->dir = ATTACHMENTS_DIR;
65
 
160
 
161
 
162
 
163
+ /**
164
+ * Facilitates searching for Attachments
165
+ *
166
+ * @since 3.3
167
+ */
168
+ function search( $query = null, $params = array() )
169
+ {
170
+ $defaults = array(
171
+ 'attachment_id' => null, // not searching for a single attachment ID
172
+ 'instance' => 'attachments', // default instance
173
+ 'post_type' => null, // search 'any' post type
174
+ 'post_id' => null, // searching all posts
175
+ 'post_status' => 'publish', // search only published posts
176
+ 'fields' => null, // search all fields
177
+ );
178
+
179
+ $query = is_null( $query ) ? null : sanitize_text_field( $query );
180
+ $params = array_merge( $defaults, $params );
181
+
182
+ // sanitize parameters
183
+ $params['attachment_id'] = is_null( $params['attachment_id'] ) ? null : intval( $params['attachment_id'] );
184
+ $params['instance'] = !is_string( $params['instance'] ) ? 'attachments' : sanitize_text_field( $params['instance'] );
185
+ $params['post_type'] = is_null( $params['post_type'] ) ? 'any' : sanitize_text_field( $params['post_type'] );
186
+ $params['post_id'] = is_null( $params['post_id'] ) ? null : intval( $params['post_id'] );
187
+
188
+ $params['post_status'] = sanitize_text_field( $params['post_status'] );
189
+
190
+ if( is_string( $params['fields'] ) )
191
+ $params['fields'] = array( $params['fields'] ); // we always want an array
192
+
193
+ // since we have an array for our fields, we need to loop through and sanitize
194
+ for( $i = 0; $i < count( $params['fields'] ); $i++ )
195
+ $params['fields'][$i] = sanitize_text_field( $params['fields'][$i] );
196
+
197
+ // prepare our search args
198
+ $args = array(
199
+ 'nopaging' => true,
200
+ 'post_status' => $params['post_status'],
201
+ 'meta_query' => array(
202
+ array(
203
+ 'key' => 'attachments',
204
+ 'value' => $query,
205
+ 'compare' => 'LIKE'
206
+ )
207
+ ),
208
+ );
209
+
210
+ // append any applicable parameters that got passed to the original method call
211
+ if( $params['post_type'] )
212
+ $args['post_type'] = $params['post_type'];
213
+
214
+ if( $params['post_id'] )
215
+ $args['post__in'] = array( $params['post_id'] ); // avoid using 'p' or 'page_id'
216
+
217
+ // we haven't utilized all parameters yet because they're meta-value based so we need to
218
+ // do some parsing on our end to validate the returned results
219
+
220
+ $possible_posts = new WP_Query( $args );
221
+ $potential_attachments = false; // stores valid attachments as restrictions are added
222
+
223
+ if( $possible_posts->found_posts )
224
+ {
225
+ // we have results from the reliminary search, we need to quantify them
226
+ while( $possible_posts->have_posts() )
227
+ {
228
+ $possible_posts->next_post();
229
+ $possible_post_ids[] = $possible_posts->post->ID;
230
+ }
231
+
232
+ // now that we have our possible post IDs we can grab all Attachments for all of those posts
233
+ foreach( $possible_post_ids as $possible_post_id )
234
+ {
235
+ $possible_attachments = $this->get_attachments( $params['instance'], $possible_post_id );
236
+
237
+ foreach( $possible_attachments as $possible_attachment )
238
+ $potential_attachments[] = $possible_attachment;
239
+ }
240
+
241
+ }
242
+
243
+ // if there aren't even any potential attachments, we'll just short circuit
244
+ if( !$potential_attachments )
245
+ return;
246
+
247
+ // first we need to make sure that our query matches each attachment
248
+ // we need to do this because the LIKE query returned the entire meta record,
249
+ // not necessarily tied to any specific Attachment
250
+ $total_potentials = count( $potential_attachments );
251
+ for( $i = 0; $i < $total_potentials; $i++ )
252
+ {
253
+ $valid = false;
254
+
255
+ // if we need to limit our search to specific fields, we'll do that here
256
+ if( $params['fields'] )
257
+ {
258
+ // we only want to check certain fields
259
+ foreach( $params['fields'] as $field )
260
+ if( isset( $potential_attachments[$i]->fields->$field ) ) // does the field exist?
261
+ if( strpos( strtolower( $potential_attachments[$i]->fields->$field ),
262
+ strtolower( $query ) ) !== false ) // does the value match?
263
+ $valid = true;
264
+ }
265
+ else
266
+ {
267
+ // we want to check all fields
268
+ foreach( $potential_attachments[$i]->fields as $field_name => $field_value )
269
+ if( strpos( strtolower( $field_value) , strtolower( $query ) ) !== false )
270
+ $valid = true;
271
+ }
272
+
273
+ if( !$valid )
274
+ unset( $potential_attachments[$i] );
275
+
276
+ // now our potentials have been limited to each match the query based on any field
277
+ }
278
+
279
+ // limit to attachment ID if applicable
280
+ if( $params['attachment_id'] )
281
+ {
282
+ $total_potentials = count( $potential_attachments );
283
+ for( $i = 0; $i < $total_potentials; $i++ )
284
+ if( $potential_attachments[$i]->id != $params['attachment_id'] )
285
+ unset( $potential_attachments[$i] );
286
+ }
287
+
288
+ $this->attachments = array_values( $potential_attachments );
289
+ }
290
+
291
+
292
+
293
  /**
294
  * Returns whether or not the current object has any Attachments
295
  *
348
  *
349
  * @since 3.0.6
350
  */
351
+ function asset( $size = 'thumbnail', $index = null )
352
  {
353
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
354
+
355
  // do we have our meta yet?
356
+ if( !isset( $this->attachments[$index]->meta ) )
357
+ $this->attachments[$index]->meta = wp_get_attachment_metadata( $this->attachments[$index]->id );
358
 
359
  // is it an image?
360
  if(
361
+ isset( $this->attachments[$index]->meta['sizes'] ) && // is it an image?
362
  in_array( $size, $this->image_sizes ) ) // do we have the right size?
363
  {
364
+ $asset = wp_get_attachment_image_src( $this->attachments[$index]->id, $size );
365
  }
366
  else
367
  {
379
  *
380
  * @since 3.0.6
381
  */
382
+ function icon( $index = null )
383
  {
384
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
385
+ $asset = wp_get_attachment_image_src( $this->attachments[$index]->id, null, true );
386
  return $asset;
387
  }
388
 
393
  *
394
  * @since 3.0
395
  */
396
+ function image( $size = 'thumbnail', $index = null )
397
  {
398
  $asset = $this->asset( $size );
399
 
400
  $image_src = $asset[0];
401
  $image_width = $asset[1];
402
  $image_height = $asset[2];
403
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
404
+ $image_alt = get_post_meta( $this->attachments[$index]->id, '_wp_attachment_image_alt', true );
405
 
406
  $image = '<img src="' . $image_src . '" width="' . $image_width . '" height="' . $image_height . '" alt="' . $image_alt . '" />';
407
 
415
  *
416
  * @since 3.0
417
  */
418
+ function src( $size = 'thumbnail', $index = null )
419
  {
420
  $asset = $this->asset( $size );
421
  return $asset[0];
428
  *
429
  * @since 3.0
430
  */
431
+ function filesize( $index = null )
432
  {
433
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
434
+
435
+ if( !isset( $this->attachments[$index]->id ) )
436
  return false;
437
 
438
+ $url = wp_get_attachment_url( $this->attachments[$index]->id );
439
  $uploads = wp_upload_dir();
440
  $file_path = str_replace( $uploads['baseurl'], $uploads['basedir'], $url );
441
 
454
  *
455
  * @since 3.0
456
  */
457
+ function type( $index = null )
458
  {
459
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
460
+
461
+ if( !isset( $this->attachments[$index]->id ) )
462
  return false;
463
 
464
+ $attachment_mime = explode( '/', get_post_mime_type( $this->attachments[$index]->id ) );
465
+ return isset( $attachment_mime[0] ) ? $attachment_mime[0] : false;
466
  }
467
 
468
 
472
  *
473
  * @since 3.0
474
  */
475
+ function subtype( $index = null )
476
  {
477
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
478
+
479
+ if( !isset( $this->attachments[$index]->id ) )
480
  return false;
481
 
482
+ $attachment_mime = explode( '/', get_post_mime_type( $this->attachments[$index]->id ) );
483
+ return isset( $attachment_mime[1] ) ? $attachment_mime[1] : false;
484
  }
485
 
486
 
490
  *
491
  * @since 3.0
492
  */
493
+ function id( $index = null )
494
  {
495
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
496
+
497
+ return isset( $this->attachments[$index]->id ) ? $this->attachments[$index]->id : false;
498
+ }
499
+
500
+
501
+
502
+ /**
503
+ * Returns the $post->ID of the current Attachment
504
+ *
505
+ * @since 3.3
506
+ */
507
+ function post_id( $index = null )
508
+ {
509
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
510
+
511
+ return isset( $this->attachments[$index]->post_id ) ? $this->attachments[$index]->post_id : false;
512
  }
513
 
514
 
518
  *
519
  * @since 3.0
520
  */
521
+ function url( $index = null )
522
  {
523
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
 
524
 
525
+ return isset( $this->attachments[$index]->id ) ? wp_get_attachment_url( $this->attachments[$index]->id ) : false;
526
  }
527
 
528
 
532
  *
533
  * @since 3.0
534
  */
535
+ function field( $name = 'title', $index = null )
536
  {
537
+ $index = is_null( $index ) ? $this->attachments_ref : intval( $index );
538
+
539
+ return isset( $this->attachments[$index]->fields->$name ) ? $this->attachments[$index]->fields->$name : false;
540
  }
541
 
542
 
763
 
764
  targetAttachment = $(this).parents('.attachments-attachment');
765
 
766
+ targetAttachment.find('.attachment-meta').fadeOut(125);
767
+ targetAttachment.css('min-height',0).animate(
768
+ {
769
+ padding: 0,
770
+ margin: 0,
771
+ height: 0
772
+ },
773
+ 600,
774
+ function(){
775
+ targetAttachment.remove();
776
+ }
777
+ );
778
 
779
  } );
780
 
796
  $field_types = array(
797
  'text' => ATTACHMENTS_DIR . 'classes/fields/class.field.text.php',
798
  'textarea' => ATTACHMENTS_DIR . 'classes/fields/class.field.textarea.php',
799
+ 'select' => ATTACHMENTS_DIR . 'classes/fields/class.field.select.php',
800
  'wysiwyg' => ATTACHMENTS_DIR . 'classes/fields/class.field.wysiwyg.php',
801
  );
802
 
850
  'name' => 'title',
851
  'type' => 'text',
852
  'label' => __( 'Title', 'attachments' ),
853
+ 'meta' => array(),
854
  );
855
 
856
  $params = array_merge( $defaults, $params );
866
  if( isset( $params['label'] ) )
867
  $params['label'] = __( esc_html( $params['label'] ) );
868
 
869
+ if( !isset( $params['meta'] ) || !is_array( $params['meta'] ) )
870
+ $params['meta'] = array();
871
+
872
  // instantiate the class for this field and send it back
873
+ return new $this->fields[ $params['type'] ]( $params['name'], $params['label'], $params['meta'] );
874
  }
875
 
876
 
1068
  $name = sanitize_title( $field['name'] );
1069
  $label = esc_html( $field['label'] );
1070
  $default = isset( $field['default'] ) ? $field['default'] : false; // validated in the class
1071
+ $meta = isset( $field['meta'] ) ? $field['meta'] : array();
1072
+ $value = isset( $attachment->fields->$name ) ? $attachment->fields->$name : null;
1073
 
1074
+ $field = new $this->fields[$type]( $name, $label, $value, $meta );
 
 
1075
  $field->value = $field->format_value_for_input( $field->value );
1076
 
1077
  // does this field already have a unique ID?
1331
  $field_value = str_replace("\n", "%%ATTACHMENTS_NEWLINE%%", $field_value );
1332
 
1333
  // slashes were already added so we're going to strip them
1334
+ $field_value = stripslashes_deep( $field_value );
1335
 
1336
  // put back our newlines
1337
  $field_value = str_replace("%%ATTACHMENTS_NEWLINE%%", "\\n", $field_value );
1338
 
1339
  // encode the whole thing
1340
+ $field_value = $this->encode_field_value( $field_value );
1341
 
1342
  // encode things properly
1343
  $attachment['fields'][$key] = $field_value;
1367
 
1368
 
1369
 
1370
+ /**
1371
+ * Recursive function to encode a field type before saving
1372
+ * @param mixed $field_value The field value
1373
+ * @return mixed The encoded field value
1374
+ *
1375
+ * @since 3.3
1376
+ */
1377
+ function encode_field_value( $field_value = null )
1378
+ {
1379
+ if( is_null( $field_value ) )
1380
+ return;
1381
+
1382
+ if( is_object( $field_value ) )
1383
+ {
1384
+ $input = get_object_vars( $field_value );
1385
+
1386
+ foreach( $input as $key => $val )
1387
+ $field_value[$key] = $this->encode_field_value( $val );
1388
+
1389
+ $field_value = (object) $field_value;
1390
+ }
1391
+ elseif( is_array( $field_value ) )
1392
+ {
1393
+ foreach( $field_value as $key => $val )
1394
+ $field_value[$key] = $this->encode_field_value( $val );
1395
+ }
1396
+ else
1397
+ $field_value = htmlentities( $field_value, ENT_QUOTES, 'UTF-8' );
1398
+
1399
+ return $field_value;
1400
+ }
1401
+
1402
+
1403
+
1404
  /**
1405
  * Retrieves all Attachments for the submitted instance and post ID
1406
  *
1407
  * @since 3.0
1408
  */
1409
+ function get_attachments( $instance = null, $post_id = null )
1410
+ {
1411
+ $post_id = $this->determine_post_id( $post_id );
1412
+
1413
+ if( !$post_id )
1414
+ return false;
1415
+
1416
+ $attachments = array();
1417
+ $attachments_raw = $this->get_attachments_metadata( $post_id );
1418
+
1419
+ // we need to decode the fields (that were encoded during save) and run them through
1420
+ // their format_value_for_input as defined in it's class
1421
+ if( !is_null( $instance ) && is_string( $instance ) && isset( $attachments_raw->$instance ) )
1422
+ {
1423
+ foreach( $attachments_raw->$instance as $attachment )
1424
+ $attachments[] = $this->process_attachment( $attachment, $instance );
1425
+ }
1426
+ elseif( is_null( $instance ) )
1427
+ {
1428
+ // return them all, regardless of instance
1429
+ foreach( $attachments_raw as $instance => $attachments_unprocessed )
1430
+ foreach( $attachments_unprocessed as $unprocessed_attachment )
1431
+ $attachments[] = $this->process_attachment( $unprocessed_attachment, $instance );
1432
+ }
1433
+
1434
+ // tack on the post ID for each attachment
1435
+ for( $i = 0; $i < count( $attachments ); $i++ )
1436
+ $attachments[$i]->post_id = $post_id;
1437
+
1438
+ return $attachments;
1439
+ }
1440
+
1441
+
1442
+
1443
+ /**
1444
+ * Retrieves the post_meta record (saved as JSON) and processes it
1445
+ * @param int $post_id The post ID
1446
+ * @return object Attachments for the post
1447
+ *
1448
+ * @since 3.3
1449
+ */
1450
+ function get_attachments_metadata( $post_id )
1451
+ {
1452
+ $post_id = intval( $post_id );
1453
+
1454
+ // grab our JSON and decode it
1455
+ $attachments_json = get_post_meta( $post_id, $this->meta_key, true );
1456
+ $attachments_raw = is_string( $attachments_json ) ? json_decode( $attachments_json ) : false;
1457
+
1458
+ return $attachments_raw;
1459
+ }
1460
+
1461
+
1462
+
1463
+ /**
1464
+ * Determines a proper post ID based on whether one was passed, the global $post object, or a GET variable
1465
+ * @param int $post_id Desired post ID
1466
+ * @return mixed The understood post ID
1467
+ */
1468
+ function determine_post_id( $post_id = null )
1469
  {
1470
  global $post;
1471
 
1485
  else
1486
  {
1487
  // no post ID, nothing to do...
1488
+ $post_id = false;
1489
  }
1490
 
1491
+ return $post_id;
1492
+ }
1493
+
1494
 
 
 
 
1495
 
1496
+ /**
1497
+ * Processes Attachment (including fields) in preparation for return
1498
+ * @param object $attachment An Attachment object as it was stored as post metadata
1499
+ * @return object Post-processed Attachment data
1500
+ *
1501
+ * @since 3.3
1502
+ */
1503
+ function process_attachment( $attachment, $instance )
1504
+ {
1505
+ if( !is_object( $attachment ) || !is_string( $instance ) )
1506
+ return $attachment;
1507
+
1508
+ if( is_object( $attachment->fields ) )
1509
  {
1510
+ foreach( $attachment->fields as $key => $value )
1511
  {
1512
+ // loop through the instance fields to get the type
1513
+ if( isset( $this->instances[$instance]['fields'] ) )
1514
  {
1515
+ $type = '';
1516
+ foreach( $this->instances[$instance]['fields'] as $field )
1517
  {
1518
+ if( isset( $field['name'] ) && $field['name'] == $key )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1519
  {
1520
+ $type = isset( $field['type'] ) ? $field['type'] : false;
1521
+ break;
1522
  }
1523
  }
1524
+ if( isset( $this->fields[$type] ) )
1525
+ {
1526
+ // we need to decode the html entities that were encoded for the save
1527
+ $attachment->fields->$key = $this->decode_field_value( $attachment->fields->$key );
1528
+ }
1529
+ else
1530
+ {
1531
+ // the type doesn't exist
1532
+ $attachment->fields->$key = false;
1533
+ }
1534
+ }
1535
+ else
1536
+ {
1537
+ // this was a theme file request, just grab it
1538
+ $attachment->fields->$key = $this->decode_field_value( $attachment->fields->$key );
1539
  }
 
1540
  }
1541
  }
1542
+ return $attachment;
1543
+ }
1544
+
1545
+
1546
+
1547
+ /**
1548
+ * Recursive function to decode a field value when retrieving it
1549
+ * @param mixed $field_value The field value
1550
+ * @return mixed The encoded field value
1551
+ *
1552
+ * @since 3.3
1553
+ */
1554
+ function decode_field_value( $field_value = null )
1555
+ {
1556
+ if( is_null( $field_value ) )
1557
+ return;
1558
+
1559
+ if( is_object( $field_value ) )
1560
+ {
1561
+ $input = get_object_vars( $field_value );
1562
+
1563
+ foreach( $input as $key => $val )
1564
+ $field_value[$key] = $this->decode_field_value( $val );
1565
+
1566
+ $field_value = (object) $field_value;
1567
+ }
1568
+ elseif( is_array( $field_value ) )
1569
  {
1570
+ foreach( $field_value as $key => $val )
1571
+ $field_value[$key] = $this->decode_field_value( $val );
1572
  }
1573
+ else
1574
+ $field_value = html_entity_decode( $field_value, ENT_QUOTES, 'UTF-8' );
1575
 
1576
+ return $field_value;
1577
  }
1578
 
1579
 
classes/class.field.php CHANGED
@@ -10,15 +10,10 @@
10
  // Declare our class
11
  if ( !class_exists( 'Attachments_Field' ) ) :
12
 
13
- interface Attachments_Field_Template
14
- {
15
- public function html( $field );
16
- public function format_value_for_input( $value, $field = null );
17
- public function assets();
18
- public function init();
19
- }
20
-
21
- class Attachments_Field implements Attachments_Field_Template
22
  {
23
  public $instance; // the instance this field is used within
24
  public $name; // the user-defined field name
@@ -30,23 +25,46 @@ if ( !class_exists( 'Attachments_Field' ) ) :
30
  public $value; // the value for the field
31
  public $defaults; // stores possible defaults the user can use which correlate with WP Media meta
32
  public $default; // the user-defined default value when first selected from the modal
 
 
33
 
34
- function __construct( $name = 'name', $label = 'Name', $value = null )
 
 
 
 
 
 
 
35
  {
36
  $this->name = sanitize_title( $name );
37
  $this->label = __( esc_attr( $label) );
38
  $this->value = $value;
39
  $this->default = '';
40
-
41
  $this->defaults = array( 'title', 'caption', 'alt', 'description' ); // WordPress-specific Media meta
42
  // TODO: determine how to integrate with custom metadata that was added to Media
43
  }
44
 
 
 
 
 
 
 
 
45
  function set_field_instance( $instance, $field )
46
  {
47
  $field->instance = $instance;
48
  }
49
 
 
 
 
 
 
 
 
50
  function set_field_identifiers( $field, $uid = null )
51
  {
52
  // we MUST have an instance
@@ -65,39 +83,63 @@ if ( !class_exists( 'Attachments_Field' ) ) :
65
  $field->field_id = $this->field_name . $this->uid;
66
  }
67
 
 
 
 
 
 
 
68
  function set_field_type( $field_type )
69
  {
70
  $this->type = $field_type;
71
  }
72
 
 
 
 
 
 
 
73
  function set_field_default( $default = '' )
74
  {
75
  if( is_string( $default ) && !empty( $default ) && in_array( strtolower( $default ), $this->defaults ) )
76
  $this->default = strtolower( $default );
77
  }
78
 
79
- public function html( $field )
80
- {
81
- ?>
82
- <input type="text" name="<?php esc_attr_e( $field->field_name ); ?>" id="<?php esc_attr_e( $field->field_id ); ?>" class="attachments attachments-field attachments-field-<?php esc_attr_e( $field->field_name ); ?> attachments-field-<?php esc_attr_e( $field->field_id ); ?>" value="<?php esc_attr_e( $field->value ); ?>" data-default="<?php esc_attr_e( $field->default ); ?>" />
83
- <?php
84
- }
85
 
86
- public function format_value_for_input( $value, $field = null )
87
- {
88
- return $value;
89
- }
90
 
91
- public function assets()
92
- {
93
- return;
94
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
- public function init()
97
- {
98
- return;
99
- }
100
 
 
 
 
 
 
101
  }
102
 
103
- endif; // class_exists check
10
  // Declare our class
11
  if ( !class_exists( 'Attachments_Field' ) ) :
12
 
13
+ /**
14
+ * Attachments_Field
15
+ */
16
+ abstract class Attachments_Field
 
 
 
 
 
17
  {
18
  public $instance; // the instance this field is used within
19
  public $name; // the user-defined field name
25
  public $value; // the value for the field
26
  public $defaults; // stores possible defaults the user can use which correlate with WP Media meta
27
  public $default; // the user-defined default value when first selected from the modal
28
+ public $meta; // houses any metadata necessary for the field
29
+
30
 
31
+
32
+ /**
33
+ * Constructor
34
+ * @param string $name Field name
35
+ * @param string $label Field label
36
+ * @param mixed $value Field value
37
+ */
38
+ function __construct( $name = 'name', $label = 'Name', $value = null, $meta = array() )
39
  {
40
  $this->name = sanitize_title( $name );
41
  $this->label = __( esc_attr( $label) );
42
  $this->value = $value;
43
  $this->default = '';
44
+ $this->meta = $meta;
45
  $this->defaults = array( 'title', 'caption', 'alt', 'description' ); // WordPress-specific Media meta
46
  // TODO: determine how to integrate with custom metadata that was added to Media
47
  }
48
 
49
+
50
+
51
+ /**
52
+ * Sets the field instance
53
+ * @param string $instance The instance name
54
+ * @param Attachments_Field $field The field object
55
+ */
56
  function set_field_instance( $instance, $field )
57
  {
58
  $field->instance = $instance;
59
  }
60
 
61
+
62
+
63
+ /**
64
+ * Sets the UID, name, and id of the field
65
+ * @param Attachments_Field $field The field object
66
+ * @param string $uid Existing UID if applicable
67
+ */
68
  function set_field_identifiers( $field, $uid = null )
69
  {
70
  // we MUST have an instance
83
  $field->field_id = $this->field_name . $this->uid;
84
  }
85
 
86
+
87
+
88
+ /**
89
+ * Sets the field type of the field
90
+ * @param string $field_type Registered field type name
91
+ */
92
  function set_field_type( $field_type )
93
  {
94
  $this->type = $field_type;
95
  }
96
 
97
+
98
+
99
+ /**
100
+ * Sets the WordPress meta attribute to be used as the default
101
+ * @param string $default One of the approved defauls (title, caption, alt, description)
102
+ */
103
  function set_field_default( $default = '' )
104
  {
105
  if( is_string( $default ) && !empty( $default ) && in_array( strtolower( $default ), $this->defaults ) )
106
  $this->default = strtolower( $default );
107
  }
108
 
 
 
 
 
 
 
109
 
 
 
 
 
110
 
111
+ /**
112
+ * Outputs the HTML for the field
113
+ * @param Attachments_Field $field The field object
114
+ * @return void
115
+ */
116
+ abstract public function html( $field );
117
+
118
+
119
+
120
+ /**
121
+ * Filter the field value to appear within the input as expected
122
+ * @param string $value The field value
123
+ * @param Attachments_field $field The field object
124
+ * @return string The formatted value
125
+ */
126
+ abstract public function format_value_for_input( $value, $field = null );
127
+
128
+
129
+
130
+ /**
131
+ * Fires once per field type per instance and outputs any additional assets (e.g. external JavaScript)
132
+ * @return void
133
+ */
134
+ abstract public function assets();
135
+
136
 
 
 
 
 
137
 
138
+ /**
139
+ * Hook into WordPress' init action
140
+ * @return void
141
+ */
142
+ abstract public function init();
143
  }
144
 
145
+ endif; // class_exists check
classes/fields/class.field.select.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Attachments select field
5
+ *
6
+ * @package Attachments
7
+ * @subpackage Main
8
+ */
9
+
10
+ class Attachments_Field_Select extends Attachments_Field
11
+ {
12
+
13
+ private $allow_null; // whether null is allowed
14
+ private $multiple; // whether it's a multiple <select>
15
+ private $options; // the <options> for the <select>
16
+
17
+
18
+ /**
19
+ * Constructor
20
+ * @param string $name Field name
21
+ * @param string $label Field label
22
+ * @param mixed $value Field value
23
+ */
24
+ function __construct( $name = 'name', $label = 'Name', $value = null, $meta = array() )
25
+ {
26
+ $defaults = array(
27
+ 'allow_null' => true,
28
+ 'multiple' => false,
29
+ 'options' => array(), // no <option>s by default
30
+ );
31
+
32
+ $meta = array_merge( $defaults, $meta );
33
+
34
+ $this->options = is_array( $meta['options'] ) ? $meta['options'] : array();
35
+ $this->allow_null = is_bool( $meta['allow_null'] ) ? $meta['allow_null'] : true;
36
+ $this->multiple = is_bool( $meta['multiple'] ) ? $meta['multiple'] : false;
37
+
38
+ parent::__construct( $name, $label, $value, $meta );
39
+ }
40
+
41
+
42
+
43
+ /**
44
+ * Outputs the HTML for the field
45
+ * @param Attachments_Field $field The field object
46
+ * @return void
47
+ */
48
+ function html( $field )
49
+ {
50
+ ?>
51
+ <select name="<?php esc_attr_e( $field->field_name ); ?><?php if( $this->multiple ) : ?>[]<?php endif; ?>" id="<?php esc_attr_e( $field->field_id ); ?>" class="attachments attachments-field attachments-field-<?php esc_attr_e( $field->field_name ); ?> attachments-field-<?php esc_attr_e( $field->field_id ); ?>"<?php if( $this->multiple ) : ?> multiple<?php endif; ?>>
52
+ <?php if( $this->allow_null && !$this->multiple ) : ?><option value="">&mdash;</option><?php endif; ?>
53
+ <?php foreach ( $this->options as $option_value => $option_label ) : ?>
54
+ <?php
55
+ $selected = selected( $field->value, $option_value ) ? ' selected' : '';
56
+
57
+ if( is_array( $field->value ) )
58
+ $selected = in_array( $option_value, $field->value ) ? ' selected' : '';
59
+
60
+ if( is_object( $field->value ) )
61
+ {
62
+ $values = get_object_vars( $field->value );
63
+ $selected = in_array( $option_value, $values ) ? ' selected' : '';
64
+ }
65
+
66
+ ?>
67
+ <option value="<?php esc_attr_e( $option_value ); ?>"<?php echo $selected; ?>>
68
+ <?php echo $option_label; ?>
69
+ </option>
70
+ <?php endforeach; ?>
71
+ </select>
72
+ <?php
73
+ }
74
+
75
+
76
+
77
+ /**
78
+ * Filter the field value to appear within the input as expected
79
+ * @param string $value The field value
80
+ * @param Attachments_field $field The field object
81
+ * @return string The formatted value
82
+ */
83
+ function format_value_for_input( $value, $field = null )
84
+ {
85
+ return $value;
86
+ }
87
+
88
+
89
+
90
+ /**
91
+ * Fires once per field type per instance and outputs any additional assets (e.g. external JavaScript)
92
+ * @return void
93
+ */
94
+ public function assets()
95
+ {
96
+ return;
97
+ }
98
+
99
+
100
+
101
+ /**
102
+ * Hook into WordPress' init action
103
+ * @return void
104
+ */
105
+ function init()
106
+ {
107
+ return;
108
+ }
109
+
110
+ }
classes/fields/class.field.text.php CHANGED
@@ -7,14 +7,27 @@
7
  * @subpackage Main
8
  */
9
 
10
- class Attachments_Field_Text extends Attachments_Field implements Attachments_Field_Template
11
  {
12
 
13
- function __construct( $name = 'name', $label = 'Name', $value = null )
 
 
 
 
 
 
14
  {
15
- parent::__construct( $name, $label, $value );
16
  }
17
 
 
 
 
 
 
 
 
18
  function html( $field )
19
  {
20
  ?>
@@ -22,19 +35,39 @@ class Attachments_Field_Text extends Attachments_Field implements Attachments_Fi
22
  <?php
23
  }
24
 
 
 
 
 
 
 
 
 
25
  function format_value_for_input( $value, $field = null )
26
  {
27
  return htmlspecialchars( $value, ENT_QUOTES );
28
  }
29
 
 
 
 
 
 
 
30
  public function assets()
31
  {
32
  return;
33
  }
34
 
 
 
 
 
 
 
35
  function init()
36
  {
37
  return;
38
  }
39
 
40
- }
7
  * @subpackage Main
8
  */
9
 
10
+ class Attachments_Field_Text extends Attachments_Field
11
  {
12
 
13
+ /**
14
+ * Constructor
15
+ * @param string $name Field name
16
+ * @param string $label Field label
17
+ * @param mixed $value Field value
18
+ */
19
+ function __construct( $name = 'name', $label = 'Name', $value = null, $meta = array() )
20
  {
21
+ parent::__construct( $name, $label, $value, $meta );
22
  }
23
 
24
+
25
+
26
+ /**
27
+ * Outputs the HTML for the field
28
+ * @param Attachments_Field $field The field object
29
+ * @return void
30
+ */
31
  function html( $field )
32
  {
33
  ?>
35
  <?php
36
  }
37
 
38
+
39
+
40
+ /**
41
+ * Filter the field value to appear within the input as expected
42
+ * @param string $value The field value
43
+ * @param Attachments_field $field The field object
44
+ * @return string The formatted value
45
+ */
46
  function format_value_for_input( $value, $field = null )
47
  {
48
  return htmlspecialchars( $value, ENT_QUOTES );
49
  }
50
 
51
+
52
+
53
+ /**
54
+ * Fires once per field type per instance and outputs any additional assets (e.g. external JavaScript)
55
+ * @return void
56
+ */
57
  public function assets()
58
  {
59
  return;
60
  }
61
 
62
+
63
+
64
+ /**
65
+ * Hook into WordPress' init action
66
+ * @return void
67
+ */
68
  function init()
69
  {
70
  return;
71
  }
72
 
73
+ }
classes/fields/class.field.textarea.php CHANGED
@@ -7,14 +7,27 @@
7
  * @subpackage Main
8
  */
9
 
10
- class Attachments_Field_Textarea extends Attachments_Field implements Attachments_Field_Template
11
  {
12
 
13
- function __construct( $name = 'name', $label = 'Name', $value = null )
 
 
 
 
 
 
14
  {
15
- parent::__construct( $name, $label, $value );
16
  }
17
 
 
 
 
 
 
 
 
18
  function html( $field )
19
  {
20
  ?>
@@ -22,19 +35,39 @@ class Attachments_Field_Textarea extends Attachments_Field implements Attachment
22
  <?php
23
  }
24
 
 
 
 
 
 
 
 
 
25
  function format_value_for_input( $value, $field = null )
26
  {
27
  return $value;
28
  }
29
 
 
 
 
 
 
 
30
  public function assets()
31
  {
32
  return;
33
  }
34
 
 
 
 
 
 
 
35
  function init()
36
  {
37
  return;
38
  }
39
 
40
- }
7
  * @subpackage Main
8
  */
9
 
10
+ class Attachments_Field_Textarea extends Attachments_Field
11
  {
12
 
13
+ /**
14
+ * Constructor
15
+ * @param string $name Field name
16
+ * @param string $label Field label
17
+ * @param mixed $value Field value
18
+ */
19
+ function __construct( $name = 'name', $label = 'Name', $value = null, $meta = array() )
20
  {
21
+ parent::__construct( $name, $label, $value, $meta );
22
  }
23
 
24
+
25
+
26
+ /**
27
+ * Outputs the HTML for the field
28
+ * @param Attachments_Field $field The field object
29
+ * @return void
30
+ */
31
  function html( $field )
32
  {
33
  ?>
35
  <?php
36
  }
37
 
38
+
39
+
40
+ /**
41
+ * Filter the field value to appear within the input as expected
42
+ * @param string $value The field value
43
+ * @param Attachments_field $field The field object
44
+ * @return string The formatted value
45
+ */
46
  function format_value_for_input( $value, $field = null )
47
  {
48
  return $value;
49
  }
50
 
51
+
52
+
53
+ /**
54
+ * Fires once per field type per instance and outputs any additional assets (e.g. external JavaScript)
55
+ * @return void
56
+ */
57
  public function assets()
58
  {
59
  return;
60
  }
61
 
62
+
63
+
64
+ /**
65
+ * Hook into WordPress' init action
66
+ * @return void
67
+ */
68
  function init()
69
  {
70
  return;
71
  }
72
 
73
+ }
classes/fields/class.field.wysiwyg.php CHANGED
@@ -7,16 +7,28 @@
7
  * @subpackage Main
8
  */
9
 
10
- class Attachments_Field_WYSIWYG extends Attachments_Field implements Attachments_Field_Template
11
  {
12
 
13
- function __construct( $name = 'name', $label = 'Name', $value = null )
 
 
 
 
 
 
14
  {
15
- parent::__construct( $name, $label, $value );
16
 
17
  add_filter( 'wp_default_editor', array( $this, 'wp_default_editor' ) );
18
  }
19
 
 
 
 
 
 
 
20
  function init()
21
  {
22
  global $post;
@@ -29,6 +41,13 @@ class Attachments_Field_WYSIWYG extends Attachments_Field implements Attachments
29
  echo '<style type="text/css">#poststuff .postarea { display:none; }</style>';
30
  }
31
 
 
 
 
 
 
 
 
32
  function html( $field )
33
  {
34
  ?>
@@ -40,6 +59,12 @@ class Attachments_Field_WYSIWYG extends Attachments_Field implements Attachments
40
  <?php
41
  }
42
 
 
 
 
 
 
 
43
  function assets()
44
  {
45
  if( 'true' == get_user_meta( get_current_user_id(), 'rich_editing', true ) ) :
@@ -96,14 +121,28 @@ class Attachments_Field_WYSIWYG extends Attachments_Field implements Attachments
96
  endif;
97
  }
98
 
 
 
 
 
 
 
 
 
99
  function format_value_for_input( $value, $field = null )
100
  {
101
  return wp_richedit_pre( $value );
102
  }
103
 
 
 
 
 
 
 
104
  function wp_default_editor()
105
  {
106
  return 'tinymce'; // html or tinymce
107
  }
108
 
109
- }
7
  * @subpackage Main
8
  */
9
 
10
+ class Attachments_Field_WYSIWYG extends Attachments_Field
11
  {
12
 
13
+ /**
14
+ * Constructor
15
+ * @param string $name Field name
16
+ * @param string $label Field label
17
+ * @param mixed $value Field value
18
+ */
19
+ function __construct( $name = 'name', $label = 'Name', $value = null, $meta = array() )
20
  {
21
+ parent::__construct( $name, $label, $value, $meta );
22
 
23
  add_filter( 'wp_default_editor', array( $this, 'wp_default_editor' ) );
24
  }
25
 
26
+
27
+
28
+ /**
29
+ * Hook into WordPress' init action
30
+ * @return void
31
+ */
32
  function init()
33
  {
34
  global $post;
41
  echo '<style type="text/css">#poststuff .postarea { display:none; }</style>';
42
  }
43
 
44
+
45
+
46
+ /**
47
+ * Outputs the HTML for the field
48
+ * @param Attachments_Field $field The field object
49
+ * @return void
50
+ */
51
  function html( $field )
52
  {
53
  ?>
59
  <?php
60
  }
61
 
62
+
63
+
64
+ /**
65
+ * Fires once per field type per instance and outputs any additional assets (e.g. external JavaScript)
66
+ * @return void
67
+ */
68
  function assets()
69
  {
70
  if( 'true' == get_user_meta( get_current_user_id(), 'rich_editing', true ) ) :
121
  endif;
122
  }
123
 
124
+
125
+
126
+ /**
127
+ * Filter the field value to appear within the input as expected
128
+ * @param string $value The field value
129
+ * @param Attachments_field $field The field object
130
+ * @return string The formatted value
131
+ */
132
  function format_value_for_input( $value, $field = null )
133
  {
134
  return wp_richedit_pre( $value );
135
  }
136
 
137
+
138
+
139
+ /**
140
+ * Callback for 'wp_default_editor' action in constructor. Sets the default editor to TinyMCE.
141
+ * @return string Editor name
142
+ */
143
  function wp_default_editor()
144
  {
145
  return 'tinymce'; // html or tinymce
146
  }
147
 
148
+ }
css/attachments.css CHANGED
@@ -8,6 +8,7 @@ a.attachments-invoke {
8
  padding:5px 0 25px;
9
  border-bottom:1px solid #e7e7e7;
10
  min-height:125px;
 
11
  }
12
 
13
  .attachments-attachment:before,
@@ -189,6 +190,16 @@ a.attachments-invoke {
189
  resize:vertical;
190
  }
191
 
 
 
 
 
 
 
 
 
 
 
192
  .attachments-handle {
193
  position:absolute;
194
  left:0;
8
  padding:5px 0 25px;
9
  border-bottom:1px solid #e7e7e7;
10
  min-height:125px;
11
+ overflow:hidden;
12
  }
13
 
14
  .attachments-attachment:before,
190
  resize:vertical;
191
  }
192
 
193
+ /* Select styling */
194
+ .attachments-attachment-field-select select {
195
+ display:block;
196
+ width:100%;
197
+ }
198
+
199
+ .attachments-attachment-field-select select[multiple] {
200
+ height:100px;
201
+ }
202
+
203
  .attachments-handle {
204
  position:absolute;
205
  left:0;
index.php CHANGED
@@ -6,7 +6,7 @@
6
  * Description: Attachments gives the ability to append any number of Media Library items to Pages, Posts, and Custom Post Types
7
  * Author: Jonathan Christopher
8
  * Author URI: http://mondaybynoon.com/
9
- * Version: 3.2
10
  * Text Domain: attachments
11
  * Domain Path: /languages/
12
  * License: GPLv2 or later
6
  * Description: Attachments gives the ability to append any number of Media Library items to Pages, Posts, and Custom Post Types
7
  * Author: Jonathan Christopher
8
  * Author URI: http://mondaybynoon.com/
9
+ * Version: 3.3
10
  * Text Domain: attachments
11
  * Domain Path: /languages/
12
  * License: GPLv2 or later
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://mondaybynoon.com/donate/
4
  Tags: post, page, posts, pages, images, PDF, doc, Word, image, jpg, jpeg, picture, pictures, photos, attachment
5
  Requires at least: 3.0
6
  Tested up to: 3.5
7
- Stable tag: 3.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -91,7 +91,11 @@ Attachments uses WordPress' built in Media library for uploads and storage.
91
 
92
  = I lost my Attachments after upgrading! =
93
 
94
- ***DO NOT update any Post/Page/CPT that should have existing Attachments***, the data *has not been lost*. Please reference the **Installation > Upgrade Notice** details.
 
 
 
 
95
 
96
  == Screenshots ==
97
 
@@ -103,6 +107,12 @@ Attachments uses WordPress' built in Media library for uploads and storage.
103
 
104
  == Changelog ==
105
 
 
 
 
 
 
 
106
  = 3.2 =
107
  * Added option to disable the Settings screen
108
  * Added the ability to set a default for fields using the metadata that exists in WordPress. Available defaults include: title, caption, alt, and description. If set, the metadata for the correlating field will be used as the field default when initially adding an Attachment from the Media modal. Only applies to text, textarea, and wysiwyg fields.
@@ -338,19 +348,27 @@ Planned feature additions include:
338
 
339
  == Usage ==
340
 
 
 
341
  Attachments ships with a `Settings` screen (found under the `Settings` menu in the main WordPress admin navigation) that facilitates data migration from version 1.x and also offers some code snippets. If you would like to **disable the Settings screen** add the following to your theme's `functions.php`:
342
 
343
  `define( 'ATTACHMENTS_SETTINGS_SCREEN', false ); // disable the Settings screen`
344
 
 
 
345
  When Attachments is first activated, a default instance is created titled Attachments. It has two fields:
346
 
347
  1. Title
348
  1. Caption
349
 
 
 
350
  If you would like to *disable the default instance* (meta box titled 'Attachments' with a 'Title' and 'Caption' field) add the following to your `wp-config.php`:
351
 
352
  `define( 'ATTACHMENTS_DEFAULT_INSTANCE', false );`
353
 
 
 
354
  You may create instances with your own custom fields by using the `attachments_register` action. To create your own instance add the following to your theme's `functions.php` or your own plugin:
355
 
356
  `<?php
@@ -411,6 +429,69 @@ function my_attachments( $attachments )
411
 
412
  add_action( 'attachments_register', 'my_attachments' );`
413
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
  Once your instances are set up and working, you'll also need to edit your theme's template files to pull the data to the front end. To retrieve the Attachments for the current post, add this within The Loop:
415
 
416
  `<?php $attachments = new Attachments( 'attachments' ); /* pass the instance name */ ?>
@@ -425,6 +506,8 @@ Once your instances are set up and working, you'll also need to edit your theme'
425
  </ul>
426
  <?php endif; ?>`
427
 
 
 
428
  If you want to get the Attachments for a post **outside The Loop**, add a second parameter with the post ID when instantiating Attachments:
429
 
430
  `<?php
@@ -442,6 +525,8 @@ If you want to get the Attachments for a post **outside The Loop**, add a second
442
  </ul>
443
  <?php endif; ?>`
444
 
 
 
445
  You can also retrieve various attributes of the current Attachment using these utility functions:
446
 
447
  `<?php $attachments = new Attachments( 'attachments' ); /* pass the instance name */ ?>
@@ -465,12 +550,72 @@ You can also retrieve various attributes of the current Attachment using these u
465
  </ul>
466
  <?php endif; ?>`
467
 
 
 
468
  If you don't want to use the above implementation to loop through your Attachments, can also retrieve them explicitly:
469
 
470
  `<?php $attachments = new Attachments( 'attachments' ); ?>
471
  <?php if( $attachments->exist() ) : ?>
472
- <?php if( $attachment = $attachments->get_single( 0 ) ) : ?>
 
473
  <h3>Attachment at index 0:</h3>
474
  <pre><?php print_r( $attachment ); ?></pre>
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  <?php endif; ?>
476
  <?php endif; ?>`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  Tags: post, page, posts, pages, images, PDF, doc, Word, image, jpg, jpeg, picture, pictures, photos, attachment
5
  Requires at least: 3.0
6
  Tested up to: 3.5
7
+ Stable tag: 3.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
91
 
92
  = I lost my Attachments after upgrading! =
93
 
94
+ ***DO NOT update any Post/Page/CPT that should have existing Attachments***, the data *has not been lost*.
95
+
96
+ If you disabled the default intsance after migrating, used the default values when migrating, and used a snippet from the docs to add a new one, **make sure your instance names match**. The default value during migration uses an instance name of `attachments` while many snippets use `my_attachments`.
97
+
98
+ Else: please reference the **Installation > Upgrade Notice** details.
99
 
100
  == Screenshots ==
101
 
107
 
108
  == Changelog ==
109
 
110
+ = 3.3 =
111
+ * Added a `search()` method to allow searching for Attachments based on their attributes (e.g. attachment ID, post ID, post type, field values, etc.)
112
+ * Improved the 'Remove' animation
113
+ * New field: select
114
+ * New parameter for Attachments attributes methods. You can pass the index (`int`) of the Attachment you'd like to utilize when firing the method.
115
+
116
  = 3.2 =
117
  * Added option to disable the Settings screen
118
  * Added the ability to set a default for fields using the metadata that exists in WordPress. Available defaults include: title, caption, alt, and description. If set, the metadata for the correlating field will be used as the field default when initially adding an Attachment from the Media modal. Only applies to text, textarea, and wysiwyg fields.
348
 
349
  == Usage ==
350
 
351
+ = Disable Settings Screen =
352
+
353
  Attachments ships with a `Settings` screen (found under the `Settings` menu in the main WordPress admin navigation) that facilitates data migration from version 1.x and also offers some code snippets. If you would like to **disable the Settings screen** add the following to your theme's `functions.php`:
354
 
355
  `define( 'ATTACHMENTS_SETTINGS_SCREEN', false ); // disable the Settings screen`
356
 
357
+ = Setting Up Instances =
358
+
359
  When Attachments is first activated, a default instance is created titled Attachments. It has two fields:
360
 
361
  1. Title
362
  1. Caption
363
 
364
+ **Disable the Default Instance**
365
+
366
  If you would like to *disable the default instance* (meta box titled 'Attachments' with a 'Title' and 'Caption' field) add the following to your `wp-config.php`:
367
 
368
  `define( 'ATTACHMENTS_DEFAULT_INSTANCE', false );`
369
 
370
+ **Create Custom Instances**
371
+
372
  You may create instances with your own custom fields by using the `attachments_register` action. To create your own instance add the following to your theme's `functions.php` or your own plugin:
373
 
374
  `<?php
429
 
430
  add_action( 'attachments_register', 'my_attachments' );`
431
 
432
+ **Fields Reference**
433
+
434
+ At this time there are **four** field types available:
435
+
436
+ 1. `text`
437
+ 1. `textarea`
438
+ 1. `select`
439
+ 1. `wysiwyg`
440
+
441
+ When declaring fields for your instance, you'll be composing an array of fields, each with an array of parameters that set the various attributes of each field. Here is a full example of all available parameters for all available fields:
442
+
443
+ `<?php
444
+ /**
445
+ * Fields for the instance are stored in an array. Each field consists of
446
+ * an array with three required keys: name, type, label
447
+ * and one optional key: meta
448
+ *
449
+ * name - (string) The field name used. No special characters.
450
+ * type - (string) The registered field type.
451
+ * Fields available: text, textarea, wysiwyg, select
452
+ * label - (string) The label displayed for the field.
453
+ * default - (string) The default WordPress metadata to use when initially adding the Attachment
454
+ * Defaults available: title, caption, alt, description
455
+ * meta - (array) The field-specific parameters that apply only to that field type
456
+ */
457
+
458
+ $fields => array(
459
+ array(
460
+ 'name' => 'title', // unique field name
461
+ 'type' => 'text', // registered field type
462
+ 'label' => __( 'Title', 'attachments' ), // label to display
463
+ 'default' => 'title', // default value upon selection
464
+ ),
465
+ array(
466
+ 'name' => 'caption', // unique field name
467
+ 'type' => 'textarea', // registered field type
468
+ 'label' => __( 'Caption', 'attachments' ), // label to display
469
+ 'default' => 'caption', // default value upon selection
470
+ ),
471
+ array(
472
+ 'name' => 'option', // unique field name
473
+ 'type' => 'select', // registered field type
474
+ 'label' => __( 'Option', 'attachments' ), // label to display
475
+ 'meta' => array( // field-specific meta as defined by field class
476
+ 'allow_null' => true, // allow null value? (adds 'empty' <option>)
477
+ 'multiple' => true, // multiple <select>?
478
+ 'options' => array( // the <option>s to use
479
+ '1' => 'Option 1',
480
+ '2' => 'Option 2',
481
+ )
482
+ ),
483
+ ),
484
+ array(
485
+ 'name' => 'description', // unique field name
486
+ 'type' => 'wysiwyg', // registered field type
487
+ 'label' => __( 'Description', 'attachments' ), // label to display
488
+ 'default' => 'description', // default value upon selection
489
+ ),
490
+ );
491
+ ?>`
492
+
493
+ = Pulling Attachments to your Theme =
494
+
495
  Once your instances are set up and working, you'll also need to edit your theme's template files to pull the data to the front end. To retrieve the Attachments for the current post, add this within The Loop:
496
 
497
  `<?php $attachments = new Attachments( 'attachments' ); /* pass the instance name */ ?>
506
  </ul>
507
  <?php endif; ?>`
508
 
509
+ **Retrieve Attachments Outside The Loop**
510
+
511
  If you want to get the Attachments for a post **outside The Loop**, add a second parameter with the post ID when instantiating Attachments:
512
 
513
  `<?php
525
  </ul>
526
  <?php endif; ?>`
527
 
528
+ **Retrieve Attachment Attributes**
529
+
530
  You can also retrieve various attributes of the current Attachment using these utility functions:
531
 
532
  `<?php $attachments = new Attachments( 'attachments' ); /* pass the instance name */ ?>
550
  </ul>
551
  <?php endif; ?>`
552
 
553
+ **Retrieve Single Attachments**
554
+
555
  If you don't want to use the above implementation to loop through your Attachments, can also retrieve them explicitly:
556
 
557
  `<?php $attachments = new Attachments( 'attachments' ); ?>
558
  <?php if( $attachments->exist() ) : ?>
559
+ <?php $my_index = 0; ?>
560
+ <?php if( $attachment = $attachments->get_single( $my_index ) ) : ?>
561
  <h3>Attachment at index 0:</h3>
562
  <pre><?php print_r( $attachment ); ?></pre>
563
+ <ul>
564
+ <li>
565
+ ID: <?php echo $attachments->id( $my_index ); ?><br />
566
+ Type: <?php echo $attachments->type( $my_index ); ?><br />
567
+ Subtype: <?php echo $attachments->subtype( $my_index ); ?><br />
568
+ URL: <?php echo $attachments->url( $my_index ); ?><br />
569
+ Image: <?php echo $attachments->image( 'thumbnail', $my_index ); ?><br />
570
+ Source: <?php echo $attachments->src( 'full', $my_index ); ?><br />
571
+ Size: <?php echo $attachments->filesize( $my_index ); ?><br />
572
+ Title Field: <?php echo $attachments->field( 'title', $my_index ); ?><br />
573
+ Caption Field: Name: <?php echo $attachments->field( 'caption', $my_index ); ?>
574
+ </li>
575
+ </ul>
576
  <?php endif; ?>
577
  <?php endif; ?>`
578
+
579
+ = Search =
580
+
581
+ Attachments provides a method of searching it's own data using a number of attributes. This faciliates a search to be as widespread or as specific as you'd like.
582
+
583
+ `<?php
584
+ $attachments = new Attachments();
585
+
586
+ $search_args = array(
587
+ 'instance' => 'attachments', // search all instances
588
+ 'fields' => array( 'caption' ), // search the 'caption' field only
589
+ );
590
+
591
+ $attachments->search( 'lorem ipsum', $search_args ); // search for 'lorem ipsum'
592
+
593
+ if( $attachments->exist() ) : ?>
594
+ <h3>Attachments</h3>
595
+ <ul>
596
+ <?php while( $attachments->get() ) : ?>
597
+ <li>
598
+ Attachment ID: <?php echo $attachments->id(); ?><br />
599
+ Post ID: <?php echo $attachments->post_id(); ?><br />
600
+ Title Field: <?php echo $attachments->field( 'title' ); ?><br />
601
+ Caption Field: <?php echo $attachments->field( 'caption' ); ?>
602
+ </li>
603
+ <?php endwhile; ?>
604
+ </ul>
605
+ <?php endif;
606
+ ?>`
607
+
608
+ The full list of available search arguments (and their defaults) is as follows:
609
+
610
+ `<?php
611
+ $defaults = array(
612
+ 'attachment_id' => null, // (int) not searching for a single attachment ID
613
+ 'instance' => 'attachments', // (string) the instance you want to search
614
+ 'post_type' => null, // (string) search 'any' post type
615
+ 'post_id' => null, // (int) searching all posts
616
+ 'post_status' => 'publish', // (string) search only published posts
617
+ 'fields' => null, // (string|array) search all fields
618
+ );
619
+ ?>`
620
+
621
+ Once you've performed your search, you can loop through the returned Attachments as you normally would.