bibhamrokhanpin/wp-content/__plugins/redux-framework/redux-templates/classes/class-api.php

1303 lines
35 KiB
PHP
Raw Normal View History

2024-04-10 12:01:06 +00:00
<?php // phpcs:ignore WordPress.Files.FileName
/**
* Redux templates API class.
*
* @since 4.0.0
* @package Redux Framework
*/
namespace ReduxTemplates;
use ReduxTemplates;
use WP_Patterns_Registry;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* ReduxTemplates API class.
*
* @since 4.0.0
*/
class Api {
/**
* Seconds to cache the local files.
*
* @var int
*/
private $cache_time = 24 * 3600; // 24 hours
/**
* Timeout for requests.
*
* @var int
*/
private $timeout = 145;
/**
* API URL.
*
* @var string
*/
protected $api_base_url = 'https://api.redux.io/';
/**
* License API URL.
*
* @var string
*/
protected $license_base_url = 'https://redux.io/';
/**
* Default headers array.
*
* @var array
*/
protected $default_request_headers = array();
/**
* Filesystem object instance.
*
* @var Filesystem
*/
protected $filesystem;
/**
* Cache folder location.
*
* @var string
*/
protected $cache_folder;
/**
* Constructor.
*/
public function __construct() {
add_filter( 'redux_templates_api_headers', array( $this, 'request_verify' ) );
$this->default_request_headers = apply_filters( 'redux_templates_api_headers', $this->default_request_headers );
add_action( 'rest_api_init', array( $this, 'register_api_hooks' ), 0 );
}
/**
* Get the filesystem.
*
* @return Filesystem
*/
private function get_filesystem() {
if ( empty( $this->filesystem ) ) {
$this->filesystem = \Redux_Filesystem::get_instance();
}
return $this->filesystem;
}
/**
* Process the registered blocks from the library.
*
* @param array $parameters Array to be returned if no response, or to have data appended to.
*
* @return array Array of properly processed blocks and supported plugins.
*/
private function process_registered_blocks( $parameters ) {
$data = $this->api_cache_fetch( array(), array(), 'library.json' );
if ( empty( $data ) || ( ! empty( $data ) && ! isset( $data['plugins'] ) ) ) {
return $parameters;
}
$supported = ReduxTemplates\Supported_Plugins::instance();
$supported->init( $data['plugins'] );
$plugins = $supported::get_plugins();
$installed_plugins = array();
if ( ! isset( $parameters['registered_blocks'] ) ) {
$parameters['registered_blocks'] = array();
}
foreach ( $plugins as $key => $value ) {
if ( isset( $value['version'] ) ) {
array_push( $installed_plugins, $key . '~' . $value['version'] );
$found_already = array_search( $key, $parameters['registered_blocks'], true );
if ( false !== $found_already ) {
unset( $parameters['registered_blocks'][ $found_already ] );
}
if ( isset( $value['namespace'] ) && $key !== $value['namespace'] ) {
$found = array_search( $value['namespace'], $parameters['registered_blocks'], true );
if ( false !== $found ) {
unset( $parameters['registered_blocks'][ $found ] );
}
}
}
}
$parameters['registered_blocks'] = array_values( array_merge( $installed_plugins, $parameters['registered_blocks'] ) );
return $parameters;
}
/**
* Process the dependencies.
*
* @param array $data Data array.
* @param string $key Key param.
*
* @return array Data array with dependencies outlined.
*/
private function process_dependencies( $data, $key ) {
foreach ( $data[ $key ] as $kk => $pp ) {
$debug = false;
// Add debug if statement if key matches here.
if ( isset( $pp['dependencies'] ) ) {
foreach ( $pp['dependencies'] as $dep ) {
if ( isset( $data['plugins'][ $dep ] ) ) {
if ( isset( $data['plugins'][ $dep ]['no_plugin'] ) || 'core' === $dep ) {
continue;
}
if ( isset( $data['plugins'][ $dep ]['free_slug'] ) ) {
if ( isset( $data['plugins'][ $data['plugins'][ $dep ]['free_slug'] ] ) ) {
$plugin = $data['plugins'][ $data['plugins'][ $dep ]['free_slug'] ];
if ( ! isset( $plugin['is_pro'] ) ) {
if ( ! isset( $data[ $key ][ $kk ]['proDependenciesMissing'] ) ) {
$data[ $key ][ $kk ]['proDependenciesMissing'] = array();
}
$data[ $key ][ $kk ]['proDependenciesMissing'][] = $dep;
}
if ( ! isset( $data[ $key ][ $kk ]['proDependencies'] ) ) {
$data[ $key ][ $kk ]['proDependencies'] = array();
}
$data[ $key ][ $kk ]['proDependencies'][] = $dep;
}
} else {
if ( ! isset( $data['plugins'][ $dep ]['version'] ) ) {
if ( ! isset( $data[ $key ][ $kk ]['installDependenciesMissing'] ) ) {
$data[ $key ][ $kk ]['installDependenciesMissing'] = array();
}
$data[ $key ][ $kk ]['installDependenciesMissing'][] = $dep;
}
if ( ! isset( $data[ $key ][ $kk ]['installDependencies'] ) ) {
$data[ $key ][ $kk ]['installDependencies'] = array();
}
$data[ $key ][ $kk ]['installDependencies'][] = $dep;
}
}
}
}
// Print the debug here if the key exists. Use `print_r( $data[ $key ][ $kk ] );exit();`.
}
return $data;
}
/**
* Get the last cache time.
*
* @param string $abs_path Absolute path to a file.
*
* @return string|bool Last modified time.
*/
private function get_cache_time( $abs_path ) {
$filesystem = $this->get_filesystem();
$last_modified = false;
if ( $filesystem->file_exists( $abs_path ) ) {
$last_modified = filemtime( $abs_path );
}
return $last_modified;
}
/**
* Fetch from the cache if had.
*
* @param array $parameters Absolute path to a file.
* @param array $config Absolute path to a file.
* @param string $path URL path perform a request to a file.
* @param bool $cache_only Set to only fetch from the local cache.
*
* @return array Response and possibly the template if recovered.
*/
public function api_cache_fetch( $parameters, $config, $path, $cache_only = false ) {
$filesystem = $this->get_filesystem();
$this->cache_folder = trailingslashit( $filesystem->cache_folder ) . 'templates/';
if ( ! $filesystem->file_exists( $this->cache_folder ) ) {
$filesystem->mkdir( $this->cache_folder );
}
if ( strpos( $path, $this->cache_folder ) === false ) {
$path = $this->cache_folder . $path;
}
if ( ! $filesystem->file_exists( dirname( $path ) ) ) {
$filesystem->mkdir( dirname( $path ) );
}
$last_modified = file_exists( $path ) ? $this->get_cache_time( $path ) : false;
$use_cache = true;
if ( isset( $parameters['no_cache'] ) ) {
$use_cache = false;
}
if ( ! empty( $last_modified ) ) {
$config['headers']['Redux-Cache-Time'] = $last_modified;
if ( time() > $last_modified + $this->cache_time ) {
$use_cache = false;
}
}
if ( $cache_only ) {
$use_cache = true;
}
$data = array();
if ( file_exists( $path ) && $use_cache ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors
$data = @json_decode( $filesystem->get_contents( $path ), true );
}
// If somehow we got an invalid response, let's not persist it.
if ( isset( $data['message'] ) && false !== strpos( $data['message'], 'meta http-equiv="refresh" content="0;URL=' ) ) {
$data = false;
}
if ( $cache_only ) {
return $data;
}
if ( ! $use_cache && isset( $config['headers']['Redux-Cache-Time'] ) ) {
unset( $config['headers']['Redux-Cache-Time'] );
}
if ( empty( $data ) ) {
if ( isset( $parameters['registered_blocks'] ) ) {
$config['headers']['Redux-Registered-Blocks'] = implode( ',', $parameters['registered_blocks'] );
}
$results = $this->api_request( $config );
if ( ! empty( $results ) ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors
$data = @json_decode( $results, true );
if ( isset( $data['use_cache'] ) ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors
$data = @json_decode( $filesystem->get_contents( $path ), true );
$data['cache'] = 'used';
} else {
if ( empty( $data ) ) {
$data = array( 'message' => $results );
}
if ( isset( $data['status'] ) && 'error' === $data['status'] ) {
wp_send_json_error( array( 'message' => $data['message'] ) );
}
$filesystem->put_contents( $path, wp_json_encode( $data ) );
}
} else {
wp_send_json_error( array( 'message' => __( 'API fetch failure.', 'redux-framework' ) ) );
}
}
if ( empty( $data ) ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors
$data = @json_decode( $filesystem->get_contents( $path ), true );
if ( $data ) {
$data['status'] = 'error';
$data['message'] = __( 'Fetching failed, used a cached version.', 'redux-framework' );
} else {
$data = array(
'message' => 'Error Fetching',
);
}
} else {
if ( ! $use_cache ) {
$data['cache'] = 'cleared';
}
}
return $data;
}
/**
* Get library index. Support for library, collections, pages, sections all in a single request.
*
* @param \WP_REST_Request $request WP Rest request.
*
* @since 4.0.0
*/
public function get_index( \WP_REST_Request $request ) {
$parameters = $request->get_params();
$attributes = $request->get_attributes();
$type = $request->get_route();
$type = explode( '/', $type );
$type = end( $type );
if ( empty( $type ) ) {
wp_send_json_error( 'No type specified.' );
}
$config = array(
'path' => 'library/',
);
$test_path = dirname( __FILE__ ) . '/library.json';
if ( file_exists( $test_path ) ) {
$data = json_decode( ReduxTemplates\Init::get_local_file_contents( $test_path ), true );
} else {
$parameters['no_cache'] = 1;
$data = $this->api_cache_fetch( $parameters, $config, 'library/' );
}
if ( isset( $data['plugins'] ) ) {
$supported = ReduxTemplates\Supported_Plugins::instance();
$supported->init( $data['plugins'] );
$data['plugins'] = $supported::get_plugins();
$data['plugins']['redux-framework']['version'] = \Redux_Core::$version;
if ( \Redux_Helpers::mokama() ) {
if ( class_exists( 'Redux_Pro' ) ) {
$data['plugins']['redux-framework']['is_pro'] = \Redux_Pro::$version;
} else {
$data['plugins']['redux-framework']['is_pro'] = \Redux_Core::$version;
}
}
$data = $this->process_dependencies( $data, 'sections' );
$data = $this->process_dependencies( $data, 'pages' );
}
if ( class_exists( 'WP_Patterns_Registry' ) ) {
$patterns = \WP_Patterns_Registry::get_instance()->get_all_registered();
foreach ( $patterns as $k => $p ) {
$id = 'wp_block_pattern_' . $k;
$data['sections'][ $id ] = array(
'name' => $p['title'],
'categories' => array( 'WP Block Patterns' ),
'source' => 'wp_block_patterns',
'id' => $id,
);
}
}
wp_send_json_success( $data );
}
/**
* Filter an array recursively.
*
* @param array $input Array to filter.
*
* @return array Filtered array.
*/
private function array_filter_recursive( $input ) {
foreach ( $input as &$value ) {
if ( is_array( $value ) ) {
$value = $this->array_filter_recursive( $value );
}
}
return array_filter( $input );
}
/**
* Method for transmitting a template the user is sharing remotely.
*
* @param \WP_REST_Request $request WP Rest request.
*
* @since 4.0.0
*/
public function share_template( \WP_REST_Request $request ) {
$parameters = $request->get_params();
$attributes = $request->get_attributes();
$parameters = $this->process_registered_blocks( $parameters );
if ( empty( $parameters ) ) {
wp_send_json_error( 'No template data found.' );
}
$config = array(
'path' => 'template_share/',
'uid' => get_current_user_id(),
'editor_content' => isset( $parameters['editor_content'] ) ? (string) $parameters['editor_content'] : '',
'editor_blocks' => isset( $parameters['editor_blocks'] ) ? $parameters['editor_blocks'] : '',
'postID' => isset( $parameters['postID'] ) ? (string) sanitize_text_field( $parameters['postID'] ) : '',
'title' => isset( $parameters['title'] ) ? (string) sanitize_text_field( $parameters['title'] ) : 'The Title',
'type' => isset( $parameters['type'] ) ? (string) sanitize_text_field( $parameters['type'] ) : 'page',
'categories' => isset( $parameters['categories'] ) ? (string) sanitize_text_field( $parameters['categories'] ) : '',
'description' => isset( $parameters['description'] ) ? (string) sanitize_text_field( $parameters['description'] ) : '',
'headers' => array(
'Redux-Registered-Blocks' => isset( $parameters['registered_blocks'] ) ? (string) sanitize_text_field( implode( ',', $parameters['registered_blocks'] ) ) : '',
),
);
$config = $this->array_filter_recursive( $config );
if ( ! isset( $config['title'] ) ) {
wp_send_json_error( array( 'messages' => 'A title is required.' ) );
}
if ( ! isset( $config['type'] ) ) {
wp_send_json_error( array( 'messages' => 'A type is required.' ) );
}
$response = $this->api_request( $config );
// phpcs:ignore WordPress.PHP.NoSilencedErrors
$data = @json_decode( $response, true );
if ( 'success' === $data['status'] && isset( $data['url'] ) ) {
wp_send_json_success( array( 'url' => $data['url'] ) );
}
wp_send_json_error( $data );
}
/**
* Run an API request.
*
* @param array $data Array related to an API request.
*
* @return string API response string.
*/
public function api_request( $data ) {
$api_url = $this->api_base_url;
if ( isset( $data['path'] ) ) {
if ( 'library/' === $data['path'] ) {
$api_url = 'https://files.redux.io/library.json';
$request = wp_remote_get( $api_url, array( 'timeout' => $this->timeout ) );
if ( is_wp_error( $request ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => $request->get_error_messages(),
'message_types' => 'error',
)
);
}
if ( 404 === wp_remote_retrieve_response_code( $request ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => 'Error fetching library, URL not found. Please try again',
'message_types' => 'error',
)
);
}
return $request['body'];
}
$api_url = $api_url . $data['path'];
}
if ( isset( $data['_locale'] ) ) {
unset( $data['_locale'] );
}
$headers = array();
if ( isset( $data['headers'] ) ) {
$headers = $data['headers'];
unset( $data['headers'] );
}
if ( isset( $data['p'] ) ) {
$headers['Redux-P'] = $data['p'];
unset( $data['p'] );
}
if ( isset( $data['path'] ) ) {
$headers['Redux-Path'] = $data['path'];
unset( $data['path'] );
}
$headers['Redux-Slug'] = \Redux_Helpers::get_hash();
$headers = wp_parse_args( $headers, $this->default_request_headers );
$headers['Content-Type'] = 'application/json; charset=utf-8';
$headers = array_filter( $headers );
if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
$headers['Redux-User-Agent'] = (string) sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) );
}
$headers['Redux-SiteURL'] = get_site_url( get_current_blog_id() );
$post_args = array(
'timeout' => $this->timeout,
'body' => wp_json_encode( $data ),
'method' => 'POST',
'data_format' => 'body',
'redirection' => 5,
'headers' => $headers,
);
$request = wp_remote_post( $api_url, $post_args );
// Handle redirects.
if ( ! is_wp_error( $request ) && isset( $request['http_response'] ) && $request['http_response'] instanceof \WP_HTTP_Requests_Response && method_exists( $request['http_response'], 'get_response_object' ) && strpos( $request['http_response']->get_response_object()->url, 'files.redux.io' ) !== false ) {
if ( isset( $data['no_redirect'] ) ) {
return $request['http_response']->get_response_object()->url;
} else {
$request = wp_remote_get( $request['http_response']->get_response_object()->url, array( 'timeout' => $this->timeout ) );
}
}
if ( is_wp_error( $request ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => $request->get_error_messages(),
'message_types' => 'error',
)
);
}
if ( 404 === wp_remote_retrieve_response_code( $request ) ) {
return false;
}
return $request['body'];
}
/**
* Fetch a single template.
*
* @param \WP_REST_Request $request WP Rest request.
*
* @since 4.0.0
*/
public function get_template( \WP_REST_Request $request ) {
$parameters = $request->get_params();
$attributes = $request->get_attributes();
$parameters = $this->process_registered_blocks( $parameters );
if ( in_array( $parameters['type'], array( 'sections', 'pages' ), true ) ) {
$parameters['type'] = substr_replace( $parameters['type'], '', - 1 );
}
$config = array(
'path' => 'template/',
'id' => sanitize_text_field( $parameters['id'] ),
'type' => (string) sanitize_text_field( $parameters['type'] ),
'source' => isset( $parameters['source'] ) ? $parameters['source'] : '',
);
$template_response = $this->check_template_response( $parameters );
if ( 'wp_block_patterns' === $config['source'] && class_exists( 'WP_Patterns_Registry' ) ) {
$patterns = \WP_Patterns_Registry::get_instance()->get_all_registered();
$id = explode( '_', $config['id'] );
$id = end( $id );
if ( isset( $patterns[ $id ] ) ) {
$response = array( 'template' => $patterns[ $id ]['content'] );
}
} else {
$cache_path = $config['type'] . DIRECTORY_SEPARATOR . $config['id'] . '.json';
$parameters['no_cache'] = 1;
$response = $this->api_cache_fetch( $parameters, $config, $cache_path );
if ( false === $response ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => 'Error fetching template. Please try again',
'message_types' => 'error',
)
);
}
$response = wp_parse_args( $response, $template_response );
}
if ( ! empty( $response ) && isset( $response['message'] ) ) {
$response['template'] = $response['message'];
unset( $response['message'] );
}
wp_send_json_success( $response );
}
/**
* Check template reponse.
*
* @param array $parameters Parameters array.
*
* @return array
* @since 4.0.0
*/
public function check_template_response( $parameters ) {
$response = array();
if ( ! \Redux_Helpers::mokama() ) {
if ( \Redux_Functions_Ex::activated() ) {
$response['left'] = 999;
} else {
$count = ReduxTemplates\Init::left( $parameters['uid'] );
$count = intval( $count ) - 1;
if ( 0 === $count ) {
$response['left'] = $count;
update_user_meta( $parameters['uid'], '_redux_templates_counts', -1 );
} elseif ( $count < 0 ) {
wp_send_json_error(
array(
'message' => 'Please activate Redux',
'left' => 0,
)
);
} else {
update_user_meta( $parameters['uid'], '_redux_templates_counts', $count );
}
$response['left'] = $count;
}
}
return $response;
}
/**
* Check template reponse.
*
* @param array $parameters Parameters array.
*
* @since 4.0.0
*/
public function activate_redux( $parameters ) {
if ( \Redux_Functions_Ex::activated() ) {
$response['left'] = 999;
} else {
\Redux_Core::$insights->optin();
if ( \Redux_Functions_Ex::activated() ) {
$response['left'] = 999;
} else {
$count = get_user_meta( get_current_user_id(), '_redux_templates_counts', true );
if ( false === $count ) {
$count = Init::$default_left;
update_user_meta( get_current_user_id(), '_redux_templates_counts', $count );
}
$response = array(
'left' => $count,
);
}
}
if ( 999 === $response['left'] ) {
wp_send_json_success( $response );
}
wp_send_json_error( $response );
}
/**
* Fetch a single template.
*
* @param array $data Data array.
*
* @return array
* @since 4.0.0
*/
public function request_verify( $data = array() ) {
$config = array(
'Redux-Version' => REDUXTEMPLATES_VERSION,
'Redux-Multisite' => is_multisite(),
'Redux-Mokama' => \Redux_Helpers::mokama(),
'Redux-Insights' => \Redux_Core::$insights->tracking_allowed(),
);
// TODO - Update this with the EDD key or developer key.
$config['Redux-API-Key'] = '';
if ( ! empty( \Redux_Core::$pro_loaded ) && \Redux_Core::$pro_loaded ) {
$config['Redux-Pro'] = \Redux_Core::$pro_loaded;
}
$data = wp_parse_args( $data, $config );
return $data;
}
/**
* Get all saved blocks (reusable blocks).
*
* @param \WP_REST_Request $request WP Rest request.
*
* @since 4.0.0
*/
public function get_saved_blocks( \WP_REST_Request $request ) {
$args = array(
'post_type' => 'wp_block',
'post_status' => 'publish',
);
$r = wp_parse_args( null, $args );
$get_posts = new \WP_Query();
$wp_blocks = $get_posts->query( $r );
wp_send_json_success( $wp_blocks );
}
/**
* Delete a single saved (reusable) block
*
* @param \WP_REST_Request $request WP Rest request.
*
* @since 4.0.0
*/
public function delete_saved_block( \WP_REST_Request $request ) {
$parameters = $request->get_params();
$attributes = $request->get_attributes();
if ( ! isset( $parameters['block_id'] ) ) {
return wp_send_json_error(
array(
'status' => 'error',
'message' => 'Missing block_id.',
)
);
}
$block_id = (int) sanitize_text_field( wp_unslash( $parameters['block_id'] ) );
$deleted_block = wp_delete_post( $block_id );
wp_send_json_success( $deleted_block );
}
/**
* Record that the user has used the welcome guide.
*
* @param \WP_REST_Request $request WP Rest request.
*
* @since 4.0.0
*/
public function welcome_guide( \WP_REST_Request $request ) {
$parameters = $request->get_params();
$attributes = $request->get_attributes();
if ( ! isset( $parameters['uid'] ) ) {
return wp_send_json_error(
array(
'status' => 'error',
'message' => 'User ID required.',
)
);
}
update_user_meta( $parameters['uid'], '_redux_welcome_guide', '1' );
wp_send_json_success( array( 'status' => 'success' ) );
}
/**
* Method used to register all rest endpoint hooks.
*
* @since 4.0.0
*/
public function register_api_hooks() {
$hooks = array(
'library' => array(
'callback' => 'get_index',
),
'pages' => array(
'callback' => 'get_index',
),
'sections' => array(
'callback' => 'get_index',
),
'collections' => array(
'callback' => 'get_index',
),
'feedback' => array(
'callback' => 'send_feedback',
),
'suggestion' => array(
'callback' => 'send_suggestion',
),
'template' => array(
'callback' => 'get_template',
),
'share' => array(
'method' => 'POST',
'callback' => 'share_template',
),
'get_saved_blocks' => array(
'callback' => 'get_saved_blocks',
),
'delete_saved_block' => array(
'method' => 'POST',
'callback' => 'delete_saved_block',
),
'activate' => array(
'method' => 'GET',
'callback' => 'activate_redux',
),
'plugin-install' => array(
'method' => 'GET',
'callback' => 'plugin_install',
),
'license' => array(
'method' => 'GET',
'callback' => 'license',
),
'license-validate' => array(
'method' => 'GET',
'callback' => 'validate_license',
),
'license-activate' => array(
'method' => 'GET',
'callback' => 'activate_license',
),
'license-deactivate' => array(
'method' => 'GET',
'callback' => 'deactivate_license',
),
'get-pro-url' => array(
'method' => 'GET',
'callback' => 'get_pro_url',
),
'opt_out' => array(
'method' => 'GET',
'callback' => 'opt_out_account',
),
'welcome' => array(
'method' => 'POST',
'callback' => 'welcome_guide',
),
'nps' => array(
'method' => 'POST',
'callback' => 'send_nps',
),
);
$fs = \Redux_Filesystem::get_instance();
foreach ( $hooks as $route => $data ) {
$methods = array( 'GET', 'POST' );
if ( isset( $data['method'] ) ) {
$methods = explode( ',', $data['method'] );
}
foreach ( $methods as $method ) {
$args = array(
'methods' => $method,
'callback' => array( $this, $data['callback'] ),
'args' => array(),
);
if ( defined( 'REDUX_PLUGIN_FILE' ) && ! $fs->file_exists( trailingslashit( dirname( REDUX_PLUGIN_FILE ) ) . 'local_developer.txt' ) ) {
$args['permission_callback'] = function () {
return current_user_can( 'install_plugins' );
};
} else {
$args['permission_callback'] = '__return_true';
}
register_rest_route(
'redux/v1/templates',
$route,
$args
);
}
}
}
/**
* Install plugin endpoint.
*
* @param \WP_REST_Request $request WP Rest request.
*
* @since 4.0.0
*/
public function plugin_install( \WP_REST_Request $request ) {
$data = $request->get_params();
if ( empty( $data['slug'] ) ) {
wp_send_json_error(
array(
'error' => __( 'Slug not specified.', 'redux-framework' ),
)
);
}
$slug = (string) sanitize_text_field( $data['slug'] );
if ( ! empty( $data['redux_pro'] ) ) {
if ( \Redux_Helpers::mokama() || 'redux-pro' === $slug ) {
$config = array(
'path' => 'installer/',
'slug' => $slug,
'no_redirect' => true,
);
$parameters['no_cache'] = 1;
if ( 'redux-pro' === $slug ) {
$lic_status = get_option( 'redux_pro_license_status', false );
if ( 'valid' !== $lic_status && 'active' !== $lic_status ) {
$status = array(
'error' => __( 'Redux Pro license not active, please activate.', 'redux-framework' ),
);
} else {
$array = array(
'edd_action' => 'get_version',
);
$request = $this->do_license_request( $array );
if ( isset( $request['download_link'] ) ) {
$status = ReduxTemplates\Installer::run( $slug, $request['download_link'] );
} else {
$status = array(
'error' => __( 'Invalid license key.', 'redux-framework' ),
);
delete_option( 'redux_pro_license_status' );
}
}
} else {
$response = $this->api_cache_fetch( $parameters, $config, false, false );
if ( isset( $response['message'] ) && false !== strpos( $response['message'], 'redux.io' ) ) {
$status = ReduxTemplates\Installer::run( $slug, $response['message'] );
} else {
if ( isset( $response['error'] ) && ! empty( $response['error'] ) ) {
$status = array(
'error' => $response['error'],
);
} else {
$status = array(
'error' => __( 'A valid Redux Pro subscription is required.', 'redux-framework' ),
);
}
}
}
} else {
$status = array(
'error' => __( 'A valid Redux Pro subscription is required.', 'redux-framework' ),
);
}
} else {
$status = ReduxTemplates\Installer::run( $slug );
}
if ( isset( $status['error'] ) ) {
wp_send_json_error( $status );
}
if ( 'otter-blocks' === $slug ) {
update_option( 'themeisle_blocks_settings_default_block', false );
}
wp_send_json_success( $status );
}
/**
* Check the license key.
*
* @since 4.1.18
* @return bool|array
*/
protected function check_license_key() {
$lic = get_option( 'redux_pro_license_key' );
if ( empty( $lic ) ) {
delete_option( 'redux_pro_license_status' );
return array(
'success' => 'false',
'message' => 'No license found.',
'message_types' => 'error',
);
}
return true;
}
/**
* Run the license API calls.
*
* @param \WP_REST_Request $request WP Rest request.
* @since 4.1.18
*/
public function license( \WP_REST_Request $request ) {
$data = $request->get_params();
if ( ! isset( $data['key'] ) || ( isset( $data['key'] ) && empty( $data['key'] ) ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => 'License key not provided or empty.',
'message_types' => 'error',
)
);
}
$array = array(
'edd_action' => 'check_license',
'license' => $data['key'],
);
$response = $this->do_license_request( $array );
if ( isset( $response['license'] ) && in_array( $response['license'], array( 'valid', 'site_inactive', 'inactive' ), true ) ) {
if ( 'valid' === $response['license'] ) {
wp_send_json_success( array( 'status' => 'success' ) );
} else {
if ( 0 === $response['data']['activations_left'] ) {
delete_option( 'redux_pro_license_key' );
wp_send_json_error(
array(
'status' => 'error',
'message' => __( 'You have reached your activation limits for Redux Pro', 'redux-framework' ),
)
);
}
update_option( 'redux_pro_license_key', $data['key'] );
$array = array(
'edd_action' => 'activate_license',
);
$response = $this->do_license_request( $array );
if ( isset( $response['license'] ) && 'valid' === $response['license'] ) {
\Redux_Functions_Ex::set_activated();
wp_send_json_success( $response );
}
}
}
wp_send_json_error(
array(
'status' => 'error',
'msg' => __( 'Invalid license key.', 'redux-framework' ),
'response' => $response,
)
);
}
/**
* Validate a license key.
*
* @param \WP_REST_Request $request WP Rest request.
* @since 4.1.18
*/
public function validate_license( \WP_REST_Request $request ) {
$data = $request->get_params();
if ( ! isset( $data['key'] ) || ( isset( $data['key'] ) && empty( $data['key'] ) ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => 'License key not provided or empty.',
'message_types' => 'error',
)
);
}
$array = array(
'edd_action' => 'check_license',
'license' => $data['key'],
);
$response = $this->do_license_request( $array );
if ( isset( $response['license'] ) && in_array( $response['key'], array( 'valid', 'site_inactive' ), true ) ) {
update_option( 'redux_pro_license_status', $data['key'] );
wp_send_json_success( $response );
} else {
wp_send_json_error(
$response
);
}
}
/**
* Activate a license key.
*
* @param \WP_REST_Request $request WP Rest request.
* @since 4.1.18
*/
public function activate_license( \WP_REST_Request $request ) {
$check = $this->check_license_key();
if ( is_array( $check ) ) {
wp_send_json_error( $check );
}
$lic = get_option( 'redux_pro_license_key' );
if ( empty( $lic ) ) {
delete_option( 'redux_pro_license_status' );
wp_send_json_error(
array(
'success' => 'false',
'message' => 'No license found.',
'message_types' => 'error',
)
);
}
$array = array(
'edd_action' => 'activate_license',
);
$request = $this->do_license_request( $array );
if ( isset( $request['license'] ) && 'valid' === $request['license'] ) {
wp_send_json_success( $request );
}
wp_send_json_error(
array(
'success' => 'false',
'message' => 'License is not valid.',
'message_types' => 'error',
)
);
}
/**
* Deactivate a license key.
*
* @since 4.1.18
*/
public function deactivate_license() {
$check = $this->check_license_key();
if ( is_array( $check ) ) {
wp_send_json_error( $check );
}
$lic = get_option( 'redux_pro_license_key' );
if ( empty( $lic ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => 'No license found.',
'message_types' => 'error',
)
);
}
$array = array(
'edd_action' => 'deactivate_license',
);
$request = $this->do_license_request( $array );
if ( isset( $request['license'] ) && 'deactivated' === $request['license'] ) {
delete_option( 'redux_pro_license_key' );
wp_send_json_success( $request );
}
wp_send_json_error(
array(
'success' => 'false',
'message' => 'License is not valid.',
'message_types' => 'error',
)
);
}
/**
* Get the Redux Pro download URL.
*
* @since 4.1.18
*/
public function get_pro_url() {
$lic_status = get_option( 'redux_pro_license_status', 'inactive' );
if ( 'valid' !== $lic_status && 'active' !== $lic_status ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => 'License not active, please activate.',
'message_types' => 'error',
)
);
}
$array = array(
'edd_action' => 'get_version',
);
$request = $this->do_license_request( $array );
if ( isset( $request['download_link'] ) ) {
wp_send_json_success( $request['download_link'] );
}
wp_send_json_error(
array(
'success' => 'false',
'message' => 'Could not recover Pro download URL.',
'message_types' => 'error',
)
);
}
/**
* Run the license API calls.
*
* @param array $args Array of args.
* @since 4.1.18
* @return mixed
*/
private function do_license_request( $args ) {
$defaults = array(
'item_name' => 'Redux Pro',
'url' => network_site_url(),
'license' => get_option( 'redux_pro_license_key' ),
);
$args = wp_parse_args( $args, $defaults );
if ( ! isset( $args['edd_action'] ) || ( isset( $args['edd_action'] ) && empty( $args['edd_action'] ) ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => 'Missing edd_action.',
'message_types' => 'error',
)
);
}
if ( 'check_license' !== $args['edd_action'] ) {
$check = $this->check_license_key();
if ( is_array( $check ) ) {
wp_send_json_error( $check );
}
}
$url = add_query_arg( $args, $this->license_base_url );
$request = wp_remote_get( $url, array( 'timeout' => $this->timeout ) );
if ( is_wp_error( $request ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => $request->get_error_messages(),
'message_types' => 'error',
)
);
}
if ( 404 === wp_remote_retrieve_response_code( $request ) ) {
wp_send_json_error(
array(
'success' => 'false',
'message' => 'Our API appears to be down... please try again later.',
'message_types' => 'error',
)
);
}
$data = json_decode( $request['body'], true );
if ( isset( $data['license'] ) ) {
update_option( 'redux_pro_license_status', $data['license'] );
}
return $data;
}
/**
* Send the NPS value.
*
* @param \WP_REST_Request $request WP Rest request.
* @since 4.1.19
*/
public function send_nps( \WP_REST_Request $request ) {
$data = $request->get_params();
if ( empty( $data['nps'] ) ) {
wp_send_json_error(
array(
'error' => __( 'NPS not specified.', 'redux-framework' ),
)
);
}
$nps = (string) sanitize_text_field( $data['nps'] );
$the_request = array(
'path' => 'nps',
'nps' => $nps,
);
$response = $this->api_request( $the_request );
if ( false === $response ) {
wp_send_json_error(
array(
'message' => __( 'Could not record score.', 'redux-framework' ),
)
);
}
wp_send_json_success( json_decode( $response ) );
}
}