. * * Followed the following tutorials * http://wpengineer.com/2076/add-custom-field-attachment-in-wordpress/ * http://bueltge.de/eigene-felder-dateiverwaltung-wordpress/1226/ (same like above, but in German) * * */ //avoid direct calls to this file if (!function_exists('add_action')) { header('Status: 403 Forbidden'); header('HTTP/1.1 403 Forbidden'); exit(); } define('ISCVERSION', '1.1.3'); define('ISCNAME', 'Image Source Control'); define('ISCTEXTDOMAIN', 'isc'); define('ISCDIR', basename(dirname(__FILE__))); define('ISCPATH', plugin_dir_path(__FILE__)); load_plugin_textdomain(ISCTEXTDOMAIN, false, dirname(plugin_basename(__FILE__)) . '/languages/'); if (!class_exists('ISC_CLASS')) { class ISC_CLASS { /** * define default meta fields */ protected $_fields = array( 'image_source' => array( 'id' => 'isc_image_source', 'default' => '', ), 'image_source_own' => array( 'id' => 'isc_image_source_own', 'default' => '', ) ); /** * allowed image file types/extensions * @since 1.1 */ protected $_allowedExtensions = array( 'jpg', 'png', 'gif' ); /** * Setup registers filterts and actions. */ public function __construct() { // insert all function for the frontend here add_shortcode('isc_list', array($this, 'list_post_attachments_with_sources_shortcode')); add_shortcode('isc_list_all', array($this, 'list_all_post_attachments_sources_shortcode')); // insert all backend functions below this check if (!current_user_can('upload_files')) { return false; } add_filter('attachment_fields_to_edit', array($this, 'add_isc_fields'), 10, 2); add_filter('attachment_fields_to_save', array($this, 'isc_fields_save'), 10, 2); add_action('admin_menu', array($this, 'create_menu')); add_action('admin_enqueue_scripts', array($this, 'add_admin_scripts')); // ajax function; 'add_meta_fields' is the action defined in isc.js as the action to be called via ajax add_action('wp_ajax_add_meta_fields', array($this, 'add_meta_values_to_attachments')); // save image information in meta field when a post is saved add_action('save_post', array($this, 'save_image_information_on_post_save')); } /** * create the menu pages for isc */ public function create_menu() { // this page should be accessable by editors and higher $menuhook = add_submenu_page('upload.php', 'missing image sources by Image Source Control Plugin', __('Missing Sources', ISCTEXTDOMAIN), 'edit_others_posts', ISCPATH . '/templates/missing_sources.php', ''); } /** * add scripts to admin pages * @since 1.0 * @update 1.1.1 */ public function add_admin_scripts($hook) { if ($hook != 'image-source-control-isc/templates/missing_sources.php') { return; } wp_enqueue_script('isc_script', plugins_url('/js/isc.js', __FILE__), false, ISCVERSION); // this is to define ajaxurl to be able to use this in its own js script // wp_localize_script( 'isc_script', 'IscAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) ); } /** * add custom field to attachment * @param arr $form_fields * @param object $post * @return arr * @since 1.0 * @updated 1.1 */ public function add_isc_fields($form_fields, $post) { // add input field for source $form_fields['isc_image_source']['label'] = __('Image Source', ISCTEXTDOMAIN); $form_fields['isc_image_source']['value'] = get_post_meta($post->ID, 'isc_image_source', true); $form_fields['isc_image_source']['helps'] = __('Include the image source here.', ISCTEXTDOMAIN); // add checkbox to mark as your own image $form_fields['isc_image_source_own']['input'] = 'html'; $form_fields['isc_image_source_own']['label'] = ''; $form_fields['isc_image_source_own']['helps'] = __('Check this box if this is your own image and doesn\'t need a source.', ISCTEXTDOMAIN); $form_fields['isc_image_source_own']['html'] = "ID, 'isc_image_source_own', true), 1, false ) . " style=\"width:14px\"/> " . __('This is my image', ISCTEXTDOMAIN); return $form_fields; } /** * save image source to post_meta * @param object $post * @param $attachment * @return object $post */ public function isc_fields_save($post, $attachment) { if (isset($attachment['isc_image_source'])) { update_post_meta($post['ID'], 'isc_image_source', $attachment['isc_image_source']); } update_post_meta($post['ID'], 'isc_image_source_own', $attachment['isc_image_source_own']); return $post; } /** * create image sources list for all images of this post * @since 1.0 * @update 1.1 * @param int $post_id id of the current post/page * @return echo output */ public function list_post_attachments_with_sources($post_id = 0) { global $post; if (empty($post_id)) { if (!empty($post->ID)) { $post_id = $post->ID; } else { return; } } $attachments = get_post_meta($post_id, 'isc_post_images', true); // if attachments is an empty string, search for images in it if ($attachments == '') { $this->save_image_information_on_load ($post_id, $_content); $attachments = get_post_meta($post_id, 'isc_post_images', true); } $return = ''; if (!empty($attachments)) { $atts = array(); foreach ($attachments as $attachment_id => $attachment_array) { $atts[$attachment_id]['title'] = get_the_title($attachment_id); $own = get_post_meta($attachment_id, 'isc_image_source_own', true); $source = get_post_meta($attachment_id, 'isc_image_source', true); if ( $own == '' && $source == '' ) { // remove if no information set unset($atts[$attachment_id]); continue; } elseif ($own != '') { $atts[$attachment_id ]['source'] = __('by the author', ISCTEXTDOMAIN); } else { $atts[$attachment_id ]['source'] = $source; } } $return = $this->_renderAttachments($atts); } return $return; } /** * @param array $attachments */ protected function _renderAttachments($attachments) { // don't display anything, if no image sources displayed if ($attachments == array()) { return ; } ob_start(); // TODO this is almost trivial to replace with sprintf ?>

