<?php
/**
* XPoster Pro, premium add-on for XPoster
*
* @package XPoster Pro
* @author Joe Dolson
* @copyright 2014-2024 Joe Dolson
* @license GPL-2.0+
*
* @wordpress-plugin
* Plugin Name: XPoster Pro
* Plugin URI: https://www.wptweetspro.com/wp-tweets-pro
* Description: Adds great new features to extend XPoster.
* Author: Joe Dolson
* Author URI: https://www.joedolson.com
* Text Domain: wp-tweets-pro
* License: GPL-2.0+
* License URI: https://www.gnu.org/license/gpl-2.0.txt
* Domain Path: lang
* Version: 3.2.2
* Requires Plugins: wp-to-twitter
*/
/*
Copyright 2014-2024 Joe Dolson (email : joe@joedolson.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $wptp_version;
$wptp_version = '3.2.2';
add_action( 'init', 'wptp_load_textdomain' );
/**
* Load internationalization.
*/
function wptp_load_textdomain() {
load_plugin_textdomain( 'wp-tweets-pro', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );
}
// The URL of the site with EDD installed.
define( 'EDD_WPT_STORE_URL', 'https://xposterpro.com' );
define( 'EDD_WPT_ITEM_ID', 47131 );
if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
// load our custom updater if it doesn't already exist.
require_once __DIR__ . '/updates/EDD_SL_Plugin_Updater.php';
}
// retrieve our license key from the DB.
$license_key = trim( get_option( 'wpt_license_key' ) );
// setup the updater.
$edd_updater = new EDD_SL_Plugin_Updater(
EDD_WPT_STORE_URL,
__FILE__,
array(
'version' => $wptp_version, // current version number.
'license' => $license_key, // license key (used get_option above to retrieve from DB).
'item_id' => EDD_WPT_ITEM_ID, // name of this plugin.
'author' => 'Joe Dolson', // author of this plugin.
'url' => home_url(),
)
);
register_activation_hook( __FILE__, 'wpt_activate' );
register_deactivation_hook( __FILE__, 'wpt_deactivation' );
/**
* Action to perform on deactivation.
*/
function wpt_deactivation() {
wp_clear_scheduled_hook( 'wpt_recurring_tweets' );
wp_clear_scheduled_hook( 'wptcron' );
}
/**
* Action to perform on activation.
*/
function wpt_activate() {
// Set media upload option to enabled by default unless already set otherwise.
$media_option = get_option( 'wpt_media', 'unset' );
if ( 'unset' === $media_option ) {
update_option( 'wpt_media', '1' );
}
}
require plugin_dir_path( __FILE__ ) . 'wpt-users.php';
require plugin_dir_path( __FILE__ ) . 'wpt-auto-repost.php';
require plugin_dir_path( __FILE__ ) . 'wpt-scheduled-tweets.php';
require plugin_dir_path( __FILE__ ) . 'wpt-past-tweets.php';
require plugin_dir_path( __FILE__ ) . 'wpt-failed-tweets.php';
require plugin_dir_path( __FILE__ ) . 'wpt-pro-settings.php';
require plugin_dir_path( __FILE__ ) . 'wpt-player-card.php';
add_filter( 'wpt_status', 'wpt_filter_tweet', 10, 3 );
/**
* Filter Tweet text to replace tag values with hashtags in title or post excerpt
*
* @param string $tweet_text Text of the Tweet.
* @param int $id post id.
* @param string $context whether checking post content or title.
*
* @return string Update text of field being searched.
*/
function wpt_filter_tweet( $tweet_text, $id, $context ) {
if ( ( get_option( 'wpt_filter_title' ) && 'title' === $context ) || ( 1 === (int) get_option( 'wpt_filter_post' ) && 'post' === $context ) ) {
$term_meta = false;
$tags = get_the_tags( $id );
if ( $tags > 0 ) {
foreach ( $tags as $value ) {
if ( 'slug' === get_option( 'wpt_tag_source' ) ) {
$tag = $value->slug;
} else {
$tag = $value->name;
}
$replace = get_option( 'jd_replace_character' );
$strip = get_option( 'jd_strip_nonan' );
$search = '/[^a-zA-Z0-9]/';
if ( '[ ]' === $replace || '' === $replace ) {
$replace = '';
}
$newtag = str_ireplace( ' ', $replace, trim( $tag ) );
$t_id = $value->term_id;
$term_meta = get_option( "wpt_taxonomy_$t_id" );
if ( '1' === $strip ) {
$newtag = preg_replace( $search, $replace, $newtag );
}
switch ( $term_meta ) {
case 1:
$newtag = "#$tag";
break;
case 2:
$newtag = "$$tag";
break;
case 3:
$newtag = '';
break;
case 4:
$newtag = $tag;
break;
case 5:
$newtag = "@$tag";
break;
default:
/**
* Change the default tag character when replacing tags in titles & descriptions. Default '#'.
*
* @hook wpt_tag_default
* @param {string} $char Character used to convert tags into hashtags.
* @param {int} $t_id Term ID.
* @param {string} $context Flag indicating whether this is post content or a title.
*
* @return {string}
*/
$newtag = apply_filters( 'wpt_tag_default', '#', $t_id, $context ) . $tag;
}
if ( mb_strlen( $newtag ) > 2 ) {
// replaces whole words only.
$tag = preg_replace( '/[\/]/', '', $tag ); // need to remove slashes.
$string = preg_replace( '/\b' . $tag . '\b/i', $newtag, $tweet_text );
}
}
}
}
return $string;
}
/**
* Return a path relative to the XPoster Pro plugin regardless of calling location.
*
* @param string $filename The name of the file called.
*
* @return string
*/
function wpt_img_path( $filename ) {
return plugins_url( 'images/' . $filename, __FILE__ );
}
add_action( 'split_shared_term', 'wpt_update_term_meta', 10, 4 );
/**
* Ensure that newly edited split terms get same settings as old term.
*
* @param int $old_term_id Term ID for old term.
* @param int $new_term_id Term ID for new term.
* @param int $term_taxonomy_id Old Term Taxonomy.
* @param int $taxonomy New Term Taxonomy.
*/
function wpt_update_term_meta( $old_term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
$value = get_option( "wpt_taxonomy_$old_term_id" );
add_option( "wpt_taxonomy_$new_term_id", $value );
$value = get_option( "wpt_taxonomy_revive_$old_term_id" );
add_option( "wpt_taxonomy_revive_$new_term_id", $value );
}
add_filter( 'wpt_schedule_retweet', 'wpt_blackout_period', 10, 4 );
/**
* Manipulate time to avoid blackout periods.
*
* @param string $time Timestamp.
* @param mixed int/boolean $acct Account being sent to.
* @param int $i Retweet value.
* @param array $post_info Post data.
*
* @return new timestamp.
*/
function wpt_blackout_period( $time, $acct, $i, $post_info ) {
$blackout = get_option( 'wpt_blackout' );
if ( ! $blackout ) {
return $time;
}
/**
* Filter blackout window based on accounts, reposts, and post information.
*
* @hook wpt_blackout_period
*
* @param {array} $blackout Array of parameters indicating from and to daily blackout times.
* @param {int|bool} $acct Account being posted to. User ID or false.
* @param {int} $i Retweet value if this is being reposted.
* @param {array} $post_info Array of post data.
*
* @return {array}
*/
$blackout = apply_filters( 'wpt_blackout_period', $blackout, $acct, $i, $post_info );
$from = $blackout['from'];
$to = $blackout['to'];
if ( $from === $to ) {
return $time;
}
$hour = date( 'G', current_time( 'timestamp' ) + $time ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested, WordPress.DateTime.RestrictedFunctions.date_date
if ( $from < $to ) {
$jump = ( ( 24 - $from ) + $to ) - 24;
$blackout = ( $hour > $from && $hour < $to ) ? true : false;
} else {
$jump = ( ( 24 - $from ) + $to );
$blackout = ( $hour > $from || $hour < $to ) ? true : false;
}
if ( $blackout ) {
$time = $time + ( $jump * 60 * 60 );
}
return $time;
}
add_filter( 'wpt_insert_post', 'wpt_insert_post_values', 10, 2 );
/**
* Save XPoster Pro meta values on post save
*
* @param array $post POST data.
* @param int $post_id Post ID.
*
* @return boolean Whether an update was performed.
*/
function wpt_insert_post_values( $post, $post_id ) {
$update = false;
if ( isset( $post['_wpt_delay_tweet'] ) && '' !== $post['_wpt_delay_tweet'] ) {
$wpt_delay_tweet = (int) $post['_wpt_delay_tweet'];
$update = update_post_meta( $post_id, '_wpt_delay_tweet', $wpt_delay_tweet );
}
if ( isset( $post['_wpt_noautopost'] ) && 1 === (int) $post['_wpt_noautopost'] ) {
$update = update_post_meta( $post_id, '_wpt_noautopost', 1 );
} elseif ( isset( $post['_wpt_noautopost'] ) && 1 !== (int) $post['_wpt_noautopost'] || ! isset( $post['_wpt_noautopost'] ) ) {
delete_post_meta( $post_id, '_wpt_noautopost' );
}
if ( isset( $post['_wpt_retweet_repeat'] ) && '' !== $post['_wpt_retweet_repeat'] ) {
$wpt_retweet_repeat = (int) $post['_wpt_retweet_repeat'];
$update = update_post_meta( $post_id, '_wpt_retweet_repeat', $wpt_retweet_repeat );
}
if ( isset( $post['_wpt_retweet_after'] ) && '' !== $post['_wpt_retweet_after'] ) {
$wpt_retweet_after = (float) $post['_wpt_retweet_after'];
$update = update_post_meta( $post_id, '_wpt_retweet_after', $wpt_retweet_after );
}
if ( isset( $post['_wpt_twitter_card'] ) && '' !== $post['_wpt_twitter_card'] ) {
switch ( $post['_wpt_twitter_card'] ) {
case 'photo':
case 'summary_large_image':
$wpt_twitter_card = 'summary_large_image';
break;
case 'player':
$wpt_twitter_card = 'player';
break;
default:
$wpt_twitter_card = 'summary';
}
$update = update_post_meta( $post_id, '_wpt_twitter_card', $wpt_twitter_card );
}
if ( isset( $post['_wpt_video_subtitle'] ) ) {
$update = update_post_meta( $post_id, '_wpt_video_subtitle', $post['_wpt_video_subtitle'] );
}
if ( isset( $post['_wpt_video_ratio'] ) ) {
$update = update_post_meta( $post_id, '_wpt_video_ratio', $post['_wpt_video_ratio'] );
}
if ( isset( $post['_wpt_video_source'] ) ) {
$update = update_post_meta( $post_id, '_wpt_video_source', $post['_wpt_video_source'] );
}
if ( isset( $post['_wpt_cotweet'] ) && 'on' === $post['_wpt_cotweet'] ) {
$update = update_post_meta( $post_id, '_wpt_cotweet', 1 );
} else {
delete_post_meta( $post_id, '_wpt_cotweet' );
}
if ( isset( $post['_wpt_image'] ) && 1 === (int) $post['_wpt_image'] ) {
$update = update_post_meta( $post_id, '_wpt_image', 1 );
} else {
delete_post_meta( $post_id, '_wpt_image' );
}
if ( isset( $post['_wpt_custom_image'] ) ) {
$update = update_post_meta( $post_id, '_wpt_custom_image', absint( $post['_wpt_custom_image'] ) );
} else {
delete_post_meta( $post_id, '_wpt_custom_image' );
}
if ( isset( $post['_wpt_authorized_users'] ) ) {
$update = update_post_meta( $post_id, '_wpt_authorized_users', $post['_wpt_authorized_users'] );
} else {
delete_post_meta( $post_id, '_wpt_authorized_users' );
}
if ( isset( $post['_wpt_retweet_text'] ) ) {
$update = update_post_meta( $post_id, '_wpt_retweet_text', $post['_wpt_retweet_text'] );
} else {
delete_post_meta( $post_id, '_wpt_retweet_text' );
}
if ( isset( $post['_wpt_retweet_delay'] ) ) {
$update = update_post_meta( $post_id, '_wpt_retweet_delay', $post['_wpt_retweet_delay'] );
} else {
delete_post_meta( $post_id, '_wpt_retweet_delay' );
}
return $update;
}
/**
* Insert coTweeting into My Calendar
*
* @return string
*/
function wpt_my_calendar_options() {
$cotweet_enabled = get_option( 'wpt_cotweet' );
$return = '';
if ( $cotweet_enabled ) {
$return = '<input type="hidden" name="_wpt_cotweet" value="on" />';
}
return $return;
}
add_filter( 'mc_insert_custom_fields', 'wpt_my_calendar_options' );
/**
* Setup custom post filters
*
* @return string
*/
function wpt_setup_filters() {
$filters = get_option( 'wpt_filters' );
$available = array(
'postTitle' => __( 'Post Title', 'wp-tweets-pro' ),
'postContent' => __( 'Post Content', 'wp-tweets-pro' ),
'postLink' => __( 'Permalink', 'wp-tweets-pro' ),
'shortUrl' => __( 'Shortened URL', 'wp-tweets-pro' ),
'postStatus' => __( 'Post Status', 'wp-tweets-pro' ),
'postType' => __( 'Post Type', 'wp-tweets-pro' ),
'id' => __( 'Post ID', 'wp-tweets-pro' ),
'authId' => __( 'Author ID', 'wp-tweets-pro' ),
'postExcerpt' => __( 'Post Excerpt', 'wp-tweets-pro' ),
);
$return = "<table class='widefat fixed'>
<thead>
<tr>
<th scope='col' id='wpt_filter_field'>" . __( 'Filter field', 'wp-tweets-pro' ) . "</th>
<th scope='col' id='wpt_filter_type'>" . __( 'Filter type', 'wp-tweets-pro' ) . "</th>
<th scope='col' id='wpt_filter_value'>" . __( 'Filter value', 'wp-tweets-pro' ) . "</th>
<th scope='col' id='wpt_filter_delete'>" . __( 'Delete filter', 'wp-tweets-pro' ) . '</th>
</tr>
</thead>
<tbody>';
$key = 0;
if ( is_array( $filters ) ) {
foreach ( $filters as $key => $value ) {
$key = absint( $key );
$return .= "
<tr><td>
<select name='wpt_filters[ $key ][field]' aria-labelledby='wpt_filter_field'>";
foreach ( $available as $k => $v ) {
if ( $k === $value['field'] ) {
$selected = ' selected="selected"';
} else {
$selected = '';
}
$return .= "<option value='$k'$selected>$v</option>";
}
$return .= "</select></td>
<td><select name='wpt_filters[ $key ][type]' aria-labelledby='wpt_filter_type'>
<option value='equals'" . ( ( 'equals' === $value['type'] ) ? ' selected="selected"' : '' ) . ">is equal to</option>
<option value='notin'" . ( ( 'notin' === $value['type'] ) ? ' selected="selected"' : '' ) . ">does not contain</option>
<option value='in'" . ( ( 'in' === $value['type'] ) ? ' selected="selected"' : '' ) . ">contains</option>
<option value='notequals'" . ( ( 'notequals' === $value['type'] ) ? ' selected="selected"' : '' ) . ">is not equal to</option>
</select></td>
<td><input type='text' aria-labelledby='wpt_filter_value' name='wpt_filters[ $key ][value]' value='$value[value]' /></td>
<td><input type='checkbox' aria-labelledby='wpt_filter_delete' name='wpt_filters[ $key ][delete]' value='on' /></td>
</tr>";
}
}
$key = $key + 1;
$return .= "
<tr>
<td><select name='wpt_filters[ $key ][field]' aria-labelledby='wpt_filter_field'>
<option value='0'> -- </option>";
foreach ( $available as $k => $v ) {
$return .= "<option value='$k'>$v</option>";
}
$return .= "</select></td>
<td><select name='wpt_filters[ $key ][type]' aria-labelledby='wpt_filter_type'>
<option value='0'> -- </option>
<option value='equals'>is equal to</option>
<option value='notin'>does not contain</option>
<option value='in'>contains</option>
<option value='notequals'>is not equal to</option>
</select></td>
<td><input type='text' aria-labelledby='wpt_filter_value' name='wpt_filters[ $key ][value]' value='' /></td>
</tr></tbody></table>";
return $return;
}
/**
* Save custom post filters
*/
function wpt_build_filters() {
$filters = get_option( 'wpt_filters' );
if ( ! is_array( $filters ) ) {
$filters = array();
}
if ( isset( $_POST['wpt_filters'] ) ) {
foreach ( $_POST['wpt_filters'] as $key => $value ) {
if ( isset( $value['delete'] ) && 'on' === $value['delete'] ) {
unset( $filters[ $key ] );
continue;
}
if ( ! in_array( $value['type'], array( 'in', 'notin', 'equals', 'notequals' ), true ) ) {
continue;
}
$filters[ $key ] = $value;
}
}
update_option( 'wpt_filters', $filters );
}
/**
* Apply custom post filters
*
* @param bool $filter Should the current post be filtered.
* @param array $post_info Array of Post data.
*
* @return boolean true: Tweet this; false: don't.
*/
function wpt_filter_post_info( $filter, $post_info ) {
$filters = get_option( 'wpt_filters' );
if ( is_array( $filters ) ) {
foreach ( $filters as $filter => $rule ) {
$comparison = $rule['type'];
switch ( $comparison ) {
case 'equals':
if ( $post_info[ $rule['field'] ] === $rule['value'] ) {
return true;
}
break;
case 'notin':
if ( false === strpos( $post_info[ $rule['field'] ], $rule['value'] ) ) {
return true;
}
break;
case 'in':
if ( false !== strpos( $post_info[ $rule['field'] ], $rule['value'] ) ) {
return true;
}
break;
case 'notequals':
if ( $post_info[ $rule['field'] ] !== $rule['value'] ) {
return true;
}
break;
default:
return true;
}
}
return false;
}
return $filter;
}
add_filter( 'wpt_should_block_status', 'wpt_filter_post_info', 10, 2 );
/**
* Process shortcodes inside a Tweet.
*
* @param string $tweet Tweet text.
* @param int $post_ID Post ID.
*
* @return string New tweet text.
*/
function wpt_process_shortcodes( $tweet, $post_ID ) {
/**
* Filter Tweet text prior to processing WordPress shortcodes.
*
* @hook wpt_process_shortcodes
* @param {string} $tweet Text of Tweet.
* @param {int} $post_ID Post ID.
*
* @return {string}
*/
$tweet = apply_filters( 'wpt_process_shortcodes', $tweet, $post_ID );
return do_shortcode( $tweet );
}
add_filter( 'wpt_tweet_sentence', 'wpt_process_shortcodes', 10, 2 );
/**
* Handle recurring Tweets.
*
* @param int $auth Author ID.
* @param string $sentence Tweet text.
* @param int $rt repost count.
* @param int $post_id post ID.
*/
function wpt_recurring_tweet_handler( $auth, $sentence, $rt, $post_id ) {
wpt_mail( "Recurring Tweet Happening: #$post_id", "$sentence, $rt, $post_id", $post_id ); // DEBUG.
// set up sentence.
$post_info = wpt_post_info( $post_id );
$sentence = jd_truncate_tweet( $sentence, $post_info, $post_id, false, $auth );
// set up media.
$media = ( ( '1' === get_option( 'wpt_media' ) ) && ( has_post_thumbnail( $post_id ) || wpt_post_attachment( $post_id ) ) ) ? true : false;
/**
* Customize whether media should be uploaded for the current Tweet action.
*
* @hook wpt_scheduled_media
*
* @param {bool} $media True to post media; false to not.
* @param {int} $post_id Post ID.
* @param {int} $rt Which time this is being reposted, if a repost.
*
* @return {bool}
*/
$media = apply_filters( 'wpt_scheduled_media', $media, $post_id, $rt ); // filter based on post ID.
// send Tweet.
wpt_post_to_service( $sentence, $auth, $post_id, $media );
}
add_action( 'wpt_recurring_tweets', 'wpt_recurring_tweet_handler', 10, 4 );
add_filter( 'wpt_post_info', 'wpt_insert_post_info', 10, 2 );
/**
* Add XPoster Pro post meta values into post_info array
*
* @param array $values Existing values.
* @param int $post_ID Post ID.
*
* @return array New values.
*/
function wpt_insert_post_info( $values, $post_ID ) {
if ( is_array( $values ) ) {
$delay = ( isset( $_POST['_wpt_delay_tweet'] ) && is_numeric( $_POST['_wpt_delay_tweet'] ) ) ? $_POST['_wpt_delay_tweet'] : get_post_meta( $post_ID, '_wpt_delay_tweet', true );
$after = ( isset( $_POST['_wpt_retweet_after'] ) && is_numeric( $_POST['_wpt_retweet_after'] ) ) ? $_POST['_wpt_retweet_after'] : get_post_meta( $post_ID, '_wpt_retweet_after', true );
$auth_repeat = ( '' !== get_user_meta( $values['authId'], 'wpt_retweet_repeat', true ) ) ? get_user_meta( $values['authId'], 'wpt_retweet_repeat', true ) : false;
$repeat = ( isset( $_POST['_wpt_retweet_repeat'] ) && is_numeric( $_POST['_wpt_retweet_repeat'] ) ) ? $_POST['_wpt_retweet_repeat'] : get_post_meta( $post_ID, '_wpt_retweet_repeat', true );
$no_delay = ( isset( $_POST['wpt-no-delay'] ) ) ? 'on' : false;
$no_repost = ( isset( $_POST['wpt-no-repost'] ) ) ? 'on' : false;
$image = ( isset( $_POST['_wpt_image'] ) && 1 === (int) $_POST['_wpt_image'] ) ? 1 : false;
$cotweet = ( isset( $_POST['wpt_cotweet'] ) ) ? 1 : get_post_meta( $post_ID, '_wpt_cotweet', true );
$wpt_authorized_users = ( isset( $_POST['_wpt_authorized_users'] ) ) ? $_POST['_wpt_authorized_users'] : array();
$values['wpt_cotweet'] = $cotweet;
$values['wpt_authorized_users'] = $wpt_authorized_users;
$values['wpt_no_delay'] = $no_delay;
$values['wpt_image'] = $image;
$values['wpt_no_repost'] = $no_repost;
$values['wpt_delay_tweet'] = ( '' !== $delay ) ? (int) $delay : get_option( 'wpt_delay_tweets' );
$values['wpt_retweet_after'] = ( '' !== $after ) ? (float) $after : get_option( 'wpt_retweet_after' );
$values['wpt_retweet_repeat'] = ( '' !== $repeat ) ? (int) $repeat : get_option( 'wpt_retweet_repeat' );
}
return $values;
}
add_filter( 'wpt_allow_reposts', 'wpt_test_user_reposts', 10, 4 );
/**
* Test how many times this user is allowed to repost.
*
* @param boolean $should_continue True = allowed to continue.
* @param int $rt Number of retweets so far.
* @param int $post_ID Post ID of current post.
* @param int $auth_id ID of current user.
*
* @return boolean Allowed to continue.
*/
function wpt_test_user_reposts( $should_continue, $rt, $post_ID, $auth_id ) {
if ( $auth_id ) {
$auth_value = get_user_meta( $auth_id, 'wpt_retweet_repeat', true );
$auth_repeat = ( '' !== $auth_value ) ? $auth_value : false;
// if author has a defined repost value & this retweet # is higher than their value, cancel it.
if ( $auth_repeat && ( $auth_repeat > $rt ) ) {
return false;
}
}
return $should_continue;
}
/**
* Notify users who have disabled or uninstalled XPoster
*/
function wpt_warning() {
echo "<div class='notice error'><p>" . __( '<strong>XPoster Pro</strong> requires that the current version of XPoster is also activated. Please re-activate or update XPoster! Thank you!', 'wp-tweets-pro' ) . '</p></div>';
}
/**
* Add Twitter 3-legged authentication to user account
*
* Need to update to latest TwitterOAuth to do this.
add_filter( 'wpt_twitter_user_fields', 'wpt_twitter_oauth3' );
function wpt_twitter_oauth3() {
// Build TwitterOAuth object with client credentials.
$current_user = wp_get_current_user();
$user_edit = ( isset( $_GET['user_id'] ) ) ? (int) $_GET['user_id'] : $current_user->ID;
$ack = get_option( 'app_consumer_key' );
$acs = get_option( 'app_consumer_secret' );
$connection = new Wpt_TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
// Get temporary credentials.
$request_token = $connection->oauth( 'oauth/request_token', array( 'oauth_callback' => home_url() ) );
print_r($request_token);
}
*/
/**
* Filter Tweet template to check for any term-specific template.
* Term-specific templates are implemented before other changes.
*
* @param string $tweet Current tweet text.
* @param int $post_ID Current post ID.
*
* @return string New tweet.
*/
function wpt_taxonomy_template( $tweet, $post_ID ) {
$taxonomies = get_post_taxonomies( $post_ID );
foreach ( $taxonomies as $tax ) {
$terms = get_the_terms( $post_ID, $tax );
if ( is_array( $terms ) ) {
foreach ( $terms as $term ) {
$template = get_term_meta( $term->term_id, '_wpt_term_template', true );
if ( '' !== $template ) {
/**
* Filter the Tweet template for Tweets in a specific term.
*
* @hook wpt_term_template_filter
*
* @param {string} $template The template to use to generate Tweets.
* @param {int} $term_id Term ID.
*
* @return {string}
*/
return apply_filters( 'wpt_term_template_filter', $template, $term->term_id );
}
}
}
}
return $tweet;
}
add_filter( 'wpt_tweet_sentence', 'wpt_taxonomy_template', 9, 2 );
/**
* Add Twitter user settings to user account profile.
*
* @return string
*/
function wpt_twitter_user_fields() {
$current_user = wp_get_current_user();
$edit_id = ( isset( $_GET['user_id'] ) ) ? (int) $_GET['user_id'] : $current_user->ID;
$templates = get_user_meta( $edit_id, 'wpt_templates', true );
$reposts = get_user_meta( $edit_id, 'wpt_retweet_repeat', true );
$edit = ( isset( $templates['edit'] ) ) ? $templates['edit'] : '';
$new = ( isset( $templates['new'] ) ) ? $templates['new'] : '';
$num_reposts = ( '' === $reposts ) ? get_option( 'wpt_retweet_repeat', '' ) : $reposts;
return sprintf(
"<tr><th scope='row'><label for='wpt_new'>" . __( 'Tweet Template for new posts:', 'wp-tweets-pro' ) . '</label></th><td><input type="text" class="regular-text" name="wpt_templates[new]" id="wpt_new" value="%1$s" /></td></tr>' . "
<tr><th scope='row'><label for='wpt_edit'>" . __( 'Tweet Template for edited posts:', 'wp-tweets-pro' ) . '</label></th><td><input type="text" class="regular-text" name="wpt_templates[edit]" id="wpt_edit" value="%2$s" /></td></tr>
<tr><th scope="row"><label for="wpt_retweet_repeat">' . __( 'Number of reposts', 'wp-tweets-pro' ) . '</label></th><td><select id="wpt_retweet_repeat" name="wpt_retweet_repeat">
<option value="">' . __( 'Default', 'wp-tweets-pro' ) . '</option>
<option value="0"' . selected( $num_reposts, 0, false ) . '>0</option>
<option value="1"' . selected( $num_reposts, 1, false ) . '>1</option>
<option value="2"' . selected( $num_reposts, 2, false ) . '>2</option>
<option value="3"' . selected( $num_reposts, 3, false ) . '>3</option>
</select></td></tr>',
$new,
$edit
);
}
add_filter( 'wpt_twitter_user_fields', 'wpt_twitter_user_fields' );
/**
* Filter Tweet to use current user's defined template.
*
* @param string $text Current text.
* @param string $status Current publication status.
* @param boolean $alt Use alternate.
* @param int $auth Current author.
*
* @return string new text.
*/
function wpt_filter_user_text( $text, $status, $alt = false, $auth = false ) {
global $current_user;
if ( '' !== $text && ! $alt ) {
return $text;
}
$auth = ( ! $auth ) ? $current_user->ID : intval( $auth );
$user_text = get_user_meta( $auth, 'wpt_templates', true );
if ( 'publish' !== $status ) {
if ( isset( $user_text['new'] ) && '' !== trim( $user_text['new'] ) ) {
$text = stripcslashes( $user_text['new'] );
}
} else {
if ( isset( $user_text['edit'] ) && '' !== trim( $user_text['edit'] ) ) {
$text = stripcslashes( $user_text['edit'] );
}
}
return $text;
}
add_filter( 'wpt_user_text', 'wpt_filter_user_text', 10, 3 );
/**
* Handle scheduled Tweets
*
* @param int $id Author ID.
* @param string $sentence Tweet text.
* @param int $rt repost count.
* @param int $post_id post ID.
*/
function wpt_schedule_tweet( $id, $sentence, $rt, $post_id ) {
wpt_mail( "Scheduled Action Happening: #$id", "$sentence, $rt, $post_id", $post_id ); // DEBUG.
// check whether the last autopost Tweet was the same as this one.
$last_autopost_tweet = get_option( 'wpt_last_autopost_tweet' );
/**
* Render the template of a scheduled Tweet only at the time it's sent.
*
* @hook wpt_postpone_rendering
* @param {bool} $postpone True to postpone rendering.
*
* @return {bool}
*/
$postpone_rendering = apply_filters( 'wpt_postpone_rendering', get_option( 'wpt_postpone_rendering', 'false' ) );
if ( 'false' !== $postpone_rendering ) {
$post_info = wpt_post_info( $post_id );
$sentence = jd_truncate_tweet( $sentence, $post_info, $post_id );
wpt_mail( "Postponed Tweet Rendering: #$id", "$sentence, $rt, $post_id", $post_id ); // DEBUG.
}
if ( $sentence === $last_autopost_tweet ) {
// If this Tweet is the same as the last autoposted Tweet, do not send it.
// Prevents runaway cron jobs. Possibly duplicates existing check, but earlier.
die;
}
$media = ( ( '1' === get_option( 'wpt_media' ) ) && ( has_post_thumbnail( $post_id ) || wpt_post_attachment( $post_id ) ) ) ? true : false;
/**
* Customize whether media should be uploaded for the current Tweet action.
*
* @hook wpt_scheduled_media
*
* @param {bool} $media True to post media; false to not.
* @param {int} $post_id Post ID.
* @param {int} $rt Which time this is being reposted, if a repost.
*
* @return {bool}
*/
$media = apply_filters( 'wpt_scheduled_media', $media, $post_id, $rt ); // filter based on post ID.
// generate hash of this Tweet's data.
$attachment = wpt_post_attachment( $post_id );
$hash = md5( "$sentence, $id, $post_id, $media, $attachment" );
// check whether this exact Tweet has already occurred.
$action = wpt_check_action( $hash );
if ( ! $action ) {
wpt_post_to_service( $sentence, $id, $post_id, $media );
wpt_register_action( $hash );
}
}
add_action( 'wpt_schedule_tweet_action', 'wpt_schedule_tweet', 10, 4 );
/**
* Filter upload to send custom attachment to Twitter.
*
* @param integer $attachment Attachment to send.
* @param integer $post_ID Post ID.
*
* @return integer
*/
function wpt_custom_attachment( $attachment, $post_ID ) {
$custom_image = get_post_meta( $post_ID, '_wpt_custom_image', true );
if ( $custom_image ) {
return $custom_image;
}
return $attachment;
}
add_filter( 'wpt_post_attachment', 'wpt_custom_attachment', 10, 2 );
/**
* Get stored options of last 100 scheduled Tweets and check against it. This is protection against run away cron jobs.
*
* @param string $hash hash of Tweet text, author, post ID, and media configuration.
*
* @return boolean true if found
*/
function wpt_check_action( $hash ) {
$stored = get_option( 'wpt_scheduled_tweets' );
if ( ! is_array( $stored ) ) {
// If nothing is stored, no Tweet will be found.
return false;
}
$check = ( in_array( $hash, $stored, true ) ) ? true : false;
return $check;
}
/**
* Store hash of last scheduled Tweet.
*
* @param string $hash hash of Tweet text, author, post ID, and media configuration.
*/
function wpt_register_action( $hash ) {
$stored = get_option( 'wpt_scheduled_tweets' );
if ( is_array( $stored ) ) {
// trim array to 99 items; removed oldest, add to end.
$stored = array_slice( $stored, 1, 99 );
$stored[] = $hash;
} else {
$stored = array( $hash );
}
update_option( 'wpt_scheduled_tweets', $stored );
}
add_filter( 'wpt_scheduled_media', 'wpt_filter_scheduled_media', 10, 3 );
/**
* Handle individual repost's media settings
*
* @param boolean $media Whether to attach media to post.
* @param int $post_ID Current post ID.
* @param int $rt Current retweet value.
*
* @return boolean Whether to attach media.
*/
function wpt_filter_scheduled_media( $media, $post_ID, $rt ) {
switch ( $rt ) {
case 1:
$rt1 = get_option( 'wpt_rt_media' );
$return = ( 'true' === $rt1 ) ? false : $media;
break;
case 2:
$rt2 = get_option( 'wpt_rt_media2' );
$return = ( 'true' === $rt2 ) ? false : $media;
break;
case 3:
$rt3 = get_option( 'wpt_rt_media3' );
$return = ( 'true' === $rt3 ) ? false : $media;
break;
default:
$return = $media;
}
return $return;
}
add_filter( 'wpt_upload_media', 'wpt_filter_upload_media', 10, 2 );
/**
* If this post is configured to skip media, skip media.
*
* @param boolean $media Whether to attach media.
* @param int $post_ID Post ID.
*
* @return boolean
*/
function wpt_filter_upload_media( $media, $post_ID ) {
$skip = get_post_meta( $post_ID, '_wpt_image', true );
if ( 1 === (int) $skip ) {
return false;
}
return $media;
}
add_filter( 'wpt_custom_retweet_fields', 'wpt_retweet_custom_tweets', 10, 2 );
/**
* Setup individual fields for each custom Tweet text field.
*
* @param string $output HTML output of fields.
* @param int $post_ID Post ID.
*
* @return boolean
*/
function wpt_retweet_custom_tweets( $output, $post_ID = false ) {
$repeat = get_post_meta( $post_ID, '_wpt_retweet_repeat', true );
$repeat = ( $repeat ) ? $repeat : get_option( 'wpt_retweet_repeat' );
$custom_tweets = ( $post_ID ) ? get_post_meta( $post_ID, '_wpt_retweet_text', true ) : false;
$custom_times = ( $post_ID ) ? get_post_meta( $post_ID, '_wpt_retweet_delay', true ) : false;
if ( $repeat > 0 ) {
$output = "<p class='panel-toggle'><a href='#wpt_custom_retweets' class='tweet-toggle'><span class='dashicons dashicons-plus' aria-hidden='true'></span>" . __( 'Add custom retweets', 'wp-tweets-pro' ) . "</a></p><div class='expandable' id='wpt_custom_retweets'>";
for ( $i = 0; $i < $repeat; $i++ ) {
$n = $i + 1;
if ( $custom_tweets && ! empty( $custom_tweets ) ) {
$tweet = ( isset( $custom_tweets[ $i ] ) ) ? $custom_tweets[ $i ] : '';
} else {
if ( 'prefix' === get_option( 'wpt_custom_type' ) ) {
$tweet = '';
} else {
$x = ( 1 === $n ) ? '' : $n;
$tweet = get_option( "wpt_prepend_rt$x" );
}
}
if ( $custom_times && ! empty( $custom_times ) ) {
$time = ( isset( $custom_times['time'][ $i ] ) ) ? $custom_times['time'][ $i ] : '';
$date = ( isset( $custom_times['date'][ $i ] ) ) ? $custom_times['date'][ $i ] : '';
} else {
$time = '';
$date = '';
}
// Translators: retweet number.
$output .= '<fieldset><legend>' . sprintf( __( 'Retweet %d', 'wp-tweets-pro' ), $n ) . "</legend><p class='jtw'><label for='wpt_retweet_$i'>" . sprintf( __( 'Custom Tweet', 'wp-tweets-pro' ), $n ) . "</label> <textarea class='wpt_tweet_box' name='_wpt_retweet_text[]' id='wpt_retweet_$i'>" . esc_attr( stripslashes( $tweet ) ) . '</textarea></p>';
// Translators: retweet number.
$output .= "<p class='jtw2'><label for='wpt_retweet_delay_date_$i'>" . sprintf( __( 'Date (%d)', 'wp-tweets-pro' ), $n ) . "</label> <input type='text' class='wpt_date wpt_delay_time' name='_wpt_retweet_delay[date][]' id='wpt_retweet_delay_date_$i' value='" . esc_attr( $date ) . "'><br />";
// Translators: retweet number.
$output .= "<label for='wpt_retweet_delay_time_$i'>" . sprintf( __( 'Time (%d)', 'wp-tweets-pro' ), $n ) . "</label> <input type='text' class='wpt_time wpt_delay_time' name='_wpt_retweet_delay[time][]' id='wpt_retweet_delay_time_$i' value='" . esc_attr( $time ) . "'></p></fieldset>";
}
$output .= '</div>';
}
return $output;
}
/**
* Form to input XPoster Pro settings in XPoster meta box
*
* @param int $post_id Post ID.
* @param string $display Controls or hidden inputs.
*/
function wpt_schedule_values( $post_id, $display = 'normal' ) {
$delay = get_post_meta( $post_id, '_wpt_delay_tweet', true );
$retweet = get_post_meta( $post_id, '_wpt_retweet_after', true );
// this looks awkward, but it makes sense, really.
$cotweet = get_post_meta( $post_id, '_wpt_cotweet', true );
$cotweet = ( $cotweet ) ? true : get_option( 'wpt_cotweet' );
$cotweet = ( $cotweet ) ? true : false;
$repeat = ( false === (bool) get_post_meta( $post_id, '_wpt_retweet_repeat', true ) ) ? get_option( 'wpt_retweet_repeat' ) : get_post_meta( $post_id, '_wpt_retweet_repeat', true );
$upload = ( 1 === (int) get_post_meta( $post_id, '_wpt_image', true ) ) ? 'no' : 'yes';
$wpt_images = ( 1 === (int) get_option( 'wpt_media' ) ) ? 'yes' : 'no';
$noautopost = get_post_meta( $post_id, '_wpt_noautopost', true );
if ( 'hidden' === $display ) {
?>
<input type='hidden' name='_wpt_cotweet' value='<?php echo ( $cotweet ) ? 'on' : ''; ?>' />
<input type='hidden' name='_wpt_delay_tweet' value='<?php echo ( $delay ) ? $delay : get_option( 'wpt_delay_tweets' ); ?>' />
<input type='hidden' name='_wpt_retweet_after' value='<?php echo ( $retweet ) ? $retweet : get_option( 'wpt_retweet_after' ); ?>' />
<input type='hidden' name='_wpt_retweet_repeat' value='<?php echo ( $repeat ) ? $repeat : get_option( 'wpt_retweet_repeat' ); ?>' />
<input type='hidden' name='_wpt_noautopost' value='<?php echo $noautopost; ?>' />
<?php
} else {
?>
<h3><?php _e( 'Reposting Rules', 'wp-tweets-pro' ); ?></h3>
<p>
<label for="wtd"><?php _e( 'Delay posting (in minutes)', 'wp-tweets-pro' ); ?></label><br /><input type="text" name="_wpt_delay_tweet" size="3" value="<?php echo ( false !== (bool) $delay ) ? $delay : get_option( 'wpt_delay_tweets' ); ?>" id="wtd" /> <input type='checkbox' value='on' name='wpt-no-delay' id='wpt-no-delay' /> <label for='wpt-no-delay'><?php _e( 'No delay', 'wp-tweets-pro' ); ?></label>
</p>
<p>
<label for="wtr"><?php _e( 'Repost after (hours)', 'wp-tweets-pro' ); ?></label><br /><input type="text" name="_wpt_retweet_after" size="3" value="<?php echo ( false !== (bool) $retweet ) ? $retweet : get_option( 'wpt_retweet_after' ); ?>" id="wtr" /> <input type='checkbox' value='on' name='wpt-no-repost' id='wpt-no-repost' /> <label for='wpt-no-repost'><?php _e( 'No repost', 'wp-tweets-pro' ); ?></label>
</p>
<?php
if ( 1 === (int) get_option( 'jd_individual_twitter_users' ) && wpt_get_authorized_users() ) {
?>
<p>
<?php
$checked = ( $cotweet ) ? ' checked="checked"' : '';
?>
<input type='checkbox' value='on' name='_wpt_cotweet' id='wpt_cotweet'<?php echo $checked; ?> /> <label for='wpt_cotweet'><?php _e( 'Co-tweet to site Twitter account', 'wp-tweets-pro' ); ?></label>
</p>
<?php
}
?>
<p>
<label for="wrr"><?php _e( 'Number of reposts', 'wp-tweets-pro' ); ?></label>
<select name="_wpt_retweet_repeat" id="wrr">
<?php
/**
* Adjust the values available to choose for setting the number of times a Tweet can be reposted. Default `4`.
*
* @hook wpt_tweet_repeat_count
*
* @param {int} $count Maximum number of times a Tweet can be reposted.
*
* @return {int}
*/
$retweet_repeat_count = apply_filters( 'wpt_tweet_repeat_count', 4 );
for ( $i = 0; $i < $retweet_repeat_count; $i++ ) {
print( '<option value="' . $i . '"' . selected( $repeat, $i, false ) . '>' . $i . ' </option>' );
}
?>
</select>
</p>
<?php
if ( '' !== get_option( 'wpt_schedule' ) ) {
?>
<p>
<input type='checkbox' value='1' id='wpt_noautopost' name='_wpt_noautopost'<?php checked( $noautopost, 1 ); ?> /> <label for='wpt_noautopost'><?php _e( 'Omit from autoposting', 'wp-tweets-pro' ); ?></label>
</p>
<?php
}
$cards = ( 1 === (int) get_option( 'wpt_twitter_card' ) || 1 === (int) get_option( 'wpt_og_card' ) ) ? true : false;
$images = ( 1 === (int) get_option( 'wpt_media' ) ) ? true : false;
$player_card_enabled = get_option( 'wpt_player_card', '0' );
$selector = ( 1 === (int) get_option( 'wpt_media' ) || '1' === $player_card_enabled ) ? true : false;
if ( $cards || $images || $selector ) {
?>
<h3><?php _e( 'Media Settings', 'wp-tweets-pro' ); ?></h3>
<?php
if ( $cards ) {
$card = ( '' !== get_post_meta( $post_id, '_wpt_twitter_card', true ) ) ? get_post_meta( $post_id, '_wpt_twitter_card', true ) : get_option( 'wpt_twitter_card_type' );
$video_url = ( '' !== get_post_meta( $post_id, '_wpt_video_source', true ) ) ? get_post_meta( $post_id, '_wpt_video_source', true ) : '';
$subtitle = ( '' !== get_post_meta( $post_id, '_wpt_video_subtitle', true ) ) ? get_post_meta( $post_id, '_wpt_video_subtitle', true ) : '';
$ratio = ( '' !== get_post_meta( $post_id, '_wpt_video_ratio', true ) ) ? get_post_meta( $post_id, '_wpt_video_ratio', true ) : '';
?>
<p>
<label for='wpt_twitter_card'><?php _e( 'Preview Card', 'wp-tweets-pro' ); ?></label>
<select name='_wpt_twitter_card' id='wpt_twitter_card' />
<option value='summary'<?php selected( $card, 'summary' ); ?>><?php _e( 'Summary', 'wp-tweets-pro' ); ?></option>
<option value='summary_large_image'<?php selected( $card, 'summary_large_image' ); ?>><?php _e( 'Summary, Large Image', 'wp-tweets-pro' ); ?></option>
<option value='player'<?php selected( $card, 'player' ); ?>><?php _e( 'Player', 'wp-tweets-pro' ); ?></option>
</select>
</p>
<?php
if ( '1' === $player_card_enabled ) {
?>
<div class="wpt-player-card-settings">
<p id="wpt_player_instructions">
<?php
_e( 'Add links to Vimeo, YouTube, or upload <code>.mp4</code> videos. Caption file only used with uploaded videos.', 'wp-tweets-pro' );
$test_url = wpt_get_player_video( $post_id );
if ( $test_url ) {
echo '<p class="wpt-test"><a href="' . esc_url( add_query_arg( 'test', 'true', $test_url ) ) . '">' . __( 'Check your video embed', 'wp-tweets-pro' ) . '</a></p>';
}
?>
</p>
<div>
<label for="wpt_video_source"><?php _e( 'Video URL (.mp4, YouTube, Vimeo)', 'wp-tweets-pro' ); ?></label>
<div class='wpt-wrap'>
<input type="url" name="_wpt_video_source" id="wpt_video_source" placeholder="e.g. https://vimeo.com/video_ID" aria-describedby="wpt_player_instructions" value="<?php echo esc_url( $video_url ); ?>" /> <button class="button-secondary" type="button" id="wpt_video_select"><span class="dashicons dashicons-upload" aria-hidden="true"></span><span class="screen-reader-text"><?php _e( 'Upload or Select', 'wp-tweets-pro' ); ?></span></button>
</div>
</div>
<div>
<label for="wpt_video_subtitle"><?php _e( 'Captions URL (.vtt)', 'wp-tweets-pro' ); ?></label>
<div class='wpt-wrap'>
<input type="url" name="_wpt_video_subtitle" id="wpt_video_subtitle" placeholder="e.g. <?php echo home_url(); ?>/captions.vtt" value="<?php echo esc_url( $subtitle ); ?>" /> <button class="button-secondary" type="button" id="wpt_caption_select"><span class="dashicons dashicons-upload" aria-hidden="true"></span><span class="screen-reader-text"><?php _e( 'Upload or Select', 'wp-tweets-pro' ); ?></span></button>
</div>
</div>
<p>
<label for="wpt_video_ratio"><?php _e( 'Video aspect ratio', 'wp-tweets-pro' ); ?></label>
<select name="_wpt_video_ratio" id="wpt_video_ratio">
<option value='16:9'<?php selected( $ratio, '16:9' ); ?>>16:9 (<?php _e( 'Standard TV, common', 'wp-tweets-pro' ); ?>)</option>
<option value='4:3'<?php selected( $ratio, '4:3' ); ?>>4:3 (<?php _e( 'Classic TV/film', 'wp-tweets-pro' ); ?>)</option>
<option value='1.85'<?php selected( $ratio, '1.85' ); ?>>1.85 (<?php _e( 'Cinema/widescreen', 'wp-tweets-pro' ); ?>)</option>
<option value='2.39'<?php selected( $ratio, '2.39' ); ?>>2.39 (<?php _e( 'Cinema/anamorphic', 'wp-tweets-pro' ); ?>)</option>
</select>
</p>
</div>
<?php
}
}
$checked = ( 'no' === $upload && 'no' === $wpt_images ) ? 'no' : $upload;
$checked = ( 'yes' !== $checked && 'no' !== $checked ) ? 'no' : $checked;
$custom_image = get_post_meta( $post_id, '_wpt_custom_image', true );
$alt = ( $custom_image ) ? get_post_meta( $custom_image, '_wp_attachment_image_alt', true ) : '';
$image_html = ( $custom_image ) ? wp_get_attachment_image( $custom_image, 'medium', false, array( 'alt' => $alt ) ) : '';
if ( $images ) {
/**
* Set the default state of the upload image toggle input when setting Tweet status. Default depends on post meta data.
*
* @hook wpt_default_upload_image
*
* @param {string} $checked 'No' to not upload; 'yes' to upload.
* @param {string} $upload The setting for this post.
*
* @return {string}
*/
$checked = apply_filters( 'wpt_default_upload_image', $checked, $upload );
?>
<p class='toggle-btn-group'>
<input type='radio' name='_wpt_image' id='wpt_image_no' value='1'<?php checked( $checked, 'no' ); ?> /> <label for='wpt_image_no'><?php _e( 'No upload', 'wp-tweets-pro' ); ?></label>
<input type='radio' name='_wpt_image' id='wpt_image_yes' value='0'<?php checked( $checked, 'yes' ); ?> /> <label for='wpt_image_yes'><?php _e( 'Upload image', 'wp-tweets-pro' ); ?></label>
</p>
<?php
}
if ( $selector ) {
?>
<div class='wpt_custom_image field-holder'>
<div id='wpt_selected_image'><?php echo $image_html; ?></div>
<button id='wpt_custom_image_select' type='button' class='button-secondary'><?php _e( 'Choose Custom Image', 'wp-tweets-pro' ); ?></button>
<input type='hidden' name='_wpt_custom_image' id='wpt_image_id' value='<?php echo $custom_image; ?>' />
</div>
<?php
}
}
}
}
if ( ! function_exists( 'wpt_pro_exists' ) ) {
/**
* Define functional existence.
*/
function wpt_pro_exists() {
return true;
}
}
add_action( 'admin_notices', 'wpt_admin_notice' );
/**
* Create admin notices when license not entered.
*/
function wpt_admin_notice() {
global $current_screen;
if ( stripos( $current_screen->id, 'wp-tweets-pro' ) || stripos( $current_screen->id, 'wp-to-twitter' ) ) {
if ( ! ( 'active' === get_option( 'wpt_license_valid' ) || 'valid' === get_option( 'wpt_license_valid' ) || 'true' === get_option( 'wpt_license_valid' ) ) ) {
if ( ! isset( $_POST['wpt_license_key'] ) ) {
// Translators: URL to Pro Settings screen.
$message = sprintf( __( "You must <a href='%s'>enter your XPoster Pro license key</a> for support & updates to XPoster Pro features.", 'wp-tweets-pro' ), admin_url( 'admin.php?page=wp-tweets-pro&tab=pro' ) );
if ( ! current_user_can( 'manage_options' ) ) {
return;
} else {
echo "<div class='error'><p>$message</p></div>";
}
}
}
}
}
/**
* Generate a list of active post types.
*
* @param string $root URL.
*
* @return string
*/
function wpt_types_list( $root ) {
$settings = ( is_array( get_option( 'wpt_post_types' ) ) ) ? get_option( 'wpt_post_types' ) : array();
$post_types = array_keys( $settings );
$types = '';
$i = 0;
foreach ( $post_types as $pt ) {
if ( '1' === (string) $settings[ $pt ]['post-published-update'] || '1' === (string) $settings[ $pt ]['post-edited-update'] ) {
++$i;
$post_type = get_post_type_object( $pt );
if ( ! $post_type ) {
// translators: Post type label.
$post_type_name = sprintf( __( '%s (inactive)', 'wp-tweets-pro' ), $pt );
} else {
$post_type_name = ( '' !== $post_type->label ) ? $post_type->label : $post_type->labels->singular_name;
}
$active = ( isset( $_GET['ptype'] ) ) ? $_GET['ptype'] : 'post';
if ( $pt === $active ) {
$types .= "<a href='$root&ptype=$pt' class='nav-tab nav-tab-active' aria-current='true'>$post_type_name</a>";
} else {
$types .= "<a href='$root&ptype=$pt' class='nav-tab'>$post_type_name</a>";
}
}
}
$types = ( $i > 1 ) ? '<h3 id="wpt-nav">' . __( 'Filter by post type', 'wp-tweets-pro' ) . "</h3>
<nav class='nav-tab-wrapper' aria-labelledby='wpt-nav'>
$types
</nav>" : '';
return $types;
}
/**
* Get the default enabled post type.
*
* @return string
*/
function wpt_default_type() {
$settings = ( is_array( get_option( 'wpt_post_types' ) ) ) ? get_option( 'wpt_post_types' ) : array();
$post_types = array_keys( $settings );
foreach ( $post_types as $pt ) {
if ( '1' === (string) $settings[ $pt ]['post-published-update'] || '1' === (string) $settings[ $pt ]['post-edited-update'] ) {
return $pt;
}
}
// Default is 'post' if nothing active.
return 'post';
}
/**
* Provide feedback about user accounts, when features are enabled that depend on that option.
*/
function wpt_notes() {
$is_enabled = get_option( 'jd_individual_twitter_users' );
if ( $is_enabled ) {
$message = '<em>' . __( 'Individual Author accounts are enabled.', 'wp-tweets-pro' ) . '</em>';
} else {
$admin_url = admin_url( 'admin.php?page=wp-tweets-pro&tab=advanced#indauthors' );
// translators: URL for advanced settings.
$message = sprintf( __( "<em>Enable individual Author accounts in <a href='%s'>Advanced Settings</a>.</em>", 'wp-tweets-pro' ), $admin_url );
}
print( '
<div class="ui-sortable meta-box-sortables wp-tweets-notes">
<div class="postbox">
<h3><span>' . __( 'XPoster Pro Notes', 'wp-tweets-pro' ) . '</span></h3>
<div class="inside">
<p>' . __( 'Most XPoster Pro settings can also be set on a per-post basis. Leave empty for instant posting and no re-post.', 'wp-tweets-pro' ) . '</p>
<p>' . __( 'Twitter blocks identical Tweets. Prepend text to differentiate reposts.', 'wp-tweets-pro' ) . '</p>
<p>' . __( 'Additional Twitter accounts are added in user profiles.', 'wp-tweets-pro' ) . ' ' . $message . '</p>
</div>
</div>
</div>' );
}
/**
* Get array of users authorized to post to Twitter.
*
* @return bool|array
*/
function wpt_get_authorized_users() {
$args = array(
'meta_query' => array(
array(
'key' => 'wtt_twitter_username',
'compare' => 'EXISTS',
),
),
);
// get all authorized users.
$users = get_users( $args );
$authorized_users = array();
if ( is_array( $users ) ) {
foreach ( $users as $this_user ) {
if ( wtt_oauth_test( $this_user->ID, 'verify' ) ) {
$twitter = get_user_meta( $this_user->ID, 'wtt_twitter_username', true );
$authorized_users[] = array(
'ID' => $this_user->ID,
'name' => $this_user->display_name,
'twitter' => $twitter,
);
}
}
} else {
$authorized_users = false;
}
return $authorized_users;
}
/**
* Get list of users authorized to post to Twitter
*
* @param array $selected Authors selected in this context.
*
* @return string HTML select field.
*/
function wpt_authorized_users( $selected = array() ) {
/**
* Override authors available to select to send Tweets to. Default `false`.
*
* @hook wpt_override_author_selection
* @param {bool|string} $override False or completely realized `select` field with name `_wpt_authorized_users[]`.
*
* @return {bool|string}
*/
$override = apply_filters( 'wpt_override_author_selection', false );
if ( $override ) {
return $override;
}
if ( ! is_array( $selected ) ) {
return $override;
}
global $user_ID;
$users = get_option( 'wpt_authorized_users' );
if ( ! $users ) {
$authorized_users = wpt_get_authorized_users();
update_option( 'wpt_authorized_users', $authorized_users );
$users = $authorized_users;
}
$main_account = get_option( 'wtt_twitter_username' );
$select = "<p class='wpt_auth_users'><label for='wpt_authorized_users'>" . __( 'Tweet to:', 'wp-tweets-pro' ) . "</label><br /><select multiple='multiple' name='_wpt_authorized_users[]' id='wpt_authorized_users'>
<option value='main'>" . __( 'Main:', 'wp-tweets-pro' ) . " @$main_account</option>";
if ( ! empty( $users ) ) {
foreach ( $users as $user ) {
$current = $user_ID;
$active = '';
// if this has been directly pulled, these are objects. Otherwise, arrays.
if ( is_object( $user ) ) {
$id = $user->ID;
$name = $user->display_name;
$twitter = get_user_meta( $id, 'wtt_twitter_username', true );
} else {
$id = $user['ID'];
$name = $user['name'];
$twitter = $user['twitter'];
}
global $post;
if ( ( $id === $current && $current === $post->post_author ) || in_array( $id, $selected, true ) ) {
$active = ' selected="selected"';
}
$select .= " <option value='$id'$active>$name (@$twitter)</option>\n";
}
}
$select .= '</select></p>';
return $select;
}
/**
* Add custom JS
*/
function wpt_add_js() {
global $current_screen;
if ( 'xposter-pro_page_wp-to-twitter-tweets' === $current_screen->id || 'xposter-pro_page_wp-to-twitter-errors' === $current_screen->id ) {
echo '
<script type="text/javascript">
(function ($) {
$(function() {
$("#wpt ul").hide();
$("#wpt button").attr( "aria-expanded", "false" );
$("#wpt button .dashicons" ).addClass( "dashicons-plus" );
$("#wpt th > button").on( "click", function(e) {
e.preventDefault();
var next = $(this).next("ul");
next.toggle();
if ( next.is( ":visible" ) ) {
$(this).find( ".dashicons" ).addClass( "dashicons-minus" );
$(this).find( ".dashicons" ).removeClass( "dashicons-plus" );
$(this).attr( "aria-expanded", "true" );
} else {
$(this).find( ".dashicons" ).addClass( "dashicons-plus" );
$(this).find( ".dashicons" ).removeClass( "dashicons-minus" );
$(this).attr( "aria-expanded", "false" );
}
});
})
})(jQuery);
</script>
';
}
}
add_filter( 'wpt_set_retweet_text', 'wpt_set_retweet_text', 10, 3 );
/**
* Define custom retweet text
*
* @param string $template Default template.
* @param int $rt Retweet number.
* @param int $post_id Post ID being tweeted.
*
* @return string new template.
*/
function wpt_set_retweet_text( $template, $rt, $post_id ) {
$prepend = '';
$append = '';
$option = (int) get_option( 'wpt_prepend' );
switch ( $rt ) {
case 1:
$prepend = ( 1 === $option ) ? '' : get_option( 'wpt_prepend_rt' );
$append = ( 1 !== $option ) ? '' : get_option( 'wpt_prepend_rt' );
break;
case 2:
$prepend = ( 1 === $option ) ? '' : get_option( 'wpt_prepend_rt2' );
$append = ( 1 !== $option ) ? '' : get_option( 'wpt_prepend_rt2' );
break;
case 3:
$prepend = ( 1 === $option ) ? '' : get_option( 'wpt_prepend_rt3' );
$append = ( 1 !== $option ) ? '' : get_option( 'wpt_prepend_rt3' );
break;
}
if ( 'template' === get_option( 'wpt_custom_type' ) ) {
$retweet = stripslashes( $prepend . $append );
} else {
$retweet = stripslashes( $prepend ) . $template . stripslashes( $append );
}
// get custom value.
$retweet_texts = get_post_meta( $post_id, '_wpt_retweet_text', true );
$prev_retweet = $retweet;
if ( $retweet_texts || ( isset( $_POST['_wpt_retweet_text'] ) ) ) {
$test_value = '';
$templates = ( isset( $_POST['_wpt_retweet_text'] ) ) ? $_POST['_wpt_retweet_text'] : $retweet_texts;
if ( isset( $templates[ ( $rt - 1 ) ] ) && '' !== trim( $templates[ ( $rt - 1 ) ] ) ) {
$retweet = trim( stripslashes( $templates[ ( $rt - 1 ) ] ) );
}
if ( '' === trim( $retweet ) || ! $retweet || is_array( $retweet ) ) {
$retweet = $prev_retweet;
}
}
return $retweet;
}
add_filter( 'wpt_schedule_retweet', 'wpt_schedule_retweet', 10, 4 );
/**
* Determine time for a retweet.
*
* @param string $time Timestamp.
* @param int $acct User account ID.
* @param int $rt Retweet number.
* @param array $post_info Array of post info.
*
* @return string time.
*/
function wpt_schedule_retweet( $time, $acct, $rt, $post_info ) {
// get custom value.
$post_id = $post_info['id'];
$times = get_post_meta( $post_id, '_wpt_retweet_delay', true );
if ( $times || ( isset( $_POST['_wpt_retweet_delay'] ) && ! empty( $_POST['_wpt_retweet_delay'] ) ) ) {
$prev_time = $time;
$times = ( isset( $_POST['_wpt_retweet_delay'] ) ) ? $_POST['_wpt_retweet_delay'] : $times;
if ( isset( $times['time'][ ( $rt - 1 ) ] ) && '' !== trim( $times['time'][ ( $rt - 1 ) ] ) ) {
// time is a numeric value indicating an amount of time ahead of the current time.
$time = trim( stripslashes( $times['time'][ ( $rt - 1 ) ] ) );
$date = ( isset( $times['date'][ ( $rt - 1 ) ] ) ) ? trim( stripslashes( $times['date'][ ( $rt - 1 ) ] ) ) : date( 'Y-m-d', current_time( 'timestamp' ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested, WordPress.DateTime.RestrictedFunctions.date_date
// convert time and date to diff.
if ( '' !== $date . $time ) {
$realtime = strtotime( $date . ' ' . $time );
$diff = $realtime - current_time( 'timestamp' ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
$time = $diff;
} else {
$time = '';
}
}
if ( '' === $time || ! $time || is_array( $time ) ) {
$time = $prev_time;
}
}
return $time;
}
/**
* Assume is approved, unless otherwise informed by comment validator.
*
* @param int $comment_id Comment ID.
* @param int $approved Comment status.
*
* @return comment post ID.
*/
function wpt_set_comment_tweet( $comment_id, $approved ) {
$_t = get_comment( $comment_id );
$post_ID = $_t->comment_post_ID;
$commenter = $_t->comment_author;
$comment = $_t->comment_content;
$user_id = $_t->user_id;
$excerpt_length = ( '' !== get_option( 'jd_post_excerpt', '' ) ) ? absint( get_option( 'jd_post_excerpt' ) ) : 140;
$comment_excerpt = @mb_substr( strip_tags( strip_shortcodes( $comment ) ), 0, $excerpt_length ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$comment_date = $_t->comment_date;
$dateformat = ( '' === get_option( 'jd_date_format', '' ) ) ? get_option( 'date_format' ) : get_option( 'jd_date_format' );
$comment_date = mysql2date( $dateformat, $comment_date );
$post_info = wpt_post_info( $post_ID );
$sentence = '';
/**
* Customize the URL shortening of a comment link.
*
* @hook wptt_shorten_link
*
* @param {string} $comment_url The comment link.
* @param {string} $title The post title.
* @param {int} $post_ID The post ID.
* @param {bool} $test True means this is a test run.
*
* @return {string}
*/
$comment_url = apply_filters( 'wptt_shorten_link', get_comment_link( $comment_id ), $post_info['postTitle'], $post_ID, false );
$sentence = stripcslashes( get_option( 'comment-published-text' ) );
$sentence = str_replace( '#commenter#', $commenter, $sentence );
$sentence = str_replace( '#comment#', $comment_excerpt, $sentence );
$sentence = str_replace( '#comment_date#', $comment_date, $sentence );
$sentence = str_replace( '#comment_url#', $comment_url, $sentence );
$sentence = jd_truncate_tweet( $sentence, $post_info, $post_ID );
if ( '' !== $sentence ) {
/**
* Modify the Tweet saved to comment meta prior to Tweeting.
*
* @hook wpt_filter_comment_tweet
*
* @param {string} $sentence The Tweet text to be sent.
* @param {object} $_t The comment object.
*
* @return {string}
*/
$comment_tweet = apply_filters( 'wpt_filter_comment_tweet', $sentence, $_t );
add_comment_meta( $comment_id, 'wpt_comment_tweet', $comment_tweet, true );
}
if ( user_can( $user_id, 'moderate_comments' ) || 1 === (int) $approved ) {
wpt_twit_comment( $_t );
}
return $post_ID;
}
/**
* Filter comment info to check whether this comment can be Tweeted.
*
* @param object $comment Comment object.
*
* @return boolean.
*/
function wpt_filter_comment_info( $comment ) {
$filters = get_option( 'wpt_filters' );
if ( is_array( $filters ) ) {
foreach ( $filters as $filter => $rule ) {
$comparison = $rule['type'];
$field = $rule['field'];
switch ( $field ) {
case 'postTitle':
$value = get_the_title( $comment->comment_post_ID );
break;
case 'postLink':
$value = get_the_permalink( $comment->comment_post_ID );
break;
case 'shortUrl':
$short = wpt_short_url( $comment->comment_post_ID );
break;
case 'postStatus':
$value = 'publish';
break; // comments are only on published posts.
case 'postType':
$value = get_post_type( $comment->comment_post_ID );
break;
case 'id':
$value = $comment->comment_post_ID;
break;
case 'authId':
$value = $comment->user_id;
break;
case 'postExcerpt':
$value = wpt_get_excerpt_by_id( $comment->comment_post_ID );
break;
}
switch ( $comparison ) {
case 'equals':
if ( $value === $rule['value'] ) {
return true;
}
break;
case 'notin':
if ( false === strpos( $value, $rule['value'] ) ) {
return true;
}
break;
case 'in':
if ( false !== strpos( $value, $rule['value'] ) ) {
return true;
}
break;
case 'notequals':
if ( $value !== $rule['value'] ) {
return true;
}
break;
default:
return true;
}
}
return false;
}
return false;
}
/**
* Tweet a comment.
*
* @param object $comment Comment object.
*/
function wpt_twit_comment( $comment ) {
if ( isset( $_REQUEST['tweet'] ) && 'false' === $_REQUEST['tweet'] ) {
return;
}
$block = wpt_filter_comment_info( $comment );
$delay = ( '' === get_option( 'wpt_comment_delay' ) ) ? false : get_option( 'wpt_comment_delay' );
// If $block is true block this comment.
if ( ! $block ) {
$comment_id = $comment->comment_ID;
$post_ID = $comment->comment_post_ID;
$sentence = get_comment_meta( $comment_id, 'wpt_comment_tweet', true );
if ( $sentence && ! $delay ) {
wpt_post_to_service( $sentence, false, $post_ID );
} else {
/**
* Modify the delay before posting a comment Tweet.
*
* @hook wpt_schedule_comment_delay
*
* @param {int} $delay An amount of time in minutes to delay Tweets of comments.
* @param {int} $post_ID Post ID for the post receiving a comment.
*
* @return {int}
*/
$delay = apply_filters( 'wpt_schedule_comment_delay', ( (int) $delay ) * 60, $post_ID );
wp_schedule_single_event(
time() + $delay,
'wpt_schedule_tweet_action',
array(
'id' => false,
'sentence' => $sentence,
'rt' => 0,
'post_id' => $post_ID,
)
);
}
}
}
if ( 1 === (int) get_option( 'comment-published-update' ) && ( get_option( 'comment_moderation' ) || 1 === (int) get_option( 'comment_previously_approved' ) ) ) {
add_action( 'comment_post', 'wpt_set_comment_tweet', 10, 2 );
add_action( 'comment_unapproved_to_approved', 'wpt_twit_comment', 10, 2 );
add_filter( 'manage_edit-comments_columns', 'wpt_comment_columns' );
add_filter( 'manage_comments_custom_column', 'wpt_comment_column', 10, 2 );
}
/**
* Set up comment columns.
*
* @param array $columns Columns.
*
* @return array new columns.
*/
function wpt_comment_columns( $columns ) {
$columns['wpt_comment_tweet'] = __( 'Comment Tweet', 'wp-tweets-pro' );
return $columns;
}
/**
* Fetch comment column information.
*
* @param string $column Column name.
* @param int $comment_id Comment ID.
*/
function wpt_comment_column( $column, $comment_id ) {
if ( 'wpt_comment_tweet' === $column ) {
$comment = get_comment( $comment_id );
$meta = get_comment_meta( $comment_id, $column, true );
if ( $meta ) {
echo $meta;
if ( 1 !== (int) $comment->comment_approved ) {
$approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) );
$url = "comment.php?c=$comment_id&action=approvecomment&tweet=false&$approve_nonce";
echo "<p><span class='approve'>";
// Translators: 1) comment approval URL, 2) Comment ID.
printf( __( '<a href="%1$s" data-wp-lists="dim:the-comment-list:comment-%2$d:unapproved:e7e7d3:tweet=false:new=approved" class="vim-a">Approve without Tweeting</a>', 'wp-tweets-pro' ), $url, $comment_id );
echo '</span></p>';
}
} else {
_e( 'No Tweet saved for this comment.', 'wp-tweets-pro' );
}
}
}
/**
* Set up stylesheets.
*/
function wpt_add_styles() {
global $current_screen, $wptp_version;
if ( SCRIPT_DEBUG ) {
$wptp_version .= '-' . wp_rand( 10000, 99999 );
}
wp_register_style( 'xposter-pro', plugins_url( 'css/style.css', __FILE__ ), array(), $wptp_version );
$cs = $current_screen->id;
if ( 'profile' === $cs || 'xposter-pro_page_wp-to-twitter-tweets' === $cs || 'xposter-pro_page_wp-to-twitter-errors' === $cs || 'toplevel_page_xposter-pro' === $cs || 'xposter-pro_page_wp-to-twitter-schedule' === $cs ) {
wp_enqueue_style( 'xposter-pro' );
}
}
add_action( 'admin_enqueue_scripts', 'wpt_add_styles' );
add_action( 'admin_head', 'wpt_add_js' );
add_action( 'admin_enqueue_scripts', 'wpt_enqueue_js' );
if ( 1 === (int) get_option( 'wpt_twitter_card' ) ) {
// Disable Yoast SEO card if using XPoster cards.
add_filter( 'wpseo_output_twitter_card', '__return_false' );
add_action( 'wp_head', 'wpt_twitter_card' );
}
if ( 1 === (int) get_option( 'wpt_og_card' ) ) {
add_action( 'wp_head', 'wpt_og_card' );
}
/**
* Determine type of twitter card to show
* photo cards deprecated by Twitter July 3, 2015
*
* @param int $id Post ID.
*
* @return string card type.
*/
function wpt_twitter_card_type( $id ) {
$default = get_option( 'wpt_twitter_card_type' );
$has_img = ( wp_get_attachment_url( get_post_meta( $id, '_wpt_custom_image', true ) ) || wp_get_attachment_url( get_post_thumbnail_id( $id ) ) ) ? true : false;
if ( 'photo' === get_post_meta( $id, '_wpt_twitter_card', true ) && $has_img ) {
return 'summary_large_image';
} elseif ( 'summary_large_image' === get_post_meta( $id, '_wpt_twitter_card', true ) && $has_img ) {
return 'summary_large_image';
} elseif ( 'player' === get_post_meta( $id, '_wpt_twitter_card', true ) && esc_url( get_post_meta( $id, '_wpt_video_source', true ) ) && $has_img ) {
// Player cards need to have a video URL & a poster image.
return 'player';
} else {
$post = get_post( $id );
$content = $post->post_content;
$length_limit = ( get_option( 'wpt_toggle_card' ) ) ? get_option( 'wpt_toggle_card' ) : 0;
if ( strlen( $content ) <= $length_limit && wp_get_attachment_url( get_post_thumbnail_id( $id ) ) ) {
update_post_meta( $id, '_wpt_twitter_card', 'summary_large_image' );
return 'summary_large_image';
}
}
return ( 'summary' === $default ) ? 'summary' : 'summary_large_image';
}
/**
* Generate Twitter Card
*/
function wpt_twitter_card() {
$meta = '';
if ( is_singular() ) {
$post_ID = get_the_ID();
$type = wpt_twitter_card_type( $post_ID );
$excerpt = wpt_get_excerpt_by_id( $post_ID );
$meta = '
<!-- XPoster Pro -->
<meta name="twitter:card" content="' . $type . '" />';
$meta .= '
<meta name="twitter:site" content="@' . esc_attr( get_option( 'wtt_twitter_username' ) ) . '" />
<meta name="twitter:title" content="' . esc_attr( strip_tags( get_the_title( $post_ID ) ) ) . '" />
<meta name="twitter:description" content="' . esc_attr( $excerpt ) . '" />
';
if ( 'player' === $type ) {
$url = wpt_get_player_video( $post_ID );
$ratio = get_post_meta( $post_ID, '_wpt_video_ratio', true );
switch ( $ratio ) {
// classic film/tv.
case '4:3':
$height = round( 640 / ( 4 / 3 ), 0 );
break;
// anamorphic cinema.
case '2.39':
$height = round( 640 / 2.39, 0 );
break;
// cinema widescreen.
case '1.85':
$height = round( 640 / 1.85, 0 );
break;
// Standard european/modern TV, consumer cameras.
default:
$height = round( 640 / ( 16 / 9 ), 0 );
}
// Calculate the proportional height needed for controls.
$prop = 436 / 640 * $height;
$add = round( 52 / ( $prop / $height ), 0 );
$height = $height + $add;
$meta .= '
<meta name="twitter:player" content="' . esc_url( $url ) . '" />
<meta name="twitter:player:width" content="640" />
<meta name="twitter:player:height" content="' . $height . '" />';
}
$custom_image = get_post_meta( $post_ID, '_wpt_custom_image', true );
if ( $custom_image ) {
$alt = get_post_meta( $custom_image, '_wp_attachment_image_alt', true );
$meta .= '<meta name="twitter:image" content="' . esc_url( wp_get_attachment_url( $custom_image ) ) . '">' . PHP_EOL;
$meta .= '<meta name="twitter:image:alt" content="' . esc_attr( $alt ) . '">';
} else {
if ( wp_get_attachment_url( get_post_thumbnail_id( $post_ID ) ) ) {
$thumb_id = get_post_thumbnail_id( $post_ID );
$alt = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true );
$meta .= '<meta name="twitter:image" content="' . esc_url( wp_get_attachment_url( $thumb_id ) ) . '">' . PHP_EOL;
$meta .= '<meta name="twitter:image:alt" content="' . esc_attr( $alt ) . '">' . PHP_EOL;
}
}
$meta .= '<!-- XPoster Pro -->' . "\n";
} else {
$title = ( is_archive() ) ? get_the_archive_title() : get_bloginfo( 'name' );
$description = ( is_archive() ) ? get_the_archive_description() : get_bloginfo( 'description' );
$meta = '
<!-- XPoster Pro -->
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="' . esc_attr( strip_tags( $title ) ) . '" />
<meta name="twitter:description" content="' . esc_attr( strip_tags( $description ) ) . '" />' . PHP_EOL;
if ( get_theme_mod( 'custom_logo' ) ) {
$thumb_id = get_theme_mod( 'custom_logo' );
$alt = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true );
$meta .= '
<meta name="twitter:image" content="' . esc_url( wp_get_attachment_url( $thumb_id ) ) . '">' . PHP_EOL;
$meta .= '
<meta name="twitter:image:alt" content="' . esc_attr( $alt ) . '">' . PHP_EOL;
}
$meta .= '
<!-- XPoster Pro -->' . "\n";
}
echo $meta;
}
/**
* Generate Open Graph Card
*/
function wpt_og_card() {
$meta = '';
if ( is_singular() ) {
$post_ID = get_the_ID();
$type = wpt_twitter_card_type( $post_ID );
$excerpt = wpt_get_excerpt_by_id( $post_ID );
$meta = '
<!-- XPoster Pro -->
<meta name="og:type" content="article" />';
$meta .= '
<meta name="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '" />
<meta name="og:title" content="' . esc_attr( strip_tags( get_the_title( $post_ID ) ) ) . '" />
<meta name="og:description" content="' . esc_attr( $excerpt ) . '" />
';
if ( 'player' === $type ) {
$url = wpt_get_player_video( $post_ID );
$ratio = get_post_meta( $post_ID, '_wpt_video_ratio', true );
switch ( $ratio ) {
// classic film/tv.
case '4:3':
$height = round( 640 / ( 4 / 3 ), 0 );
break;
// anamorphic cinema.
case '2.39':
$height = round( 640 / 2.39, 0 );
break;
// cinema widescreen.
case '1.85':
$height = round( 640 / 1.85, 0 );
break;
// Standard european/modern TV, consumer cameras.
default:
$height = round( 640 / ( 16 / 9 ), 0 );
}
// Calculate the proportional height needed for controls.
$prop = 436 / 640 * $height;
$add = round( 52 / ( $prop / $height ), 0 );
$height = $height + $add;
$meta .= '
<meta name="og:video" content="' . esc_url( $url ) . '" />
<meta name="og:video:width" content="640" />
<meta name="og:video:height" content="' . $height . '" />';
}
$custom_image = get_post_meta( $post_ID, '_wpt_custom_image', true );
if ( $custom_image ) {
$alt = get_post_meta( $custom_image, '_wp_attachment_image_alt', true );
$meta .= '<meta name="og:image" content="' . esc_url( wp_get_attachment_url( $custom_image ) ) . '">' . PHP_EOL;
$meta .= '<meta name="og:image:alt" content="' . esc_attr( $alt ) . '">';
} else {
if ( wp_get_attachment_url( get_post_thumbnail_id( $post_ID ) ) ) {
$thumb_id = get_post_thumbnail_id( $post_ID );
$alt = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true );
$meta .= '<meta name="og:image" content="' . esc_url( wp_get_attachment_url( $thumb_id ) ) . '">' . PHP_EOL;
$meta .= '<meta name="og:image:alt" content="' . esc_attr( $alt ) . '">' . PHP_EOL;
}
}
$meta .= '<!-- XPoster Pro -->' . "\n";
} else {
$title = ( is_archive() ) ? get_the_archive_title() : get_bloginfo( 'name' );
$description = ( is_archive() ) ? get_the_archive_description() : get_bloginfo( 'description' );
$meta = '
<!-- XPoster Pro -->
<meta name="og:type" content="website" />
<meta name="og:title" content="' . esc_attr( strip_tags( $title ) ) . '" />
<meta name="og:description" content="' . esc_attr( strip_tags( $description ) ) . '" />' . PHP_EOL;
if ( get_theme_mod( 'custom_logo' ) ) {
$thumb_id = get_theme_mod( 'custom_logo' );
$alt = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true );
$meta .= '
<meta name="og:image" content="' . esc_url( wp_get_attachment_url( $thumb_id ) ) . '">' . PHP_EOL;
$meta .= '
<meta name="og:image:alt" content="' . esc_attr( $alt ) . '">' . PHP_EOL;
}
$meta .= '
<!-- XPoster Pro -->' . "\n";
}
echo $meta;
}
/**
* Generate video URL for player cards.
*
* @param int $post_ID Post ID.
*
* @return string
*/
function wpt_get_player_video( $post_ID ) {
$video = get_post_meta( $post_ID, '_wpt_video_source', true );
$url = '';
// For remote player video cards, use URL directly. Otherwise, use local.
if ( stripos( $video, 'youtube.com' ) || stripos( $video, 'youtu.be' ) ) {
preg_match( "/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^\?&\"'>]+)/", $video, $matches );
$video_id = $matches[1];
$url = 'https://youtube.com/embed/' . $video_id;
} elseif ( stripos( $video, 'vimeo.com' ) ) {
preg_match( '%^https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\#?)(?:[?]?.*)$%im', $video, $matches );
$video_id = $matches[3];
$url = 'https://player.vimeo.com/' . $video_id;
} else {
if ( $video ) {
$url = add_query_arg( 'card', 'true', get_the_permalink( $post_ID ) );
}
}
return $url;
}
/**
* Get excerpt for use in Tweets.
*
* @param int $post Post ID.
* @param int $length Length of excerpt.
* @param string $tags Allowed tags.
* @param string $extra 'More' string.
*
* @return mixed boolean/string.
*/
function wpt_get_excerpt_by_id( $post, $length = 15, $tags = '<a><em><strong>', $extra = ' …' ) {
if ( is_int( $post ) ) {
// get the post object of the passed ID.
$post = get_post( $post );
} elseif ( ! is_object( $post ) ) {
return false;
}
if ( has_excerpt( $post->ID ) ) {
$the_excerpt = $post->post_excerpt;
} else {
$the_excerpt = $post->post_content;
}
$the_excerpt = strip_shortcodes( strip_tags( $the_excerpt ), $tags );
$the_excerpt = preg_split( '/\b/', $the_excerpt, $length * 2 + 1 );
array_pop( $the_excerpt );
$the_excerpt = implode( $the_excerpt );
$the_excerpt .= $extra;
return preg_replace( '/\s+/', ' ', trim( $the_excerpt ) );
}
/**
* Enqueue JavaScript.
*/
function wpt_enqueue_js() {
global $current_screen;
if ( ( isset( $_GET['page'] ) && 'wp-to-twitter-schedule' === $_GET['page'] ) || 'post' === $current_screen->base ) {
wp_enqueue_script( 'wpt.mediaselector', plugins_url( 'js/media.js', __FILE__ ), array( 'jquery' ) );
wp_localize_script(
'wpt.mediaselector',
'wptp',
array(
'thumbHeight' => get_option( 'thumbnail_size_h' ),
)
);
if ( function_exists( 'wp_enqueue_media' ) && ! did_action( 'wp_enqueue_media' ) ) {
wp_enqueue_media();
}
wp_enqueue_script( 'jquery-ui-autocomplete' );
wp_enqueue_script( 'wpt.suggest', plugins_url( 'js/jquery.suggest.js', __FILE__ ), array( 'jquery', 'jquery-ui-autocomplete' ) );
wp_enqueue_script( 'wpt.general', plugins_url( 'js/general.js', __FILE__ ), array( 'jquery' ), false, true );
wp_localize_script(
'wpt.suggest',
'wpta',
array(
'ajax_action' => 'wpt_post_lookup',
)
);
}
}
add_action( 'wp_ajax_wpt_post_lookup', 'wpt_post_lookup' );
/**
* Look up a post. Generic AJAX post lookup.
*/
function wpt_post_lookup() {
if ( isset( $_REQUEST['term'] ) ) {
$posts = get_posts(
array(
's' => $_REQUEST['term'],
'post_type' => wpt_allowed_post_types(),
)
);
$suggestions = array();
global $post;
foreach ( $posts as $post ) {
setup_postdata( $post );
$suggestion = array();
$suggestion['value'] = esc_html( $post->post_title );
$suggestion['id'] = $post->ID;
$suggestions[] = $suggestion;
}
echo $_GET['callback'] . '(' . json_encode( $suggestions ) . ')';
exit;
}
}
/**
* Show message confirmation of OAuth connection.
*
* @param int $id Post ID.
*/
function wpt_connect_oauth_message( $id ) {
$message = get_user_meta( $id, 'wpt-connection-message', true );
echo ( '' === $message ) ? '' : "<div id='message' class='updated'><p>$message</p></div>";
}
add_action( 'init', 'wpt_edit_terms_fields' );
/**
* Set up actions for editing terms.
*/
function wpt_edit_terms_fields() {
$args = apply_filters( 'wpt_revive_taxonomies', array() );
$taxonomies = get_taxonomies( $args );
if ( ! is_array( $taxonomies ) ) {
$taxonomies = array();
}
foreach ( $taxonomies as $value ) {
add_action( $value . '_add_form_fields', 'wpt_add_term', 10, 1 );
add_action( $value . '_edit_form_fields', 'wpt_edit_term', 10, 2 );
add_action( 'edit_' . $value, 'wpt_save_term', 10, 2 );
add_action( 'created_' . $value, 'wpt_save_term', 10, 2 );
}
}
/**
* Save custom fields for a term.
*
* @param int $term_id Term ID.
* @param int $tax_id Taxonomy ID.
*/
function wpt_save_term( $term_id, $tax_id ) {
$option_set = (int) get_option( "wpt_taxonomy_revive_$term_id" );
if ( isset( $_POST['taxonomy'] ) ) {
if ( isset( $_POST['wpt_term_template'] ) ) {
update_term_meta( $term_id, '_wpt_term_template', trim( strip_tags( sanitize_textarea_field( $_POST['wpt_term_template'] ) ) ) );
}
$taxonomy = sanitize_text_field( $_POST['taxonomy'] );
if ( isset( $_POST['wpt_term_revive'] ) && 1 !== $option_set ) {
update_option( "wpt_taxonomy_revive_$term_id", 1 );
$args = array(
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'field' => 'id',
'terms' => $term_id,
),
),
'fields' => 'ids',
'posts_per_page' => -1,
);
$posts = new WP_Query( $args );
foreach ( $posts->posts as $post ) {
update_post_meta( $post, '_wpt_noautopost', 1 );
}
} elseif ( ! isset( $_POST['wpt_term_revive'] ) && 1 === $option_set ) {
delete_option( "wpt_taxonomy_revive_$term_id" );
$args = array(
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'field' => 'id',
'terms' => $term_id,
),
),
'fields' => 'ids',
'posts_per_page' => -1,
);
$posts = new WP_Query( $args );
foreach ( $posts->posts as $post ) {
delete_post_meta( $post, '_wpt_noautopost' );
}
}
}
}
/**
* Fields to edit on term editor.
*
* @param object $term Term object.
* @param object $taxonomy Taxonomy object. [not used].
*/
function wpt_edit_term( $term, $taxonomy ) {
$t_id = $term->term_id;
$term_meta = get_option( "wpt_taxonomy_revive_$t_id" );
$template = get_term_meta( $t_id, '_wpt_term_template', true );
?>
<tr class="form-field">
<th valign="top" scope="row">
<label for="wpt_term_revive"><?php _e( "Don't autotweet this term", 'wp-tweets-pro' ); ?></label>
</th>
<td>
<input type='checkbox' value='1' name='wpt_term_revive' id='wpt_term_revive'<?php checked( $term_meta, 1 ); ?> />
</td>
</tr>
<tr class="form-field">
<th valign="top" scope="row">
<label for="wpt_term_template"><?php _e( 'Term Tweet Template', 'wp-tweets-pro' ); ?></label>
</th>
<td>
<input type='text' value='<?php echo esc_attr( $template ); ?>' name='wpt_term_template' id='wpt_term_template' />
</td>
</tr>
<?php
}
/**
* Custom fields on new term screen.
*
* @param object $tag Not used.
*/
function wpt_add_term( $tag ) {
?>
<div class="form-field">
<input type='checkbox' value='1' id='wpt_term_revive' name='wpt_term_revive' /> <label for="wpt_term_revive" style='display: inline;'><?php _e( "Don't autotweet this term", 'wp-tweets-pro' ); ?></label>
</div>
<div class="form-field">
<label for="wpt_term_template" style='display: inline;'><?php _e( 'Term Tweet Template', 'wp-tweets-pro' ); ?></label>
<input type='text' value='' id='wpt_term_template' name='wpt_term_template' />
</div>
<?php
}
if ( '1' === get_option( 'wpt_use_cats' ) ) {
add_action( 'post_category_add_form_fields', 'wpt_add_tag' );
add_action( 'post_category_edit_form_fields', 'wpt_edit_tag' );
add_action( 'edited_post_category', 'wpt_save_tag', 10, 2 );
add_action( 'created_post_category', 'wpt_save_tag', 10, 2 );
} else {
add_action( 'post_tag_add_form_fields', 'wpt_add_tag' );
add_action( 'post_tag_edit_form_fields', 'wpt_edit_tag' );
add_action( 'edited_post_tag', 'wpt_save_tag', 10, 2 );
add_action( 'created_post_tag', 'wpt_save_tag', 10, 2 );
}
/**
* Enable terms other than post and category to customize tags for hashtags. Return an array of taxonomy names to enable those taxonomies.
*
* @hook wpt_hash_tag_sources
*
* @param {bool|array} $taxonomies Additional taxonomies that should be supported for Tweet customization fields.
*
* @return {bool|array}
*/
$wpt_additional_taxonomies = apply_filters( 'wpt_hash_tag_sources', false );
if ( is_array( $wpt_additional_taxonomies ) && ! empty( $wpt_additional_taxonomies ) ) {
foreach ( $wpt_additional_taxonomies as $key => $taxonomy ) {
add_action( $taxonomy . '_add_form_fields', 'wpt_add_tag' );
add_action( $taxonomy . '_edit_form_fields', 'wpt_edit_tag' );
add_action( 'edited_' . $taxonomy, 'wpt_save_tag', 10, 2 );
add_action( 'created_' . $taxonomy, 'wpt_save_tag', 10, 2 );
}
}
/**
* Save tag information.
*
* @param int $term_id Term ID.
*/
function wpt_save_tag( $term_id ) {
if ( isset( $_POST['wpt_tag'] ) ) {
$wpt_tag = sanitize_text_field( $_POST['wpt_tag'] );
update_option( "wpt_taxonomy_$term_id", $wpt_tag );
}
}
/**
* Edit tag fields.
*
* @param object $term Term Object.
*/
function wpt_edit_tag( $term ) {
$t_id = $term->term_id;
$term_meta = (int) get_option( "wpt_taxonomy_$t_id" );
?>
<tr class="form-field">
<th valign="top" scope="row">
<label for="wpt_tag"><?php _e( 'Tweet tag as', 'wp-tweets-pro' ); ?></label>
</th>
<td>
<select name="wpt_tag" id="wpt_tag">
<option value='1'<?php echo ( 1 === $term_meta ) ? "selected='selected'" : ''; ?>>#tag</option>
<option value='2'<?php echo ( 2 === $term_meta ) ? "selected='selected'" : ''; ?>>$tag</option>
<option value='5'<?php echo ( 5 === $term_meta ) ? "selected='selected'" : ''; ?>>@tag</option>
<option value='4'<?php echo ( 4 === $term_meta ) ? "selected='selected'" : ''; ?>>tag</option>
<option value='3'<?php echo ( 3 === $term_meta ) ? "selected='selected'" : ''; ?>><?php _e( 'ignore', 'wp-tweets-pro' ); ?></option>
</select>
</td>
</tr>
<?php
}
/**
* Form when adding new tag.
*/
function wpt_add_tag() {
?>
<tr class="form-field">
<th valign="top" scope="row">
<label for="wpt_tag"><?php _e( 'Tweet tag as', 'wp-tweets-pro' ); ?></label>
</th>
<td>
<select name="wpt_tag" id="wpt_tag">
<option value='1'>#tag</option>
<option value='2'>$tag</option>
<option value='5'>@tag</option>
<option value='3'><?php _e( 'ignore', 'wp-tweets-pro' ); ?></option>
</select>
</td>
</tr>
<?php
}
add_filter( 'wpt_settings', 'wpt_set_filter_terms', 10, 2 );
/**
* Set term filters.
*
* @param string $message Notification message.
* @param array $post POST data.
*
* @return string
*/
function wpt_set_filter_terms( $message, $post ) {
if ( isset( $post['wpt_terms'] ) ) {
// if setting term filters, delete old filters.
delete_option( 'wpt_tweet_cats' );
delete_option( 'limit_categories' );
delete_option( 'tweet_categories' );
foreach ( $post['wpt_terms'] as $tax => $terms ) {
$terms = array_unique( $terms );
$wpt_terms[ $tax ] = $terms;
}
update_option( 'wpt_terms', $wpt_terms );
$message .= ' ' . __( 'Term filters updated.', 'wp-tweets-pro' );
} else {
delete_option( 'wpt_terms' );
}
if ( isset( $post['wpt_term_filters'] ) ) {
update_option( 'wpt_term_filters', $post['wpt_term_filters'] );
$message .= ' ' . __( 'Term filtering method reversed.', 'wp-tweets-pro' );
} else {
delete_option( 'wpt_term_filters' );
}
return $message;
}
add_filter( 'wpt_filter_terms', 'wpt_apply_term_filters', 10, 2 );
/**
* Test against term filters.
*
* @param bool $filter Is post being filtered.
* @param array $args Post data.
*/
function wpt_apply_term_filters( $filter, $args ) {
$post_type = ( isset( $args['type'] ) ) ? $args['type'] : false;
$post_ID = ( isset( $args['id'] ) ) ? $args['id'] : false;
// If the $filter equals true, allowed.
$term_ids = array();
$filters = get_option( 'wpt_terms' );
if ( is_array( $filters ) ) {
$filtered_taxonomies = array_keys( $filters );
$taxonomies = get_object_taxonomies( $post_type, 'names' );
$terms = wp_get_object_terms( $post_ID, $taxonomies );
foreach ( $terms as $term ) {
$term_ids[ $term->taxonomy ][] = $term->term_id;
// term IDs are unique, so I don't care which taxonomy this is.
}
$positive = get_option( 'wpt_term_filters' );
// items in array are checked positively.
foreach ( $filters as $key => $value ) {
// if there are terms in both sets.
// this keeps going unless any test comes up as false.
if ( ! empty( $filters[ $key ] ) ) {
if ( isset( $term_ids[ $key ] ) ) {
$result = array_intersect( $term_ids[ $key ], $filters[ $key ] );
if ( isset( $positive[ $key ] ) && count( $result ) >= 1 ) {
$filter = true;
} elseif ( isset( $positive[ $key ] ) && 0 === count( $result ) ) {
$filter = false;
} elseif ( count( $result ) >= 1 && ! isset( $positive[ $key ] ) ) {
$filter = false;
}
}
}
}
}
/**
* Run filters based on taxonomy terms. Used to exclude or include particular terms from Tweets. A true value means continue, but does not mean that a Tweet will be sent; a Tweet could still be filtered out for a different reason.
*
* @hook wpt_modify_term_filters
*
* @param {bool} $filter Boolean true to continue, false to prevent Tweets.
* @param {array} $args Data about the current post.
*
* @return {bool}
*/
$filter = apply_filters( 'wpt_modify_term_filters', $filter, $args );
wpt_mail( '3d: Taxonomy limits executed', $filter . "\n\n" . print_r( $args, 1 ), $post_ID );
return $filter;
}
/**
* Generate list of terms and filtering status.
*
* @param string $post_type Post Type internal name.
* @param string $post_name Display name for post type.
*/
function wpt_list_terms( $post_type, $post_name ) {
$selected = '';
$taxonomies = get_object_taxonomies( $post_type, 'object' );
$term_filters = get_option( 'wpt_terms' );
$filter_type = get_option( 'wpt_term_filters' );
$nonce = wp_nonce_field( 'wp-to-twitter-nonce', '_wpnonce', true, false );
$input = '';
if ( ! empty( $taxonomies ) ) {
foreach ( $taxonomies as $taxonomy ) {
$name = $taxonomy->labels->name;
$slug = $taxonomy->name;
$count = wp_count_terms( $slug );
echo "<input type='hidden' name='wpt_term_taxonomies[]' value='$slug' />";
if ( $count > 500 ) {
_e( 'There are more than 500 terms in this taxonomy. Use the <code>wpt_filter_terms</code> filter to apply custom limits on this taxonomy.', 'wp-tweets-pro' );
} else {
$terms = get_terms( $slug, array( 'hide_empty' => false ) );
if ( 0 === count( $terms ) ) {
continue;
}
$checked = ( isset( $filter_type[ $slug ] ) ) ? ' checked="checked"' : '';
if ( ! $checked ) {
$exclude = __( 'Exclude', 'wp-tweets-pro' );
} else {
$exclude = __( 'Include', 'wp-tweets-pro' );
}
// translators: 1) Taxonomy label 2) Current state (exclude or include) 3) Post type name.
$input = "<fieldset class='wpt-terms'><legend>" . sprintf( __( '%3$s %1$s by %2$s', 'wp-tweets-pro' ), $post_name, $name, $exclude ) . '</legend>';
// translators: Taxonomy name.
$input .= '<p><input type="checkbox" name="wpt_term_filters[' . $slug . '][]" id="wpt_term_filters_' . $slug . '" value="1"' . $checked . ' /> <label for="wpt_term_filters_' . $slug . '">' . sprintf( __( 'Checked %s will be Tweeted', 'wp-tweets-pro' ), strtolower( $name ) ) . '</label></p>';
$input .= "
<ul class='wpt-terms'>\n";
$class = '';
if ( ! empty( $terms ) ) {
foreach ( $terms as $term ) {
if ( is_array( $term_filters ) ) {
$filter = ( isset( $term_filters[ $slug ] ) ) ? $term_filters[ $slug ] : array();
if ( is_array( $filter ) && in_array( (string) $term->term_id, $filter, true ) ) {
$selected = ' checked="checked"';
$class = ( $checked ) ? 'tweet' : 'notweet';
} else {
$selected = '';
$class = 'unchecked';
}
}
$input .= '<li class="' . $class . '"><input' . $selected . ' type="checkbox" name="wpt_terms[' . $slug . '][]" value="' . $term->term_id . '" id="' . $term->slug . $term->term_id . '" /> <label for="' . $term->slug . $term->term_id . '">' . $term->name . "</label></li>\n";
}
} else {
$input .= __( 'No terms in this taxonomy.', 'wp-tweets-pro' );
}
$input .= '</ul>
</fieldset>';
echo $input;
}
}
} else {
_e( 'No taxonomies found.', 'wp-tweets-pro' );
}
}
/**
* Add the screen option for num per page
*/
function wpt_add_screen_option() {
$items_per_page = ( get_option( 'wpt_num_per_page' ) ) ? get_option( 'wpt_num_per_page' ) : 50;
$option = 'per_page';
$args = array(
'label' => 'Tweets',
'default' => $items_per_page,
'option' => 'wpt_num_per_page',
);
add_screen_option( $option, $args );
}
add_filter( 'set-screen-option', 'wpt_set_screen_option', 10, 3 );
/**
* Set the num per page value
*
* @param string $status Status.
* @param string $option Option name.
* @param string $value New value.
*
* @return string $value
*/
function wpt_set_screen_option( $status, $option, $value ) {
if ( 'wpt_num_per_page' === $option ) {
update_user_meta( get_current_user_ID(), 'wpt_num_per_page', $value );
}
return $value;
}