version = '3.5.1';
$this->url = ATTACHMENTS_URL;
$this->dir = ATTACHMENTS_DIR;
$plugin = 'attachments/index.php';
// includes
include_once( ATTACHMENTS_DIR . 'upgrade.php' );
include_once( ATTACHMENTS_DIR . '/classes/class.attachments.legacy.php' );
include_once( ATTACHMENTS_DIR . '/classes/class.attachments.search.php' );
include_once( ATTACHMENTS_DIR . '/classes/class.field.php' );
// include our fields
$this->fields = $this->get_field_types();
// set our image sizes
$this->image_sizes = array_merge( $this->image_sizes, get_intermediate_image_sizes() );
// add 'Extend' link
add_filter( "plugin_action_links_$plugin", array( $this, 'plugin_settings_link' ) );
// set up l10n
add_action( 'plugins_loaded', array( $this, 'l10n' ) );
// load extensions
add_action( 'plugins_loaded', array( $this, 'load_extensions' ) );
// hook into WP
add_action( 'admin_enqueue_scripts', array( $this, 'assets' ), 999, 1 );
// register our user-defined instances
add_action( 'init', array( $this, 'setup_instances' ) );
// determine which instances apply to the current post type
add_action( 'init', array( $this, 'set_instances_for_current_post_type' ) );
add_action( 'add_meta_boxes', array( $this, 'meta_box_init' ) );
add_action( 'admin_footer', array( $this, 'admin_footer' ) );
add_action( 'save_post', array( $this, 'save' ) );
// only show the Settings screen if it hasn't been explicitly disabled
if( !( defined( 'ATTACHMENTS_SETTINGS_SCREEN' ) && ATTACHMENTS_SETTINGS_SCREEN === false ) )
add_action( 'admin_menu', array( $this, 'admin_page' ) );
add_action( 'admin_head', array( $this, 'field_inits' ) );
add_action( 'admin_print_footer_scripts', array( $this, 'field_assets' ) );
add_action( 'admin_init', array( $this, 'admin_init' ) );
// execution of actions varies depending on whether we're in the admin or not and an instance was passed
if( is_admin() )
{
add_action( 'after_setup_theme', array( $this, 'apply_init_filters' ) );
$this->attachments = $this->get_attachments( $instance, $post_id );
}
elseif( !is_null( $instance ) )
{
$this->apply_init_filters();
$this->attachments = $this->get_attachments( $instance, $post_id );
}
}
function plugin_settings_link( $links )
{
$extend_link = ''. __( 'Extend', 'attachments' ) . '';
array_unshift( $links, $extend_link );
return $links;
}
/**
* Callback for WordPress' admin_init action
*
* @since 3.4.3
*/
function admin_init()
{
if( current_user_can( 'delete_posts' ) )
add_action( 'delete_post', array( $this, 'handle_wp_post_delete' ), 10 );
}
/**
* Getter for the existing fields
*
* @return array
* @since 3.5
*/
function get_fields()
{
return $this->fields;
}
/**
* Callback for WordPress' delete_post action. Searches all saved Attachments
* data for any records using a deleted attachment. If found, the record is removed.
*
* @param int $pid Post ID
* @since 3.4.3
*/
function handle_wp_post_delete( $pid )
{
// check to make sure it was an attachment
if( 'attachment' != get_post_type( $pid ) )
return;
// if a user deletes an attachment from the Media library (but it's been used
// in Attachments somewhere else) we need to clean that up...
// we hook into delete_post because the only other option is to filter
// each Attachment when retrieving Attachments via get_attachments()
// which could potentially be a ton of database calls
// so we're going to use the search class to find all instances
// for any occurrence of the deleted attachment (which has an ID of $pid)
if( is_array( $this->instances ) )
{
foreach( $this->instances as $instance => $details )
{
$search_args = array(
'instance' => $instance,
'attachment_id' => intval( $pid ),
);
$this->search( null, $search_args );
if( $this->exist() )
{
// we've got a hit (e.g. an existing post uses the deleted attachment)
while( $attachment = $this->get() )
{
$post_id = $attachment->post_id;
// we'll use the post ID to snag the details
$post_attachments = $this->get_attachments_metadata( $post_id );
if( is_object( $post_attachments ) )
{
foreach( $post_attachments as $existing_instance => $existing_instance_attachments )
foreach( $existing_instance_attachments as $existing_instance_attachment_key => $existing_instance_attachment )
if( $pid == intval( $existing_instance_attachment->id ) )
unset( $post_attachments->{$existing_instance}[$existing_instance_attachment_key] );
// saving routine assumes array from POST so we'll typecast it
$post_attachments = (array) $post_attachments;
// save the revised Attachments metadata
$this->save_metadata( $post_id, $post_attachments );
}
}
}
}
}
}
/**
* Getter for the current meta_key
*
* @since 3.4.2
*/
function get_meta_key()
{
return $this->meta_key;
}
/**
* Getter for our URL
*
* @since 3.5
*/
function get_url()
{
return $this->url;
}
/**
* Register our textdomain for l10n
*
* @since 3.4.2
*/
function l10n()
{
load_plugin_textdomain( 'attachments', false, trailingslashit( ATTACHMENTS_DIR ) . 'languages' );
}
function load_extensions()
{
do_action( 'attachments_extension', $this );
}
/**
* Various initialization filter triggers
*
* @since 3.4
*/
function apply_init_filters()
{
// allows a different meta_key to be used
$this->meta_key = apply_filters( 'attachments_meta_key', $this->meta_key );
}
/**
* Facilitates searching for Attachments
*
* @since 3.3
*/
function search( $query = null, $params = array() )
{
$results = new AttachmentsSearch( $query, $params );
$this->attachments = $results->results;
}
/**
* Returns whether or not the current object has any Attachments
*
* @since 3.0
*/
function exist()
{
return !empty( $this->attachments );
}
/**
* Returns the number of Attachments
*
* @since 3.0.6
*/
function total()
{
return count( $this->attachments );
}
/**
* Returns the next Attachment for the current object and increments the index
*
* @since 3.0
*/
function get()
{
$this->attachments_ref++;
if( !count( $this->attachments ) || $this->attachments_ref >= count( $this->attachments ) )
return false;
return $this->attachments[$this->attachments_ref];
}
/**
* Returns a specific Attachment
*
* @since 3.2
*/
function get_single( $index )
{
return isset( $this->attachments[$index] ) ? $this->attachments[$index] : false;
}
/**
* Returns the asset (array) for the current Attachment
*
* @since 3.0.6
*/
function asset( $size = 'thumbnail', $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
// do we have our meta yet?
if( !isset( $this->attachments[$index]->meta ) )
$this->attachments[$index]->meta = wp_get_attachment_metadata( $this->attachments[$index]->id );
// is it an image?
if( isset( $this->attachments[$index]->meta['sizes'] ) )
{
$asset = wp_get_attachment_image_src( $this->attachments[$index]->id, $size );
}
else
{
// either it's not an image or we don't have the proper size, so we'll use the icon
$asset = $this->icon( $index );
}
return $asset;
}
/**
* Returns the icon (array) for the current Attachment
*
* @since 3.0.6
*/
function icon( $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
$asset = wp_get_attachment_image_src( $this->attachments[$index]->id, null, true );
return $asset;
}
/**
* Returns the date for the current Attachment
* @author Hasin Hayder
*
* @since 3.4.1
*/
function date( $d = "d/m/Y", $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
$date = get_the_time( $d, $this->attachments[$index]->id );
return $date;
}
/**
* Returns an appropriate for the current Attachment if it's an image
*
* @since 3.0
*/
function image( $size = 'thumbnail', $index = null )
{
$asset = $this->asset( $size, $index );
$image_src = $asset[0];
$image_width = $asset[1];
$image_height = $asset[2];
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
$image_alt = get_post_meta( $this->attachments[$index]->id, '_wp_attachment_image_alt', true );
$image = '
';
return $image;
}
/**
* Returns the URL for the current Attachment if it's an image
*
* @since 3.0
*/
function src( $size = 'thumbnail', $index = null )
{
$asset = $this->asset( $size, $index );
return $asset[0];
}
/**
* Returns the width of the current Attachment if it's an image
*
* @since 3.5
*/
function width( $size = 'thumbnail', $index = null )
{
$asset = $this->asset( $size, $index );
return $asset[1];
}
/**
* Returns the height of the current Attachment if it's an image
*
* @since 3.5
*/
function height( $size = 'thumbnail', $index = null )
{
$asset = $this->asset( $size, $index );
return $asset[2];
}
/**
* Returns the formatted filesize of the current Attachment
*
* @since 3.0
*/
function filesize( $index = null, $size = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
if( !isset( $this->attachments[$index]->id ) )
return false;
// if an image size is passed along, use that
$url = is_string( $size ) ? $this->src( $size, $index ) : wp_get_attachment_url( $this->attachments[$index]->id );
$uploads = wp_upload_dir();
$file_path = str_replace( $uploads['baseurl'], $uploads['basedir'], $url );
$formatted = '0 bytes';
if( file_exists( $file_path ) )
$formatted = size_format( @filesize( $file_path ) );
return $formatted;
}
/**
* Returns the type of the current Attachment
*
* @since 3.0
*/
function type( $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
if( !isset( $this->attachments[$index]->id ) )
return false;
$attachment_mime = $this->get_mime_type( $this->attachments[$index]->id );
return $attachment_mime;
}
/**
* Retrieves the mime type for a WordPress $post ID
*
* @since 3.4.2
*/
function get_mime_type( $id = null )
{
$attachment_mime = explode( '/', get_post_mime_type( intval( $id ) ) );
return isset( $attachment_mime[0] ) ? $attachment_mime[0] : false;
}
/**
* Returns the subtype of the current Attachment
*
* @since 3.0
*/
function subtype( $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
if( !isset( $this->attachments[$index]->id ) )
return false;
$attachment_mime = explode( '/', get_post_mime_type( $this->attachments[$index]->id ) );
return isset( $attachment_mime[1] ) ? $attachment_mime[1] : false;
}
/**
* Returns the id of the current Attachment
*
* @since 3.0
*/
function id( $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
return isset( $this->attachments[$index]->id ) ? $this->attachments[$index]->id : false;
}
/**
* Returns the $post->ID of the current Attachment
*
* @since 3.3
*/
function post_id( $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
return isset( $this->attachments[$index]->post_id ) ? $this->attachments[$index]->post_id : false;
}
/**
* Returns the URL for the current Attachment
*
* @since 3.0
*/
function url( $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
return isset( $this->attachments[$index]->id ) ? wp_get_attachment_url( $this->attachments[$index]->id ) : false;
}
/**
* Returns the field value for the submitted field name
*
* @since 3.0
*/
function field( $name = 'title', $index = null )
{
$index = is_null( $index ) ? $this->attachments_ref : intval( $index );
return isset( $this->attachments[$index]->fields->$name ) ? $this->attachments[$index]->fields->$name : false;
}
/**
* Fires all of our actions
*
* @since 3.0
*/
function setup_instances()
{
// implement our default instance if appropriate
if( !defined( 'ATTACHMENTS_DEFAULT_INSTANCE' ) )
$this->register();
// facilitate user-defined instance registration
do_action( 'attachments_register', $this );
}
/**
* Enqueues our necessary assets
*
* @since 3.0
*/
function assets( $hook )
{
global $post;
// we only want our assets on edit screens
if( !empty( $this->instances_for_post_type ) && 'edit.php' != $hook && 'post.php' != $hook && 'post-new.php' != $hook )
return;
// we only want to enqueue if appropriate
if( empty( $this->instances_for_post_type ) )
return;
$post_id = isset( $post->ID ) ? $post->ID : null;
wp_enqueue_media( array( 'post' => $post_id ) );
wp_enqueue_style( 'attachments', trailingslashit( $this->url ) . 'css/attachments.css', null, $this->version, 'screen' );
wp_enqueue_script( 'attachments', trailingslashit( $this->url ) . 'js/attachments.js', array( 'jquery', 'jquery-ui-sortable' ), $this->version, true );
}
/**
* Registers meta box(es) for the current edit screen
*
* @since 3.0
*/
function meta_box_init()
{
$nonce_sent = false;
if( !empty( $this->instances_for_post_type ) )
{
foreach( $this->instances_for_post_type as $instance )
{
// facilitate more fine-grained meta box positioning than post type
$applicable = apply_filters( "attachments_location_{$instance}", true, $instance );
// obtain other details about instance
$instance_name = $instance;
$instance = (object) $this->instances[$instance];
$instance->name = $instance_name;
$position = isset($instance->position) ? $instance->position : 'normal';
$priority = isset($instance->priority) ? $instance->priority : 'high';
if( $applicable )
add_meta_box(
'attachments-' . $instance_name,
__( esc_attr( $instance->label ) ),
array( $this, 'meta_box_markup' ),
$this->get_post_type(),
$position,
$priority,
array(
'instance' => $instance,
'setup_nonce' => !$nonce_sent
)
);
$nonce_sent = true;
}
}
}
/**
* Callback that outputs the meta box markup
*
* @since 3.0
*/
function meta_box_markup( $post, $metabox )
{
// single out our $instance
$instance = (object) $metabox['args']['instance'];
if( $metabox['args']['setup_nonce'] )
wp_nonce_field( 'attachments_save', 'attachments_nonce' );
?>