plugin updates
This commit is contained in:
@@ -1,228 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WPSEO Premium plugin file.
|
||||
*
|
||||
* @package WPSEO\Premium\Classes\Export
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Export_Keywords_CSV
|
||||
*
|
||||
* Exports data as returned by WPSEO_Export_Keywords_Presenter to CSV.
|
||||
*/
|
||||
class WPSEO_Export_Keywords_CSV {
|
||||
|
||||
/**
|
||||
* The columns that should be presented.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $columns;
|
||||
|
||||
/**
|
||||
* Data to be exported.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = '';
|
||||
|
||||
/**
|
||||
* WPSEO_Export_Keywords_CSV constructor.
|
||||
*
|
||||
* Supported values for columns are 'title', 'url', 'keywords', 'readability_score' and 'keywords_score'.
|
||||
* Requesting 'keywords_score' will always also return 'keywords'.
|
||||
*
|
||||
* @param array $columns An array of columns that should be presented.
|
||||
*/
|
||||
public function __construct( array $columns ) {
|
||||
$this->columns = array_filter( $columns, 'is_string' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Echoes the CSV headers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function print_headers() {
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Correctly escaped in get_headers() method below.
|
||||
echo $this->get_headers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Echoes a formatted row.
|
||||
*
|
||||
* @param array $row Row to add to the export.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function print_row( $row ) {
|
||||
echo $this->format( $row );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CSV headers based on the queried columns.
|
||||
*
|
||||
* @return string The headers in CSV format.
|
||||
*/
|
||||
protected function get_headers() {
|
||||
$header_columns = [
|
||||
'title' => esc_html__( 'title', 'wordpress-seo-premium' ),
|
||||
'url' => esc_html__( 'url', 'wordpress-seo-premium' ),
|
||||
'readability_score' => esc_html__( 'readability score', 'wordpress-seo-premium' ),
|
||||
'keywords' => esc_html__( 'keyphrase', 'wordpress-seo-premium' ),
|
||||
'keywords_score' => esc_html__( 'keyphrase score', 'wordpress-seo-premium' ),
|
||||
'seo_title' => esc_html__( 'seo title', 'wordpress-seo-premium' ),
|
||||
'meta_description' => esc_html__( 'meta description', 'wordpress-seo-premium' ),
|
||||
];
|
||||
|
||||
$csv = $this->sanitize_csv_column( esc_html__( 'ID', 'wordpress-seo-premium' ) );
|
||||
$csv .= ',' . $this->sanitize_csv_column( esc_html_x( 'type', 'post_type of a post or the taxonomy of a term', 'wordpress-seo-premium' ) );
|
||||
|
||||
foreach ( $this->columns as $column ) {
|
||||
if ( array_key_exists( $column, $header_columns ) ) {
|
||||
$csv .= ',' . $this->sanitize_csv_column( $header_columns[ $column ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $csv . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a WPSEO_Export_Keywords_Query result as a CSV line.
|
||||
* In case of multiple keywords it will return multiple lines.
|
||||
*
|
||||
* @param array $result A result as returned from WPSEO_Export_Keywords_Query::get_data.
|
||||
*
|
||||
* @return string A line of CSV, beginning with EOL.
|
||||
*/
|
||||
protected function format( array $result ) {
|
||||
// If our input is malformed return an empty string.
|
||||
if ( ! array_key_exists( 'ID', $result ) || ! array_key_exists( 'type', $result ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Ensure we have arrays in the keywords.
|
||||
$result['keywords'] = $this->get_array_from_result( $result, 'keywords' );
|
||||
$result['keywords_score'] = $this->get_array_from_result( $result, 'keywords_score' );
|
||||
|
||||
$csv = '';
|
||||
|
||||
// Add at least one row plus additional ones if we have more keywords.
|
||||
$keywords = max( 1, count( $result['keywords'] ) );
|
||||
for ( $keywords_index = 0; $keywords_index < $keywords; $keywords_index++ ) {
|
||||
// Add static columns.
|
||||
$csv .= $this->sanitize_csv_column( $result['ID'] );
|
||||
$csv .= ',' . $this->sanitize_csv_column( $result['type'] );
|
||||
|
||||
// Add dynamic columns.
|
||||
foreach ( $this->columns as $column ) {
|
||||
$csv .= $this->get_csv_column_from_result( $result, $column, $keywords_index );
|
||||
}
|
||||
|
||||
$csv .= PHP_EOL;
|
||||
}
|
||||
|
||||
return $csv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CSV column, including comma, from the result object based on the specified key
|
||||
*
|
||||
* @param array $result The result object.
|
||||
* @param string $key The key of the value to get the CSV column for.
|
||||
* @param int $keywords_index The number keyword to output.
|
||||
*
|
||||
* @return string CSV formatted column.
|
||||
*/
|
||||
protected function get_csv_column_from_result( array $result, $key, $keywords_index ) {
|
||||
if ( in_array( $key, [ 'title', 'url', 'seo_title', 'meta_description', 'readability_score' ], true ) ) {
|
||||
return $this->get_csv_string_column_from_result( $result, $key );
|
||||
}
|
||||
|
||||
if ( in_array( $key, [ 'keywords', 'keywords_score' ], true ) ) {
|
||||
return $this->get_csv_array_column_from_result( $result, $key, $keywords_index );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array from the result object.
|
||||
*
|
||||
* @param array $result The result object.
|
||||
* @param string $key The key of the array to retrieve.
|
||||
*
|
||||
* @return array Contents of the key in the object.
|
||||
*/
|
||||
protected function get_array_from_result( array $result, $key ) {
|
||||
if ( array_key_exists( $key, $result ) && is_array( $result[ $key ] ) ) {
|
||||
return $result[ $key ];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CSV column, including comma, from the result object by the specified key.
|
||||
* Expects the value to be a string.
|
||||
*
|
||||
* @param array $result The result object to get the CSV column from.
|
||||
* @param string $key The key of the value to get the CSV column for.
|
||||
*
|
||||
* @return string A CSV formatted column.
|
||||
*/
|
||||
protected function get_csv_string_column_from_result( array $result, $key ) {
|
||||
if ( array_key_exists( $key, $result ) ) {
|
||||
return ',' . $this->sanitize_csv_column( $result[ $key ] );
|
||||
}
|
||||
|
||||
return ',';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CSV column, including comma, from the result object by the specified key.
|
||||
* Expects the value to be inside an array.
|
||||
*
|
||||
* @param array $result The result object to get the CSV column from.
|
||||
* @param string $key The key of the array to get the CSV column for.
|
||||
* @param int $index The index of the value in the array.
|
||||
*
|
||||
* @return string A CSV formatted column.
|
||||
*/
|
||||
protected function get_csv_array_column_from_result( array $result, $key, $index ) {
|
||||
// If the array has an element at $index.
|
||||
if ( $index < count( $result[ $key ] ) ) {
|
||||
return ',' . $this->sanitize_csv_column( $result[ $key ][ $index ] );
|
||||
}
|
||||
|
||||
return ',';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a value to be output as a CSV value.
|
||||
*
|
||||
* @param string $value The value to sanitize.
|
||||
*
|
||||
* @return string The sanitized value.
|
||||
*/
|
||||
protected function sanitize_csv_column( $value ) {
|
||||
// Return an empty string if value is null.
|
||||
if ( $value === null ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Convert non-string values to strings.
|
||||
if ( ! is_string( $value ) ) {
|
||||
$value = var_export( $value, true );
|
||||
}
|
||||
|
||||
// Replace all whitespace with spaces because Excel can't deal with newlines and tabs even if escaped.
|
||||
$value = preg_replace( '/\s/', ' ', $value );
|
||||
|
||||
// Escape double quotes.
|
||||
$value = str_replace( '"', '""', $value );
|
||||
|
||||
// Return the value enclosed in double quotes.
|
||||
return '"' . $value . '"';
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WPSEO Premium plugin file.
|
||||
*
|
||||
* @package WPSEO\Premium\Classes\Export
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Export_Keywords_Post_Presenter
|
||||
*
|
||||
* Readies data as returned by WPSEO_Export_Keywords_Post_Query for exporting.
|
||||
*/
|
||||
class WPSEO_Export_Keywords_Post_Presenter implements WPSEO_Export_Keywords_Presenter {
|
||||
|
||||
/**
|
||||
* The columns to query for.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $columns;
|
||||
|
||||
/**
|
||||
* WPSEO_Export_Keywords_Post_Presenter constructor.
|
||||
*
|
||||
* Supported values for columns are 'title', 'url', 'keywords', 'readability_score' and 'keywords_score'.
|
||||
* Requesting 'keywords_score' will always also return 'keywords'.
|
||||
*
|
||||
* @param array $columns The columns we want our query to return.
|
||||
*/
|
||||
public function __construct( array $columns ) {
|
||||
$this->columns = array_filter( $columns, 'is_string' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a presentable result by modifying and adding the requested fields.
|
||||
*
|
||||
* @param array $result The result to modify.
|
||||
*
|
||||
* @return array The modified result or an empty array if the result is considered invalid.
|
||||
*/
|
||||
public function present( array $result ) {
|
||||
if ( ! $this->validate_result( $result ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ( $this->columns as $column ) {
|
||||
$result = $this->prepare_column_result( $result, $column );
|
||||
}
|
||||
|
||||
$result['type'] = $result['post_type'];
|
||||
unset( $result['post_type'] );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the passed result to make it more presentable.
|
||||
*
|
||||
* @param array $result The result to modify.
|
||||
* @param string $column The requested column.
|
||||
*
|
||||
* @return array The prepared result.
|
||||
*/
|
||||
protected function prepare_column_result( array $result, $column ) {
|
||||
switch ( $column ) {
|
||||
case 'title':
|
||||
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Using WP native filter.
|
||||
$result['title'] = apply_filters( 'the_title', $result['post_title'], $result['ID'] );
|
||||
unset( $result['post_title'] );
|
||||
break;
|
||||
case 'url':
|
||||
$result['url'] = get_permalink( $result['ID'] );
|
||||
break;
|
||||
case 'readability_score':
|
||||
$result['readability_score'] = WPSEO_Rank::from_numeric_score( (int) $result['readability_score'] )->get_label();
|
||||
break;
|
||||
case 'keywords':
|
||||
$result = $this->convert_result_keywords( $result );
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a result to present is a valid result.
|
||||
*
|
||||
* @param array $result The result to validate.
|
||||
*
|
||||
* @return bool True for a value valid result.
|
||||
*/
|
||||
protected function validate_result( array $result ) {
|
||||
// If there is no ID then it's not valid.
|
||||
if ( ! array_key_exists( 'ID', $result ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a title is requested but not present then it's not valid.
|
||||
if ( $this->column_is_present( 'title' ) && $this->has_title( $result ) === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the result contains a valid title.
|
||||
*
|
||||
* @param array $result The result array to check for a title.
|
||||
*
|
||||
* @return bool Whether or not a title is valid.
|
||||
*/
|
||||
protected function has_title( $result ) {
|
||||
if ( ! is_array( $result ) || ! array_key_exists( 'post_title', $result ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_string( $result['post_title'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the wanted column exists within the $this->columns class variable.
|
||||
*
|
||||
* @param string $column The column to search for.
|
||||
*
|
||||
* @return bool Whether or not the column exists.
|
||||
*/
|
||||
protected function column_is_present( $column ) {
|
||||
if ( ! is_string( $column ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array( $column, $this->columns, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the results of the query from strings and JSON string to keyword arrays.
|
||||
*
|
||||
* @param array $result The result to convert.
|
||||
*
|
||||
* @return array The converted result.
|
||||
*/
|
||||
protected function convert_result_keywords( array $result ) {
|
||||
$result['keywords'] = [];
|
||||
|
||||
if ( $this->column_is_present( 'keywords_score' ) ) {
|
||||
$result['keywords_score'] = [];
|
||||
}
|
||||
|
||||
if ( $this->has_primary_keyword( $result ) ) {
|
||||
$result['keywords'][] = $result['primary_keyword'];
|
||||
|
||||
// Convert multiple keywords from the Premium plugin from json to string arrays.
|
||||
$keywords = $this->parse_result_keywords_json( $result, 'other_keywords' );
|
||||
|
||||
$other_keywords = wp_list_pluck( $keywords, 'keyword' );
|
||||
$result['keywords'] = array_merge( $result['keywords'], $other_keywords );
|
||||
|
||||
if ( $this->column_is_present( 'keywords_score' ) ) {
|
||||
$result['keywords_score'] = $this->get_result_keywords_scores( $result, $keywords );
|
||||
}
|
||||
}
|
||||
|
||||
// Unset all old variables, if they do not exist nothing will happen.
|
||||
unset( $result['primary_keyword'], $result['primary_keyword_score'], $result['other_keywords'] );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether there's a valid primary keyword present in the result array.
|
||||
*
|
||||
* @param array $result The result array to check for the primary_keyword key.
|
||||
*
|
||||
* @return bool Whether or not a valid primary keyword is present.
|
||||
*/
|
||||
protected function has_primary_keyword( $result ) {
|
||||
if ( ! is_array( $result ) || ! array_key_exists( 'primary_keyword', $result ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_string( $result['primary_keyword'] ) && ! empty( $result['primary_keyword'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses then keywords JSON string in the result object for the specified key.
|
||||
*
|
||||
* @param array $result The result object.
|
||||
* @param string $key The key containing the JSON.
|
||||
*
|
||||
* @return array The parsed keywords.
|
||||
*/
|
||||
protected function parse_result_keywords_json( array $result, $key ) {
|
||||
if ( empty( $result[ $key ] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$parsed = json_decode( $result[ $key ], true );
|
||||
|
||||
if ( ! $parsed ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all scores from the result object and the parsed keywords JSON.
|
||||
*
|
||||
* @param array $result The result object.
|
||||
* @param array $keywords The parsed keywords.
|
||||
*
|
||||
* @return array The keyword scores.
|
||||
*/
|
||||
protected function get_result_keywords_scores( array $result, $keywords ) {
|
||||
$scores = [];
|
||||
|
||||
$rank = WPSEO_Rank::from_numeric_score( (int) $result['primary_keyword_score'] );
|
||||
$scores[] = $rank->get_label();
|
||||
|
||||
foreach ( $keywords as $keyword ) {
|
||||
if ( isset( $keyword['score'] ) ) {
|
||||
$rank = new WPSEO_Rank( $keyword['score'] );
|
||||
$scores[] = $rank->get_label();
|
||||
}
|
||||
}
|
||||
|
||||
return $scores;
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WPSEO Premium plugin file.
|
||||
*
|
||||
* @package WPSEO\Premium\Classes\Export
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Export_Keywords_Post_Query
|
||||
*
|
||||
* Creates an SQL query to gather all post data for a keywords export.
|
||||
*/
|
||||
class WPSEO_Export_Keywords_Post_Query implements WPSEO_Export_Keywords_Query {
|
||||
|
||||
/**
|
||||
* The columns to query for.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $columns;
|
||||
|
||||
/**
|
||||
* The database columns to select in the query.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $selects;
|
||||
|
||||
/**
|
||||
* The database tables to join in the query.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $joins = [];
|
||||
|
||||
/**
|
||||
* Number of items to fetch per page.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $page_size;
|
||||
|
||||
/**
|
||||
* Escaped list of post types.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $escaped_post_types;
|
||||
|
||||
/**
|
||||
* WPSEO_Export_Keywords_Query constructor.
|
||||
*
|
||||
* Supported values for columns are 'title', 'url', 'keywords', 'readability_score' and 'keywords_score'.
|
||||
* Requesting 'keywords_score' will always also return 'keywords'.
|
||||
*
|
||||
* @param array $columns List of columns that need to be retrieved.
|
||||
* @param int $page_size Number of items to retrieve.
|
||||
*/
|
||||
public function __construct( array $columns, $page_size = 1000 ) {
|
||||
$this->page_size = max( 1, (int) $page_size );
|
||||
|
||||
$this->set_columns( $columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the query and executes it, returning an array of objects containing the columns this object was
|
||||
* constructed with. Every object will always contain the ID column.
|
||||
*
|
||||
* @param int $page Paginated page to retrieve.
|
||||
*
|
||||
* @return array An array of associative arrays containing the keys as requested in the constructor.
|
||||
*/
|
||||
public function get_data( $page = 1 ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $this->columns === [] ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$post_types = WPSEO_Post_Type::get_accessible_post_types();
|
||||
if ( empty( $post_types ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Pages have a starting index of 1, we need to convert to a 0 based offset.
|
||||
$offset_multiplier = max( 0, ( $page - 1 ) );
|
||||
|
||||
$replacements = [];
|
||||
$replacements[] = $wpdb->posts;
|
||||
$replacements[] = 'post_status';
|
||||
$replacements[] = 'post_type';
|
||||
$replacements = array_merge( $replacements, $post_types );
|
||||
$replacements[] = $this->page_size;
|
||||
$replacements[] = ( $offset_multiplier * $this->page_size );
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnsupportedPlaceholder,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Already prepared, and no cache applicable.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
'SELECT ' . implode( ', ', $this->selects )
|
||||
. ' FROM %i AS posts '
|
||||
. implode( ' ', $this->joins )
|
||||
. ' WHERE posts.%i = "publish" AND posts.%i IN ('
|
||||
. implode( ',', array_fill( 0, count( $post_types ), '%s' ) ) . ')'
|
||||
. ' LIMIT %d OFFSET %d',
|
||||
$replacements
|
||||
),
|
||||
ARRAY_A
|
||||
);
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the necessary selects and joins to get all data in a single query.
|
||||
*
|
||||
* @param array $columns The columns we want our query to return.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_columns( array $columns ) {
|
||||
$this->columns = $columns;
|
||||
|
||||
$this->joins = [];
|
||||
$this->selects = [ 'posts.ID', 'posts.post_type' ];
|
||||
|
||||
if ( in_array( 'title', $this->columns, true ) ) {
|
||||
$this->selects[] = 'posts.post_title';
|
||||
}
|
||||
|
||||
// If we're selecting keywords_score then we always want the keywords as well.
|
||||
if ( in_array( 'keywords', $this->columns, true ) || in_array( 'keywords_score', $this->columns, true ) ) {
|
||||
$this->add_meta_join( 'primary_keyword', WPSEO_Meta::$meta_prefix . 'focuskw' );
|
||||
$this->add_meta_join( 'other_keywords', WPSEO_Meta::$meta_prefix . 'focuskeywords' );
|
||||
}
|
||||
|
||||
if ( in_array( 'readability_score', $this->columns, true ) ) {
|
||||
$this->add_meta_join( 'readability_score', WPSEO_Meta::$meta_prefix . 'content_score' );
|
||||
}
|
||||
|
||||
if ( in_array( 'keywords_score', $this->columns, true ) ) {
|
||||
// Score for other keywords is already in the other_keywords select so only join for the primary_keyword_score.
|
||||
$this->add_meta_join( 'primary_keyword_score', WPSEO_Meta::$meta_prefix . 'linkdex' );
|
||||
}
|
||||
|
||||
if ( in_array( 'seo_title', $this->columns, true ) ) {
|
||||
$this->add_meta_join( 'seo_title', WPSEO_Meta::$meta_prefix . 'title' );
|
||||
}
|
||||
|
||||
if ( in_array( 'meta_description', $this->columns, true ) ) {
|
||||
$this->add_meta_join( 'meta_description', WPSEO_Meta::$meta_prefix . 'metadesc' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page size for the query.
|
||||
*
|
||||
* @return int Page size that is being used.
|
||||
*/
|
||||
public function get_page_size() {
|
||||
return $this->page_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an aliased join to the $wpdb->postmeta table so that multiple meta values can be selected in a single row.
|
||||
*
|
||||
* While this function should never be used with user input,
|
||||
* all non-word non-digit characters are removed from both params for increased robustness.
|
||||
*
|
||||
* @param string $alias The alias to use in our query output.
|
||||
* @param string $key The meta_key to select.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function add_meta_join( $alias, $key ) {
|
||||
global $wpdb;
|
||||
$alias = preg_replace( '/[^\w\d]/', '', $alias );
|
||||
$key = preg_replace( '/[^\w\d]/', '', $key );
|
||||
|
||||
$this->selects[] = $alias . '_join.meta_value AS ' . $alias;
|
||||
$this->joins[] = 'LEFT OUTER JOIN ' . $wpdb->prefix . 'postmeta AS ' . $alias . '_join '
|
||||
. 'ON ' . $alias . '_join.post_id = posts.ID '
|
||||
. 'AND ' . $alias . '_join.meta_key = "' . $key . '"';
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WPSEO Premium plugin file.
|
||||
*
|
||||
* @package WPSEO\Premium\Classes\Export
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface WPSEO_Export_Keywords_Presenter
|
||||
*
|
||||
* Readies data as returned by WPSEO_Export_Keywords_Query for exporting.
|
||||
*/
|
||||
interface WPSEO_Export_Keywords_Presenter {
|
||||
|
||||
/**
|
||||
* WPSEO_Export_Keywords_Presenter constructor.
|
||||
*
|
||||
* Supported values for columns are 'title', 'url', 'keywords', 'readability_score' and 'keywords_score'.
|
||||
* Requesting 'keywords_score' will always also return 'keywords'.
|
||||
*
|
||||
* @param array $columns The columns we want our query to return.
|
||||
*/
|
||||
public function __construct( array $columns );
|
||||
|
||||
/**
|
||||
* Updates a result by modifying and adding the requested fields.
|
||||
*
|
||||
* @param array $result The result to modify.
|
||||
*
|
||||
* @return array The modified result.
|
||||
*/
|
||||
public function present( array $result );
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WPSEO Premium plugin file.
|
||||
*
|
||||
* @package WPSEO\Premium\Classes\Export
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface WPSEO_Export_Keywords_Query
|
||||
*
|
||||
* Creates a SQL query to gather all data for a keywords export.
|
||||
*/
|
||||
interface WPSEO_Export_Keywords_Query {
|
||||
|
||||
/**
|
||||
* Returns the page size for the query.
|
||||
*
|
||||
* @return int Page size that is being used.
|
||||
*/
|
||||
public function get_page_size();
|
||||
|
||||
/**
|
||||
* Constructs the query and executes it, returning an array of objects containing the columns this object was constructed with.
|
||||
* Every object will always contain the ID column.
|
||||
*
|
||||
* @param int $page Paginated page to retrieve.
|
||||
*
|
||||
* @return array An array of associative arrays containing the keys as requested in the constructor.
|
||||
*/
|
||||
public function get_data( $page = 1 );
|
||||
|
||||
/**
|
||||
* Prepares the necessary selects and joins to get all data in a single query.
|
||||
*
|
||||
* @param array $columns The columns we want our query to return.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_columns( array $columns );
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WPSEO Premium plugin file.
|
||||
*
|
||||
* @package WPSEO\Premium\Classes\Export
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Export_Keywords_Term_Presenter
|
||||
*
|
||||
* Readies data as returned by WPSEO_Export_Keywords_Term_Query for exporting.
|
||||
*/
|
||||
class WPSEO_Export_Keywords_Term_Presenter implements WPSEO_Export_Keywords_Presenter {
|
||||
|
||||
/**
|
||||
* The columns to query for.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $columns;
|
||||
|
||||
/**
|
||||
* WPSEO_Export_Keywords_Term_Presenter constructor.
|
||||
*
|
||||
* Supported values for columns are 'title', 'url', 'keywords', 'readability_score' and 'keywords_score'.
|
||||
* Requesting 'keywords_score' will always also return 'keywords'.
|
||||
*
|
||||
* @param array $columns The columns we want our query to return.
|
||||
*/
|
||||
public function __construct( array $columns ) {
|
||||
$this->columns = array_filter( $columns, 'is_string' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a presentable result by modifying and adding the requested fields.
|
||||
*
|
||||
* @param array $result The result to modify.
|
||||
*
|
||||
* @return array The modified result or an empty array if the result is considered invalid.
|
||||
*/
|
||||
public function present( array $result ) {
|
||||
if ( ! $this->validate_result( $result ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$result['ID'] = (int) $result['term_id'];
|
||||
unset( $result['term_id'] );
|
||||
|
||||
foreach ( $this->columns as $column ) {
|
||||
$result = $this->prepare_column_result( $result, $column );
|
||||
}
|
||||
|
||||
$result['type'] = $result['taxonomy'];
|
||||
unset( $result['taxonomy'] );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the passed result to make it more presentable.
|
||||
*
|
||||
* @param array $result The result to modify.
|
||||
* @param string $column The requested column.
|
||||
*
|
||||
* @return array The prepared result.
|
||||
*/
|
||||
protected function prepare_column_result( array $result, $column ) {
|
||||
switch ( $column ) {
|
||||
case 'keywords':
|
||||
$result['keywords'] = $this->get_result_keywords( $result );
|
||||
break;
|
||||
case 'keywords_score':
|
||||
$result['keywords_score'] = $this->get_result_keywords_score( $result );
|
||||
break;
|
||||
case 'url':
|
||||
$result['url'] = get_term_link( $result['ID'], $result['taxonomy'] );
|
||||
break;
|
||||
case 'title':
|
||||
$result['title'] = $result['name'];
|
||||
unset( $result['name'] );
|
||||
break;
|
||||
case 'seo_title':
|
||||
$result['seo_title'] = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'title' );
|
||||
break;
|
||||
case 'meta_description':
|
||||
$result['meta_description'] = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'desc' );
|
||||
break;
|
||||
case 'readability_score':
|
||||
$content_score = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'content_score' );
|
||||
$result['readability_score'] = WPSEO_Rank::from_numeric_score( (int) $content_score )->get_label();
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a result to present is a valid result.
|
||||
*
|
||||
* @param array $result The result to validate.
|
||||
*
|
||||
* @return bool True if the result is validated.
|
||||
*/
|
||||
protected function validate_result( array $result ) {
|
||||
// If there is no ID then it's not valid.
|
||||
if ( ! array_key_exists( 'term_id', $result ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a title is requested but not present then it's not valid.
|
||||
if ( $this->column_is_present( 'title' ) && $this->has_title( $result ) === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the result contains a valid title.
|
||||
*
|
||||
* @param array $result The result array to check for a title.
|
||||
*
|
||||
* @return bool Whether or not a title is valid.
|
||||
*/
|
||||
protected function has_title( $result ) {
|
||||
if ( ! is_array( $result ) || ! array_key_exists( 'name', $result ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_string( $result['name'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the wanted column exists within the $this->columns class variable.
|
||||
*
|
||||
* @param string $column The column to search for.
|
||||
*
|
||||
* @return bool Whether or not the column exists.
|
||||
*/
|
||||
protected function column_is_present( $column ) {
|
||||
if ( ! is_string( $column ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array( $column, $this->columns, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result keywords from WPSEO_Taxonomy_Meta.
|
||||
*
|
||||
* @param array $result The result to get the keywords for.
|
||||
*
|
||||
* @return array The keywords.
|
||||
*/
|
||||
protected function get_result_keywords( array $result ) {
|
||||
$keyword = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'focuskw' );
|
||||
|
||||
if ( $keyword === false || empty( $keyword ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [ (string) $keyword ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result keyword scores from WPSEO_Taxonomy_Meta.
|
||||
*
|
||||
* @param array $result The result to get the keyword scores for.
|
||||
*
|
||||
* @return array The keyword scores.
|
||||
*/
|
||||
protected function get_result_keywords_score( array $result ) {
|
||||
$keyword_score = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'linkdex' );
|
||||
|
||||
if ( $keyword_score === false || empty( $keyword_score ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$keyword_score_label = WPSEO_Rank::from_numeric_score( (int) $keyword_score )->get_label();
|
||||
|
||||
return [ $keyword_score_label ];
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WPSEO Premium plugin file.
|
||||
*
|
||||
* @package WPSEO\Premium\Classes\Export
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Export_Keywords_Term_Query
|
||||
*
|
||||
* Creates an SQL query to gather all term data for a keywords export.
|
||||
*/
|
||||
class WPSEO_Export_Keywords_Term_Query implements WPSEO_Export_Keywords_Query {
|
||||
|
||||
/**
|
||||
* The columns to query for, an array of strings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $columns;
|
||||
|
||||
/**
|
||||
* The database columns to select in the query, an array of strings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $selects;
|
||||
|
||||
/**
|
||||
* Number of items to fetch per page.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $page_size;
|
||||
|
||||
/**
|
||||
* WPSEO_Export_Keywords_Query constructor.
|
||||
*
|
||||
* Supported values for columns are 'title', 'url', 'keywords', 'readability_score' and 'keywords_score'.
|
||||
* Requesting 'keywords_score' will always also return 'keywords'.
|
||||
*
|
||||
* @param array $columns List of columns that need to be retrieved.
|
||||
* @param int $page_size Number of items to retrieve.
|
||||
*/
|
||||
public function __construct( array $columns, $page_size = 1000 ) {
|
||||
$this->page_size = max( 1, (int) $page_size );
|
||||
$this->set_columns( $columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page size for the query.
|
||||
*
|
||||
* @return int Page size that is being used.
|
||||
*/
|
||||
public function get_page_size() {
|
||||
return $this->page_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the query and executes it, returning an array of objects containing the columns this object was constructed with.
|
||||
* Every object will always contain the ID column.
|
||||
*
|
||||
* @param int $page Paginated page to retrieve.
|
||||
*
|
||||
* @return array An array of associative arrays containing the keys as requested in the constructor.
|
||||
*/
|
||||
public function get_data( $page = 1 ) {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if ( $this->columns === [] ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$taxonomies = get_taxonomies(
|
||||
[
|
||||
'public' => true,
|
||||
'show_ui' => true,
|
||||
],
|
||||
'names'
|
||||
);
|
||||
|
||||
if ( empty( $taxonomies ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Pages have a starting index of 1, we need to convert to a 0 based offset.
|
||||
$offset_multiplier = max( 0, ( $page - 1 ) );
|
||||
|
||||
$replacements = [];
|
||||
$replacements[] = $wpdb->terms;
|
||||
$replacements[] = $wpdb->term_taxonomy;
|
||||
$replacements[] = 'term_id';
|
||||
$replacements[] = 'term_id';
|
||||
$replacements[] = 'taxonomy';
|
||||
$replacements = array_merge( $replacements, $taxonomies );
|
||||
$replacements[] = $this->page_size;
|
||||
$replacements[] = ( $offset_multiplier * $this->page_size );
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnsupportedPlaceholder,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Already prepared, and no cache applicable.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
'SELECT ' . implode( ', ', $this->selects )
|
||||
. ' FROM %i AS terms'
|
||||
. ' INNER JOIN %i AS taxonomies'
|
||||
. ' ON terms.%i = taxonomies.%i AND taxonomies.%i IN ('
|
||||
. implode( ',', array_fill( 0, count( $taxonomies ), '%s' ) ) . ')'
|
||||
. ' LIMIT %d OFFSET %d',
|
||||
$replacements
|
||||
),
|
||||
ARRAY_A
|
||||
);
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the necessary selects and joins to get all data in a single query.
|
||||
*
|
||||
* @param array $columns The columns we want our query to return.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_columns( array $columns ) {
|
||||
$this->columns = $columns;
|
||||
|
||||
$this->selects = [ 'terms.term_id', 'taxonomies.taxonomy' ];
|
||||
|
||||
if ( in_array( 'title', $this->columns, true ) ) {
|
||||
$this->selects[] = 'terms.name';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user