/** * Creates new items from the "Bulk Translate" list. * * @since 2.11 * * @param array $item_content NULL, to indicate no handler. * @param string $bulk_action the requested action. * @param integer $post_id the affected attachment. * * @return object updated $item_content. NULL if no handler, otherwise * ( 'message' => error or status message(s), 'body' => '' ) */ public static function mla_list_table_custom_bulk_action($item_content, $bulk_action, $post_id) { global $polylang; MLA::mla_debug_add(__LINE__ . " MLA_Polylang::mla_list_table_bulk_action_item_request( {$bulk_action}, {$post_id} )", MLA::MLA_DEBUG_CATEGORY_LANGUAGE); if ('pll-translate' == $bulk_action) { $translations = array(); if (isset($_REQUEST['bulk_tr_languages'])) { $bulk_tr_languages = $_REQUEST['bulk_tr_languages']; // Expand All Languages selection if (isset($bulk_tr_languages['all'])) { foreach ($polylang->model->get_languages_list() as $language) { $bulk_tr_languages[$language->slug] = 'translate'; } unset($bulk_tr_languages['all']); } // Process language selection(s) foreach ($bulk_tr_languages as $language => $action) { $new_id = MLA_Polylang::_get_translation($post_id, $language); $translations[] = $new_id; } } // Clear all the "Filter-by" parameters if (isset($_REQUEST['bulk_tr_options']['clear_filters'])) { MLA::mla_clear_filter_by(); } if (empty($translations)) { $item_content = array('message' => "Item {$post_id}, no translations."); } else { $_REQUEST['heading_suffix'] = __('Bulk Translations', 'media-library-assistant'); MLA_Polylang::$bulk_action_includes = array_merge(MLA_Polylang::$bulk_action_includes, $translations); $translations = implode(',', $translations); $item_content = array('message' => "Item {$post_id}, translation(s): {$translations}."); } } return $item_content; }
/** * Filter the $tax_input array to a specific language * * @since 2.11 * @uses MLA_WPML::$tax_input * @uses MLA_WPML::$existing_terms * * @param integer $post_id ID of the post to be updated * @param string $post_language explicit language_code; optional * * @return array language-specific $tax_inputs */ private static function _apply_tax_input($post_id, $post_language = NULL) { global $sitepress; if (NULL == $post_language) { if (isset(self::$existing_terms['element_id']) && $post_id == self::$existing_terms['element_id']) { $post_language = self::$existing_terms['language_code']; } else { $post_language = $sitepress->get_element_language_details($post_id, 'post_attachment'); $post_language = $post_language->language_code; } } MLA::mla_debug_add("MLA_WPML::_apply_tax_input( {$post_id} ) \$post_language = " . var_export($post_language, true), MLA::MLA_DEBUG_CATEGORY_AJAX); MLA::mla_debug_add("MLA_WPML::_apply_tax_input( {$post_id} ) self::\$tax_input[ \$post_language ] = " . var_export(self::$tax_input[$post_language], true), MLA::MLA_DEBUG_CATEGORY_AJAX); return self::$tax_input[$post_language]; }
/** * Retrieve the terms in one or more taxonomies. * * Alternative to WordPress /wp-includes/taxonomy.php function get_terms() that provides * an accurate count of attachments associated with each term. * * taxonomy - string containing one or more (comma-delimited) taxonomy names * or an array of taxonomy names. Default 'post_tag'. * * post_mime_type - MIME type(s) of the items to include in the term-specific counts. Default 'all'. * * post_type - The post type(s) of the items to include in the term-specific counts. * The default is "attachment". * * post_status - The post status value(s) of the items to include in the term-specific counts. * The default is "inherit". * * ids - A comma-separated list of attachment ID values for an item-specific cloud. * * include - An array, comma- or space-delimited string of term ids to include * in the return array. * * exclude - An array, comma- or space-delimited string of term ids to exclude * from the return array. If 'include' is non-empty, 'exclude' is ignored. * * parent - term_id of the terms' immediate parent; 0 for top-level terms. * * minimum - minimum number of attachments a term must have to be included. Default 0. * * no_count - 'true', 'false' (default) to suppress term-specific attachment-counting process. * * number - maximum number of term objects to return. Terms are ordered by count, * descending and then by term_id before this value is applied. Default 0. * * orderby - 'count', 'id', 'name' (default), 'none', 'random', 'slug' * * order - 'ASC' (default), 'DESC' * * no_orderby - 'true', 'false' (default) to suppress ALL sorting clauses else false. * * preserve_case - 'true', 'false' (default) to make orderby case-sensitive. * * pad_counts - 'true', 'false' (default) to to include the count of all children in their parents' count. * * limit - final number of term objects to return, for pagination. Default 0. * * offset - number of term objects to skip, for pagination. Default 0. * * @since 1.60 * * @param array taxonomies to search and query parameters * * @return array array of term objects, empty if none found */ public static function mla_get_terms($attr) { global $wpdb; /* * Make sure $attr is an array, even if it's empty */ if (empty($attr)) { $attr = array(); } elseif (is_string($attr)) { $attr = shortcode_parse_atts($attr); } /* * Merge input arguments with defaults */ $attr = apply_filters('mla_get_terms_query_attributes', $attr); $arguments = shortcode_atts(self::$mla_get_terms_parameters, $attr); $arguments = apply_filters('mla_get_terms_query_arguments', $arguments); /* * Build an array of individual clauses that can be filtered */ $clauses = array('fields' => '', 'join' => '', 'where' => '', 'order' => '', 'orderby' => '', 'limits' => ''); /* * If we're not counting attachments per term, strip * post fields out of list and adjust the orderby value */ if ($no_count = 'true' == (string) $arguments['no_count']) { $field_array = explode(',', $arguments['fields']); foreach ($field_array as $index => $field) { if (false !== strpos($field, 'p.')) { unset($field_array[$index]); } } $arguments['fields'] = implode(',', $field_array); $arguments['minimum'] = 0; $arguments['post_mime_type'] = 'all'; if ('count' == strtolower($arguments['orderby'])) { $arguments['orderby'] = 'none'; } } $clauses['fields'] = $arguments['fields']; $clause = array('INNER JOIN `' . $wpdb->term_taxonomy . '` AS tt ON t.term_id = tt.term_id'); $clause_parameters = array(); if (!$no_count) { $clause[] = 'LEFT JOIN `' . $wpdb->term_relationships . '` AS tr ON tt.term_taxonomy_id = tr.term_taxonomy_id'; $clause[] = 'LEFT JOIN `' . $wpdb->posts . '` AS p ON tr.object_id = p.ID'; /* * Add type and status constraints */ if (is_array($arguments['post_type'])) { $post_types = $arguments['post_type']; } else { $post_types = array($arguments['post_type']); } $placeholders = array(); foreach ($post_types as $post_type) { $placeholders[] = '%s'; $clause_parameters[] = $post_type; } $clause[] = 'AND p.post_type IN (' . join(',', $placeholders) . ')'; if (is_array($arguments['post_status'])) { $post_stati = $arguments['post_status']; } else { $post_stati = array($arguments['post_status']); } $placeholders = array(); foreach ($post_stati as $post_status) { if ('private' != $post_status || is_user_logged_in()) { $placeholders[] = '%s'; $clause_parameters[] = $post_status; } } $clause[] = 'AND p.post_status IN (' . join(',', $placeholders) . ')'; } $clause = join(' ', $clause); $clauses['join'] = $wpdb->prepare($clause, $clause_parameters); /* * Start WHERE clause with a taxonomy constraint */ if (is_array($arguments['taxonomy'])) { $taxonomies = $arguments['taxonomy']; } else { $taxonomies = array($arguments['taxonomy']); } foreach ($taxonomies as $taxonomy) { if (!taxonomy_exists($taxonomy)) { $error = new WP_Error('invalid_taxonomy', __('Invalid taxonomy', 'media-library-assistant'), $taxonomy); return $error; } } $clause_parameters = array(); $placeholders = array(); foreach ($taxonomies as $taxonomy) { $placeholders[] = '%s'; $clause_parameters[] = $taxonomy; } $clause = array('tt.taxonomy IN (' . join(',', $placeholders) . ')'); /* * The "ids" parameter can build an item-specific cloud. * Compile a list of all the terms assigned to the items. */ if (!empty($arguments['ids']) && empty($arguments['include'])) { $ids = wp_parse_id_list($arguments['ids']); $placeholders = implode("','", $ids); $clause[] = "AND p.ID IN ( '{$placeholders}' )"; $includes = array(); foreach ($ids as $id) { foreach ($taxonomies as $taxonomy) { $terms = get_the_terms($id, $taxonomy); if (is_array($terms)) { foreach ($terms as $term) { $includes[$term->term_id] = $term->term_id; } // terms } } // taxonomies } // ids /* * If there are no terms we want an empty cloud */ if (empty($includes)) { $arguments['include'] = (string) 0x7fffffff; } else { ksort($includes); $arguments['include'] = implode(',', $includes); } } /* * Add include/exclude and parent constraints to WHERE cluse */ if (!empty($arguments['include'])) { $placeholders = implode("','", wp_parse_id_list($arguments['include'])); $clause[] = "AND t.term_id IN ( '{$placeholders}' )"; } elseif (!empty($arguments['exclude'])) { $placeholders = implode("','", wp_parse_id_list($arguments['exclude'])); $clause[] = "AND t.term_id NOT IN ( '{$placeholders}' )"; } if ('' !== $arguments['parent']) { $parent = (int) $arguments['parent']; $clause[] = "AND tt.parent = '{$parent}'"; } if ('all' !== strtolower($arguments['post_mime_type'])) { $where = str_replace('%', '%%', wp_post_mime_type_where($arguments['post_mime_type'], 'p')); if (0 == absint($arguments['minimum'])) { $clause[] = ' AND ( p.post_mime_type IS NULL OR ' . substr($where, 6); } else { $clause[] = $where; } } $clause = join(' ', $clause); $clauses['where'] = $wpdb->prepare($clause, $clause_parameters); /* * For the inner/initial query, always select the most popular terms */ if ($arguments['no_orderby']) { $arguments['orderby'] = 'count'; $arguments['order'] = 'DESC'; } /* * Add sort order */ $orderby = strtolower($arguments['orderby']); $order = strtoupper($arguments['order']); if ('DESC' != $order) { $order = 'ASC'; } $clauses['order'] = $order; $clauses['orderby'] = "ORDER BY {$orderby}"; /* * Count, Descending, is the default order so no further work * is needed unless a different order is specified */ if ('count' != $orderby || 'DESC' != $order) { if ('true' == strtolower($arguments['preserve_case'])) { $binary_keys = array('name', 'slug'); } else { $binary_keys = array(); } $allowed_keys = array('empty_orderby_default' => 'name', 'count' => 'count', 'id' => 'term_id', 'name' => 'name', 'random' => 'RAND()', 'slug' => 'slug'); $clause = 'ORDER BY ' . self::_validate_sql_orderby($arguments, '', $allowed_keys, $binary_keys); $clauses['orderby'] = substr($clause, 0, strrpos($clause, ' ' . $order)); } // add ORDER BY /* * Add pagination */ $clauses['limits'] = ''; $offset = absint($arguments['offset']); $limit = absint($arguments['limit']); if (0 < $offset && 0 < $limit) { $clauses['limits'] = "LIMIT {$offset}, {$limit}"; } elseif (0 < $limit) { $clauses['limits'] = "LIMIT {$limit}"; } elseif (0 < $offset) { $clause_parameters = 0x7fffffff; $clauses['limits'] = "LIMIT {$offset}, {$clause_parameters}"; } $clauses = apply_filters('mla_get_terms_clauses', $clauses); /* * Build the final query */ $query = array('SELECT'); $query[] = $clauses['fields']; $query[] = 'FROM `' . $wpdb->terms . '` AS t'; $query[] = $clauses['join']; $query[] = 'WHERE ('; $query[] = $clauses['where']; $query[] = ') GROUP BY tt.term_taxonomy_id'; $clause_parameters = absint($arguments['minimum']); if (0 < $clause_parameters) { $query[] = "HAVING count >= {$clause_parameters}"; } /* * If specifically told to omit the ORDER BY clause or the COUNT, * supply a sort order for the initial/inner query only */ if (!($arguments['no_orderby'] || $no_count)) { $query[] = 'ORDER BY count DESC, t.term_id ASC'; } /* * Limit the total number of terms returned */ $terms_limit = absint($arguments['number']); if (0 < $terms_limit) { $query[] = "LIMIT {$terms_limit}"; } /* * $final_clauses, if present, require an SQL subquery */ $final_clauses = array(); if ('count' != $orderby || 'DESC' != $order) { $final_clauses[] = $clauses['orderby']; $final_clauses[] = $clauses['order']; } if ('' !== $clauses['limits']) { $final_clauses[] = $clauses['limits']; } /* * If we're limiting the final results, we need to get an accurate total count first */ if (!$no_count && (0 < $offset || 0 < $limit)) { $count_query = 'SELECT COUNT(*) as count FROM (' . join(' ', $query) . ' ) as subQuery'; $count = $wpdb->get_results($count_query); $found_rows = $count[0]->count; } if (!empty($final_clauses)) { if (!$no_count) { array_unshift($query, 'SELECT * FROM ('); $query[] = ') AS subQuery'; } $query = array_merge($query, $final_clauses); } $query = join(' ', $query); $tags = $wpdb->get_results($query); if (!isset($found_rows)) { $found_rows = $wpdb->num_rows; } if (self::$mla_debug) { MLA::mla_debug_add('<strong>' . __('mla_debug query arguments', 'media-library-assistant') . '</strong> = ' . var_export($arguments, true)); MLA::mla_debug_add('<strong>' . __('mla_debug last_query', 'media-library-assistant') . '</strong> = ' . var_export($wpdb->last_query, true)); MLA::mla_debug_add('<strong>' . __('mla_debug last_error', 'media-library-assistant') . '</strong> = ' . var_export($wpdb->last_error, true)); MLA::mla_debug_add('<strong>' . __('mla_debug num_rows', 'media-library-assistant') . '</strong> = ' . var_export($wpdb->num_rows, true)); MLA::mla_debug_add('<strong>' . __('mla_debug found_rows', 'media-library-assistant') . '</strong> = ' . var_export($found_rows, true)); } if ('true' == strtolower(trim($arguments['pad_counts']))) { self::_pad_term_counts($tags, reset($taxonomies), $post_types, $post_stati); } $tags['found_rows'] = $found_rows; $tags = apply_filters('mla_get_terms_query_results', $tags); return $tags; }
/** * Filters taxonomy updates by language for Bulk Edit during Add New Media * and the Media/Edit Media screen * * @since 2.11 * * @param integer ID of the current post */ public static function edit_attachment($post_id) { static $already_updating = 0; MLA::mla_debug_add(__LINE__ . " MLA_Polylang::edit_attachment( {$post_id} ) _REQUEST = " . var_export($_REQUEST, true), MLA::MLA_DEBUG_CATEGORY_LANGUAGE); /* * mla_update_single_item may call this action again */ if ($already_updating == $post_id) { return; } else { $already_updating = $post_id; } /* * Check for Bulk Edit during Add New Media */ if (!empty($_REQUEST['mlaAddNewBulkEditFormString'])) { if (!empty(self::$bulk_edit_request['tax_input'])) { $tax_inputs = self::$bulk_edit_request['tax_input']; if ('checked' == MLAOptions::mla_get_option('term_assignment', false, false, MLA_WPML::$mla_language_option_definitions)) { self::_build_tax_input($post_id, $tax_inputs, self::$bulk_edit_request['tax_action']); $tax_inputs = self::_apply_tax_input($post_id); } } else { $tax_inputs = NULL; } $updates = MLA::mla_prepare_bulk_edits($post_id, self::$bulk_edit_request, self::$bulk_edit_map); unset($updates['tax_input']); unset($updates['tax_action']); MLAData::mla_update_single_item($post_id, $updates, $tax_inputs); return; } // Upload New Media Bulk Edit /* * For the Bulk Edit action on the Media/Assistant screen, only synchronization is needed */ if (!(isset($_REQUEST['bulk_action']) && 'bulk_edit' == $_REQUEST['bulk_action'])) { /* * This is the Media/Edit Media screen. * The category taxonomy (edit screens) is a special case because * post_categories_meta_box() changes the input name */ if (isset($_REQUEST['tax_input'])) { $tax_inputs = $_REQUEST['tax_input']; } else { $tax_inputs = array(); } if (isset($_REQUEST['post_category'])) { $tax_inputs['category'] = $_REQUEST['post_category']; } if (isset($_REQUEST['tax_action'])) { $tax_actions = $_REQUEST['tax_action']; } else { $tax_actions = NULL; } if (!empty($tax_inputs) && 'checked' == MLAOptions::mla_get_option('term_assignment', false, false, MLA_WPML::$mla_language_option_definitions)) { self::_build_tax_input($post_id, $tax_inputs, $tax_actions); $tax_inputs = self::_apply_tax_input($post_id); } if (!empty($tax_inputs)) { MLAData::mla_update_single_item($post_id, array(), $tax_inputs); } } // Media/Edit Media screen, NOT Bulk Edit }
/** * Get ALL markup templates from $mla_templates, including 'default' * * @since 0.80 * * @return array|null name => value for all markup templates or null if no templates */ public static function mla_get_markup_templates() { if (!is_array(self::$mla_option_templates)) { MLA::mla_debug_add('<strong>mla_debug mla_get_markup_templates()</strong> ' . __('no templates exist', 'media-library-assistant')); return null; } $templates = array(); foreach (self::$mla_option_templates as $key => $value) { // Note order: -row-open must precede -open! $tail = strrpos($key, '-row-open-markup'); if (!(false === $tail)) { $name = substr($key, 0, $tail); $templates[$name]['row-open'] = $value; continue; } $tail = strrpos($key, '-open-markup'); if (!(false === $tail)) { $name = substr($key, 0, $tail); $templates[$name]['open'] = $value; continue; } $tail = strrpos($key, '-item-markup'); if (!(false === $tail)) { $name = substr($key, 0, $tail); $templates[$name]['item'] = $value; continue; } $tail = strrpos($key, '-row-close-markup'); if (!(false === $tail)) { $name = substr($key, 0, $tail); $templates[$name]['row-close'] = $value; continue; } $tail = strrpos($key, '-close-markup'); if (!(false === $tail)) { $name = substr($key, 0, $tail); $templates[$name]['close'] = $value; } } // foreach return $templates; }
/** * Log debug information * * @since 2.12 * * @param string $message Error message. */ private static function _mla_debug_add($message) { if (self::$mla_debug) { if (class_exists('MLA')) { MLA::mla_debug_add($message); } else { error_log($message, 0); } } }
/** * Filters all clauses for shortcode queries, post caching plugins * * This is for debug purposes only. * Defined as public because it's a filter. * * @since 1.80 * * @param array query clauses before modification * * @return array query clauses after modification (none) */ public static function mla_query_posts_clauses_request_filter($pieces) { /* translators: 1: DEBUG tag 2: SQL clauses */ MLA::mla_debug_add(sprintf(_x('%1$s: mla_query_posts_clauses_request_filter = "%2$s".', 'error_log', 'media-library-assistant'), __('DEBUG', 'media-library-assistant'), var_export($pieces, true))); return $pieces; }