0), $atts)); // if $id not set, use the current ID from the post if (empty($id)) { $id = $post->ID; } if (empty($id)) { return; } return $this->list_post_attachments_with_sources($id); } /** * get all attachments without sources * the downside of this function: is there is not even an empty metakey field, nothing is going to be retrieved * @todo fix this in WP 3.5 with compare => 'NOT EXISTS' */ public function get_attachments_without_sources() { $args = array( 'post_type' => 'attachment', 'numberposts' => -1, 'post_status' => null, 'post_parent' => null, 'meta_query' => array( // image source is empty array( 'key' => 'isc_image_source', 'value' => '', 'compare' => '=', ), // and image source is not set array( 'key' => 'isc_image_source_own', 'value' => '1', 'compare' => '!=', ), ) ); $attachments = get_posts($args); if (!empty($attachments)) { return $attachments; } } /** * add meta values to all attachments * @todo probably need to fix this when more fields are added along the way * @todo use compare => 'NOT EXISTS' when WP 3.5 is up to retrieve only values where it is not set * @todo this currently updates all empty fields; empty in this context is empty string, 0, false or not existing; add check if meta field already existed before */ public function add_meta_values_to_attachments() { // retrieve all attachments $args = array( 'post_type' => 'attachment', 'numberposts' => -1, 'post_status' => null, 'post_parent' => null, ); $attachments = get_posts($args); if (empty($attachments)) { return; } $count = 0; foreach ($attachments as $_attachment) { $set = false; setup_postdata($_attachment); foreach ($this->_fields as $_field) { $meta = get_post_meta($_attachment->ID, $_field['id'], true); if (empty($meta)) { update_post_meta($_attachment->ID, $_field['id'], $_field['default']); $set = true; } } if ($set) { $count++; } } echo sprintf(__('Added meta fields to %d images.', ISCTEXTDOMAIN), $count) . '
'; die(); } /** * show the loading image from wp-admin/images/loading.gif * @param bool $display should this be displayed directly or hidden? via inline css */ public function show_loading_image($display = true) { $img_path = admin_url("/images/loading.gif"); $file_path = ABSPATH . "wp-admin/images/loading.gif"; if (file_exists($file_path)) { echo ''; } } /** * this is an entry function to save image information to a post when it is saved * @since 1.1 * @param type $post_id */ public function save_image_information_on_post_save($post_id) { // return, if save_post is called more than one time if (did_action('save_post') !== 1) { return; } if (isset($_POST['post_type']) && 'attachment' == $_POST['post_type']) { return; } // check if this is a revision and if so, use parent post id if ($_id = wp_is_post_revision($post_id)) { $post_id = $_id; } $_content = stripslashes($_REQUEST['content']); $this->save_image_information($post_id, $_content); } /** * save image information for a post when it is viewed and the image source list is enabled * (this is in case the plugin is new and the current post wasn't saved before) * * @since 1.1 */ public function save_image_information_on_load() { global $post; if (empty($post->ID)) { return; } $post_id = $post->ID; $_content = $post->post_content; $this->save_image_information($post_id, $_content); } /** * retrieve images added to a post or page and save all information as a meta value * @since 1.1 * @todo check for more post types that maybe should not be parsed here */ public function save_image_information($post_id, $_content) { $_image_urls = $this->_filter_src_attributes($_content); $_imgs = array(); foreach ($_image_urls as $_image_url) { // get ID of images by url $img_id = $this->get_image_by_url($_image_url); $_imgs[$img_id] = array( 'src' => $_image_url ); } // add thumbnail information $thumb_id = get_post_thumbnail_id($post_id); $_imgs[$thumb_id] = array( 'src' => wp_get_attachment_url($thumb_id), 'thumbnail' => true ); // TODO _imgs is an non-empty array by now if (empty($_imgs)) { $_imgs = false; } update_post_meta($post_id, 'isc_post_images', $_imgs); } /** * filter image src attribute from text * @since 1.1 * @updated 1.1.3 * @return array with image src uris */ public function _filter_src_attributes($content = '') { $srcs = array(); if (empty($content)) return $srcs; // parse HTML with DOM $dom = new DOMDocument; $dom->loadHTML($content); foreach ($dom->getElementsByTagName('img') as $node) { $srcs[] = $node->getAttribute('src'); } return $srcs; } /** * get image by url accessing the database directly * @since 1.1 * @updated 1.1.3 * @param string $url url of the image * @return id of the image */ public function get_image_by_url($url = '') { if (empty($url)) { return 0; } $types = implode('|', $this->_allowedExtensions); // check for the format 'image-title-(e12452112-)300x200.jpg' and remove the image size and edit mark from it $newurl = preg_replace("/(-e\d+){0,1}-(\d+)x(\d+)\.({$types})$/i", '.${4}', $url); global $wpdb; $query = $wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid = %s", $newurl); $id = $wpdb->get_var($query); return $id; } /** * create shortcode to list all image sources in the frontend * @param array $atts * @since 1.1.3 * @todo link to the post */ public function list_all_post_attachments_sources_shortcode($atts = array()) { /** * @todo why not translate here with the code below? */ extract(shortcode_atts(array( 'per_page' => 99999, 'before_links' => '', 'after_links' => '', 'prev_text' => '« Previous', 'next_text' => 'Next »' ), $atts)); /** * @todo why not include this into the array above? */ if ('« Previous' == $prev_text) $prev_text = __('« Previous', ISCTEXTDOMAIN); if ('Next »' == $next_text) $next_text = __('Next »', ISCTEXTDOMAIN); // retrieve all attachments $args = array( 'post_type' => 'attachment', 'numberposts' => -1, 'post_status' => null, 'post_parent' => null, /** @todo maybe add offset to not retrieve the first results when not on first page */ /** @todo maybe add limit to not retrieve more results than on the current page */ ); $attachments = get_posts($args); if (empty($attachments)) { return; } $connected_atts = array(); //Keeps only those ones who have parent foreach ($attachments as $_attachment) { if ($_attachment->post_parent) { $connected_atts[$_attachment->ID]['source'] = get_post_meta($_attachment->ID, 'isc_image_source', true); $connected_atts[$_attachment->ID]['own'] = get_post_meta($_attachment->ID, 'isc_image_source_own', true); $connected_atts[$_attachment->ID]['title'] = $_attachment->post_title; $connected_atts[$_attachment->ID]['parent'] = get_the_title($_attachment->post_parent); } } $total = count($connected_atts); if (0 == $total) return; $page = isset($_GET['isc-page']) ? intval($_GET['isc-page']) : 1; $down_limit = 1; // First page $up_limit = 1; if ($per_page < $total) { $rem = $total % $per_page; // The Remainder of $total/$per_page $up_limit = ($total - $rem) / $per_page; if (0 < $rem) { $up_limit++; //If rem is positive, add the last page that contains less than $per_page attachment; } } ob_start(); if ( 2 > $up_limit ) { $this->display_all_attachment_list($connected_atts); } else { $starting_atts = $per_page * ($page - 1); // for page 2 and 3 $per_page start display on $connected_atts[3*(2-1) = 3] $paged_atts = array_slice($connected_atts, $starting_atts, $per_page, true); $this->display_all_attachment_list($paged_atts); $this->pagination_links($up_limit, $before_links, $after_links, $prev_text, $next_text); } $output = ob_get_clean(); return $output; } /** * performs rendering of all attachments list * @since 1.1.3 */ public function display_all_attachment_list($atts) { if (! is_array($atts) || $atts == array()) return; ?> */ ?> $data) : ?> */ ?>
list_post_attachments_with_sources($post_id); } }