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++;
}
}
}
/**
* 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 = '';
if ( !empty( $_REQUEST['content']) ) $_content = stripslashes($_REQUEST['content']);
// Needs to be called before the 'isc_post_images' field is updated.
$this->update_image_posts_meta($post_id, $_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);
/**
* if an image is used both inside the post and as post thumbnail, the thumbnail entry overrides the regular image.
*/
if ( !empty( $thumb_id )) {
$_imgs[$thumb_id] = array(
'src' => wp_get_attachment_url($thumb_id),
'thumbnail' => true
);
}
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;
libxml_use_internal_errors(true);
$dom->loadHTML($content);
// Prevents from sending E_WARNINGs notice (Outputs are forbidden during activation)
libxml_clear_errors();
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;
}
/**
* Update isc_image_posts meta field for all images found in a post with a given ID.
* @param $post_id ID of the target post
* @param $content content of the target post
*/
public function update_image_posts_meta($post_id, $content)
{
$image_urls = $this->_filter_src_attributes($content);
$image_ids = array();
$added_images = array();
$removed_images = array();
$isc_post_images = get_post_meta($post_id, 'isc_post_images', true);
foreach ($image_urls as $url) {
$id = intval($this->get_image_by_url($url));
array_push($image_ids, $id);
if (is_array($isc_post_images) && !array_key_exists($id, $isc_post_images)) {
array_push($added_images, $id);
}
}
if (is_array($isc_post_images)) {
foreach ($isc_post_images as $old_id => $value) {
if (!in_array($old_id, $image_ids)) {
array_push($removed_images, $old_id);
} else {
if (!empty($old_id)) {
$meta = get_post_meta($old_id, 'isc_image_posts', true);
if (empty($meta)) {
update_post_meta($old_id, 'isc_image_posts', array($post_id));
} else {
// In case the isc_image_posts is not up to date
if (is_array($meta) && !in_array($post_id, $meta)) {
array_push($meta, $post_id);
update_post_meta($old_id, 'isc_image_posts', $meta);
}
}
}
}
}
}
foreach ($added_images as $id) {
$meta = get_post_meta($id, 'isc_image_posts', true);
if (!is_array($meta) || array() == $meta) {
update_post_meta($id, 'isc_image_posts', array($post_id));
} else {
array_push($meta, $post_id);
update_post_meta($id, 'isc_image_posts', $meta);
}
}
foreach ($removed_images as $id) {
$image_meta = get_post_meta($id, 'isc_image_posts', true);
if (is_array($image_meta)) {
$offset = array_search($post_id, $image_meta);
if (false !== $offset) {
array_splice($image_meta, $offset, 1);
update_post_meta($id, 'isc_image_posts', $image_meta);
}
}
}
}
/**
* 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?
* > Because the two if statements below will need to call gettext (again) for comparing values.
*/
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,
'meta_query' => array(
array(
'key' => 'isc_image_posts',
'value' => 'a:0:{}',
'compare' => '!='
)
)
/** @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 */
/** >No, we need to get total count of attachment with parents for $max_page in the pagination link. */
);
$attachments = get_posts($args);
if (empty($attachments)) {
return;
}
$options = $this->get_isc_options();
$connected_atts = array();
//Keeps only those ones who have parent
foreach ($attachments as $_attachment) {
$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]['author_name'] = '';
if ('' != $connected_atts[$_attachment->ID]['own']) {
$parent = get_post($_attachment->post_parent);
$connected_atts[$_attachment->ID]['author_name'] = get_the_author_meta('display_name', $parent->post_author);
}
$metadata = get_post_meta($_attachment->ID, 'isc_image_posts', true);
$parents_data = '';
if (is_array($metadata) && array() != $metadata) {
$parents_data .= "
";
foreach($metadata as $data) {
$parents_data .= sprintf(__('
get_page_link() returns the permalink but for the default WP permalink structure, the permalink looks like "http://domain.tld/?p=52", while $_GET
* still has a field named 'page_id' with the same value of 52.
*/
$pos = strpos($page_link, '?');
if (false !== $pos) {
$page_link = substr($page_link, 0, $pos);
}
/**
* Unset the actual "$_GET['isc-page']" variable (if is set). Pagination variable will be appended to the new query string with a different value for each
* pagination link.
*/
if (isset($_GET['isc-page'])) {
unset($_GET['isc-page']);
}
$query_string = http_build_query($_GET);
$isc_query_tag = '';
if (empty($query_string)) {
$isc_query_tag = '?isc-page=';
} else {
$query_string = '?' . $query_string;
$isc_query_tag = '&isc-page=';
}
if ($min_page != $page) {
?>
1......
default_options() );
}
$options = $this->get_isc_options();
if (!$options['installed']) {
/**
* Here, all jobs to perform during first installation, especially options and custom fields.
* Important: No add_action('something', 'somefunction').
*/
// adds meta fields for attachments
$this->add_meta_values_to_attachments();
// set all isc_image_posts meta fields.
$this->init_image_posts_metafield();
$options['installed'] = true;
update_option('isc_options', $options);
}
}
/**
* Returns default options
*/
public function default_options()
{
$default['image_list_headline'] = __('image sources', ISCTEXTDOMAIN);
$default['use_authorname'] = true;
$default['by_author_text'] = __('Owned by the author', ISCTEXTDOMAIN);
$default['installed'] = false;
$default['version'] = '1.2';
$default['webgilde'] = false;
$default['thumbnail_in_list'] = false;
$default['thumbnail_size'] = 'thumbnail';
$default['thumbnail_width'] = 150;
$default['thumbnail_height'] = 150;
return $default;
}
/**
* Settings API initialization
*/
public function SAPI_init()
{
$this->upgrade_management();
register_setting('isc_options_group', 'isc_options', array($this, 'settings_validation'));
add_settings_section('isc_settings_section', '', '__return_false', 'isc_settings_page');
add_settings_field('image_list_headline', __('Image list headline', ISCTEXTDOMAIN), array($this, 'renderfield_list_headline'), 'isc_settings_page', 'isc_settings_section');
add_settings_field('use_authorname', __('Use authors names', ISCTEXTDOMAIN), array($this, 'renderfield_use_authorname'), 'isc_settings_page', 'isc_settings_section');
add_settings_field('by_author_text', __('Custom text for owned images', ISCTEXTDOMAIN), array($this, 'renderfield_byauthor_text'), 'isc_settings_page', 'isc_settings_section');
add_settings_field('webgilde_backlink', __("Link to webgilde's website", ISCTEXTDOMAIN), array($this, 'renderfield_webgile'), 'isc_settings_page', 'isc_settings_section');
add_settings_field('use_thumbnail', __("Use thumbnails in images list", ISCTEXTDOMAIN), array($this, 'renderfield_use_thumbnail'), 'isc_settings_page', 'isc_settings_section');
add_settings_field('thumbnail_width', __("Thumbnails max-width", ISCTEXTDOMAIN), array($this, 'renderfield_thumbnail_width'), 'isc_settings_page', 'isc_settings_section');
add_settings_field('thumbnail_height', __("Thumbnails max-height", ISCTEXTDOMAIN), array($this, 'renderfield_thumbnail_height'), 'isc_settings_page', 'isc_settings_section');
}
/**
* manage data structure upgrading of outdated versions
*/
public function upgrade_management() {
/**
* Since the activation hook is not executed on plugin upgrade, this function checks options in database
* during the admin_init hook to handle plugin's upgrade.
*/
$options = get_option( 'isc_options' );
$max_step = count($this->_upgrade_step);
$step_count = 0;
if (!is_array($options) || !isset($options['version'])){ // versions prior to 1.2
$default = $this->default_options();
$options = $options + $default;
$this->init_image_posts_metafield();
$options['installed'] = true;
update_option('isc_options', $options);
$step_count++;
} elseif(ISCVERSION != $options['version']) {
while (ISCVERSION != $options['version'] && $step_count <= $max_step) {
switch ($options['version']) {
/**
* Here, the incremental upgrade process depending on the currently installed version.
*/
}
}
}
}
/**
* Image_control's page callback
*/
public function render_isc_settings_page()
{
?>
get_isc_options();
$description = __('The headline of the image list added via shortcode or function in your theme.', ISCTEXTDOMAIN);
?>
get_isc_options();
$description = __("Display the author's public name as source when the image is owned by the author. Uncheck to use a custom text instead.", ISCTEXTDOMAIN);
?>
/>
get_isc_options();
$description = __("Enter the custom text to display if you do not want to use the author's public name.", ISCTEXTDOMAIN);
?>
class="regular-text" />
get_isc_options();
/**
* Avoid warning notices because of the absence of webgilde field in isc_options throughout development steps.
* This 'if' block can be removed for the next release.
*/
if (!isset($options['webgilde'])) {
$options = $options + $this->default_options();
}
$description = sprintf(__('Display a link to Image Source Control plugin's website below the list of all images in the blog?', ISCTEXTDOMAIN), WEBGILDE);
?>
/>
get_isc_options();
if (!isset($options['thumbnail_size'])) {
$options = $options + $this->default_options();
}
$description = __('Display thumbnails on the list of all images in the blog.' ,ISCTEXTDOMAIN);
?>
/>
get_isc_options();
if (!isset($options['thumbnail_size'])) {
$options = $options + $this->default_options();
}
$description = __('Custom value of the maximum allowed width for thumbnail.' ,ISCTEXTDOMAIN);
?>
px
get_isc_options();
if (!isset($options['thumbnail_size'])) {
$options = $options + $this->default_options();
}
$description = __('Custom value of the maximum allowed height for thumbnail.' ,ISCTEXTDOMAIN);
?>
px
default_options());
}
/*
* Input validation function.
* @param array $input values from the admin panel
*/
public function settings_validation($input)
{
$output = $this->get_isc_options();
$output['image_list_headline'] = esc_html($input['image_list_headline_field']);
if (isset($input['use_authorname_ckbox'])) {
// Don't worry about the custom text if the author name is selected.
$output['use_authorname'] = true;
} else {
$output['use_authorname'] = false;
$output['by_author_text'] = esc_html($input['by_author_text_field']);
}
if (isset($input['webgilde_field'])) {
$output['webgilde'] = true;
} else {
$output['webgilde'] = false;
}
if (isset($input['use_thumbnail'])) {
$output['thumbnail_in_list'] = true;
if (in_array($input['size_select'], $this->_thumbnail_size)) {
$output['thumbnail_size'] = $input['size_select'];
}
if ('custom' == $input['size_select']) {
if (is_numeric($input['thumbnail_width'])) {
// Ensures that the value stored in database in a positive integer.
$output['thumbnail_width'] = abs(intval(round($input['thumbnail_width'])));
}
if (is_numeric($input['thumbnail_height'])) {
$output['thumbnail_height'] = abs(intval(round($input['thumbnail_height'])));
}
}
} else {
$output['thumbnail_in_list'] = false;
}
return $output;
}
/**
* Adds isc_image_posts on all attachments. Launched during first installation.
*/
public function init_image_posts_metafield()
{
$args = array(
'post_type' => 'any',
'numberposts' => -1,
'post_status' => null,
'post_parent' => null,
);
$posts = get_posts($args);
foreach ($posts as $post) {
setup_postdata($post);
$image_urls = $this->_filter_src_attributes($post->post_content);
$image_ids = array();
foreach ($image_urls as $url) {
$image_id = intval($this->get_image_by_url($url));
array_push($image_ids,$image_id);
}
foreach ($image_ids as $id) {
$meta = get_post_meta($id, 'isc_image_posts', true);
if (empty($meta)) {
update_post_meta($id, 'isc_image_posts', array($post->ID));
} else {
if (!in_array($post->ID, $meta)) {
array_push($meta, $post->ID);
update_post_meta($id, 'isc_image_posts', $meta);
}
}
}
}
}
}// end of class
$inc_path = ABSPATH . 'wp-includes/';
/**
* "pluggable.php" is not defined at this point. Not sure about the reason.
*/
require_once($inc_path . 'pluggable.php');
/**
* Need an instance of ISC_CLASS when the register_activation_hook is called (earlier than the "plugins_loaded" hook).
*/
global $my_isc;
$my_isc = new ISC_CLASS();
/**
* the next functions are just to have an easier access from outside the class
*/
function isc_list($post_id = 0) {
$isc = new ISC_CLASS();
echo $isc->list_post_attachments_with_sources($post_id);
}
}