Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
<?php
/**
* Class TPM_Admin
* - included by main plugin class if the current request is_admin()
*
* @see is_admin()
*/
class TPM_Admin {
private static $instance;
private function __construct() {
/**
* update tpm_version option
*/
add_action(
'admin_init',
function () {
/**
* On each TPM update clear cache
* - clear cache each time user updates TPM
*/
if ( $this->check_plugin_version( Thrive_Product_Manager::V ) ) {
$this->clear_all_cache();
update_option( 'tpm_version', Thrive_Product_Manager::V );
}
}
);
/**
* delete tpm_version from DB
*/
add_action(
'admin_init',
static function () {
register_deactivation_hook(
WP_PLUGIN_DIR . '/thrive-product-manager/thrive-product-manager.php',
array(
TPM_Admin::get_instance(),
'deactivation_callback',
)
);
}
);
}
/**
* @return TPM_Admin
*/
public static function get_instance() {
if ( empty( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Clears all cache
* - ttw products list
* - ttw licenses
*/
public function clear_all_cache() {
TPM_Product_List::get_instance()->clear_cache();
TPM_License_Manager::get_instance()->clear_cache();
}
/**
* Checks if the option saved in DB is lower strict than the current TPM plugin constant
* - used to run some code
*
* @param string version
*
* @return bool
*/
public function check_plugin_version( $version ) {
return version_compare( get_option( 'tpm_version', '1.0' ), $version, '<' );
}
/**
* Deletes tpm_version option from DB
*/
public function delete_tpm_version() {
delete_option( 'tpm_version' );
}
/**
* Callback when TPM is deactivated
* @see register_deactivation_hook()
*/
public function deactivation_callback() {
TPM_Product_List::get_instance()->clear_cache();
TPM_License_Manager::get_instance()->clear_cache();
TPM_License_Manager::get_instance()->deactivate_all_licenses();
$this->delete_tpm_version();
delete_option( 'tpm_bk_connection' );
}
}
if ( is_admin() ) {
return TPM_Admin::get_instance();
}

View File

@@ -0,0 +1,413 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TPM_Connection
*
* @property int ttw_id
* @property string ttw_salt
* @property string ttw_email
* @property string status
* @property string ttw_expiration datetime until the current connection is known by TTW; ttw_salt has to be refreshed after this date;
*/
class TPM_Connection {
const CONNECTED = 'connected';
const NAME = 'tpm_connection';
const SIGNATURE = 's6!xv(Q7Zp234L_snodt]CvG2meROk0Gurc49KiyJzz6kSjqAyqpUL&9+P4s';
protected $_data = array();
protected $_messages = array();
protected $_errors = array();
protected $_expected_data
= array(
'ttw_id',
'ttw_email',
'ttw_salt',
'ttw_expiration',
);
protected static $_instance;
private function __construct() {
$this->_data = get_option( self::NAME, array() );
$this->_messages = get_option( 'tpm_connection_messages', array() );
add_filter( 'tpm_messages', array( $this, 'apply_messages' ) );
}
/**
* @return TPM_Connection
*/
public static function get_instance() {
if ( ! self::$_instance ) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __isset( $name ) {
return isset( $this->_data[ $name ] );
}
public function __set( $key, $value ) {
$this->_data[ $key ] = $value;
return $this->_data[ $key ];
}
public function __get( $param ) {
$value = null;
if ( isset( $this->_data[ $param ] ) ) {
$value = $this->_data[ $param ];
}
return $value;
}
public function is_connected() {
return $this->status === self::CONNECTED;
}
public function set_data( $data ) {
$this->_data = $data;
}
public function get_login_url() {
return add_query_arg( array(
'callback_url' => urlencode( base64_encode( $this->get_callback_url() ) ),
'tpm_site' => base64_encode( get_site_url() ),
), Thrive_Product_Manager::get_ttw_url() . '/connect-account' );
}
/**
* URL where user is redirected back after he logs in TTW
*
* @return string
*/
protected function get_callback_url() {
$url = Thrive_Product_Manager::get_instance()->get_admin_url();
$url = add_query_arg( array(
'tpm_token' => base64_encode( $this->get_token() ),
), $url );
return $url;
}
public function get_token() {
$token = get_option( 'tpm_token', null );
if ( ! empty( $token ) ) {
return $this->decrypt( $token );
}
$rand_nr = mt_rand( 1, 11 );
$rand_chars = '^!#)_@%*^@(yR&dsYh';
$rand_string = substr( str_shuffle( $rand_chars ), 0, $rand_nr );
$token = $rand_string . strrev( base_convert( bin2hex( hash( 'sha512', uniqid( mt_rand() . microtime( true ) * 10000, true ), true ) ), 16, 36 ) );
$to_length = ceil( strlen( $token ) / 2 );
$token = $rand_nr . substr( $token, mt_rand( 1, 9 ), $to_length );
add_option( 'tpm_token', $this->encrypt( $token ) );
return $token;
}
public function encrypt( $str ) {
$str .= '-' . self::SIGNATURE;
$str = base64_encode( $str );
return $str;
}
public function decrypt( $str ) {
$str = base64_decode( $str );
$str = explode( '-', $str );
return $str[0];
}
protected function _is_valid_token( $token ) {
$tpm_token = get_option( 'tpm_token', null );
return $this->decrypt( $tpm_token ) === $token;
}
/**
* Process the request
* Validate it and sve the connection into DB
*
* @return bool
*/
public function process_data() {
if ( ! $this->_is_valid_token( base64_decode( $_REQUEST['tpm_token'] ) ) ) {
$this->_errors[] = __( 'Invalid token', Thrive_Product_Manager::T );
return false;
}
$data = $this->_read_data();
if ( ! $this->_is_valid( $data ) ) {
$this->_errors[] = __( 'Invalid data', Thrive_Product_Manager::T );
return false;
}
return $this->_save_connection( $data );
}
/**
* Reads expected data from request
*
* @return array
*/
protected function _read_data() {
$data = array();
$no_decode = array(
'ttw_salt',
);
foreach ( $this->_expected_data as $key ) {
//this has to be in clear; not encoded
if ( in_array( $key, $no_decode, false ) ) {
$data[ $key ] = $_REQUEST[ $key ];
continue;
}
if ( ! empty( $_REQUEST[ $key ] ) ) {
$data[ $key ] = base64_decode( urldecode( $_REQUEST[ $key ] ) );
}
}
return $data;
}
public function render( $return = false ) {
ob_start();
include thrive_product_manager()->path( 'inc/templates/header.phtml' );
if ( count( $this->_errors ) ) {
include thrive_product_manager()->path( 'inc/templates/connection/error.phtml' );
} else {
include thrive_product_manager()->path( 'inc/templates/connection/form.phtml' );
}
$html = ob_get_clean();
if ( $return === true ) {
return $html;
}
echo $html;
}
public function get_data() {
return $this->_data;
}
/**
* @param $data
*
* @return bool
*/
protected function _save_connection( $data ) {
$data['status'] = self::CONNECTED;
$this->_data = $data;
update_option( self::NAME, $data );
delete_option( 'tpm_bk_connection' );
tpm_cron()->log( '_save_connection()' );
if ( ! tpm_cron()->schedule( $this->ttw_expiration ) ) {
add_filter( 'tpm_messages', array( tpm_cron(), 'push_message_event_unscheduled' ) );
}
tpm_delete_transient( 'td_ttw_licenses_details' );
tpm_delete_transient( 'td_ttw_connection_error' );
return true;
}
/**
* Check if data is as expected
*
* @param $data array
*
* @return bool
*/
protected function _is_valid( $data ) {
if ( ! is_array( $data ) ) {
return false;
}
$keys = array_intersect( array_keys( $data ), $this->_expected_data );
return $keys === $this->_expected_data;
}
public function apply_messages( $messages = array() ) {
$messages = array_merge( $messages, $this->_messages );
$this->_messages = array();
update_option( 'tpm_connection_messages', array() );
return $messages;
}
public function push_message( $str, $status ) {
$str = __( $str, Thrive_Product_Manager::T );
$this->_messages[] = array(
'message' => $str,
'status' => $status,
);
update_option( 'tpm_connection_messages', $this->_messages );
}
public function disconnect() {
TPM_Product_List::get_instance()->clear_cache();
TPM_License_Manager::get_instance()->clear_cache();
tpm_cron()->unschedule();
//save the connection data to be used at TPM deactivation plugin
update_option( 'tpm_bk_connection', $this->_data );
tpm_delete_transient( 'td_ttw_licenses_details' );
tpm_delete_transient( 'td_ttw_connection_error' );
return delete_option( self::NAME );
}
public function get_email() {
return $this->ttw_email;
}
public function get_disconnect_url() {
$url = Thrive_Product_Manager::get_instance()->get_admin_url();
$url = add_query_arg( array( 'tpm_disconnect' => 1 ), $url );
return $url;
}
/**
* Checks if token's validation date is lower or equal than now()
*
* @return bool
*/
public function is_expired() {
$date = (int) strtotime( $this->ttw_expiration );
return $date <= time();
}
/**
* Does a request to TTW for a new token and saves it on connection
* - sets a WP Cron
*
* @return bool
*/
public function refresh_token() {
tpm_cron()->log( 'refresh_token()' );
$user_id = $this->ttw_id;
if ( empty( $user_id ) ) {
return false;
}
$ttw_salt = $this->ttw_salt;
if ( empty( $ttw_salt ) ) {
return false;
}
$params = array();
$request = new TPM_Request( '/api/v1/public/refresh-tokens/user/' . $user_id, $params );
$request->set_header( 'Authorization', $ttw_salt );
tpm_cron()->log( var_export( $request, true ) );
$proxy_request = new TPM_Proxy_Request( $request );
$response = $proxy_request->execute( '/tpm/proxy' );
$body = wp_remote_retrieve_body( $response );
tpm_cron()->log( var_export( $body, true ) );
if ( empty( $body ) ) {
return false;
}
$defaults = array(
'success' => false,
'auth_token' => '',
);
$body = json_decode( $body, true );
if ( true === is_array( $body ) ) {
$body = array_merge( $defaults, $body );
} else {
$body = $defaults;
}
if ( empty( $body['auth_token'] ) ) {
return false;
}
! empty( $body['auth_token'] ) ? $this->_data['ttw_salt'] = $body['auth_token'] : null;
! empty( $body['ttw_expiration'] ) ? $this->_data['ttw_expiration'] = $body['ttw_expiration'] : null;
return $this->_save_connection( $this->_data );
}
}

View File

@@ -0,0 +1,207 @@
<?php
/**
* Class TPM_Cron
* WP Cron Event for refreshing TPM Token
* - schedules a cron event to be executed on custom interval at a date defined by TTW
* - when a new token is recived and connection saved a new event will be set
* and the current one unscheduled
*/
final class TPM_Cron {
/**
* @var TPM_Cron
*/
private static $instance;
/**
* Cron hook name
*/
const CRON_HOOK_NAME = 'tpm_cron_hook';
/**
* Name of the Custom Cron Interval
*/
const CRON_INTERVAL_NAME = 'tpm_interval';
/**
* TPM_Cron private constructor to ensure the singleton
*/
private function __construct() {
$this->_init_hooks();
}
/**
* Defines hooks to be loaded once
*/
private function _init_hooks() {
/**
* Cron Hook Definition
*/
add_action( self::CRON_HOOK_NAME, array( $this, 'execute' ) );
/**
* define custom interval for wp cron
*/
add_filter( 'cron_schedules', array( $this, 'cron_interval' ) );
/**
* unschedule cron from DB when TPM is deactivated
*/
add_action(
'admin_init',
function () {
register_deactivation_hook(
WP_PLUGIN_DIR . '/thrive-product-manager/thrive-product-manager.php',
array(
$this,
'unschedule',
)
);
}
);
}
/**
* Pushes a custom interval
*
* @param array $schedules
*
* @return array
*/
public function cron_interval( $schedules ) {
$schedules[ self::CRON_INTERVAL_NAME ] = array(
'interval' => DAY_IN_SECONDS,
'display' => esc_html__( 'Once Daily' ),
);
return $schedules;
}
/**
* Execution of Cron Event
* - fetches a new token from TTW
*/
public function execute() {
tpm_cron()->log( 'execute()' );
TPM_Connection::get_instance()->refresh_token();
}
/**
* Schedule a new Cron Event on a specific date
* - usually specified by TTW
* - unschedules current event before
*
* @param string $date
*
* @return bool
*/
public function schedule( $date ) {
tpm_cron()->log( 'schedule()' );
/**
* when this cron will be executed 1st time
*/
$at = strtotime( $date );
$set = false;
if ( $at < time() ) {
return false;
}
if ( ! $this->unschedule() ) {
return add_filter( 'tpm_messages', array( $this, 'push_message_event_unscheduled' ) );
}
if ( ! wp_next_scheduled( self::CRON_HOOK_NAME ) ) {
$set = wp_schedule_event( $at, self::CRON_INTERVAL_NAME, self::CRON_HOOK_NAME );
}
tpm_cron()->log( "set was " . var_export( $set, true ) . " to execute first time at: " . date( 'Y-m-d H:i:s', $at ) . "\n===========================" );
return $set;
}
/**
* Unschedule current event
* - if it doesn't exist true is returned
*
* @return bool
*/
public function unschedule() {
$timestamp = wp_next_scheduled( self::CRON_HOOK_NAME );
$unset = true;
if ( false !== $timestamp ) {
$unset = wp_unschedule_event( $timestamp, self::CRON_HOOK_NAME );
tpm_cron()->log( 'unschedule event with: ' . var_export( $unset, true ) . ' scheduled at: ' . date( 'Y-m-d H:i:s', $timestamp ) );
}
return $unset;
}
/**
* Push a tpm message to be displayed by JS
* when the cron event cannot be unscheduled
*
* @param $messages
*
* @return array
*/
public function push_message_event_unscheduled( $messages ) {
$messages[] = array(
'status' => 'warning',
'message' => 'A cron event could not be unschedule. Please contact Thrive Themes Support !',
);
return $messages;
}
/**
* Singleton
*
* @return TPM_Cron
*/
public static function get_instance() {
if ( ! self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Log log messages only if the debug mode is ON
*
* @param string $message
*/
public function log( $message ) {
if ( false === Thrive_Product_Manager::is_debug_mode() ) {
return;
}
$filename = WP_CONTENT_DIR . '/cron.log';
file_put_contents( $filename, date( 'Y-m-d H:i:s', time() ) . " => " . $message . "\n", FILE_APPEND );
}
}
/**
* Helper for TPM_Cron Singleton
*
* @return TPM_Cron
*/
function tpm_cron() {
return TPM_Cron::get_instance();
}
tpm_cron();

View File

@@ -0,0 +1,38 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Dashboard {
public static function init() {
/* the priority here must be lower than the one set from thrive-dashboard/version.php */
add_action( 'plugins_loaded', [ __CLASS__, 'load_dash_version' ], 1 );
}
/**
* Check the current version of the dashboard and decide if we load this one or a newer one
*/
public static function load_dash_version() {
$tpm_dash_path = thrive_product_manager()->path() . '/thrive-dashboard';
$tve_dash_file_path = $tpm_dash_path . '/version.php';
if ( is_file( $tve_dash_file_path ) ) {
$version = require_once( $tve_dash_file_path );
$GLOBALS['tve_dash_versions'][ $version ] = array(
'path' => $tpm_dash_path . '/thrive-dashboard.php',
'folder' => '/thrive-product-manager',
'from' => 'plugins',
);
}
}
}

View File

@@ -0,0 +1,411 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_License_Manager {
const NAME = 'tpm_ttw_licenses';
const CACHE_LIFE_TIME = 28800; //8 hours
/**
* @var TPM_License_Manager
*/
protected static $_instance;
/**
* Array of tags set from old licensing system
* Used for backwards compatibility
*
* @var array
*/
protected $_thrive_license;
/**
* List of all licenses the user has on ttw website
*
* @var array
*/
protected $_ttw_licenses = array();
protected $ttw_license_instances = array();
private function __construct() {
$this->_thrive_license = get_option( 'thrive_license', array() );
}
public static function get_instance() {
if ( ! self::$_instance ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Checks if there is a license saved/used for current site and has $product tag
*
* @param $product TPM_Product
*
* @return bool
*/
public function is_licensed( TPM_Product $product ) {
$exists = false;
/**
* @var $license_id int
* @var $license TPM_License
*/
foreach ( TPM_License::get_saved_licenses() as $license_id => $license ) {
if ( $license->has_tag( $product->get_tag() ) ) {
$exists = true;
break;
}
}
return $exists;
}
/**
* Checks in TTW licenses if there is one which has $product tag
*
* @param TPM_Product $product
*
* @return bool
*/
public function is_purchased( TPM_Product $product ) {
//check old licenses
$thrive_license = get_option( 'thrive_license', array() );
if ( in_array( 'all', $thrive_license, false ) || in_array( $product->get_tag(), $thrive_license, false ) ) {
return true;
}
/** @var $license TPM_License */
foreach ( $this->get_ttw_license_instances() as $id => $license ) {
if ( $license->has_tag( $product->get_tag() ) ) {
return true;
}
}
}
public function get_ttw_license_instances() {
if ( ! empty( $this->ttw_license_instances ) ) {
return $this->ttw_license_instances;
}
foreach ( $this->_get_ttw_licenses() as $license_id => $data ) {
$instance = new TPM_License( $license_id, $data['tags'], $data['usage']['used'], $data['usage']['max'] );
$this->ttw_license_instances[ $license_id ] = $instance;
}
return $this->ttw_license_instances;
}
/**
* Based on current connection a request is made to TTW for assigned licenses
*
* @param TPM_Connection $connection
*
* @return array
*/
protected function _get_connection_licenses( TPM_Connection $connection ) {
if ( ! $connection->is_connected() ) {
return array();
}
$licenses = tpm_get_transient( self::NAME );
if ( Thrive_Product_Manager::CACHE_ENABLED && $licenses !== false ) {
return $licenses;
}
$params = array(
'user_id' => $connection->ttw_id,
);
$route = '/api/v1/public/get_licenses';
$request = new TPM_Request( $route, $params );
$request->set_header( 'Authorization', $connection->ttw_salt );
$proxy_request = new TPM_Proxy_Request( $request );
$response = $proxy_request->execute( '/tpm/proxy' );
$body = wp_remote_retrieve_body( $response );
$body = json_decode( $body, true );
if ( ! is_array( $body ) || empty( $body['success'] ) ) {
tpm_set_transient( self::NAME, array(), self::CACHE_LIFE_TIME );
return array();
}
$licenses = $body['data'];
//sort licenses so that the ones with 'all' tags will be 1st in list
//so they have priority on usage
uasort( $licenses, static function ( $license_a, $license_b ) {
$a_tags = is_array( $license_a ) && ! empty( $license_a['tags'] ) && is_array( $license_a['tags'] ) ? $license_a['tags'] : array();
$b_tags = is_array( $license_b ) && ! empty( $license_b['tags'] ) && is_array( $license_b['tags'] ) ? $license_b['tags'] : array();
if ( in_array( 'all', $a_tags, true ) && in_array( 'all', $b_tags, true ) ) {
return 0;
}
if ( false === in_array( 'all', $a_tags, true ) && in_array( 'all', $b_tags, true ) ) {
return 1;
}
return - 1;
} );
tpm_set_transient( self::NAME, $licenses, self::CACHE_LIFE_TIME );
return $licenses;
}
/**
* Searches in all licenses user has bought on TTW site
*
* @param TPM_Product $product
*
* @return int|null
*/
public function get_product_license( TPM_Product $product ) {
/** @var TPM_License $license */
foreach ( $this->get_ttw_license_instances() as $license ) {
if ( $license->has_tag( $product->get_tag() ) && $license->get_used() < $license->get_max() ) {
return $license->get_id();
}
}
return null;
}
/**
* If $products have a license id assigned then
* - a request to TTW is made to increase the usage of the license/licenses
*
* @param array $products tag
*
* @return array|bool
*/
public function activate_licenses( $products = array() ) {
if ( empty( $products ) ) {
return false;
}
$licenses_ids = array();
$product_tags = array();
/** @var TPM_Product $product */
foreach ( $products as $product ) {
$product_tags[ $product->get_tag() ] = false;
$id = $product->get_license();
if ( ! empty( $id ) ) {
$licenses_ids[] = $id;
}
}
$licenses_ids = array_filter( $licenses_ids );
$licenses_ids = array_unique( $licenses_ids );
if ( empty( $licenses_ids ) ) {
return false;
}
$params = array(
'user_id' => TPM_Connection::get_instance()->ttw_id,
'user_site_url' => get_site_url(),
'data' => $licenses_ids,
);
$request = new TPM_Request( '/api/v1/public/license_uses', $params );
$request->set_header( 'Authorization', TPM_Connection::get_instance()->ttw_salt );
$proxy_request = new TPM_Proxy_Request( $request );
$response = $proxy_request->execute( '/tpm/proxy' );
if ( is_wp_error( $response ) ) {
return false;
}
$body = wp_remote_retrieve_body( $response );
$result = json_decode( $body, true );
if ( ! is_array( $result ) || ! isset( $result['success'] ) || ! isset( $result['data'] ) || ! is_array( $result['data'] ) ) {
return false;
}
$ttw_licenses = $this->_get_ttw_licenses();
foreach ( $result['data'] as $license_id => $activated ) {
if ( ! array_key_exists( $license_id, $ttw_licenses ) ) {
continue;
}
$license = $ttw_licenses[ $license_id ];
$license_instance = new TPM_License( $license_id, $license['tags'] );
if ( $activated === true ) {
$license_instance->save();
//prepare response
foreach ( $product_tags as $tag => $value ) {
if ( $license_instance->has_tag( $tag ) ) {
$product_tags[ $tag ] = true;
}
}
}
}
return $product_tags;
}
/**
* @return array
*/
protected function _get_ttw_licenses() {
if ( empty( $this->_ttw_licenses ) ) {
$this->_ttw_licenses = $this->_get_connection_licenses( TPM_Connection::get_instance() );
}
return $this->_ttw_licenses;
}
/**
* @param $license_id
*
* @return TPM_License|null;
*/
public function get_license_instance( $license_id ) {
$license_id = (int) $license_id;
if ( empty( $license_id ) ) {
return null;
}
$license = null;
$list = TPM_License::get_saved_licenses();
/** @var TPM_License $item */
foreach ( $list as $item_id => $item ) {
if ( $item->get_id() === $license_id ) {
$license = $item;
break;
}
}
return $license;
}
public function license_deactivate( WP_REST_Request $request ) {
$authorization = $request->get_param( 'Authorization' );
$connection = TPM_Connection::get_instance();
$tpm_token = $connection->decrypt( get_option( 'tpm_token', null ) );
if ( $authorization !== $tpm_token ) {
return array(
'success' => false,
'message' => 'No permission',
);
}
$deactivated = true;
$message = 'License deactivated with success';
$response = array(
'success' => $deactivated,
'message' => $message,
);
$license_id = (int) $request->get_param( 'id' );
if ( empty( $license_id ) ) {
$response['success'] = false;
$response['message'] = 'Invalid param license id ' . $request->get_param( 'id' );
return $response;
}
$license = $this->get_license_instance( $license_id );
if ( ! ( $license instanceof TPM_License ) ) {
$response['success'] = true;
$response['message'] = "Couldn't find any license with ID " . $request->get_param( 'id' );
return $response;
}
if ( $license->delete() !== true ) {
$response['success'] = false;
$response['message'] = "Couldn't not deactivate license " . $request->get_param( 'id' );
}
TPM_Product_List::get_instance()->clear_cache();
self::get_instance()->clear_cache();
return $response;
}
public function clear_cache() {
return tpm_delete_transient( self::NAME );
}
/**
* Deletes the local saved licenses
* - increments the usages for licenses by doing a request to TTW
*/
public function deactivate_all_licenses() {
$licenses = TPM_License::get_saved_licenses();
if ( empty( $licenses ) ) {
return;
}
$connection = TPM_Connection::get_instance();
//if user has disconnected TPM then try to use the backup connection saved at disconnecting
if ( false === $connection->is_connected() ) {
$connection->set_data( get_option( 'tpm_bk_connection', array() ) );
}
$params = array(
'user_id' => $connection->ttw_id,
'user_site_url' => get_site_url(),
'direction' => 'down',
'data' => array_keys( $licenses ),
);
$request = new TPM_Request( '/api/v1/public/license_uses', $params );
$request->set_header( 'Authorization', $connection->ttw_salt );
$proxy_request = new TPM_Proxy_Request( $request );
$response = $proxy_request->execute( '/tpm/proxy' );
TPM_Log_Manager::get_instance()->set_message( var_export( $response, true ) )->log();
delete_option( TPM_License::NAME );
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_License {
const NAME = 'tpm_licenses';
/** @var integer */
protected $id = 0;
/** @var array */
protected $tags = array();
/** @var int */
protected $used = 0;
/** @var int */
protected $max = 0;
public function __construct( $id, $tags, $used = 0, $max = 0 ) {
$this->id = (int) $id;
$this->used = (int) $used;
$this->max = (int) $max;
if ( is_array( $tags ) ) {
$this->tags = $tags;
}
}
/**
* @param $tag string
*
* @return bool
*/
public function has_tag( $tag ) {
return in_array( $tag, $this->tags ) || in_array( 'all', $this->tags );
}
public function get_id() {
return $this->id;
}
public function get_max() {
return (int) $this->max;
}
public function get_used() {
return (int) $this->used;
}
public function save() {
$current_licenses = get_option( self::NAME, array() );
$current_licenses[ $this->id ] = $this->tags;
update_option( self::NAME, $current_licenses );
return true;
}
public function delete() {
$current_licenses = get_option( self::NAME, array() );
if ( isset( $current_licenses[ $this->id ] ) ) {
unset( $current_licenses[ $this->id ] );
}
update_option( self::NAME, $current_licenses );
return true;
}
/**
* Fetches a list of licenses which are used on current site
* - each license may have more tags
*
* @return TPM_License[]
*/
public static function get_saved_licenses() {
$licenses = array();
foreach ( get_option( self::NAME, array() ) as $license_id => $tags ) {
$licenses[ $license_id ] = new self( $license_id, $tags );
}
return $licenses;
}
/**
* Checks of max is strict greater than used
*
* @return bool
*/
public function has_usages() {
return $this->get_max() > $this->get_used();
}
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Log_Manager {
const FILE_NAME = 'tpm.log';
protected $_message;
protected static $_instance;
private function __construct() {
}
public static function get_instance() {
if ( empty( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
protected function _is_valid() {
return ! empty( $this->_message );
}
/**
* @param $message string|WP_Error
*
* @return $this
*/
public function set_message( $message ) {
if ( is_wp_error( $message ) ) {
$message = $message->get_error_message();
}
$this->_message = $message;
return $this;
}
public function log() {
if ( ! $this->_is_valid() ) {
return false;
}
return $this->_write();
}
protected function _get_file() {
return thrive_product_manager()->path( self::FILE_NAME );
}
protected function _write() {
$bytes = 0;
if ( Thrive_Product_Manager::is_debug_mode() && wp_is_writable( $this->_get_file() ) ) {
$bytes = file_put_contents( $this->_get_file(), "\n" . "[" . date( 'Y-m-d h:i:s' ) . "] " . $this->_message, FILE_APPEND );
}
return $bytes !== false;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Message {
protected $_instance;
protected $_messages = array();
private function __construct() {
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Page_Manager {
protected static $_instance;
private function __construct() {
}
public function render() {
if ( TPM_Connection::get_instance()->is_connected() === false ) {
TPM_Connection::get_instance()->render();
} else {
TPM_Product_List::get_instance()->render();
}
}
public static function get_instance() {
if ( ! self::$_instance ) {
self::$_instance = new self();
}
return self::$_instance;
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Plugin_Installer_Skin extends Plugin_Installer_Skin {
public $done_header = true;
public $done_footer = true;
public $messages = array();
public function request_filesystem_credentials( $error = false, $context = false, $allow_relaxed_file_ownership = false ) {
return $this->options;
}
public function feedback( $string, ...$args ) {
if ( empty( $string ) ) {
return;
}
$this->messages[] = $string;
}
}

View File

@@ -0,0 +1,190 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Product_List {
const NAME = 'tpm_all_ttw_products';
const CACHE_LIFE_TIME = WEEK_IN_SECONDS;
protected $_products = array();
public static $type_to_tag_dependencies = array(
'skin' => array( 'ttb' ), // a skin has a dependency on TTB
);
protected static $_instance;
private function __construct() {
}
public static function get_instance() {
if ( empty( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
public function render( $return = false ) {
ob_start();
include thrive_product_manager()->path( 'inc/templates/header.phtml' );
include thrive_product_manager()->path( 'inc/templates/product/list.phtml' );
$html = ob_get_clean();
if ( $return === true ) {
return $html;
}
echo $html;
}
protected function _get_products() {
if ( empty( $this->_products ) ) {
$this->_products = $this->_get_all_ttw_products();
}
foreach ( $this->_products as &$product ) {
$instance = $this->_product_factory( $product );
$product['status'] = $instance->get_status();
if ( isset( self::$type_to_tag_dependencies[ $product['type'] ] ) ) {
$product['dependencies'] = self::$type_to_tag_dependencies[ $product['type'] ];
}
}
return $this->_products;
}
public function get_products_array() {
return array_values( $this->_get_products() );
}
/**
* @return array
*/
protected function _get_all_ttw_products() {
if ( ! TPM_Connection::get_instance()->is_connected() ) {
return array();
}
if ( Thrive_Product_Manager::CACHE_ENABLED && ( $products = tpm_get_transient( self::NAME ) ) !== false ) {
return $products;
}
$connection = TPM_Connection::get_instance();
$params = array(
'user_id' => $connection->ttw_id,
'tpm_version' => Thrive_Product_Manager::V,
);
$request = new TPM_Request( '/api/v1/public/get_products', $params );
$request->set_header( 'Authorization', $connection->ttw_salt );
$proxy_request = new TPM_Proxy_Request( $request );
$response = $proxy_request->execute( '/tpm/proxy' );
$body = wp_remote_retrieve_body( $response );
$body = json_decode( $body, true );
$products = array();
if ( is_array( $body ) && ! empty( $body['data'] ) ) {
foreach ( $body['data'] as $product_data ) {
$product = $this->_product_factory( $product_data );
$products[ $product->get_tag() ] = $product->to_array();
}
}
if ( ! empty( $products ) ) {
tpm_set_transient( self::NAME, $products, self::CACHE_LIFE_TIME );
}
return $products;
}
/**
* @param $data
*
* @return TPM_Product_Plugin|TPM_Product_Theme|TPM_Product_Skin|TPM_Product
*/
protected function _product_factory( $data ) {
if ( ! is_array( $data ) || empty( $data ) ) {
$data = array();
}
$instance_name = 'TPM_Product';
//defaults
$name = 'No name';
$description = 'No description';
$logo_url = 'https://thrivethemes.com/wp-content/uploads/2016/10/thrive-themes-logo-home-2.png';
$type = '';
$tag = '';
$api_slug = '';
$file = '';
extract( $data );
if ( empty( $type ) || ! in_array( $type, array( 'plugin', 'theme', 'skin' ) ) ) {
return new TPM_Product( $name, $description, $logo_url, $tag, $api_slug, $file );
}
$instance_name .= '_' . ucfirst( $type );
if ( $tag === 'ttb' ) {
$instance_name .= '_Builder';
} elseif ( $tag === 'tap' ) {
$instance_name .= '_Automator';
}
$instance = new $instance_name( $name, $description, $logo_url, $tag, $api_slug, $file );
return $instance;
}
/**
* Create a TPM_Product instance based on $tag string
*
* @param string $tag
*
* @return TPM_Product|TPM_Product_Plugin|TPM_Product_Skin|TPM_Product_Theme
*/
public function get_product_instance( $tag ) {
$ttw_products = $this->_get_products();
$product_data = ! empty( $ttw_products[ $tag ] )
? $ttw_products[ $tag ]
: array(
'tag' => $tag,
);
return $this->_product_factory( $product_data );
}
/**
* Deletes transient for TTW Products
* - TTW Product list will be fetched
*/
public function clear_cache() {
tpm_delete_transient( self::NAME );
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package ${NAMESPACE}
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class fro Thrive Automator
* - which extends and overwrites the Thrive Plugin
* - TAP is a free product of TTW
*/
class TPM_Product_Plugin_Automator extends TPM_Product_Plugin {
/**
* @return true because this product offered by TTW as free
*/
public function is_purchased() {
return true;
}
/**
* @return true because this product offered by TTW as free
*/
public function is_licensed() {
return true;
}
}

View File

@@ -0,0 +1,152 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Product_Plugin extends TPM_Product {
/**
* Checks if product is installed/downloaded in WP_PLUGIN_DIR
*
* @return bool
*/
public function is_installed() {
if ( empty( $this->file ) ) {
return false;
}
$path = rtrim( WP_PLUGIN_DIR, '/' ) . '/' . trim( $this->file, '/' );
return file_exists( $path );
}
/**
* Returns array of its properties
*
* @return array
*/
public function to_array() {
$data = parent::to_array();
$data['type'] = 'plugin';
return $data;
}
protected function _get_download_url() {
$result = $this->_prepare_download_url();
if ( is_wp_error( $result ) ) {
return $this->_prepare_download_url( true );
}
return $result;
}
/**
* This method will prepare the download URL when someone tries to download any of the Thrive Themes products from TPM.
*
* @param boolean $with_ssl_verify
* @return void
*/
private function _prepare_download_url( $with_ssl_verify = false ) {
$options = [
'timeout' => 20, //seconds
'sslverify' => $with_ssl_verify,
'headers' => [
'Accept' => 'application/json',
],
];
/**
* prepare the POST parameters
*/
$options['body'] = [
'api_slug' => $this->api_slug,
];
$url = add_query_arg( [ 'p' => $this->_get_hash( $options['body'] ) ], 'https://service-api.thrivethemes.com/plugin/update' );
$result = wp_remote_post( $url, $options );
if ( ! is_wp_error( $result ) ) {
$info = json_decode( wp_remote_retrieve_body( $result ), true );
if ( ! empty( $info ) ) {
return $info['download_url'];
}
}
return new WP_Error( '400', wp_remote_retrieve_body( $result ) );
}
/**
* @param $credentials array
*
* @return bool|WP_Error
*/
public function install( $credentials ) {
if ( $this->is_installed() ) {
return true;
}
add_filter( 'upgrader_package_options', array( $this, 'upgrader_package_options' ) );
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
$url = $this->_get_download_url();
if ( is_wp_error( $url ) ) {
$error = "Couldn't get download URL for " . $this->name;
TPM_Log_Manager::get_instance()->set_message( $error )->log();
return new WP_Error( 'download_url', $error );
}
/** @var $wp_filesystem WP_Filesystem_Base */
global $wp_filesystem;
$connected = WP_Filesystem( $credentials );
if ( $connected === false ) {
return $wp_filesystem->errors;
}
require_once __DIR__ . '/class-tpm-plugin-installer-skin.php';
$installer = new Plugin_Upgrader( new TPM_Plugin_Installer_Skin( $credentials ) );
$result = $installer->install( $url );
remove_filter( 'upgrader_package_options', array( $this, 'upgrader_package_options' ) );
return $result;
}
public function upgrader_package_options( $options ) {
$options['clear_destination'] = true;
return $options;
}
public function is_activated() {
return is_plugin_active( $this->file );
}
public function activate() {
if ( $this->is_activated() ) {
return true;
}
return activate_plugin( $this->file );
}
}

View File

@@ -0,0 +1,284 @@
<?php
/**
* Class TPM_Product_Skin
* Beside Plugins and Themes TPM offers Thrive Theme Builder Skins
* Which are handled by this class and are known as TTB Themes
*/
class TPM_Product_Skin extends TPM_Product_Theme {
/**
* The default skin which will be installed together with the theme
* This is also used in TTB
*/
const DEFAULT_TAG = 'q1qj01';
/**
* @var WP_Term
*/
protected $ttb_skin;
/**
* @var [WP_Term]
*/
protected $ttb_downloaded_skins = array();
/**
* @return array
*/
public function to_array() {
$data = parent::to_array();
$data['type'] = 'skin';
return $data;
}
/**
* Download and install the current skin
* - TTB API is used which TTB is required to be installed and activated
*
* @param array $credentials
*
* @return bool|WP_Error
* @see activate()
*
*/
public function install( $credentials ) {
/* Before installing the skin we need to make sure the theme code is available */
$this->include_thrive_theme();
$response = $this->_install_ttb_skin( $this->api_slug );
if ( true === $response instanceof WP_Term ) {
$this->ttb_skin = $response;
}
return $response;
}
/**
* Include TTB & TAR code in order to be able to do the skin install without the theme being active
* Hope this behaves well in the wild :)
*/
public function include_thrive_theme() {
global $thrive_theme;
if ( false === empty( $thrive_theme ) ) {
return;
}
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );
/**
* We are changing this constant because in the theme we are using get_template_directory() - which is based on the active theme
* And in this case the theme is not active
*/
defined( 'THEME_PATH' ) || define( 'THEME_PATH', get_theme_root() . '/thrive-theme' );
defined( 'TVE_TCB_ROOT_PATH ' ) || define( 'TVE_TCB_ROOT_PATH ', get_theme_root() . '/thrive-theme/architect/' );
if ( ! defined( 'TVE_TCB_CORE_INCLUDED' ) ) {
include_once THEME_PATH . '/architect/plugin-core.php';
}
if ( false === defined( 'TVE_DASH_VERSION' ) ) {
define( 'TVE_DASH_PATH', THEME_PATH . '/thrive-dashboard' );
require_once TVE_DASH_PATH . '/thrive-dashboard.php';
}
require_once THEME_PATH . '/inc/constants.php';
require_once THEME_PATH . '/inc/classes/class-thrive-theme.php';
$thrive_theme = new Thrive_Theme();
$thrive_theme->init();
}
/**
* Uses TTB to activate current skin
*
* @return bool|WP_Error
*/
public function activate() {
if ( $this->is_activated() ) {
return true;
}
$skin = $this->_get_ttb_skin();
if ( false === $skin instanceof WP_Term ) {
return new WP_Error( 400, sprintf( __( 'Could not activate skin: %s', Thrive_Product_Manager::T ), $this->name ) );
}
$skin_id = $skin->term_id;
Thrive_Skin_Taxonomy::set_skin_active( $skin_id );
/* We need to make sure that the instance is the one with the active skin before we generate the css file */
thrive_skin( $skin_id )->generate_style_file();
return true;
}
/**
* The skin is installed if the theme is installed
*
* @return bool
*/
public function is_installed() {
$theme = wp_get_theme( 'thrive-theme' );
return ! is_wp_error( $theme->errors() );
}
/**
* Check if the skin exists
*
* @return bool
*/
public function exists() {
$installed = false;
$skins = $this->_get_all_downloaded_skins();
foreach ( $skins as $skin ) {
if ( ! empty( $skin->tag ) && $skin->tag === $this->api_slug ) {
$installed = true;
break;
}
}
return $installed;
}
/**
* @return WP_Term[]
*/
protected function _get_all_downloaded_skins() {
if ( false === class_exists( 'Thrive_Skin_Taxonomy', false ) ) {
return $this->ttb_downloaded_skins;
}
if ( empty( $this->ttb_downloaded_skins ) ) {
$this->ttb_downloaded_skins = Thrive_Skin_Taxonomy::get_all();
}
return $this->ttb_downloaded_skins;
}
/**
* Gets the current Thrive_Skin instance
* - instance exists if the current flow is install one
*
* @return WP_Term|null
*/
protected function _get_ttb_skin() {
if ( false === $this->ttb_skin instanceof WP_Term ) {
return null;
}
return $this->ttb_skin;
}
/**
* Uses TTB API to install a skin
*
* @param $skin_id
*
* @return WP_Term|WP_Error on error
*/
protected function _install_ttb_skin( $skin_id ) {
if ( false === class_exists( 'Thrive_Theme_Cloud_Api_Factory', false ) ) {
return new WP_Error( 400, sprintf( __( 'Could not install Theme: %s', Thrive_Product_Manager::T ), $this->name ) );
}
try {
/**
* Try to create some default data for TTB cos it ain't created on try_install_activate request for TTB
*/
if ( class_exists( 'Thrive_Theme_Default_Data', false ) ) {
Thrive_Theme_Default_Data::create_default();
}
$zip = Thrive_Theme_Cloud_Api_Factory::build( 'skins' )->download_item( $skin_id, null );
$import = new Thrive_Transfer_Import( $zip );
$response = $import->import( 'skin' );
} catch ( Exception $e ) {
$response = new WP_Error( 400, $e->getMessage() );
}
return $response;
}
/**
* Checks if current skin is active for TTB
*
* @return bool
*/
public function is_activated() {
$skin_activated = false;
if ( class_exists( 'Thrive_Skin', false ) ) {
$current_skin = new Thrive_Skin( 0 ); //current active skin in TTB
$skin_activated = $current_skin->get_tag() === $this->api_slug;
}
return $skin_activated;
}
public function get_status() {
if ( ! empty( $this->status ) ) {
return $this->status;
}
if ( ! $this->is_purchased() ) {
$this->status = self::AVAILABLE;
return $this->status;
}
if ( ! $this->is_licensed() ) {
$this->status = self::TO_LICENSE;
return $this->status;
}
if ( ! $this->is_installed() ) {
$this->status = self::TO_INSTALL;
return $this->status;
}
if ( ! $this->is_activated() ) {
$this->status = self::TO_ACTIVATE;
return $this->status;
}
$this->status = self::READY;
return $this->status;
}
/**
* When installing the skin, change the response data
*
* @param array $data
*
* @return array|mixed
*/
public function before_response( $data ) {
return $this->get_response_status( 'installed' );
}
}

View File

@@ -0,0 +1,185 @@
<?php
class TPM_Product_Theme_Builder extends TPM_Product_Theme {
public function to_array() {
$data = parent::to_array();
$data['type'] = 'theme';
$data['hidden'] = true;
return $data;
}
/**
* Finds out URL where to download the zip from
*
* @param string $api_slug
*
* @return WP_Error|string url
*/
protected function _get_download_url( $api_slug ) {
$request = array(
'sslverify' => false,
'body' => array(
'action' => 'theme_update',
'type' => 'latest',
),
'timeout' => 60,
);
$thrive_update_api_url = add_query_arg( array(
'p' => $this->_get_hash( $request['body'] ),
), 'https://service-api.thrivethemes.com/theme/update' );
$result = wp_remote_get( $thrive_update_api_url, $request );
if ( ! is_wp_error( $result ) ) {
$info = @unserialize( wp_remote_retrieve_body( $result ) );
if ( Thrive_Product_Manager::is_debug_mode() ) {
$package = defined( 'TTB_TEST_ARCHIVE' ) ? TTB_TEST_ARCHIVE : '';
}
if ( empty( $package ) ) {
$package = ! empty( $info['package'] ) ? $info['package'] : new WP_Error( '404', 'Bad request' );
}
return $package;
}
return new WP_Error( '400', $result->get_error_message() );
}
/**
* Activates TTB
*
* @return bool|WP_Error
*/
public function activate() {
if ( ! $this->previously_installed ) {
return true;
}
$activated = $this->is_activated();
if ( ! $activated && $this->is_installed() ) {
$theme = wp_get_theme( 'thrive-theme' );
$activated = true;
switch_theme( $theme->get_stylesheet() );
}
return $activated;
}
/**
* Install Theme Builder
*
* @param array $credentials
*
* @return array|bool|WP_Error|WP_Term
*/
public function install( $credentials ) {
$installed = parent::install( $credentials );
/* If the theme builder install went ok, we will install also the default skin */
if ( $installed && ! $this->previously_installed && ! is_wp_error( $installed ) ) {
$skin = TPM_Product_List::get_instance()->get_product_instance( TPM_Product_Skin::DEFAULT_TAG );
$installed = $skin->install( $credentials );
if ( ! is_wp_error( $installed ) ) {
static::set_fresh_install_flag( 1 );
}
}
return $installed;
}
/**
* Set a flag to let the theme know if the user installed TTB for the first time
* Also called from TTB
*
* @param $value
*/
public static function set_fresh_install_flag( $value ) {
update_option( 'thrive_theme_is_fresh_install', $value );
}
/**
* Check if the fresh install flag is set, defaulting to 0. Also called from TTB
* @return bool
*/
public static function is_fresh_install() {
return (int) get_option( 'thrive_theme_is_fresh_install', 0 ) === 1;
}
/**
* Used in frontend/js
*
* @return string
*/
public static function get_dashboard_url() {
return admin_url( 'admin.php?page=thrive-theme-dashboard' );
}
/**
* Check if the TTB with slug thrive-theme is installed
*
* @return bool
*/
public function is_installed() {
$theme = wp_get_theme( 'thrive-theme' );
return ! is_wp_error( $theme->errors() );
}
/**
* Change the response after installing / activating theme builder
*
* @param array $data
*
* @return array|mixed
*/
public function before_response( $data ) {
return $this->get_response_status( empty( $this->previously_installed ) ? 'installed' : 'ready' );
}
public function get_status() {
if ( ! empty( $this->status ) ) {
return $this->status;
}
if ( ! $this->is_purchased() ) {
$this->status = self::AVAILABLE;
return $this->status;
}
if ( ! $this->is_installed() ) {
$this->status = self::TO_INSTALL;
return $this->status;
}
if ( ! $this->is_activated() ) {
return $this->status = self::TO_ACTIVATE;
}
if ( ! $this->is_licensed() ) {
$this->status = self::TO_LICENSE;
return $this->status;
}
$this->status = self::READY;
return $this->status;
}
}

View File

@@ -0,0 +1,157 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Product_Theme extends TPM_Product {
/**
* Keep a flag to check if the theme was installed before
*
* @var bool
*/
protected $previously_installed = false;
public function get_status() {
if ( ! empty( $this->status ) ) {
return $this->status;
}
if ( ! $this->is_purchased() ) {
$this->status = self::AVAILABLE;
return $this->status;
}
if ( ! $this->is_installed() ) {
$this->status = self::TO_INSTALL;
return $this->status;
}
if ( ! $this->is_licensed() ) {
$this->status = self::TO_LICENSE;
return $this->status;
}
if ( $this->is_activated() ) {
$this->status = self::ACTIVATED;
return $this->status;
}
$this->status = self::READY;
return $this->status;
}
public function is_activated() {
/** @var WP_Theme $current_theme */
$current_theme = wp_get_theme();
return $this->name === $current_theme->get( 'Name' );
}
public function is_installed() {
$theme = wp_get_theme( $this->api_slug );
return ! is_wp_error( $theme->errors() );
}
public function to_array() {
$data = parent::to_array();
$data['type'] = 'theme';
return $data;
}
protected function _get_download_url( $api_slug ) {
global $wp_version;
$args = array(
'slug' => $api_slug,
'version' => '1.0',
);
$request = array(
'sslverify' => false,
'body' => array(
'action' => 'theme_update',
'request' => serialize( $args ),
'api-key' => md5( home_url() ),
),
'timeout' => 30,
'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url(),
);
$thrive_update_api_url = add_query_arg(
array(
'p' => $this->_get_hash( $request['body'] ),
),
'https://service-api.thrivethemes.com/theme/update'
);
$result = wp_remote_post( $thrive_update_api_url, $request );
if ( ! is_wp_error( $result ) ) {
$info = @unserialize( wp_remote_retrieve_body( $result ) );
if ( ! empty( $info ) ) {
return $info['package'];
}
}
return new WP_Error( '400', $result->get_error_message() );
}
public function install( $credentials ) {
if ( $this->is_installed() ) {
$this->previously_installed = true;
return true;
}
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
$url = $this->_get_download_url( $this->api_slug );
global $wp_filesystem;
$connected = WP_Filesystem( $credentials );
if ( false === $connected ) {
return $wp_filesystem->errors;
}
require_once __DIR__ . '/class-tpm-theme-installer-skin.php';
$skin = new TPM_Theme_Installer_Skin( $credentials );
$installer = new Theme_Upgrader( $skin );
$installed = $installer->install( $url );
if ( null === $installed ) {
/** @var TPM_Theme_Installer_Skin $installer ->skin */
$installed = new WP_Error( '500', end( $installer->skin->messages ) );
}
return $installed;
}
/**
* @param $previously_installed
*/
public function set_previously_installed( $previously_installed ) {
$this->previously_installed = $previously_installed;
}
}

View File

@@ -0,0 +1,216 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Product {
const AVAILABLE = 'available'; //product has been purchased by the user and there is a license for it
const INSTALLED = 'installed'; //product is downloaded in its folder
const ACTIVATED = 'activated'; //product is downloaded in its folder and WP knows it as activated
const READY = 'ready'; //product is installed/activated/licensed and ready to be used
const TO_INSTALL = 'to_install'; //product is not downloaded in its folder
const TO_ACTIVATE = 'to_activate'; //product is downloaded in its folder but not activated
const TO_LICENSE = 'to_license'; //product has to be licensed
protected $name;
protected $description;
protected $logo_url;
protected $tag;
protected $file;
protected $api_slug;
protected $status;
protected $_license_id;
public function __construct( $name, $description, $logo_url, $tag, $api_slug, $file ) {
$this->name = $name;
$this->description = $description;
$this->logo_url = $logo_url;
$this->tag = $tag;
$this->api_slug = $api_slug;
$this->file = $file;
}
public function to_array() {
$data = array(
'name' => $this->name,
'description' => empty( $this->description ) ? $this->name : $this->description,
'logo_url' => $this->logo_url,
'tag' => $this->tag,
'api_slug' => $this->api_slug,
'file' => $this->file,
'hidden' => false,
);
return $data;
}
/**
* Checks if its tag exists somewhere in DB and
*
* @return bool
*/
public function is_licensed() {
$thrive_license = get_option( 'thrive_license', array() );
$backwards = in_array( $this->get_tag(), $thrive_license ) || in_array( 'all', $thrive_license );
return $backwards || TPM_License_Manager::get_instance()->is_licensed( $this );
}
/**
* Product is installed and activated physically on WP site
*
* @return bool
*/
public function is_activated() {
return false;
}
/**
* @return bool
*/
public function is_installed() {
return false;
}
/**
* Checks in TTW licenses if there is one which has $product tag
*
* @return bool
*/
public function is_purchased() {
return TPM_License_Manager::get_instance()->is_purchased( $this );
}
/**
* We care only for statuses which are relate to TTW license
* - available (not purchased)
* - purchased
* - licensed
*
* @return string
*/
public function get_status() {
if ( ! empty( $this->status ) ) {
return $this->status;
}
if ( ! $this->is_purchased() ) {
return $this->status = self::AVAILABLE;
}
if ( ! $this->is_installed() ) {
return $this->status = self::TO_INSTALL;
}
if ( ! $this->is_activated() ) {
return $this->status = self::TO_ACTIVATE;
}
if ( ! $this->is_licensed() ) {
return $this->status = self::TO_LICENSE;
}
return $this->status = self::READY;
}
public function get_tag() {
return $this->tag;
}
public function get_name() {
return $this->name;
}
/**
* @param $credentials array
*
* @return bool|WP_Error
*/
public function install( $credentials ) {
return new WP_Error( 'empty_product_install', 'This product cannot be installed' );
}
public function activate() {
return false;
}
public function search_license() {
$license_id = TPM_License_Manager::get_instance()->get_product_license( $this );
$this->_license_id = $license_id;
}
public function set_license( $id ) {
$this->_license_id = (int) $id;
}
public function get_license() {
return $this->_license_id;
}
protected function _get_hash( $data ) {
$key = '@#$()%*%$^&*(#@$%@#$%93827456MASDFJIK3245';
return md5( $key . serialize( $data ) . $key );
}
/**
* Change the response before sending it
*
* @param array $data
*
* @return mixed
*/
public function before_response( $data ) {
return $data;
}
/**
* Get a comprehensive response message based on a status
*
* @param string $status
*
* @return array
*/
public function get_response_status( $status ) {
switch ( $status ) {
case self::READY:
$data['status'] = self::READY;
$data['message'] = sprintf( '%s is now ready to use', $this->get_name() );
break;
case self::INSTALLED:
$data['status'] = self::INSTALLED;
$data['message'] = sprintf( '%s is now installed successfully', $this->get_name() );
break;
default:
$data = array();
break;
}
return $data;
}
}

View File

@@ -0,0 +1,98 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TPM_Proxy_Request
* Decorator for TPM_Request
*/
class TPM_Proxy_Request {
const URL = 'https://service-api.thrivethemes.com';
const API_PASS = '!!@#ThriveIsTheBest123$$@#';
const API_KEY = '@(#$*%)^SDFKNgjsdi870234521SADBNC#';
protected $secret_key = '@#$()%*%$^&*(#@$%@#$%93827456MASDFJIK3245';
/** @var TPM_Request */
protected $request;
public function __construct( TPM_Request $request ) {
$this->request = $request;
}
public function execute( $route ) {
// Allow bypassing proxy server
if ( defined( 'TPM_BYPASS_PROXY' ) && TPM_BYPASS_PROXY ) {
return $this->request->execute();
}
$params['body'] = $this->request->get_body();
$params['headers'] = $this->request->get_headers();
$params['url'] = $this->request->get_url();
$params['pw'] = self::API_PASS;
$headers = array(
'X-Thrive-Authenticate' => $this->_buildAuthString( $params ),
);
$args = array(
'headers' => $headers,
'body' => $params,
'timeout' => 30,
'sslverify' => false,
);
$url = add_query_arg( array(
'p' => $this->_calc_hash( $params ),
), trim( $this->_get_url(), '/' ) . '/' . ltrim( $route, '/' ) );
$response = wp_remote_post( $url, $args );
if ( is_wp_error( $response ) ) {
$args['sslverify'] = true;
$response = wp_remote_post( $url, $args );
return $response;
}
return $response;
}
protected function _get_url() {
if ( defined( 'TPM_DEBUG' ) && TPM_DEBUG === true && defined( 'TVE_CLOUD_URL' ) ) {
return TVE_CLOUD_URL;
}
return self::URL;
}
protected function _calc_hash( $params ) {
return md5( $this->secret_key . serialize( $params ) . $this->secret_key );
}
protected function _buildAuthString( $data = null ) {
$string = '';
foreach ( $data as $field => $value ) {
if ( is_array( $value ) ) {
$value = serialize( $value );
}
$string .= $field . '=' . $value;
$string .= '|' . self::API_KEY . '|';
}
return md5( $string );
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Request {
protected $url;
protected $args
= array(
'headers' => array(
'Content-Type' => 'application/json',
),
'timeout' => 20,
);
protected $params = array();
protected $route;
public function __construct( $route, $params ) {
$this->route = $route;
$this->params = $params;
$this->url = Thrive_Product_Manager::get_ttw_url();
}
public function execute() {
$this->args['body'] = $this->get_body();
return wp_remote_post( $this->get_url(), $this->args );
}
public function get_body() {
return json_encode( $this->params );
}
public function get_params() {
return $this->params;
}
public function set_header( $name, $value ) {
$this->args['headers'][ $name ] = $value;
}
public function get_headers() {
return $this->args['headers'];
}
public function get_url() {
$url = trim( $this->url, '/' ) . '/' . trim( $this->route, '/' );
return $url;
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-product-manager
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TPM_Theme_Installer_Skin extends Theme_Installer_Skin {
public $done_header = true;
public $done_footer = true;
public $messages = array();
public function request_filesystem_credentials( $error = false, $context = false, $allow_relaxed_file_ownership = false ) {
return $this->options;
}
public function feedback( $string, ...$args ) {
if ( empty( $string ) ) {
return;
}
$this->messages[] = $string;
}
}