1834 lines
56 KiB
PHP
1834 lines
56 KiB
PHP
<?php
|
|
/**
|
|
* /premium/indexing.php
|
|
*
|
|
* @package Relevanssi_Premium
|
|
* @author Mikko Saari
|
|
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
|
* @see https://www.relevanssi.com/
|
|
*/
|
|
|
|
/**
|
|
* Indexes user profiles when profile updates.
|
|
*
|
|
* @param object|int $user User object or user ID.
|
|
*/
|
|
function relevanssi_profile_update( $user ) {
|
|
if ( 'on' === get_option( 'relevanssi_index_users' ) ) {
|
|
if ( is_integer( $user ) ) {
|
|
$user = get_user_by( 'id', $user );
|
|
}
|
|
/**
|
|
* Checks if the user can be indexed.
|
|
*
|
|
* @param boolean $index Should the user be indexed, default true.
|
|
* @param object $user The user object.
|
|
*
|
|
* @return boolean $index If false, do not index the user.
|
|
*/
|
|
$index_this_user = apply_filters( 'relevanssi_user_index_ok', true, $user );
|
|
if ( $index_this_user ) {
|
|
$update = true;
|
|
relevanssi_index_user( $user, $update );
|
|
} else {
|
|
relevanssi_delete_user( $user->ID );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Indexes taxonomy terms when term is updated.
|
|
*
|
|
* @param string $term The term.
|
|
* @param int $taxonomy_term_id The term taxonomy ID (not used here).
|
|
* @param string $taxonomy The taxonomy.
|
|
*/
|
|
function relevanssi_edit_term( $term, $taxonomy_term_id, $taxonomy ) {
|
|
$update = true;
|
|
relevanssi_do_term_indexing( $term, $taxonomy, $update );
|
|
}
|
|
|
|
/**
|
|
* Indexes taxonomy terms when term is added.
|
|
*
|
|
* @param string $term The term.
|
|
* @param int $taxonomy_term_id The term taxonomy ID (not used here).
|
|
* @param string $taxonomy The taxonomy.
|
|
*/
|
|
function relevanssi_add_term( $term, $taxonomy_term_id, $taxonomy ) {
|
|
$update = false;
|
|
relevanssi_do_term_indexing( $term, $taxonomy, $update );
|
|
}
|
|
|
|
/**
|
|
* Indexes taxonomy term, if taxonomy term indexing is enabled.
|
|
*
|
|
* @param string $term The term.
|
|
* @param string $taxonomy The taxonomy.
|
|
* @param boolean $update If true, term is updated; if false, it is added.
|
|
*/
|
|
function relevanssi_do_term_indexing( $term, $taxonomy, $update ) {
|
|
if ( 'on' === get_option( 'relevanssi_index_taxonomies' ) ) {
|
|
$taxonomies = get_option( 'relevanssi_index_terms' );
|
|
if ( in_array( $taxonomy, $taxonomies, true ) ) {
|
|
relevanssi_index_taxonomy_term( $term, $taxonomy, $update );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes an user from Relevanssi index.
|
|
*
|
|
* Deletes an user from the Relevanssi index. Attached to the 'delete_user' action.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param int $user User ID to delete.
|
|
*/
|
|
function relevanssi_delete_user( int $user ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
$user = intval( $user );
|
|
$wpdb->query( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE item = $user AND type = 'user'" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
}
|
|
|
|
/**
|
|
* Deletes a taxonomy term from Relevanssi index.
|
|
*
|
|
* Deletes a taxonomy term from the Relevanssi index. Attached to the 'delete_term' action.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param int $term Term ID to remove.
|
|
* @param int $term_taxonomy_id Term taxonomy ID (not used).
|
|
* @param string $taxonomy The taxonomy.
|
|
*/
|
|
function relevanssi_delete_taxonomy_term( $term, $term_taxonomy_id, $taxonomy ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
$wpdb->query(
|
|
$wpdb->prepare(
|
|
'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE item = %d AND type = %s', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
$term,
|
|
$taxonomy
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Generates the custom field detail field for indexing.
|
|
*
|
|
* Premium stores more detail about custom field indexing. This function
|
|
* generates the custom field detail.
|
|
*
|
|
* @param array $insert_data Data used to generate the INSERT queries.
|
|
* @param string $token The indexed token.
|
|
* @param int $count The number of matches.
|
|
* @param string $field Name of the custom field.
|
|
*
|
|
* @return array $insert_data New source data for the INSERT queries added.
|
|
*/
|
|
function relevanssi_customfield_detail( $insert_data, $token, $count, $field ) {
|
|
if ( isset( $insert_data[ $token ]['customfield_detail'] ) ) {
|
|
// Custom field detail for this token already exists.
|
|
$custom_field_detail = json_decode( $insert_data[ $token ]['customfield_detail'], true );
|
|
} else {
|
|
// Nothing yet, create new.
|
|
$custom_field_detail = array();
|
|
}
|
|
|
|
relevanssi_increase_value( $custom_field_detail[ $field ], $count );
|
|
|
|
$insert_data[ $token ]['customfield_detail'] = wp_json_encode( $custom_field_detail );
|
|
return $insert_data;
|
|
}
|
|
|
|
/**
|
|
* Indexes custom MySQL column content.
|
|
*
|
|
* Generates the INSERT query base data for MySQL column content.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
*
|
|
* @param array $insert_data Data used to generate the INSERT queries.
|
|
* @param string $post_id Post ID.
|
|
*
|
|
* @return array $insert_data New source data for the INSERT queries added.
|
|
*/
|
|
function relevanssi_index_mysql_columns( $insert_data, $post_id ) {
|
|
$custom_columns = get_option( 'relevanssi_mysql_columns' );
|
|
if ( ! empty( $custom_columns ) ) {
|
|
global $wpdb;
|
|
|
|
// Get a list of possible column names.
|
|
$column_list = wp_cache_get( 'relevanssi_column_list' );
|
|
if ( false === $column_list ) {
|
|
$column_list = $wpdb->get_results( "SHOW COLUMNS FROM $wpdb->posts" );
|
|
wp_cache_set( 'relevanssi_column_list', $column_list );
|
|
}
|
|
$valid_columns = array();
|
|
foreach ( $column_list as $column ) {
|
|
array_push( $valid_columns, $column->Field ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
|
|
}
|
|
|
|
// This is to remove problems where the list ends in a comma.
|
|
$custom_column_array = explode( ',', $custom_columns );
|
|
$custom_column_list_array = array();
|
|
foreach ( $custom_column_array as $column ) {
|
|
$column = trim( $column );
|
|
if ( in_array( $column, $valid_columns, true ) ) {
|
|
$custom_column_list_array[] = $column;
|
|
}
|
|
}
|
|
$custom_column_list = implode( ', ', $custom_column_list_array );
|
|
|
|
$custom_column_data = $wpdb->get_row( "SELECT $custom_column_list FROM $wpdb->posts WHERE ID=$post_id", ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
$remove_stopwords = true;
|
|
$minimum_word_length = get_option( 'relevanssi_min_word_length', 3 );
|
|
if ( is_array( $custom_column_data ) ) {
|
|
foreach ( $custom_column_data as $column => $data ) {
|
|
/** This filter is documented in common/indexing.php */
|
|
$data = apply_filters(
|
|
'relevanssi_indexing_tokens',
|
|
relevanssi_tokenize( $data, $remove_stopwords, $minimum_word_length, 'indexing' ),
|
|
'mysql-content'
|
|
);
|
|
if ( count( $data ) > 0 ) {
|
|
foreach ( $data as $term => $count ) {
|
|
if ( isset( $insert_data[ $term ]['mysqlcolumn'] ) ) {
|
|
$insert_data[ $term ]['mysqlcolumn'] += $count;
|
|
} else {
|
|
$insert_data[ $term ]['mysqlcolumn'] = $count;
|
|
}
|
|
$insert_data = relevanssi_mysqlcolumn_detail( $insert_data, $term, $count, $column );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $insert_data;
|
|
}
|
|
|
|
/**
|
|
* Generates the MySQL column detail field for indexing.
|
|
*
|
|
* This function generates the MySQL column detail.
|
|
*
|
|
* @param array $insert_data Data used to generate the INSERT queries.
|
|
* @param string $token The indexed token.
|
|
* @param int $count The number of matches.
|
|
* @param string $column Name of the column.
|
|
*
|
|
* @return array $insert_data New source data for the INSERT queries added.
|
|
*/
|
|
function relevanssi_mysqlcolumn_detail( $insert_data, $token, $count, $column ) {
|
|
if ( isset( $insert_data[ $token ]['mysqlcolumn_detail'] ) ) {
|
|
// Custom field detail for this token already exists.
|
|
$mysqlcolumn_detail = json_decode( $insert_data[ $token ]['mysqlcolumn_detail'], true );
|
|
} else {
|
|
// Nothing yet, create new.
|
|
$mysqlcolumn_detail = array();
|
|
}
|
|
|
|
relevanssi_increase_value( $mysqlcolumn_detail[ $column ], $count );
|
|
|
|
$insert_data[ $token ]['mysqlcolumn_detail'] = wp_json_encode( $mysqlcolumn_detail );
|
|
|
|
return $insert_data;
|
|
}
|
|
|
|
/**
|
|
* Processes internal links.
|
|
*
|
|
* Process the internal links the way user wants: no indexing, indexing, or stripping.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param string $contents Post content.
|
|
* @param int $post_id Post ID.
|
|
*
|
|
* @return string $contents Contents, modified.
|
|
*/
|
|
function relevanssi_process_internal_links( $contents, $post_id ) {
|
|
$internal_links_behaviour = get_option( 'relevanssi_internal_links', 'noindex' );
|
|
|
|
if ( 'noindex' !== $internal_links_behaviour ) {
|
|
global $relevanssi_variables, $wpdb;
|
|
$min_word_length = get_option( 'relevanssi_min_word_length', 3 );
|
|
|
|
// Index internal links.
|
|
$internal_links = relevanssi_get_internal_links( $contents );
|
|
|
|
if ( ! empty( $internal_links ) ) {
|
|
foreach ( $internal_links as $link => $text ) {
|
|
$link_id = url_to_postid( $link );
|
|
if ( ! empty( $link_id ) ) {
|
|
/** This filter is documented in common/indexing.php */
|
|
$link_words = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $text, true, $min_word_length, 'indexing' ), 'internal-links' );
|
|
if ( count( $link_words ) > 0 ) {
|
|
foreach ( $link_words as $word => $count ) {
|
|
$wpdb->query(
|
|
$wpdb->prepare(
|
|
'INSERT IGNORE INTO ' . $relevanssi_variables['relevanssi_table'] . ' (doc, term, term_reverse, link, item) VALUES (%d, %s, REVERSE(%s), %d, %d)', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
$link_id,
|
|
$word,
|
|
$word,
|
|
$count,
|
|
$post_id
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( 'strip' === $internal_links_behaviour ) {
|
|
$contents = relevanssi_strip_internal_links( $contents );
|
|
}
|
|
}
|
|
}
|
|
|
|
return $contents;
|
|
}
|
|
|
|
/**
|
|
* Finds internal links.
|
|
*
|
|
* A function to find all internal links in the parameter text.
|
|
*
|
|
* @param string $text Text where the links are extracted from.
|
|
*
|
|
* @return array $links All links in the post, or false if fails.
|
|
*/
|
|
function relevanssi_get_internal_links( $text ) {
|
|
$links = array();
|
|
if ( preg_match_all( '@<a[^>]*?href="(' . home_url() . '[^"]*?)"[^>]*?>(.*?)</a>@siu', $text, $m ) ) {
|
|
foreach ( $m[1] as $i => $link ) {
|
|
if ( ! isset( $links[ $link ] ) ) {
|
|
$links[ $link ] = '';
|
|
}
|
|
$links[ $link ] .= ' ' . $m[2][ $i ];
|
|
}
|
|
}
|
|
if ( preg_match_all( '@<a[^>]*?href="(/[^"]*?)"[^>]*?>(.*?)</a>@siu', $text, $m ) ) {
|
|
foreach ( $m[1] as $i => $link ) {
|
|
if ( ! isset( $links[ $link ] ) ) {
|
|
$links[ $link ] = '';
|
|
}
|
|
$links[ $link ] .= ' ' . $m[2][ $i ];
|
|
}
|
|
}
|
|
if ( count( $links ) > 0 ) {
|
|
return $links;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Strips internal links.
|
|
*
|
|
* A function to strip all internal links from the parameter text.
|
|
*
|
|
* @param string $text Text where the links are extracted from.
|
|
*
|
|
* @return array $links The text without the links.
|
|
*/
|
|
function relevanssi_strip_internal_links( $text ) {
|
|
$text = preg_replace(
|
|
array(
|
|
'@<a[^>]*?href="' . home_url() . '[^>]*?>.*?</a>@siu',
|
|
),
|
|
' ',
|
|
$text
|
|
);
|
|
$text = preg_replace(
|
|
array(
|
|
'@<a[^>]*?href="/[^>]*?>.*?</a>@siu',
|
|
),
|
|
' ',
|
|
$text
|
|
);
|
|
return $text;
|
|
}
|
|
|
|
/**
|
|
* Applies the thousands separator rule to text.
|
|
*
|
|
* Finds numbers separated by the chosen thousand separator and combine them.
|
|
*
|
|
* @param string $str The string to fix.
|
|
*
|
|
* @return string $str The fixed string.
|
|
*/
|
|
function relevanssi_apply_thousands_separator( $str ) {
|
|
$thousands_separator = get_option( 'relevanssi_thousand_separator', '' );
|
|
if ( ! empty( $thousands_separator ) ) {
|
|
$pattern = '/(\d+)' . preg_quote( $thousands_separator, '/' ) . '(\d+)/u';
|
|
$str = preg_replace( $pattern, '$1$2', $str );
|
|
}
|
|
return $str;
|
|
}
|
|
|
|
/**
|
|
* Adds a stemmer-enabling filter.
|
|
*
|
|
* This filter introduces a new filter hook that runs the stemmers.
|
|
*
|
|
* @param string $str The string that is stemmed.
|
|
*
|
|
* @return string $str The string after stemming.
|
|
*/
|
|
function relevanssi_enable_stemmer( $str ) {
|
|
add_filter( 'pre_option_relevanssi_implicit_operator', 'relevanssi_return_or' );
|
|
/**
|
|
* Applies stemmer to document content and search terms.
|
|
*
|
|
* @param string $str The string that is stemmed.
|
|
*
|
|
* @return string $str The string after stemming.
|
|
*/
|
|
$str = apply_filters( 'relevanssi_stemmer', $str );
|
|
remove_filter( 'pre_option_relevanssi_implicit_operator', 'relevanssi_return_or' );
|
|
return $str;
|
|
}
|
|
|
|
/**
|
|
* Does simple English stemming.
|
|
*
|
|
* A simple suffix stripper that can be used to stem English texts.
|
|
*
|
|
* @param string $term Search term to stem.
|
|
*
|
|
* @return string $term The stemmed term.
|
|
*/
|
|
function relevanssi_simple_english_stemmer( $term ) {
|
|
$len = strlen( $term );
|
|
|
|
$end1 = substr( $term, -1, 1 );
|
|
if ( 's' === $end1 && $len > 3 ) {
|
|
$term = substr( $term, 0, -1 );
|
|
--$len;
|
|
}
|
|
$end = substr( $term, -3, 3 );
|
|
|
|
if ( 'ing' === $end && $len > 5 ) {
|
|
return substr( $term, 0, -3 );
|
|
}
|
|
if ( 'est' === $end && $len > 5 ) {
|
|
return substr( $term, 0, -3 );
|
|
}
|
|
|
|
$end = substr( $end, 1 );
|
|
if ( 'es' === $end && $len > 3 ) {
|
|
return substr( $term, 0, -2 );
|
|
}
|
|
if ( 'ie' === $end && $len > 3 ) {
|
|
return substr( $term, 0, -1 );
|
|
}
|
|
if ( 'ed' === $end && $len > 3 ) {
|
|
return substr( $term, 0, -2 );
|
|
}
|
|
if ( 'en' === $end && $len > 3 ) {
|
|
return substr( $term, 0, -2 );
|
|
}
|
|
if ( 'er' === $end && $len > 3 ) {
|
|
return substr( $term, 0, -2 );
|
|
}
|
|
if ( 'ly' === $end && $len > 4 ) {
|
|
return substr( $term, 0, -2 );
|
|
}
|
|
|
|
$end = substr( $end, -1 );
|
|
if ( 'y' === $end && $len > 3 ) {
|
|
return substr( $term, 0, -1 ) . 'i';
|
|
}
|
|
|
|
return $term;
|
|
}
|
|
|
|
/**
|
|
* Creates the synonym replacement array.
|
|
*
|
|
* A helper function that generates a synonym replacement array. The array
|
|
* is then stored in a global variable, so that it only needs to generated
|
|
* once per running the script.
|
|
*
|
|
* @global $relevanssi_variables The global Relevanssi variables, used to
|
|
* store the synonym database.
|
|
*/
|
|
function relevanssi_create_synonym_replacement_array() {
|
|
global $relevanssi_variables;
|
|
|
|
$synonym_data = get_option( 'relevanssi_synonyms' );
|
|
$current_language = relevanssi_get_current_language();
|
|
$synonyms = array();
|
|
|
|
if ( isset( $synonym_data[ $current_language ] ) ) {
|
|
$synonym_data = relevanssi_strtolower( $synonym_data[ $current_language ] );
|
|
$pairs = explode( ';', $synonym_data );
|
|
|
|
foreach ( $pairs as $pair ) {
|
|
if ( empty( $pair ) ) {
|
|
continue;
|
|
}
|
|
$parts = explode( '=', $pair );
|
|
$key = strval( trim( $parts[0] ) );
|
|
$value = trim( $parts[1] );
|
|
if ( ! isset( $synonyms[ $value ] ) ) {
|
|
$synonyms[ $value ] = "$value $key";
|
|
} else {
|
|
$synonyms[ $value ] .= " $key";
|
|
}
|
|
}
|
|
}
|
|
$relevanssi_variables['synonyms'] = $synonyms;
|
|
}
|
|
|
|
/**
|
|
* Adds synonyms to post content and titles for indexing.
|
|
*
|
|
* In order to use synonyms in AND searches, the synonyms must be indexed within the posts.
|
|
* This function adds synonyms for post content and titles when indexing posts.
|
|
*
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the synonym database.
|
|
*
|
|
* @param array $tokens An array of tokens and their frequencies.
|
|
*
|
|
* @return array An array of filtered token-frequency pairs.
|
|
*/
|
|
function relevanssi_add_indexing_synonyms( $tokens ) {
|
|
global $relevanssi_variables;
|
|
|
|
if ( ! isset( $relevanssi_variables['synonyms'] ) ) {
|
|
relevanssi_create_synonym_replacement_array();
|
|
}
|
|
|
|
$new_tokens = array();
|
|
$synonyms = $relevanssi_variables['synonyms'];
|
|
|
|
foreach ( $tokens as $token => $tf ) {
|
|
if ( isset( $synonyms[ $token ] ) ) {
|
|
$token_and_the_synonyms = explode( ' ', $synonyms[ $token ] );
|
|
foreach ( $token_and_the_synonyms as $new_token ) {
|
|
$new_tokens[ $new_token ] = $tf;
|
|
}
|
|
} else {
|
|
$new_tokens[ $token ] = $tf;
|
|
}
|
|
}
|
|
|
|
return $new_tokens;
|
|
}
|
|
|
|
/**
|
|
* Adds synonyms to a content.
|
|
*
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the synonym database.
|
|
*
|
|
* @param string $content The content to add synonyms to.
|
|
*
|
|
* @return string $content The content with synonyms.
|
|
*/
|
|
function relevanssi_prepare_indexing_content( $content ) {
|
|
global $relevanssi_variables;
|
|
|
|
if ( ! isset( $relevanssi_variables['synonyms'] ) ) {
|
|
relevanssi_create_synonym_replacement_array();
|
|
}
|
|
|
|
$synonyms = $relevanssi_variables['synonyms'];
|
|
$content = relevanssi_strtolower( $content );
|
|
$content = preg_split( '/[\s,.()!?]/', $content );
|
|
$ret = array();
|
|
$len = count( $content );
|
|
for ( $i = 0; $i < $len; ++$i ) {
|
|
$val = $content[ $i ];
|
|
if ( 0 === strlen( $val ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( isset( $synonyms[ $val ] ) ) {
|
|
$ret[] = $synonyms[ $val ];
|
|
} else {
|
|
$ret[] = $val;
|
|
}
|
|
}
|
|
|
|
return implode( ' ', $ret );
|
|
}
|
|
|
|
|
|
/**
|
|
* Adds ACF repeater fields to the list of custom fields.
|
|
*
|
|
* Goes through custom fields, finds fields that match the fieldname_%_subfieldname
|
|
* pattern, finds the number of fields from the fieldname custom field and then
|
|
* adds the fieldname_0_subfieldname... fields to the list of custom fields. Only
|
|
* works one level deep.
|
|
*
|
|
* @param array $custom_fields The list of custom fields, used as a reference.
|
|
* @param int $post_id The post ID of the current post.
|
|
*/
|
|
function relevanssi_add_repeater_fields( &$custom_fields, $post_id ) {
|
|
global $wpdb;
|
|
|
|
/**
|
|
* Filters the list of custom fields to index before the repeater fields
|
|
* are expanded. If you want to add repeater fields using the
|
|
* field_%_subfield notation from code, you can use this filter hook.
|
|
*
|
|
* @param array $custom_fields The list of custom fields. This array
|
|
* includes all custom fields that are to be indexed, so make sure you add
|
|
* new fields here and don't remove anything you want included in the index.
|
|
*/
|
|
$custom_fields = apply_filters( 'relevanssi_custom_fields_before_repeaters', $custom_fields );
|
|
$repeater_fields = array();
|
|
foreach ( $custom_fields as $field ) {
|
|
$number_of_levels = substr_count( $field, '%' );
|
|
if ( $number_of_levels > 0 ) {
|
|
$field = str_replace( '\%', '%', $wpdb->esc_like( $field ) );
|
|
$fields = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM $wpdb->postmeta WHERE meta_key LIKE %s AND post_id = %d", $field, $post_id ) );
|
|
|
|
$repeater_fields = array_merge( $repeater_fields, $fields );
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$custom_fields = array_merge( $custom_fields, $repeater_fields );
|
|
}
|
|
|
|
/**
|
|
* Adds the PDF data from child posts to parent posts.
|
|
*
|
|
* Takes the PDF content data from child posts for indexing purposes.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
*
|
|
* @param array $insert_data The base data for INSERT queries.
|
|
* @param int $post_id The post ID.
|
|
*
|
|
* @return array $insert_data The INSERT data with new content added.
|
|
*/
|
|
function relevanssi_index_pdf_for_parent( $insert_data, $post_id ) {
|
|
$option = get_option( 'relevanssi_index_pdf_parent', '' );
|
|
if ( empty( $option ) || 'off' === $option ) {
|
|
return $insert_data;
|
|
}
|
|
|
|
global $wpdb;
|
|
|
|
$post_id = intval( $post_id );
|
|
$query = "SELECT meta_value FROM $wpdb->postmeta AS pm, $wpdb->posts AS p WHERE pm.post_id = p.ID AND p.post_parent = $post_id AND meta_key = '_relevanssi_pdf_content'";
|
|
/**
|
|
* Filters the database query that fetches the PDF content for the parent post.
|
|
*
|
|
* @param string $query The MySQL query.
|
|
* @param int $post_id The parent post ID.
|
|
*/
|
|
$query = apply_filters( 'relevanssi_pdf_for_parent_query', $query, $post_id );
|
|
$pdf_content = $wpdb->get_col( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
|
|
if ( is_array( $pdf_content ) ) {
|
|
/**
|
|
* Filters the custom field value before indexing.
|
|
*
|
|
* @param array Custom field values.
|
|
* @param string $field The custom field name.
|
|
* @param int $post_id The post ID.
|
|
*/
|
|
$pdf_content = apply_filters( 'relevanssi_custom_field_value', $pdf_content, '_relevanssi_pdf_content', $post_id );
|
|
foreach ( $pdf_content as $row ) {
|
|
/** This filter is documented in common/indexing.php */
|
|
$data = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $row, true, get_option( 'relevanssi_min_word_length', 3 ), 'indexing' ), 'pdf-content' );
|
|
if ( count( $data ) > 0 ) {
|
|
foreach ( $data as $term => $count ) {
|
|
if ( isset( $insert_data[ $term ]['customfield'] ) ) {
|
|
$insert_data[ $term ]['customfield'] += $count;
|
|
} else {
|
|
$insert_data[ $term ]['customfield'] = $count;
|
|
}
|
|
$insert_data = relevanssi_customfield_detail( $insert_data, $term, $count, '_relevanssi_pdf_content' );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filters the index data for the PDF contents.
|
|
*
|
|
* @param array $insert_data The data for INSERT clauses, format is
|
|
* $insert_data[ term ][ column ] = frequency.
|
|
* @param int $post_id The parent post ID.
|
|
*/
|
|
return apply_filters( 'relevanssi_pdf_for_parent_insert_data', $insert_data, $post_id );
|
|
}
|
|
|
|
/**
|
|
* Indexes all users.
|
|
*
|
|
* Runs indexing on all users.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*/
|
|
function relevanssi_index_users() {
|
|
global $wpdb, $relevanssi_variables;
|
|
|
|
// Delete all users from the Relevanssi index first.
|
|
$wpdb->query( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE type = 'user'" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
|
|
$users = relevanssi_get_users( array() );
|
|
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress = WP_CLI\Utils\make_progress_bar( 'Indexing users', count( $users ) );
|
|
}
|
|
|
|
$update = false;
|
|
foreach ( $users as $user ) {
|
|
/**
|
|
* Checks if the user can be indexed.
|
|
*
|
|
* @param boolean $index Should the user be indexed, default true.
|
|
* @param object $user The user object.
|
|
*
|
|
* @return boolean $index If false, do not index the user.
|
|
*/
|
|
$index_this_user = apply_filters( 'relevanssi_user_index_ok', true, $user );
|
|
|
|
if ( $index_this_user ) {
|
|
relevanssi_index_user( $user, $update );
|
|
}
|
|
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress->tick();
|
|
}
|
|
}
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress->finish();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Indexes users in AJAX context.
|
|
*
|
|
* Runs indexing on all users in AJAX context.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param int $limit Number of users to index on one go.
|
|
* @param int $offset Indexing offset.
|
|
*
|
|
* @return array $response AJAX response, number of users indexed in the $response['indexed'].
|
|
*/
|
|
function relevanssi_index_users_ajax( $limit, $offset ) {
|
|
$args = array(
|
|
'number' => intval( $limit ),
|
|
'offset' => intval( $offset ),
|
|
);
|
|
|
|
$users = relevanssi_get_users( $args );
|
|
|
|
$indexed_users = 0;
|
|
$update = false;
|
|
foreach ( $users as $user ) {
|
|
/**
|
|
* Checks if the user can be indexed.
|
|
*
|
|
* @param boolean $index Should the user be indexed, default true.
|
|
* @param object $user The user object.
|
|
*
|
|
* @return boolean $index If false, do not index the user.
|
|
*/
|
|
$index_this_user = apply_filters( 'relevanssi_user_index_ok', true, $user );
|
|
if ( $index_this_user ) {
|
|
relevanssi_index_user( $user, $update );
|
|
++$indexed_users;
|
|
}
|
|
}
|
|
|
|
$response = array(
|
|
'indexed' => $indexed_users,
|
|
);
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Gets the list of users.
|
|
*
|
|
* @param array $args The user indexing arguments.
|
|
*
|
|
* @return array An array of user profiles.
|
|
*/
|
|
function relevanssi_get_users( array $args ) {
|
|
$index_subscribers = get_option( 'relevanssi_index_subscribers' );
|
|
if ( 'on' !== $index_subscribers ) {
|
|
$args['role__not_in'] = array( 'subscriber' );
|
|
}
|
|
|
|
/**
|
|
* Filters the user fetching arguments.
|
|
*
|
|
* Useful to control the user role, for example: just set 'role__in' to whatever
|
|
* you need.
|
|
*
|
|
* @param array User fetching arguments.
|
|
*/
|
|
$users_list = get_users( apply_filters( 'relevanssi_user_indexing_args', $args ) );
|
|
$users = array();
|
|
foreach ( $users_list as $user ) {
|
|
$users[] = get_userdata( $user->ID );
|
|
}
|
|
|
|
return $users;
|
|
}
|
|
|
|
/**
|
|
* Indexes one user.
|
|
*
|
|
* Indexes one user profile.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param object|int $user The user object or user ID.
|
|
* @param boolean $remove_first Should the user be deleted first or not, default false.
|
|
*/
|
|
function relevanssi_index_user( $user, $remove_first = false ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
|
|
if ( is_numeric( $user ) ) {
|
|
// Not an object, make it an object.
|
|
$user = get_userdata( $user );
|
|
if ( false === $user ) {
|
|
// Invalid user ID given, no user found. Exit.
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( $remove_first ) {
|
|
relevanssi_delete_user( $user->ID );
|
|
}
|
|
|
|
/**
|
|
* Allows manipulating the user object before indexing.
|
|
*
|
|
* This filter can be used to manipulate the user object before it is
|
|
* processed for indexing. It's possible to add extra data (for example to
|
|
* user description field) or to change the existing data.
|
|
*
|
|
* @param object $user The user object.
|
|
*/
|
|
$user = apply_filters( 'relevanssi_user_add_data', $user );
|
|
|
|
$insert_data = array();
|
|
$min_length = get_option( 'relevanssi_min_word_length', 3 );
|
|
$remove_stopwords = true;
|
|
|
|
$values = relevanssi_get_user_field_content( $user->ID );
|
|
foreach ( $values as $field => $value ) {
|
|
/** This filter is documented in common/indexing.php */
|
|
$tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $value, $remove_stopwords, $min_length, 'indexing' ), 'user-fields' );
|
|
foreach ( $tokens as $term => $tf ) {
|
|
if ( isset( $insert_data[ $term ]['customfield'] ) ) {
|
|
$insert_data[ $term ]['customfield'] += $tf;
|
|
} else {
|
|
$insert_data[ $term ]['customfield'] = $tf;
|
|
}
|
|
$insert_data = relevanssi_customfield_detail( $insert_data, $term, $tf, $field );
|
|
}
|
|
}
|
|
|
|
if ( isset( $user->description ) && '' !== $user->description ) {
|
|
/** This filter is documented in common/indexing.php */
|
|
$tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $user->description, $remove_stopwords, $min_length, 'indexing' ), 'user-description' );
|
|
foreach ( $tokens as $term => $tf ) {
|
|
if ( isset( $insert_data[ $term ]['content'] ) ) {
|
|
$insert_data[ $term ]['content'] += $tf;
|
|
} else {
|
|
$insert_data[ $term ]['content'] = $tf;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isset( $user->first_name ) && '' !== $user->first_name ) {
|
|
$parts = explode( ' ', strtolower( $user->first_name ) );
|
|
foreach ( $parts as $part ) {
|
|
if ( empty( $part ) ) {
|
|
continue;
|
|
}
|
|
if ( isset( $insert_data[ $part ]['title'] ) ) {
|
|
++$insert_data[ $part ]['title'];
|
|
} else {
|
|
$insert_data[ $part ]['title'] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isset( $user->last_name ) && ' ' !== $user->last_name ) {
|
|
$parts = explode( ' ', strtolower( $user->last_name ) );
|
|
foreach ( $parts as $part ) {
|
|
if ( empty( $part ) ) {
|
|
continue;
|
|
}
|
|
if ( isset( $insert_data[ $part ]['title'] ) ) {
|
|
++$insert_data[ $part ]['title'];
|
|
} else {
|
|
$insert_data[ $part ]['title'] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isset( $user->display_name ) && ' ' !== $user->display_name ) {
|
|
$parts = explode( ' ', strtolower( $user->display_name ) );
|
|
foreach ( $parts as $part ) {
|
|
if ( empty( $part ) ) {
|
|
continue;
|
|
}
|
|
if ( isset( $insert_data[ $part ]['title'] ) ) {
|
|
++$insert_data[ $part ]['title'];
|
|
} else {
|
|
$insert_data[ $part ]['title'] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Allows the user insert data to be manipulated.
|
|
*
|
|
* This function manipulates the user insert data used to create the INSERT queries.
|
|
*
|
|
* @param array $insert_data The source data for the INSERT queries.
|
|
* @param object $user The user object.
|
|
*/
|
|
$insert_data = apply_filters( 'relevanssi_user_data_to_index', $insert_data, $user );
|
|
|
|
foreach ( $insert_data as $term => $data ) {
|
|
$fields = array( 'content', 'title', 'comment', 'tag', 'link', 'author', 'category', 'excerpt', 'taxonomy', 'customfield', 'customfield_detail' );
|
|
foreach ( $fields as $field ) {
|
|
if ( ! isset( $data[ $field ] ) ) {
|
|
$data[ $field ] = 0;
|
|
}
|
|
}
|
|
|
|
$content = $data['content'];
|
|
$title = $data['title'];
|
|
$comment = $data['comment'];
|
|
$tag = $data['tag'];
|
|
$link = $data['link'];
|
|
$author = $data['author'];
|
|
$category = $data['category'];
|
|
$excerpt = $data['excerpt'];
|
|
$taxonomy = $data['taxonomy'];
|
|
$customfield = $data['customfield'];
|
|
$cf_detail = $data['customfield_detail'];
|
|
|
|
$wpdb->query(
|
|
$wpdb->prepare(
|
|
'INSERT IGNORE INTO ' . $relevanssi_variables['relevanssi_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
' (item, doc, term, term_reverse, content, title, comment, tag, link, author, category, excerpt, taxonomy, customfield, type, customfield_detail, taxonomy_detail, mysqlcolumn_detail)
|
|
VALUES (%d, %d, %s, REVERSE(%s), %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %s)',
|
|
$user->ID,
|
|
-1,
|
|
$term,
|
|
$term,
|
|
$content,
|
|
$title,
|
|
$comment,
|
|
$tag,
|
|
$link,
|
|
$author,
|
|
$category,
|
|
$excerpt,
|
|
$taxonomy,
|
|
$customfield,
|
|
'user',
|
|
$cf_detail,
|
|
'',
|
|
''
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Counts users.
|
|
*
|
|
* Figures out how many users there are to index.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
*
|
|
* @return int $count_users Number of users, -1 if user indexing is disabled.
|
|
*/
|
|
function relevanssi_count_users() {
|
|
$index_users = get_option( 'relevanssi_index_users' );
|
|
if ( empty( $index_users ) || 'off' === $index_users ) {
|
|
return -1;
|
|
}
|
|
|
|
$args = array(
|
|
'fields' => 'ID',
|
|
);
|
|
|
|
$index_subscribers = get_option( 'relevanssi_index_subscribers' );
|
|
if ( 'on' !== $index_subscribers ) {
|
|
$args['role__not_in'] = array( 'subscriber' );
|
|
}
|
|
|
|
$users = get_users(
|
|
/**
|
|
* Documented in /premium/indexing.php.
|
|
*/
|
|
apply_filters( 'relevanssi_user_indexing_args', $args )
|
|
);
|
|
$count_users = count( $users );
|
|
|
|
return $count_users;
|
|
}
|
|
|
|
/**
|
|
* Counts taxonomy terms.
|
|
*
|
|
* Figures out how many taxonomy terms there are to index.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
*
|
|
* @return int $count_terms Number of taxonomy terms, -1 if taxonomy term indexing is disabled.
|
|
*/
|
|
function relevanssi_count_taxonomy_terms() {
|
|
$index_taxonomies = get_option( 'relevanssi_index_taxonomies' );
|
|
if ( empty( $index_taxonomies ) || 'off' === $index_taxonomies ) {
|
|
return -1;
|
|
}
|
|
|
|
global $wpdb;
|
|
|
|
$taxonomies = get_option( 'relevanssi_index_terms' );
|
|
if ( empty( $taxonomies ) ) {
|
|
// No taxonomies chosen for indexing.
|
|
return -1;
|
|
}
|
|
$count_terms = 0;
|
|
foreach ( $taxonomies as $taxonomy ) {
|
|
if ( ! taxonomy_exists( $taxonomy ) ) {
|
|
// Non-existing taxonomy. Shouldn't be possible, but better be sure.
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Determines whether empty terms are indexed or not.
|
|
*
|
|
* @param boolean $hide_empty_terms If true, empty terms are not indexed. Default true.
|
|
*/
|
|
$hide_empty = apply_filters( 'relevanssi_hide_empty_terms', true );
|
|
|
|
$count = '';
|
|
if ( $hide_empty ) {
|
|
$count = 'AND tt.count > 0';
|
|
}
|
|
|
|
$terms = $wpdb->get_col( "SELECT t.term_id FROM $wpdb->terms AS t, $wpdb->term_taxonomy AS tt WHERE t.term_id = tt.term_id $count AND tt.taxonomy = '$taxonomy'" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
|
|
$count_terms += count( $terms );
|
|
}
|
|
return $count_terms;
|
|
}
|
|
|
|
/**
|
|
* Returns the list of taxonomies chosen for indexing.
|
|
*
|
|
* Returns the list of taxonomies chosen for indexing from the 'relevanssi_index_terms' option.
|
|
*
|
|
* @return array $taxonomies A list of taxonomies chosen to be indexed.
|
|
*/
|
|
function relevanssi_list_taxonomies() {
|
|
return get_option( 'relevanssi_index_terms' );
|
|
}
|
|
|
|
/**
|
|
* Indexes taxonomy terms in AJAX context.
|
|
*
|
|
* Runs indexing on taxonomy terms in one taxonomy in AJAX context.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param string $taxonomy The taxonomy to index.
|
|
* @param int $limit Number of users to index on one go.
|
|
* @param int $offset Indexing offset.
|
|
*
|
|
* @return array $response AJAX response, number of taxonomy terms indexed in the
|
|
* $response['indexed'] and a boolean value in $response['taxonomy_completed'] that
|
|
* tells whether the taxonomy is indexed completely or not.
|
|
*/
|
|
function relevanssi_index_taxonomies_ajax( $taxonomy, $limit, $offset ) {
|
|
global $wpdb;
|
|
|
|
$indexed_terms = 0;
|
|
$end_reached = false;
|
|
|
|
$terms = relevanssi_get_terms( $taxonomy, intval( $limit ), intval( $offset ) );
|
|
|
|
if ( count( $terms ) < $limit ) {
|
|
$end_reached = true;
|
|
}
|
|
|
|
do_action( 'relevanssi_pre_index_taxonomies' );
|
|
|
|
foreach ( $terms as $term_id ) {
|
|
$update = false;
|
|
$term = get_term( $term_id, $taxonomy );
|
|
relevanssi_index_taxonomy_term( $term, $taxonomy, $update );
|
|
++$indexed_terms;
|
|
}
|
|
|
|
do_action( 'relevanssi_post_index_taxonomies' );
|
|
|
|
$response = array(
|
|
'indexed' => $indexed_terms,
|
|
'taxonomy_completed' => 'not',
|
|
);
|
|
if ( $end_reached ) {
|
|
$response['taxonomy_completed'] = 'done';
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Indexes all taxonomies.
|
|
*
|
|
* Runs indexing on all taxonomies.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param boolean $is_ajax Whether indexing is done in the AJAX context, default false.
|
|
*
|
|
* @return array $response If $is_ajax is true, the function returns indexing status in an array.
|
|
*/
|
|
function relevanssi_index_taxonomies( $is_ajax = false ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
|
|
$wpdb->query( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE doc = -1 AND type NOT IN ('user', 'post_type')" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
|
|
do_action( 'relevanssi_pre_index_taxonomies' );
|
|
|
|
$taxonomies = get_option( 'relevanssi_index_terms' );
|
|
$indexed_terms = 0;
|
|
foreach ( $taxonomies as $taxonomy ) {
|
|
$terms = relevanssi_get_terms( $taxonomy, 0, 0 );
|
|
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress = WP_CLI\Utils\make_progress_bar( "Indexing $taxonomy", count( $terms ) );
|
|
}
|
|
|
|
$update = false;
|
|
foreach ( $terms as $term ) {
|
|
relevanssi_index_taxonomy_term( $term, $taxonomy, $update );
|
|
++$indexed_terms;
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress->tick();
|
|
}
|
|
}
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress->finish();
|
|
}
|
|
}
|
|
|
|
do_action( 'relevanssi_post_index_taxonomies' );
|
|
|
|
if ( $is_ajax ) {
|
|
if ( $indexed_terms > 0 ) {
|
|
// translators: the number of taxonomy terms.
|
|
return sprintf( __( 'Indexed %d taxonomy terms.', 'relevanssi' ), $indexed_terms );
|
|
} else {
|
|
return __( 'No taxonomies to index.', 'relevanssi' );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets a list of taxonomy terms.
|
|
*
|
|
* @param string $taxonomy The taxonomy to index.
|
|
* @param int $limit Number of users to index on one go.
|
|
* @param int $offset Indexing offset.
|
|
*
|
|
* @return array A list of taxonomy terms.
|
|
*/
|
|
function relevanssi_get_terms( string $taxonomy, int $limit = 0, int $offset = 0 ): array {
|
|
global $wpdb;
|
|
|
|
/**
|
|
* Determines whether empty terms are indexed or not.
|
|
*
|
|
* @param boolean $hide_empty_terms If true, empty terms are not indexed. Default true.
|
|
*/
|
|
$hide_empty = apply_filters( 'relevanssi_hide_empty_terms', true );
|
|
$count = '';
|
|
if ( $hide_empty ) {
|
|
$count = 'AND tt.count > 0';
|
|
}
|
|
|
|
$limit_sql = '';
|
|
if ( $limit && $offset ) {
|
|
$limit_sql = $wpdb->prepare( 'LIMIT %d OFFSET %d', $limit, $offset );
|
|
}
|
|
|
|
$terms = $wpdb->get_col(
|
|
$wpdb->prepare(
|
|
"SELECT t.term_id FROM $wpdb->terms AS t, $wpdb->term_taxonomy AS tt
|
|
WHERE t.term_id = tt.term_id $count AND tt.taxonomy = %s $limit_sql ", // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
$taxonomy
|
|
)
|
|
);
|
|
|
|
return $terms;
|
|
}
|
|
|
|
/**
|
|
* Indexes one taxonomy term.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param object|int $term The term object or term ID.
|
|
* @param string $taxonomy The name of the taxonomy.
|
|
* @param boolean $remove_first Should the term be deleted first or not, default false.
|
|
* @param boolean $debug If true, print out debug information, default false.
|
|
*/
|
|
function relevanssi_index_taxonomy_term( $term, $taxonomy, $remove_first = false, $debug = false ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
|
|
if ( is_numeric( $term ) ) {
|
|
// Not an object, so let's get the object.
|
|
$term = get_term( $term, $taxonomy );
|
|
}
|
|
|
|
/**
|
|
* Allows the term object to be handled before indexing.
|
|
*
|
|
* This filter can be used to add data to term objects before indexing, or to manipulate the object somehow.
|
|
*
|
|
* @param object $term The term object.
|
|
* @param string $taxonomy The taxonomy.
|
|
*/
|
|
$term = apply_filters( 'relevanssi_term_add_data', $term, $taxonomy );
|
|
|
|
$temp_post = new stdClass();
|
|
$temp_post->post_content = $term->description;
|
|
$temp_post->post_title = $term->name;
|
|
|
|
/**
|
|
* Allows modifying the fake post for the taxonomy term.
|
|
*
|
|
* In order to index taxonomy terms, Relevanssi generates fake posts from the
|
|
* terms. This filter lets you modify the post object. The term description
|
|
* is in the post_content and the term name in the post_title.
|
|
*
|
|
* @param object $temp_post The post object.
|
|
* @param object $term The term object.
|
|
*/
|
|
$temp_post = apply_filters( 'relevanssi_post_to_index', $temp_post, $term );
|
|
|
|
$term->description = $temp_post->post_content;
|
|
$term->name = $temp_post->post_title;
|
|
|
|
$index_this_post = true;
|
|
|
|
/**
|
|
* Determines whether a term is indexed or not.
|
|
*
|
|
* If this filter returns true, this term should not be indexed.
|
|
*
|
|
* @param boolean $block If true, do not index this post. Default false.
|
|
* @param WP_Term $term The term object.
|
|
* @param string $taxonomy The term taxonomy.
|
|
*/
|
|
if ( true === apply_filters( 'relevanssi_do_not_index_term', false, $term, $taxonomy ) ) {
|
|
// Filter says no.
|
|
if ( $debug ) {
|
|
relevanssi_debug_echo( 'relevanssi_do_not_index_term returned true.' );
|
|
}
|
|
$index_this_post = false;
|
|
}
|
|
|
|
if ( $remove_first ) {
|
|
// The 0 doesn't mean anything, but because of WP hook parameters, it needs to be there
|
|
// so the taxonomy can be passed as the third parameter.
|
|
relevanssi_delete_taxonomy_term( $term->term_id, 0, $taxonomy );
|
|
}
|
|
|
|
// This needs to be here, after the call to relevanssi_delete_taxonomy_term(), because otherwise
|
|
// a post that's in the index but shouldn't be there won't get removed.
|
|
if ( ! $index_this_post ) {
|
|
return 'donotindex';
|
|
}
|
|
|
|
$insert_data = array();
|
|
$remove_stopwords = true;
|
|
|
|
$min_length = get_option( 'relevanssi_min_word_length', 3 );
|
|
if ( ! isset( $term->description ) ) {
|
|
$term->description = '';
|
|
}
|
|
/**
|
|
* Allows adding extra content to the term before indexing.
|
|
*
|
|
* The term description is passed through this filter, so if you want to add
|
|
* extra content to the description, you can use this filter.
|
|
*
|
|
* @param string $term->description The term description.
|
|
* @param object $term The term object.
|
|
*/
|
|
$description = apply_filters( 'relevanssi_tax_term_additional_content', $term->description, $term );
|
|
if ( ! empty( $description ) ) {
|
|
/** This filter is documented in common/indexing.php */
|
|
$tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $description, $remove_stopwords, $min_length, 'indexing' ), 'term-description' );
|
|
foreach ( $tokens as $t_term => $tf ) {
|
|
if ( ! isset( $insert_data[ $t_term ]['content'] ) ) {
|
|
$insert_data[ $t_term ]['content'] = 0;
|
|
}
|
|
$insert_data[ $t_term ]['content'] += $tf;
|
|
}
|
|
}
|
|
|
|
if ( isset( $term->name ) && ! empty( $term->name ) ) {
|
|
/** This filter is documented in common/indexing.php */
|
|
$tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $term->name, $remove_stopwords, $min_length, 'indexing' ), 'term-name' );
|
|
foreach ( $tokens as $t_term => $tf ) {
|
|
if ( ! isset( $insert_data[ $t_term ]['title'] ) ) {
|
|
$insert_data[ $t_term ]['title'] = 0;
|
|
}
|
|
$insert_data[ $t_term ]['title'] += $tf;
|
|
}
|
|
}
|
|
|
|
foreach ( $insert_data as $t_term => $data ) {
|
|
$fields = array( 'content', 'title', 'comment', 'tag', 'link', 'author', 'category', 'excerpt', 'taxonomy', 'customfield' );
|
|
foreach ( $fields as $field ) {
|
|
if ( ! isset( $data[ $field ] ) ) {
|
|
$data[ $field ] = 0;
|
|
}
|
|
}
|
|
|
|
$content = $data['content'];
|
|
$title = $data['title'];
|
|
$comment = $data['comment'];
|
|
$tag = $data['tag'];
|
|
$link = $data['link'];
|
|
$author = $data['author'];
|
|
$category = $data['category'];
|
|
$excerpt = $data['excerpt'];
|
|
$customfield = $data['customfield'];
|
|
$t_term = trim( $t_term ); // Numeric terms start with a space.
|
|
|
|
$wpdb->query(
|
|
$wpdb->prepare(
|
|
'INSERT IGNORE INTO ' . $relevanssi_variables['relevanssi_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
' (item, doc, term, term_reverse, content, title, comment, tag, link, author, category, excerpt, taxonomy, customfield, type, customfield_detail, taxonomy_detail, mysqlcolumn_detail)
|
|
VALUES (%d, %d, %s, REVERSE(%s), %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %s)',
|
|
$term->term_id,
|
|
-1,
|
|
$t_term,
|
|
$t_term,
|
|
$content,
|
|
$title,
|
|
$comment,
|
|
$tag,
|
|
$link,
|
|
$author,
|
|
$category,
|
|
$excerpt,
|
|
'',
|
|
$customfield,
|
|
$taxonomy,
|
|
'',
|
|
'',
|
|
''
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes a document from the index.
|
|
*
|
|
* This Premium version also takes care of internal linking keywords, either keeping them (in case of
|
|
* an update) or removing them (if the post is removed).
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param int $post_id The post ID.
|
|
* @param boolean $keep_internal_linking If true, do not remove internal link keywords from this post.
|
|
*/
|
|
function relevanssi_premium_remove_doc( $post_id, $keep_internal_linking ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
|
|
$post_id = intval( $post_id );
|
|
if ( empty( $post_id ) ) {
|
|
// No post ID specified.
|
|
return;
|
|
}
|
|
|
|
$internal_links = '';
|
|
if ( $keep_internal_linking ) {
|
|
$internal_links = 'AND link = 0';
|
|
}
|
|
|
|
$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE doc=%s $internal_links", $post_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
|
|
if ( ! $keep_internal_linking ) {
|
|
$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE link > 0 AND doc=%s', $post_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes an item (user or taxonomy term) from the index.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the database table names.
|
|
*
|
|
* @param int $item_id The item ID number.
|
|
* @param string $type The item type.
|
|
*/
|
|
function relevanssi_remove_item( $item_id, $type ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
|
|
$item_id = intval( $item_id );
|
|
|
|
if ( 0 === $item_id && 'post' === $type ) {
|
|
// Security measures.
|
|
return;
|
|
}
|
|
|
|
$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE item = %d AND type = %s', $item_id, $type ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
}
|
|
|
|
/**
|
|
* Checks if post is hidden.
|
|
*
|
|
* Used in indexing process to check if post is hidden. Checks the
|
|
* '_relevanssi_hide_post' custom field.
|
|
*
|
|
* @param int $post_id The post ID to check.
|
|
*
|
|
* @return boolean $hidden Is the post hidden?
|
|
*/
|
|
function relevanssi_hide_post( $post_id ) {
|
|
$hidden = false;
|
|
$field_value = get_post_meta( $post_id, '_relevanssi_hide_post', true );
|
|
if ( 'on' === $field_value ) {
|
|
$hidden = true;
|
|
}
|
|
return $hidden;
|
|
}
|
|
|
|
/**
|
|
* Indexes post type archive pages.
|
|
*
|
|
* Goes through all the post type archive pages and indexes them using
|
|
* relevanssi_index_post_type_archive().
|
|
*
|
|
* @see relevanssi_index_post_type_archive()
|
|
* @since 2.2
|
|
*
|
|
* @global object $wpdb The WordPress database object.
|
|
*/
|
|
function relevanssi_index_post_type_archives() {
|
|
if ( 'on' === get_option( 'relevanssi_index_post_type_archives' ) ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
|
|
// Delete all post types from the Relevanssi index first.
|
|
$wpdb->query(
|
|
'DELETE FROM ' . $relevanssi_variables['relevanssi_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
" WHERE type = 'post_type'"
|
|
);
|
|
|
|
$post_types = relevanssi_get_indexed_post_type_archives();
|
|
if ( ! empty( $post_types ) ) {
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress = WP_CLI\Utils\make_progress_bar(
|
|
'Indexing post type archives',
|
|
count( $post_types )
|
|
);
|
|
}
|
|
foreach ( $post_types as $post_type ) {
|
|
relevanssi_index_post_type_archive( $post_type );
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress->tick();
|
|
}
|
|
}
|
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
$progress->finish();
|
|
}
|
|
} elseif ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
WP_CLI::log( 'No post types available for post type archive indexing.' );
|
|
}
|
|
} elseif ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
WP_CLI::error( 'Post type archive indexing disabled.' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Indexes post type archive pages in AJAX context.
|
|
*
|
|
* Runs indexing on all post type archives in AJAX context.
|
|
*
|
|
* @return array $response AJAX response, number of post type archives indexed
|
|
* in the$response['indexed'].
|
|
*/
|
|
function relevanssi_index_post_type_archives_ajax() {
|
|
$post_types = relevanssi_get_indexed_post_type_archives();
|
|
|
|
if ( empty( $post_types ) ) {
|
|
$response = array(
|
|
'indexed' => 0,
|
|
);
|
|
return $response;
|
|
}
|
|
|
|
$indexed_post_types = 0;
|
|
foreach ( $post_types as $post_type ) {
|
|
relevanssi_index_post_type_archive( $post_type );
|
|
++$indexed_post_types;
|
|
}
|
|
|
|
$response = array(
|
|
'indexed' => $indexed_post_types,
|
|
);
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Assigns numeric IDs for post types.
|
|
*
|
|
* Relevanssi requires numeric IDs for post types for indexing purposes. This
|
|
* function assigns numbers for each post type, in alphabetical order. This is a
|
|
* bit of a hack, and fails if new post types are added, but hopefully that
|
|
* doesn't happen too often. The assigned numbers are stored in the option
|
|
* relevanssi_post_type_ids.
|
|
*
|
|
* @since 2.2
|
|
*
|
|
* @return array The post type ID arrays (by ID and by name).
|
|
*/
|
|
function relevanssi_assign_post_type_ids() {
|
|
$post_types = relevanssi_get_indexed_post_type_archives();
|
|
sort( $post_types );
|
|
|
|
$post_type_ids_by_id = array();
|
|
$post_type_ids_by_name = array();
|
|
|
|
$id = 1;
|
|
foreach ( $post_types as $post_type ) {
|
|
$post_type_ids_by_id[ $id ] = $post_type;
|
|
$post_type_ids_by_name[ $post_type ] = $id;
|
|
++$id;
|
|
}
|
|
update_option(
|
|
'relevanssi_post_type_ids',
|
|
array(
|
|
'by_id' => $post_type_ids_by_id,
|
|
'by_name' => $post_type_ids_by_name,
|
|
)
|
|
);
|
|
|
|
return array(
|
|
'by_id' => $post_type_ids_by_id,
|
|
'by_name' => $post_type_ids_by_name,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Gets the post type ID by post type name.
|
|
*
|
|
* Fetches the post type ID from the relevanssi_post_type_ids option by the post
|
|
* type name. If the option is empty, will populate it with values. If the post
|
|
* type can't be found in the list, the function tries to regenerate the list in
|
|
* case there's a new post type Relevanssi doesn't know.
|
|
*
|
|
* @see relevanssi_assign_post_type_ids()
|
|
* @see relevanssi_get_post_type_by_id()
|
|
* @since 2.2
|
|
*
|
|
* @param string $post_type The name of the post type.
|
|
*
|
|
* @return integer|null The post type ID number or null if not a valid post
|
|
* type.
|
|
*/
|
|
function relevanssi_get_post_type_by_name( $post_type ) {
|
|
$post_type_ids = get_option( 'relevanssi_post_type_ids', false );
|
|
if ( empty( $post_type_ids ) ) {
|
|
$post_type_ids = relevanssi_assign_post_type_ids();
|
|
}
|
|
if ( ! isset( $post_type_ids['by_name'][ $post_type ] ) ) {
|
|
$post_type_ids = relevanssi_assign_post_type_ids();
|
|
}
|
|
if ( isset( $post_type_ids['by_name'][ $post_type ] ) ) {
|
|
return $post_type_ids['by_name'][ $post_type ];
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the post type name by post type ID.
|
|
*
|
|
* Fetches the post type name from the relevanssi_post_type_ids option by the
|
|
* post type ID. If the option is empty, will populate it with values. If the
|
|
* post type can't be found in the list, the function tries to regenerate the
|
|
* list in case there's a new post type Relevanssi doesn't know.
|
|
*
|
|
* @see relevanssi_assign_post_type_ids()
|
|
* @see relevanssi_get_post_type_by_name()
|
|
* @since 2.2
|
|
*
|
|
* @param integer $id The ID number of the post type.
|
|
*
|
|
* @return string|null The post type name or null if not a valid post type.
|
|
*/
|
|
function relevanssi_get_post_type_by_id( $id ) {
|
|
$post_type_ids = get_option( 'relevanssi_post_type_ids', false );
|
|
if ( empty( $post_type_ids ) ) {
|
|
$post_type_ids = relevanssi_assign_post_type_ids();
|
|
}
|
|
if ( ! isset( $post_type_ids['by_id'][ $id ] ) ) {
|
|
$post_type_ids = relevanssi_assign_post_type_ids();
|
|
}
|
|
if ( isset( $post_type_ids['by_id'][ $id ] ) ) {
|
|
return $post_type_ids['by_id'][ $id ];
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Indexes a post type archive page.
|
|
*
|
|
* Indexes a post type archive page, indexing the archive label and the
|
|
* description which can be set when the post type is registered. The filter
|
|
* hook relevanssi_post_type_additional_content can be used to add additional
|
|
* content to the post type archive description.
|
|
*
|
|
* @since 2.2
|
|
*
|
|
* @param string $post_type The name of the post type.
|
|
* @param boolean $remove_first Should the post type be removed first from the
|
|
* index.
|
|
*
|
|
* @global object $wpdb The WordPress database object.
|
|
* @global array $relevanssi_variables The Relevanssi global variables.
|
|
*/
|
|
function relevanssi_index_post_type_archive( $post_type, $remove_first = true ) {
|
|
$post_type_object = get_post_type_object( $post_type );
|
|
global $wpdb, $relevanssi_variables;
|
|
|
|
/**
|
|
* Allows excluding post type archives from the index.
|
|
*
|
|
* If this filter hook returns false, the post type archive won't be
|
|
* indexed and if it's already indexed, it will be removed from the index.
|
|
*
|
|
* @param boolean If true, index the archive. Default true.
|
|
* @param object The post type object.
|
|
*/
|
|
if ( ! apply_filters( 'relevanssi_post_type_archive_ok', true, $post_type ) ) {
|
|
relevanssi_delete_post_type_object( $post_type );
|
|
return;
|
|
}
|
|
|
|
$temp_post = new stdClass();
|
|
$temp_post->post_content = $post_type_object->description;
|
|
$temp_post->post_title = $post_type_object->name;
|
|
|
|
/**
|
|
* Allows modifying the fake post for the post type archive.
|
|
*
|
|
* In order to index post type archives, Relevanssi generates fake posts
|
|
* from the post types. This filter lets you modify the post object. The
|
|
* post type description is in the post_content and the post type name in
|
|
* the post_title.
|
|
*
|
|
* @param object $temp_post The post object.
|
|
* @param object $post_type The post type object.
|
|
*/
|
|
$temp_post = apply_filters(
|
|
'relevanssi_post_to_index',
|
|
$temp_post,
|
|
$post_type_object
|
|
);
|
|
|
|
$post_type_object->description = $temp_post->post_content;
|
|
$post_type_object->name = $temp_post->post_title;
|
|
|
|
if ( $remove_first ) {
|
|
relevanssi_delete_post_type_object( $post_type );
|
|
}
|
|
|
|
$insert_data = array();
|
|
$remove_stopwords = true;
|
|
|
|
$min_length = get_option( 'relevanssi_min_word_length', 3 );
|
|
if ( ! isset( $post_type_object->description ) ) {
|
|
$post_type_object->description = '';
|
|
}
|
|
/**
|
|
* Allows adding extra content to the post type before indexing.
|
|
*
|
|
* The post type description is passed through this filter, so if you want
|
|
* to add extra content to the description, you can use this filter.
|
|
*
|
|
* @param string $post_type_object->description The post type description.
|
|
* @param object $post_type_object The post type object.
|
|
*/
|
|
$description = apply_filters(
|
|
'relevanssi_post_type_additional_content',
|
|
$post_type_object->description,
|
|
$post_type_object
|
|
);
|
|
if ( ! empty( $description ) ) {
|
|
/** This filter is documented in lib/indexing.php */
|
|
$tokens = apply_filters(
|
|
'relevanssi_indexing_tokens',
|
|
relevanssi_tokenize( $description, $remove_stopwords, $min_length, 'indexing' ),
|
|
'posttype-description'
|
|
);
|
|
foreach ( $tokens as $t_term => $tf ) {
|
|
if ( ! isset( $insert_data[ $t_term ]['content'] ) ) {
|
|
$insert_data[ $t_term ]['content'] = 0;
|
|
}
|
|
$insert_data[ $t_term ]['content'] += $tf;
|
|
}
|
|
}
|
|
|
|
if ( isset( $post_type_object->name ) && ! empty( $post_type_object->name ) ) {
|
|
/** This filter is documented in lib/indexing.php */
|
|
$tokens = apply_filters(
|
|
'relevanssi_indexing_tokens',
|
|
relevanssi_tokenize( $post_type_object->label, $remove_stopwords, $min_length, 'indexing' ),
|
|
'posttype-name'
|
|
);
|
|
foreach ( $tokens as $t_term => $tf ) {
|
|
if ( ! isset( $insert_data[ $t_term ]['title'] ) ) {
|
|
$insert_data[ $t_term ]['title'] = 0;
|
|
}
|
|
$insert_data[ $t_term ]['title'] += $tf;
|
|
}
|
|
}
|
|
|
|
$post_type_id = relevanssi_get_post_type_by_name( $post_type );
|
|
foreach ( $insert_data as $t_term => $data ) {
|
|
$fields = array( 'content', 'title', 'comment', 'tag', 'link', 'author', 'category', 'excerpt', 'taxonomy', 'customfield' );
|
|
foreach ( $fields as $field ) {
|
|
if ( ! isset( $data[ $field ] ) ) {
|
|
$data[ $field ] = 0;
|
|
}
|
|
}
|
|
|
|
$content = $data['content'];
|
|
$title = $data['title'];
|
|
$comment = $data['comment'];
|
|
$tag = $data['tag'];
|
|
$link = $data['link'];
|
|
$author = $data['author'];
|
|
$category = $data['category'];
|
|
$excerpt = $data['excerpt'];
|
|
$customfield = $data['customfield'];
|
|
$t_term = trim( $t_term ); // Numeric terms start with a space.
|
|
|
|
$wpdb->query(
|
|
$wpdb->prepare(
|
|
'INSERT IGNORE INTO ' . $relevanssi_variables['relevanssi_table'] . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
' (item, doc, term, term_reverse, content, title, comment, tag, link, author, category, excerpt, taxonomy, customfield, type, customfield_detail, taxonomy_detail, mysqlcolumn_detail)
|
|
VALUES (%d, %d, %s, REVERSE(%s), %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %s)',
|
|
$post_type_id,
|
|
-1,
|
|
$t_term,
|
|
$t_term,
|
|
$content,
|
|
$title,
|
|
$comment,
|
|
$tag,
|
|
$link,
|
|
$author,
|
|
$category,
|
|
$excerpt,
|
|
'',
|
|
$customfield,
|
|
'post_type',
|
|
'',
|
|
'',
|
|
''
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes a post type archive from Relevanssi index.
|
|
*
|
|
* @global $wpdb The WordPress database interface.
|
|
* @global $relevanssi_variables The global Relevanssi variables, used for the
|
|
* database table names.
|
|
*
|
|
* @param string $post_type Name of the post type to remove.
|
|
*/
|
|
function relevanssi_delete_post_type_object( $post_type ) {
|
|
global $wpdb, $relevanssi_variables;
|
|
$id = relevanssi_get_post_type_by_name( $post_type );
|
|
if ( $id ) {
|
|
$wpdb->query(
|
|
'DELETE FROM ' .
|
|
$relevanssi_variables['relevanssi_table'] . " WHERE item = $id " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
"AND type = 'post_type'"
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the list of post type archives indexed.
|
|
*
|
|
* Returns a list of post types that have _builtin set to false and has_archive
|
|
* set to true. The list can be adjusted with the
|
|
* relevanssi_indexed_post_type_archives filter hook.
|
|
*
|
|
* @return array An array of post types.
|
|
*/
|
|
function relevanssi_get_indexed_post_type_archives() {
|
|
$args = array(
|
|
'_builtin' => false,
|
|
'has_archive' => true,
|
|
);
|
|
$post_types = get_post_types( $args );
|
|
/**
|
|
* Filters the list of post type archives that are indexed by Relevanssi.
|
|
*
|
|
* @param array An array of post types.
|
|
*
|
|
* @return array An array of post types.
|
|
*/
|
|
return apply_filters( 'relevanssi_indexed_post_type_archives', $post_types );
|
|
}
|
|
|
|
/**
|
|
* Runs taxonomy, user and post type archive indexing if necessary.
|
|
*/
|
|
function relevanssi_premium_indexing() {
|
|
if ( 'on' === get_option( 'relevanssi_index_taxonomies' ) ) {
|
|
relevanssi_index_taxonomies();
|
|
}
|
|
if ( 'on' === get_option( 'relevanssi_index_users' ) ) {
|
|
relevanssi_index_users();
|
|
}
|
|
if ( 'on' === get_option( 'relevanssi_index_post_type_archives' ) ) {
|
|
relevanssi_index_post_type_archives();
|
|
}
|
|
}
|