esc_like() Vs esc_sql() * * @since 2.13 * * @var boolean */ public static $wp_4dot0_plus = true; /** * Initialization function, similar to __construct() * * @since 0.1 */ public static function initialize() { self::$wp_4dot0_plus = version_compare( get_bloginfo('version'), '4.0', '>=' ); self::_localize_default_columns_array(); // Set up the Media/Assistant submenu table column definitions $taxonomies = get_taxonomies( array ( 'show_ui' => true ), 'names' ); foreach ( $taxonomies as $tax_name ) { if ( MLACore::mla_taxonomy_support( $tax_name ) ) { $tax_object = get_taxonomy( $tax_name ); self::$default_columns[ 't_' . $tax_name ] = esc_html( $tax_object->labels->name ); self::$default_hidden_columns [] = 't_' . $tax_name; // self::$default_sortable_columns [] = none at this time } // supported taxonomy } // foreach $tax_name /* * For WP 4.3+ icon will be merged with the first visible preferred column */ if ( MLATest::$wp_4dot3_plus ) { unset( self::$default_columns['icon'] ); } self::$default_columns = array_merge( self::$default_columns, MLACore::mla_custom_field_support( 'default_columns' ) ); self::$default_hidden_columns = array_merge( self::$default_hidden_columns, MLACore::mla_custom_field_support( 'default_hidden_columns' ) ); self::$default_sortable_columns = array_merge( self::$default_sortable_columns, MLACore::mla_custom_field_support( 'default_sortable_columns' ) ); } /** * Find Featured Image and inserted image/link references to an attachment * * Searches all post and page content to see if the attachment is used * as a Featured Image or inserted in the post as an image or link. * * @since 0.1 * * @param int post ID of attachment * @param int post ID of attachment's parent, if any * @param boolean True to compute references, false to return empty values * * @return array Reference information; see $references array comments */ public static function mla_fetch_attachment_references( $ID, $parent, $add_references = true ) { /* * The MLAReferences class is only loaded when needed. */ if ( !class_exists( 'MLAReferences' ) ) { if ( -1 === $ID ) { return NULL; } require_once( MLA_PLUGIN_PATH . 'includes/class-mla-data-references.php' ); } return MLAReferences::mla_fetch_attachment_references_handler( $ID, $parent, $add_references ); } /** * Add Featured Image and inserted image/link references to an array of attachments * * Searches all post and page content to see if the attachmenta are used * as a Featured Image or inserted in the post as an image or link. * * @since 1.94 * * @param array WP_Post objects, passed by reference * * @return void updates WP_Post objects with new mla_references property */ public static function mla_attachment_array_fetch_references( &$attachments ) { /* * The MLAReferences class is only loaded when needed. */ if ( !class_exists( 'MLAReferences' ) ) { require_once( MLA_PLUGIN_PATH . 'includes/class-mla-data-references.php' ); } return MLAReferences::mla_attachment_array_fetch_references_handler( $attachments ); } /** * Invalidates the $mla_galleries or $galleries array and cached values * * @since 1.00 * * @param string name of the gallery's cache/option variable * * @return void */ public static function mla_flush_mla_galleries( $option_name ) { delete_transient( MLA_OPTION_PREFIX . 't_' . $option_name ); /* * If MLAReferences isn't loaded there is nothing else to do */ if ( class_exists( 'MLAReferences' ) ) { MLAReferences::mla_flush_mla_galleries_handler( $option_name ); } } /* * The $default_columns, $default_hidden_columns, and $default_sortable_columns * arrays define the "Media/Assistant" table columns. */ /** * Table column definitions * * This array defines table columns and titles where the key is the column slug (and class) * and the value is the column's title text. If you need a checkbox for bulk actions, * use the special slug "cb". * * The 'cb' column is treated differently than the rest. If including a checkbox * column in your table you must create a column_cb() method. If you don't need * bulk actions or checkboxes, simply leave the 'cb' entry out of your array. * * All of the columns are added to this array by MLA_List_Table::mla_admin_init_action. * * @since 0.1 * * @var array */ public static $default_columns = array(); /** * Default values for hidden columns * * This array is used when the user-level option is not set, i.e., * the user has not altered the selection of hidden columns. * * The value on the right-hand side must match the column slug, e.g., * array(0 => 'ID_parent, 1 => 'title_name'). * * Taxonomy and custom field columns are added to this array by * MLA_List_Table::mla_admin_init_action. * * @since 0.1 * * @var array */ public static $default_hidden_columns = array( // 'ID_parent', // 'title_name', 'post_title', 'post_name', 'parent', 'menu_order', 'featured', 'inserted', 'galleries', 'mla_galleries', // 'alt_text', // 'caption', // 'description', 'post_mime_type', 'file_url', 'base_file', // 'date', 'modified', 'author', // 'attached_to', // taxonomy columns added by mla_admin_init_action // custom field columns added by mla_admin_init_action ); /** * Sortable column definitions * * This array defines the table columns that can be sorted. The array key * is the column slug that needs to be sortable, and the value is database column * to sort by. Often, the key and value will be the same, but this is not always * the case (as the value is a column name from the database, not the list table). * * The array value also contains a boolean which is 'true' if the initial sort order * for the column is DESC/Descending. * * Taxonomy and custom field columns are added to this array by * MLAQuery::initialize. * * @since 0.1 * * @var array */ public static $default_sortable_columns = array( 'ID_parent' => array('ID',true), 'title_name' => array('title_name',false), 'post_title' => array('post_title',false), 'post_name' => array('post_name',false), 'parent' => array('post_parent',false), 'menu_order' => array('menu_order',false), // 'featured' => array('featured',false), // 'inserted' => array('inserted',false), // 'galleries' => array('galleries',false), // 'mla_galleries' => array('mla_galleries',false), 'alt_text' => array('_wp_attachment_image_alt',true), 'caption' => array('post_excerpt',false), 'description' => array('post_content',false), 'post_mime_type' => array('post_mime_type',false), 'file_url' => array('guid',false), 'base_file' => array('_wp_attached_file',false), 'date' => array('post_date',true), 'modified' => array('post_modified',true), 'author' => array('post_author',false), 'attached_to' => array('post_parent',false), // sortable taxonomy columns, if any, added by MLAQuery::initialize // sortable custom field columns, if any, added by MLAQuery::initialize ); /** * Builds the $default_columns array with translated source texts. * * @since 1.71 */ private static function _localize_default_columns_array( ) { if ( empty( self::$default_columns ) ) { // Build the default columns array at runtime to accomodate calls to the localization functions self::$default_columns = array( 'cb' => '', //Render a checkbox instead of text 'icon' => '', 'ID_parent' => esc_html( _x( 'ID/Parent', 'list_table_column', 'media-library-assistant' ) ), 'title_name' => esc_html( _x( 'Title/Name', 'list_table_column', 'media-library-assistant' ) ), 'post_title' => esc_html( _x( 'Title', 'list_table_column', 'media-library-assistant' ) ), 'post_name' => esc_html( _x( 'Name', 'list_table_column', 'media-library-assistant' ) ), 'parent' => esc_html( _x( 'Parent ID', 'list_table_column', 'media-library-assistant' ) ), 'menu_order' => esc_html( _x( 'Menu Order', 'list_table_column', 'media-library-assistant' ) ), 'featured' => esc_html( _x( 'Featured in', 'list_table_column', 'media-library-assistant' ) ), 'inserted' => esc_html( _x( 'Inserted in', 'list_table_column', 'media-library-assistant' ) ), 'galleries' => esc_html( _x( 'Gallery in', 'list_table_column', 'media-library-assistant' ) ), 'mla_galleries' => esc_html( _x( 'MLA Gallery in', 'list_table_column', 'media-library-assistant' ) ), 'alt_text' => esc_html( _x( 'ALT Text', 'list_table_column', 'media-library-assistant' ) ), 'caption' => esc_html( _x( 'Caption', 'list_table_column', 'media-library-assistant' ) ), 'description' => esc_html( _x( 'Description', 'list_table_column', 'media-library-assistant' ) ), 'post_mime_type' => esc_html( _x( 'MIME Type', 'list_table_column', 'media-library-assistant' ) ), 'file_url' => esc_html( _x( 'File URL', 'list_table_column', 'media-library-assistant' ) ), 'base_file' => esc_html( _x( 'Base File', 'list_table_column', 'media-library-assistant' ) ), 'date' => esc_html( _x( 'Date', 'list_table_column', 'media-library-assistant' ) ), 'modified' => esc_html( _x( 'Last Modified', 'list_table_column', 'media-library-assistant' ) ), 'author' => esc_html( _x( 'Author', 'list_table_column', 'media-library-assistant' ) ), 'attached_to' => esc_html( _x( 'Attached to', 'list_table_column', 'media-library-assistant' ) ), // taxonomy columns, if any, added by MLAQuery::initialize // custom field columns, if any, added by MLAQuery::initialize ); } } /** * Return the names and display values of the sortable columns * * @since 0.30 * * @return array name => array( orderby value, heading ) for sortable columns */ public static function mla_get_sortable_columns( ) { $results = array() ; foreach ( self::$default_sortable_columns as $key => $value ) { $value[1] = self::$default_columns[ $key ]; $results[ $key ] = $value; } return $results; } /** * Cache the results of mla_count_list_table_items for reuse in mla_query_list_table_items * * @since 1.40 * * @var array */ private static $mla_list_table_items = NULL; /** * Retrieve the terms in a given taxonomy, adjusting for changes in WP 4.5.0 * * @since 2.66 * * @param mixed single taxonomy (string) or taxonomy list (array of strings) * @param array arguments for taxonomy terms query * * @return array|int|WP_Error) List of WP_Term instances and their children. Will return WP_Error, if any of $taxonomies do not exist. */ public static function mla_wp_get_terms( $taxonomy, $args ) { if ( version_compare( get_bloginfo('version'), '4.5.0', '>=' ) ) { $args['taxonomy'] = $taxonomy; $terms = get_terms( $args ); } else { $terms = get_terms( $taxonomy, $args ); } return $terms; } /** * Get the total number of attachment posts * * @since 0.30 * * @param array Query variables, e.g., from $_REQUEST * @param int (optional) number of rows to skip over to reach desired page * @param int (optional) number of rows on each page * * @return integer Number of attachment posts */ public static function mla_count_list_table_items( $request, $offset = NULL, $count = NULL ) { if ( NULL !== $offset && NULL !== $count ) { $request = self::_prepare_list_table_query( $request, $offset, $count ); $request = apply_filters( 'mla_list_table_query_final_terms', $request ); self::$mla_list_table_items = apply_filters( 'mla_list_table_query_custom_items', NULL, $request ); if ( is_null( self::$mla_list_table_items ) ) { self::$mla_list_table_items = self::_execute_list_table_query( $request ); } return self::$mla_list_table_items->found_posts; } $request = self::_prepare_list_table_query( $request ); $request = apply_filters( 'mla_list_table_query_final_terms', $request ); $results = apply_filters( 'mla_list_table_query_custom_items', NULL, $request ); if ( is_null( $results ) ) { $results = self::_execute_list_table_query( $request ); } self::$mla_list_table_items = NULL; return $results->found_posts; } /** * Retrieve attachment objects for list table display * * Supports prepare_items in class-mla-list-table.php. * Modeled after wp_edit_attachments_query in wp-admin/post.php * * @since 0.1 * * @param array query parameters from web page, usually found in $_REQUEST * @param int number of rows to skip over to reach desired page * @param int number of rows on each page * * @return array attachment objects (posts) including parent data, meta data and references */ public static function mla_query_list_table_items( $request, $offset, $count ) { if ( NULL == self::$mla_list_table_items ) { $request = self::_prepare_list_table_query( $request, $offset, $count ); $request = apply_filters( 'mla_list_table_query_final_terms', $request ); self::$mla_list_table_items = apply_filters( 'mla_list_table_query_custom_items', NULL, $request ); if ( is_null( self::$mla_list_table_items ) ) { self::$mla_list_table_items = self::_execute_list_table_query( $request ); } } $attachments = self::$mla_list_table_items->posts; foreach ( $attachments as $index => $attachment ) { /* * Add parent data */ $parent_data = self::mla_fetch_attachment_parent_data( $attachment->post_parent ); foreach ( $parent_data as $parent_key => $parent_value ) { $attachments[ $index ]->{$parent_key} = $parent_value; } /* * Add meta data */ $meta_data = self::mla_fetch_attachment_metadata( $attachment->ID ); foreach ( $meta_data as $meta_key => $meta_value ) { $attachments[ $index ]->{$meta_key} = $meta_value; } } /* * Add references */ self::mla_attachment_array_fetch_references( $attachments ); return $attachments; } /** * Retrieve attachment objects for the WordPress Media Manager * * Supports month-year and taxonomy-term filters as well as the enhanced search box * * @since 1.20 * * @param array query parameters from Media Manager * @param int number of rows to skip over to reach desired page * @param int number of rows on each page * * @return object WP_Query object with query results */ public static function mla_query_media_modal_items( $request, $offset, $count ) { $request = self::_prepare_list_table_query( $request, $offset, $count ); $request = apply_filters( 'mla_media_modal_query_final_terms', $request ); $results = apply_filters( 'mla_media_modal_query_custom_items', NULL, $request ); return is_null( $results ) ? self::_execute_list_table_query( $request ) : $results; } /** * Returns information about an attachment's parent, if found * * @since 0.1 * * @param int post ID of attachment's parent, if any * * @return array Parent information; post_date, post_title and post_type */ public static function mla_fetch_attachment_parent_data( $parent_id ) { static $save_id = -1, $parent_data; if ( $save_id == $parent_id ) { return $parent_data; } elseif ( $parent_id == -1 ) { $save_id = -1; return NULL; } $parent_data = array(); if ( $parent_id ) { $parent = get_post( $parent_id ); if ( isset( $parent->post_name ) ) { $parent_data['parent_name'] = $parent->post_name; } if ( isset( $parent->post_type ) ) { $parent_data['parent_type'] = $parent->post_type; } if ( isset( $parent->post_title ) ) { $parent_data['parent_title'] = $parent->post_title; } if ( isset( $parent->post_date ) ) { $parent_data['parent_date'] = $parent->post_date; } if ( isset( $parent->post_status ) ) { $parent_data['parent_status'] = $parent->post_status; } } $save_id = $parent_id; return $parent_data; } /** * Fetch and filter meta data for an attachment * * Returns a filtered array of a post's meta data. Internal values beginning with '_' * are stripped out or converted to an 'mla_' equivalent. * * @since 0.1 * * @param int post ID of attachment * * @return array Meta data variables */ public static function mla_fetch_attachment_metadata( $post_id ) { static $save_id = -1, $results; if ( $save_id == $post_id ) { return $results; } elseif ( $post_id == -1 ) { $save_id = -1; return NULL; } $attached_file = NULL; $results = array(); $post_meta = get_metadata( 'post', $post_id ); if ( is_array( $post_meta ) ) { foreach ( $post_meta as $post_meta_key => $post_meta_value ) { if ( empty( $post_meta_key ) ) { continue; } if ( '_' == $post_meta_key{0} ) { if ( stripos( $post_meta_key, '_wp_attached_file' ) === 0 ) { $key = 'mla_wp_attached_file'; $attached_file = $post_meta_value[0]; } elseif ( stripos( $post_meta_key, '_wp_attachment_metadata' ) === 0 ) { $key = 'mla_wp_attachment_metadata'; } elseif ( stripos( $post_meta_key, '_wp_attachment_image_alt' ) === 0 ) { $key = 'mla_wp_attachment_image_alt'; } else { continue; } } else { if ( stripos( $post_meta_key, 'mla_' ) === 0 ) { $key = $post_meta_key; } else { $key = 'mla_item_' . $post_meta_key; } } /* * At this point, every value is an array; one element per instance of the key. * We'll test anyway, just to be sure, then convert single-instance values to a scalar. * Metadata array values are serialized for storage in the database. */ if ( is_array( $post_meta_value ) ) { if ( count( $post_meta_value ) == 1 ) { $post_meta_value = maybe_unserialize( $post_meta_value[0] ); } else { foreach ( $post_meta_value as $single_key => $single_value ) { $post_meta_value[ $single_key ] = maybe_unserialize( $single_value ); } } } $results[ $key ] = $post_meta_value; } // foreach $post_meta if ( ! empty( $attached_file ) ) { $last_slash = strrpos( $attached_file, '/' ); if ( false === $last_slash ) { $results['mla_wp_attached_path'] = ''; $results['mla_wp_attached_filename'] = $attached_file; } else { $results['mla_wp_attached_path'] = substr( $attached_file, 0, $last_slash + 1 ); $results['mla_wp_attached_filename'] = substr( $attached_file, $last_slash + 1 ); } } // $attached_file } // is_array($post_meta) $save_id = $post_id; return $results; } /** * WP_Query filter "parameters" * * This array defines parameters for the query's join, where and orderby filters. * The parameters are set up in the _prepare_list_table_query function, and * any further logic required to translate those values is contained in the filters. * * Array index values are: use_alt_text_view, use_postmeta_view, use_orderby_view, * alt_text_value, postmeta_key, postmeta_value, patterns, detached, * orderby, order, mla-metavalue, debug (also in search_parameters) * * @since 0.30 * * @var array */ public static $query_parameters = array(); /** * WP_Query 'posts_search' filter "parameters" * * This array defines parameters for the query's posts_search filter, which uses * 'search_string' to add a clause to the query's WHERE clause. It is shared between * the list_table-query functions here and the mla_get_shortcode_attachments function * in class-mla-shortcodes.php. This array passes the relevant parameters to the filter. * * Array index values are: * ['mla_terms_search']['phrases'] * ['mla_terms_search']['taxonomies'] * ['mla_terms_search']['radio_phrases'] => AND/OR * ['mla_terms_search']['radio_terms'] => AND/OR * ['s'] => numeric for ID/parent search * ['mla_search_fields'] => 'title', 'name', 'alt-text', 'excerpt', 'content', 'file' ,'terms' * Note: 'alt-text' and 'file' are not supported in [mla_gallery] * ['mla_search_connector'] => AND/OR * ['sentence'] => entire string must match as one "keyword" * ['exact'] => entire string must match entire field value * ['debug'] => internal element, console/log/shortcode/none * ['tax_terms_count'] => internal element, shared with JOIN and GROUP BY filters * * @since 2.00 * * @var array */ public static $search_parameters = array(); /** * Fetch custom field option value given a slug * * @since 1.10 * * @param string slug, e.g., 'c_File Size' for the 'File Size' field * * @return array option value, e.g., array( 'name' => 'File Size', ... ) */ public static function mla_custom_field_option_value( $slug ) { $option_values = MLACore::mla_get_option( 'custom_field_mapping' ); foreach ( $option_values as $key => $value ) { if ( $slug == 'c_' . $value['name'] ) { return $value; } } return array(); } // mla_custom_field_option_value /** * Separate negative ("NOT IN") search string phrases from positive phrases * * @since 2.78 * * @uses array self::$search_parameters * * @param string whole_string e.g., ( "a phrase" separate phrase ) without parens, space delimited * @param string term_delimiter separator between terms for terms search * @param string negative_delimiter delimiter for negative phrases, e.g., /exclude this/, /"exclude also"/ * * @return array ( 'original' => all phrases, 'positive' => positive phrases, 'negative' => negative phrases ) */ public static function mla_divide_search_string( $whole_string, $term_delimiter = ',', $negative_delimiter = '/' ) { $phrases = array( 'original' => $whole_string, 'positive' => '', 'negative' => '' ); $separator_list = " \n\t\r\0\x0B"; if ( false === strpos( $separator_list, $term_delimiter ) ) { $separator_list .= $term_delimiter; } else { $separator_list .= ','; } $negative_prepend = false; $in_negative = false; $current_quote = ''; $in_trim = false; $current_separator = ' '; $argument = ''; $index = 0; while ( $index < strlen( $whole_string ) ) { $byte = $whole_string[ $index++ ]; //error_log( __LINE__ . " MLAQuery::mla_divide_search_string byte |{$byte}| in_trim |{$in_trim}| in_negative |{$in_negative}| current_quote |{$current_quote}| current_separator |{$current_separator}| argument |{$argument}| phrases = " . var_export( $phrases, true ), 0 ); // Are we between arguments? if ( ( false !== strpos( $separator_list, $byte ) ) && !( $in_negative || $current_quote ) ) { $in_trim = true; if ( $term_delimiter === $byte ) { $current_separator = $term_delimiter; } continue; } elseif ( $in_trim ) { // Have we seen a positive argument? if ( strlen( $argument ) ) { if ( $negative_prepend ) { $phrases['negative'] .= $argument; $negative_prepend = false; } else { $phrases['positive'] .= $argument; } $argument = ''; } if ( strlen( $phrases['positive'] ) ) { $phrases['positive'] .= $current_separator; } if ( strlen( $phrases['negative'] ) ) { $phrases['negative'] .= $current_separator; } $current_separator = ' '; $in_trim = false; } // Are we finishing a negative phrase? if ( $in_negative && ( $negative_delimiter == $byte ) ) { if ( strlen( $argument ) ) { $phrases['negative'] .= $argument; $negative_prepend = false; // handle double-delimiting, i.e., -/phrase/ $argument = ''; } $in_negative = false; continue; } // Are we finishing a quoted phrase? if ( $current_quote == $byte ) { if ( strlen( $argument ) ) { if ( $in_negative ) { $phrases['negative'] .= $current_quote . $argument . $current_quote; } else { if ( $negative_prepend ) { $phrases['negative'] .= $current_quote . $argument . $current_quote; $negative_prepend = false; } else { $phrases['positive'] .= $current_quote . $argument . $current_quote; } } $argument = ''; } $current_quote = ''; continue; } // Are we starting a negative phrase? if ( ( $negative_delimiter == $byte ) && !$current_quote ) { if ( strlen( $argument ) ) { if ( $negative_prepend ) { $phrases['negative'] .= $argument; $negative_prepend = false; } else { $phrases['positive'] .= $argument; } $argument = ''; } $in_negative = true; continue; } // Are we starting a quoted phrase? if ( !$current_quote && ( '\'' == $byte || '"' == $byte ) ) { $current_quote = $byte; continue; } // Look for prepended "-" as added to WP_Query in WP 4.4 if ( !$current_quote && empty( $argument ) && '-' === $byte ) { $negative_prepend = true; } else { // Accumulate a phrase $argument .= $byte; } } // index < strlen // Close out the final argument if ( strlen( $argument ) ) { if ( $negative_prepend ) { $phrases['negative'] .= $argument; } else { $phrases['positive'] .= $argument; } } //error_log( __LINE__ . ' MLAQuery::mla_divide_search_string phrases = ' . var_export( $phrases, true ), 0 ); return $phrases; } // mla_divide_search_string /** * Sanitize and expand query arguments from request variables * * Prepare the arguments for WP_Query. * Modeled after wp_edit_attachments_query in wp-admin/post.php * * @since 0.1 * * @param array query parameters from web page, usually found in $_REQUEST * @param int Optional number of rows (default 0) to skip over to reach desired page * @param int Optional number of rows on each page (0 = all rows, default) * * @return array revised arguments suitable for WP_Query */ private static function _prepare_list_table_query( $raw_request, $offset = 0, $count = 0 ) { /* * Go through the $raw_request, take only the arguments that are used in the query and * sanitize or validate them. */ if ( ! is_array( $raw_request ) ) { /* translators: 1: ERROR tag 2: function name 3: non-array value */ MLACore::mla_debug_add( sprintf( _x( '%1$s: %2$s non-array "%3$s"', 'error_log', 'media-library-assistant' ), __( 'ERROR', 'media-library-assistant' ), 'MLAQuery::_prepare_list_table_query', var_export( $raw_request, true ) ), MLACore::MLA_DEBUG_CATEGORY_ANY ); return NULL; } // Make sure the current orderby choice still exists or revert to default. $default_orderby = array_merge( array( 'none' => array('none',false) ), self::mla_get_sortable_columns( ) ); $current_orderby = MLACore::mla_get_option( MLACoreOptions::MLA_DEFAULT_ORDERBY ); $found_current = false; foreach ( $default_orderby as $key => $value ) { if ( $current_orderby == $value[0] ) { $found_current = true; break; } } if ( $found_current ) { /* * Custom fields can have HTML reserved characters, which are encoded by * mla_get_sortable_columns, so a separate, unencoded list is required. */ $default_orderby = MLACore::mla_custom_field_support( 'custom_sortable_columns' ); foreach ( $default_orderby as $sort_key => $sort_value ) { if ( $current_orderby == $sort_key ) { $current_orderby = 'c_' . $sort_value[0]; break; } } // foreach } else { MLACore::mla_delete_option( MLACoreOptions::MLA_DEFAULT_ORDERBY ); $current_orderby = MLACore::mla_get_option( MLACoreOptions::MLA_DEFAULT_ORDERBY ); } $clean_request = array ( 'm' => 0, 'orderby' => $current_orderby, 'order' => MLACore::mla_get_option( MLACoreOptions::MLA_DEFAULT_ORDER ), 'post_type' => 'attachment', 'post_status' => 'inherit', 'mla_search_connector' => 'AND', 'mla_search_fields' => array() ); foreach ( $raw_request as $key => $value ) { switch ( $key ) { /* * 'sentence' and 'exact' modify the keyword search ('s') * Their value is not important, only their presence. */ case 'sentence': case 'exact': case 'mla-tax': case 'mla-term': $clean_request[ $key ] = sanitize_title_for_query( $value ); break; case 'orderby': if ( in_array( $value, array( 'none', 'post__in' ) ) ) { $clean_request[ $key ] = $value; } else { $orderby = NULL; /* * Custom fields can have HTML reserved characters, which are encoded by * mla_get_sortable_columns, so a separate, unencoded list is required. */ $sortable_columns = MLACore::mla_custom_field_support( 'custom_sortable_columns' ); foreach ($sortable_columns as $sort_key => $sort_value ) { if ( $value == $sort_key ) { $orderby = 'c_' . $sort_value[0]; break; } } // foreach if ( NULL === $orderby ) { $sortable_columns = MLAQuery::mla_get_sortable_columns(); foreach ($sortable_columns as $sort_key => $sort_value ) { if ( $value == $sort_value[0] ) { $orderby = $value; break; } } // foreach } if ( NULL !== $orderby ) { $clean_request[ $key ] = $orderby; } } break; // ids allows hooks to supply a persistent list of items case 'ids': if ( is_array( $value ) ) { $clean_request[ 'post__in' ] = $value; } else { $clean_request[ 'post__in' ] = array_map( 'absint', explode( ',', $value ) ); } break; // post__in and post__not_in are used in the Media Modal Ajax queries case 'post__in': case 'post__not_in': case 'post_mime_type': // post_parent__in and post_parent__not_in are used in example plugins case 'post_parent__in': case 'post_parent__not_in': $clean_request[ $key ] = $value; break; case 'parent': case 'post_parent': $clean_request[ 'post_parent' ] = absint( $value ); break; // ['m'] - filter by year and month of post, e.g., 201204 case 'author': case 'm': $clean_request[ $key ] = absint( $value ); break; // ['mla_filter_term'] - filter by taxonomy term ID (-1 allowed), or by custom field case 'mla_filter_term': if ( MLACoreOptions::MLA_FILTER_METAKEY == MLACore::mla_taxonomy_support('', 'filter') ) { if ( MLACoreOptions::ALL_MLA_FILTER_METAKEY != $value ) { $clean_request['mla-metakey'] = MLACore::mla_taxonomy_support('', 'metakey'); $clean_request['mla-metavalue'] = stripslashes( $value ); } break; } $clean_request[ $key ] = intval( $value ); break; case 'order': switch ( $value = strtoupper ($value ) ) { case 'ASC': case 'DESC': $clean_request[ $key ] = $value; break; default: $clean_request[ $key ] = 'ASC'; } break; case 'detached': if ( ( '0' == $value ) || ( '1' == $value ) ) { $clean_request['detached'] = $value; } break; case 'status': if ( 'trash' == $value ) { $clean_request['post_status'] = 'trash'; } break; /* * ['s'] - Search Media by one or more keywords * ['mla_search_connector'], ['mla_search_fields'] - Search Media options */ case 's': switch ( substr( $value, 0, 3 ) ) { case '>|<': $clean_request['debug'] = 'console'; break; case '<|>': $clean_request['debug'] = 'log'; break; } if ( isset( $clean_request['debug'] ) ) { $value = substr( $value, 3 ); } $value = stripslashes( trim( $value ) ); if ( ! empty( $value ) ) { $clean_request[ $key ] = $value; } break; case 'mla_terms_search': if ( ! empty( $value['phrases'] ) && ! empty( $value['taxonomies'] ) ) { $value['phrases'] = stripslashes( trim( $value['phrases'] ) ); if ( ! empty( $value['phrases'] ) ) { $clean_request[ $key ] = $value; } } break; case 'mla_search_connector': case 'mla_search_fields': $clean_request[ $key ] = $value; break; case 'mla-metakey': case 'mla-metavalue': $clean_request[ $key ] = stripslashes( html_entity_decode( $value ) ); break; case 'meta_query': if ( ! empty( $value ) ) { if ( is_array( $value ) ) { $clean_request[ $key ] = $value; } else { $clean_request[ $key ] = json_decode( stripslashes( $value ), true ); unset( $clean_request[ $key ]['slug'] ); } // not array } break; // boolean values, default true case 'cache_results': case 'update_post_meta_cache': case 'update_post_term_cache': if ( ! empty( $value ) && ( 'true' != strtolower( $value ) ) ) { $clean_request[ $key ] = false; } break; default: // ignore anything else in $_REQUEST } // switch $key } // foreach $raw_request // Pass query and search parameters to the filters for _execute_list_table_query self::$query_parameters = array( self::MLA_ALT_TEXT_SUBQUERY => false, self::MLA_FILE_SUBQUERY => false, self::MLA_TABLE_VIEW_SUBQUERY => false, self::MLA_ORDERBY_SUBQUERY => false, 'orderby' => $clean_request['orderby'], 'order' => $clean_request['order'] ); self::$query_parameters['detached'] = isset( $clean_request['detached'] ) ? $clean_request['detached'] : NULL; self::$search_parameters = array( 'debug' => 'none' ); /* * Matching a meta_value to NULL requires a LEFT JOIN to a view and a special WHERE clause * Matching a wildcard pattern requires mainpulating the WHERE clause, too */ if ( isset( $clean_request['meta_query']['key'] ) ) { self::$query_parameters[self::MLA_TABLE_VIEW_SUBQUERY] = true; self::$query_parameters['postmeta_key'] = $clean_request['meta_query']['key']; self::$query_parameters['postmeta_value'] = NULL; unset( $clean_request['meta_query'] ); } elseif ( isset( $clean_request['meta_query']['patterns'] ) ) { self::$query_parameters['patterns'] = $clean_request['meta_query']['patterns']; unset( $clean_request['meta_query']['patterns'] ); } if ( isset( $clean_request['debug'] ) ) { self::$query_parameters['debug'] = $clean_request['debug']; self::$search_parameters['debug'] = $clean_request['debug']; MLACore::mla_debug_mode( $clean_request['debug'] ); unset( $clean_request['debug'] ); } // We must patch the WHERE clause if there are leading spaces in the meta_value if ( isset( $clean_request['mla-metavalue'] ) && ( 0 < strlen( $clean_request['mla-metavalue'] ) ) && ( ' ' == $clean_request['mla-metavalue'][0] ) ) { self::$query_parameters['mla-metavalue'] = $clean_request['mla-metavalue']; } // We will handle "Terms Search" in the mla_query_posts_search_filter. if ( isset( $clean_request['mla_terms_search'] ) ) { self::$search_parameters['mla_terms_search'] = $clean_request['mla_terms_search']; // The Terms Search overrides any terms-based keyword search for now; too complicated. if ( isset( $clean_request['mla_search_fields'] ) ) { foreach ( $clean_request['mla_search_fields'] as $index => $field ) { if ( 'terms' == $field ) { unset ( $clean_request['mla_search_fields'][ $index ] ); } } } } // We will handle keyword search in the mla_query_posts_search_filter. if ( isset( $clean_request['s'] ) ) { self::$search_parameters['s'] = $clean_request['s']; self::$search_parameters['mla_search_fields'] = apply_filters( 'mla_list_table_search_filter_fields', $clean_request['mla_search_fields'], array( 'title', 'name', 'alt-text', 'excerpt', 'content', 'file' ,'terms' ) ); self::$search_parameters['mla_search_connector'] = $clean_request['mla_search_connector']; self::$search_parameters['sentence'] = isset( $clean_request['sentence'] ); self::$search_parameters['exact'] = isset( $clean_request['exact'] ); if ( in_array( 'alt-text', self::$search_parameters['mla_search_fields'] ) ) { self::$query_parameters[self::MLA_ALT_TEXT_SUBQUERY] = true; } if ( in_array( 'file', self::$search_parameters['mla_search_fields'] ) ) { self::$query_parameters[self::MLA_FILE_SUBQUERY] = true; } if ( in_array( 'terms', self::$search_parameters['mla_search_fields'] ) ) { self::$search_parameters['mla_search_taxonomies'] = MLACore::mla_supported_taxonomies( 'term-search' ); } unset( $clean_request['s'] ); unset( $clean_request['mla_search_connector'] ); unset( $clean_request['mla_search_fields'] ); unset( $clean_request['sentence'] ); unset( $clean_request['exact'] ); } /* * We have to handle custom field/post_meta values here * because they need a JOIN clause supplied by WP_Query */ if ( 'c_' == substr( $clean_request['orderby'], 0, 2 ) ) { $option_value = MLAQuery::mla_custom_field_option_value( $clean_request['orderby'] ); if ( isset( $option_value['name'] ) ) { self::$query_parameters[self::MLA_ORDERBY_SUBQUERY] = true; self::$query_parameters['orderby_key'] = $option_value['name']; if ( isset($clean_request['orderby']) ) { unset($clean_request['orderby']); } if ( isset($clean_request['order']) ) { unset($clean_request['order']); } } } else { // custom field switch ( self::$query_parameters['orderby'] ) { /* * '_wp_attachment_image_alt' is special; it can have NULL values, * so we'll handle it in the JOIN and ORDERBY filters */ case '_wp_attachment_image_alt': self::$query_parameters[self::MLA_ORDERBY_SUBQUERY] = true; self::$query_parameters['orderby_key'] = '_wp_attachment_image_alt'; if ( isset($clean_request['orderby']) ) { unset($clean_request['orderby']); } if ( isset($clean_request['order']) ) { unset($clean_request['order']); } break; case '_wp_attached_file': $clean_request['meta_key'] = '_wp_attached_file'; $clean_request['orderby'] = 'meta_value'; $clean_request['order'] = self::$query_parameters['order']; break; } // switch $orderby } // Ignore incoming paged value; use offset and count instead if ( ( (int) $count ) > 0 ) { $clean_request['offset'] = $offset; $clean_request['posts_per_page'] = $count; } elseif ( ( (int) $count ) == -1 ) { $clean_request['posts_per_page'] = $count; } /* * ['mla_filter_term'] - filter by taxonomy * * cat = 0 is "All Categories", i.e., no filtering * cat = -1 is "No Categories" */ if ( isset( $clean_request['mla_filter_term'] ) ) { if ( $clean_request['mla_filter_term'] != 0 ) { $tax_filter = MLACore::mla_taxonomy_support('', 'filter'); if ( $clean_request['mla_filter_term'] == -1 ) { $term_list = MLAQuery::mla_wp_get_terms( $tax_filter, array( 'fields' => 'ids', 'hide_empty' => false ) ); $clean_request['tax_query'] = array( array( 'taxonomy' => $tax_filter, 'field' => 'id', 'terms' => $term_list, 'operator' => 'NOT IN' ) ); } else { // mla_filter_term == -1 $clean_request['tax_query'] = array( array( 'taxonomy' => $tax_filter, 'field' => 'id', 'terms' => array( (int) $clean_request['mla_filter_term'] ), 'include_children' => ( 'checked' == MLACore::mla_get_option( MLACoreOptions::MLA_TAXONOMY_FILTER_INCLUDE_CHILDREN ) ) ) ); } // mla_filter_term != -1 } // mla_filter_term != 0 unset( $clean_request['mla_filter_term'] ); } // isset mla_filter_term if ( isset( $clean_request['mla-tax'] ) && isset( $clean_request['mla-term'] )) { $clean_request['tax_query'] = array( array( 'taxonomy' => $clean_request['mla-tax'], 'field' => 'slug', 'terms' => $clean_request['mla-term'], 'include_children' => false ) ); unset( $clean_request['mla-tax'] ); unset( $clean_request['mla-term'] ); } // isset mla_tax if ( isset( $clean_request['mla-metakey'] ) && isset( $clean_request['mla-metavalue'] ) ) { $clean_request['meta_key'] = $clean_request['mla-metakey']; $clean_request['meta_value'] = $clean_request['mla-metavalue']; unset( $clean_request['mla-metakey'] ); unset( $clean_request['mla-metavalue'] ); } // isset mla_tax if ( !empty( self::$search_parameters['s'] ) ) { $search_phrases = self::mla_divide_search_string( self::$search_parameters['s'] ); //error_log( __LINE__ . " MLAQuery::_prepare_list_table_query search_phrases = " . var_export( $search_phrases, true ), 0 ); if ( !empty( $search_phrases['negative'] ) ) { self::$search_parameters['s'] = $search_phrases['negative']; $clean_request['fields'] = 'ids'; $excluded_items = self::_execute_list_table_query( $clean_request ); //error_log( __LINE__ . " MLAQuery::_prepare_list_table_query posts = " . var_export( $excluded_items->posts, true ), 0 ); unset( $clean_request['fields'] ); self::$search_parameters['s'] = $search_phrases['positive']; self::$search_parameters['exclude'] = implode( ',', $excluded_items->posts); } } //error_log( __LINE__ . " MLAQuery::_prepare_list_table_query clean_request = " . var_export( $clean_request, true ), 0 ); //error_log( __LINE__ . " MLAQuery::_prepare_list_table_query search_parameters = " . var_export( self::$search_parameters, true ), 0 ); if ( !empty( self::$search_parameters['mla_terms_search'] ) ) { $search_phrases = self::mla_divide_search_string( self::$search_parameters['mla_terms_search']['phrases'] ); //error_log( __LINE__ . " MLAQuery::_prepare_list_table_query mla_terms_search search_phrases = " . var_export( $search_phrases, true ), 0 ); if ( !empty( $search_phrases['negative'] ) ) { self::$search_parameters['mla_terms_search']['phrases'] = $search_phrases['negative']; $clean_request['fields'] = 'ids'; $excluded_items = self::_execute_list_table_query( $clean_request ); //error_log( __LINE__ . " MLAQuery::_prepare_list_table_query mla_terms_search posts = " . var_export( $excluded_items->posts, true ), 0 ); unset( $clean_request['fields'] ); unset( self::$search_parameters['tax_terms_count'] ); self::$search_parameters['mla_terms_search']['phrases'] = $search_phrases['positive']; self::$search_parameters['mla_terms_search']['exclude'] = implode( ',', $excluded_items->posts ); } } //error_log( __LINE__ . " MLAQuery::_prepare_list_table_query clean_request = " . var_export( $clean_request, true ), 0 ); //error_log( __LINE__ . " MLAQuery::_prepare_list_table_query search_parameters = " . var_export( self::$search_parameters, true ), 0 ); return $clean_request; } /** * Add filters, run query, remove filters * * @since 0.30 * * @param array query parameters from web page, usually found in $_REQUEST * * @return object WP_Query object with query results */ private static function _execute_list_table_query( $request ) { global $wpdb; static $wpmf_pre_get_posts_priority = false, $wpmf_pre_get_posts1_priority = false; add_filter( 'posts_search', 'MLAQuery::mla_query_posts_search_filter' ); add_filter( 'posts_where', 'MLAQuery::mla_query_posts_where_filter' ); add_filter( 'posts_join', 'MLAQuery::mla_query_posts_join_filter' ); add_filter( 'posts_groupby', 'MLAQuery::mla_query_posts_groupby_filter' ); add_filter( 'posts_orderby', 'MLAQuery::mla_query_posts_orderby_filter' ); /* * Disable Relevanssi - A Better Search, v3.2 by Mikko Saari * relevanssi_prevent_default_request( $request, $query ) * apply_filters('relevanssi_admin_search_ok', $admin_search_ok, $query ); */ if ( function_exists( 'relevanssi_prevent_default_request' ) ) { add_filter( 'relevanssi_admin_search_ok', 'MLAQuery::mla_query_relevanssi_admin_search_ok_filter' ); } // Remove WP Media Folders actions from MLA queries for the Media/Assistant submenu table if ( isset( $GLOBALS['wp_media_folder'] ) && isset( $_REQUEST['page'] ) && ( MLACore::ADMIN_PAGE_SLUG == $_REQUEST['page'] ) ) { $wpmf_pre_get_posts_priority = has_filter( 'pre_get_posts', array( $GLOBALS['wp_media_folder'], 'wpmf_pre_get_posts' ) ); $wpmf_pre_get_posts1_priority = has_filter( 'pre_get_posts', array( $GLOBALS['wp_media_folder'], 'wpmf_pre_get_posts1' ) ); } if ( false !== $wpmf_pre_get_posts_priority ) { remove_action( 'pre_get_posts', array( $GLOBALS['wp_media_folder'], 'wpmf_pre_get_posts' ), $wpmf_pre_get_posts_priority ); } if ( false !== $wpmf_pre_get_posts1_priority ) { remove_action( 'pre_get_posts', array( $GLOBALS['wp_media_folder'], 'wpmf_pre_get_posts1' ), $wpmf_pre_get_posts1_priority ); } if ( isset( self::$query_parameters['debug'] ) ) { $debug_array = array( 'posts_search' => MLACore::mla_decode_wp_filter('posts_search'), 'posts_join' => MLACore::mla_decode_wp_filter('posts_join'), 'posts_where' => MLACore::mla_decode_wp_filter('posts_where'), 'posts_orderby' => MLACore::mla_decode_wp_filter('posts_orderby') ); /* translators: 1: DEBUG tag 2: query filter details */ MLACore::mla_debug_add( sprintf( _x( '%1$s: _execute_list_table_query $wp_filter = "%2$s".', 'error_log', 'media-library-assistant' ), __( 'DEBUG', 'media-library-assistant' ), var_export( $debug_array, true ) ) ); add_filter( 'posts_clauses', 'MLAQuery::mla_query_posts_clauses_filter', 0x7FFFFFFF, 1 ); add_filter( 'posts_clauses_request', 'MLAQuery::mla_query_posts_clauses_request_filter', 0x7FFFFFFF, 1 ); } // debug $results = new WP_Query( $request ); if ( isset( self::$query_parameters['debug'] ) ) { remove_filter( 'posts_clauses', 'MLAQuery::mla_query_posts_clauses_filter', 0x7FFFFFFF ); remove_filter( 'posts_clauses_request', 'MLAQuery::mla_query_posts_clauses_request_filter', 0x7FFFFFFF ); $debug_array = array( 'request' => $request, 'query_parameters' => self::$query_parameters, 'post_count' => $results->post_count, 'found_posts' => $results->found_posts ); /* translators: 1: DEBUG tag 2: query details */ MLACore::mla_debug_add( sprintf( _x( '%1$s: _execute_list_table_query WP_Query = "%2$s".', 'error_log', 'media-library-assistant' ), __( 'DEBUG', 'media-library-assistant' ), var_export( $debug_array, true ) ) ); /* translators: 1: DEBUG tag 2: SQL statement */ MLACore::mla_debug_add( sprintf( _x( '%1$s: _execute_list_table_query SQL_request = "%2$s".', 'error_log', 'media-library-assistant' ), __( 'DEBUG', 'media-library-assistant' ), var_export( $results->request, true ) ) ); } // debug if ( false !== $wpmf_pre_get_posts1_priority ) { add_action( 'pre_get_posts', array( $GLOBALS['wp_media_folder'], 'wpmf_pre_get_posts1' ), $wpmf_pre_get_posts1_priority ); } if ( false !== $wpmf_pre_get_posts_priority ) { add_action( 'pre_get_posts', array( $GLOBALS['wp_media_folder'], 'wpmf_pre_get_posts' ), $wpmf_pre_get_posts_priority ); } if ( function_exists( 'relevanssi_prevent_default_request' ) ) { remove_filter( 'relevanssi_admin_search_ok', 'MLAQuery::mla_query_relevanssi_admin_search_ok_filter' ); } remove_filter( 'posts_orderby', 'MLAQuery::mla_query_posts_orderby_filter' ); remove_filter( 'posts_groupby', 'MLAQuery::mla_query_posts_groupby_filter' ); remove_filter( 'posts_join', 'MLAQuery::mla_query_posts_join_filter' ); remove_filter( 'posts_where', 'MLAQuery::mla_query_posts_where_filter' ); remove_filter( 'posts_search', 'MLAQuery::mla_query_posts_search_filter' ); return $results; } /** * Detects wildcard searches, i.e., containing an asterisk outside quotes * * Defined as public because it's a callback from array_map(). * * @since 2.13 * * @param string search string * * @return boolean true if wildcard */ private static function _wildcard_search_string( $search_string ) { preg_match_all('/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $search_string, $matches); if ( is_array( $matches ) ) { foreach ( $matches[0] as $term ) { if ( '"' == substr( $term, 0, 1) ) { continue; } if ( false !== strpos( $term, '*' ) ) { return true; } } } return false; } /** * Replaces a WordPress function deprecated in v3.7 * * Defined as public because it's a callback from array_map(). * * @since 1.51 * * @param string search term before modification * * @return string cleaned up search term */ public static function mla_search_terms_tidy( $term ) { return trim( $term, "\"'\n\r " ); } /** * Isolates keyword match results to word boundaries * * Eliminates matches such as "man" in "woman". * * @since 2.11 * * @param string the quoted phrase (without enclosing quotes) * @param string the entire term * * @return boolean $needle is a word match within $haystack */ private static function _match_quoted_phrase( $needle, $haystack ) { $haystack = strtolower( html_entity_decode( $haystack ) ); $needle = strtolower( html_entity_decode( $needle ) ); // Escape the PCRE meta-characters $safe_needle = ''; for ( $index = 0; $index < strlen( $needle ); $index++ ) { $chr = $needle[ $index ]; if ( false !== strpos( '\\^$.[]()?*+{}/', $chr ) ) { $safe_needle .= '\\'; } $safe_needle .= $chr; } $pattern = '/^' . $safe_needle . '$|^' . $safe_needle . '\s+|\s+' . $safe_needle . '\s+|\s+' . $safe_needle . '$/'; $match_count = preg_match_all($pattern, $haystack, $matches); return 0 < $match_count; } /** * Process a terms search term or phrase list with quoted phrases and variable delimiters * * @since 2.31 * * @param string phrases, e.g., ( "a phrase" separate phrase ) without parens, space delimited * @param string inter-term/phrase delimiter * @param boolean true escape backslash values, false to preserve them * * @return array individual arguments, e.g. array( 0 => '"a phrase"', 1 => 'separate', 2 => 'phrase' ) */ private static function _parse_terms_search( $whole_string, $delimiter = ',', $full_parse = false ) { $trim_list = " \n\t\r\0\x0B,"; // space,line feed,tab,carriage return, null,vertical tab,comma if ( false === strpos( $trim_list, $delimiter ) ) { $trim_list .= $delimiter; } $whole_string = trim( $whole_string, $trim_list ); $phrases = array(); //error_log( __LINE__ . " MLAQuery::_parse_terms_search( {$full_parse} ) whole_string = " . var_export( $whole_string, true ), 0 ); while ( strlen( $whole_string ) ) { $argument = ''; $index = 0; // Check for enclosing quotes $current_delimiter = $whole_string[0]; if ( '\'' == $current_delimiter || '"' == $current_delimiter ) { $index++; } else { $current_delimiter = ''; } while ( $index < strlen( $whole_string ) ) { $byte = $whole_string[ $index++ ]; if ( '\\' == $byte && $full_parse ) { // could be a 1- to 3-digit octal value $digit_limit = $index + 3; $digit_index = $index; while ( $digit_index < $digit_limit ) { if ( ! ctype_digit( $whole_string[ $digit_index ] ) ) { break; } else { $digit_index++; } } if ( $digit_count = $digit_index - $index ) { $argument .= chr( octdec( substr( $whole_string, $index, $digit_count ) ) ); $index += $digit_count; } else { // accept the character following the backslash $argument .= $whole_string[ $index ]; $index++; } } else { // just another character, but check for closing delimiter if ( $current_delimiter == $byte || ( empty( $current_delimiter ) && $delimiter == $byte ) ) { break; } $argument .= $byte; } } // index < strlen if ( $full_parse ) { $phrases[] = $argument; } else { // Restore quotes for word-boundary check $phrases[] = $current_delimiter . $argument . $current_delimiter; } //error_log( __LINE__ . " MLAQuery::_parse_terms_search( {$index} ) whole_string = " . var_export( $whole_string, true ), 0 ); $whole_string = trim( substr( $whole_string, $index ), $trim_list ); //error_log( __LINE__ . ' MLAQuery::_parse_terms_search whole_string = ' . var_export( $whole_string, true ), 0 ); //error_log( __LINE__ . ' MLAQuery::_parse_terms_search phrases = ' . var_export( $phrases, true ), 0 ); } // strlen( $whole_string ) return $phrases; } /** * Adds a keyword search to the WHERE clause, if required * * Defined as public because it's a filter. * * @since 0.60 * * @param array Terms search phrases and delimiters * @param string SQL clause for tax query, by reference * * @return integer Taxonomy JOIN clauses required. Updates $tax_clause as well */ private static function _generate_tax_clause( $terms_search_parameters, &$tax_clause ) { //error_log( __LINE__ . ' MLAQuery::_generate_tax_clause terms_search_parameters = ' . var_export( $terms_search_parameters, true ), 0 ); $term_delimiter = isset( $terms_search_parameters['term_delimiter'] ) ? $terms_search_parameters['term_delimiter'] : ','; $phrase_delimiter = isset( $terms_search_parameters['phrase_delimiter'] ) ? $terms_search_parameters['phrase_delimiter'] : ' '; $tax_clause = ''; $tax_index = 0; $terms = self::_parse_terms_search( $terms_search_parameters['phrases'], $term_delimiter ); //error_log( __LINE__ . " MLAQuery::_generate_tax_clause terms_search_parameters terms = " . var_export( $terms, true ), 0 ); if ( 1 < count( $terms ) ) { $terms_connector = '('; } else { $terms_connector = ''; } $matched_terms = 0; foreach ( $terms as $term ) { // Find the quoted phrases for a word-boundary check $phrases = self::_parse_terms_search( $term, $phrase_delimiter, false ); //error_log( __LINE__ . " MLAQuery::_generate_tax_clause terms_search_parameters( {$term} ) phrases = " . var_export( $phrases, true ), 0 ); $quoted = array(); foreach ( $phrases as $index => $phrase ) { $delimiter = substr( $phrase, 0, 1 ); $quoted[ $index ] = ( '"' == $delimiter ) || ( "'" == $delimiter ); } //error_log( __LINE__ . " MLAQuery::_generate_tax_clause terms_search_parameters( {$term} ) quoted = " . var_export( $quoted, true ), 0 ); // Strip delimiters and escape backslashes $phrases = self::_parse_terms_search( $term, $phrase_delimiter, true ); //error_log( __LINE__ . " MLAQuery::_generate_tax_clause terms_search_parameters( {$term} ) phrases = " . var_export( $phrases, true ), 0 ); $tax_terms = array(); $tax_counts = array(); foreach ( $phrases as $index => $phrase ) { if ( isset( $terms_search_parameters['exact'] ) ) { $the_terms = array(); foreach( $terms_search_parameters['taxonomies'] as $taxonomy ) { // WordPress encodes special characters, e.g., "&" as HTML entities in term names $the_term = get_term_by( 'name', _wp_specialchars( $phrase ), $taxonomy ); if ( false !== $the_term ) { $the_terms[] = $the_term; } } } else { $is_wildcard_search = ( ! $quoted[ $index ] ) && self::_wildcard_search_string( $phrase ); if ( $is_wildcard_search ) { add_filter( 'terms_clauses', 'MLAQuery::mla_query_terms_clauses_filter', 0x7FFFFFFF, 3 ); } // WordPress encodes special characters, e.g., "&" as HTML entities in term names $the_terms = MLAQuery::mla_wp_get_terms( $terms_search_parameters['taxonomies'], array( 'name__like' => _wp_specialchars( $phrase ), 'fields' => 'all', 'hide_empty' => false ) ); if ( $is_wildcard_search ) { remove_filter( 'terms_clauses', 'MLAQuery::mla_query_terms_clauses_filter', 0x7FFFFFFF ); } // Invalid taxonomy will return WP_Error object if ( ! is_array( $the_terms ) ) { $the_terms = array(); } if ( $quoted[ $index ] ) { foreach ( $the_terms as $term_index => $the_term ) { if ( ! self::_match_quoted_phrase( $phrase, $the_term->name ) ) { unset( $the_terms[ $term_index ]); } } } // quoted phrase } // not exact //error_log( __LINE__ . " MLAQuery::_generate_tax_clause terms_search_parameters( {$index}, {$phrase} ) the_terms = " . var_export( $the_terms, true ), 0 ); foreach( $the_terms as $the_term ) { $tax_terms[ $the_term->taxonomy ][ $the_term->term_id ] = (integer) $the_term->term_taxonomy_id; if ( isset( $tax_counts[ $the_term->taxonomy ][ $the_term->term_id ] ) ) { $tax_counts[ $the_term->taxonomy ][ $the_term->term_id ]++; } else { $tax_counts[ $the_term->taxonomy ][ $the_term->term_id ] = 1; } } } // foreach phrase //error_log( __LINE__ . ' MLAQuery::_generate_tax_clause tax_counts = ' . var_export( $tax_counts, true ), 0 ); // For the AND connector, a taxonomy term must have all of the search terms within it if ( 'AND' == $terms_search_parameters['radio_phrases'] ) { $search_term_count = count( $phrases ); foreach ($tax_terms as $taxonomy => $term_ids ) { foreach ( $term_ids as $term_id => $term_taxonomy_id ) { if ( $search_term_count != $tax_counts[ $taxonomy ][ $term_id ] ) { unset( $term_ids[ $term_id ] ); } } if ( empty( $term_ids ) ) { unset( $tax_terms[ $taxonomy ] ); } else { $tax_terms[ $taxonomy ] = $term_ids; } } // foreach taxonomy } // AND (i.e., All phrases) //error_log( __LINE__ . ' MLAQuery::_generate_tax_clause tax_terms = ' . var_export( $tax_terms, true ), 0 ); if ( empty( $tax_terms ) ) { if ( 'AND' == $terms_search_parameters['radio_terms'] ) { $tax_clause = ''; break; } } else { $inner_connector = ''; $tax_clause .= $terms_connector; foreach( $tax_terms as $tax_term ) { if ( 'AND' == $terms_search_parameters['radio_terms'] ) { $prefix = 'mlatt' . $tax_index++; } else { $prefix = 'mlatt0'; $tax_index = 1; // only one JOIN needed for the "Any Term" case } $tax_clause .= sprintf( '%1$s %2$s.term_taxonomy_id IN (%3$s)', $inner_connector, $prefix, implode( ',', $tax_term ) ); $inner_connector = ' OR'; } // foreach tax_term $terms_connector = ' ) ' . $terms_search_parameters['radio_terms'] . ' ('; } // tax_terms present } // foreach term if ( 1 < count( $terms ) && ! empty( $tax_clause ) ) { $tax_clause .= ')'; } if ( empty( $tax_clause ) ) { $tax_clause = '1=0'; $tax_index = 0; }; //error_log( __LINE__ . " MLAQuery::_generate_tax_clause( {$tax_index} ) tax_clause = " . var_export( $tax_clause, true ), 0 ); return $tax_index; } /** * Adds a keyword search to the WHERE clause, if required * * Defined as public because it's a filter. * * @since 0.60 * * @param string query clause before modification * * @return string query clause after keyword search addition */ public static function mla_query_posts_search_filter( $search_string ) { global $wpdb; $numeric_clause = ''; $search_clause = ''; $tax_clause = ''; $tax_connector = 'AND'; $tax_index = 0; //error_log( __LINE__ . " MLAQuery::mla_query_posts_search_filter search_string = " . var_export( $search_string, true ), 0 ); //error_log( __LINE__ . " MLAQuery::mla_query_posts_search_filter search_parameters = " . var_export( self::$search_parameters, true ), 0 ); // Process the Terms Search arguments, if present. if ( isset( self::$search_parameters['mla_terms_search']['phrases'] ) ) { self::$search_parameters['tax_terms_count'] = self::_generate_tax_clause( self::$search_parameters['mla_terms_search'], $tax_clause ); //error_log( __LINE__ . " MLAQuery::mla_query_posts_search_filter tax_clause = " . var_export( $tax_clause, true ), 0 ); if ( '1=0' === $tax_clause && !empty( self::$search_parameters['mla_terms_search']['exclude'] ) ) { $tax_clause = ''; } } // Process the keyword search argument, if present. if ( ! empty( self::$search_parameters['s'] ) ) { // WordPress v3.7 says: there are no line breaks in fields $keyword_string = stripslashes( str_replace( array( "\r", "\n" ), '', self::$search_parameters['s'] ) ); $is_wildcard_search = self::_wildcard_search_string( $keyword_string ); if ( $is_wildcard_search || self::$search_parameters['sentence'] || self::$search_parameters['exact'] ) { $keyword_array = array( $keyword_string ); } else { // v3.6.1 was '/".*?("|$)|((?<=[\r\n\t ",+])|^)[^\r\n\t ",+]+/' preg_match_all('/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $keyword_string, $matches); $keyword_array = array_map( 'MLAQuery::mla_search_terms_tidy', $matches[0]); $numeric_array = array_filter( $keyword_array, 'is_numeric' ); //error_log( __LINE__ . " MLAQuery::mla_query_posts_search_filter keyword_array = " . var_export( $keyword_array, true ), 0 ); /* * If all the "keywords" are numeric, interpret it/them as the ID(s) of a specific attachment * or the ID(s) of a parent post/page; add it/them to the regular text-based search. */ if ( count( $keyword_array ) && count( $keyword_array ) == count( $numeric_array ) ) { $numeric_array = implode( ',', $numeric_array ); $numeric_clause = '( ( ' . $wpdb->posts . '.ID IN (' . $numeric_array . ') ) OR ( ' . $wpdb->posts . '.post_parent IN (' . $numeric_array . ') ) ) OR '; } } $fields = self::$search_parameters['mla_search_fields']; $allow_terms_search = in_array( 'terms', $fields ) && ( ! $is_wildcard_search ); $percent = self::$search_parameters['exact'] ? '' : '%'; $connector = ''; if ( empty( $fields ) ) { $search_clause = '1=0'; } else { foreach ( $keyword_array as $phrase ) { if ( $is_wildcard_search ) { // Escape any % in the source string if ( self::$wp_4dot0_plus ) { $sql_phrase = $wpdb->esc_like( $phrase ); $sql_phrase = $wpdb->prepare( '%s', $sql_phrase ); } else { $sql_phrase = "'" . esc_sql( like_escape( $phrase ) ) . "'"; } // Convert wildcard * to SQL % $sql_phrase = str_replace( '*', '%', $sql_phrase ); } else { if ( self::$wp_4dot0_plus ) { $sql_phrase = $percent . $wpdb->esc_like( $phrase ) . $percent; $sql_phrase = $wpdb->prepare( '%s', $sql_phrase ); } else { $sql_phrase = "'" . $percent . esc_sql( like_escape( $phrase ) ) . $percent . "'"; } } $inner_connector = ''; $inner_clause = ''; if ( in_array( 'content', $fields ) ) { $inner_clause .= "{$inner_connector}({$wpdb->posts}.post_content LIKE {$sql_phrase})"; $inner_connector = ' OR '; } if ( in_array( 'title', $fields ) ) { $inner_clause .= "{$inner_connector}({$wpdb->posts}.post_title LIKE {$sql_phrase})"; $inner_connector = ' OR '; } if ( in_array( 'excerpt', $fields ) ) { $inner_clause .= "{$inner_connector}({$wpdb->posts}.post_excerpt LIKE {$sql_phrase})"; $inner_connector = ' OR '; } if ( in_array( 'alt-text', $fields ) ) { $view_name = self::MLA_ALT_TEXT_SUBQUERY; $inner_clause .= "{$inner_connector}({$view_name}.meta_value LIKE {$sql_phrase})"; $inner_connector = ' OR '; } if ( in_array( 'file', $fields ) ) { $view_name = self::MLA_FILE_SUBQUERY; $inner_clause .= "{$inner_connector}({$view_name}.meta_value LIKE {$sql_phrase})"; $inner_connector = ' OR '; } if ( in_array( 'name', $fields ) ) { $inner_clause .= "{$inner_connector}({$wpdb->posts}.post_name LIKE {$sql_phrase})"; } $inner_clause = apply_filters( 'mla_list_table_search_filter_inner_clause', $inner_clause, $inner_connector, $wpdb->posts, $sql_phrase ); if ( ! empty($inner_clause) ) { $search_clause .= "{$connector}({$inner_clause})"; $connector = ' ' . self::$search_parameters['mla_search_connector'] . ' '; } } // foreach phrase if ( $allow_terms_search ) { self::$search_parameters['tax_terms_count'] = self::_generate_tax_clause( array( 'phrases' => $keyword_string, 'radio_phrases' => self::$search_parameters['mla_search_connector'], 'radio_terms' => self::$search_parameters['mla_search_connector'], 'taxonomies' => self::$search_parameters['mla_search_taxonomies'] ), $tax_clause ); //error_log( __LINE__ . " MLAQuery::mla_query_posts_search_filter tax_clause = " . var_export( $tax_clause, true ), 0 ); if ( '1=0' === $tax_clause ) { // If "Terms" is the only field and no terms are present, the search must fail. if ( ( 1 < count( $fields ) ) || ( 'terms' !== array_shift( $fields ) ) ) { $tax_clause = ''; } } else { $tax_connector = 'OR'; } // tax_terms present } // terms in fields } // fields not empty } // isset 's' if ( ! empty( $tax_clause ) && ! empty( $search_clause ) ) { $tax_clause = " {$tax_connector} ({$tax_clause} )"; } if ( ! empty( $search_clause ) || ! empty( $tax_clause ) ) { $search_clause = " AND ( {$numeric_clause}{$search_clause}{$tax_clause} ) "; if ( ! is_user_logged_in() ) { $search_clause .= " AND ( {$wpdb->posts}.post_password = '' ) "; } } if ( 'none' != self::$search_parameters['debug'] ) { $debug_array['search_string'] = $search_string; $debug_array['search_parameters'] = self::$search_parameters; $debug_array['search_clause'] = $search_clause; if ( 'shortcode' == self::$search_parameters['debug'] ) { MLACore::mla_debug_add( 'mla_debug posts_search filter = ' . var_export( $debug_array, true ) ); } else { /* translators: 1: DEBUG tag 2: search filter details */ MLACore::mla_debug_add( sprintf( _x( '%1$s: mla_query_posts_search_filter = "%2$s".', 'error_log', 'media-library-assistant' ), __( 'DEBUG', 'media-library-assistant' ), var_export( $debug_array, true ) ) ); } } // debug // Remove posts containing "negative" search phrases $excludes = array(); if ( !empty( self::$search_parameters['exclude'] ) ) { $excludes[] = self::$search_parameters['exclude']; } if ( !empty( self::$search_parameters['mla_terms_search']['exclude'] ) ) { $excludes[] = self::$search_parameters['mla_terms_search']['exclude']; } if ( count( $excludes ) ) { $search_clause .= " AND ( {$wpdb->posts}.ID NOT IN ( " . implode( ',', $excludes ) . " ) )"; } //error_log( __LINE__ . " MLAQuery::mla_query_posts_search_filter search_clause = " . var_export( $search_clause, true ), 0 ); return $search_clause; } /** * Adds/modifies the WHERE clause for meta values, LIKE patterns and detached items * * Modeled after _edit_attachments_query_helper in wp-admin/post.php. * Defined as public because it's a filter. * * @since 0.1 * * @param string query clause before modification * * @return string query clause after modification */ public static function mla_query_posts_where_filter( $where_clause ) { global $wpdb; if ( isset( self::$query_parameters['debug'] ) ) { $debug_array = array( 'where_string' => $where_clause ); } // WordPress filters meta_value thru trim() - which we must reverse if ( isset( self::$query_parameters['mla-metavalue'] ) ) { if ( is_array( self::$query_parameters['mla-metavalue'] ) ) { foreach ( self::$query_parameters['mla-metavalue'] as $pattern => $replacement ) { $where_clause = preg_replace( '/(^.*meta_value AS CHAR\) = \')(' . $pattern . '[^\']*)/m', '${1}' . $replacement, $where_clause ); } } else { $where_clause = preg_replace( '/(^.*meta_value AS CHAR\) = \')([^\']*)/m', '${1}' . self::$query_parameters['mla-metavalue'], $where_clause ); } } // Matching a NULL meta value if ( array_key_exists( 'postmeta_value', self::$query_parameters ) && NULL == self::$query_parameters['postmeta_value'] ) { $where_clause .= ' AND ' . self::MLA_TABLE_VIEW_SUBQUERY . '.meta_value IS NULL'; } // WordPress modifies the LIKE clause - which we must reverse if ( isset( self::$query_parameters['patterns'] ) ) { foreach ( self::$query_parameters['patterns'] as $pattern ) { $pattern = str_replace( '_', '\\\\_', $pattern ); $match_clause = '%' . str_replace( '%', '\\\\%', $pattern ) . '%'; $where_clause = str_replace( "LIKE '{$match_clause}'", "LIKE '{$pattern}'", $where_clause ); } } // Unattached items require some help if ( isset( self::$query_parameters['detached'] ) ) { if ( '1' == self::$query_parameters['detached'] ) { $where_clause .= sprintf( ' AND %1$s.post_parent < 1', $wpdb->posts ); } elseif ( '0' == self::$query_parameters['detached'] ) { $where_clause .= sprintf( ' AND %1$s.post_parent > 0', $wpdb->posts ); } } if ( isset( self::$query_parameters['debug'] ) ) { $debug_array['where_clause'] = $where_clause; /* translators: 1: DEBUG tag 2: where filter details */ MLACore::mla_debug_add( sprintf( _x( '%1$s: mla_query_posts_where_filter = "%2$s".', 'error_log', 'media-library-assistant' ), __( 'DEBUG', 'media-library-assistant' ), var_export( $debug_array, true ) ) ); } // debug return $where_clause; } /** * Adds a JOIN clause, if required, to handle sorting/searching on custom fields or ALT Text * * Defined as public because it's a filter. * * @since 0.30 * * @param string query clause before modification * * @return string query clause after "LEFT JOIN view ON post_id" item modification */ public static function mla_query_posts_join_filter( $join_clause ) { global $wpdb; if ( isset( self::$query_parameters['debug'] ) ) { $debug_array = array( 'join_string' => $join_clause ); } /* * ALT Text searches, File Name searches, custom field Table Views and custom field * sorts are special; we have to use a subquery to build an intermediate table and * modify the JOIN to include posts with no value for the metadata field. * Four clauses are used because all four conditions can be present at once. */ if ( self::$query_parameters[self::MLA_ALT_TEXT_SUBQUERY] ) { $sub_query = sprintf( 'SELECT post_id, meta_value FROM %1$s WHERE %1$s.meta_key = \'%2$s\'', $wpdb->postmeta, '_wp_attachment_image_alt' ); $join_clause .= sprintf( ' LEFT JOIN ( %1$s ) %2$s ON (%3$s.ID = %2$s.post_id)', $sub_query, self::MLA_ALT_TEXT_SUBQUERY, $wpdb->posts ); } if ( self::$query_parameters[self::MLA_FILE_SUBQUERY] ) { $sub_query = sprintf( 'SELECT post_id, meta_value FROM %1$s WHERE %1$s.meta_key = \'%2$s\'', $wpdb->postmeta, '_wp_attached_file' ); $join_clause .= sprintf( ' LEFT JOIN ( %1$s ) %2$s ON (%3$s.ID = %2$s.post_id)', $sub_query, self::MLA_FILE_SUBQUERY, $wpdb->posts ); } if ( self::$query_parameters[self::MLA_TABLE_VIEW_SUBQUERY] ) { $sub_query = sprintf( 'SELECT post_id, meta_value FROM %1$s WHERE %1$s.meta_key = \'%2$s\'', $wpdb->postmeta, self::$query_parameters['postmeta_key'] ); $join_clause .= sprintf( ' LEFT JOIN ( %1$s ) %2$s ON (%3$s.ID = %2$s.post_id)', $sub_query, self::MLA_TABLE_VIEW_SUBQUERY, $wpdb->posts ); } if ( self::$query_parameters[self::MLA_ORDERBY_SUBQUERY] ) { $sub_query = sprintf( 'SELECT post_id, meta_value FROM %1$s WHERE %1$s.meta_key = \'%2$s\'', $wpdb->postmeta, self::$query_parameters['orderby_key'] ); $join_clause .= sprintf( ' LEFT JOIN ( %1$s ) %2$s ON (%3$s.ID = %2$s.post_id)', $sub_query, self::MLA_ORDERBY_SUBQUERY, $wpdb->posts ); } if ( isset( self::$query_parameters['orderby'] ) ) { if ( ( 'c_' == substr( self::$query_parameters['orderby'], 0, 2 ) ) || ( '_wp_attachment_image_alt' == self::$query_parameters['orderby'] ) ) { $orderby = self::MLA_ORDERBY_SUBQUERY . '.meta_value'; } } if ( isset( self::$search_parameters['tax_terms_count'] ) && ( 0 < self::$search_parameters['tax_terms_count'] ) ) { $tax_index = 0; $tax_clause = ''; while ( $tax_index < self::$search_parameters['tax_terms_count'] ) { $prefix = 'mlatt' . $tax_index++; $tax_clause .= sprintf( ' LEFT JOIN %1$s AS %2$s ON (%3$s.ID = %2$s.object_id)', $wpdb->term_relationships, $prefix, $wpdb->posts ); } $join_clause .= $tax_clause; } if ( isset( self::$query_parameters['debug'] ) ) { $debug_array['join_clause'] = $join_clause; /* translators: 1: DEBUG tag 2: join filter details */ MLACore::mla_debug_add( sprintf( _x( '%1$s: mla_query_posts_join_filter = "%2$s".', 'error_log', 'media-library-assistant' ), __( 'DEBUG', 'media-library-assistant' ), var_export( $debug_array, true ) ) ); } // debug return $join_clause; } /** * Adds a GROUPBY clause, if required * * Taxonomy text queries and postmeta queries can return multiple results for the same ID. * Defined as public because it's a filter. * * @since 1.90 * * @param string query clause before modification * * @return string updated query clause */ public static function mla_query_posts_groupby_filter( $groupby_clause ) { global $wpdb; if ( ( ! empty( self::$query_parameters[self::MLA_TABLE_VIEW_SUBQUERY] ) ) || ( ! empty( self::$query_parameters[self::MLA_ALT_TEXT_SUBQUERY] ) ) || ( ! empty( self::$query_parameters[self::MLA_FILE_SUBQUERY] ) ) || ( ! empty( self::$query_parameters[self::MLA_ORDERBY_SUBQUERY] ) ) || isset( self::$search_parameters['tax_terms_count'] ) ) { $groupby_clause = "{$wpdb->posts}.ID"; } return $groupby_clause; } /** * Adds a ORDERBY clause, if required * * Expands the range of sort options because the logic in WP_Query is limited. * Defined as public because it's a filter. * * @since 0.30 * * @param string query clause before modification * * @return string updated query clause */ public static function mla_query_posts_orderby_filter( $orderby_clause ) { global $wpdb; if ( isset( self::$query_parameters['debug'] ) ) { $debug_array = array( 'orderby_string' => $orderby_clause ); } if ( isset( self::$query_parameters['orderby'] ) ) { if ( 'c_' == substr( self::$query_parameters['orderby'], 0, 2 ) ) { $orderby = self::MLA_ORDERBY_SUBQUERY . '.meta_value'; } /* custom field sort */ else { switch ( self::$query_parameters['orderby'] ) { case 'none': $orderby = ''; $orderby_clause = ''; break; /* * post__in is passed from Media Manager Modal Window */ case 'post__in': return $orderby_clause; /* * There are two columns defined that end up sorting on post_title, * so we can't use the database column to identify the column but * we actually sort on the database column. */ case 'title_name': $orderby = $wpdb->posts . '.post_title'; break; /* * The _wp_attached_file meta data value is present for all attachments, and the * sorting on the meta data value is handled by WP_Query */ case '_wp_attached_file': $orderby = ''; break; /* * The _wp_attachment_image_alt value is only present for images, so we have to * use the view we prepared to get attachments with no meta data value */ case '_wp_attachment_image_alt': $orderby = self::MLA_ORDERBY_SUBQUERY . '.meta_value'; break; default: $orderby = $wpdb->posts . '.' . self::$query_parameters['orderby']; } // $query_parameters['orderby'] } if ( ! empty( $orderby ) ) { $orderby_clause = $orderby . ' ' . self::$query_parameters['order']; } } // isset if ( isset( self::$query_parameters['debug'] ) ) { $debug_array['orderby_clause'] = $orderby_clause; /* translators: 1: DEBUG tag 2: orderby details details */ MLACore::mla_debug_add( sprintf( _x( '%1$s: mla_query_posts_orderby_filter = "%2$s".', 'error_log', 'media-library-assistant' ), __( 'DEBUG', 'media-library-assistant' ), var_export( $debug_array, true ) ) ); } // debug return $orderby_clause; } /** * Disable Relevanssi - A Better Search, v3.2 by Mikko Saari * Defined as public because it's a filter. * * @since 1.80 * * @param boolean Default setting * * @return boolean Updated setting */ public static function mla_query_relevanssi_admin_search_ok_filter( $admin_search_ok ) { return false; } /** * Disable Relevanssi - A Better Search, v3.2 by Mikko Saari * Defined as public because it's a filter. * * @since 2.25 * * @param boolean Default setting * * @return boolean Updated setting */ public static function mla_query_relevanssi_prevent_default_request_filter( $prevent ) { return false; } /** * Filters all clauses for get_terms queries * * Defined as public because it's a filter. * * @since 2.13 * * @param array $pieces Terms query SQL clauses. * @param array $taxonomies An array of taxonomies. * @param array $args An array of terms query arguments. */ public static function mla_query_terms_clauses_filter( $pieces, $taxonomies, $args ) { global $wpdb; if ( empty( $args['name__like'] ) ) { return $pieces; } $term = $args['name__like']; /* * Escape any % in the source string */ if ( self::$wp_4dot0_plus ) { $sql_term = $wpdb->esc_like( $term ); $sql_term = $wpdb->prepare( '%s', $sql_term ); } else { $sql_term = "'" . esc_sql( like_escape( $term ) ) . "'"; } /* * Convert wildcard * to SQL % */ $sql_term = str_replace( '*', '%', $sql_term ); /* * Replace the LIKE pattern in the WHERE clause */ $match_clause = '%' . str_replace( '%', '\\\\%', $term ) . '%'; $pieces['where'] = str_replace( "LIKE '{$match_clause}'", "LIKE {$sql_term}", $pieces['where'] ); return $pieces; } /** * Filters all clauses for shortcode queries, pre 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_filter( $pieces ) { /* translators: 1: DEBUG tag 2: SQL clauses */ MLACore::mla_debug_add( sprintf( _x( '%1$s: mla_query_posts_clauses_filter = "%2$s".', 'error_log', 'media-library-assistant' ), __( 'DEBUG', 'media-library-assistant' ), var_export( $pieces, true ) ) ); return $pieces; } /** * 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 */ MLACore::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; } } // class MLAQuery ?>