File "SWP_Post_Cache.php"
Full Path: /home/bfxleof/www/wp-content/plugins/social-warfare/lib/utilities/SWP_Post_Cache.php
File size: 33.62 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* The Post_Cache Object
*
* This class will control the cached data for each individual post across a
* WordPress website. Direct calls for data such as share counts, will pull and
* return cached data.
*
* Since all Post_Cache objects should be loaded via the Post_Cache_Loader class,
* we will use the instantiation method (__construct) to queue up asyncronous
* methods for rebuilding cached data. This should allow us to run that subset
* of functions only once per page load, and then the cache will once again be
* fresh for a few hours before we need to do it again.
*
* This class contains four major sections of methods:
* 1. Set up the cache object and necessary properties.
* 2. Check if the cache is fresh or not.
* 3. Update the cached data when the cache is expired.
* 4. Allow a publicly accessable method for fetching cached counts.
*
* @package SocialWarfare\Functions\Utilities
* @copyright Copyright (c) 2018, Warfare Plugins, LLC
* @license GPL-3.0+
* @since 3.1.0 | 20 JUN 2018 | Created
* @access public
*
*/
class SWP_Post_Cache {
/**
* SWP_Debug_Trait provides useful tool like error handling and a debug
* method which outputs the contents of the current object.
*
*/
use SWP_Debug_Trait;
/**
* SECTION #1: SETTING UP THE CACHE OBJECT
*
* The methods in this section are used to set up the cache object by
* initializing the object, setting up local properties, and pulling in the
* global $post object that will be used throughout the class.
*
*/
/**
* The WordPress Post Object
*
* @see $this->establish_post_data() method.
* @var object
*
*/
public $post;
/**
* The ID of the Current Post Being Processed
*
* @see $this->establish_post_data() method.
* @var integer
*
*/
public $id;
/**
* The Magic Construct Method
*
* This method 1.) instantiates the object
* making the public methods available for use by the plugin, and
* 2.) Determine if the cache is fresh, and if not, trigger an
* asyncronous request to rebuild the cached data.
*
* @todo Can we eliminate all post data except for the post_id?
* @since 3.1.0 | 20 JUN 2018 | Created
* @param integer $post_id The ID of the post
* @return void
*
*/
public function __construct( $post_id ) {
// Set up the post data into local properties.
$this->post_id = $post_id;
$this->establish_share_counts();
// If the cache is expired, trigger the rebuild processes.
if ( false === $this->is_cache_fresh() ){
$this->rebuild_cached_data();
}
// Debugging
add_action( 'wp_footer', array( $this, 'debug' ) );
}
/**
* SECTION #2: CHECKING IF THE CACHE IS FRESH
*
* The methods in this section are used to determine whether or not the
* cached data needs to be rebuilt or not.
*
*/
/**
* Determines if the data has recently been updated.
*
* This is the determining method to decide if a cache is fresh or if it
* needs to be rebuilt.
*
* @since 3.1.0 | 19 JUN 2018 | Ported from function to class method.
* @access public
* @param void
* @return boolean True if fresh, false if expired and needs rebuilt.
*
*/
public function is_cache_fresh() {
// Bail early if it's a crawl bot. If so, ONLY SERVE CACHED RESULTS FOR MAXIMUM SPEED.
if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && preg_match( '/bot|crawl|slurp|spider/i', wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) ) :
return true;
endif;
// Always be true if we're not a single post.
if ( !is_singular() && !is_admin() ) :
return true;
endif;
// If a URL parameter is specifically telling it to rebuild.
if ( isset( $_GET['swp_cache'] ) && 'rebuild' === $_GET['swp_cache'] ) {
return false;
}
// If a POST request (AJAX) is specifically telling it to rebuild.
if( isset( $_POST['swp_cache'] ) && 'rebuild' === $_POST['swp_cache'] ) {
return false;
}
// Check if the cache is older than is allowable for this post.
if( $this->get_cache_age() >= $this->get_allowable_age() ):
return false;
endif;
return true;
}
/**
* Determines how recently, in hours, the cache has been updated.
*
* @since 3.1.0 | 19 JUN 2018 | Created the method.
* @todo Review
* @param void
* @return int The current age of the cache in hours.
*
*/
protected function get_cache_age() {
/**
* Fetch the current time and the time that the cache was last updated
* so that we can compare them to find out how old the cache is.
*
*/
$current_time = floor( ( ( date( 'U' ) / 60 ) / 60 ) );
$last_updated_time = get_post_meta( $this->post_id, 'swp_cache_timestamp', true );
/**
* If the meta field is empty or non-existent, get_post_meta() will
* return false. If it does, we'll simply convert it to an integer (0)
* so that we can use it in the mathematical comparisons.
*
*/
if ( false == is_numeric( $last_updated_time ) ) {
$last_updated_time = 0;
}
/**
* Compare the current time to the time the cache was last updated, and
* determine the age of the cache.
*
*/
$cache_age = $current_time - $last_updated_time;
return $cache_age;
}
/**
* Get the duration during which this cache can be considered fresh.
*
* A cache is fresh for the following durations:
* 1 Hour - New Posts less than 21 days old.
* 4 Hours - Medium Posts less than 60 days old.
* 12 Hours - Old Posts Older than 60 days old.
* 24 Hours - Share counts are disabled, but we still need to fetch
* periodically for the admin post column and popular posts
* widget to have data to puplate correctly.
*
* @since 3.1.0 | 20 JUN 2018 | Created
* @since 3.4.0 | Added check for share counts being active.
* @param void
* @return integer The duration in hours that applies to this cache.
*
*/
public function get_allowable_age() {
/**
* Don't fetch share counts very often if share counts are disabled both
* as totals and on the buttons. We will only fetch once in a while so
* that we can cache the data and use it for things like the popular
* posts calculations and the admin posts column.
*
*/
$network_shares = SWP_Utility::get_option( 'network_shares' );
$total_shares = SWP_Utility::get_option( 'total_shares' );
if( false == ( $network_shares || $total_shares ) ) {
return 24;
}
// Integer in hours of the current age of the post.
$current_time = floor( date( 'U' ) );
$publication_time = get_post_time( 'U' , false , $this->post_id );
$post_age = $current_time - $publication_time;
// If it's less than 3 days old.
if( $post_age < ( 3 * 86400 ) ) {
return 1;
}
// If it's less than 21 days old.
if( $post_age < ( 21 * 86400 ) ) {
return 3;
}
// If it's less than 60 days old.
if( $post_age < ( 60 * 86400 ) ) {
return 6;
}
// If it's really old.
return 24;
}
/**
* SECTION #3: REBUILDING THE CACHED DATA
*
* The methods in this section are used to rebuild all of the cached data.
*
*/
/**
* A method to rebuild all cached data
*
* This is the method that will be called during the rebuild. This is also
* the method that we want to run asyncronously. This method will call all
* other methods and run the action filter to allow third-party functions
* to run during the cache rebuild process.
*
* @since 3.1.0 | 20 JUN 2018 | Created
* @todo Move all calls to cache rebuild methods into this method. This
* will become the one and only method that is used to rebuild this
* particular cache of data.
* @param void
* @return void
*
*/
public function rebuild_cached_data() {
$this->update_image_cache( 'swp_pinterest_image' );
$this->update_image_cache( 'swp_og_image' );
// Don't run these methods unless the post is published.
if( true === $this->is_post_published() ) {
$this->rebuild_share_counts();
$this->process_urls();
$this->reset_timestamp();
// A hook to allow third-party functions to run.
do_action( 'swp_cache_rebuild', $this->post_id );
}
}
/**
* Should we fetch share counts for this post?
*
* This method controls which instances we should be fetching share counts
* and which instances whe shouldn't.
*
* @since 3.2.0 | 24 JUL 2018 | Created
* @param void
* @return bool True: fetch share counts; False: don't fetch counts.
*
*/
protected function is_post_published() {
// Only fetch on published posts
if( 'publish' !== get_post_status( $this->post_id ) ) {
$this->debug_message( 'No data updated. This post is not yet published.' );
return false;
}
return true;
}
/**
* Process the URLs for shortlinks, UTM, etc.
*
* @since 3.1.0 | 20 JUN 2018 | Created
* @param void
* @return void
*
*/
public function process_urls() {
global $swp_social_networks;
$permalink = get_permalink( $this->post_id );
foreach( $swp_social_networks as $network ) {
if( $network->is_active() ) {
SWP_Link_Manager::process_url( $permalink, $network->key, $this->post_id, false );
}
}
}
/**
* Store image url, id, and metadata in post_meta for quicker access later.
*
* @since 3.5.0 | 19 DEC 2018 | Merged old methods into this new method.
* @since 3.6.0 | 22 APR 2019 | Remvoed calls to delete the original field.
* @param string $meta_key The image field to update. Known examples include
* swp_og_image, swp_pinterest_image, swp_twitter_image
* @param int $new_id The attachment ID to update.
* @return void
*
*/
public function update_image_cache( $meta_key ) {
/**
* Fetch the ID of the image in question. We will use this to extrapalate
* the information that we need to prepopulate into the other fields.
*
*/
$new_id = SWP_Utility::get_meta( $this->post_id, $meta_key );
$old_data = SWP_Utility::get_meta_array( $this->post_id, $meta_key . '_data' );
/**
* The following two processes are designed to fix and restore the image
* from a bug that was either converting the field from and ID to an array
* or was deleting the field entirely in which case we restore it from
* the cached fields.
*
* RESTORE FIELD FROM CACHE
*
* If the field is empty, but we have the correct cached data, then
* let's repopulate the field from the cache. The empty field is most
* likely caused by the bug from 3.5.x that was deleting or altering
* the data in the field. This will restore it.
*
* RESTORE FIELD FROM ARRAY
*
* If the meta key was stored as an array, let's find the URL of the
* image, convert it back to the correct ID of said image, and store that
* back in the original meta field.
*
* This was caused by a bug in a previous version that was overwriting
* the ID in this field with the image_data array. This will fix that
* and restore the field to an ID.
*
*/
$restore_from_cache = empty( $new_id ) && is_array( $old_data ) && false !== filter_var( $old_data[0], FILTER_VALIDATE_URL );
$restore_from_array = is_array( $new_id ) && false !== filter_var( $new_id[0], FILTER_VALIDATE_URL );
/**
* Filter out requests from the admin so that this "fix" doesn't
* override the user's preference whilst they are updating a post.
*
* This block is for people who are missing a key like `swp_og_image`
* between v3.5.0 and v3.5.4. The logic below will create the missing
* key based off of data we have previously saved.
*
*/
if ( ($restore_from_cache || $restore_from_array) && !is_admin() ) {
// Convert the image URL into a valid WP ID.
if ( $restore_from_array ) {
$new_id = SWP_Utility::get_image_id_by_url( $new_id[0] );
} elseif ( $restore_from_cache ) {
$new_id = SWP_Utility::get_image_id_by_url( $old_data[0] );
}
// Bail if we didn't get an ID from the above function.
if ( empty( $new_id ) ) {
return;
}
// Delete and update the meta field with the corrected ID.
delete_post_meta( $this->post_id, $meta_key );
update_post_meta( $this->post_id, $meta_key, $new_id );
}
/**
* If there is no image ID from the meta field, we need to delete this
* and all related fields just in case there used to be an image but it
* was removed. Prior to deleting these fields, the Pinterest image
* URL and data generated here would persist after the image was
* deleted from the meta field.
*
*/
if ( empty( $new_id ) ) {
delete_post_meta( $this->post_id, $meta_key.'_data' );
delete_post_meta( $this->post_id, $meta_key.'_url' );
delete_post_meta( $this->post_id, $meta_key );
return;
}
/**
* Fetch the data array of the new image and the data array of the old
* previously cached image (fetchd above) so that we can see if anything
* has changed.
*
*/
$new_data = wp_get_attachment_image_src( $new_id, 'full_size' );
/**
* If the old data is the same as the new data, then there is no need to
* make any new database calls. Just exit and move on with our lives.
*
*/
if ( false == $new_data || $new_data === $old_data ) {
return;
}
/**
* We are not changing the value of the original field which contains
* the WordPress attachement ID of the image in question. We are,
* however, updating two additional fields (_data and _url) so that this
* data will be preloaded with the post load. We will delete them first
* to ensure that we never have more than one of the same field.
*
*/
delete_post_meta( $this->post_id, $meta_key.'_data' );
delete_post_meta( $this->post_id, $meta_key.'_url' );
update_post_meta( $this->post_id, $meta_key.'_data', json_encode( $new_data ) );
update_post_meta( $this->post_id, $meta_key.'_url', $new_data[0] );
}
/**
* Resets the cache timestamp to the current time in hours since Unix epoch.
*
* @since 3.1.0 | 19 JUN 2018 | Ported from function to class method.
* @access protected
* @param void
* @return void
*
*/
public function reset_timestamp() {
delete_post_meta( $this->post_id, 'swp_cache_timestamp' );
update_post_meta( $this->post_id, 'swp_cache_timestamp', floor( ( ( date( 'U' ) / 60 ) / 60 ) ) );
}
/**
* Removes the timestamp on certain hooks like when a post is updated.
*
* @since 3.1.0 | 19 JUN 2018 | Ported from function to class method.
* @param void
* @return void
*
*/
public function delete_timestamp() {
delete_post_meta( $this->post_id, 'swp_cache_timestamp' );
}
/**
* Finishes processing the share data after the network links have been set up.
*
* The flow of logic should look something like this:
* establish_permalinks(); $this->permalinks;
* establish_api_request_urls(); $this->api_urls;
* fetch_api_responses(); $this->raw_api_responses;
* parse_api_responses(); $this->parsed_api_responses;
* calculate_network_shares(); $this->share_counts;
* calculate_total_shares(); $this->share_counts['total_shares'];
* cache_share_counts(); Stored in DB post meta.
*
* @since 3.1.0 | 21 JUN 2018 | Created
* @access protected
* @param void
* @return void
*
*/
protected function rebuild_share_counts() {
$this->establish_permalinks();
$this->establish_api_request_urls();
$this->fetch_api_responses();
$this->parse_api_responses();
$this->calculate_network_shares();
$this->cache_share_counts();
}
/**
* Establish the Permalinks to be checked for shares.
*
* The word Permalink here specifically refers to URL's of blog posts which
* we want to fetch share counts for. We want a system that allows us to
* create permalinks for the primary permalink, the share recovery permalink,
* allow a filter for programatic adding of others, and so on.
*
* The processed results will be stored in $this->permalinks.
* @var permalinks Links to be checked for share counts during the
* share count update process.
*
* @since 3.1.0 | 21 JUN 2018 | Created
* @since 4.0.0 | 20 FEB 2020 | Added call to debug_display_permalinks()
* @since 4.0.0 | 21 FEB 2020 | Added call to add_trailing_slashes()
* @param void
* @return void
*
*/
protected function establish_permalinks() {
global $swp_social_networks;
$this->permalinks = array();
/**
* Loop through the global social network objects, identify the active
* networks, and find the permalinks to check for each one.
*
*/
foreach( $swp_social_networks as $key => $object) {
/**
* If this particular network isn't active, we need to skip it and
* not fetch any share counts for it.
*
*/
if ( false == $object->active ) {
continue;
}
/**
* This is the standard, current permalink for the post. We use the
* standard permalink by default for checking for share counts.
*
*/
$this->permalinks[$key][] = get_permalink( $this->post_id );
/**
* If share count recovery is activated, we'll add a second permalink
* to the array for each network. So now we'll have two permalinks
* for which to fetch share counts.
*
*/
if( true === SWP_Utility::get_option('recover_shares') ) {
$this->permalinks[$key][] = SWP_Permalink::get_alt_permalink( $this->post_id );
}
/**
* This filter allows third-parties to enable another permalink for
* which to check for share counts.
*
*/
$this->permalinks = apply_filters( 'swp_recovery_filter', $this->permalinks );
/**
* Duplicates the URL's so that the given network will be check for
* a permalink with both a trailing slash and without one.
*
*/
$this->add_trailing_slashes( $key );
$this->add_utm_codes( $key );
}
}
/**
* Prepares outbound API links per network.
*
* @since 3.1.0 | 25 JUN 2018 | Created the method.
* @var api_urls The array of outbound API request destinations.
* @param void
* @return void
*
*/
protected function establish_api_request_urls() {
global $swp_social_networks;
$this->api_urls = array();
foreach ( $this->permalinks as $network => $links ) {
$current_request = 0;
foreach( $links as $url ) {
$this->api_urls[$current_request][$network] = $swp_social_networks[$network]->get_api_link( $url );
++$current_request;
}
}
}
/**
* Fetch responses from the network API's.
*
* This method will use the $this->api_urls array, loop through them, and
* using curl_multi will fetch raw responses from the network API's. The
* results will be stored in $this->raw_api_responses array.
*
* @since 3.1.0 | 25 JUN 2018 | Created
* @var raw_api_responses An array of responses from the API's.
* @param void
* @return void All data is stored in local properties.
*
*/
protected function fetch_api_responses() {
$current_request = 0;
foreach ( $this->api_urls as $request => $networks ) {
$this->raw_api_responses[$current_request] = SWP_CURL::fetch_shares_via_curl_multi( $networks );
$current_request++;
}
}
/**
* Parse the API responses
*
* This method will take the array of raw responses stored inside the
* $this->raw_api_responses property and use each network's parse method
* to convert them into integers that we can use to tally up our share counts.
*
* @since 3.1.0 | 25 JUN 2018 | Created
* @var parsed_api_responses An array of integers from parsing the responses.
* @param void
* @return void Processed data is stored in local properties.
*
*/
protected function parse_api_responses() {
global $swp_social_networks;
/**
* If for any reason the $raw_api_responses property failed to get
* populated just gracefully bail out and stop processing.
*
*/
if ( empty( $this->raw_api_responses ) ) {
return;
}
$this->parsed_api_responses = array();
foreach( $this->raw_api_responses as $request => $responses ) {
$current_request = 0;
foreach ( $responses as $key => $response ) {
$this->parsed_api_responses[$current_request][$key][] = $swp_social_networks[$key]->parse_api_response( $response );
$current_request++;
}
}
/**
* This will output the checked permalinks to the screen when the following
* URL parameters are added to the address bar: ?swp_cache=rebuild&swp_debug=recovery.
*
*/
$this->debug_display_permalinks();
}
/**
* Calculate the network shares.
*
* This method is used to calculate the shares for each network based on
* what we have just retrieved from the API responses. Another method,
* establish_share_counts will be used to create this data from the cached
* database data. This one is ONLY used when the cache is not fresh and the
* data is being rebuilt.
*
* @since 3.1.0 | 25 JUN 2018 | Created
* @since 3.4.0 | 18 OCT 2018 | Refactored to ensure that force_new_shares
* works the way that it's supposed to.
* @since 3.4.0 | 18 OCT 2018 | Added array_unique to prevent double counts.
* @var share_counts An array of share count numbers.
* @param void
* @return void All data stored in local properties.
*
*/
protected function calculate_network_shares() {
global $swp_social_networks;
/**
* If for any reason the $parsed_api_responses property failed to get
* populated just gracefully bail out and stop processing.
*
*/
if ( empty( $this->parsed_api_responses ) ) {
return;
}
$share_counts = array();
$share_counts['total_shares'] = 0;
$checked_networks = array();
/**
* This loops through all of the parsed API responses and converts them
* into share counts. The next loop below will then go through all the
* remaining networks that didn't have API requests/responses.
*
*/
foreach ( $this->parsed_api_responses as $request => $networks ) {
foreach ( $networks as $network => $count_array ) {
/**
* Added a call to array_unique to eliminate duplicate share
* counts when share recovery is active. In some cases, the
* social networks detect the change in URL and return the same
* share count for the current URL as well as the old, redirected
* URL. This prevents the count from being doubled.
*
*/
$count_array = array_unique( $count_array );
foreach ( $count_array as $count ) {
if ( !is_numeric( $count ) ) {
continue;
}
if ( !isset( $share_counts[$network] ) ) {
$share_counts[$network] = 0;
}
$share_counts[$network] += $count;
}
$checked_networks[] = $network;
}
}
/**
* After we processed the API responses, we'll now go through all active
* networks regardless of whether or not they have an API, and process
* their share counts. Of course, most of these will be zeroes unless it
* is a network that used to have share counts. If so, we will not
* override the old share counts unless the user is using the debug
* parameter to force it to do so.
*
*/
foreach( SWP_Utility::get_option( 'order_of_icons' ) as $network ) {
$count = 0;
/**
* If this is a network that we checked above (that has an API),
* then let's start by using the count fetched from the API.
*
*/
if ( in_array( $network, $checked_networks ) ) {
$count = $share_counts[$network];
}
/**
* Let's fetch the previous count that we have stored in the database
* from the previous API calls so that we can run a comparison.
*
*/
$previous_count = get_post_meta( $this->post_id, "_${network}_shares", true );
if( false === $previous_count ) {
$previous_count = 0;
}
/**
* The ?swp_debug=force_new_shares will force it to update to the
* newest numbers even if it is a lower number. If this debug
* parameter is off, however, then we simply use whichever number is
* highest between the current and previously fetched counts.
*
*/
if ( $count < $previous_count && false == SWP_Utility::debug( 'force_new_shares' ) ) {
$count = $previous_count;
}
/**
* Iterate the total shares with our new numbers, and then store
* this network's count in the local property for caching and
* display later on.
*
*/
$share_counts['total_shares'] += $count;
$share_counts[$network] = $count;
}
$this->share_counts = $share_counts;
}
/**
* Update the meta fields with the new share counts.
*
* As per the inline docblock below, we only update if larger numbers are
* recieved than the previous checks. This is because some networks, like
* Pinterest are notorious for randomly resetting some counts all the way
* back to zero. This will prevent a post with 10K shares from keeping the
* zero response.
*
* @since 3.1.0 | 25 JUN 2018 | Created
* @param void
* @return void
*
*/
protected function cache_share_counts() {
global $swp_social_networks;
/**
* If the local property $share_counts is empty, then we won't have any
* share counts to cache in the database so just bail out.
*
*/
if ( empty( $this->share_counts ) ) {
return;
}
/**
* Loop through the share counts for each network and store the new
* counts in the databse in custom fields.
*
* @var $key The key corresponding to a social network (e.g. 'twitter')
* @var $count The share count for this network.
*
*/
foreach( $this->share_counts as $key => $count ) {
// Skip it if this is the total shares. This will be added later.
if ( empty( $swp_social_networks[$key] ) ) {
continue;
}
if( 0 === $swp_social_networks[$key]->get_api_link('') ) {
continue;
}
// Access the Social_Network object and update its count.
$Current_Social_Network = $swp_social_networks[$key];
$Current_Social_Network->update_share_count( $this->post_id, $count );
}
// Update the total shares.
delete_post_meta( $this->post_id, '_total_shares');
update_post_meta( $this->post_id, '_total_shares', $this->share_counts['total_shares'] );
$this->cleanup_remnants();
do_action('swp_analytics_record_shares', $this->post_id, $this->share_counts );
}
/**
* Gets the computed share data.
*
* @since 3.1.0 | 20 JUN 2018 | Created the method.
* @param void
* @return array $this->share_counts if it exists, or an empty array.
*
*/
public function get_shares() {
if ( !empty( $this->share_counts ) ) {
return $this->share_counts;
}
return array();
}
/**
* Fetch and return the cached share data from the database.
*
* @since 3.1.0 | 21 JUN 2018 | Created the method.
* @access protected
* @param void
* @return void
*
*/
protected function establish_share_counts() {
global $swp_social_networks;
$this->share_counts['total_shares'] = 0;
/**
* Loop through the social networks and pull their share count from
* the custom fields for this post.
*
*/
foreach( $swp_social_networks as $Network ) {
// Get the current share count from the cache.
$this->share_counts[$Network->key] = $Network->get_share_count( $this->post_id );
// Add up the total shares based on the counts of the active networks.
if( true === $Network->is_active() ) {
$this->share_counts['total_shares'] += $this->share_counts[$Network->key];
}
}
}
/**
* A method for outputting debug notices when cache rebuild parameters are present.
*
* @since 3.2.0 | 31 JUL 2018 | Created
* @param string $string The message to be displayed.
* @return void
*
*/
protected function debug_message( $string ) {
if( isset( $_GET['swp_cache'] ) && 'rebuild' === $_GET['swp_cache'] ) {
echo $string;
}
}
/**
* A method for displaying the permalinks that are being used to fetch
* share counts for this post or page. This will output an array of permalinks
* separated by social network.
*
* To activate: ?swp_cache=rebuild&swp_debug=recovery
*
* @since 4.0.0 | 19 FEB 2020 | Created
* @param void
* @return void All data is output to the screen.
*
*/
protected function debug_display_permalinks() {
// Bail if debugging is not currently active.
if( false === SWP_Utility::debug( 'recovery' ) ) {
return;
}
// Output the preformatted box with the array of permalinks.
echo '<pre style="background:yellow;">';
$with_pro = '';
if( defined( 'SWPP_VERSION' ) && defined( 'SWPP_DEV_VERSION' ) ) {
$with_pro = '(with Pro ' . SWPP_VERSION .'.'. SWPP_DEV_VERSION .')';
}
echo '<p>Social Warfare ' . SWP_VERSION .'.'. SWP_DEV_VERSION .' ' . $with_pro . ' </p>';
echo '<h1>The URL\'s Being Checked:</h1>';
var_dump($this->permalinks);
echo '<h1>The Responses from the API:</h1>';
var_dump($this->raw_api_responses);
echo '<h1>This is the share counts array</h1>';
var_dump($this->share_counts);
echo '</pre>';
}
/**
* This function will add or remove the trailing slash so that we check a
* network for share counts for both versions of the link. Now we will check
* for the following versions of a link:
*
* Note: This is currently done exclusively for Pinterest, but other networks
* can be added instantaneously by adding them to the $eligible_networks array below.
*
* /my-blog-post/
* /my-blog-post
*
* @since 4.0.0 | 21 FEB 2020 | Created
* @param string $key The key corresponding to the current social network.
* @return void All data is stored in class properties.
*
*/
protected function add_trailing_slashes( $key ) {
// The list of networks that we will check both URL versions for.
$eligible_networks = array('pinterest');
// If this isn't one of those networks, bail out early.
if( false === in_array( $key, $eligible_networks ) ) {
return false;
}
/**
* We'll add our newly created permalinks to this now-empty array. Later
* we'll merge this back into the original class property array.
*
*/
$new_links = array();
/**
* We'll loop through every single permalink that is being checked for
* this network (both normal and recovery), and create a second version
* either by adding a trailing slash or removing it.
*
*/
foreach( $this->permalinks[$key] as $permalink ) {
// If it doesn't have a trailing slash, we'll add one.
if( false === SWP_Utility::ends_with( $permalink, '/' ) ) {
$new_links[] = $permalink . '/';
// If it does have a trailing slash, we'll remove it.
} else {
$new_links[] = rtrim( $permalink, '/');
}
}
/**
* Merge our newly created permalinks array into the class property array
* whilst specifically targeting the array that lives in the indice for
* this network.
*/
$this->permalinks[$key] = array_merge( $this->permalinks[$key], $new_links );
}
/**
* This function will add a version of the URL with UTM codes so we check a
* network for share counts for both versions of the link. Now we will check
* for the following versions of a link:
*
* Note: This is currently done exclusively for Pinterest, but other networks
* can be added instantaneously by adding them to the $eligible_networks array below.
*
* /my-blog-post/
* /my-blog-post/?utm=blahblah
*
* @since 4.2.0 | 30 NOV 2020 | Created
* @param string $key The key corresponding to the current social network.
* @return void All data is stored in class properties.
*
*/
protected function add_utm_codes( $key ) {
global $swp_social_networks;
// The list of networks that we will check both URL versions for.
$eligible_networks = array('pinterest');
// If this isn't one of those networks, bail out early.
if( false === in_array( $key, $eligible_networks ) ) {
return false;
}
// If Google Analytics are turned off, then just bail out.
if( false === SWP_Utility::get_option( 'google_analytics' ) ) {
return;
}
// If UTM is turned off on Pinterest, and this is Pinterest, just bail out.
if( false === SWP_Utility::get_option( 'utm_on_pins' ) && 'pinterest' === $key ) {
return;
}
/**
* We'll add our newly created permalinks to this now-empty array. Later
* we'll merge this back into the original class property array.
*
*/
$new_links = array();
// The data needed by the get_shareable_permalink() method below.
$post_data = array(
'ID' => $this->post_id,
'permalink' => $this->permalinks[$key][0]
);
$new_links[] = urldecode( $swp_social_networks[$key]->get_shareable_permalink( $post_data ) );
/**
* Merge our newly created permalinks array into the class property array
* whilst specifically targeting the array that lives in the indice for
* this network.
*/
$this->permalinks[$key] = array_merge( $this->permalinks[$key], $new_links );
}
public function cleanup_remnants() {
delete_post_meta( $this->post_id, '_totes');
delete_post_meta( $this->post_id, '_email_shares');
delete_post_meta( $this->post_id, '_more_shares');
delete_post_meta( $this->post_id, '_print_shares');
delete_post_meta( $this->post_id, '_telegram_shares');
}
}