This commit is contained in:
2026-04-26 23:47:49 +02:00
parent 1b95f03d1e
commit b073e009d8
5288 changed files with 1112699 additions and 55536 deletions

View File

@@ -0,0 +1,42 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use Smashballoon\Stubs\Services\ServiceProvider;
class ActivationService extends ServiceProvider {
public function register() {
add_action( 'activated_plugin', [ $this, 'on_plugin_activation' ] );
}
public function on_plugin_activation( $plugin ) {
if ( ! in_array( basename( $plugin ), array( 'youtube-feed.php', 'youtube-feed-pro.php' ) ) ) {
return;
}
$plugin_to_deactivate = 'youtube-feed.php';
if ( basename( $plugin ) === $plugin_to_deactivate ) {
$plugin_to_deactivate = 'youtube-feed-pro.php';
}
foreach ( $this->get_active_plugins() as $basename ) {
if ( false !== strpos( $basename, $plugin_to_deactivate ) ) {
deactivate_plugins( $basename );
return;
}
}
}
private function get_active_plugins() {
if ( is_multisite() ) {
$active_plugins = array_keys( (array) get_site_option( 'active_sitewide_plugins', array() ) );
} else {
$active_plugins = (array) get_option( 'active_plugins', array() );
}
return $active_plugins;
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use SmashBalloon\YouTubeFeed\Vendor\DI\Container;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Customizer\Customizer_Compatibility;
use SmashBalloon\YouTubeFeed\Pro\SBY_API_Connect_Pro;
use SmashBalloon\YouTubeFeed\SBY_API_Connect;
use SmashBalloon\YouTubeFeed\SBY_Settings;
use SmashBalloon\YouTubeFeed\Admin\SBY_Admin_Notice;
use SmashBalloon\YouTubeFeed\Services\Admin\Settings\PagesServiceContainer;
class AdminServiceContainer extends ServiceProvider {
private $services = [
MenuService::class,
Customizer_Compatibility::class,
AssetsService::class,
GUIService::class,
LicenseService::class,
MiscService::class,
PagesServiceContainer::class,
SourcesService::class,
SBY_Admin_Notice::class,
ImporterService::class,
CacheService::class
];
public function register() {
$container = \SmashBalloon\YouTubeFeed\Container::get_instance();
$container->set(SBY_Settings::class, new SBY_Settings([], sby_get_database_settings()));
foreach ( $this->services as $service ) {
$container->get($service)->register();
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use Smashballoon\Stubs\Services\ServiceProvider;
class AssetsService extends ServiceProvider {
public function register() {
add_action( 'admin_enqueue_scripts', [$this, 'sby_admin_style'] );
add_action( 'admin_enqueue_scripts', [$this, 'sby_admin_scripts'] );
add_action( 'admin_enqueue_scripts', [$this, 'enqueue_vue_assets'] );
}
public function enqueue_vue_assets() {
if ( ! sby_is_admin_page() ) {
return;
}
wp_enqueue_script(
'feed-builder-vue',
'https://cdn.jsdelivr.net/npm/vue@2.6.12',
null,
'2.6.12',
true
);
}
public function sby_admin_style() {
wp_enqueue_style( SBY_SLUG . '_admin_notices_css', SBY_PLUGIN_URL . 'css/sby-notices.css', array(), SBYVER );
wp_enqueue_style( SBY_SLUG . '_admin_css', SBY_PLUGIN_URL . 'css/admin.css', array(), SBYVER );
if ( ! sby_is_admin_page() ) {
return;
}
wp_enqueue_style( 'sb_font_awesome',
'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' );
wp_enqueue_style( 'wp-color-picker' );
}
public function sby_admin_scripts() {
// We need to enqueue this globally
wp_enqueue_script( SBY_SLUG . '_sby_admin_js', SBY_PLUGIN_URL . 'js/sby-admin.js', array(), SBYVER );
// wp_enqueue_script( SBY_SLUG . '_admin_js', SBY_PLUGIN_URL . 'js/admin.js', array(), SBYVER );
wp_localize_script( SBY_SLUG . '_sby_admin_js', 'sby_admin', array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'sby-admin' )
)
);
if ( ! sby_is_admin_page() ) {
return;
}
wp_enqueue_script( 'wp-color-picker' );
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Helpers\Util;
class CacheService extends ServiceProvider {
public function register() {
add_action( 'wp_ajax_sby_clear_cache', [ $this, 'ajax_clear_cache' ] );
}
public function ajax_clear_cache() {
Util::ajaxPreflightChecks();
// clear object cache
sby_clear_object_cache();
// clear transients
sby_clear_cache();
wp_clear_scheduled_hook( 'sby_feed_update' );
wp_send_json_success();
}
}

View File

@@ -0,0 +1,104 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use Smashballoon\Stubs\Services\ServiceProvider;
class GUIService extends ServiceProvider {
public function register() {
add_action( 'wp_ajax_sby_dismiss_api_key_notice', [$this, 'sby_dismiss_api_key_notice'] );
add_action( 'wp_ajax_sby_dismiss_at_warning_notice', [$this, 'sby_dismiss_at_warning_notice'] );
add_action( 'wp_ajax_sby_dismiss_connect_warning_button', [$this, 'sby_dismiss_connect_warning_notice'] );
add_action( 'admin_footer', [$this, 'sby_access_token_warning_modal'], 1 );
add_action('admin_init', [$this, 'sby_nag_ignore']);
add_action( 'admin_print_scripts', [$this, 'sby_admin_hide_unrelated_notices'] );
}
public function sby_dismiss_api_key_notice() {
update_user_meta( get_current_user_id(), 'sby_api_key_notice', 'dismissed' );
die();
}
public function sby_dismiss_at_warning_notice() {
update_user_meta( get_current_user_id(), 'sby_at_warning_notice', time() );
die();
}
public function sby_dismiss_connect_warning_notice() {
update_user_meta( get_current_user_id(), 'sby_connect_warning_notice', time() );
die();
}
public function sby_access_token_warning_modal() {
if ( isset( $_GET['page'] ) && $_GET['page'] === SBY_SLUG && isset( $_GET['sby_access_token'] ) && sby_notice_not_dismissed() ) {
$text_domain = SBY_TEXT_DOMAIN;
include_once trailingslashit( SBY_PLUGIN_DIR ) . 'inc/Admin/templates/modal.php';
echo '<span class="sby_account_just_added"></span>';
}
}
public function sby_nag_ignore() {
global $current_user;
$user_id = $current_user->ID;
if ( isset($_GET['sby_nag_ignore']) && '0' == $_GET['sby_nag_ignore'] ) {
add_user_meta($user_id, 'sby_ignore_notice', 'true', true);
}
}
/**
* Remove non-WPForms notices from WPForms pages.
*
* @since 1.3.9
*/
public function sby_admin_hide_unrelated_notices() {
// Bail if we're not on a Sby screen or page.
if ( ! sby_is_admin_page() ) {
return;
}
// Extra banned classes and callbacks from third-party plugins.
$blacklist = array(
'classes' => array(),
'callbacks' => array(
'sbydb_admin_notice', // 'Database for Sby' plugin.
),
);
global $wp_filter;
foreach ( array( 'user_admin_notices', 'admin_notices', 'all_admin_notices' ) as $notices_type ) {
if ( empty( $wp_filter[ $notices_type ]->callbacks ) || ! is_array( $wp_filter[ $notices_type ]->callbacks ) ) {
continue;
}
foreach ( $wp_filter[ $notices_type ]->callbacks as $priority => $hooks ) {
foreach ( $hooks as $name => $arr ) {
if ( $arr['function'] instanceof \Closure ) {
unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] );
continue;
}
$class = ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) ? strtolower( get_class( $arr['function'][0] ) ) : '';
if (
! empty( $class ) &&
strpos( $class, 'sby' ) !== false &&
! in_array( $class, $blacklist['classes'], true )
) {
continue;
}
if (
! empty( $name ) && (
strpos( $name, 'sby' ) === false ||
in_array( $class, $blacklist['classes'], true ) ||
in_array( $name, $blacklist['callbacks'], true )
)
) {
unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] );
}
}
}
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use Smashballoon\Customizer\Feed_Saver_Manager;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Helpers\Util;
class ImporterService extends ServiceProvider {
/**
* @var Feed_Saver_Manager
*/
private $saver_manager;
public function __construct(Feed_Saver_Manager $saver_manager) {
$this->saver_manager = $saver_manager;
}
public function register() {
add_action('wp_ajax_sby_do_feed_import', [$this, 'ajax_handle_file_import']);
}
public function ajax_handle_file_import() {
Util::ajaxPreflightChecks();
$filename = $_FILES['feedFile']['name'];
$ext = pathinfo( $filename, PATHINFO_EXTENSION );
if ( 'json' !== $ext ) {
wp_send_json_error(['message' => __('Unsupported file type.', 'feeds-for-youtube'), 'success' => false]);
}
$imported_settings = file_get_contents( $_FILES['feedFile']['tmp_name'] );
if ( empty($imported_settings) ) {
wp_send_json_error(['message' => __('Could not parse file contents.', 'feeds-for-youtube'), 'success' => false]);
}
$decoded_settings = json_decode($imported_settings, true);
$result = $this->saver_manager->import_feed($imported_settings, $decoded_settings['feedName']);
wp_send_json_success($result);
}
}

View File

@@ -0,0 +1,761 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use SmashBalloon\YouTubeFeed\HTTP_Request;
use SmashBalloon\YouTubeFeed\Response;
use SmashBalloon\YouTubeFeed\Services\LicenseNotification;
class LicenseService extends ServiceProvider {
private $license_service;
public function __construct() {
$this->license_service = new LicenseNotification();
}
public function register() {
/* Display a license expired notice */
add_action('sby_admin_notices', [$this, 'sby_renew_license_notice']);
add_action('sby_admin_header_notices', [$this, 'sby_admin_header_license_notice']);
// Add extra localize script items
add_filter('sby_localized_settings', [$this, 'localized_license_settings']);
add_action('wp_ajax_sby_check_connection', [$this, 'test_connection']);
add_action('wp_ajax_sby_license_activation', [$this, 'ajax_activate_license']);
add_action('wp_ajax_sby_license_deactivation', [$this, 'ajax_deactivate_license']);
add_action( 'wp_ajax_sby_check_license', [ $this, 'check_license' ] );
add_action( 'wp_ajax_sby_dismiss_license_notice', [ $this, 'dismiss_license_notice' ] );
}
public function localized_license_settings($settings) {
$license_key = $this->get_license_key();
$settings['licenseStatus'] = $this->get_license_status();
$settings['licenseData'] = $this->get_license_data();
$settings['licenseKey'] = $license_key;
$settings['upgradeUrl'] = sprintf( 'https://smashballoon.com/youtube-feed/pricing/?edd_license_key=%s&upgrade=true&utm_campaign=youtube-pro&utm_source=settings&utm_medium=upgrade-license', $this->get_license_key() );
return $settings;
}
public function test_connection() {
check_ajax_referer( 'sby-admin', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(); // This auto-dies.
}
$api_params = array(
'edd_action' => 'check_license',
'license' => $this->get_license_key(),
'item_name' => urlencode( SBY_PLUGIN_EDD_NAME ), // the name of our product in EDD
);
$url = add_query_arg( $api_params, SBY_STORE_URL );
$args = array(
'timeout' => 60,
);
// Make the remote API request
$request = HTTP_Request::request( 'GET', $url, $args );
if ( HTTP_Request::is_error( $request ) ) {
$response = new Response(
false,
array(
'hasError' => true,
)
);
$response->send();
}
$response = new Response(
true,
array(
'hasError' => false,
)
);
$response->send();
}
public function ajax_deactivate_license() {
check_ajax_referer( 'sby-admin', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(); // This auto-dies.
}
$response = $this->sby_deactivate_license();
if ( $response === true ) {
wp_send_json_success( [
'licenseStatus' => $this->get_license_status(),
'licenseData' => $this->get_license_data()
] );
}
wp_send_json_error();
}
public function ajax_activate_license() {
check_ajax_referer( 'sby-admin', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(); // This auto-dies.
}
$license_key = sanitize_text_field($_POST['license_key']);
$response = $this->sby_activate_license($license_key);
if ( $response === true ) {
wp_send_json_success( [
'licenseStatus' => $this->get_license_status(),
'licenseData' => $this->get_license_data()
] );
}
wp_send_json_error();
}
public function sby_activate_license($license_key) {
// retrieve the license from the database
$sby_license = trim( $license_key );
// data to send in our API request
$api_params = array(
'edd_action' => 'activate_license',
'license' => $sby_license,
'item_name' => urlencode( SBY_PLUGIN_EDD_NAME ), // the name of our product in EDD
'url' => home_url()
);
// Call the custom API.
$response = wp_remote_get( add_query_arg( $api_params, SBY_STORE_URL ),
array( 'timeout' => 15, 'sslverify' => false ) );
// make sure the response came back okay
if ( is_wp_error( $response ) ) {
return false;
}
// decode the license data
$sby_license_data = json_decode( wp_remote_retrieve_body( $response ) );
if (
isset( $sby_license_data->success ) && ( $sby_license_data->success == false ) ||
isset( $sby_license_data->error ) && ( $sby_license_data->error == 'missing' ) ||
isset( $sby_license_data->license ) && (
$sby_license_data->license == 'invalid_item_id' ||
$sby_license_data->license == 'invalid' ||
$sby_license_data->license == 'expired'
)
) {
return false;
}
// only store the license key
update_option( 'sby_license_key', $license_key );
//store the license data in an option
update_option( 'sby_license_data', $sby_license_data );
// $license_data->license will be either "valid" or "invalid"
update_option( 'sby_license_status', $sby_license_data->license );
// make license check_api true so next time it expires it checks again
update_option( 'sby_check_license_api_when_expires', 'true' );
update_option( 'sby_check_license_api_post_grace_period', 'true' );
return true;
}
public function sby_deactivate_license() {
// retrieve the license from the database
$sby_license= trim( get_option( 'sby_license_key' ) );
// data to send in our API request
$api_params = array(
'edd_action'=> 'deactivate_license',
'license' => $sby_license,
'item_name' => urlencode( SBY_PLUGIN_EDD_NAME ), // the name of our product in EDD
'url' => home_url()
);
// Call the custom API.
$response = wp_remote_get( add_query_arg( $api_params, SBY_STORE_URL ), array( 'timeout' => 15, 'sslverify' => false ) );
// make sure the response came back okay
if ( is_wp_error( $response ) ) {
return false;
}
// decode the license data
$sby_license_data = json_decode( wp_remote_retrieve_body( $response ) );
// $license_data->license will be either "deactivated" or "failed"
if( $sby_license_data->license == 'deactivated' || $sby_license_data->license == 'failed' ) {
delete_option( 'sby_license_data' );
delete_option( 'sby_license_status' );
}
return true;
}
/**
* Check license key
*
* @since 2.0.2
*/
public function sby_check_license( $sby_license, $check_license_status = false ) {
// data to send in our API request
$sby_api_params = array(
'edd_action'=> 'check_license',
'license' => $sby_license,
'item_name' => urlencode( SBY_PLUGIN_NAME ) // the name of our product in EDD
);
$api_url = add_query_arg( $sby_api_params, SBY_STORE_URL );
$args = array(
'timeout' => 60,
'sslverify' => false
);
// Call the custom API.
$request = wp_remote_get( $api_url, $args );
if ( is_wp_error( $request ) ) {
return;
}
// decode the license data
$sby_license_data = json_decode( wp_remote_retrieve_body( $request ) );
if ( $check_license_status ) {
//Check whether it's active
if( $sby_license_data['license'] !== 'expired' && ( strtotime( $sby_license_data['expires'] ) > strtotime( $sby_todays_date ) ) ){
$sby_license_status = false;
} else {
$sby_license_status = true;
//Set a flag so it doesn't check the API again until the next time it expires
update_option( 'sby_check_license_api_when_expires', 'false' );
}
return $sby_license_status;
}
//Store license data in db
update_option( 'sby_license_data', $sby_license_data );
return $sby_license_data;
}
public function sby_renew_license_notice() {
if ( !current_user_can( Util::sby_capability_check() ) ) {
return;
}
// We will display the license notice only on specified allowed screens
if ( ! Util::isCurrentScreenAllowed() ) {
return;
}
// Check that the license exists and the user hasn't already clicked to ignore the message
if ( empty( Util::get_license_key() ) ) {
return;
}
// If license not expired then return;
if ( !Util::is_license_expired() ) {
return;
}
// Grace period ended?
if ( Util::is_license_grace_period_ended() ) {
return;
}
// So, license has expired and grace period active
// Lets display the error notice
echo $this->get_expired_license_notice_content();
}
public function old_sby_renew_license_notice() {
//Show this notice on every page apart from the YouTube Feed settings pages
isset($_GET['page'])? $sby_check_page = $_GET['page'] : $sby_check_page = '';
( $sby_check_page == 'youtube-feed' || $sby_check_page == 'sby_single_settings' || $sby_check_page == 'youtube-feed_license' ) ? $sby_notice_dismissible = false : $sby_notice_dismissible = true;
//If the user is re-checking the license key then use the API below to recheck it
( isset( $_GET['sbychecklicense'] ) ) ? $sby_check_license = true : $sby_check_license = false;
$sby_license = trim( get_option( 'sby_license_key' ) );
global $current_user;
$user_id = $current_user->ID;
// Use this to show notice again
// delete_user_meta($user_id, 'sby_ignore_notice');
/* Check that the license exists and the user hasn't already clicked to ignore the message */
if( empty($sby_license) || !isset($sby_license) || ( ( get_user_meta( $user_id,
'sby_ignore_notice' ) && $sby_notice_dismissible ) && ! $sby_check_license ) ) {
return;
}
//Is there already license data in the db?
if( get_option( 'sby_license_data' ) && !$sby_check_license ){
//Yes
//Get license data from the db and convert the object to an array
$sby_license_data = (array) get_option( 'sby_license_data' );
} else {
//No
// data to send in our API request
$sby_api_params = array(
'edd_action'=> 'check_license',
'license' => $sby_license,
'item_name' => urlencode( SBY_PLUGIN_EDD_NAME ) // the name of our product in EDD
);
// Call the custom API.
$sby_response = wp_remote_get( add_query_arg( $sby_api_params, SBY_STORE_URL ), array( 'timeout' => 60, 'sslverify' => false ) );
// decode the license data
$sby_license_data = (array) json_decode( wp_remote_retrieve_body( $sby_response ) );
//Store license data in db
update_option( 'sby_license_data', $sby_license_data );
}
//Number of days until license expires
$sby_license_expires_date = isset( $sby_license_data['expires'] ) ? $sby_license_data['expires'] : $sby_license_expires_date = '2036-12-31 23:59:59'; //If expires param isn't set yet then set it to be a date to avoid PHP notice
if( $sby_license_expires_date == 'lifetime' ) $sby_license_expires_date = '2036-12-31 23:59:59';
$sby_todays_date = date('Y-m-d');
$sby_interval = round(abs(strtotime($sby_todays_date . ' -1 day')-strtotime($sby_license_expires_date))/86400); //-1 day to make sure auto-renewal has run before showing expired
//Is license expired?
if( $sby_interval == 0 || strtotime($sby_license_expires_date) < strtotime($sby_todays_date) ){
//If we haven't checked the API again one last time before displaying the expired notice then check it to make sure the license hasn't been renewed
if( get_option( 'sby_check_license_api_when_expires' ) == FALSE || get_option( 'sby_check_license_api_when_expires' ) == 'true' ){
// Check the API
$sby_api_params = array(
'edd_action'=> 'check_license',
'license' => $sby_license,
'item_name' => urlencode( SBY_PLUGIN_EDD_NAME ) // the name of our product in EDD
);
$sby_response = wp_remote_get( add_query_arg( $sby_api_params, SBY_STORE_URL ), array( 'timeout' => 60, 'sslverify' => false ) );
$sby_license_data = (array) json_decode( wp_remote_retrieve_body( $sby_response ) );
//Check whether it's active
if( $sby_license_data['license'] !== 'expired' && ( strtotime( $sby_license_data['expires'] ) > strtotime($sby_todays_date) ) ){
$sby_license_expired = false;
} else {
$sby_license_expired = true;
//Set a flag so it doesn't check the API again until the next time it expires
update_option( 'sby_check_license_api_when_expires', 'false' );
}
//Store license data in db
update_option( 'sby_license_data', $sby_license_data );
} else {
//Display the expired notice
$sby_license_expired = true;
}
} else {
$sby_license_expired = false;
//License is not expired so change the check_api setting to be true so the next time it expires it checks again
update_option( 'sby_check_license_api_when_expires', 'true' );
}
//If expired date is returned as 1970 (or any other 20th century year) then it means that the correct expired date was not returned and so don't show the renewal notice
if( $sby_license_expires_date[0] == '1' ) $sby_license_expired = false;
//If there's no expired date then don't show the expired notification
if( empty($sby_license_expires_date) || !isset($sby_license_expires_date) ) $sby_license_expired = false;
//Is license missing - ie. on very first check
if( isset($sby_license_data['error']) ){
if( $sby_license_data['error'] == 'missing' ) $sby_license_expired = false;
}
//Is the license expired?
if( $sby_license_expired || $sby_check_license ) {
global $sby_download_id;
$sby_expired_box_classes = "sby-license-expired";
$sby_expired_box_msg = '<svg style="width:16px;height:16px;" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="exclamation-triangle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-exclamation-triangle fa-w-18 fa-2x"><path fill="currentColor" d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z" class=""></path></svg>';
$sby_expired_box_msg .= "<b>Important: Your YouTube Feeds Pro license key has expired.</b><br /><span>You are no longer receiving updates that protect you against upcoming YouTube platform changes.</span>";
//Create the re-check link using the existing query string in the URL
$sby_url = '?' . $_SERVER["QUERY_STRING"];
//Determine the separator
( !empty($sby_url) && $sby_url != '' ) ? $separator = '&' : $separator = '';
//Add the param to check license if it doesn't already exist in URL
if( strpos($sby_url, 'sbychecklicense') === false ) $sby_url .= $separator . "sbychecklicense=true";
//Create the notice message
$sby_expired_box_msg .= " &nbsp;<a href='https://smashballoon.com/checkout/?edd_license_key=".$sby_license."&download_id=".$sby_download_id."&utm_source=plugin-pro&utm_campaign=youtube-pro&utm_medium=expired-notice-dashboard' target='_blank' class='button button-primary'>Renew License</a><a href='javascript:void(0);' id='sby-why-renew-show' onclick='sbyShowReasons()' class='button button-secondary'>Why renew?</a><a href='javascript:void(0);' id='sby-why-renew-hide' onclick='sbyHideReasons()' class='button button-secondary' style='display: none;'>Hide text</a> <a href='".$sby_url."' class='button button-secondary'>Re-check License</a></p>
<div id='sby-why-renew' style='display: none;'>
<h4><svg style='width:16px;height:16px;' aria-hidden='true' focusable='false' data-prefix='fas' data-icon='shield-check' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' class='svg-inline--fa fa-shield-check fa-w-16 fa-2x' data-ce-key='470'><path fill='currentColor' d='M466.5 83.7l-192-80a48.15 48.15 0 0 0-36.9 0l-192 80C27.7 91.1 16 108.6 16 128c0 198.5 114.5 335.7 221.5 380.3 11.8 4.9 25.1 4.9 36.9 0C360.1 472.6 496 349.3 496 128c0-19.4-11.7-36.9-29.5-44.3zm-47.2 114.2l-184 184c-6.2 6.2-16.4 6.2-22.6 0l-104-104c-6.2-6.2-6.2-16.4 0-22.6l22.6-22.6c6.2-6.2 16.4-6.2 22.6 0l70.1 70.1 150.1-150.1c6.2-6.2 16.4-6.2 22.6 0l22.6 22.6c6.3 6.3 6.3 16.4 0 22.6z' class='' data-ce-key='471'></path></svg>Protected Against All Upcoming YouTube Platform Updates and API Changes</h4>
<p>You currently don't need to worry about your YouTube feeds breaking due to constant changes in the YouTube platform. You are currently protected by access to continual plugin updates, giving you peace of mind that the software will always be up to date.</p>
<h4><svg style='width:16px;height:16px;' aria-hidden='true' focusable='false' data-prefix='fab' data-icon='wordpress' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' class='svg-inline--fa fa-wordpress fa-w-16 fa-2x'><path fill='currentColor' d='M61.7 169.4l101.5 278C92.2 413 43.3 340.2 43.3 256c0-30.9 6.6-60.1 18.4-86.6zm337.9 75.9c0-26.3-9.4-44.5-17.5-58.7-10.8-17.5-20.9-32.4-20.9-49.9 0-19.6 14.8-37.8 35.7-37.8.9 0 1.8.1 2.8.2-37.9-34.7-88.3-55.9-143.7-55.9-74.3 0-139.7 38.1-177.8 95.9 5 .2 9.7.3 13.7.3 22.2 0 56.7-2.7 56.7-2.7 11.5-.7 12.8 16.2 1.4 17.5 0 0-11.5 1.3-24.3 2l77.5 230.4L249.8 247l-33.1-90.8c-11.5-.7-22.3-2-22.3-2-11.5-.7-10.1-18.2 1.3-17.5 0 0 35.1 2.7 56 2.7 22.2 0 56.7-2.7 56.7-2.7 11.5-.7 12.8 16.2 1.4 17.5 0 0-11.5 1.3-24.3 2l76.9 228.7 21.2-70.9c9-29.4 16-50.5 16-68.7zm-139.9 29.3l-63.8 185.5c19.1 5.6 39.2 8.7 60.1 8.7 24.8 0 48.5-4.3 70.6-12.1-.6-.9-1.1-1.9-1.5-2.9l-65.4-179.2zm183-120.7c.9 6.8 1.4 14 1.4 21.9 0 21.6-4 45.8-16.2 76.2l-65 187.9C426.2 403 468.7 334.5 468.7 256c0-37-9.4-71.8-26-102.1zM504 256c0 136.8-111.3 248-248 248C119.2 504 8 392.7 8 256 8 119.2 119.2 8 256 8c136.7 0 248 111.2 248 248zm-11.4 0c0-130.5-106.2-236.6-236.6-236.6C125.5 19.4 19.4 125.5 19.4 256S125.6 492.6 256 492.6c130.5 0 236.6-106.1 236.6-236.6z' class=''></path></svg>WordPress Compatability Updates</h4>
<p>With WordPress updates being released continually, we make sure the plugin is always compatible with the latest version so you can update WordPress without needing to worry.</p>
<h4><svg style='width:16px;height:16px;' aria-hidden='true' focusable='false' data-prefix='far' data-icon='life-ring' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' class='svg-inline--fa fa-life-ring fa-w-16 fa-2x' data-ce-key='500'><path fill='currentColor' d='M256 504c136.967 0 248-111.033 248-248S392.967 8 256 8 8 119.033 8 256s111.033 248 248 248zm-103.398-76.72l53.411-53.411c31.806 13.506 68.128 13.522 99.974 0l53.411 53.411c-63.217 38.319-143.579 38.319-206.796 0zM336 256c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zm91.28 103.398l-53.411-53.411c13.505-31.806 13.522-68.128 0-99.974l53.411-53.411c38.319 63.217 38.319 143.579 0 206.796zM359.397 84.72l-53.411 53.411c-31.806-13.505-68.128-13.522-99.973 0L152.602 84.72c63.217-38.319 143.579-38.319 206.795 0zM84.72 152.602l53.411 53.411c-13.506 31.806-13.522 68.128 0 99.974L84.72 359.398c-38.319-63.217-38.319-143.579 0-206.796z' class='' data-ce-key='501'></path></svg>Expert Technical Support</h4>
<p>Without a valid license key you will no longer be able to receive updates or support for the YouTube Feeds plugin. A renewed license key grants you access to our top-notch, quick and effective support for another full year.</p>
<h4><svg style='width:16px;height:16px;' aria-hidden='true' focusable='false' data-prefix='fas' data-icon='unlock' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512' class='svg-inline--fa fa-unlock fa-w-14 fa-2x' data-ce-key='477'><path fill='currentColor' d='M400 256H152V152.9c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v16c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-16C376 68 307.5-.3 223.5 0 139.5.3 72 69.5 72 153.5V256H48c-26.5 0-48 21.5-48 48v160c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48z' class='' data-ce-key='478'></path></svg>All Pro YouTube Feeds Features</h4>
<p>Live Streaming API, Custom End-of-Video Actions, YouTube Search API, Carousel Sliders, Combine Feeds, Convert Videos to WP Posts, Favorites, Video Filtering, Smart Video Player Loading, and more!</p>
</div>";
if( $sby_check_license && !$sby_license_expired ){
$sby_expired_box_classes = "sby-license-expired sby-license-valid";
$sby_expired_box_msg = "Thanks ".$sby_license_data["customer_name"].", your YouTube Feeds Pro license key is valid.";
}
_e("<div class='".$sby_expired_box_classes."'>");
if( $sby_notice_dismissible ){
_e("<a style='float:right; color: #dd3d36; text-decoration: none;' href='" .esc_url( add_query_arg( 'sby_nag_ignore', '0' ) ). "'>Dismiss</a>");
}
_e("<p>".$sby_expired_box_msg."
</div>
<script type='text/javascript'>
function sbyShowReasons() {
document.getElementById('sby-why-renew').style.display = 'block';
document.getElementById('sby-why-renew-show').style.display = 'none';
document.getElementById('sby-why-renew-hide').style.display = 'inline-block';
}
function sbyHideReasons() {
document.getElementById('sby-why-renew').style.display = 'none';
document.getElementById('sby-why-renew-show').style.display = 'inline-block';
document.getElementById('sby-why-renew-hide').style.display = 'none';
}
</script>
<style>.sby-license-expired{clear:both;width:96%;margin:10px 0 20px 0;background:#f7e6e6;padding:15px 1.5%;border:1px solid #ba7b7b;color:#592626;border-left:4px solid #dc3232;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.sby-license-valid{border:1px solid #5baf2a;background:#e2f2d5}.sby-license-expired p{padding:0;margin:0 5px 0 0}.sby-license-expired b{display:inline-block;padding:0;font-size:15px}#sby-why-renew{clear:both;width:100%}#sby-why-renew h4{clear:both;margin:15px 0 0 0;font-size:15px}#sby-why-renew p{margin:0;clear:both}.sby-license-expired .button-primary{margin:0 4px 0 5px}.sby-license-expired .button-secondary{margin:0 0 0 3px;background:rgba(255,255,255,.3);border:1px solid rgba(0,0,0,.15);display:inline-block}.sby-license-expired svg{width:16px;height:16px;position:relative;top:2px;margin:0 8px 0 0}.sby-license-expired svg path{fill:#cc2727}@media all and (max-width:600px){.sby-license-expired b{display:inline}.sby-license-expired span{display:block}.sby-license-expired .button{margin:10px 5px 0 0}}</style>
");
}
}
/**
* Admin header notices
*
* @since 2.0.2
*/
public function sby_admin_header_license_notice () {
if ( !sby_is_pro() ) {
return;
}
if ( !current_user_can( Util::sby_capability_check() ) ) {
return;
}
// We will display the license notice only on specified allowed screens
if ( ! Util::isCurrentScreenAllowed() ) {
return;
}
// Check that the license exists and the user hasn't already clicked to ignore the message
if ( empty( Util::get_license_key() ) ) {
echo $this->get_post_grace_period_header_notice( $inactive = 'sby-license-inactive-state' );
return;
}
// If license not expired then return;
$license_expired = Util::is_license_expired();
if ( !$license_expired ) {
return;
}
// Grace period ended?
if ( Util::is_license_grace_period_ended( true ) ) {
if ( get_option( 'sby_check_license_api_post_grace_period' ) !== 'false' ) {
$license_expired = Util::sby_check_license( Util::get_license_key(), true, true );
}
if ( $license_expired ) {
echo $this->get_post_grace_period_header_notice();
}
}
return;
}
/**
* Get post grace period header notice content
*
* @since 2.0
*/
public function get_post_grace_period_header_notice( $license_status = 'expired' ) {
$notice_text = 'Your YouTube Feeds Pro License has expired. Renew to keep using PRO features.';
if ( $license_status == 'sby-license-inactive-state' ) {
$notice_text = 'Your license key is inactive. Please add license key to enable PRO features.';
}
return '<div id="sby-license-expired-agp" class="sby-license-expired-agp sby-le-flow-1 '. $license_status .'">
<span class="sby-license-expired-agp-message">'. $notice_text .' <span @click.prevent.default="activateView(\'licenseLearnMore\')">Learn More</span></span>
<button type="button" id="sby-dismiss-header-notice" title="Dismiss this message" data-page="overview" class="sby-dismiss">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.8327 5.34175L14.6577 4.16675L9.99935 8.82508L5.34102 4.16675L4.16602 5.34175L8.82435 10.0001L4.16602 14.6584L5.34102 15.8334L9.99935 11.1751L14.6577 15.8334L15.8327 14.6584L11.1744 10.0001L15.8327 5.34175Z" fill="white"></path>
</svg>
</button>
</div>';
}
private function get_license_key() {
return Util::get_license_key();
}
private function recheck_license_status() {
if ( empty( $this->get_license_key() ) ) {
return [];
}
$license_last_check = get_option( 'sby_license_last_check_timestamp' );
$date = time() - ( DAY_IN_SECONDS * 90 );
if ( $date < $license_last_check ) {
return $this->get_license_data();
}
$sby_license = $this->get_license_key();
$this->sby_activate_license($sby_license);
update_option( 'sby_license_last_check_timestamp', time() );
return $this->get_license_data();
}
public function get_license_status() {
return get_option('sby_license_status', 'inactive');
}
public function get_license_data() {
return $this->get_license_error_message( get_option( 'sby_license_data' ) );
}
public function get_license_error_message( $license_data ) {
global $sby_download_id;
$license_key = $this->get_license_key();
$upgrade_url = sprintf( 'https://smashballoon.com/youtube-feed/pricing/?edd_license_key=%s&upgrade=true&utm_campaign=youtube-pro&utm_source=settings&utm_medium=upgrade-license', $license_key );
$renew_url = sprintf( 'https://smashballoon.com/checkout/?edd_license_key=%s&download_id=%s&utm_campaign=youtube-pro&utm_source=settings&utm_medium=upgrade-license&utm_content=renew-license', $license_key, $sby_download_id );
$learn_more_url = 'https://smashballoon.com/doc/my-license-key-wont-activate/?utm_campaign=youtube-pro&utm_source=settings&utm_medium=license&utm_content=learn-more';
// Check if the license key reached max site installations
if ( !empty($license_data->error) && 'no_activations_left' === $license_data->error ) {
$license_data->errorMsg = sprintf(
'%s (%s/%s). %s <a href="%s" target="_blank">%s</a> %s <a href="%s" target="_blank">%s</a>',
__( 'You have reached the maximum number of sites available in your plan', 'feeds-for-youtube' ),
$license_data->site_count,
$license_data->max_sites,
__( 'Learn more about it', 'feeds-for-youtube' ),
$learn_more_url,
'here',
__( 'or upgrade your plan.', 'feeds-for-youtube' ),
$upgrade_url,
__( 'Upgrade', 'feeds-for-youtube' )
);
}
// Check if the license key has expired
if (
( !empty( $license_data->license ) && 'expired' === $license_data->license ) ||
( !empty( $license_data->error ) && 'expired' === $license_data->error )
) {
$license_data->error = true;
$expired_date = new \DateTime( $license_data->expires );
$expired_date = $expired_date->format( 'F d, Y' );
$license_data->errorMsg = sprintf(
'%s %s. %s <a href="%s" target="_blank">%s</a>',
__( 'The license expired on ', 'feeds-for-youtube' ),
$expired_date,
__( 'Please renew it and try again.', 'feeds-for-youtube' ),
$renew_url,
__( 'Renew', 'feeds-for-youtube' )
);
}
return $license_data;
}
/**
* Get content for expired license notice
*
* @since 2.0
*
* @return string $output
*/
public function get_expired_license_notice_content() {
global $current_user;
$current_screen = get_current_screen();
$output = '<div class="sb-license-notice">
<h4>Your license key has expired</h4>
<p>You are no longer receiving updates that protect you against upcoming YouTube changes. Theres a <strong>14 day</strong> grace period before access to some Pro features in the plugin will be limited.</p>
<div class="sb-notice-buttons">
<a href="'. $this->license_service->get_renew_url() .'" class="sb-btn sb-btn-blue" target="_blank">Renew License</a>
<a href="#" class="sb-btn" @click.prevent.default="activateView(\'whyRenewLicense\')">Why Renew?</a>
<a href="" class="sb-btn" @click.prevent.default="reCheckLicenseKey()" v-html="recheckBtnText()" :class="recheckLicenseStatus">Re-check License Key</a>
</div>
<svg class="sb-notice-icon" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 0C4.48 0 0 4.48 0 10C0 15.52 4.48 20 10 20C15.52 20 20 15.52 20 10C20 4.48 15.52 0 10 0ZM11 15H9V13H11V15ZM11 11H9V5H11V11Z" fill="#D72C2C"/></svg>
</div>';
if ( ! empty( $current_screen->base ) && $current_screen->base == 'dashboard' ) {
$output .= '<button id="sb-dismiss-notice">
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.66683 1.27325L8.72683 0.333252L5.00016 4.05992L1.2735 0.333252L0.333496 1.27325L4.06016 4.99992L0.333496 8.72659L1.2735 9.66659L5.00016 5.93992L8.72683 9.66659L9.66683 8.72659L5.94016 4.99992L9.66683 1.27325Z" fill="white"/>
</svg>
</button>';
}
return $output;
}
/**
* Get content for successfully renewed license notice
*
* @since 2.0
*
* @return string $output
*/
public function get_renewed_license_notice_content() {
$output = '<span class="sb-notice-icon sb-error-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12C22 6.5 17.5 2 12 2ZM10 17L5 12L6.41 10.59L10 14.17L17.59 6.58L19 8L10 17Z" fill="#59AB46"/>
</svg>
</span>
<div class="sb-notice-body">
<h3 class="sb-notice-title">Thanks! Your license key is valid.</h3>
<p>You can safely dismiss this modal.</p>
<div class="license-action-btns">
<a target="_blank" class="sby-license-btn sby-btn-blue sby-notice-btn" id="sby-hide-notice">
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.66683 1.27325L8.72683 0.333252L5.00016 4.05992L1.2735 0.333252L0.333496 1.27325L4.06016 4.99992L0.333496 8.72659L1.2735 9.66659L5.00016 5.93992L8.72683 9.66659L9.66683 8.72659L5.94016 4.99992L9.66683 1.27325Z" fill="white"/>
</svg>
Dismiss
</a>
</div>
</div>';
return $output;
}
/**
* Get modal content that will trigger by "Why Renew" button
*
* @since 2.0
*
* @return string $output
*/
public function get_modal_content() {
$output = '<div class="sby-sb-modal license-details-modal">
<div class="sby-modal-content">
<button type="button" class="cancel-btn sby-btn" id="sby-sb-close-modal">
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.2084 2.14275L12.8572 0.791504L7.50008 6.14859L2.143 0.791504L0.791748 2.14275L6.14883 7.49984L0.791748 12.8569L2.143 14.2082L7.50008 8.85109L12.8572 14.2082L14.2084 12.8569L8.85133 7.49984L14.2084 2.14275Z" fill="#141B38">
</path>
</svg>
</button>
<div class="sby-sb-modal-body">
<h2 class="sb-modal-title">Why Renew?</h2>
<p class="sb-modal-description">See below for why it\'s so important to keep an active plugin license.</p>
<div class="sb-why-renew-list-parent">
<div class="sb-why-renew-list">
<div class="sb-icon">
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 1.33325L4 6.66659V14.6666C4 22.0666 9.12 28.9866 16 30.6666C22.88 28.9866 28 22.0666 28 14.6666V6.66659L16 1.33325Z" fill="#59AB46"/>
<path d="M10.3433 16.5525L14.1145 20.3237L21.657 12.7813" stroke="white" stroke-width="2.66667"/>
</svg>
</div>
<div class="sb-list-item">
<h4>Protected Against All Upcoming YouTube Platform Updates and API Changes</h4>
<p>Don\'t worry about your YouTubes feeds breaking due to constant changes in the YouTube platform. Stay protected with access to continual plugin updates, giving you peace of mind that the software will always be up to date.</p>
</div>
</div>
<div class="sb-why-renew-list">
<div class="sb-icon">
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.9998 2.66675C8.63984 2.66675 2.6665 8.64008 2.6665 16.0001C2.6665 23.3601 8.63984 29.3334 15.9998 29.3334C23.3598 29.3334 29.3332 23.3601 29.3332 16.0001C29.3332 8.64008 23.3598 2.66675 15.9998 2.66675ZM25.9465 12.1601L22.2398 13.6934C21.9059 12.7949 21.3814 11.9793 20.7025 11.3027C20.0235 10.626 19.2061 10.1043 18.3065 9.77341L19.8398 6.06675C22.6398 7.13341 24.8665 9.36008 25.9465 12.1601ZM15.9998 20.0001C13.7865 20.0001 11.9998 18.2134 11.9998 16.0001C11.9998 13.7867 13.7865 12.0001 15.9998 12.0001C18.2132 12.0001 19.9998 13.7867 19.9998 16.0001C19.9998 18.2134 18.2132 20.0001 15.9998 20.0001ZM12.1732 6.05341L13.7332 9.76008C12.8229 10.0918 11.9959 10.6179 11.3097 11.3018C10.6235 11.9857 10.0946 12.811 9.75984 13.7201L6.05317 12.1734C6.58782 10.7816 7.40887 9.51764 8.46313 8.46338C9.5174 7.40911 10.7814 6.58806 12.1732 6.05341ZM6.05317 19.8267L9.75984 18.2934C10.0923 19.2002 10.619 20.0233 11.303 20.705C11.9871 21.3868 12.812 21.9107 13.7198 22.2401L12.1598 25.9467C10.771 25.4097 9.51009 24.5876 8.45831 23.5335C7.40653 22.4795 6.58722 21.2167 6.05317 19.8267ZM19.8398 25.9467L18.3065 22.2401C19.2103 21.9052 20.0304 21.3775 20.7097 20.6936C21.3889 20.0098 21.9111 19.1862 22.2398 18.2801L25.9465 19.8401C25.4101 21.2272 24.5898 22.4869 23.5382 23.5385C22.4866 24.59 21.2269 25.4103 19.8398 25.9467Z" fill="#59AB46"/>
</svg>
</div>
<div class="sb-list-item">
<h4>Expert Technical Support</h4>
<p>Without a valid license key you will no longer be able to receive updates or support for the YouTube Feeds plugin. A renewed license key grants you access to our top-notch, quick and effective support for another full year.</p>
</div>
</div>
<div class="sb-why-renew-list">
<div class="sb-icon">
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 0C7.16343 0 0 7.16342 0 16C0 24.8365 7.16343 32 16 32C24.8366 32 32 24.8365 32 16C32 7.16342 24.8366 0 16 0ZM16 0.96C18.0308 0.96 20.0004 1.35753 21.8539 2.14152C22.7449 2.51837 23.6044 2.98488 24.4084 3.528C25.205 4.06617 25.9541 4.68427 26.6349 5.3651C27.3157 6.04593 27.9338 6.79507 28.472 7.59163C29.0152 8.39563 29.4816 9.25507 29.8585 10.146C30.6425 11.9996 31.04 13.9692 31.04 16C31.04 18.0308 30.6425 20.0003 29.8585 21.8539C29.4816 22.7449 29.0152 23.6043 28.472 24.4083C27.9338 25.2049 27.3157 25.954 26.6349 26.6349C25.9541 27.3157 25.205 27.9338 24.4084 28.472C23.6044 29.0151 22.7449 29.4816 21.8539 29.8584C20.0004 30.6425 18.0308 31.04 16 31.04C13.9692 31.04 11.9996 30.6425 10.1461 29.8584C9.25508 29.4816 8.39564 29.0151 7.59164 28.472C6.79508 27.9338 6.04594 27.3157 5.36511 26.6349C4.68428 25.954 4.06618 25.2049 3.528 24.4083C2.98488 23.6043 2.51837 22.7449 2.14152 21.8539C1.35754 20.0003 0.960001 18.0308 0.960001 16C0.960001 13.9692 1.35754 11.9996 2.14152 10.146C2.51837 9.25507 2.98488 8.39563 3.528 7.59163C4.06618 6.79507 4.68428 6.04593 5.36511 5.3651C6.04594 4.68427 6.79508 4.06617 7.59164 3.528C8.39564 2.98488 9.25508 2.51837 10.1461 2.14152C11.9996 1.35753 13.9692 0.96 16 0.96Z" fill="#0068A0"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M27.7008 9.60322C27.7581 10.0278 27.7904 10.4834 27.7904 10.9742C27.7904 12.3266 27.537 13.8476 26.7762 15.7497L22.7039 27.5239C26.6679 25.2129 29.3337 20.9184 29.3337 15.9996C29.3337 13.6814 28.7413 11.5022 27.7008 9.60322ZM16.2346 17.1658L12.2335 28.7901C13.4284 29.1417 14.6917 29.3334 16.0004 29.3334C17.553 29.3334 19.0425 29.0654 20.4283 28.5774C20.3926 28.5204 20.3598 28.4598 20.3326 28.3937L16.2346 17.1658ZM25.0015 15.3271C25.0015 13.6788 24.4094 12.5379 23.9023 11.6501C23.2264 10.5513 22.5925 9.62166 22.5925 8.52289C22.5925 7.29745 23.5219 6.15659 24.8316 6.15659C24.8908 6.15659 24.9468 6.16369 25.0042 6.16734C22.632 3.9938 19.4715 2.66675 16.0004 2.66675C11.342 2.66675 7.24413 5.05691 4.85997 8.6762C5.17303 8.68614 5.46799 8.69238 5.71807 8.69238C7.11237 8.69238 9.27175 8.52289 9.27175 8.52289C9.99012 8.48079 10.075 9.53674 9.357 9.62166C9.357 9.62166 8.63445 9.70628 7.83113 9.74833L12.6863 24.1908L15.6046 15.4399L13.5274 9.74833C12.809 9.70628 12.129 9.62166 12.129 9.62166C11.4102 9.57922 11.4944 8.48079 12.2135 8.52289C12.2135 8.52289 14.415 8.69238 15.725 8.69238C17.1193 8.69238 19.279 8.52289 19.279 8.52289C19.9978 8.48079 20.0824 9.53674 19.364 9.62166C19.364 9.62166 18.6407 9.70628 17.8381 9.74833L22.6566 24.0807L24.0321 19.7223C24.6432 17.8175 25.0015 16.468 25.0015 15.3271ZM2.66699 15.9996C2.66699 21.2769 5.73372 25.838 10.1819 27.999L3.82154 10.5734C3.08171 12.2315 2.66699 14.0665 2.66699 15.9996Z" fill="#0068A0"/>
</svg>
</div>
<div class="sb-list-item">
<h4>WordPress Compatibility Updates</h4>
<p>With WordPress updates being released continually, we make sure the plugin is always compatible with the latest version so you can update WordPress without needing to worry.</p>
</div>
</div>
<div class="sb-why-renew-list">
<div class="sb-icon">
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.1583 8.40195C12.8183 7.39434 10.3809 5.88954 8.10558 5.18909C8.91398 7.03648 9.59628 9.00467 10.3023 10.9501C8.89406 11.9642 7.2491 12.7514 5.67754 13.6091C7.0149 14.8758 8.9089 15.609 10.418 16.7112C9.20919 18.1404 6.83433 19.6258 6.25565 20.9211C8.758 20.6207 11.6739 20.1336 14.0021 20.0348C14.5137 22.4989 14.7776 25.2005 15.5052 27.4577C16.5887 24.4706 17.5684 21.384 18.8581 18.5945C20.8485 19.3834 23.2742 20.3453 25.2172 20.8103C23.8539 18.9776 22.6098 17.0307 21.4018 15.0493C23.1895 13.8079 24.9976 12.5862 26.7202 11.2824C24.2854 11.0675 21.7627 10.9367 19.205 10.8394C18.7985 8.31133 18.9053 5.29159 18.28 2.97334C17.3339 4.87343 16.2174 6.61017 15.1583 8.40195ZM16.3145 29.3411C15.993 30.6598 17.0524 31.2007 16.8926 32C15.8465 31.6546 15.0596 31.4771 13.6553 31.6676C13.6992 30.6387 14.6649 30.4932 14.4646 29.2303C-0.500692 27.5999 -0.530751 1.68764 14.349 0.0928438C32.9539 -1.90125 33.5377 28.8829 16.3145 29.3411Z" fill="#FE544F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2802 2.97314C18.9055 5.2914 18.7987 8.31114 19.2052 10.8391C21.7629 10.9365 24.2856 11.0672 26.7204 11.2823C24.9978 12.586 23.1896 13.8077 21.4019 15.0491C22.61 17.0305 23.8541 18.9774 25.2174 20.8101C23.2744 20.3451 20.8487 19.3832 18.8583 18.5943C17.5686 21.3838 16.5889 24.4704 15.5054 27.4575C14.7778 25.2003 14.5139 22.4987 14.0023 20.0346C11.6741 20.1334 8.7582 20.6205 6.25584 20.9209C6.83452 19.6256 9.20937 18.1402 10.4181 16.7109C8.90907 15.6088 7.01509 14.8756 5.67773 13.6089C7.24929 12.7512 8.89422 11.964 10.3025 10.9499C9.59646 9.00448 8.91419 7.03628 8.10578 5.18889C10.381 5.88935 12.8185 7.39414 15.1585 8.40176C16.2176 6.60997 17.3341 4.87324 18.2802 2.97314Z" fill="white"/>
</svg>
</div>
<div class="sb-list-item">
<h4>All Pro YouTube Feeds Features</h4>
<p>Video Statistics, Live Streams, Search Feeds, PlayLists, Call to Action Settings, Carousel Layouts, Video filtering and more!</p>
</div>
</div>
</div>
</div>
</div>
</div>';
return $output;
}
/**
* SBY Check License
*
* @since 2.0
*/
public function check_license() {
$sby_license = trim( get_option( 'sby_license_key' ) );
// Check the API
$sby_api_params = array(
'edd_action'=> 'check_license',
'license' => $sby_license,
'item_name' => urlencode( SBY_PLUGIN_NAME ) // the name of our product in EDD
);
$sby_response = wp_remote_get( add_query_arg( $sby_api_params, SBY_STORE_URL ), array( 'timeout' => 60, 'sslverify' => false ) );
$sby_license_data = (array) json_decode( wp_remote_retrieve_body( $sby_response ) );
// Update the updated license data
update_option( 'sby_license_data', $sby_license_data );
$sby_todays_date = date('Y-m-d');
// Check whether it's active
if( $sby_license_data['license'] !== 'expired' && ( strtotime( $sby_license_data['expires'] ) > strtotime($sby_todays_date) ) ) {
// if the license is active then lets remove the ignore check for dashboard so next time it will show the expired notice in dashboard screen
update_user_meta( get_current_user_id(), 'sby_ignore_dashboard_license_notice', false );
wp_send_json_success( array(
'msg' => 'License Active',
'content' => $this->get_renewed_license_notice_content()
) );
} else {
$content = $this->get_expired_license_notice_content();
$content = str_replace( 'Your YouTube Feeds Pro license key has expired', 'We rechecked but your license key is still expired', $content );
wp_send_json_success( array(
'msg' => 'License Not Renewed',
'content' => $content
) );
}
}
/**
* SBY Dismiss Notice
*
* @since 2.0
*/
public function dismiss_license_notice() {
global $current_user;
$user_id = $current_user->ID;
update_user_meta( $user_id, 'sby_ignore_dashboard_license_notice', true );
}
}

View File

@@ -0,0 +1,138 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use Smashballoon\Customizer\Container;
use Smashballoon\Customizer\Feed_Builder;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Admin\SBY_Notifications;
class MenuService extends ServiceProvider {
/**
* @var mixed|Feed_Builder
*/
private $builder;
/**
* @var SBY_Notifications
*/
private $notifications;
public function __construct(SBY_Notifications $notifications) {
$this->builder = Container::getInstance()->get(Feed_Builder::class);
$this->notifications = $notifications;
}
public function register() {
add_action('admin_menu', [$this, 'register_menus']);
}
public function register_menus() {
$cap = current_user_can( 'manage_options' ) ? 'manage_options' : 'manage_youtube_feed_options';
add_menu_page(
__('YouTube Feed', 'feeds-for-youtube'),
__('YouTube Feed', 'feeds-for-youtube') . $this->alert_html(),
$cap,
SBY_MENU_SLUG,
null,
'dashicons-video-alt3',
99
);
add_submenu_page(
SBY_MENU_SLUG,
__( 'All Feeds', 'feeds-for-youtube' ),
__( 'All Feeds', 'feeds-for-youtube' ),
$cap,
SBY_MENU_SLUG,
array( $this->builder, 'feed_builder' ),
0
);
if ( (sby_is_pro() && empty( Util::get_license_key() )) || Util::is_license_expired() || !sby_is_pro() ) {
add_submenu_page(
SBY_MENU_SLUG,
__( 'Upgrade to Pro', 'feeds-for-youtube' ),
__( '<span class="sby_get_pro">Try the Pro Demo</span>', 'feeds-for-youtube' ),
$cap,
'https://smashballoon.com/youtube-feed/demo/?utm_campaign=youtube-free&utm_source=menu-link&utm_medium=upgrade-link',
''
);
}
if ( sby_should_add_free_plugin_submenu( 'facebook' ) ) {
add_submenu_page(
SBY_MENU_SLUG,
__( 'Facebook Feed', 'feeds-for-youtube' ),
'<span class="sby_get_cff">' . __( 'Facebook Feed', 'feeds-for-youtube' ) . '</span>',
'manage_options',
'admin.php?page=sby-feed-builder&tab=more',
5
);
}
if ( sby_should_add_free_plugin_submenu( 'instagram' ) ) {
add_submenu_page(
SBY_MENU_SLUG,
__( 'Instagram Feed', 'feeds-for-youtube' ),
'<span class="sby_get_sbi">' . __( 'Instagram Feed', 'feeds-for-youtube' ) . '</span>',
'manage_options',
'admin.php?page=sby-feed-builder&tab=more',
6
);
}
if ( sby_should_add_free_plugin_submenu( 'twitter' ) ) {
add_submenu_page(
SBY_MENU_SLUG,
__( 'Twitter Feed', 'feeds-for-youtube' ),
'<span class="sby_get_ctf">' . __( 'Twitter Feed', 'feeds-for-youtube' ) . '</span>',
'manage_options',
'admin.php?page=sby-feed-builder&tab=more',
7
);
}
if ( sby_should_add_free_plugin_submenu( 'tiktok' ) ) {
add_submenu_page(
SBY_MENU_SLUG,
__( 'Tiktok Feed', 'feeds-for-youtube' ),
'<span class="sby_get_sbtt">' . __( 'Tiktok Feed', 'feeds-for-youtube' ) . '</span>',
'manage_options',
'admin.php?page=sby-feed-builder&tab=more',
8
);
}
if ( sby_should_add_free_plugin_submenu( 'reviews' ) ) {
add_submenu_page(
SBY_MENU_SLUG,
__( 'Reviews Feed', 'feeds-for-youtube' ),
'<span class="sby_get_sbr">' . __( 'Reviews Feed', 'feeds-for-youtube' ) . '</span>',
'manage_options',
'admin.php?page=sby-feed-builder&tab=more',
9
);
}
}
private function alert_html() {
$notice = '';
$notice_bubble = '';
$notifications = $this->notifications->get();
if ( empty( $notice ) && ! empty( $notifications ) && is_array( $notifications ) ) {
$notice_bubble = ' <span class="sby-notice-alert"><span>' . count( $notifications ) . '</span></span>';
}
if ( sby_is_pro() && empty( Util::get_license_key() ) || Util::is_license_expired() ) {
$notice_bubble = ' <span class="sby-notice-alert"><span>1</span></span>';
}
return $notice_bubble . $notice;
}
}

View File

@@ -0,0 +1,226 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use SmashBalloon\YouTubeFeed\Pro\SBY_API_Connect_Pro;
use SmashBalloon\YouTubeFeed\Services\AdminAjaxService;
class MiscService extends ServiceProvider {
public function register() {
add_action( 'wp_ajax_sby_ca_after_remove_clicked', [$this, 'sby_delete_connected_account'] );
add_action( 'wp_ajax_sby_process_access_token', [$this, 'sby_process_access_token'] );
add_action( 'wp_ajax_sby_delete_wp_posts', [$this, 'sby_delete_wp_posts'] );
add_action( 'wp_ajax_sbspf_account_search', [$this, 'sbspf_account_search'] );
add_action('admin_init', [$this, 'sby_register_option']);
add_action( 'wp_ajax_sby_do_import_batch', [$this, 'sby_do_import_batch'] );
add_action( 'sby_settings_after_configure_save', [$this, 'sby_reset_cron'], 10, 1 );
}
public function sby_delete_connected_account() {
if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['account_id']) ) return;
$nonce = $_POST['sbspf_nonce'];
if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
die ( 'You did not do this the right way!' );
}
global $sby_settings;
$account_id = sanitize_text_field( $_POST['account_id'] );
$to_save = array();
foreach ( $sby_settings['connected_accounts'] as $connected_account ) {
if ( (string)$connected_account['channel_id'] !== (string)$account_id ) {
$to_save[ $connected_account['channel_id'] ] = $connected_account;
}
}
$sby_settings['connected_accounts'] = $to_save;
update_option( 'sby_settings', $sby_settings );
echo wp_json_encode( array( 'success' => true ) );
die();
}
public function sby_process_access_token() {
if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['sby_access_token'] ) ) return;
$nonce = $_POST['sbspf_nonce'];
if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
die ( 'You did not do this the right way!' );
}
$account = sby_attempt_connection();
if ( $account ) {
global $sby_settings;
$options = $sby_settings;
$username = $account['username'] ? $account['username'] : $account['channel_id'];
if ( isset( $account['local_avatar'] ) && $account['local_avatar'] && isset( $options['favorlocal'] ) && $options['favorlocal' ] === 'on' ) {
$upload = wp_upload_dir();
$resized_url = trailingslashit( $upload['baseurl'] ) . trailingslashit( SBY_UPLOADS_NAME );
$profile_picture = '<img class="sbspf_ca_avatar" src="'.$resized_url . $account['username'].'.jpg" />'; //Could add placeholder avatar image
} else {
$profile_picture = $account['profile_picture'] ? '<img class="sbspf_ca_avatar" src="'.$account['profile_picture'].'" />' : ''; //Could add placeholder avatar image
}
$text_domain = SBY_TEXT_DOMAIN;
$slug = SBY_SLUG;
ob_start();
include_once trailingslashit( SBY_PLUGIN_DIR ) . 'inc/Admin/templates/single-connected-account.php';
if ( sby_notice_not_dismissed() ) {
include_once trailingslashit( SBY_PLUGIN_DIR ) . 'inc/Admin/templates/modal.php';
echo '<span class="sby_account_just_added"></span>';
}
$html = ob_get_contents();
ob_get_clean();
$return = array(
'account_id' => $account['channel_id'],
'html' => $html
);
} else {
$return = array(
'error' => __( 'Could not connect your account. Please check to make sure this is a valid access token for the Smash Balloon YouTube App.'),
'html' => ''
);
}
echo wp_json_encode( $return );
die();
}
public function sby_delete_wp_posts() {
if ( ! isset( $_POST['sbspf_nonce'] ) ) return;
$nonce = $_POST['sbspf_nonce'];
if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
die ( 'You did not do this the right way!' );
}
sby_clear_wp_posts();
sby_clear_cache();
echo '{}';
die();
}
public function sbspf_account_search() {
if ( ! isset( $_POST['sbspf_nonce'] ) || ! isset( $_POST['term']) ) return;
$nonce = $_POST['sbspf_nonce'];
if ( ! wp_verify_nonce( $nonce, 'sbspf_nonce' ) ) {
die ( 'You did not do this the right way!' );
}
global $sby_settings;
$term = sanitize_text_field( $_POST['term'] );
$params = array(
'q' => $term,
'type' => 'channel'
);
$connected_account_for_term = array();
foreach ( $sby_settings['connected_accounts'] as $connected_account ) {
$connected_account_for_term = $connected_account;
}
if ( $connected_account_for_term['expires'] < time() + 5 ) {
$new_token_data = SBY_API_Connect::refresh_token( '', $connected_account_for_term['refresh_token'], '' );
if ( isset( $new_token_data['access_token'] ) ) {
$connected_account_for_term['access_token'] = $new_token_data['access_token'];
$connected_accounts_for_feed[ $term ]['access_token'] = $new_token_data['access_token'];
$connected_account_for_term['expires'] = $new_token_data['expires_in'] + time();
$connected_accounts_for_feed[ $term ]['expires'] = $new_token_data['expires_in'] + time();
sby_update_or_connect_account( $connected_account_for_term );
}
}
$search = new SBY_API_Connect( $connected_account_for_term, 'search', $params );
$search->connect();
echo wp_json_encode( $search->get_data() );
die();
}
public function sby_register_option() {
// creates our settings in the options table
register_setting('sby_license', 'sby_license_key', 'sby_sanitize_license' );
}
public function sby_do_import_batch() {
Util::ajaxPreflightChecks();
$next_page = isset( $_POST['page'] ) ? sanitize_text_field( $_POST['page'] ) : '';
$channel = isset( $_POST['channel'] ) ? sanitize_text_field( $_POST['channel'] ) : '';
$needed = isset( $_POST['needed'] ) ? sanitize_text_field( $_POST['needed'] ) : 1;
$playlist = isset( $_POST['playlist'] ) ? sanitize_text_field( $_POST['playlist'] ) : '';
if ( empty( $channel ) && empty( $playlist ) ) {
die();
}
$params = array(
'num' => (int) $needed
);
if ( ! empty( $next_page ) ) {
$params['nextPageToken'] = $next_page;
}
if ( strpos( $channel, 'UC' ) === 0 ) {
$params['channel_id'] = $channel;
} else {
$params['channel_name'] = $channel;
}
if ( empty( $playlist ) ) {
$connection = new SBY_API_Connect_Pro( sby_get_first_connected_account(), 'channels', $params );
$connection->connect();
$channel_data = $connection->get_data();
$playlist = isset( $channel_data['items'][0]['contentDetails']['relatedPlaylists']['uploads'] ) ? $channel_data['items'][0]['contentDetails']['relatedPlaylists']['uploads'] : false;
}
$return = array();
if ( $playlist ) {
$return['playlist'] = $playlist;
$params['playlist_id'] = $playlist;
$playlist_connection = new SBY_API_Connect_Pro( sby_get_first_connected_account(), 'playlistItems', $params );
$playlist_connection->connect();
$data = $playlist_connection->get_data();
$posts = isset( $data['items'] ) ? $data['items'] : array();
AdminAjaxService::sby_process_post_set_caching( $posts, 'sby_importer' );
$return['num_retrieved'] = count( $posts );
$return['next'] = $playlist_connection->get_next_page();
echo wp_json_encode( $return );
}
die();
}
public function sby_reset_cron( $settings ) {
$sby_caching_type = isset( $settings['caching_type'] ) ? $settings['caching_type'] : '';
$sby_cache_cron_interval = isset( $settings['cache_cron_interval'] ) ? $settings['cache_cron_interval'] : '';
$sby_cache_cron_time = isset( $settings['cache_cron_time'] ) ? $settings['cache_cron_time'] : '';
$sby_cache_cron_am_pm = isset( $settings['cache_cron_am_pm'] ) ? $settings['cache_cron_am_pm'] : '';
if ( $sby_caching_type === 'background' ) {
delete_option( 'sby_cron_report' );
SBY_Cron_Updater::start_cron_job( $sby_cache_cron_interval, $sby_cache_cron_time, $sby_cache_cron_am_pm );
}
}
}

