Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/spotlight-social-photo-feeds/modules/Dev/DevSimError.php
+++ b/spotlight-social-photo-feeds/modules/Dev/DevSimError.php
@@ -2,14 +2,14 @@
namespace RebelCodeSpotlightInstagramModulesDev;
-use Exception;
use RebelCodeSpotlightInstagramErrorLog;
+use Exception;
class DevSimError
{
public function __invoke()
{
- $nonce = filter_input(INPUT_POST, 'sli_dev_sim_error');
+ $nonce = sanitize_text_field($_POST['sli_dev_sim_error'] ?? '');
if (!$nonce) {
return;
}
@@ -20,7 +20,7 @@
]);
}
- $message = filter_input(INPUT_POST, 'sli_dev_error_msg', FILTER_SANITIZE_STRING);
+ $message = sanitize_text_field($_POST['sli_dev_error_msg'] ?? '');
$message = empty(trim($message)) ? 'Simulated error' : $message;
ErrorLog::exception(new Exception($message));
--- a/spotlight-social-photo-feeds/plugin.php
+++ b/spotlight-social-photo-feeds/plugin.php
@@ -5,7 +5,7 @@
*
* Plugin Name: Spotlight - Social Media Feeds
* Description: Easily embed beautiful Instagram feeds on your WordPress site.
- * Version: 1.7.0
+ * Version: 1.7.1
* Author: RebelCode
* Plugin URI: https://spotlightwp.com
* Author URI: https://rebelcode.com
@@ -80,7 +80,7 @@
// The plugin name
define('SL_INSTA_NAME', 'Spotlight - Social Media Feeds');
// The plugin version
- define('SL_INSTA_VERSION', '1.7.0');
+ define('SL_INSTA_VERSION', '1.7.1');
// The path to the plugin's main file
define('SL_INSTA_FILE', __FILE__);
// The dir to the plugin's directory
--- a/spotlight-social-photo-feeds/src/core/RestApi/EndPoints/Accounts/ConnectAccountEndPoint.php
+++ b/spotlight-social-photo-feeds/src/core/RestApi/EndPoints/Accounts/ConnectAccountEndPoint.php
@@ -2,15 +2,15 @@
namespace RebelCodeSpotlightInstagramRestApiEndPointsAccounts;
-use Exception;
-use RebelCodeSpotlightInstagramIgApiAccessToken;
-use RebelCodeSpotlightInstagramIgApiIgAccount;
-use RebelCodeSpotlightInstagramIgApiIgApiClient;
-use RebelCodeSpotlightInstagramPostTypesAccountPostType;
-use RebelCodeSpotlightInstagramRestApiEndPointsAbstractEndpointHandler;
-use RebelCodeSpotlightInstagramWpPostType;
-use WP_REST_Request;
use WP_REST_Response;
+use WP_REST_Request;
+use RebelCodeSpotlightInstagramWpPostType;
+use RebelCodeSpotlightInstagramRestApiEndPointsAbstractEndpointHandler;
+use RebelCodeSpotlightInstagramPostTypesAccountPostType;
+use RebelCodeSpotlightInstagramIgApiIgApiClient;
+use RebelCodeSpotlightInstagramIgApiIgAccount;
+use RebelCodeSpotlightInstagramIgApiAccessToken;
+use Exception;
class ConnectAccountEndPoint extends AbstractEndpointHandler
{
@@ -52,14 +52,14 @@
protected function handle(WP_REST_Request $request)
{
// Get the access token code from the request
- $tokenCode = filter_var($request['accessToken'], FILTER_SANITIZE_STRING);
+ $tokenCode = isset($request['accessToken']) ? sanitize_text_field($request['accessToken']) : '';
if (empty($tokenCode)) {
return new WP_REST_Response(['error' => "The access token is required."], 400);
}
$isBusinessToken = stripos($tokenCode, 'EA') === 0 && strlen($tokenCode) > 145;
- $userId = filter_var($request['userId'], FILTER_SANITIZE_STRING);
+ $userId = isset($request['userId']) ? sanitize_text_field($request['userId']): '';
try {
// Construct the access token object
--- a/spotlight-social-photo-feeds/src/core/RestApi/EndPoints/Accounts/GetAccountsEndPoint.php
+++ b/spotlight-social-photo-feeds/src/core/RestApi/EndPoints/Accounts/GetAccountsEndPoint.php
@@ -2,16 +2,16 @@
namespace RebelCodeSpotlightInstagramRestApiEndPointsAccounts;
-use DhiiTransformerTransformerInterface;
-use RebelCodeSpotlightInstagramPostTypesAccountPostType;
-use RebelCodeSpotlightInstagramPostTypesCustomMedia;
-use RebelCodeSpotlightInstagramRestApiEndPointsAbstractEndpointHandler;
-use RebelCodeSpotlightInstagramUtilsArrays;
-use RebelCodeSpotlightInstagramWpPostType;
-use WP_Error;
-use WP_Post;
-use WP_REST_Request;
use WP_REST_Response;
+use WP_REST_Request;
+use WP_Post;
+use WP_Error;
+use RebelCodeSpotlightInstagramWpPostType;
+use RebelCodeSpotlightInstagramUtilsArrays;
+use RebelCodeSpotlightInstagramRestApiEndPointsAbstractEndpointHandler;
+use RebelCodeSpotlightInstagramPostTypesCustomMedia;
+use RebelCodeSpotlightInstagramPostTypesAccountPostType;
+use DhiiTransformerTransformerInterface;
/**
* The handler for the endpoint that provides account information.
@@ -55,8 +55,7 @@
*/
protected function handle(WP_REST_Request $request)
{
- $id = filter_var($request['id'], FILTER_SANITIZE_STRING);
-
+ $id = isset($request['id']) ? sanitize_text_field($request['id']) : '';
if (empty($id)) {
$data = Arrays::map($this->cpt->query(), function ($account) use ($request) {
return $this->transformAccount($account);
--- a/spotlight-social-photo-feeds/src/core/RestApi/EndPoints/Embed/CreatePostEndPoint.php
+++ b/spotlight-social-photo-feeds/src/core/RestApi/EndPoints/Embed/CreatePostEndPoint.php
@@ -2,10 +2,10 @@
namespace RebelCodeSpotlightInstagramRestApiEndPointsEmbed;
-use RebelCodeSpotlightInstagramRestApiEndPointsAbstractEndpointHandler;
-use WP_Error;
-use WP_REST_Request;
use WP_REST_Response;
+use WP_REST_Request;
+use WP_Error;
+use RebelCodeSpotlightInstagramRestApiEndPointsAbstractEndpointHandler;
class CreatePostEndPoint extends AbstractEndpointHandler
{
@@ -20,10 +20,10 @@
}
$useCase = $request->get_param('useCase');
- $useCase = filter_var($useCase, FILTER_SANITIZE_STRING);
+ $useCase = sanitize_text_field($useCase);
$postType = $request->get_param('postType');
- $postType = filter_var($postType, FILTER_SANITIZE_STRING);
+ $postType = sanitize_text_field($postType);
$args = [
'post_type' => $postType,
--- a/spotlight-social-photo-feeds/src/core/RestApi/EndPoints/Feeds/GetFeedsEndpoint.php
+++ b/spotlight-social-photo-feeds/src/core/RestApi/EndPoints/Feeds/GetFeedsEndpoint.php
@@ -2,12 +2,12 @@
namespace RebelCodeSpotlightInstagramRestApiEndPointsFeeds;
-use DhiiTransformerTransformerInterface;
-use RebelCodeSpotlightInstagramRestApiEndPointsAbstractEndpointHandler;
-use RebelCodeSpotlightInstagramWpPostType;
-use WP_Error;
-use WP_REST_Request;
use WP_REST_Response;
+use WP_REST_Request;
+use WP_Error;
+use RebelCodeSpotlightInstagramWpPostType;
+use RebelCodeSpotlightInstagramRestApiEndPointsAbstractEndpointHandler;
+use DhiiTransformerTransformerInterface;
/**
* The handler for the REST API endpoint that exposes feeds.
@@ -51,7 +51,7 @@
*/
protected function handle(WP_REST_Request $request)
{
- $id = filter_var($request['id'], FILTER_SANITIZE_STRING);
+ $id = isset($request['id']) ? sanitize_text_field($request['id']) : '';
if (empty($id)) {
return new WP_REST_Response(array_map([$this->transformer, 'transform'], $this->cpt->query([
--- a/spotlight-social-photo-feeds/src/core/Wp/NoticesManager.php
+++ b/spotlight-social-photo-feeds/src/core/Wp/NoticesManager.php
@@ -60,8 +60,8 @@
/** Handles a notice dismissal request */
public function handleAjax()
{
- $id = filter_input(INPUT_POST, 'notice', FILTER_SANITIZE_STRING);
- $nonce = filter_input(INPUT_POST, 'nonce', FILTER_SANITIZE_STRING);
+ $id = isset($_POST['notice']) ? sanitize_text_field($_POST['notice']) : '';
+ $nonce = isset($_POST['nonce']) ? sanitize_text_field($_POST['nonce']) : '';
if (!wp_verify_nonce($nonce, $this->nonce)) {
status_header(400);
--- a/spotlight-social-photo-feeds/vendor/autoload.php
+++ b/spotlight-social-photo-feeds/vendor/autoload.php
@@ -22,4 +22,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInitbd5b9cada860447312954188d6593fb2::getLoader();
+return ComposerAutoloaderInit5d9c133150599e0f6bac1c0fad6f7541::getLoader();
--- a/spotlight-social-photo-feeds/vendor/composer/autoload_real.php
+++ b/spotlight-social-photo-feeds/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInitbd5b9cada860447312954188d6593fb2
+class ComposerAutoloaderInit5d9c133150599e0f6bac1c0fad6f7541
{
private static $loader;
@@ -22,16 +22,16 @@
return self::$loader;
}
- spl_autoload_register(array('ComposerAutoloaderInitbd5b9cada860447312954188d6593fb2', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit5d9c133150599e0f6bac1c0fad6f7541', 'loadClassLoader'), true, true);
self::$loader = $loader = new ComposerAutoloadClassLoader(dirname(__DIR__));
- spl_autoload_unregister(array('ComposerAutoloaderInitbd5b9cada860447312954188d6593fb2', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit5d9c133150599e0f6bac1c0fad6f7541', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- call_user_func(ComposerAutoloadComposerStaticInitbd5b9cada860447312954188d6593fb2::getInitializer($loader));
+ call_user_func(ComposerAutoloadComposerStaticInit5d9c133150599e0f6bac1c0fad6f7541::getInitializer($loader));
$loader->register(true);
- $filesToLoad = ComposerAutoloadComposerStaticInitbd5b9cada860447312954188d6593fb2::$files;
+ $filesToLoad = ComposerAutoloadComposerStaticInit5d9c133150599e0f6bac1c0fad6f7541::$files;
$requireFile = Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
--- a/spotlight-social-photo-feeds/vendor/composer/autoload_static.php
+++ b/spotlight-social-photo-feeds/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
namespace ComposerAutoload;
-class ComposerStaticInitbd5b9cada860447312954188d6593fb2
+class ComposerStaticInit5d9c133150599e0f6bac1c0fad6f7541
{
public static $files = array (
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
@@ -141,9 +141,9 @@
public static function getInitializer(ClassLoader $loader)
{
return Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInitbd5b9cada860447312954188d6593fb2::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInitbd5b9cada860447312954188d6593fb2::$prefixDirsPsr4;
- $loader->classMap = ComposerStaticInitbd5b9cada860447312954188d6593fb2::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInit5d9c133150599e0f6bac1c0fad6f7541::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit5d9c133150599e0f6bac1c0fad6f7541::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInit5d9c133150599e0f6bac1c0fad6f7541::$classMap;
}, null, ClassLoader::class);
}
--- a/spotlight-social-photo-feeds/vendor/composer/installed.php
+++ b/spotlight-social-photo-feeds/vendor/composer/installed.php
@@ -65,9 +65,9 @@
'dev_requirement' => false,
),
'freemius/wordpress-sdk' => array(
- 'pretty_version' => '2.8.1',
- 'version' => '2.8.1.0',
- 'reference' => 'cc31279d088909135b6b2d8b4f2696312f5731fc',
+ 'pretty_version' => '2.11.0',
+ 'version' => '2.11.0.0',
+ 'reference' => null,
'type' => 'library',
'install_path' => __DIR__ . '/../freemius/wordpress-sdk',
'aliases' => array(),
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/class-freemius.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/class-freemius.php
@@ -110,6 +110,12 @@
private $_enable_anonymous = true;
/**
+ * @since 2.9.1
+ * @var string|null Hints the SDK whether the plugin supports parallel activation mode, preventing the auto-deactivation of the free version when the premium version is activated, and vice versa.
+ */
+ private $_premium_plugin_basename_from_parallel_activation;
+
+ /**
* @since 1.1.7.5
* @var bool Hints the SDK if plugin should run in anonymous mode (only adds feedback form).
*/
@@ -381,13 +387,6 @@
/**
* @author Leo Fajardo (@leorw)
- * @since 2.3.1
- *
- * @var boolean|null
- */
- private $_use_external_pricing = null;
- /**
- * @author Leo Fajardo (@leorw)
* @since 2.4.2
*
* @var string|null
@@ -1380,17 +1379,31 @@
}
/**
- * Opens the support forum subemenu item in a new browser page.
+ * Modifies all external links in the submenu by altering their href, and also opens them in new tab if needed.
*
* @author Vova Feldman (@svovaf)
+ * @author Swashata Ghosh (@swashata)
* @since 2.1.4
*/
- static function _open_support_forum_in_new_page() {
+ static function _handle_submenu_external_link() {
?>
<script type="text/javascript">
- (function ($) {
- $('.fs-submenu-item.wp-support-forum').parent().attr( { target: '_blank', rel: 'noopener noreferrer' } );
- })(jQuery);
+ (function ( $ ) {
+ $( '.fs-submenu-item' ).each( function () {
+ var $this = $( this ),
+ $parent = $this.parent(),
+ externalLink = $this.data( 'fs-external-url' ),
+ isOpensInNewTab = $this.data( 'fs-new-tab' );
+
+ if ( externalLink ) {
+ $parent.attr( 'href', externalLink );
+ }
+
+ if ( isOpensInNewTab ) {
+ $parent.attr( { target: '_blank', rel: 'noopener noreferrer' } );
+ }
+ } );
+ } )( jQuery );
</script>
<?php
}
@@ -1487,7 +1500,7 @@
}
add_action( 'init', array( &$this, '_maybe_add_gdpr_optin_ajax_handler') );
- add_action( 'init', array( &$this, '_maybe_add_pricing_ajax_handler' ) );
+ add_action( 'init', array( &$this, '_add_pricing_ajax_handler' ) );
}
if ( $this->is_plugin() ) {
@@ -1644,6 +1657,31 @@
);
}
}
+
+ if (
+ $this->is_user_in_admin() &&
+ $this->is_parallel_activation() &&
+ $this->_premium_plugin_basename !== $this->_premium_plugin_basename_from_parallel_activation
+ ) {
+ $this->_premium_plugin_basename = $this->_premium_plugin_basename_from_parallel_activation;
+
+ register_activation_hook(
+ dirname( $this->_plugin_dir_path ) . '/' . $this->_premium_plugin_basename,
+ array( &$this, '_activate_plugin_event_hook' )
+ );
+ }
+ }
+
+ /**
+ * Determines if a plugin is running in parallel activation mode.
+ *
+ * @author Leo Fajardo (@leorw)
+ * @since 2.9.1
+ *
+ * @return bool
+ */
+ private function is_parallel_activation() {
+ return ! empty( $this->_premium_plugin_basename_from_parallel_activation );
}
/**
@@ -3429,7 +3467,7 @@
$clone_manager = FS_Clone_Manager::instance();
add_action( 'init', array( $clone_manager, '_init' ) );
- add_action( 'admin_footer', array( 'Freemius', '_open_support_forum_in_new_page' ) );
+ add_action( 'admin_footer', array( 'Freemius', '_handle_submenu_external_link' ) );
if ( self::is_plugins_page() || self::is_themes_page() ) {
add_action( 'admin_print_footer_scripts', array( 'Freemius', '_maybe_add_beta_label_styles' ), 9 );
@@ -5148,11 +5186,35 @@
$this->_plugin :
new FS_Plugin();
+ $is_premium = $this->get_bool_option( $plugin_info, 'is_premium', true );
$premium_suffix = $this->get_option( $plugin_info, 'premium_suffix', '(Premium)' );
+ $module_type = $this->get_option( $plugin_info, 'type', $this->_module_type );
+
+ $parallel_activation = $this->get_option( $plugin_info, 'parallel_activation' );
+
+ if (
+ ! $is_premium &&
+ is_array( $parallel_activation ) &&
+ ( WP_FS__MODULE_TYPE_PLUGIN === $module_type ) &&
+ $this->get_bool_option( $parallel_activation, 'enabled' )
+ ) {
+ $premium_basename = $this->get_option( $parallel_activation, 'premium_version_basename' );
+
+ if ( empty( $premium_basename ) ) {
+ throw new Exception('You need to specify the premium version basename to enable parallel version activation.');
+ }
+
+ $this->_premium_plugin_basename_from_parallel_activation = $premium_basename;
+
+ if ( is_plugin_active( $premium_basename ) ) {
+ $is_premium = true;
+ }
+ }
+
$plugin->update( array(
'id' => $id,
- 'type' => $this->get_option( $plugin_info, 'type', $this->_module_type ),
+ 'type' => $module_type,
'public_key' => $public_key,
'slug' => $this->_slug,
'premium_slug' => $this->get_option( $plugin_info, 'premium_slug', "{$this->_slug}-premium" ),
@@ -5160,7 +5222,7 @@
'version' => $this->get_plugin_version(),
'title' => $this->get_plugin_name( $premium_suffix ),
'file' => $this->_plugin_basename,
- 'is_premium' => $this->get_bool_option( $plugin_info, 'is_premium', true ),
+ 'is_premium' => $is_premium,
'premium_suffix' => $premium_suffix,
'is_live' => $this->get_bool_option( $plugin_info, 'is_live', true ),
'affiliate_moderation' => $this->get_option( $plugin_info, 'has_affiliation' ),
@@ -5229,7 +5291,14 @@
$this->_anonymous_mode = false;
} else {
$this->_enable_anonymous = $this->get_bool_option( $plugin_info, 'enable_anonymous', true );
- $this->_anonymous_mode = $this->get_bool_option( $plugin_info, 'anonymous_mode', false );
+ $this->_anonymous_mode = (
+ $this->get_bool_option( $plugin_info, 'anonymous_mode', false ) ||
+ (
+ $this->apply_filters( 'playground_anonymous_mode', true ) &&
+ ! empty( $_SERVER['HTTP_HOST'] ) &&
+ FS_Site::is_playground_wp_environment_by_host( $_SERVER['HTTP_HOST'] )
+ )
+ );
}
$this->_permissions = $this->get_option( $plugin_info, 'permissions', array() );
$this->_is_bundle_license_auto_activation_enabled = $this->get_option( $plugin_info, 'bundle_license_auto_activation', false );
@@ -5437,7 +5506,7 @@
if ( $this->is_registered() ) {
// Schedule code type changes event.
- $this->schedule_install_sync();
+ $this->maybe_schedule_install_sync_cron();
}
/**
@@ -6501,6 +6570,33 @@
}
/**
+ * Instead of running blocking install sync event, execute non blocking scheduled cron job.
+ *
+ * @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding specified blog ID from being the cron job executor.
+ *
+ * @author Leo Fajardo (@leorw)
+ * @since 2.9.1
+ */
+ private function maybe_schedule_install_sync_cron( $except_blog_id = 0 ) {
+ if ( ! $this->is_user_in_admin() ) {
+ return;
+ }
+
+ if ( $this->is_clone() ) {
+ return;
+ }
+
+ if (
+ // The event has been properly scheduled, so no need to reschedule it.
+ is_numeric( $this->next_install_sync() )
+ ) {
+ return;
+ }
+
+ $this->schedule_cron( 'install_sync', 'install_sync', 'single', WP_FS__SCRIPT_START_TIME, false, $except_blog_id );
+ }
+
+ /**
* @author Vova Feldman (@svovaf)
* @since 1.1.7.3
*
@@ -6598,22 +6694,6 @@
}
/**
- * Instead of running blocking install sync event, execute non blocking scheduled wp-cron.
- *
- * @author Vova Feldman (@svovaf)
- * @since 1.1.7.3
- *
- * @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor.
- */
- private function schedule_install_sync( $except_blog_id = 0 ) {
- if ( $this->is_clone() ) {
- return;
- }
-
- $this->schedule_cron( 'install_sync', 'install_sync', 'single', WP_FS__SCRIPT_START_TIME, false, $except_blog_id );
- }
-
- /**
* Unix timestamp for previous install sync cron execution or false if never executed.
*
* @todo There's some very strange bug that $this->_storage->install_sync_timestamp value is not being updated. But for sure the sync event is working.
@@ -7404,7 +7484,7 @@
*/
if (
is_plugin_active( $other_version_basename ) &&
- $this->apply_filters( 'deactivate_on_activation', true )
+ $this->apply_filters( 'deactivate_on_activation', ! $this->is_parallel_activation() )
) {
deactivate_plugins( $other_version_basename );
}
@@ -7418,7 +7498,7 @@
// Schedule re-activation event and sync.
// $this->sync_install( array(), true );
- $this->schedule_install_sync();
+ $this->maybe_schedule_install_sync_cron();
// If activating the premium module version, add an admin notice to congratulate for an upgrade completion.
if ( $is_premium_version_activation ) {
@@ -8609,7 +8689,7 @@
return;
}
- $this->schedule_install_sync();
+ $this->maybe_schedule_install_sync_cron();
// $this->sync_install( array(), true );
}
@@ -13596,8 +13676,11 @@
*/
function get_pricing_js_path() {
if ( ! isset( $this->_pricing_js_path ) ) {
- $pricing_js_path = $this->apply_filters( 'freemius_pricing_js_path', '' );
+ $default_path = WP_FS__DIR_JS . '/pricing/freemius-pricing.js';
+ $pricing_js_path = $this->apply_filters( 'freemius_pricing_js_path', $default_path );
+
+ // Backward compatibility for people who placed the freemius-pricing inside `includes` directory. Let it take more preference than the default path.
if ( empty( $pricing_js_path ) ) {
global $fs_active_plugins;
@@ -13616,6 +13699,11 @@
}
}
+ // If it is still empty, load the default pricing JS.
+ if ( ! file_exists( $pricing_js_path ) ) {
+ $pricing_js_path = $default_path;
+ }
+
$this->_pricing_js_path = $pricing_js_path;
}
@@ -13626,16 +13714,12 @@
* @author Leo Fajardo (@leorw)
* @since 2.3.1
*
+ * @deprecated Since v2.9.0 we have removed the iFrame based pricing. This will always return `false`.
+ *
* @return bool
*/
function should_use_external_pricing() {
- if ( is_null( $this->_use_external_pricing ) ) {
- $pricing_js_path = $this->get_pricing_js_path();
-
- $this->_use_external_pricing = ( empty( $pricing_js_path ) || ! file_exists( $pricing_js_path ) );
- }
-
- return $this->_use_external_pricing;
+ return false;
}
/**
@@ -15963,7 +16047,7 @@
if ( $this->is_install_sync_scheduled() &&
$context_blog_id == $this->get_install_sync_cron_blog_id()
) {
- $this->schedule_install_sync( $context_blog_id );
+ $this->maybe_schedule_install_sync_cron( $context_blog_id );
}
}
@@ -17999,9 +18083,16 @@
*
* @author Leo Fajardo (@leorw)
*/
+ $user = $this->_user;
+
$this->_user = null;
fs_redirect( $this->get_activation_url( array( 'error' => $result->error->message ) ) );
+
+ /**
+ * Restore the user after the redirect, this is relevant when there are cases where the redirect will choose not to do anything.
+ */
+ $this->_user = $user;
}
}
@@ -18766,16 +18857,29 @@
if ( $add_submenu_items ) {
if (! WP_FS__DEMO_MODE && ! $this->is_whitelabeled() ) {
// Add contact page.
- $this->add_submenu_item(
- $this->get_text_inline( 'Contact Us', 'contact-us' ),
- array( &$this, '_contact_page_render' ),
- $this->get_plugin_name() . ' – ' . $this->get_text_inline( 'Contact Us', 'contact-us' ),
- 'manage_options',
- 'contact',
- 'Freemius::_clean_admin_content_section',
- WP_FS__DEFAULT_PRIORITY,
- $this->is_submenu_item_visible( 'contact' )
- );
+ if ( $this->is_premium() ) {
+ $this->add_submenu_item(
+ $this->get_text_inline( 'Contact Us', 'contact-us' ),
+ array( &$this, '_contact_page_render' ),
+ $this->get_plugin_name() . ' – ' . $this->get_text_inline( 'Contact Us', 'contact-us' ),
+ 'manage_options',
+ 'contact',
+ 'Freemius::_clean_admin_content_section',
+ WP_FS__DEFAULT_PRIORITY,
+ $this->is_submenu_item_visible( 'contact' )
+ );
+ } else {
+ $this->add_submenu_link_item(
+ $this->get_text_inline( 'Contact Us', 'contact-us' ),
+ FS_Contact_Form_Manager::instance()->get_standalone_link( $this ),
+ 'contact',
+ 'manage_options',
+ WP_FS__DEFAULT_PRIORITY,
+ $this->is_submenu_item_visible( 'contact' ),
+ 'fs_external_contact',
+ true
+ );
+ }
}
if ( $this->has_addons() ) {
@@ -18877,9 +18981,9 @@
* @since 1.1.4
*/
private function embed_submenu_items() {
- $item_template = $this->_menu->is_top_level() ?
- '<span class="fs-submenu-item %s %s %s">%s</span>' :
- '<span class="fs-submenu-item fs-sub %s %s %s">%s</span>';
+ $item_classes = $this->_menu->is_top_level() ? 'fs-submenu-item' : 'fs-submenu-item fs-sub';
+
+ $item_template = '<span class="' . $item_classes . ' %1$s %2$s %3$s" data-fs-external-url="%5$s" data-fs-new-tab="%6$s">%4$s</span>';
$top_level_menu_capability = $this->get_top_level_menu_capability();
@@ -18896,7 +19000,9 @@
$this->get_unique_affix(),
$item['menu_slug'],
! empty( $item['class'] ) ? $item['class'] : '',
- $item['menu_title']
+ $item['menu_title'],
+ esc_attr( isset( $item['url'] ) ? $item['url'] : '' ),
+ esc_attr( isset( $item['new_tab'] ) ? 'true' : 'false' )
);
$top_level_menu_slug = $this->get_top_level_menu_slug();
@@ -19052,7 +19158,9 @@
'wp-support-forum',
null,
50,
- $this->is_submenu_item_visible( 'support' )
+ $this->is_submenu_item_visible( 'support' ),
+ '',
+ true
);
}
}
@@ -19131,6 +19239,7 @@
* @param int $priority
* @param bool $show_submenu
* @param string $class
+ * @param bool $new_tab
*/
function add_submenu_link_item(
$menu_title,
@@ -19139,7 +19248,8 @@
$capability = 'read',
$priority = WP_FS__DEFAULT_PRIORITY,
$show_submenu = true,
- $class = ''
+ $class = '',
+ $new_tab = false
) {
$this->_logger->entrance( 'Title = ' . $menu_title . '; Url = ' . $url );
@@ -19154,7 +19264,8 @@
$capability,
$priority,
$show_submenu,
- $class
+ $class,
+ $new_tab
);
return;
@@ -19175,6 +19286,7 @@
'before_render_function' => '',
'show_submenu' => $show_submenu,
'class' => $class,
+ 'new_tab' => $new_tab,
);
}
@@ -21686,10 +21798,11 @@
* @since 1.1.8.1
*
* @param bool|string $plan_name
+ * @param bool $add_sticky_notice
*
* @return bool If trial was successfully started.
*/
- function start_trial( $plan_name = false ) {
+ function start_trial( $plan_name = false, $add_sticky_notice = false ) {
$this->_logger->entrance();
// Alias.
@@ -21700,18 +21813,20 @@
$this->_admin_notices->add(
sprintf( $this->get_text_inline( 'You are already running the %s in a trial mode.', 'in-trial-mode' ), $this->_module_type ),
$oops_text,
- 'error'
+ 'error',
+ $add_sticky_notice
);
return false;
}
- if ( $this->_site->is_trial_utilized() ) {
+ if ( $this->_site->is_trial_utilized() && ! $this->is_payments_sandbox() ) {
// Trial was already utilized.
$this->_admin_notices->add(
$this->get_text_inline( 'You already utilized a trial before.', 'trial-utilized' ),
$oops_text,
- 'error'
+ 'error',
+ $add_sticky_notice
);
return false;
@@ -21725,7 +21840,8 @@
$this->_admin_notices->add(
sprintf( $this->get_text_inline( 'Plan %s do not exist, therefore, can't start a trial.', 'trial-plan-x-not-exist' ), $plan_name ),
$oops_text,
- 'error'
+ 'error',
+ $add_sticky_notice
);
return false;
@@ -21736,7 +21852,8 @@
$this->_admin_notices->add(
sprintf( $this->get_text_inline( 'Plan %s does not support a trial period.', 'plan-x-no-trial' ), $plan_name ),
$oops_text,
- 'error'
+ 'error',
+ $add_sticky_notice
);
return false;
@@ -21747,7 +21864,8 @@
$this->_admin_notices->add(
sprintf( $this->get_text_inline( 'None of the %s's plans supports a trial period.', 'no-trials' ), $this->_module_type ),
$oops_text,
- 'error'
+ 'error',
+ $add_sticky_notice
);
return false;
@@ -21758,15 +21876,27 @@
$plan = $plans_with_trial[0];
}
- $api = $this->get_api_site_scope();
- $plan = $api->call( "plans/{$plan->id}/trials.json", 'post' );
+ $trial_params = array();
+
+ if ( $this->is_payments_sandbox() ) {
+ $trial_params['trial_timestamp'] = time();
+ $trial_params['trial_token'] = FS_Security::instance()->get_trial_token(
+ $this->get_plugin(),
+ $plan,
+ $trial_params['trial_timestamp']
+ );
+ }
- if ( ! $this->is_api_result_entity( $plan ) ) {
+ $api = $this->get_api_site_scope();
+ $trial = $api->call( "plans/{$plan->id}/trials.json", 'post', $trial_params );
+
+ if ( ! $this->is_api_result_entity( $trial ) ) {
// Some API error while trying to start the trial.
$this->_admin_notices->add(
- $this->get_api_error_message( $plan ),
+ $this->get_api_error_message( $trial ),
$oops_text,
- 'error'
+ 'error',
+ $add_sticky_notice
);
return false;
@@ -22006,6 +22136,9 @@
if ( true === $fetch_readme ) {
$latest_version_endpoint = add_query_arg( 'readme', 'true', $latest_version_endpoint );
+
+ // Don't cache the API response when fetching readme information.
+ $expiration = null;
}
$tag = $this->get_api_site_or_plugin_scope()->get(
@@ -23247,6 +23380,9 @@
function _pricing_page_render() {
$this->_logger->entrance();
+ fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
+ fs_enqueue_local_style( 'fs_checkout', '/admin/checkout.css' );
+
$vars = array( 'id' => $this->_module_id );
if ( 'true' === fs_request_get( 'checkout', false ) ) {
@@ -23260,10 +23396,8 @@
* @author Leo Fajardo (@leorw)
* @since 2.3.1
*/
- function _maybe_add_pricing_ajax_handler() {
- if ( ! $this->should_use_external_pricing() ) {
- $this->add_ajax_action( 'pricing_ajax_action', array( &$this, '_fs_pricing_ajax_action_handler' ) );
- }
+ function _add_pricing_ajax_handler() {
+ $this->add_ajax_action( 'pricing_ajax_action', array( &$this, '_fs_pricing_ajax_action_handler' ) );
}
/**
@@ -23313,14 +23447,28 @@
$result = $api->get( 'pricing.json?' . http_build_query( $params ) );
break;
case 'start_trial':
- $result = $this->opt_in(
- false,
- false,
- false,
- false,
- false,
- fs_request_get( 'plan_id' )
- );
+ $trial_plan_id = fs_request_get( 'plan_id' );
+
+ if ( $this->is_registered() && $this->is_tracking_allowed() ) {
+ $plan = $this->_get_plan_by_id( $trial_plan_id );
+
+ if ( ! $plan ) {
+ $this->shoot_ajax_failure( 'Invalid plan ID.' );
+ return;
+ }
+
+ $result = $this->start_trial( $plan->name, true );
+ } else {
+ // @todo - This fails for sandbox trial at the moment if the trial was already utilized.
+ $result = $this->opt_in(
+ false,
+ false,
+ false,
+ false,
+ false,
+ $trial_plan_id
+ );
+ }
}
if ( is_object( $result ) && $this->is_api_error( $result ) ) {
@@ -23852,13 +24000,15 @@
// Start trial button.
$button = ' ' . sprintf(
- '<a style="margin-left: 10px; vertical-align: super;" href="%s"><button class="button button-primary">%s ➜</button></a>',
+ '<div><a class="button button-primary" href="%s">%s ➜</a></div>',
$trial_url,
$this->get_text_x_inline( 'Start free trial', 'call to action', 'start-free-trial' )
);
+ $message_text = $this->apply_filters( 'trial_promotion_message', "{$message} {$cc_string}" );
+
$this->_admin_notices->add_sticky(
- $this->apply_filters( 'trial_promotion_message', "{$message} {$cc_string} {$button}" ),
+ "<div class="fs-trial-message-container"><div>{$message_text}</div> {$button}</div>",
'trial_promotion',
'',
'promotion'
@@ -25328,7 +25478,7 @@
$img_dir = WP_FS__DIR_IMG;
// Locate the main assets folder.
- if ( 1 < count( $fs_active_plugins->plugins ) ) {
+ if ( ! empty( $fs_active_plugins->plugins ) ) {
$plugin_or_theme_img_dir = ( $this->is_plugin() ? WP_PLUGIN_DIR : get_theme_root( get_stylesheet() ) );
foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) {
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/class-fs-api.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/class-fs-api.php
@@ -355,7 +355,9 @@
}
}
- self::$_cache->set( $cache_key, $result, $expiration );
+ if ( is_numeric( $expiration ) ) {
+ self::$_cache->set( $cache_key, $result, $expiration );
+ }
$cached_result = $result;
} else {
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/class-fs-plugin-updater.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/class-fs-plugin-updater.php
@@ -542,24 +542,8 @@
global $wp_current_filter;
- $current_plugin_version = $this->_fs->get_plugin_version();
-
- if ( ! empty( $wp_current_filter ) && 'upgrader_process_complete' === $wp_current_filter[0] ) {
- if (
- is_null( $this->_update_details ) ||
- ( is_object( $this->_update_details ) && $this->_update_details->new_version !== $current_plugin_version )
- ) {
- /**
- * After an update, clear the stored update details and reparse the plugin's main file in order to get
- * the updated version's information and prevent the previous update information from showing up on the
- * updates page.
- *
- * @author Leo Fajardo (@leorw)
- * @since 2.3.1
- */
- $this->_update_details = null;
- $current_plugin_version = $this->_fs->get_plugin_version( true );
- }
+ if ( ! empty( $wp_current_filter ) && in_array( 'upgrader_process_complete', $wp_current_filter ) ) {
+ return $transient_data;
}
if ( ! isset( $this->_update_details ) ) {
@@ -568,7 +552,7 @@
false,
fs_request_get_bool( 'force-check' ),
FS_Plugin_Updater::UPDATES_CHECK_CACHE_EXPIRATION,
- $current_plugin_version
+ $this->_fs->get_plugin_version()
);
$this->_update_details = false;
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/class-fs-security.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/class-fs-security.php
@@ -82,4 +82,22 @@
's_ctx_secure' => $this->get_secure_token( $entity, $timestamp, $action ),
);
}
+
+ /**
+ * Gets a sandbox trial token for a given plugin, plan, and trial timestamp.
+ *
+ * @param FS_Plugin $plugin
+ * @param FS_Plugin_Plan $plan
+ * @param int $trial_timestamp
+ *
+ * @return string
+ */
+ function get_trial_token( FS_Plugin $plugin, FS_Plugin_Plan $plan, $trial_timestamp ) {
+ return md5(
+ $plugin->secret_key . $plugin->public_key .
+ $plan->trial_period .
+ $plan->id .
+ $trial_timestamp
+ );
+ }
}
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/entities/class-fs-plugin-plan.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/entities/class-fs-plugin-plan.php
@@ -13,7 +13,6 @@
/**
* Class FS_Plugin_Plan
*
- * @property FS_Pricing[] $pricing
*/
class FS_Plugin_Plan extends FS_Entity {
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/entities/class-fs-site.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/entities/class-fs-site.php
@@ -10,16 +10,16 @@
exit;
}
- /**
- * @property int $blog_id
- */
- #[AllowDynamicProperties]
class FS_Site extends FS_Scope_Entity {
/**
* @var number
*/
public $site_id;
/**
+ * @var int
+ */
+ public $blog_id;
+ /**
* @var number
*/
public $plugin_id;
@@ -190,7 +190,7 @@
fs_ends_with( $subdomain, '.cloudwaysapps.com' ) ||
// Kinsta
(
- ( fs_starts_with( $subdomain, 'staging-' ) || fs_starts_with( $subdomain, 'env-' ) ) &&
+ ( fs_starts_with( $subdomain, 'stg-' ) || fs_starts_with( $subdomain, 'staging-' ) || fs_starts_with( $subdomain, 'env-' ) ) &&
( fs_ends_with( $subdomain, '.kinsta.com' ) || fs_ends_with( $subdomain, '.kinsta.cloud' ) )
) ||
// DesktopServer
@@ -208,6 +208,40 @@
);
}
+ /**
+ * @author Leo Fajardo (@leorw)
+ * @since 2.9.1
+ *
+ * @param string $host
+ *
+ * @return bool
+ */
+ static function is_playground_wp_environment_by_host( $host ) {
+ // Services aimed at providing a WordPress sandbox environment.
+ $sandbox_wp_environment_domains = array(
+ // InstaWP
+ 'instawp.xyz',
+
+ // TasteWP
+ 'tastewp.com',
+
+ // WordPress Playground
+ 'playground.wordpress.net',
+ );
+
+ foreach ( $sandbox_wp_environment_domains as $domain) {
+ if (
+ ( $host === $domain ) ||
+ fs_ends_with( $host, '.' . $domain ) ||
+ fs_ends_with( $host, '-' . $domain )
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
function is_localhost() {
return ( WP_FS__IS_LOCALHOST_FOR_SERVER || self::is_localhost_by_address( $this->url ) );
}
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/entities/class-fs-user.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/entities/class-fs-user.php
@@ -48,6 +48,19 @@
parent::__construct( $user );
}
+ /**
+ * This method removes the deprecated 'is_beta' property from the serialized data.
+ * Should clean up the serialized data to avoid PHP 8.2 warning on next execution.
+ *
+ * @return void
+ */
+ function __wakeup() {
+ if ( property_exists( $this, 'is_beta' ) ) {
+ // If we enter here, and we are running PHP 8.2, we already had the warning. But we sanitize data for next execution.
+ unset( $this->is_beta );
+ }
+ }
+
function get_name() {
return trim( ucfirst( trim( is_string( $this->first ) ? $this->first : '' ) ) . ' ' . ucfirst( trim( is_string( $this->last ) ? $this->last : '' ) ) );
}
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/managers/class-fs-admin-menu-manager.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/managers/class-fs-admin-menu-manager.php
@@ -699,16 +699,36 @@
$menu = $this->find_main_submenu();
}
+ $menu_slug = $menu['menu'][2];
$parent_slug = isset( $menu['parent_slug'] ) ?
- $menu['parent_slug'] :
- 'admin.php';
+ $menu['parent_slug'] :
+ 'admin.php';
- return admin_url(
- $parent_slug .
- ( false === strpos( $parent_slug, '?' ) ? '?' : '&' ) .
- 'page=' .
- $menu['menu'][2]
- );
+ if ( fs_apply_filter( $this->_module_unique_affix, 'enable_cpt_advanced_menu_logic', false ) ) {
+ $parent_slug = 'admin.php';
+
+ /**
+ * This line and the `if` block below it are based on the `menu_page_url()` function of WordPress.
+ *
+ * @author Leo Fajardo (@leorw)
+ * @since 2.10.2
+ */
+ global $_parent_pages;
+
+ if ( ! empty( $_parent_pages[ $menu_slug ] ) ) {
+ $_parent_slug = $_parent_pages[ $menu_slug ];
+ $parent_slug = isset( $_parent_pages[ $_parent_slug ] ) ?
+ $parent_slug :
+ $menu['parent_slug'];
+ }
+ }
+
+ return admin_url(
+ $parent_slug .
+ ( false === strpos( $parent_slug, '?' ) ? '?' : '&' ) .
+ 'page=' .
+ $menu_slug
+ );
}
/**
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/managers/class-fs-admin-notice-manager.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/managers/class-fs-admin-notice-manager.php
@@ -194,8 +194,14 @@
* @since 1.0.7
*/
static function _add_sticky_dismiss_javascript() {
+ $sticky_admin_notice_js_template_name = 'sticky-admin-notice-js.php';
+
+ if ( ! file_exists( fs_get_template_path( $sticky_admin_notice_js_template_name ) ) ) {
+ return;
+ }
+
$params = array();
- fs_require_once_template( 'sticky-admin-notice-js.php', $params );
+ fs_require_once_template( $sticky_admin_notice_js_template_name, $params );
}
private static $_added_sticky_javascript = false;
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/managers/class-fs-checkout-manager.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/managers/class-fs-checkout-manager.php
@@ -0,0 +1,242 @@
+<?php
+ /**
+ * @package Freemius
+ * @copyright Copyright (c) 2024, Freemius, Inc.
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
+ * @since 2.9.0
+ */
+
+ if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+ }
+
+ class FS_Checkout_Manager {
+
+ # region Singleton
+
+ /**
+ * @var FS_Checkout_Manager
+ */
+ private static $_instance;
+
+ /**
+ * @return FS_Checkout_Manager
+ */
+ static function instance() {
+ if ( ! isset( self::$_instance ) ) {
+ self::$_instance = new FS_Checkout_Manager();
+ }
+
+ return self::$_instance;
+ }
+
+ private function __construct() {
+ }
+
+ #endregion
+
+ /**
+ * Retrieves the query params needed to load the Freemius Checkout in the context of the plugin.
+ *
+ * @param Freemius $fs
+ * @param number $plugin_id
+ * @param number $plan_id
+ * @param number $licenses
+ *
+ * @return array
+ */
+ public function get_query_params( Freemius $fs, $plugin_id, $plan_id, $licenses ) {
+ $timestamp = time();
+
+ $context_params = array(
+ 'plugin_id' => $fs->get_id(),
+ 'public_key' => $fs->get_public_key(),
+ 'plugin_version' => $fs->get_plugin_version(),
+ 'mode' => 'dashboard',
+ 'trial' => fs_request_get_bool( 'trial' ),
+ 'is_ms' => ( fs_is_network_admin() && $fs->is_network_active() ),
+ );
+
+ if ( FS_Plugin_Plan::is_valid_id( $plan_id ) ) {
+ $context_params['plan_id'] = $plan_id;
+ }
+
+ if ( $licenses === strval( intval( $licenses ) ) && $licenses > 0 ) {
+ $context_params['licenses'] = $licenses;
+ }
+
+ if ( $plugin_id == $fs->get_id() ) {
+ $is_premium = $fs->is_premium();
+
+ $bundle_id = $fs->get_bundle_id();
+ if ( ! is_null( $bundle_id ) ) {
+ $context_params['bundle_id'] = $bundle_id;
+ }
+ } else {
+ // Identify the module code version of the checkout context module.
+ if ( $fs->is_addon_activated( $plugin_id ) ) {
+ $fs_addon = Freemius::get_instance_by_id( $plugin_id );
+ $is_premium = $fs_addon->is_premium();
+ } else {
+ // If add-on isn't activated assume the premium version isn't installed.
+ $is_premium = false;
+ }
+ }
+
+ // Get site context secure params.
+ if ( $fs->is_registered() ) {
+ $site = $fs->get_site();
+
+ if ( $plugin_id != $fs->get_id() ) {
+ if ( $fs->is_addon_activated( $plugin_id ) ) {
+ $fs_addon = Freemius::get_instance_by_id( $plugin_id );
+ $addon_site = $fs_addon->get_site();
+ if ( is_object( $addon_site ) ) {
+ $site = $addon_site;
+ }
+ }
+ }
+
+ $context_params = array_merge(
+ $context_params,
+ FS_Security::instance()->get_context_params(
+ $site,
+ $timestamp,
+ 'checkout'
+ )
+ );
+ } else {
+ $current_user = Freemius::_get_current_wp_user();
+
+ // Add site and user info to the request, this information
+ // is NOT being stored unless the user complete the purchase
+ // and agrees to the TOS.
+ $context_params = array_merge( $context_params, array(
+ 'user_firstname' => $current_user->user_firstname,
+ 'user_lastname' => $current_user->user_lastname,
+ 'user_email' => $current_user->user_email,
+ 'home_url' => home_url(),
+ ) );
+
+ $fs_user = Freemius::_get_user_by_email( $current_user->user_email );
+
+ if ( is_object( $fs_user ) && $fs_user->is_verified() ) {
+ $context_params = array_merge(
+ $context_params,
+ FS_Security::instance()->get_context_params(
+ $fs_user,
+ $timestamp,
+ 'checkout'
+ )
+ );
+ }
+ }
+
+ if ( $fs->is_payments_sandbox() ) {
+ // Append plugin secure token for sandbox mode authentication.
+ $context_params['sandbox'] = FS_Security::instance()->get_secure_token(
+ $fs->get_plugin(),
+ $timestamp,
+ 'checkout'
+ );
+
+ /**
+ * @since 1.1.7.3 Add security timestamp for sandbox even for anonymous user.
+ */
+ if ( empty( $context_params['s_ctx_ts'] ) ) {
+ $context_params['s_ctx_ts'] = $timestamp;
+ }
+ }
+
+ $can_user_install = (
+ ( $fs->is_plugin() && current_user_can( 'install_plugins' ) ) ||
+ ( $fs->is_theme() && current_user_can( 'install_themes' ) )
+ );
+
+ return array_merge( $context_params, $_GET, array(
+ // Current plugin version.
+ 'plugin_version' => $fs->get_plugin_version(),
+ 'sdk_version' => WP_FS__SDK_VERSION,
+ 'is_premium' => $is_premium ? 'true' : 'false',
+ 'can_install' => $can_user_install ? 'true' : 'false',
+ ) );
+ }
+
+ /**
+ * The return URL to pass to the checkout when the checkout is loaded in "redirect" mode.
+ *
+ * @param Freemius $fs
+ *
+ * @return string
+ */
+ public function get_checkout_redirect_return_url( Freemius $fs ) {
+ $request_url = remove_query_arg( '_wp_http_referer' );
+
+ return fs_nonce_url(
+ $fs->checkout_url(
+ fs_request_get( 'billing_cycle' ),
+ fs_request_get_bool( 'trial' ),
+ array(
+ 'process_redirect' => 'true',
+ '_wp_http_referer' => $request_url,
+ )
+ ),
+ $this->get_checkout_redirect_nonce_action( $fs )
+ );
+ }
+
+ /**
+ * @param array $query_params
+ * @param string $base_url
+ *
+ * @return string
+ */
+ public function get_full_checkout_url( array $query_params, $base_url = FS_CHECKOUT__ADDRESS ) {
+ return $base_url . '/?' . http_build_query( $query_params );
+ }
+
+ /**
+ * Verifies the redirect after a checkout with the nonce.
+ *
+ * @param Freemius $fs
+ */
+ public function verify_checkout_redirect_nonce( Freemius $fs ) {
+ check_admin_referer( $this->get_checkout_redirect_nonce_action( $fs ) );
+ }
+
+ /**
+ * Get the URL to process a new install after the checkout.
+ *
+ * @param Freemius $fs
+ * @param number $plugin_id
+ *
+ * @return string
+ */
+ public function get_install_url( Freemius $fs, $plugin_id ) {
+ return fs_nonce_url( $fs->_get_admin_page_url( 'account', array(
+ 'fs_action' => $fs->get_unique_affix() . '_activate_new',
+ 'plugin_id' => $plugin_id,
+ ) ), $fs->get_unique_affix() . '_activate_new' );
+ }
+
+ /**
+ * Get the URL to process a pending activation after the checkout.
+ *
+ * @param Freemius $fs
+ * @param number $plugin_id
+ *
+ * @return string
+ */
+ public function get_pending_activation_url( Freemius $fs, $plugin_id ) {
+ return fs_nonce_url( $fs->_get_admin_page_url( 'account', array(
+ 'fs_action' => $fs->get_unique_affix() . '_activate_new',
+ 'plugin_id' => $plugin_id,
+ 'pending_activation' => true,
+ 'has_upgrade_context' => true,
+ ) ), $fs->get_unique_affix() . '_activate_new' );
+ }
+
+ private function get_checkout_redirect_nonce_action( Freemius $fs ) {
+ return $fs->get_unique_affix() . '_checkout_redirect';
+ }
+ }
No newline at end of file
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/managers/class-fs-contact-form-manager.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/includes/managers/class-fs-contact-form-manager.php
@@ -0,0 +1,84 @@
+<?php
+ /**
+ * @package Freemius
+ * @copyright Copyright (c) 2024, Freemius, Inc.
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
+ * @since 2.9.0
+ */
+
+ if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+ }
+
+ class FS_Contact_Form_Manager {
+
+ # region Singleton
+
+ /**
+ * @var FS_Contact_Form_Manager
+ */
+ private static $_instance;
+
+ /**
+ * @return FS_Contact_Form_Manager
+ */
+ static function instance() {
+ if ( ! isset( self::$_instance ) ) {
+ self::$_instance = new FS_Contact_Form_Manager();
+ }
+
+ return self::$_instance;
+ }
+
+ private function __construct() {
+ }
+
+ #endregion
+
+ /**
+ * Retrieves the query params needed to load the Freemius Contact Form in the context of the plugin.
+ *
+ * @param Freemius $fs
+ *
+ * @return array<string, string>
+ */
+ public function get_query_params( Freemius $fs ) {
+ $context_params = array(
+ 'plugin_id' => $fs->get_id(),
+ 'plugin_public_key' => $fs->get_public_key(),
+ 'plugin_version' => $fs->get_plugin_version(),
+ );
+
+ // Get site context secure params.
+ if ( $fs->is_registered() ) {
+ $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params(
+ $fs->get_site(),
+ time(),
+ 'contact'
+ ) );
+ }
+
+ return array_merge( $_GET, array_merge( $context_params, array(
+ 'plugin_version' => $fs->get_plugin_version(),
+ 'wp_login_url' => wp_login_url(),
+ 'site_url' => Freemius::get_unfiltered_site_url(),
+ // 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons",
+ ) ) );
+ }
+
+ /**
+ * Retrieves the standalone link to the Freemius Contact Form.
+ *
+ * @param Freemius $fs
+ *
+ * @return string
+ */
+ public function get_standalone_link( Freemius $fs ) {
+ $query_params = $this->get_query_params( $fs );
+
+ $query_params['is_standalone'] = 'true';
+ $query_params['parent_url'] = admin_url( add_query_arg( null, null ) );
+
+ return WP_FS__ADDRESS . '/contact/?' . http_build_query( $query_params );
+ }
+ }
No newline at end of file
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/require.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/require.php
@@ -27,6 +27,8 @@
require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-clone-manager.php';
require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-permission-manager.php';
require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-cache-manager.php';
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-checkout-manager.php';
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-contact-form-manager.php';
require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-notice-manager.php';
require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-menu-manager.php';
require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-key-value-storage.php';
--- a/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/start.php
+++ b/spotlight-social-photo-feeds/vendor/freemius/wordpress-sdk/start.php
@@ -15,7 +15,7 @@
*
* @var string
*/
- $this_sdk_version = '2.8.1';
+ $this_sdk_version = '2.11.0';
#region SDK Selection Logic --------------------------------------------------------------------
@@ -36,7 +36,16 @@
require_once dirname( __FILE__ ) . '/includes/fs-essential-functions.php';
}
- /**
+ /**
+ * We updated the logic to support SDK loading from a subfolder of a theme as well as from a parent theme
+ * If the SDK is found in the active theme, it sets the relative path accordingly.
+ * If not, it checks the parent theme and sets the relative path if found there.
+ * This allows the SDK to be loaded from composer dependencies or from a custom `vendor/freemius` folder.
+ *
+ * @author Daniele Alessandra (@DanieleAlessandra)
+ * @since 2.9.0.5
+ *
+ *
* This complex logic fixes symlink issues (e.g. with Vargant). The logic assumes
* that if it's a file from an SDK running in a theme, th