File "SWP_Compatibility.php"
Full Path: /home/bfxleof/www/wp-content/plugins/social-warfare/lib/utilities/SWP_Compatibility.php
File size: 8.64 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* SWP_Compatibility: A class to enhance compatibility with other plugins
*
* @package SocialWarfare\Functions
* @copyright Copyright (c) 2018, Warfare Plugins, LLC
* @license GPL-3.0+
* @since 1.0.0
* @since 3.0.0 | 22 FEB 2018 | Refactored into a class-based system.
* @since 3.6.1 | 22 MAY 2019 | Added the Pin Button Cleaner. Updated docblocks.
*
*/
class SWP_Compatibility {
/**
* The magic method used to insantiate this class.
*
* This adds compatibility with Simple Podcast Press, the Duplicate Posts
* plugin, and Really Simple SSL.
*
* @since 2.1.4
* @since 3.6.1 | 22 MAY 2019 | Added the Pin Button Cleaner
* @since 3.6.1 | 22 MAY 2019 | Moved core functionality into separate methods.
* @access public
* @param integer $id The post ID
* @return none
*
*/
public function __construct() {
$this->queue_compatibility_filter_hooks();
$this->make_simple_podcast_press_compatible();
}
/**
* A method to hook into custom hooks provided by other plugins. These allow
* us access to their functionality to allow for easy compatibility patches.
*
* @since 3.6.1 | 22 MAY 2019 | Created
* @param void
* @return void
*
*/
public function queue_compatibility_filter_hooks() {
/**
* This will remove our custom meta fields from a newly duplicated post
* so that when Duplicate Post plugin does it's thing, the share counts
* and other data won't be duplicated with the post.
*
*/
add_filter( 'duplicate_post_meta_keys_filter' , array( $this, 'filter_duplicate_meta_keys' ) );
/**
* This will make it so that the Really Simple SSL plugin won't be able
* to hijack and manipulate the URL's that we are attempting to use for
* the share recovery features.
*
*/
add_filter("rsssl_fixer_output", array( $this, 'rsssl_fix_compatibility') );
/**
* A method used to clean out pin buttons that were generated by the JS
* inside of a page builder html and then subsequently saved into the content.
*
*/
add_filter( 'the_content', array( $this, 'clean_out_pin_buttons' ) );
}
/**
* A method used to disable the open graph tags from the Podcast Press
* plugin to allow ours to be the only ones in the markup.
*
* @since 3.6.1 | 22 MAY 2019 | Created
* @param void
* @return void
*
*/
public function make_simple_podcast_press_compatible() {
if ( is_plugin_active( 'simple-podcast-press/simple-podcast-press.php' ) ) {
global $ob_wp_simplepodcastpress;
remove_action( 'wp_head' , array( $ob_wp_simplepodcastpress, 'spp_open_graph' ) , 1 );
}
}
/**
* A method to clean out Pinterest save buttons that have been erroneously
* saved to the database.
*
* Some theme/page builders have taken the HTML generated by the javascript
* and saved that HTML directly into the database. Since the JS creates the
* pinterest save button on each page load, this has resulted in multiple
* instances of the save button being generated, saved, generated, saved, etc.
*
* This function will search the_content via the WordPress hook of the same
* name and remove them.
*
* @since 3.6.1 | 21 MAY 2019 | Created
* @param string $content The string of content passed in by WordPress core.
* @return string $content The modified content.
*
*/
public function clean_out_pin_buttons( $content ) {
/**
* If the content that is passed in is empty, then just bail out as we
* don't have anything that will need processing/filtering.
*
*/
if( empty( $content ) ) {
return $content;
}
/**
* If the content doesn't contain any pinit buttons, just bail out and
* return the content. We don't have anything to process here.
*
*/
if (strpos($content, 'sw-pinit-button') === false) {
return $content;
}
/**
* We'll be using PHP's DOMDocument to make our alterations to the
* content, so if it doesn't exist, we'll need to bail out. This has
* been available since PHP 5, but some server's may have it manually
* turned off in their configuration settings. Better safe than sorry.
*
*/
if( !class_exists( 'DOMDocument' ) ) {
return $content;
}
// DOMDocument works better with an XML delcaration.
if ( false === strpos( $content, '?xml version' ) ) {
$xml_statement = '<?xml version="1.0" encoding="UTF-8"?>';
$content = $xml_statement . $content;
$added_xml_statement = true;
}
/**
* The content is most likely not going to be a properly formatted
* HTML document. As such, it's going to throw some annoying PHP errors
* whilst still getting and parsing the information that we need. As
* such, we'll just turn off error reporting and then turn it back on
* after we're done here.
*
* This function returns the previous error reporting status. We can use
* this to revert the setting back to the user's default when we are done.
*
*/
$libxml_error_status = libxml_use_internal_errors(true);
/**
* Load the content text into a DOMDocument object, and then we'll use
* that object to create a DOMXPath object which will allow us jQuery-like
* traversal of the DOM to make our adjustments.
*
*/
$dom = new DOMDocument();
$dom->loadHTML( $content, LIBXML_HTML_NODEFDTD );
$xpath = new DOMXPath( $dom );
/**
* This will locate and remove all of the .sw-pinit-button anchor tags
* that have been placed throughout the content.
*
*/
$nodes = $xpath->query("//*[contains(@class, 'sw-pinit-button')]");
foreach( $nodes as $node ) {
$parent = $node->parentNode;
$parent->removeChild($node);
}
/**
* The anchor tags, along with the images in the content, were wrapped
* in a div wrapper. This loop will locate those wrappers and remove
* them without removing their content (i.e. the user's images).
*
*/
$nodes = $xpath->query("//*[contains(@class, 'sw-pinit')]");
foreach( $nodes as $node ) {
$parent = $node->parentNode;
while ($node->hasChildNodes()) {
$parent->insertBefore($node->lastChild, $node->nextSibling);
}
$parent->removeChild($node);
}
/**
* When everything is done, we'll save the HTML, turn error reporting
* back to their default settings, clear the errors, and remove the XML
* information that we added above. Then, of course, we'll return the
* modified content.
*
*/
$content = $dom->saveHTML();
$start = strpos( $html, '<body>' ) + 6;
$end = strrpos( $html, '</body>' ) - strlen($html);
$content = substr( $html, $start, $end );
libxml_use_internal_errors( $libxml_error_status );
libxml_clear_errors();
if ( $added_xml_statement ) {
$content = str_replace( $xml_statement, '', $content );
}
return $content;
}
/**
* A function to fix the share recovery conflict with Really Simple SSL
* plugin. Their plugin was using some sort of find/replace to ensure that
* all links on the site use the HTTPS protocol. However, share recovery is
* specifically attempting to fetch share counts for the old non-ssl
* protocol, so we need to make sure that we undo this replacement before
* fetching share counts.
*
* @since 2.2.2 | 01 JAN 2018 | Created
* @param string $html A string of html to be filtered
* @return string $html The filtered string of html
* @access public
*
*/
public function rsssl_fix_compatibility($html) {
//replace the https back to http
$html = str_replace( "swp_post_recovery_url = 'https://" , "swp_post_recovery_url = 'http://" , $html);
return $html;
}
/**
* Removes Social Warfare keys from the meta before post is duplicated.
*
* This method is a specific compatibility patch for the plugin Duplicate
* Posts. Since our share counts, social media images, descriptions, etc.,
* are all stored in post meta fields, they get duplicated when a post is
* duplicated. This results in wrong or unuseful data on the new post. This
* method stops that from happening.
*
* @since 3.4.2 | 10 DEC 2018 | Created
* @param array $meta_keys All meta keys prepared for duplication.
* @return array $meta_keys $meta_keys with no Social Warfare keys.
*
*/
public function filter_duplicate_meta_keys( $meta_keys = array() ) {
$blacklist = array( 'swp_', '_shares', 'bitly_link' );
foreach( $meta_keys as $key ) {
foreach( $blacklist as $forbidden ) {
if ( strpos( $forbidden, $key ) ) {
unset( $meta_keys[$key] );
}
}
}
return $meta_keys;
}
}