View File

@@ -0,0 +1,340 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin\Settings;
use SmashBalloon\YouTubeFeed\Helpers\Util;
class AboutPage extends BaseSettingPage {
protected $menu_slug = 'about';
protected $menu_title = 'About Us';
protected $page_title = 'About Us';
protected $has_menu = true;
protected $template_file = 'settings.index';
protected $has_assets = true;
protected $menu_position = 4;
protected $menu_position_free_version = 4;
public function register() {
parent::register();
add_filter( 'sby_localized_settings', [ $this, 'filter_settings_object' ] );
add_action( 'wp_ajax_sby_install_addon', [ $this, 'ajax_install_addon' ] );
add_action( 'wp_ajax_sby_activate_addon', [ $this, 'ajax_activate_addon' ] );
}
public function ajax_activate_addon() {
Util::ajaxPreflightChecks();
// Check for permissions.
if ( ! current_user_can( 'activate_plugins' ) ) {
wp_send_json_error();
}
if ( isset( $_POST['plugin'] ) ) {
$type = 'addon';
if ( ! empty( $_POST['type'] ) ) {
$type = sanitize_key( $_POST['type'] );
}
$activate = activate_plugins( preg_replace( '/[^a-z-_\/]/', '', wp_unslash( str_replace( '.php', '', $_POST['plugin'] ) ) ) . '.php' );
if ( ! is_wp_error( $activate ) ) {
if ( 'plugin' === $type ) {
wp_send_json_success( esc_html__( 'Plugin activated.', 'feeds-for-youtube' ) );
} else {
wp_send_json_success( esc_html__( 'Addon activated.', 'feeds-for-youtube' ) );
}
}
}
wp_send_json_error( esc_html__( 'Could not activate addon. Please activate from the Plugins page.', 'feeds-for-youtube' ) );
}
public function ajax_install_addon() {
// Run a security check.
Util::ajaxPreflightChecks();
// Check for permissions.
if ( ! current_user_can( 'install_plugins' ) ) {
wp_send_json_error();
}
$error = esc_html__( 'Could not install addon. Please download from wpforms.com and install manually.', 'feeds-for-youtube' );
if ( empty( $_POST['plugin'] ) ) {
wp_send_json_error( $error );
}
// Only install plugins from the .org repo
if ( strpos( $_POST['plugin'], 'https://downloads.wordpress.org/plugin/' ) !== 0 ) {
wp_send_json_error( $error );
}
// Set the current screen to avoid undefined notices.
set_current_screen( 'youtube-feed-about' );
// Prepare variables.
$url = esc_url_raw(
add_query_arg(
array(
'page' => 'youtube-feed-about',
),
admin_url( 'admin.php' )
)
);
$creds = request_filesystem_credentials( $url, '', false, false, null );
// Check for file system permissions.
if ( false === $creds ) {
wp_send_json_error( $error );
}
if ( ! WP_Filesystem( $creds ) ) {
wp_send_json_error( $error );
}
/*
* We do not need any extra credentials if we have gotten this far, so let's install the plugin.
*/
// Do not allow WordPress to search/download translations, as this will break JS output.
remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
if(!class_exists("Plugin_Upgrader")) {
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
include_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';
}
// Create the plugin upgrader with our custom skin.
$installer = new \Plugin_Upgrader( new \WP_Upgrader_Skin() );
// Error check.
if ( empty( $_POST['plugin'] ) ) {
wp_send_json_error( $error );
}
$installer->install( esc_url_raw( wp_unslash( $_POST['plugin'] ) ) );
// Flush the cache and return the newly installed plugin basename.
wp_cache_flush();
$plugin_basename = $installer->plugin_info();
if ( $plugin_basename ) {
$type = 'addon';
if ( ! empty( $_POST['type'] ) ) {
$type = sanitize_key( $_POST['type'] );
}
// Activate the plugin silently.
$activated = activate_plugin( $plugin_basename );
if ( ! is_wp_error( $activated ) ) {
wp_send_json_success(
array(
'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed & activated.', 'feeds-for-youtube' ) : esc_html__( 'Addon installed & activated.', 'feeds-for-youtube' ),
'is_activated' => true,
'basename' => $plugin_basename,
)
);
} else {
wp_send_json_success(
array(
'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed.', 'feeds-for-youtube' ) : esc_html__( 'Addon installed.', 'feeds-for-youtube' ),
'is_activated' => false,
'basename' => $plugin_basename,
)
);
}
}
wp_send_json_error( $error );
}
public function filter_settings_object( $settings ) {
$sb_other_plugins = sby_get_active_plugins_info();
$installed_plugins = $sb_other_plugins['installed_plugins'];
$license_key = get_option( 'sby_license_key', null );
$settings['pluginInfo'] = [
"plugins" => [
'facebook' => array(
'plugin' => $sb_other_plugins['facebook_plugin'],
'download_plugin' => 'https://downloads.wordpress.org/plugin/custom-facebook-feed.zip',
'title' => __( 'Facebook Feeds', 'feeds-for-youtube' ),
'description' => __( 'Get in depth analytics on all your social feeds in a single place', 'feeds-for-youtube' ),
'icon' => 'fb-icon.svg',
'installed' => isset( $sb_other_plugins['is_facebook_installed'] ) && $sb_other_plugins['is_facebook_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['facebook_plugin'] ),
),
'instagram' => array(
'plugin' => $sb_other_plugins['instagram_plugin'],
'download_plugin' => 'https://downloads.wordpress.org/plugin/instagram-feed.zip',
'title' => __( 'Instagram Feeds', 'feeds-for-youtube' ),
'description' => __( 'Display customizable Instagram feeds in WordPress', 'feeds-for-youtube' ),
'icon' => 'insta-icon.svg',
'installed' => isset( $sb_other_plugins['is_instagram_installed'] ) && $sb_other_plugins['is_instagram_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['instagram_plugin'] ),
),
'twitter' => array(
'plugin' => $sb_other_plugins['twitter_plugin'],
'download_plugin' => 'https://downloads.wordpress.org/plugin/custom-twitter-feeds.zip',
'title' => __( 'Twitter Feeds', 'feeds-for-youtube' ),
'description' => __( 'Display customizable Twitter feeds in WordPress', 'feeds-for-youtube' ),
'icon' => 'twitter-icon.svg',
'installed' => isset( $sb_other_plugins['is_twitter_installed'] ) && $sb_other_plugins['is_twitter_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['twitter_plugin'] ),
),
'youtube' => array(
'plugin' => $sb_other_plugins['youtube_plugin'],
'download_plugin' => 'https://downloads.wordpress.org/plugin/feeds-for-youtube.zip',
'title' => __( 'YouTube Feeds', 'feeds-for-youtube' ),
'description' => __( 'Display customizable YouTube feeds in WordPress', 'feeds-for-youtube' ),
'icon' => 'youtube-icon.svg',
'installed' => isset( $sb_other_plugins['is_youtube_installed'] ) && $sb_other_plugins['is_youtube_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['youtube_plugin'] ),
),
'tiktok' => array(
'plugin' => $sb_other_plugins['tiktok_plugin'],
'download_plugin' => 'https://downloads.wordpress.org/plugin/feeds-for-tiktok.zip',
'title' => __( 'Tiktok Feeds', 'feeds-for-youtube' ),
'description' => __( 'Display customizable TikTok feeds in WordPress', 'feeds-for-youtube' ),
'icon' => 'tiktok-icon.svg',
'installed' => isset( $sb_other_plugins['is_tiktok_installed'] ) && $sb_other_plugins['is_tiktok_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['tiktok_plugin'] ),
),
],
'social_wall' => array(
'plugin' => 'social-wall/social-wall.php',
'title' => __( 'Social Wall', 'feeds-for-youtube' ),
'description' => __( 'Connect all social feeds in a single feed with Social Wall', 'feeds-for-youtube' ),
'graphic' => 'social-wall-graphic.png',
'icon' => 'reviews-icon.svg',
'permalink' => sprintf( 'https://smashballoon.com/social-wall/demo?edd_license_key=%s&upgrade=true&utm_campaign='. sby_utm_campaign() .'&utm_source=about&utm_medium=social-wall', $license_key ),
'permalink_text' => __( 'See Demo', 'feeds-for-youtube' ),
'installed' => isset( $sb_other_plugins['is_social_wall_installed'] ) && $sb_other_plugins['is_social_wall_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['social_wall_plugin'] ),
),
'reviews' => array(
'plugin' => $sb_other_plugins['reviews_plugin'],
'download_plugin' => 'https://downloads.wordpress.org/plugin/reviews-feed.zip',
'title' => __( 'Reviews Feeds', 'feeds-for-youtube' ),
'description' => __( 'Display customizable Reviews feeds in WordPress', 'feeds-for-youtube' ),
'icon' => 'reviews-icon.svg',
'installed' => isset( $sb_other_plugins['is_reviews_installed'] ) && $sb_other_plugins['is_reviews_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['reviews_plugin'] ),
),
'click_social' => array(
'plugin' => $sb_other_plugins['click_social_plugin'],
'download_plugin' => 'https://downloads.wordpress.org/plugin/click-social.zip',
'title' => __( 'ClickSocial', 'feeds-for-youtube' ),
'description' => __( 'Effortlessly manage your social media presence directly within WordPress. ', 'feeds-for-youtube' ),
'icon' => 'click-social-icon.svg',
'installed' => isset( $sb_other_plugins['is_click_social_installed'] ) && $sb_other_plugins['is_click_social_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['click_social_plugin'] ),
),
'feed_analytics' => array(
'plugin' => $sb_other_plugins['click_social_plugin'],
'download_plugin' => '',
'title' => __( 'Feed Analytics', 'feeds-for-youtube' ),
'description' => __( 'Get in depth analytics on all your social feeds in a single place', 'feeds-for-youtube' ),
'icon' => 'feed-analytics-icon.svg',
'permalink' => sprintf( 'https://smashballoon.com/social-wall/demo?edd_license_key=%s&upgrade=true&utm_campaign='. sby_utm_campaign() .'&utm_source=about&utm_medium=social-wall', $license_key ),
'permalink_text' => __( 'See Demo', 'feeds-for-youtube' ),
'installed' => isset( $sb_other_plugins['is_click_social_installed'] ) && $sb_other_plugins['is_click_social_installed'] == true,
'activated' => is_plugin_active( $sb_other_plugins['click_social_plugin'] ),
),
'recommendedPlugins' => array(
'aioseo' => array(
'plugin' => 'all-in-one-seo-pack/all_in_one_seo_pack.php',
'download_plugin' => 'https://downloads.wordpress.org/plugin/all-in-one-seo-pack.zip',
'title' => __('All in One SEO Pack', 'feeds-for-youtube'),
'description' => __('The original WordPress SEO plugin and toolkit that improves your website\'s search rankings. Comes with all the SEO features like Local SEO, WooCommerce SEO, sitemaps, SEO optimizer, schema, and more.', 'feeds-for-youtube'),
'icon' => 'plugin-seo.png',
'installed' => isset( $installed_plugins['all-in-one-seo-pack/all_in_one_seo_pack.php'] ) ? true : false,
'activated' => is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php'),
'installs_number' => __('3 Million+ Installs', 'feeds-for-youtube')
),
'wpforms' => array(
'plugin' => 'wpforms-lite/wpforms.php',
'download_plugin' => 'https://downloads.wordpress.org/plugin/wpforms-lite.zip',
'title' => __('WPForms', 'feeds-for-youtube'),
'description' => __('The best drag & drop WordPress form builder. Easily create beautiful contact forms, surveys, payment forms, and more with our 900+ form templates. Trusted by over 6 million websites as the best forms plugin.', 'feeds-for-youtube'),
'icon' => 'plugin-wpforms.png',
'installed' => isset( $installed_plugins['wpforms-lite/wpforms.php'] ) ? true : false,
'activated' => is_plugin_active('wpforms-lite/wpforms.php'),
'installs_number' => __('6 Million+ Installs', 'feeds-for-youtube')
),
'monsterinsights' => array(
'plugin' => 'google-analytics-for-wordpress/googleanalytics.php',
'download_plugin' => 'https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.zip',
'title' => __('MonsterInsights', 'feeds-for-youtube'),
'description' => __('The leading WordPress analytics plugin that shows you how people find and use your website, so you can make data driven decisions to grow your business. Properly set up Google Analytics without writing code.', 'feeds-for-youtube'),
'icon' => 'plugin-mi.png',
'installed' => isset( $installed_plugins['google-analytics-for-wordpress/googleanalytics.php'] ) ? true : false,
'activated' => is_plugin_active('google-analytics-for-wordpress/googleanalytics.php'),
'installs_number' => __('3 Million+ Installs', 'feeds-for-youtube')
),
'optinmonster' => array(
'plugin' => 'optinmonster/optin-monster-wp-api.php',
'download_plugin' => 'https://downloads.wordpress.org/plugin/optinmonster.zip',
'title' => __('OptinMonster', 'feeds-for-youtube'),
'description' => __('Instantly get more subscribers, leads, and sales with the #1 conversion optimization toolkit. Create high converting popups, announcement bars, spin a wheel, and more with smart targeting and personalization.', 'feeds-for-youtube'),
'icon' => 'plugin-om.png',
'installed' => isset( $installed_plugins['optinmonster/optin-monster-wp-api.php'] ) ? true : false,
'activated' => is_plugin_active('optinmonster/optin-monster-wp-api.php'),
'installs_number' => __('1 Million+ Installs', 'feeds-for-youtube')
),
'wp_mail_smtp' => array(
'plugin' => 'wp-mail-smtp/wp_mail_smtp.php',
'download_plugin' => 'https://downloads.wordpress.org/plugin/wp-mail-smtp.zip',
'title' => __('WP Mail SMTP', 'feeds-for-youtube'),
'description' => __('Improve your WordPress email deliverability and make sure that your website emails reach user\'s inbox with the #1 SMTP plugin for WordPress. Over 3 million websites use it to fix WordPress email issues.', 'feeds-for-youtube'),
'icon' => 'plugin-smtp.png',
'installed' => isset( $installed_plugins['wp-mail-smtp/wp_mail_smtp.php'] ) ? true : false,
'activated' => is_plugin_active('wp-mail-smtp/wp_mail_smtp.php'),
'installs_number' => __('3 Million+ Installs', 'feeds-for-youtube')
),
'rafflepress' => array(
'plugin' => 'rafflepress/rafflepress.php',
'download_plugin' => 'https://downloads.wordpress.org/plugin/rafflepress.zip',
'title' => __('RafflePress', 'feeds-for-youtube'),
'description' => __('Turn your website visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with the most powerful giveaways & contests plugin for WordPress.', 'feeds-for-youtube'),
'icon' => 'plugin-rp.png',
'installed' => isset( $installed_plugins['rafflepress/rafflepress.php'] ) ? true : false,
'activated' => is_plugin_active('rafflepress/rafflepress.php'),
'installs_number' => __('20 Thousand+ Installs', 'feeds-for-youtube')
),
'seedprod' => array(
'plugin' => 'coming-soon/coming-soon.php',
'download_plugin' => 'https://downloads.wordpress.org/plugin/coming-soon.zip',
'title' => __('SeedProd Website Builder', 'feeds-for-youtube'),
'description' => __('The fastest drag & drop landing page builder for WordPress. Create custom landing pages without writing code, connect a CRM, collect subscribers, and grow an audience. Trusted by 1 million sites.', 'feeds-for-youtube'),
'icon' => 'plugin-seedprod.png',
'installed' => isset( $installed_plugins['coming-soon/coming-soon.php'] ) ? true : false,
'activated' => is_plugin_active('coming-soon/coming-soon.php'),
'installs_number' => __('800 Thousand+ Installs', 'feeds-for-youtube')
),
'pushengage' => array(
'plugin' => 'pushengage/main.php',
'download_plugin' => 'https://downloads.wordpress.org/plugin/pushengage.zip',
'title' => __('PushEngage Web Push Notifications', 'feeds-for-youtube'),
'description' => __('Connect with your visitors after they leave your website with the leading web push notification software. Over 10,000+ businesses worldwide use PushEngage to send 15 billion notifications each month.', 'feeds-for-youtube'),
'icon' => 'plugin-push.png',
'installed' => isset( $installed_plugins['pushengage/main.php'] ) ? true : false,
'activated' => is_plugin_active('pushengage/main.php'),
'installs_number' => __('10 Thousand+ Installs', 'feeds-for-youtube')
)
),
];
return $settings;
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin\Settings;
use Smashballoon\Customizer\Feed_Builder;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Admin\SBY_Notifications;
use SmashBalloon\YouTubeFeed\Container;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use SmashBalloon\YouTubeFeed\Pro\SBY_CPT;
use SmashBalloon\YouTubeFeed\SBY_View;
use Smashballoon\Customizer\YouTube_License_Tier;
abstract class BaseSettingPage extends ServiceProvider {
protected $has_menu = false;
protected $has_assets = false;
protected $page_title = "";
protected $menu_title = "";
protected $menu_slug = "";
protected $template_file = "";
protected $menu_position = 0;
protected $has_page_restriction = false;
protected $menu_position_free_version = 0;
public function register() {
if ( true === $this->has_menu ) {
add_action('admin_menu', [$this, 'register_menu_page']);
}
if ( ( true === $this->has_assets ) && isset( $_GET['page'] ) && false !== strpos( $_GET['page'],
SBY_SLUG . '-' . $this->menu_slug ) ) {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
}
}
public function render() {
SBY_View::render($this->template_file);
}
public function enqueue_assets() {
wp_enqueue_style(
'sby-global-style',
CUSTOMIZER_PLUGIN_URL . 'assets/css/global.css',
false,
SBYVER
);
//settings page script
$script_file = SBY_PLUGIN_URL . 'frontend/build/static/js/main.js';
if ( ! Util::isProduction() ) {
$script_file = "http://localhost:3000/static/js/main.js";
} else {
wp_enqueue_style(
'sby-settings-style',
SBY_PLUGIN_URL . 'frontend/build/static/css/main.css',
false,
SBYVER
);
}
wp_enqueue_script(
'sby-settings',
$script_file,
array( 'wp-i18n' ),
SBYVER,
true
);
wp_localize_script(
'sby-settings',
'sby_settings',
$this->get_settings_object()
);
wp_set_script_translations('sby-settings', 'feeds-for-youtube', SBY_PLUGIN_DIR . 'languages/');
}
public function register_menu_page() {
$menu_slug = SBY_SLUG . '-' . $this->menu_slug;
if ($this->has_page_restriction) {
$menu_slug = 'admin.php?page=sby-feed-builder&tab=more';
}
add_submenu_page(
SBY_MENU_SLUG,
$this->page_title,
$this->menu_title,
'manage_options',
$menu_slug,
[$this, 'render'],
$this->menu_position
);
}
private function get_notifications() {
return Container::get_instance()->get(SBY_Notifications::class)->output_return();
}
protected function get_settings_object() {
return apply_filters( 'sby_localized_settings', [
'admin_url' => admin_url(),
'ajax_handler' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'sby-admin' ),
'setupPageUrl' => admin_url( 'admin.php?page=youtube-feed-setup' ),
'supportPageUrl' => admin_url( 'admin.php?page=youtube-feed-support' ),
'settingsPageUrl' => admin_url( 'admin.php?page=youtube-feed-settings' ),
'builderUrl' => admin_url( 'admin.php?page=sby-feed-builder' ),
'connectionURL' => Feed_Builder::oauth_connet_url(),
'manageLicense' => 'https://smashballoon.com/account/downloads/?utm_campaign='. sby_utm_campaign() .'&utm_source=settings&utm_medium=manage-license',
'single_video_settings' => sby_is_pro() ? SBY_CPT::get_sby_cpt_settings() : [],
'single_video_admin_url' => admin_url("admin.php?page=youtube-feed-settings#/single-videos"),
'pluginItemName' => SBY_PLUGIN_EDD_NAME,
'licenseType' => 'pro',
'socialWallLinks' => Feed_Builder::get_social_wall_links(),
'socialWallActivated' => is_plugin_active( 'social-wall/social-wall.php' ),
'genericText' => Feed_Builder::get_generic_text(),
'licenseTierFeatures' => (new YouTube_License_Tier)->tier_features(),
'tooltipHelpSvg' => '<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.1665 8H10.8332V6.33333H9.1665V8ZM9.99984 17.1667C6.32484 17.1667 3.33317 14.175 3.33317 10.5C3.33317 6.825 6.32484 3.83333 9.99984 3.83333C13.6748 3.83333 16.6665 6.825 16.6665 10.5C16.6665 14.175 13.6748 17.1667 9.99984 17.1667ZM9.99984 2.16666C8.90549 2.16666 7.82186 2.38221 6.81081 2.801C5.79976 3.21979 4.8811 3.83362 4.10728 4.60744C2.54448 6.17024 1.6665 8.28986 1.6665 10.5C1.6665 12.7101 2.54448 14.8298 4.10728 16.3926C4.8811 17.1664 5.79976 17.7802 6.81081 18.199C7.82186 18.6178 8.90549 18.8333 9.99984 18.8333C12.21 18.8333 14.3296 17.9554 15.8924 16.3926C17.4552 14.8298 18.3332 12.7101 18.3332 10.5C18.3332 9.40565 18.1176 8.32202 17.6988 7.31097C17.28 6.29992 16.6662 5.38126 15.8924 4.60744C15.1186 3.83362 14.1999 3.21979 13.1889 2.801C12.1778 2.38221 11.0942 2.16666 9.99984 2.16666ZM9.1665 14.6667H10.8332V9.66666H9.1665V14.6667Z" fill="#434960"/></svg>',
'svgIcons' => Feed_Builder::builder_svg_icons(),
'smashBalloonInfo' => Feed_Builder::get_smashballoon_info(),
'assetsURL' => SBY_PLUGIN_URL . 'frontend/build',
'notifications' => $this->get_notifications(),
'shouldShowPostGracePeriodNotice' => Util::expiredLicenseWithGracePeriodEnded(),
'isLicenseInactive' => empty( Util::get_license_key() ),
] );
}
}

View File

@@ -0,0 +1,342 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin\Settings;
use Smashballoon\Customizer\Container;
use Smashballoon\Customizer\Feed_Builder;
use SmashBalloon\YouTubeFeed\Builder\SBY_Feed_Builder;
use SmashBalloon\YouTubeFeed\SBY_Settings;
class HelpPage extends BaseSettingPage {
protected $menu_slug = 'support';
protected $menu_title = 'Support';
protected $page_title = 'Support';
protected $has_menu = true;
protected $template_file = 'settings.index';
protected $has_assets = true;
protected $menu_position = 3;
protected $menu_position_free_version = 3;
/**
* @var Feed_Builder
*/
private $feed_builder;
public function __construct() {
$this->feed_builder = Container::getInstance()->get(Feed_Builder::class);
}
public function register() {
parent::register();
add_filter( 'sby_localized_settings', [ $this, 'filter_settings_object' ] );
}
public static function get_whitespace( $times ) {
return str_repeat( '&nbsp;', $times );
}
public function filter_settings_object( $settings ) {
$settings['system_info'] = $this->get_system_info();
$settings['system_info_n'] = str_replace( '<br />', "\n", $this->get_system_info() );
$settings['feeds'] = Container::getInstance()->get(Feed_Builder::class)->get_feed_list();
return $settings;
}
public function get_system_info() {
$output = '';
// Build the output strings
$output .= $this->get_site_n_server_info();
$output .= $this->get_active_plugins_info();
$output .= $this->get_global_settings_info();
$output .= $this->get_feeds_settings_info();
$output .= $this->get_sources_info();
$output .= $this->get_cron_report();
return $output;
}
/**
* Get Site and Server Info
*
* @since 6.0
*
* @return string
*/
public function get_site_n_server_info() {
$allow_url_fopen = ini_get( 'allow_url_fopen' ) ? 'Yes' : 'No';
$php_curl = is_callable( 'curl_init' ) ? 'Yes' : 'No';
$php_json_decode = function_exists( 'json_decode' ) ? 'Yes' : 'No';
$php_ssl = in_array( 'https', stream_get_wrappers(), true ) ? 'Yes' : 'No';
$settings = sby_get_database_settings();
$api_verification_status = get_option('sby_api_key_verification', null);
$output = '## SITE/SERVER INFO: ##<br />';
$output .= 'Plugin Version:' . self::get_whitespace( 11 ) . esc_html( SBY_PLUGIN_NAME ) . '<br />';
$output .= 'Site URL:' . self::get_whitespace( 17 ) . esc_html( site_url() ) . '<br />';
$output .= 'Home URL:' . self::get_whitespace( 17 ) . esc_html( home_url() ) . '<br />';
$output .= 'WordPress Version:' . self::get_whitespace( 8 ) . esc_html( get_bloginfo( 'version' ) ) . '<br />';
$output .= 'PHP Version:' . self::get_whitespace( 14 ) . esc_html( PHP_VERSION ) . '<br />';
$output .= 'Web Server Info:' . self::get_whitespace( 10 ) . esc_html( $_SERVER['SERVER_SOFTWARE'] ) . '<br />';
$output .= 'PHP allow_url_fopen:' . self::get_whitespace( 6 ) . esc_html( $allow_url_fopen ) . '<br />';
$output .= 'PHP cURL:' . self::get_whitespace( 17 ) . esc_html( $php_curl ) . '<br />';
$output .= 'JSON:' . self::get_whitespace( 21 ) . esc_html( $php_json_decode ) . '<br />';
$output .= 'SSL Stream:' . self::get_whitespace( 15 ) . esc_html( $php_ssl ) . '<br />';
$output .= 'API Key:' . self::get_whitespace( 18 ) . esc_html( isset($settings['api_key']) ? $settings['api_key'] : 'Empty' ) . '<br />';
$output .= 'API Status:' . self::get_whitespace( 15 ) . esc_html( !empty($api_verification_status) ? ($api_verification_status->status == true ? "Successful" : "Failed") : 'Unknown' ) . '<br />';
$output .= '<br />';
return $output;
}
/**
* Get Active Plugins
*
* @since 6.0
*
* @return string
*/
public function get_active_plugins_info() {
$plugins = get_plugins();
$active_plugins = get_option( 'active_plugins' );
$output = '## ACTIVE PLUGINS: ## <br />';
foreach ( $plugins as $plugin_path => $plugin ) {
if ( in_array( $plugin_path, $active_plugins, true ) ) {
$output .= esc_html( $plugin['Name'] ) . ': ' . esc_html( $plugin['Version'] ) . '<br />';
}
}
$output .= '<br />';
return $output;
}
/**
* Get Global Settings
*
* @since 6.0
*
* @return string
*/
public function get_global_settings_info() {
$output = '## GLOBAL SETTINGS: ## <br />';
$sby_license_key = get_option( 'sby_license_key' );
$sby_license_data = get_option( 'sby_license_data' );
$sby_license_status = get_option( 'sby_license_status' );
$sby_settings = get_option( 'settings', array() );
$usage_tracking = get_option(
'sby_usage_tracking',
array(
'last_send' => 0,
'enabled' => \sby_is_pro_version(),
)
);
$output .= 'License key: ';
if ( $sby_license_key ) {
$output .= esc_html( $sby_license_key );
} else {
$output .= ' Not added';
}
$output .= '<br />';
$output .= 'License status: ';
if ( $sby_license_status ) {
$output .= $sby_license_status;
} else {
$output .= ' Inactive';
}
$output .= '<br />';
$output .= 'Preserve settings if plugin is removed: ';
$output .= isset( $sby_settings['preserve_settings'] ) && ( $sby_settings['preserve_settings'] ) ? 'Yes' : 'No';
$output .= '<br />';
$output .= 'Connected Accounts: ';
$output .= 'Placeholder!';
$output .= '<br />';
$output .= 'Caching: ';
if ( wp_next_scheduled( 'sby_feed_update' ) ) {
$time_format = get_option( 'time_format' );
if ( ! $time_format ) {
$time_format = 'g:i a';
}
//
$schedule = wp_get_schedule( 'sby_feed_update' );
if ( $schedule === '30mins' ) {
$schedule = __( 'every 30 minutes', 'feeds-for-youtube' );
}
if ( $schedule === 'twicedaily' ) {
$schedule = __( 'every 12 hours', 'feeds-for-youtube' );
}
$sby_next_cron_event = wp_next_scheduled( 'sby_feed_update' );
$output = __( 'Next check', 'feeds-for-youtube' ) . ': ' . gmdate( $time_format, $sby_next_cron_event + sby_get_utc_offset() ) . ' (' . $schedule . ')';
} else {
$output .= 'Nothing currently scheduled';
}
$output .= '<br />';
$output .= 'GDPR: ';
$output .= isset( $sby_settings['gdpr'] ) ? $sby_settings['gdpr'] : ' Not setup';
$output .= '<br />';
$output .= 'Custom CSS: ';
$output .= isset( $sby_settings['custom_css'] ) && ! empty( $sby_settings['custom_css'] ) ? $sby_settings['custom_css'] : 'Empty';
$output .= '<br />';
$output .= 'Custom JS: ';
$output .= isset( $sby_settings['custom_js'] ) && ! empty( $sby_settings['custom_js'] ) ? $sby_settings['custom_js'] : 'Empty';
$output .= '<br />';
$output .= 'Usage Tracking: ';
$output .= isset( $usage_tracking['enabled'] ) && $usage_tracking['enabled'] === true ? 'Enabled' : 'Disabled';
$output .= '<br />';
$output .= 'AJAX theme loading fix: ';
$output .= isset( $sby_settings['ajax_theme'] ) && $sby_settings['ajax_theme'] ? 'Enabled' : 'Disabled';
$output .= '<br />';
$output .= 'AJAX Initial: ';
$output .= isset( $sby_settings['sb_ajax_initial'] ) && $sby_settings['sb_ajax_initial'] === true ? 'Enabled' : 'Disabled';
$output .= '<br />';
$output .= 'Enqueue in Head: ';
$output .= isset( $sby_settings['enqueue_js_in_head'] ) && $sby_settings['enqueue_js_in_head'] === true ? 'Enabled' : 'Disabled';
$output .= '<br />';
$output .= 'Disable WP Posts: ';
$output .= !empty($sby_settings['disable_wp_posts']) ? 'True' : 'False';;
$output .= '<br />';
$output .= 'Enqueue in Shortcode: ';
$output .= isset( $sby_settings['enqueue_css_in_shortcode'] ) && $sby_settings['enqueue_css_in_shortcode'] === true ? 'Enabled' : 'Disabled';
$output .= '<br />';
$output .= 'Enable JS Image: ';
$output .= isset( $sby_settings['disable_js_image_loading'] ) && $sby_settings['disable_js_image_loading'] === false ? 'Enabled' : 'Disabled';
$output .= '<br />';
$output .= 'Admin Error Notice: ';
$output .= isset( $sby_settings['disable_admin_notice'] ) && $sby_settings['disable_admin_notice'] === false ? 'Enabled' : 'Disabled';
$output .= '<br />';
return $output;
}
/**
* Get Feeds Settings
*
* @since 6.0
*
* @return string
*/
public function get_feeds_settings_info() {
$output = '## FEEDS: ## <br />';
$feeds_list = $this->feed_builder->get_feed_list();
$i = 0;
foreach ( $feeds_list as $feed ) {
$settings = json_decode($feed['settings'], true);
$type = ! empty( $settings['type'] ) ? $settings['type'] : 'channel';
if ( $i >= 25 ) {
break;
}
$output .= $feed['feed_name'];
$output .= '<br />';
if ( isset( $feed['location_summary'] ) && count( $feed['location_summary'] ) > 0 ) {
$first_feed = $feed['location_summary'][0];
if ( ! empty( $first_feed['link'] ) ) {
$output .= esc_html( $first_feed['link'] ) . '?sb_debug';
$output .= '<br />';
}
}
if ( $i < ( count( $feeds_list ) - 1 ) ) {
$output .= '<br />';
}
$i++;
}
$output .= '<br />';
return $output;
}
/**
* Get Feeds Settings
*
* @since 6.0
*
* @return string
*/
public function get_sources_info() {
$output = '## Sources: ## <br />';
foreach ( [] as $source ) {
$output .= $source['account_id'];
$output .= '<br />';
$output .= 'Type: ' . esc_html( $source['account_type'] );
$output .= '<br />';
$output .= 'Username: ' . esc_html( $source['username'] );
$output .= '<br />';
$output .= 'Error: ' . esc_html( $source['error'] );
$output .= '<br />';
$output .= '<br />';
$output .= '<br />';
}
$output .= '<br />';
return $output;
}
/**
* Get Reports
*
* @since 6.0
*
* @return string
*/
public function get_cron_report() {
$output = '## Cron Cache Report: ## <br />';
$cron_report = get_option( 'sby_cron_report', array() );
if ( ! empty( $cron_report ) ) {
$output .= 'Time Ran: ' . esc_html( $cron_report['notes']['time_ran'] );
$output .= '<br />';
$output .= 'Found Feeds: ' . esc_html( $cron_report['notes']['num_found_transients'] );
$output .= '<br />';
$output .= '<br />';
foreach ( $cron_report as $key => $value ) {
if ( $key !== 'notes' ) {
$output .= esc_html( $key ) . ':';
$output .= '<br />';
if ( ! empty( $value['last_retrieve'] ) ) {
$output .= 'Last Retrieve: ' . esc_html( $value['last_retrieve'] );
$output .= '<br />';
}
$output .= 'Did Update: ' . esc_html( $value['did_update'] );
$output .= '<br />';
$output .= '<br />';
}
}
} else {
$output .= '<br />';
}
$cron = _get_cron_array();
foreach ( $cron as $key => $data ) {
$is_target = false;
foreach ( $data as $key2 => $val ) {
if ( strpos( $key2, 'sby' ) !== false || strpos( $key2, 'sb_youtube' ) !== false ) {
$is_target = true;
$output .= esc_html( $key2 );
$output .= '<br />';
}
}
if ( $is_target ) {
$output .= esc_html( date( 'Y-m-d H:i:s', $key ) );
$output .= '<br />';
$output .= esc_html( 'Next Scheduled: ' . round( ( (int) $key - time() ) / 60 ) . ' minutes' );
$output .= '<br />';
$output .= '<br />';
}
}
return $output;
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin\Settings;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Container;
class PagesServiceContainer extends ServiceProvider {
private $services = [
SettingsPage::class,
SingleVideoPage::class,
HelpPage::class,
AboutPage::class,
SetupPage::class,
];
public function register() {
$container = Container::get_instance();
foreach ( $this->services as $service ) {
$container->get($service)->register();
}
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin\Settings;
use Smashballoon\Customizer\Container;
use Smashballoon\Customizer\Feed_Builder;
use Smashballoon\Customizer\Feed_Saver;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use SmashBalloon\YouTubeFeed\Pro\SBY_CPT;
use SmashBalloon\YouTubeFeed\SBY_Settings;
class SettingsPage extends BaseSettingPage {
protected $has_assets = true;
protected $has_menu = true;
protected $template_file = 'settings.index';
/**
* @var SBY_Settings
*/
private $settings;
/**
* @var Feed_Saver
*/
private $feed_saver;
public function __construct( Feed_Saver $feed_saver, SBY_Settings $settings) {
$this->page_title = __( 'Settings', 'feeds-for-youtube' );
$this->menu_title = __( 'Settings', 'feeds-for-youtube' );
$this->menu_slug = 'settings';
$this->menu_position = 1;
$this->menu_position_free_version = 1;
$this->settings = $settings;
$this->feed_saver = $feed_saver;
}
public function register() {
parent::register();
add_action( 'wp_ajax_sby_update_settings', [ $this, 'handle_settings_update' ] );
add_filter( 'sby_localized_settings', [ $this, 'filter_settings_object' ] );
}
public function handle_settings_update() {
check_ajax_referer( 'sby-admin', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error();
}
$sanitization_skip = [
'custom_js'
];
unset( $_POST['nonce'] );
if ( ! current_user_can( 'unfiltered_html' ) ) {
unset($_POST['custom_css']);
unset($_POST['custom_js']);
}
$update_array = $_POST;
$this->handle_single_video_settings( $update_array );
foreach ( $_POST as $item => $value ) {
if ( ! in_array( $item, $sanitization_skip ) ) {
$update_array[ $item ] = sanitize_text_field( $value );
}
}
wp_clear_scheduled_hook('sby_feed_update');
if ( $this->settings->update_settings( $update_array ) ) {
wp_send_json_success();
} else {
wp_send_json_error();
}
}
private function handle_single_video_settings( &$settings ) {
$prefix = "single_video_info_";
$includes = [];
$post_status = "draft";
foreach ( $settings as $key => $setting ) {
if ( false !== strpos( $key, $prefix ) ) {
$setting_name = str_replace( $prefix, "", $key );
if ( ( $setting_name !== 'post_status' ) ) {
if ( $setting === "true" ) {
$includes[] = $setting_name;
}
} else {
$post_status = $setting;
}
unset( $settings[ $key ] );
}
}
update_option( SBY_CPT . '_settings', [
"include" => $includes,
"post_status" => $post_status
] );
}
private function get_next_cron_schedule() {
$timestamp = wp_next_scheduled('sby_feed_update');
$date = new \DateTime();
$date->setTimestamp($timestamp);
$date->setTimezone(wp_timezone());
$date_string = $date->format('h:i');
$settings = $this->settings->get_settings();
$interval = !empty($settings['cache_cron_interval']) ? $settings['cache_cron_interval'] : '1hour';
$am_pm = !empty($settings['cache_cron_am_pm']) ? $settings['cache_cron_am_pm'] : 'AM';
switch($interval) {
case '30mins':
$interval_string = __('every 30 minutes', 'feeds-for-youtube');
break;
case '12hours':
$interval_string = 'every 12 hours';
break;
case '24hours':
$interval_string = 'every 24 hours';
break;
default:
$interval_string = __('every hour', 'feeds-for-youtube');
}
return sprintf(__('<strong>Next check: %s %s (%s)</strong> - Note: Clicking "Clear All Caches" will reset this schedule.', 'feeds-for-youtube'), $date_string, strtoupper($am_pm), $interval_string);
}
public function filter_settings_object( $settings ) {
$settings['settings'] = $this->settings->get_settings();
$settings['sources'] = $this->feed_saver->get_source_list();
$settings['sbyIsPro'] = \sby_is_pro() ? true : false;
$settings['user_can_unfiltered_html'] = \current_user_can( 'unfiltered_html' ) ? true : false;
$settings['feeds'] = Container::getInstance()->get(Feed_Builder::class)->get_feed_list();
$settings['next_cron'] = $this->get_next_cron_schedule();
$settings['connect_site_parameters'] = sby_builder_pro()->oauth_connet_parameters();
return $settings;
}
}

View File

@@ -0,0 +1,289 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin\Settings;
use Smashballoon\Customizer\Container;
use Smashballoon\Customizer\Feed_Builder;
use SmashBalloon\YouTubeFeed\Services\AdminAjaxService;
use SmashBalloon\YouTubeFeed\Helpers\Util;
class SetupPage extends BaseSettingPage
{
protected $menu_slug = 'setup';
protected $menu_title = 'Setup';
protected $page_title = 'Setup';
protected $has_menu = true;
protected $template_file = 'settings.index';
protected $has_assets = true;
protected $menu_position = 0;
protected $menu_position_free_version = 0;
static $plugin_name = 'youtube';
static $statues_name = 'sby_statuses';
/**
* Filter settings object
*
* @since 2.2.4
*
* @return void
*/
public function register()
{
if(! sby_is_pro() && self::should_init_wizard() ) {
parent::register();
add_action( 'wp_ajax_sby_process_wizard', [ $this, 'ajax_process_wizard' ] );
add_action( 'wp_ajax_sby_dismiss_wizard', [ $this, 'ajax_dismiss_wizard' ] );
add_filter('sby_localized_settings', [$this, 'filter_settings_object']);
}
}
/**
* Filter settings object
*
* @param array $settings
*
* @since 2.2.4
*
* @return array
*/
public function filter_settings_object($settings)
{
$settings['onboardWizardYoutubeAccountConnectURL'] = Feed_Builder::oauth_connet_url(admin_url('admin.php?page=youtube-feed-setup&step=2'));
return $settings;
}
/**
* Check if we need to Init the Onboarding wizard
*
* @since 2.2.4
*
* @return bool
*/
public static function should_init_wizard() {
$statues = get_option( self::$statues_name, array() );
if(!isset($statues['wizard_dismissed']) || $statues['wizard_dismissed'] === false ){
return true;
}
return false;
}
/**
* Install Plugin
*
* @param string $plugin_url
*
* @since 2.2.4
*
* @return void
*/
public static function install_single_plugin( $plugin_url ){
if( !$plugin_url || !current_user_can('install_plugins') ){
return false;
}
set_current_screen( 'youtube-feed-setup' );
// Prepare variables.
$url = esc_url_raw(
add_query_arg(
array(
'page' => 'youtube-feed-setup',
),
admin_url( 'admin.php' )
)
);
$creds = request_filesystem_credentials( $url, '', false, false, null );
// Check for file system permissions.
if ( false === $creds ) {
wp_send_json_error( $error );
}
if ( ! WP_Filesystem( $creds ) ) {
wp_send_json_error( $error );
}
/*
* We do not need any extra credentials if we have gotten this far, so let's install the plugin.
*/
require_once SBY_PLUGIN_DIR . 'inc/class-install-skin.php';
// Do not allow WordPress to search/download translations, as this will break JS output.
remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
// Create the plugin upgrader with our custom skin.
$installer = new \SmashBalloon\YouTubeFeed\PluginSilentUpgrader( new \SmashBalloon\YouTubeFeed\SBY_Install_Skin() );
// Error check.
if ( ! method_exists( $installer, 'install' ) || empty( $plugin_url ) ) {
wp_send_json_error( $error );
}
$installer->install( esc_url_raw( wp_unslash( $plugin_url ) ) );
// Flush the cache and return the newly installed plugin basename.
wp_cache_flush();
$plugin_basename = $installer->plugin_info();
if ( $plugin_basename ) {
activate_plugin( $plugin_basename );
}
}
/**
* Process Wizard Data
* Save Settings, Install Plugins and more
*
* @since 2.2.4
*
* @return void
*/
public function ajax_process_wizard(){
Util::ajaxPreflightChecks();
if( ! isset( $_POST['data'] ) ){
wp_send_json_error();
}
// If in the future we need to support settings.
// $sby_settings = get_option( 'sby_settings', array() );
$onboarding_data = sanitize_text_field( stripslashes( $_POST['data'] ) );
$onboarding_data = json_decode( $onboarding_data, true);
foreach (array_keys($onboarding_data) as $key) {
// If in the future we need to support settings.
// if( !empty($key) && 'settings' === $key ){
// }
if( $key && 'plugins' === $key && !empty($onboarding_data[$key]) && current_user_can( 'install_plugins' ) ){
foreach ($onboarding_data[$key] as $single) {
if(!empty($single['url']) && !empty($single['slug'])) {
@self::install_single_plugin($single['url']);
$this->disable_installed_plugins_redirect($single['slug']);
}
}
}
}
// If in the future we need to support settings.
//update_option( 'sby_settings', $sby_settings );
}
/**
* Dismiss Onboarding Wizard
*
* @since 2.2.4
*
* @return void
*/
public function ajax_dismiss_wizard(){
Util::ajaxPreflightChecks();
$sby_statuses_option = get_option( 'sby_statuses', array() );
$sby_statuses_option['wizard_dismissed'] = true;
update_option( 'sby_statuses', $sby_statuses_option );
wp_send_json_error();
}
/**
* Disable Installed Plugins Redirect
*
* @param string $plugin_slug
*
* @since 2.2.4
*
* @return void
*/
public function disable_installed_plugins_redirect($plugin_slug){
//Monster Insight
if( 'monsterinsights' === $plugin_slug ) {
delete_transient( '_monsterinsights_activation_redirect' );
}
//All in one SEO
if( 'aioseo' === $plugin_slug ) {
update_option( 'aioseo_activation_redirect', true );
}
//WPForms
if( 'wpforms' === $plugin_slug ) {
update_option( 'wpforms_activation_redirect', true );
}
//Optin Monster
if( 'optinmonster' === $plugin_slug ) {
delete_transient( 'optin_monster_api_activation_redirect' );
update_option( 'optin_monster_api_activation_redirect_disabled', true );
}
//Seed PROD
if( 'seedprod' === $plugin_slug ) {
update_option( 'seedprod_dismiss_setup_wizard', true );
}
//PushEngage
if( 'pushengage' === $plugin_slug ) {
delete_transient( 'pushengage_activation_redirect' );
}
//WP SMTP
if( 'wp_mail_smtp' === $plugin_slug ) {
delete_transient( 'wp_mail_smtp_activation_redirect' );
}
//Rafflepress
if( 'rafflepress' === $plugin_slug ) {
delete_transient( '_rafflepress_welcome_screen_activation_redirect' );
}
//Smash Plugin redirect remove
$this->disable_smash_installed_plugins_redirect($plugin_slug);
}
/**
* Disable Smash Balloon Plugins Redirect
*
* @param string $plugin_slug
*
* @since 2.2.4
*
* @return void
*/
public function disable_smash_installed_plugins_redirect($plugin_slug)
{
$smash_list = [
'facebook' => 'cff_plugin_do_activation_redirect',
'instagram' => 'sbi_plugin_do_activation_redirect',
'youtube' => 'sby_plugin_do_activation_redirect',
'twitter' => 'ctf_plugin_do_activation_redirect',
'reviews' => 'sbr_plugin_do_activation_redirect',
];
if(!empty($smash_list[self::$plugin_name])){
unset($smash_list[self::$plugin_name]);
}
if (!empty($smash_list[$plugin_slug])) {
delete_option($smash_list[$plugin_slug]);
}
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin\Settings;
use Smashballoon\Customizer\Feed_Builder;
use Smashballoon\Customizer\Feed_Saver;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use SmashBalloon\YouTubeFeed\SBY_Settings;
use Smashballoon\Customizer\YouTube_License_Tier;
class SingleVideoPage extends BaseSettingPage {
protected $has_assets = true;
protected $has_menu = true;
protected $menu_slug = 'single-videos';
protected $template_file = 'settings.index';
protected $menu_position = 2;
protected $menu_position_free_version = 2;
private $posts_table;
private $meta_table;
public function __construct() {
$this->page_title = __('Single Videos', 'feeds-for-youtube');
$this->menu_title = __('Single Videos', 'feeds-for-youtube');
// YouTube license tier
$license_tier = new YouTube_License_Tier;
$license_tier_features = $license_tier->tier_features();
// Hide Single Videos page if feature is not available in the tier
if (!in_array('convert_videos_to_cpt', $license_tier_features)) {
$this->has_page_restriction = true;
$this->menu_title = '<span class="sby-single-videos-upsell">' . __('Single Videos', 'feeds-for-youtube') . '</span>';
}
}
public function register() {
global $wpdb;
parent::register();
$this->posts_table = $wpdb->prefix . 'posts';
$this->meta_table = $wpdb->prefix . 'postmeta';
add_action( 'wp_ajax_sby_get_single_videos', [ $this, 'ajax_query_single_videos' ] );
add_action( 'wp_ajax_sby_all_videos_action', [ $this, 'ajax_all_video_action' ] );
add_action( 'pre_get_posts', [ $this, 'filter_single_videos' ] );
add_action( 'sby_localized_settings', [ $this, 'localize_listing_url' ] );
}
public function ajax_query_single_videos() {
Util::ajaxPreflightChecks();
$page = esc_sql($_POST['page']);
wp_send_json_success(['total_result' => $this->single_videos_total(), 'results' => $this->query_single_videos($page)]);
}
public function ajax_all_video_action() {
Util::ajaxPreflightChecks();
$meta_query = [
'relation' => 'OR'
];
$exploded_channels = explode(',', $_POST['channel']);
if ( is_array( $exploded_channels ) ) {
foreach ( $exploded_channels as $channel_id ) {
$meta_query[] = [
'key' => 'sby_channel_title',
'value' => esc_sql( $channel_id ),
'compare' => '=',
];
}
} else {
$meta_query[] = [
'key' => 'sby_channel_title',
'value' => esc_sql( $exploded_channels ),
'compare' => '=',
];
}
$args = array(
'post_type' => SBY_CPT,
'meta_key' => 'sby_channel_title',
'posts_per_page' => -1,
'meta_query' => $meta_query
);
$query = new \WP_Query($args);
if($_POST['perform'] === 'publish') {
foreach ( $query->get_posts() as $post ) {
$postData = [ 'ID' => $post->ID, 'post_status' => 'publish' ];
wp_update_post( $postData );
}
}
if($_POST['perform'] === 'delete') {
foreach ( $query->get_posts() as $post ) {
wp_delete_post( $post->ID, true );
}
}
wp_send_json_success();
}
public function filter_single_videos($query) {
global $pagenow;
if ( isset($_GET['post_type'], $_GET['sby_channel_filter']) && $_GET['post_type'] === SBY_CPT && $pagenow === 'edit.php' && is_admin() && $query->is_main_query() ) {
$query->set( 'meta_key', 'sby_channel_title' );
$query->set( 'meta_value', $_GET['sby_channel_filter'] );
}
return $query;
}
public function localize_listing_url($settings) {
$settings['single_videos_list'] = admin_url(sprintf('edit.php?post_type=%s', SBY_CPT));
return $settings;
}
private function query_single_videos($page, $limit = 5) {
global $wpdb;
$query = sprintf( 'SELECT SUM(%1$s.post_status="publish") AS publish,SUM(%1$s.post_status="draft") AS draft, %2$s.meta_value as title FROM `%2$s`
JOIN %1$s ON %2$s.post_id=%1$s.ID
WHERE %2$s.meta_key="sby_channel_title"
GROUP BY %2$s.meta_value ORDER BY %1$s.ID DESC LIMIT %3$s, %4$s', $this->posts_table, $this->meta_table, ($page * $limit), $limit );
$query = $wpdb->prepare($query);
return $wpdb->get_results($query);
}
private function single_videos_total() {
global $wpdb;
$total_query = sprintf( 'SELECT SUM(%1$s.post_status="publish") AS publish,SUM(%1$s.post_status="draft") AS draft, %2$s.meta_value as title FROM `%2$s`
JOIN %1$s ON %2$s.post_id=%1$s.ID
WHERE %2$s.meta_key="sby_channel_title"
GROUP BY %2$s.meta_value', $this->posts_table, $this->meta_table );
$total_query = $wpdb->prepare($total_query);
$wpdb->get_results($total_query);
return $wpdb->num_rows;
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Admin;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Data\DataFactory;
use SmashBalloon\YouTubeFeed\Data\GoogleAPIResponseStruct;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use SmashBalloon\YouTubeFeed\SBY_API_Connect;
use SmashBalloon\YouTubeFeed\SBY_Settings;
class SourcesService extends ServiceProvider {
/**
* @var SBY_Settings
*/
private $settings;
/**
* @var SBY_API_Connect
*/
private $connect;
/**
* @var GoogleAPIResponseStruct
*/
private $api_verification_data;
/**
* @var DataFactory
*/
private $data_factory;
public function __construct(SBY_Settings $settings, SBY_API_Connect $connect, DataFactory $data_factory) {
$this->settings = $settings;
$this->connect = $connect;
$this->data_factory = $data_factory;
$this->api_verification_data = $this->data_factory->create(GoogleAPIResponseStruct::class);
}
public function register() {
add_action('wp_ajax_remove_connected_account', [$this, 'ajax_remove_account']);
add_action('wp_ajax_verify_api_key', [$this, 'ajax_verify_api_key']);
}
public function ajax_remove_account() {
Util::ajaxPreflightChecks();
$account = trim( sanitize_text_field( $_POST['account_id'] ) );
$settings = $this->settings->get_settings();
$connected_accounts = $settings['connected_accounts'];
if ( ! empty( $account ) && ! empty( $connected_accounts ) && array_key_exists( $account,
$connected_accounts ) ) {
unset( $connected_accounts[ $account ] );
$settings['connected_accounts'] = $connected_accounts;
$this->settings->update_settings( $settings );
}
}
public function ajax_verify_api_key() {
Util::ajaxPreflightChecks();
$settings = $this->settings->get_settings();
$api_key = sanitize_text_field($_POST['api_key']);
if ( empty( $api_key ) ) {
$this->respond_to_api_update($settings, $api_key);
}
$this->connect->set_url(null, null, ['username' => 'smashballoon'], $api_key);
$response = wp_remote_get($this->connect->get_url(), $this->connect->get_args());
$this->api_verification_data->response = $response['response'];
$this->api_verification_data->data = json_decode($response['body']);
$this->api_verification_data->status = $response['response']['code'] === 200;
$this->respond_to_api_update($settings, $api_key);
wp_send_json_error();
}
private function respond_to_api_update($settings, $api_key) {
update_option( 'sby_api_key_verification', $this->api_verification_data );
$settings['api_key'] = $api_key;
$this->settings->update_settings( $settings );
wp_send_json_success( $this->api_verification_data );
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,139 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use SmashBalloon\YouTubeFeed\SBY_Settings;
class AssetsService extends ServiceProvider {
public function register() {
add_action( 'wp_footer', [$this, 'sby_custom_js'] );
add_action( 'wp_head', [$this, 'sby_custom_css'] );
add_action( 'sby_enqueue_scripts', [$this, 'sby_scripts_enqueue'], 10, 1);
add_action( 'wp_enqueue_scripts', [$this, 'sby_scripts_enqueue'], 10, 1);
}
/**
* Adds the ajax url and custom JavaScript to the page
*/
public function sby_custom_js() {
global $sby_settings;
$js = isset( $sby_settings['custom_js'] ) ? trim( $sby_settings['custom_js'] ) : '';
echo '<!-- YouTube Feeds JS -->';
echo "\r\n";
echo '<script type="text/javascript">';
echo "\r\n";
if ( ! empty( $js ) ) {
echo "\r\n";
echo "if (typeof jQuery !== 'undefined') { jQuery( document ).ready(function($) {";
echo "\r\n";
echo "window.sbyCustomJS = function(){";
echo "\r\n";
echo stripslashes($js);
echo "\r\n";
echo "}";
echo "\r\n";
echo "})};";
}
echo "\r\n";
echo '</script>';
echo "\r\n";
}
public function sby_custom_css() {
global $sby_settings;
$css = '';
$css = isset( $sby_settings['custom_css'] ) ? trim( $sby_settings['custom_css'] ) : '';
//Show CSS if an Admin (so can see Hide Photos link), if including Custom CSS or if hiding some photos
if ( current_user_can( 'manage_youtube_feed_options' ) || current_user_can( 'manage_options' ) || ! empty( $css ) ) {
echo '<!-- YouTube Feeds CSS -->';
echo "\r\n";
echo '<style type="text/css">';
if ( ! empty( $css ) ){
echo "\r\n";
echo stripslashes($css);
}
if ( current_user_can( 'manage_youtube_feed_options' ) || current_user_can( 'manage_options' ) ){
echo "\r\n";
echo "#sby_mod_link, #sby_mod_error{ display: block !important; width: 100%; float: left; box-sizing: border-box; }";
}
echo "\r\n";
echo '</style>';
echo "\r\n";
}
}
/**
* Makes the JavaScript file available and enqueues the stylesheet
* for the plugin
*/
public function sby_scripts_enqueue( $sby_settings ) {
if ( ! doing_action( "sby_enqueue_scripts" ) && ! is_singular( SBY_CPT ) ) {
return;
}
$database_settings = sby_get_database_settings();
$global_settings = ( new SBY_Settings( [], $database_settings ) )->get_settings();
if ( ! is_array( $sby_settings ) ) {
$sby_settings = $global_settings;
}
//Register the script to make it available
$assets_url = trailingslashit( SBY_PLUGIN_URL );
$js_file = $assets_url . 'js/sb-youtube.min.js';
if ( isset( $_GET['sb_debug'] ) ) {
$js_file = $assets_url . 'js/sb-youtube-debug.js';
}
if(!Util::isProduction()) {
$js_file = 'http://localhost:9005/sb-youtube.min.js';
}
$enqueue_in_head = isset($global_settings['enqueue_js_in_head']) ? $global_settings['enqueue_js_in_head'] : false;
wp_register_script( 'sby_scripts', $js_file, array('jquery'), SBYVER, !$enqueue_in_head );
$css_free_file_name = 'sb-youtube-free.min.css';
$css_pro_file_name = 'sb-youtube.min.css';
$css_file_name = sby_is_pro() ? $css_pro_file_name : $css_free_file_name;
if ( !empty( $sby_settings['enqueue_css_in_shortcode'] ) ) {
wp_register_style( 'sby_styles', trailingslashit( SBY_PLUGIN_URL ) . 'css/' . $css_file_name, array(), SBYVER );
} else {
wp_enqueue_style( 'sby_styles', trailingslashit( SBY_PLUGIN_URL ) . 'css/' . $css_file_name, array(), SBYVER );
}
$data = array(
'isAdmin' => is_admin(),
'adminAjaxUrl' => admin_url( 'admin-ajax.php' ),
'placeholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder.png',
'placeholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/placeholder-narrow.png',
'lightboxPlaceholder' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder.png',
'lightboxPlaceholderNarrow' => trailingslashit( SBY_PLUGIN_URL ) . 'img/lightbox-placeholder-narrow.png',
'autoplay' => $sby_settings['playvideo'] === 'automatically',
'semiEagerload' => $sby_settings['eagerload'],
'eagerload' => false,
'nonce' => wp_create_nonce( 'sby_nonce' ),
'isPro' => sby_is_pro(),
'isCustomizer' => \sby_doing_customizer( $sby_settings )
);
//Pass option to JS file
wp_localize_script('sby_scripts', 'sbyOptions', $data );
wp_enqueue_style( 'sby_styles' );
wp_enqueue_script( 'sby_scripts' );
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use Smashballoon\Stubs\Services\ServiceProvider;
class ConfigService extends ServiceProvider {
public function register() {
add_filter('sb_customizer_sources_table', function($table) {
global $wpdb;
return $wpdb->prefix . 'sby_sources';
});
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Pro\SBY_Cron_Updater_Pro;
use SmashBalloon\YouTubeFeed\Pro\SBY_Settings_Pro;
use SmashBalloon\YouTubeFeed\SBY_Settings;
use SmashBalloon\YouTubeFeed\SBY_Cron_Updater;
class CronUpdaterService extends ServiceProvider {
public function register() {
add_action( 'init', [ $this, 'maybe_run_cron' ] );
add_action( 'sby_feed_update', [ $this, 'sby_cron_updater' ] );
}
public function maybe_run_cron() {
$database_settings = sby_get_database_settings();
$settings = ( new SBY_Settings( [], $database_settings ) )->get_settings();
$next_run = wp_next_scheduled('sby_feed_update');
if ( $next_run === false || time() > $next_run ) {
SBY_Cron_Updater::start_cron_job( $settings['cache_cron_interval'], $settings['cache_cron_time'],
$settings['cache_cron_am_pm'] );
}
}
/**
* Triggered by a cron event to update feeds
*/
public function sby_cron_updater() {
if ( \sby_is_pro() ) {
SBY_Cron_Updater_Pro::do_feed_updates();
SBY_Cron_Updater_Pro::do_comment_delete();
} else {
SBY_Cron_Updater::do_feed_updates();
}
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Pro\SBY_Settings_Pro;
use SmashBalloon\YouTubeFeed\SBY_GDPR_Integrations;
class DebugReportingService extends ServiceProvider {
public function register() {
add_action( 'sby_before_feed_end', [ $this, 'sby_debug_report' ], 11, 2 );
}
public function sby_debug_report( $youtube_feed, $feed_id ) {
if ( ! isset( $_GET['sb_debug'] ) ) {
return;
}
?>
<p>Status</p>
<ul>
<li>Time: <?php echo date( "Y-m-d H:i:s", time() ); ?></li>
<?php foreach ( $youtube_feed->get_report() as $item ) : ?>
<li><?php echo esc_html( $item ); ?></li>
<?php endforeach; ?>
</ul>
<?php
$feed = $youtube_feed->get_feed_id();
$atts = array();
if ( ! empty( $feed ) ) {
$atts = array( 'feed' => $feed );
}
$settings_obj = sby_is_pro_version() ? new SBY_Settings_Pro( $atts, sby_get_database_settings() ) : new SBY_Settings( $atts, sby_get_database_settings() );
$settings = $settings_obj->get_settings();
$public_settings_keys = sby_is_pro_version() ? SBY_Settings_Pro::get_public_db_settings_keys() : SBY_Settings::get_public_db_settings_keys();
?>
<p>Settings</p>
<ul>
<?php foreach ( $public_settings_keys as $key ) : if ( isset( $settings[ $key ] ) ) : ?>
<li>
<small><?php echo esc_html( $key ); ?>:</small>
<?php if ( ! is_array( $settings[ $key ] ) ) :
echo esc_html( $settings[ $key ] );
else : ?>
<ul>
<?php foreach ( $settings[ $key ] as $sub_key => $value ) {
echo '<li><small>' . esc_html( $sub_key ). ':</small> '. esc_html( $value ) . '</li>';
} ?>
</ul>
<?php endif; ?>
</li>
<?php endif; endforeach; ?>
</ul>
<p>GDPR</p>
<ul>
<?php
$statuses = SBY_GDPR_Integrations::statuses();
foreach ( $statuses as $status_key => $value) : ?>
<li>
<small><?php echo esc_html( $status_key ); ?>:</small>
<?php if ( $value == 1 ) { echo 'success'; } else { echo 'failed'; } ?>
</li>
<?php endforeach; ?>
<li>
<small>Enabled:</small>
<?php echo SBY_GDPR_Integrations::doing_gdpr( $settings ); ?>
</li>
</ul>
<?php
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use Smashballoon\Stubs\Services\ServiceProvider;
class ErrorReportingService extends ServiceProvider {
public function register() {
add_action( 'sby_before_feed_end', [$this, 'sby_error_report'], 10, 2 );
}
/**
* Outputs an organized error report for the front end.
* This hooks into the end of the feed before the closing div
*
* @param object $youtube_feed
* @param string $feed_id
*/
public function sby_error_report( $youtube_feed, $feed_id ) {
global $sby_posts_manager;
$style = current_user_can( 'manage_youtube_feed_options' ) ? ' style="display: block;"' : '';
$error_messages = $sby_posts_manager->get_frontend_errors();
if ( ! empty( $error_messages ) ) {?>
<div id="sby_mod_error"<?php echo $style; ?>>
<span><?php _e('This error message is only visible to WordPress admins', 'feeds-for-youtube' ); ?></span><br />
<?php if ( isset( $error_messages['accesstoken'] ) ) :
echo $error_messages['accesstoken'];
?>
<?php else: ?>
<?php foreach ( $error_messages as $error_message ) {
echo $error_message;
} ?>
<?php endif; ?>
</div>
<?php
}
$sby_posts_manager->reset_frontend_errors();
}
}

View File

@@ -0,0 +1,361 @@
<?php
/**
* SB_Analytics plugin integration
* Class to impelement filters to return
* data needed in the SB_Analytics plugin
*/
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Analytics;
use Smashballoon\Customizer\Feed_Builder;
use SmashBalloon\YouTubeFeed\SBY_Feed;
use SmashBalloon\YouTubeFeed\Pro\SBY_Feed_Pro;
use SmashBalloon\YouTubeFeed\SBY_Settings;
use SmashBalloon\YouTubeFeed\Pro\SBY_Settings_Pro;
use SmashBalloon\YouTubeFeed\SBY_Parse;
class SB_Analytics
{
/**
* Summary of current_plugin
* @var string
*/
private static $current_plugin = 'youtube';
/**
* Constructor.
*
* @since x.x.x
*/
public function register()
{
$this->load();
}
/**
* Indicate if current integration is allowed to load.
*
* @since x.x.x
*
* @return bool
*/
public function allow_load()
{
//return defined( 'SB_ANALYTICS_NAMESPACE' ); -- Need to ask regarding this condition.
return true;
}
/**
* Load an integration.
*
* @since x.x.x
*/
public function load()
{
if ($this->allow_load()) {
$this->hooks();
}
}
/**
* Hooks.
*
* @since x.x.x
*/
public function hooks()
{
//Filter Top Posts
add_filter(
'sb_analytics_filter_top_posts',
[$this, 'filter_top_posts'],
10,
3
);
//Filter Profile Details
add_filter(
'sb_analytics_filter_profile_details',
[$this, 'filter_profile_details'],
10,
3
);
//Filter Feed Lists
add_filter(
'sb_analytics_filter_feed_list',
[$this, 'filter_feed_list'],
10,
3
);
}
/**
* Summary of filter_top_posts
*
* @param array $posts
* @param array $post_ids
* @param string $plugin_slug
*
* @return array
*/
public function filter_top_posts($posts, $post_ids, $plugin_slug)
{
if ($plugin_slug !== self::$current_plugin) {
return $posts;
}
if (empty($post_ids)) {
return [];
}
return self::get_posts_by_ids($post_ids);
}
/**
* Filters and modifies profile details based on the current plugin.
*
* @param array $profile_details
* @param int $feed_id
* @param string $plugin_slug
*
* @since x.x.x
*
* @return array
*/
function filter_profile_details($profile_details, $feed_id, $plugin_slug)
{
if ($plugin_slug !== self::$current_plugin) {
return $profile_details;
}
$info = self::get_feed_source_info($feed_id);
if (empty($info)) {
return [];
}
return $info;
}
/**
* Summary of filter_feed_list
*
* @param array $feeds
* @param string $plugin_slug
*
* @since x.x.x
*
* @return array
*/
public function filter_feed_list($feeds, $plugin_slug)
{
if ($plugin_slug !== self::$current_plugin) {
return $feeds;
}
return $this->get_all_feeds();
}
/**
* Get posts by id.
*
* @param array $post_ids Posts id.
*
* @since x.x.x
*
* @return array
*/
public function get_posts_by_ids($post_ids)
{
if (empty($post_ids)) {
return [];
}
$records = [];
$feeds = Feed_Builder::instance()->get_feed_list();
foreach ($feeds as $feed) {
$feed_id = $feed['id'];
if (empty($feed_id)) {
continue;
}
$atts = ['feed' => $feed_id];
$database_settings = sby_get_database_settings();
$youtube_feed_settings =
sby_is_pro()
? new SBY_Settings_Pro($atts, $database_settings, false)
: new SBY_Settings($atts, $database_settings, false);
$youtube_feed_settings->set_feed_type_and_terms();
$youtube_feed_settings->set_transient_name();
$transient_name = $youtube_feed_settings->get_transient_name();
$youtube_feed =
sby_is_pro()
? new SBY_Feed_Pro($transient_name)
: new SBY_Feed($transient_name);
$youtube_feed->set_post_data_from_cache();
$posts = $youtube_feed->get_post_data();
foreach ($posts as $post) {
$youtube_id = '';
if (!empty($post['snippet']['liveBroadcastContent'])) {
$youtube_id = !empty($post['id']) ? $post['id'] : '';
} else {
$youtube_id = !empty($post['snippet']['resourceId']['videoId']) ? $post['snippet']['resourceId']['videoId'] : '';
}
if (in_array($youtube_id, $post_ids, true)) {
$records[$youtube_id] = [
'plugin' => [
'slug' => self::$current_plugin,
],
'feed_id' => $feed_id,
'feed_post_id' => $youtube_id,
'text' => !empty($post['snippet']['title']) ? $post['snippet']['title'] : '',
'imageSrc' => !empty($post['snippet']['thumbnails']['medium']) ? $post['snippet']['thumbnails']['medium']['url'] : '',
'updated_time_ago' => !empty($post['snippet']['publishedAt']) ? sprintf('%s ago', human_time_diff(strtotime($post['snippet']['publishedAt']), time())) : '',
'profile' => [
'label' => !empty($post['snippet']['channelTitle']) ? $post['snippet']['channelTitle'] : '',
'url' => '',
'id' => !empty($post['snippet']['channelId']) ? $post['snippet']['channelId'] : '',
],
];
}
}
}
return $records;
}
/**
* Get all feeds by using the classes from the YouTube plugin.
*
* @since x.x.x
*
* @return array
*/
public function get_all_feeds()
{
$records = [];
$feeds = Feed_Builder::instance()->get_feed_list();
if (empty($feeds)) {
return $records;
}
foreach ($feeds as $feed) {
$feed_id = $feed['id'];
$records[] = [
'value' => [
'feed_id' => !empty($feed_id) ? $feed_id : '',
],
'label' => ! empty($feed['feed_title']) ? $feed['feed_title'] : $feed['feed_name'],
];
}
return $records;
}
/**
* Retrieves source information for a specific feed.
*
* @param int $feed_id
*
* @since x.x.x
*
* @return array
*/
public function get_feed_source_info($feed_id)
{
if (empty($feed_id)) {
return [];
}
$header_data = self::get_header_data($feed_id);
if (empty($header_data)) {
return [];
}
$channel_title = SBY_Parse::get_channel_title( $header_data );
$avatar = SBY_Parse::get_avatar( $header_data, [] );
$source_id = null;
if ( ! empty( $header_data['items'][0]['id'] ) ) {
$source_id = $header_data['items'][0]['id'];
}
return [
'id' => $source_id,
'pluginSlug' => self::$current_plugin,
'profile' => [
'label' => !empty($channel_title) ? $channel_title : '',
'imageSrc' => !empty($avatar) ? $avatar : '',
],
];
}
/**
* Get header data.
*
* @param int $feed_id.
*
* @since x.x.x
*
* @return array
*/
public static function get_header_data($feed_id)
{
$atts = ['feed' => $feed_id];
$database_settings = sby_get_database_settings();
$youtube_feed_settings = sby_is_pro() ? new SBY_Settings_Pro($atts, $database_settings) : new SBY_Settings($atts, $database_settings);
if (empty($database_settings['connected_accounts']) && empty($database_settings['api_key'])) {
return [];
}
$youtube_feed_settings->set_feed_type_and_terms();
$youtube_feed_settings->set_transient_name();
$transient_name = $youtube_feed_settings->get_transient_name();
$youtube_feed = sby_is_pro()
? new SBY_Feed_Pro($transient_name)
: new SBY_Feed($transient_name);
$youtube_feed->set_header_data_from_cache();
$header_data = $youtube_feed->get_header_data();
if ($header_data) {
return $header_data;
}
$youtube_feed->set_remote_header_data(
$youtube_feed_settings,
$youtube_feed_settings->get_feed_type_and_terms(),
$youtube_feed_settings->get_connected_accounts_in_feed()
);
$header_data = $youtube_feed->get_header_data();
}
}

View File

@@ -0,0 +1,196 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Divi;
use SmashBalloon\YouTubeFeed\Services\Integrations\SBY_Integration;
use SmashBalloon\YouTubeFeed\Helpers\Util;
/**
* Class Divi Handler.
*
* @since 2.3
*/
class SBY_Divi_Handler
{
/**
* Constructor.
*
* @since 2.3
*/
public function register()
{
$this->load();
}
/**
* Indicate if current integration is allowed to load.
*
* @since 2.3
*
* @return bool
*/
public function allow_load()
{
if (function_exists('et_divi_builder_init_plugin')) {
return true;
}
$allow_themes = [ 'Divi' ];
$theme_name = get_template();
return in_array($theme_name, $allow_themes, true);
}
/**
* Load an integration.
*
* @since 2.3
*/
public function load()
{
if ($this->allow_load()) {
$this->hooks();
}
}
/**
* Hooks.
*
* @since 2.3
*/
public function hooks()
{
add_action('et_builder_ready', [ $this, 'register_module' ]);
if (wp_doing_ajax()) {
add_action('wp_ajax_sb_youtubefeed_divi_preview', [ $this, 'preview' ]);
}
if ($this->is_divi_builder()) {
add_action('wp_enqueue_scripts', [ $this, 'builder_scripts' ]);
}
}
/**
* Load scripts.
*
* @since 2.3
*/
public function builder_scripts()
{
$css_free_file_name = 'sb-youtube-free.min.css';
$css_pro_file_name = 'sb-youtube.min.css';
$css_file_name = sby_is_pro() ? $css_pro_file_name : $css_free_file_name;
wp_enqueue_style('sby_styles', trailingslashit(SBY_PLUGIN_URL) . 'css/' . $css_file_name, array(), SBYVER);
$data = array(
'isAdmin' => is_admin(),
'adminAjaxUrl' => admin_url('admin-ajax.php'),
'placeholder' => trailingslashit(SBY_PLUGIN_URL) . 'img/placeholder.png',
'placeholderNarrow' => trailingslashit(SBY_PLUGIN_URL) . 'img/placeholder-narrow.png',
'lightboxPlaceholder' => trailingslashit(SBY_PLUGIN_URL) . 'img/lightbox-placeholder.png',
'lightboxPlaceholderNarrow' => trailingslashit(SBY_PLUGIN_URL) . 'img/lightbox-placeholder-narrow.png',
'autoplay' => false,
'semiEagerload' => false,
'eagerload' => false,
'nonce' => wp_create_nonce('sby_nonce'),
'isPro' => sby_is_pro(),
'resized_url' => Util::sby_get_resized_uploads_url(),
'isCustomizer' => false
);
wp_enqueue_script(
'sbyscripts',
SBY_PLUGIN_URL . 'js/sb-youtube.min.js',
array('jquery'),
SBYVER,
true
);
wp_localize_script('sbyscripts', 'sbyOptions', $data);
wp_enqueue_script(
'sbyoutube-divi',
// The unminified version is not supported by the browser.
SBY_PLUGIN_URL . 'js/divi-handler.min.js',
['react', 'react-dom', 'jquery'],
SBYVER,
true
);
wp_enqueue_script(
'sby-divi-handler',
// The unminified version is not supported by the browser.
SBY_PLUGIN_URL . 'js/divi-preview-handler.js',
['jquery'],
SBYVER,
true
);
wp_localize_script(
'sbyoutube-divi',
'sb_divi_builder',
[
'ajax_handler' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('sby-admin'),
'feed_splash' => htmlspecialchars(SBY_Integration::get_widget_cta('button'), ENT_QUOTES | ENT_HTML5)
]
);
}
/**
* Register module.
*
* @since 2.3
*/
public function register_module()
{
if (!class_exists('ET_Builder_Module')) {
return;
}
new SB_YouTube_Feed();
}
/**
* Ajax handler for the Feed preview.
*
* @since 2.3
*/
public function preview()
{
check_ajax_referer('sby-admin', 'nonce');
$cap = current_user_can('manage_youtube_feed_options') ? 'manage_youtube_feed_options' : 'manage_options';
$cap = apply_filters('sby_settings_pages_capability', $cap);
if (! current_user_can($cap)) {
wp_send_json_error(); // This auto-dies.
}
$feed_id = absint(filter_input(INPUT_POST, 'feed_id', FILTER_SANITIZE_NUMBER_INT));
wp_send_json_success(
do_shortcode(
sprintf(
'[youtube-feed feed="%1$s"]',
absint($feed_id)
)
)
);
}
/**
* Determine if a current page is opened in the Divi Builder.
*
* @since 2.3
*
* @return bool
*/
private function is_divi_builder()
{
return !empty($_GET['et_fb']); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Divi;
use ET_Builder_Module;
use SmashBalloon\YouTubeFeed\Builder\SBY_Db;
class SB_YouTube_Feed extends ET_Builder_Module {
/**
* Module slug.
*
* @var string
*/
public $slug = 'sb_youtube_feed';
/**
* VB support.
*
* @var string
*/
public $vb_support = 'on';
/**
* Init module.
*
* @since 2.3
*/
public function init() {
$this->name = esc_html__('YouTube Feed', 'feeds-for-youtube');
}
/**
* Get list of settings.
*
* @since 2.3
*
* @return array
*/
public function get_fields() {
$feeds_divi = array();
$feeds_list = SBY_Db::elementor_feeds_query();
if ( ! empty( $feeds_list ) ) {
$feeds_divi[ 'sby-0' ] = esc_html__('Select Youtube Feed', 'feeds-for-youtube');
foreach ( $feeds_list as $key => $feed ) {
$feeds_divi[ 'sby-' . $key ] = $feed;
}
}
return [
'feed_id' => [
'label' => esc_html__('Feed', 'feeds-for-youtube'),
'type' => 'select',
'option_category' => 'basic_option',
'toggle_slug' => 'main_content',
'options' => $feeds_divi,
]
];
}
/**
* Disable advanced fields configuration.
*
* @since 2.3
*
* @return array
*/
public function get_advanced_fields_config() {
return [
'link_options' => false,
'text' => false,
'background' => false,
'borders' => false,
'box_shadow' => false,
'button' => false,
'filters' => false,
'fonts' => false,
];
}
/**
* Render module on the frontend.
*
* @since 2.3
*
* @param array $attrs List of unprocessed attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render($attrs, $content = null, $render_slug = '') {
if (empty($this->props['feed_id'])) {
return '';
}
$feed_id = str_replace('sby-', '', $this->props['feed_id']);
return do_shortcode(
sprintf(
'[youtube-feed feed="%1$s"]',
absint($feed_id)
)
);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Elementor;
use \Elementor\Widget_Base;
use \Elementor\Controls_Manager;
if (!defined('ABSPATH'))
exit; // Exit if accessed directly
class CFF_Elementor_Widget extends Widget_Base {
public function get_name() {
return 'cff-widget';
}
public function get_title() {
return esc_html__('Facebook Feed', 'feeds-for-youtube');
}
public function get_icon() {
return 'sb-elem-icon sb-elem-inactive sb-elem-facebook';
}
public function get_categories() {
return array('smash-balloon');
}
public function get_script_depends() {
return [
'sby-elementor-handler'
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Elementor;
use \Elementor\Widget_Base;
use \Elementor\Controls_Manager;
if (!defined('ABSPATH'))
exit; // Exit if accessed directly
class CTF_Elementor_Widget extends Widget_Base {
public function get_name() {
return 'ctf-widget';
}
public function get_title() {
return esc_html__('Twitter Feed', 'feeds-for-youtube');
}
public function get_icon() {
return 'sb-elem-icon sb-elem-inactive sb-elem-twitter';
}
public function get_categories() {
return array('smash-balloon');
}
public function get_script_depends() {
return [
'sby-elementor-handler'
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Elementor;
use \Elementor\Widget_Base;
use \Elementor\Controls_Manager;
if (!defined('ABSPATH'))
exit; // Exit if accessed directly
class SBI_Elementor_Widget extends Widget_Base {
public function get_name() {
return 'sbi-widget';
}
public function get_title() {
return esc_html__('Instagram Feed', 'feeds-for-youtube');
}
public function get_icon() {
return 'sb-elem-icon sb-elem-inactive sb-elem-instagram';
}
public function get_categories() {
return array('smash-balloon');
}
public function get_script_depends() {
return [
'sby-elementor-handler'
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Elementor;
use \Elementor\Widget_Base;
use \Elementor\Controls_Manager;
if (!defined('ABSPATH'))
exit; // Exit if accessed directly
class SBR_Elementor_Widget extends Widget_Base {
public function get_name() {
return 'sbr-widget';
}
public function get_title() {
return esc_html__('Reviews Feed', 'feeds-for-youtube');
}
public function get_icon() {
return 'sb-elem-icon sb-elem-inactive sb-elem-reviews';
}
public function get_categories() {
return array('smash-balloon');
}
public function get_script_depends() {
return [
'sby-elementor-handler'
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Elementor;
use \Elementor\Widget_Base;
use \Elementor\Controls_Manager;
if (!defined('ABSPATH'))
exit; // Exit if accessed directly
class SBTT_Elementor_Widget extends Widget_Base {
public function get_name() {
return 'sbtt-widget';
}
public function get_title() {
return esc_html__('TikTok Feed', 'feeds-for-youtube');
}
public function get_icon() {
return 'sb-elem-icon sb-elem-inactive sb-elem-tiktok';
}
public function get_categories() {
return array('smash-balloon');
}
public function get_script_depends() {
return [
'sby-elementor-handler'
];
}
}

View File

@@ -0,0 +1,150 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Elementor;
use SmashBalloon\YouTubeFeed\Services\Integrations\Elementor\SBY_Elementor_Control;
use SmashBalloon\YouTubeFeed\Services\Integrations\Elementor\SBY_Elementor_Widget;
use SmashBalloon\YouTubeFeed\Helpers\Util;
class SBY_Elementor_Base
{
const VERSION = SBYVER;
const MINIMUM_ELEMENTOR_VERSION = '3.6.0';
const MINIMUM_PHP_VERSION = '5.6';
const NAME_SPACE = 'SmashBalloon.YouTubeFeed.Services.Integrations.Elementor.';
private static $instance;
public static function register()
{
if (!isset(self::$instance) && !self::$instance instanceof SBY_Elementor_Base) {
self::$instance = new SBY_Elementor_Base();
self::$instance->apply_hooks();
}
return self::$instance;
}
private function apply_hooks()
{
add_action('elementor/frontend/after_register_scripts', [$this, 'register_frontend_scripts']);
add_action('elementor/frontend/after_register_styles', [$this, 'register_frontend_styles'], 10);
add_action('elementor/frontend/after_enqueue_styles', [$this, 'enqueue_frontend_styles'], 10);
add_action('elementor/controls/register', [$this, 'register_controls']);
add_action('elementor/widgets/register', [$this,'register_widgets']);
add_action('elementor/elements/categories_registered', [$this, 'add_smashballon_categories']);
}
public function register_controls($controls_manager)
{
$controls_manager->register(new SBY_Elementor_Control());
}
public function register_widgets($widgets_manager)
{
$widgets_manager->register(new SBY_Elementor_Widget());
$installed_plugins = sby_get_installed_plugin_info();
unset($installed_plugins['youtube']);
foreach($installed_plugins as $plugin) {
if (!$plugin['installed']){
$plugin_class = str_replace('.','\\', self::NAME_SPACE) . $plugin['class'];
$widgets_manager->register(new $plugin_class());
}
}
}
public function register_frontend_scripts(){
$css_free_file_name = 'sb-youtube-free.min.css';
$css_pro_file_name = 'sb-youtube.min.css';
$css_file_name = sby_is_pro() ? $css_pro_file_name : $css_free_file_name;
wp_enqueue_style(
'sby_styles',
trailingslashit(SBY_PLUGIN_URL) . 'css/' . $css_file_name,
array(),
SBYVER
);
$data = array(
'isAdmin' => is_admin(),
'adminAjaxUrl' => admin_url('admin-ajax.php' ),
'placeholder' => trailingslashit(SBY_PLUGIN_URL) . 'img/placeholder.png',
'placeholderNarrow' => trailingslashit(SBY_PLUGIN_URL) . 'img/placeholder-narrow.png',
'lightboxPlaceholder' => trailingslashit(SBY_PLUGIN_URL) . 'img/lightbox-placeholder.png',
'lightboxPlaceholderNarrow' => trailingslashit(SBY_PLUGIN_URL) . 'img/lightbox-placeholder-narrow.png',
'autoplay' => false,
'semiEagerload' => false,
'eagerload' => false,
'nonce' => wp_create_nonce('sby_nonce'),
'isPro' => sby_is_pro(),
'resized_url' => Util::sby_get_resized_uploads_url(),
'isCustomizer' => false
);
wp_register_script(
'sbyscripts',
SBY_PLUGIN_URL . 'js/sb-youtube.min.js',
array('jquery'),
SBYVER,
true
);
wp_localize_script( 'sbyscripts', 'sbyOptions', $data );
$data_handler = array(
'smashPlugins' => sby_get_installed_plugin_info(),
'nonce' => wp_create_nonce('sby-admin'),
'ajax_handler' => admin_url('admin-ajax.php'),
);
wp_register_script(
'sby-elementor-handler',
SBY_PLUGIN_URL . 'js/elementor-handler.js' ,
array('jquery'),
SBYVER,
true
);
wp_localize_script('sby-elementor-handler', 'sbHandler', $data_handler);
wp_register_script(
'sby-elementor-preview',
SBY_PLUGIN_URL . 'js/elementor-preview.js' ,
array('jquery'),
SBYVER,
true
);
}
public function register_frontend_styles()
{
$css_free_file_name = 'sb-youtube-free.min.css';
$css_pro_file_name = 'sb-youtube.min.css';
$css_file_name = sby_is_pro() ? $css_pro_file_name : $css_free_file_name;
wp_register_style(
'sby-styles',
SBY_PLUGIN_URL . 'css/' . $css_file_name,
array(),
SBYVER
);
}
public function enqueue_frontend_styles()
{
wp_enqueue_style('sby-styles');
}
public function add_smashballon_categories($elements_manager)
{
$elements_manager->add_category(
'smash-balloon',
[
'title' => esc_html__('Smash Balloon', 'feeds-for-youtube'),
'icon' => 'fa fa-plug',
]
);
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Elementor;
use \Elementor\Base_Data_Control;
use \Elementor\Controls_Manager;
if (!defined('ABSPATH'))
exit; // Exit if accessed directly
class SBY_Elementor_Control extends Base_Data_Control {
public function get_type(){
return 'sby_feed_control';
}
public function enqueue(){
wp_enqueue_style(
'sby-elementor-style',
SBY_PLUGIN_URL . 'css/sb-elementor.css' ,
null,
SBYVER
);
}
protected function get_default_settings(){
return [
'label_block' => false
];
}
public function content_template() {
$control_uid = $this->get_control_uid();
?>
<div class="elementor-control-field">
<# if ( data.label ) {#>
<label for="<?php echo $control_uid; ?>" class="elementor-control-title">{{{ data.label }}}</label>
<# } #>
<div class="elementor-control-input-wrapper elementor-control-unit-5">
<select id="<?php echo $control_uid; ?>" data-setting="{{ data.name }}" onchange="jQuery(this).parents('.elementor-control-field').find('.link-sby-builder').attr('href', '<?php echo admin_url( 'admin.php?page=sby-feed-builder' ) ?>&feed_id='+jQuery(this).val())">
<#
var printOptions = function( options ) {
_.each( options, function( option_title, option_value ) { #>
<option value="{{ option_value }}">{{{ option_title }}}</option>
<# } );
};
if ( data.groups ) {
for ( var groupIndex in data.groups ) {
var groupArgs = data.groups[ groupIndex ];
if ( groupArgs.options ) { #>
<optgroup label="{{ groupArgs.label }}">
<# printOptions( groupArgs.options ) #>
</optgroup>
<# } else if ( _.isString( groupArgs ) ) { #>
<option value="{{ groupIndex }}">{{{ groupArgs }}}</option>
<# }
}
} else {
printOptions( data.options );
}
#>
</select>
<div style="font-weight: 700; color:#a73061; margin-top: 10px;">
<# if( data.controlValue != undefined && data.controlValue != '' ) { #>
<a class="link-sby-builder" href="<?php echo admin_url( 'admin.php?page=sby-feed-builder' ) ?>&feed_id={{data.controlValue}}" target="_blank"><?php echo __('Edit this Feed', 'feeds-for-youtube'); ?></a>
<span style="color:#aaa; display: inline-block; margin: 0 5px;">|</span>
<# } #>
<a href="<?php echo admin_url( 'admin.php?page=sby-feed-builder' ) ?>" target="_blank"><?php echo __('Create New Feed', 'feeds-for-youtube'); ?></a>
</div>
</div>
</div>
<# if ( data.description ) { #>
<div class="elementor-control-field-description">{{{ data.description }}}</div>
<# } #>
<?php
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations\Elementor;
use \Elementor\Widget_Base;
use \Elementor\Controls_Manager;
use SmashBalloon\YouTubeFeed\Builder\SBY_Db;
use SmashBalloon\YouTubeFeed\Services\Integrations\SBY_Integration;
if (!defined('ABSPATH'))
exit; // Exit if accessed directly
class SBY_Elementor_Widget extends Widget_Base {
public function get_name() {
return 'sby-widget';
}
public function get_title() {
return esc_html__('YouTube Feed', 'feeds-for-youtube');
}
public function get_icon() {
return 'sb-elem-icon sb-elem-youtube';
}
public function get_categories() {
return array('smash-balloon');
}
public function get_script_depends() {
return [
'sbyscripts',
'sby-elementor-preview'
];
}
protected function register_controls() {
/********************************************
CONTENT SECTION
********************************************/
$this->start_controls_section(
'section_content',
[
'label' => esc_html__('YouTube Feed Settings', 'feeds-for-youtube'),
]
);
$this->add_control(
'feed_id',
[
'label' => esc_html__('Select a Feed', 'feeds-for-youtube'),
'type' => 'sby_feed_control',
'label_block' => true,
'dynamic' => ['active' => true],
'options' => SBY_Db::elementor_feeds_query(),
]
);
$this->end_controls_section();
}
protected function render() {
$settings = $this->get_settings_for_display();
if (isset($settings['feed_id']) && !empty($settings['feed_id'])) {
$feed_id = (int) $settings['feed_id'];
$output = do_shortcode( shortcode_unautop( '[youtube-feed feed='. $feed_id .']' ) );
} else {
$output = is_admin() ? SBY_Integration::get_widget_cta() : '';
}
echo apply_filters('sby_output', $output, $settings);
}
}

View File

@@ -0,0 +1,139 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Integrations;
use SmashBalloon\YouTubeFeed\Builder\SBY_Db;
if (!defined('ABSPATH'))
exit; // Exit if accessed directly
/**
* SBY_Integration Class
* Common funcions for Elementor/Divi/Gutenberg
*
* @since 2.3
*
* @return array
*/
class SBY_Integration {
/**
* Generate link
*
* @since 2.3
*
* @return HTML
*/
public static function linkGenerator($link, $link_text) {
ob_start(); ?>
<a href="<?php echo esc_url( $link ) ?>" class="sby-feed-block-link">
<?php echo esc_html($link_text); ?>
</a>
<?php
$html = ob_get_contents();
ob_get_clean();
return $html;
}
/**
* Get Widget/Module/Block Info
*
* @since 2.3
*
* @return array
*/
public static function get_widget_info()
{
return [
'plugin' => 'youtube',
'cta_header' => esc_html__('Get started with your first feed from your YouTube Channel', 'feeds-for-youtube'),
'cta_header2' => esc_html__('Select a YouTube feed to embed', 'feeds-for-youtube'),
'cta_description_free' => esc_html__('You can display feeds for your YouTube channel, playlist, live streams and more using the ', 'feeds-for-youtube') . self::linkGenerator('https://smashballoon.com/youtube-feed/?utm_campaign=' . sby_utm_campaign() . '&utm_source=elementor&utm_medium=widget&utm_content=proversion', 'Pro version'),
'cta_description_pro' => esc_html__('You can also add Instagram, Facebook, and Twitter posts into your feed using our ', 'feeds-for-youtube') . self::linkGenerator('https://smashballoon.com/social-wall/?utm_campaign=' . sby_utm_campaign() . '&utm_source=elementor&utm_medium=widget&utm_content=socialwall', 'Social Wall plugin'),
'plugins' => sby_get_installed_plugin_info()
];
}
/**
* Widget CTA
*
* @since 2.3
*
* @return HTML
*/
public static function get_widget_cta( $type = 'dropdown' )
{
$widget_cta_html = '';
$feeds_list = SBY_Db::elementor_feeds_query();
ob_start();
self::get_widget_cta_html( $feeds_list, $type );
$widget_cta_html .= ob_get_contents();
ob_get_clean();
return $widget_cta_html;
}
public static function get_widget_cta_html( $feeds_list, $type )
{
$info = self::get_widget_info();
$feeds_exist = is_array( $feeds_list ) && sizeof( $feeds_list ) > 0;
?>
<div class="sby-feed-block-cta">
<div class="sby-feed-block-cta-img-ctn">
<div class="sby-feed-block-cta-img">
<span><?php echo $info['plugins'][$info['plugin']]['icon']; ?></span>
<svg class="sby-feed-block-cta-logo" width="31" height="39" viewBox="0 0 31 39" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.62525 18.4447C1.62525 26.7883 6.60827 33.9305 13.3915 35.171L12.9954 36.4252L12.5937 37.6973L13.923 37.5843L18.4105 37.2026L20.0997 37.0589L19.0261 35.7468L18.4015 34.9834C24.7525 33.3286 29.3269 26.4321 29.3269 18.4447C29.3269 9.29016 23.2952 1.53113 15.4774 1.53113C7.65975 1.53113 1.62525 9.2899 1.62525 18.4447Z" fill="#FE544F" stroke="white" stroke-width="1.78661"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.5669 8.05676L19.1904 14.4905L25.6512 14.6761L20.9776 19.0216L24.6689 22.3606L18.4503 23.1916L16.5651 29.4104L13.7026 23.8415L7.92284 26.4899L10.1462 20.5199L4.50931 17.6767L10.5435 15.7361L8.8784 9.79176L14.5871 13.0464L18.5669 8.05676Z" fill="white"/></svg>
</div>
</div>
<h3 class="sby-feed-block-cta-heading"><?php echo $feeds_exist ? $info['cta_header2'] : $info['cta_header'] ?></h3>
<?php if($feeds_exist): ?>
<div class="sby-feed-block-cta-selector">
<?php if( $type == 'dropdown' ): ?>
<select class="sby-feed-block-cta-feedselector">
<option><?php echo __('Select', 'feeds-for-youtube') . ' ' . ucfirst($info['plugin']) . ' '. __('Feed', 'feeds-for-youtube')?> </option>
<?php foreach ($feeds_list as $feed_id => $feed_name): ?>
<option value="<?php echo $feed_id ?>"><?php echo $feed_name ?></option>
<?php endforeach ?>
</select>
<?php elseif( $type == 'button' ): ?>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=sby-feed-builder' ) ) ?>" rel="noopener noreferrer" class="sby-feed-block-cta-btn">
<?php echo esc_html__('Create YouTube Feed', 'feeds-for-youtube'); ?>
</a>
<?php endif; ?>
<?php if( $type == 'dropdown' ): ?>
<span class="sby-feed-block-create-with">
<?php
echo esc_html__('Or create a Feed for', 'feeds-for-youtube');
unset( $info['plugins'][$info['plugin']] );
foreach ($info['plugins'] as $name => $plugin):
$dashboard_permalink = !empty($plugin['dashboard_permalink']) ? $plugin['dashboard_permalink'] : '';
$installed = !empty($plugin['installed']) ? $plugin['installed'] : '';
$activated = !empty($plugin['activated']) ? $plugin['activated'] : '';
$website_link = !empty($plugin['website_link']) ? $plugin['website_link'] : '';
$link = $installed && $activated ? $dashboard_permalink : $website_link;
?>
<a href="<?php echo esc_attr($link); ?>" target="_blank" class="sby-feed-block-link"><?php echo $name ?></a>
<?php endforeach ?>
</span>
<?php endif; ?>
</div>
<?php else: ?>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=sby-feed-builder' ) ) ?>" class="sby-feed-block-cta-btn"><?php echo esc_html__('Create', 'feeds-for-youtube') . ' ' . ucfirst($info['plugin']) . ' ' . esc_html__('Feed', 'feeds-for-youtube') ?></a>
<?php endif; ?>
<div class="sby-feed-block-cta-desc">
<strong><?php echo esc_html__('Did you Know?', 'feeds-for-youtube') ?></strong>
<span>
<?php echo \sby_is_pro() ? $info['cta_description_pro'] : $info['cta_description_free']; ?>
</span>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,158 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use SmashBalloon\YouTubeFeed\Services\Admin\LicenseService;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use Smashballoon\Customizer\Feed_Builder;
use Smashballoon\Customizer\DB;
class LicenseNotification extends ServiceProvider {
protected $db;
public function __construct() {
$this->db = new DB();
}
public function register() {
add_action( 'wp_footer', [$this, 'sby_frontend_license_error'], 300 );
add_action( 'wp_ajax_sby_hide_frontend_license_error', [$this, 'hide_frontend_license_error'], 10 );
add_action( 'wp_ajax_sby_recheck_connection', array( $this, 'sby_recheck_connection' ) );
}
/**
* Hide the frontend license error message for a day
*
* @since 2.0.3
*/
public function hide_frontend_license_error() {
check_ajax_referer( 'sby_nonce' , 'nonce');
set_transient( 'sby_license_error_notice', true, DAY_IN_SECONDS );
wp_die();
}
public function sby_frontend_license_error() {
// Don't do anything for guests.
if ( ! is_user_logged_in() ) {
return;
}
if ( ! sby_is_pro() ) {
return;
}
if ( !current_user_can( Util::sby_capability_check() ) ) {
return;
}
// Check that the license exists and the user hasn't already clicked to ignore the message
if ( empty( Util::get_license_key() ) ) {
$this->sby_frontend_license_error_content( 'inactive' );
return;
}
// If license not expired then return;
if ( !Util::is_license_expired() ) {
return;
}
if ( Util::is_license_grace_period_ended( true ) ) {
$this->sby_frontend_license_error_content();
}
return;
}
/**
* Output frontend license error HTML content
*
* @since 2.0.2
*/
public function sby_frontend_license_error_content( $license_state = 'expired' ) {
$icons = sby_builder_pro()->builder_svg_icons();
$feeds_count = $this->db->feeds_count();
if ( $feeds_count <= 0 ) {
return;
}
$should_display_license_error_notice = get_transient( 'sby_license_error_notice' );
if ( $should_display_license_error_notice ) {
return;
}
?>
<div id="sby-fr-ce-license-error" class="sby-critical-error sby-frontend-license-notice sby-ce-license-<?php echo $license_state; ?>">
<div class="sby-fln-header">
<span class="sb-left">
<?php echo $icons['eye2']; ?>
<span class="sb-text">Only Visible to WordPress Admins</span>
</span>
<span id="sby-frce-hide-license-error" class="sb-close"><?php echo $icons['times']; ?></span>
</div>
<div class="sby-fln-body">
<?php echo $icons['instagram']; ?>
<div class="sby-fln-expired-text">
<p>
<?php
printf(
__( 'Your YouTube Feeds Pro license key %s', 'feeds-for-youtube' ),
$license_state == 'expired' ? 'has ' . $license_state : 'is ' . $license_state
);
?>
<a href="<?php echo $this->get_renew_url( $license_state ); ?>">Resolve Now <?php echo $icons['chevronRight']; ?></a>
</p>
</div>
</div>
</div>
<?php
}
/**
* SBY Re-Check License
*
* @since 2.2.0
*/
public function sby_recheck_connection() {
// Do the form validation
$license_key = isset( $_POST['license_key'] ) ? sanitize_text_field( $_POST['license_key'] ) : '';
if ( empty( $license_key ) ) {
wp_send_json_error();
}
// make the remote license check API call
$sby_license_data = Util::sby_check_license( $license_key );
// update options data
$license_changed = Util::update_recheck_license_data( $sby_license_data );
// send AJAX response back
wp_send_json_success(
array(
'license' => $sby_license_data->license,
'licenseChanged' => $license_changed,
)
);
}
/**
* SBY Get Renew License URL
*
* @since 2.0
*
* @return string $url
*/
public function get_renew_url( $license_state = 'expired' ) {
global $sby_download_id;
if ( $license_state == 'inactive' ) {
return admin_url('admin.php?page=youtube-feed-settings');
}
$license_key = get_option( 'sby_license_key' ) ? get_option( 'sby_license_key' ) : null;
$url = sprintf(
'https://smashballoon.com/checkout/?edd_license_key=%s&download_id=%s&utm_campaign=youtube-pro&utm_source=expired-notice&utm_medium=renew-license',
$license_key,
$sby_download_id
);
return $url;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use SmashBalloon\YouTubeFeed\Container;
use Smashballoon\Customizer\Customizer_Service;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Builder\Tooltip_Wizard;
use SmashBalloon\YouTubeFeed\Customizer\Tabs\TabsService;
use SmashBalloon\YouTubeFeed\Builder\SBY_Feed_Saver_Manager;
use SmashBalloon\YouTubeFeed\Services\Upgrade\RoutineManagerService;
use SmashBalloon\YouTubeFeed\Services\LicenseNotification;
use SmashBalloon\YouTubeFeed\Services\Integrations\Elementor\SBY_Elementor_Base;
use SmashBalloon\YouTubeFeed\Services\Integrations\Divi\SBY_Divi_Handler;
use SmashBalloon\YouTubeFeed\Services\Integrations\Analytics\SB_Analytics;
class ServiceContainer extends ServiceProvider
{
protected $services = [
CronUpdaterService::class,
RoutineManagerService::class,
ConfigService::class,
AssetsService::class,
TabsService::class,
Customizer_Service::class,
AdminAjaxService::class,
DebugReportingService::class,
ErrorReportingService::class,
ShortcodeService::class,
SBY_Feed_Saver_Manager::class,
Tooltip_Wizard::class,
LicenseNotification::class,
SBY_Elementor_Base::class,
SBY_Divi_Handler::class,
SB_Analytics::class,
];
public function register()
{
$container = Container::get_instance();
foreach ($this->services as $service) {
$container->get($service)->register();
}
}
}

View File

@@ -0,0 +1,239 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services;
use SmashBalloon\YouTubeFeed\SBY_Feed;
use SmashBalloon\YouTubeFeed\SBY_Settings;
use SmashBalloon\YouTubeFeed\Helpers\Util;
use SmashBalloon\YouTubeFeed\Pro\SBY_Feed_Pro;
use SmashBalloon\YouTubeFeed\SBY_Cron_Updater;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Pro\SBY_Settings_Pro;
use SmashBalloon\YouTubeFeed\SBY_Display_Elements;
use SmashBalloon\YouTubeFeed\Pro\SBY_Cron_Updater_Pro;
class ShortcodeService extends ServiceProvider {
public function register() {
add_shortcode('youtube-feed', [$this, 'sby_youtube_feed']);
add_filter('sby_render_shortcode', [$this, 'sby_youtube_feed'], 10, 2);
add_filter('do_shortcode_tag', [$this, 'check_cron_status'], 10, 4);
}
public function sby_youtube_feed( $atts = array(), $preview_settings = false ) {
$database_settings = sby_get_database_settings();
$sby_settings_class = sby_is_pro() ? SBY_Settings_Pro::class : SBY_Settings::class;
$youtube_feed_settings = new $sby_settings_class( $atts, $database_settings, $preview_settings );
$youtube_feed_settings->set_feed_type_and_terms();
$youtube_feed_settings->set_transient_name();
$transient_name = $youtube_feed_settings->get_transient_name();
$settings = $youtube_feed_settings->maybe_get_settings_or_legacy_settings( $atts );
$feed_type_and_terms = $youtube_feed_settings->get_feed_type_and_terms();
do_action('sby_enqueue_scripts', $settings);
if ( !$database_settings['ajaxtheme'] ) {
wp_enqueue_script( 'sby_scripts' );
}
if ( $database_settings['enqueue_css_in_shortcode'] ) {
wp_enqueue_style( 'sby_styles' );
}
if ( empty( $database_settings['connected_accounts'] ) && empty( $database_settings['api_key'] ) ) {
$style = current_user_can( 'manage_youtube_feed_options' ) ? ' style="display: block;"' : '';
ob_start(); ?>
<div id="sbi_mod_error" <?php echo $style; ?>>
<span><?php _e('This error message is only visible to WordPress admins', 'feeds-for-youtube' ); ?></span><br />
<p><b><?php _e( 'Error: No connected account.', 'feeds-for-youtube' ); ?></b>
<p><?php _e( 'Please go to the YouTube Feeds settings page to connect an account.', 'feeds-for-youtube' ); ?></p>
</div>
<?php
$html = ob_get_contents();
ob_get_clean();
return $html;
}
if ( sby_is_pro() ) {
$youtube_feed = new SBY_Feed_Pro( $transient_name );
} else {
$youtube_feed = new SBY_Feed( $transient_name );
}
if ( $settings['caching_type'] === 'background' ) {
$youtube_feed->add_report( 'background caching used' );
if ( $youtube_feed->regular_cache_exists() ) {
$youtube_feed->add_report( 'setting posts from cache' );
$youtube_feed->set_post_data_from_cache();
}
if ( $youtube_feed->need_to_start_cron_job() ) {
$youtube_feed->add_report( 'setting up feed for cron cache' );
$to_cache = array(
'atts' => $atts,
'last_requested' => time(),
);
$youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds() );
if( Util::isPro() ) {
SBY_Cron_Updater_Pro::do_single_feed_cron_update( $youtube_feed_settings, $to_cache, $atts, false );
} else {
SBY_Cron_Updater::do_single_feed_cron_update( $youtube_feed_settings, $to_cache, $atts, false );
}
$youtube_feed->set_post_data_from_cache();
} elseif ( $youtube_feed->should_update_last_requested() ) {
$youtube_feed->add_report( 'updating last requested' );
$to_cache = array(
'last_requested' => time(),
);
$youtube_feed->set_cron_cache( $to_cache, $youtube_feed_settings->get_cache_time_in_seconds() );
}
} elseif ( $youtube_feed->regular_cache_exists() ) {
$youtube_feed->add_report( 'page load caching used and regular cache exists' );
$youtube_feed->set_post_data_from_cache();
if ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
while ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
$youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
}
$youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds() );
}
} else {
$youtube_feed->add_report( 'no feed cache found' );
while ( $youtube_feed->need_posts( $settings['num'] ) && $youtube_feed->can_get_more_posts() ) {
$youtube_feed->add_remote_posts( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
}
if ( ! $youtube_feed->should_use_backup() ) {
$youtube_feed->cache_feed_data( $youtube_feed_settings->get_cache_time_in_seconds() );
}
}
if ( $youtube_feed->should_use_backup() ) {
$youtube_feed->add_report( 'trying to use backup' );
$youtube_feed->maybe_set_post_data_from_backup();
$youtube_feed->maybe_set_header_data_from_backup();
}
$settings['feed_avatars'] = array();
if ( $youtube_feed->need_avatars( $settings ) ) {
$youtube_feed->set_up_feed_avatars( $youtube_feed_settings->get_connected_accounts_in_feed(), $feed_type_and_terms );
$settings['feed_avatars'] = $youtube_feed->get_channel_id_avatars();
}
// if need a header
if ( $youtube_feed->need_header( $settings, $feed_type_and_terms ) && ! $youtube_feed->should_use_backup() ) {
if ( $database_settings['caching_type'] === 'background' ) {
$youtube_feed->add_report( 'background header caching used' );
$youtube_feed->set_header_data_from_cache();
} elseif ( $youtube_feed->regular_header_cache_exists() ) {
// set_post_data_from_cache
$youtube_feed->add_report( 'page load caching used and regular header cache exists' );
$youtube_feed->set_header_data_from_cache();
} else {
$youtube_feed->add_report( 'no header cache exists' );
$youtube_feed->set_remote_header_data( $settings, $feed_type_and_terms, $youtube_feed_settings->get_connected_accounts_in_feed() );
$youtube_feed->cache_header_data( $youtube_feed_settings->get_cache_time_in_seconds(), $settings['backup_cache_enabled'] );
}
} else {
if ( $settings['showheader'] ) {
$settings['generic_header'] = true;
$youtube_feed->add_report( 'using generic header' );
} else {
$youtube_feed->add_report( 'no header needed' );
}
}
// get the Settings page values
$sby_settings = get_option('sby_settings', array());
$custom_template = $sby_settings['customtemplates'];
// update custom templates value from Settings page value
if ( $custom_template ) {
$settings['customtemplates'] = $custom_template;
}
// Only return this for the feed customizer area when header data needed and set to true
if ( isset( $settings['customizer'] ) && $settings['customizer'] ) {
return array(
'header' => $this->parse_header_data( $youtube_feed->get_header_data() ),
'feedInitOutput' => $youtube_feed->get_the_feed_html( $settings, $atts, $youtube_feed_settings->get_feed_type_and_terms(), $youtube_feed_settings->get_connected_accounts_in_feed() ),
);
}
return $youtube_feed->get_the_feed_html( $settings, $atts, $youtube_feed_settings->get_feed_type_and_terms(), $youtube_feed_settings->get_connected_accounts_in_feed() );
}
public function parse_header_data( $data ) {
if ( !isset( $data['items'][0]['statistics'] ) ) {
return;
}
$statistics = $data['items'][0]['statistics'];
$header_data = array(
'statistics' => array(
'viewCount' => SBY_Display_Elements::escaped_formatted_count_string( $statistics['viewCount'], __( 'Views', 'feeds-for-youtube' ) ),
'subscriberCount' => SBY_Display_Elements::escaped_formatted_count_string( $statistics['subscriberCount'], __( 'subscribers', 'feeds-for-youtube' ) ),
'videoCount' => SBY_Display_Elements::escaped_formatted_count_string( $statistics['videoCount'], __( 'Videos', 'feeds-for-youtube' ) ),
)
);
return $header_data;
}
/**
* Hooks into do_shortcode_tag and runs only on youtube-feed shortcode
* Forces cachetime attribute if the cron job next run is out of order.
*
* @param $output
* @param $tag
* @param $attributes
* @param $m
*
* @return string
*/
public function check_cron_status( $output, $tag, $attributes, $m ) {
if ( $tag !== 'youtube-feed' ) {
return $output;
}
global $shortcode_tags;
$next_run = wp_next_scheduled('sby_feed_update');
$is_late = false !== $next_run && $next_run < ( time() - 1800 );
if ( false === $next_run || $next_run < 0 || $is_late ) {
if(!is_array($attributes)) {
$attributes = [];
}
if ( empty( $attributes['caching_type'] ) ) {
$attributes['caching_type'] = 'page';
$attributes['cachetime'] = $this->get_cache_time();
$attributes['cache_time'] = $this->get_cache_time();
}
$content = isset( $m[5] ) ? $m[5] : null;
// clear the cron so it can refresh again
wp_clear_scheduled_hook( 'sby_feed_update' );
return $m[1] . call_user_func( $shortcode_tags[ $tag ], $attributes, $content, $tag ) . $m[6];
}
return $output;
}
private function get_cache_time() {
$schedule = wp_get_schedule( 'sby_feed_update' );
if($schedule === 'twicedaily') {
return 12 * 60;
}
return 30;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Upgrade;
use Smashballoon\Stubs\Services\ServiceProvider;
use SmashBalloon\YouTubeFeed\Container;
use SmashBalloon\YouTubeFeed\Services\Upgrade\Routines\UpgradeRoutine;
use SmashBalloon\YouTubeFeed\Services\Upgrade\Routines\V2Routine;
use SmashBalloon\YouTubeFeed\Services\Upgrade\Routines\OnboardingWizardRoutine;
class RoutineManagerService extends ServiceProvider {
/**
* a list of upgrade routines to be executed,
* keep the correct order, newer is always at the end of the list.
* @var UpgradeRoutine[]
*/
private $routines = [
V2Routine::class,
OnboardingWizardRoutine::class
];
public function is_fresh_install() {
$db_version = get_option( 'sby_db_version', false );
return false === $db_version;
}
public function register() {
$container = Container::get_instance();
$is_fresh_install = $this->is_fresh_install();
foreach ($this->routines as $routine) {
$routine = $container->get($routine);
$routine->set_is_fresh_install($is_fresh_install);
$routine->register();
}
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Upgrade\Routines;
class OnboardingWizardRoutine extends UpgradeRoutine {
protected $target_version = 2.3;
public function run() {
$this->set_onboarding_wizard_flag();
}
private function set_onboarding_wizard_flag() {
if($this->is_fresh_install) {
return;
}
$sby_statuses_option = get_option( 'sby_statuses', array() );
if( !isset( $sby_statuses_option['wizard_dismissed'] ) || $sby_statuses_option['wizard_dismissed'] === false){
$sby_statuses_option['wizard_dismissed'] = true;
update_option( 'sby_statuses', $sby_statuses_option );
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Upgrade\Routines;
use Smashballoon\Stubs\Services\ServiceProvider;
class UpgradeRoutine extends ServiceProvider {
protected $target_version = 0;
protected $is_fresh_install = false;
public function register() {
if ( $this->will_run() ) {
$this->run();
$this->update_db_version();
}
}
protected function will_run() {
$current_schema = (float) get_option( 'sby_db_version', 0 );
return $current_schema < (float) $this->target_version;
}
protected function update_db_version() {
update_option('sby_db_version', $this->target_version);
}
public function run() {
//implement your own version
}
/**
* Set fresh install flag.
*
* @param $is_fresh_install
*
* @return void
*/
public function set_is_fresh_install($is_fresh_install) {
$this->is_fresh_install = $is_fresh_install;
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace SmashBalloon\YouTubeFeed\Services\Upgrade\Routines;
use Smashballoon\Customizer\DB;
use Smashballoon\Customizer\Feed_Saver;
use Smashballoon\Customizer\Feed_Locator;
class V2Routine extends UpgradeRoutine {
protected $target_version = 2.0;
/**
* @var Feed_Saver
*/
private $feed_saver;
/**
* @var Feed_Locator
*/
private $feed_locator;
/**
* @var DB
*/
private $db;
public function __construct(Feed_Saver $feed_saver, DB $DB, Feed_Locator $feed_locator) {
$this->feed_saver = $feed_saver;
$this->feed_locator = $feed_locator;
$this->db = $DB;
}
public function run() {
$this->create_tables();
$this->migrate_legacy_feeds();
$this->set_rating_notice_and_first_install_flags();
}
private function create_tables() {
$this->feed_locator->create_table();
$this->db->create_tables(true, true);
}
private function migrate_legacy_feeds() {
$statuses_option = get_option( 'sby_statuses', array() );
$args = array(
'html_location' => array( 'header', 'footer', 'sidebar', 'content', 'unknown' ),
'group_by' => 'shortcode_atts',
'page' => 1
);
$feeds_data = $this->feed_locator->legacy_feed_locator_query($args);
$legacy_count = count($feeds_data);
$statuses_option['support_legacy_shortcode'] = false;
if($legacy_count > 0) {
if($legacy_count > 1) {
$statuses_option['legacy_onboarding'] = array(
'active' => true,
'type'=> 'multiple'
);
$statuses_option['support_legacy_shortcode'] = true;
} else {
$statuses_option['legacy_onboarding'] = array(
'active' => true,
'type'=> 'single'
);
$shortcode_atts = ! empty($feeds_data[0] ) && $feeds_data[0]['shortcode_atts'] != '[""]' ? json_decode( $feeds_data[0]['shortcode_atts'], true ) : [];
$shortcode_atts = is_array( $shortcode_atts ) ? $shortcode_atts : array();
$statuses_option['support_legacy_shortcode'] = true;
$shortcode_atts['from_update'] = true;
$this->feed_saver->set_data( $shortcode_atts );
$this->feed_saver->set_feed_name( "Legacy feed" );
$new_feed_id = $this->feed_saver->update_or_insert();
$args = array(
'new_feed_id' => $new_feed_id,
'legacy_feed_id' => $feeds_data[0]['feed_id'],
);
$this->feed_locator->update_legacy_to_builder( $args );
}
}
update_option( 'sby_statuses', $statuses_option, true );
}
private function set_rating_notice_and_first_install_flags() {
$sby_statuses_option = get_option( 'sby_statuses', array() );
if ( ! isset( $sby_statuses_option['first_install'] ) ) {
$options_set = get_option( 'sby_settings', false );
if ( $options_set ) {
$sby_statuses_option['first_install'] = 'from_update';
} else {
$sby_statuses_option['first_install'] = time();
}
$sby_rating_notice_option = get_option( 'sby_rating_notice', false );
if ( $sby_rating_notice_option === 'dismissed' ) {
$sby_statuses_option['rating_notice_dismissed'] = time();
}
$sby_rating_notice_waiting = get_transient( 'feeds_for_youtube_rating_notice_waiting' );
if ( $sby_rating_notice_waiting === false
&& $sby_rating_notice_option === false ) {
$time = 2 * WEEK_IN_SECONDS;
set_transient( 'feeds_for_youtube_rating_notice_waiting', 'waiting', $time );
update_option( 'sby_rating_notice', 'pending', false );
}
update_option( 'sby_statuses', $sby_statuses_option, false );
}
}
}