Skip to content

Instantly share code, notes, and snippets.

@JayWood
Created September 10, 2018 11:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JayWood/e7301489b082b8c973368b77cb969c9c to your computer and use it in GitHub Desktop.
Save JayWood/e7301489b082b8c973368b77cb969c9c to your computer and use it in GitHub Desktop.
A tool to provide reports for short-codes created.
<?php
namespace JW\CLI;
use WP_CLI;
use WP_CLI_Command;
/**
* A shortcode scraper class.
*/
class Shortcode_Scraper extends WP_CLI_Command {
private $args = [];
private $assoc_args = [];
private $progress_bar;
private $site = false;
/**
* Scrapes post content and provides a list of shortcodes that are in use.
*
* # OPTIONS
*
* [--export]
* : Exports the results to a CSV file.
*
* [--site=<slug>]
* : The site to query
*/
public function scrape( $args, $assoc_args ) {
$this->args = $args;
$this->assoc_args = $assoc_args;
// Rather or not to export the results.
$export = isset( $assoc_args['export'] );
$this->site = isset( $assoc_args['site'] ) ? $assoc_args['site'] : false;
if ( $this->site ) {
$blog_details = get_blog_details( $this->site );
if ( ! $blog_details ) {
WP_CLI::error( sprintf( 'Getting blog details for %s failed', $site ) );
}
switch_to_blog( $blog_details->blog_id );
}
/*
* Grab all posts
* check for shortcodes
* grab parameters in use for shortcode
* display results
* export results
*/
// Use these to store some arrays.
$results = [];
// Process the post results.
$multiplier = 0;
while ( $posts = $this->query_posts( $multiplier ) ) {
$this->progress_bar( count( $posts ), 'Post Objects', 'Processing' );
$this->process_posts( $posts, $results );
$this->progress_bar( 'finish' );
$multiplier++;
};
WP_CLI\Utils\format_items( 'table', $results, array( 'post_id', 'post_name', 'shortcode', 'parameters_raw' ) );
if ( $export ) {
try {
$date = current_time( 'Y-m-d' );
if ( $this->site ) {
$date = $this->site . '-' . $date;
}
$file = fopen( dirname( __FILE__ ) . '/shortcode-scrape-' . $date . '.csv', 'w' );
// Remove array data.
unset( $results['parameters_raw'] );
fputcsv( $file, array_keys( $results[0] ) );
foreach ( $results as $result ) {
fputcsv( $file, $result );
}
fclose( $file );
} catch ( \Exception $e ) {
WP_CLI::error( 'Error running export method: ' . $e->getMessage() );
}
}
// Display the table.
// output results
}
/**
* A simple SQL loopable query for pages and posts.
*
* @param int $multiplier The multiplier for batch processing
*
* @return false|array Array of objects on success, null otherwise.
*
* @author JayWood
* @since NEXT
*/
private function query_posts( $multiplier = 0 ) {
global $wpdb;
$sql_query = "
SELECT ID,post_name,post_content
FROM {$wpdb->posts}
WHERE post_status = %s
AND post_type IN ( %s, %s )
LIMIT 100 OFFSET %d
";
$sql_query = $wpdb->prepare( $sql_query, 'publish', 'post', 'page', ( $multiplier * 100 ) ); // @codingStandardsIgnoreLine Code is provided above.
$result_set = $wpdb->get_results( $sql_query );
return count( $result_set ) > 0 ? $result_set : false; // @codingStandardsIgnoreLine Code is sanitized above.
}
/**
* Processes posts queried by the database.
*
* @param array $posts Array of post objects
* @param array $results Passing by reference, an array of results to append to/modify.
*
* @return void
*
* @author JayWood
* @since NEXT
*/
private function process_posts( $posts, &$results ) {
$regex = '/\[([a-zA-Z0-9_-]+) ([^\]]+)/';
// $atts = get_shortcode_atts_regex();
foreach ( $posts as $post_data ) {
$this->progress_bar( 'tick' );
// Skip if we do not have post content.
if ( empty( $post_data->post_content ) ) {
continue;
}
preg_match_all( $regex, $post_data->post_content, $shortcodes );
$shortcodes = array_filter( $shortcodes );
if ( empty( $shortcodes ) || empty( $shortcodes[1] ) ) {
continue;
}
$shortcode_strings = $shortcodes[1];
$shortcode_parameters = empty( $shortcodes[2] ) ? array() : $shortcodes[2];
foreach ( $shortcode_parameters as $key => $value ) {
$shortcode_parameters[ $key ] = shortcode_parse_atts( $value );
}
$codes = array_combine( $shortcode_strings, $shortcode_parameters );
// Loop over and format codes for the results array now.
foreach ( $codes as $shortcode => $parameters ) {
$results[] = array(
'post_id' => $post_data->ID,
'shortcode' => $shortcode,
'post_name' => $post_data->post_name,
'parameters' => $this->format_params( $parameters ),
'parameters_raw' => $parameters,
);
}
} // End foreach().
}
/**
* Formats parameters into a readable output for the CSV.
*
* @param string $parameters
*
* @return string
*
* @author JayWood
* @since NEXT
*/
private function format_params( $parameters = '' ) {
if ( empty( $parameters ) || ! is_array( $parameters ) ) {
return '';
}
$out = [];
foreach ( $parameters as $k => $v ) {
if ( is_int( $k ) ) {
$out[] = $v;
} else {
$out[] = sprintf( '%1$s: %2$s', $k, $v );
}
}
return implode( "\r\n", $out );
}
/**
* Wrapper function for WP_CLI Progress bar
*
* @param int|string $param If integer, start progress bar, if string, should be tick or finish.
* @param string $object_type Type of object being traversed
* @param string $action Action being performed
*
* @return bool|object False on failure, WP_CLI progress bar object otherwise.
*/
private function progress_bar( $param, $object_type = '', $action = 'Migrating' ) {
if ( $param && is_numeric( $param ) ) {
$this->progress_bar = \WP_CLI\Utils\make_progress_bar( "$action $param $object_type.", $param );
} elseif ( ( $this->progress_bar && 'tick' == $param ) && method_exists( $this->progress_bar, 'tick' ) ) {
$this->progress_bar->tick();
} elseif ( ( $this->progress_bar && 'finish' == $param ) && method_exists( $this->progress_bar, 'finish' ) ) {
$this->progress_bar->finish();
}
return $this->progress_bar;
}
}
WP_CLI::add_command( 'jw-shortcode-scraper', __NAMESPACE__ . '\Shortcode_Scraper' );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment