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,278 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
if ( ! class_exists( 'App_Notification' ) ) {
class App_Notification {
protected $namespace = 'tve-dash/v1';
protected $class_path;
protected $base_path;
protected $template_path;
protected $current_page;
/**
* @var App_Notification
*/
public static $_instance;
/**
* App_Notification constructor.
*/
private function __construct() {
$this->base_path = dirname( dirname( __FILE__ ) );
$this->class_path = $this->base_path . '/classes';
$current_page = isset( $_GET['page'] ) ? $_GET['page'] : '';
$this->current_page = isset( $_GET['action'] ) ? $_GET['action'] : $current_page;
$this->template_path = $this->base_path . '/templates';
$this->_load();
$this->_hooks();
}
/**
* Singleton instance
*
* @return App_Notification
*/
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Enqueue notification scripts
*/
public function tve_dash_enqueue_notification_scripts() {
$limit = 10;
$offset = 0;
$js_prefix = tve_dash_is_debug_on() ? '.js' : '.min.js';
$notifications = ( new TD_Notifications )->check_notification();
$product_key = TD_Ian_Helper::get_product_name_by_page( $this->current_page );
$notify_class = TD_Ian_Helper::class_by_product( $product_key );
$image_url = TVE_DASH_URL . '/css/images/No-notifications-Thrive.png';
$params = array(
'baseUrl' => tva_get_rest_route_url( $this->namespace, 'app-notification' ),
't' => include $this->path( 'i18n.php' ),
'dash_url' => admin_url( 'admin.php?page=tve_dash_section' ),
'image_url' => $image_url,
'data' => $notifications,
'limit' => $limit,
'offset' => $offset + $limit,
'current_page' => $this->current_page,
'notify_class' => $notify_class,
'date_time_now' => current_time( 'Y-m-d H:i:s ' ),
'dismiss_nonce' => wp_create_nonce( 'wp_rest' ),
);
tve_dash_enqueue_style( 'tve_dash_app_notification',
TVE_DASH_URL . '/inc/app-notification/assets/css/tve-app-notification.css' );
tve_dash_enqueue_script( 'tve_dash_app_notification',
TVE_DASH_URL . '/inc/app-notification/assets/dist/tve-app-notification' . $js_prefix, array(
'jquery',
'backbone',
), TVE_DASH_VERSION, true );
tve_dash_admin_enqueue_scripts( 'tve_dash_app_notification' );
wp_enqueue_style( 'wp-block-library' );
wp_enqueue_style( 'wp-block-library-theme' );
wp_localize_script( 'tve_dash_app_notification', 'TD_Notification', $params );
}
/**
* Check if the current page is the editor
*
* @return bool
*/
private function isEditor() {
return 'architect' === $this->current_page;
}
private function is_ttb() {
return 'thrive-theme-dashboard' === $this->current_page;
}
/**
* Enqueue notification icons
*/
public function tve_dash_enqueue_notification_icons() {
$icon_file_path = TVE_DASH_PATH . '/inc/app-notification/assets/css/notification-icons.svg';
if ( file_exists( $icon_file_path ) ) {
include_once $icon_file_path;
}
}
/**
* Register REST routes
*/
public static function register_rest_routes() {
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . "Notification_Controller.php";
$notificationController = new TD_Notification_Controller();
$notificationController->register_routes();
}
/**
* Load required files
*
* @param string $path
*/
private function _load( $path = '' ) {
$path = $path ? $path : $this->class_path;
$dir = new DirectoryIterator( $path );
foreach ( $dir as $file ) {
if ( $file->isDot() ) {
continue;
}
if ( file_exists( $file->getPathname() ) && $file->isFile() ) {
require_once( $file->getPathname() );
}
}
// Run the migration if db tables are not created
TD_DbMigration::migrate();
if ( ! wp_next_scheduled( 'delete_expired_notice_daily' ) ) {
wp_schedule_event( time(), 'daily', 'delete_expired_notice_daily' );
}
add_action( 'delete_expired_notice_daily', [ $this, 'delete_expired_notices' ] );
}
public function delete_expired_notices() {
global $wpdb;
$current_time = current_time( 'Y-m-d H:i:s' );
$expired_notices_query = $wpdb->prepare( "
SELECT ID
FROM {$wpdb->prefix}td_app_notifications
WHERE end < %s
", $current_time );
$expired_notices = $wpdb->get_results( $expired_notices_query );
foreach ( $expired_notices as $notice ) {
$wpdb->delete( $wpdb->prefix . 'td_app_notifications', array( 'ID' => $notice->ID ) );
}
}
/**
* Get the full path to a file
*
* @param string $file
*
* @return string
*/
private function path( $file = '' ) {
return untrailingslashit( $this->base_path ) . ( ! empty( $file ) ? DIRECTORY_SEPARATOR : '' ) . ltrim( $file,
'\\/' );
}
/**
* Hook into WordPress actions and filters
*/
public function _hooks() {
add_filter( 'tve_dash_admin_product_menu', array( $this, 'add_to_dashboard_menu' ) );
if ( $this->isEditor() ) {
add_action( 'wp_loaded', array( $this, 'tve_dash_enqueue_notification_scripts' ) );
add_action( 'tcb_editor_iframe_after', array( $this, 'include_notification_icons_svg' ) );
} else {
add_action( 'admin_enqueue_scripts', array( $this, 'tve_dash_enqueue_notification_scripts' ) );
}
add_action( 'admin_enqueue_scripts', array( $this, 'tve_dash_enqueue_notification_icons' ) );
add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
add_action( 'tvd_notification_inbox', array( $this, 'notification_button' ) );
}
public function include_notification_icons_svg() {
$file_path = TVE_DASH_PATH . '/inc/app-notification/assets/css/notification-icons.svg';
if ( file_exists( $file_path ) ) {
include $file_path;
}
}
public static function get_unread_count() {
global $wpdb;
$current_time = current_time( 'Y-m-d H:i:s' );
$unread_count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(id) FROM {$wpdb->prefix}td_app_notifications WHERE dismissed = 0 AND start <= %s",
$current_time
)
);
if ( $unread_count > 99 ) {
$unread_count = '99+';
}
return $unread_count;
}
/**
* Add notifications to the dashboard menu
*
* @param array $menus
*
* @return array
*/
public function add_to_dashboard_menu( $menus = array() ) {
$count = static::get_unread_count();
if ( $count > 0 ) {
$menus['app_notifications'] = array(
'parent_slug' => 'tve_dash_section',
'page_title' => __( 'App Notification', 'thrive-dash' ),
'menu_title' => __( 'Notifications',
'thrive-dash' ) . '<span class="notification-indicator"></span>',
'capability' => TVE_DASH_CAPABILITY,
'menu_slug' => 'tve_dash_section&notify=1',
'function' => 'tve_dash_section',
);
} else {
unset( $menus['app_notifications'] );
}
return $menus;
}
/**
* Render the notification button
*
* @param bool $return
*
* @return string|void
*/
public function notification_button( $return = false ) {
$template = $this->template_path . '/app-notification-button.php';
ob_start();
if ( file_exists( $template ) ) {
include $template;
}
$html = ob_get_clean();
if ( $return ) {
return $html;
}
echo $html; // phpcs:ignore
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
class TD_DbMigration {
static $tableName = 'td_app_notifications';
public static function migrate() {
global $wpdb;
$charsetCollate = $wpdb->get_charset_collate();
$table = $wpdb->prefix . static::$tableName;
if ( $wpdb->get_var("SHOW TABLES LIKE '$table'") != $table ) {
$sql = "CREATE TABLE $table (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`slug` varchar(255) NOT NULL,
`title` text NOT NULL,
`content` longtext NOT NULL,
`type` varchar(64) NOT NULL,
`level` text NOT NULL,
`notification_id` bigint(20) unsigned DEFAULT NULL,
`notification_name` varchar(255) DEFAULT NULL,
`start` datetime DEFAULT NULL,
`end` datetime DEFAULT NULL,
`button1_label` varchar(255) DEFAULT NULL,
`button1_action` varchar(255) DEFAULT NULL,
`button2_label` varchar(255) DEFAULT NULL,
`button2_action` varchar(255) DEFAULT NULL,
`dismissed` tinyint(1) NOT NULL DEFAULT 0,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (id),
KEY ian_dates (start, end),
KEY ian_type (type),
KEY ian_dismissed (dismissed)
) $charsetCollate;";
dbDelta($sql);
}
$index_exists = $wpdb->get_results("SHOW INDEX FROM $table WHERE Key_name = 'ian_slug'");
if ($index_exists) {
$wpdb->query("ALTER TABLE $table DROP INDEX ian_slug");
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
class TD_Ian_Helper {
public static function product_list() {
return [
'tve_dash',// Thrive Dashboard
'thrive_automator',//Thrive Automator
'thrive_apprentice', //Thrive Apprentice
'tcm', // Thrive Comments
'tvo',// Thrive Ovation
'tab_admin_dashboard', // Thrive Optimize
'thrive_leads', // Thrive Leads
'tqb', // Thrive Quiz Builder
'tve_ult', //Thrive Ultimatum
'architect', //Thrive Architect
'thrive-theme-dashboard' //Thrive Theme Builder
];
}
public static function class_by_product( $product ) {
$classList = [
'tve_dash' => 'notify-td',
'thrive_automator' => 'notify-t-automator',
'thrive_apprentice' => 'notify-ta',
'tcm' => 'notify-tcm',
'tvo' => 'notify-tvo',
'tab_admin_dashboard' => 'notify-t-optimize',
'thrive_leads' => 'notify-thrive-leads',
'tqb' => 'notify-tqb',
'tve_ult' => 'notify-tve-ult',
'architect' => 'notify-tar',
'thrive-theme-dashboard' => 'notify-ttb'
];
return isset( $classList[ $product ] ) ? $classList[ $product ] : '';
}
public static function get_product_name_by_page( $page ) {
$products = self::product_list();
$product = "";
foreach ( $products as $p ) {
if ( strpos( $page, $p ) !== false ) {
$product = $p;
break;
}
}
return $product;
}
public static function get_user_product_ids() {
$user_license_details = thrive_get_transient( 'td_ttw_licenses_details' );
$user_products = [];
foreach ( $user_license_details as $license ) {
$user_products[] = $license['product_id'];
}
return $user_products;
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Notification Controller Class
*
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'TD_Notification_Controller' ) ) {
/**
* Notification Controller Class.
*
* @since 1.0.0
*/
class TD_Notification_Controller {
/**
* REST namespace for the controller.
*
* @since 1.0.0
* @var string
*/
const REST_NAMESPACE = 'tve-dash/v1';
/**
* Registers REST API routes for the controller.
*
* @since 1.0.0
*/
public function register_routes() {
register_rest_route( static::REST_NAMESPACE, 'app-notification/dismiss', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'dismiss_notification' ),
'args' => array(
'notification_id' => array(
'type' => 'integer || string',
'required' => true,
)
),
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
),
) );
register_rest_route( static::REST_NAMESPACE, 'app-notification/dismiss-all', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'dismiss_all_notification' ),
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
),
) );
}
/**
* Dismisses a notification.
*
* @param WP_REST_Request $request The request object.
*
* @return WP_REST_Response Response object indicating success or failure.
* @since 1.0.0
*
*/
public function dismiss_notification( $request ) {
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . "Notifications.php";
global $wpdb;
$notification_id = intval( $request->get_param( 'notification_id' ) );
$updated = $wpdb->update( $wpdb->prefix . 'td_app_notifications', [ 'dismissed' => 1 ],
[ 'notification_id' => $notification_id ] );
if ( ! $updated ) {
return new WP_REST_Response( array( 'success' => false ), 403 );
}
( new TD_Notifications() )->update_transients();
return new WP_REST_Response( array( 'success' => true ), 200 );
}
/**
* Dismisses all notifications.
*
* @return WP_REST_Response Response object indicating success or failure.
* @since 1.0.0
*
*/
public function dismiss_all_notification() {
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . "Notifications.php";
global $wpdb;
$wpdb->update( $wpdb->prefix . 'td_app_notifications', [ 'dismissed' => 1 ], [ 'dismissed' => 0 ] );
( new TD_Notifications() )->update_transients();
return new WP_REST_Response( array( 'success' => true ), 200 );
}
}
}

View File

@@ -0,0 +1,253 @@
<?php
class TD_Notifications {
private $_url;
private $_connection;
private $_request_params;
public function __construct() {
$this->_connection = TD_TTW_Connection::get_instance();
$this->_request_params = [
'user_id' => $this->_connection->ttw_id,
'user_email' => $this->_connection->ttw_email,
'last_notification_id' => get_option( 'td_last_notification_id' ),
];
$this->_url = TD_TTW_Connection::get_ttw_url() . '/wp-content/notifications.json';
}
public function handle_notifications() {
if ( $this->is_transients_exist() ) {
return;
}
$notifications = $this->get( $this->_request_params );
if ( ! $notifications || ! is_array( $notifications ) || is_wp_error( $notifications ) ) {
return;
}
foreach ( $notifications as $notification ) {
if ( $this->is_exist( $notification['notification_id'] ) || ( isset( $notification['end'] ) && $this->is_expired( $notification['end'] ) ) ) {
continue;
}
$this->add_notification( $notification );
}
}
public function check_notification() {
$this->handle_notifications();
$notifications = $this->get_notification();
return $notifications;
}
private function get_notification( $update_call = false ) {
global $wpdb;
$table_name = $wpdb->prefix . 'td_app_notifications';
$current_time = current_time( 'Y-m-d H:i:s' );
if ( $this->is_transients_exist() && ! $update_call ) {
return get_transient( 'td_app_notifications_transients' );
}
$active_notifications_query = $wpdb->prepare(
"SELECT * FROM $table_name
WHERE start <= %s
AND (end IS NULL OR end >= %s)
AND dismissed = 0
ORDER BY start DESC",
$current_time, $current_time
);
$active_notifications = $wpdb->get_results( $active_notifications_query, ARRAY_A );
$dismissed_notifications_query = $wpdb->prepare( " SELECT *
FROM $table_name
WHERE dismissed = 1
AND (end IS NULL OR end >= %s)
ORDER BY start DESC
", $current_time );
$dismissed_notifications = $wpdb->get_results( $dismissed_notifications_query, ARRAY_A );
if ( ! $active_notifications && ! $dismissed_notifications ) {
return false;
}
$notifications = [
'active' => $active_notifications,
'dismissed' => $dismissed_notifications
];
if ( ! $update_call ) {
$this->store_transients( $notifications );
}
return $notifications;
}
private function add_notification( $notification ) {
if ( ! $notification || ! is_array( $notification ) || empty( $notification ) ) {
return false;
}
if ( isset( $notification['have_license'] ) && is_array( $notification['have_license'] ) ) {
if ( ! $this->verify_access( $notification['have_license'], $notification['dont_have_license'] ) ) {
return;
}
}
global $wpdb;
$table_name = $wpdb->prefix . 'td_app_notifications';
if ( isset( $notification['btns'] ) ) {
foreach ( $notification['btns'] as $key => $value ) {
if ( $key === 'main' ) {
$notification['button1_label'] = sanitize_text_field( $value['text'] );
$notification['button1_action'] = esc_url_raw( $value['url'] );
}
if ( $key === 'alt' ) {
$notification['button2_label'] = sanitize_text_field( $value['text'] );
$notification['button2_action'] = esc_url_raw( $value['url'] );
}
}
}
if ( isset( $notification['btns'] ) ) {
unset( $notification['btns'] );
}
unset( $notification['have_license'] );
unset( $notification['dont_have_license'] );
$additional_data = [
'created' => current_time( 'Y-m-d H:i:s' ),
'updated' => current_time( 'Y-m-d H:i:s' ),
];
$notification = array_merge( $notification, $additional_data );
$last_notification_id = get_option( 'td_last_notification_id', 0 );
if ( isset( $notification['notification_id'] ) && $last_notification_id < $notification['notification_id'] ) {
update_option( 'td_last_notification_id', $notification['notification_id'] );
}
$wpdb->insert( $table_name, $notification );
}
private function verify_access( $have_license, $dont_have_license ) {
if ( ! is_array( $have_license ) && ! is_array( $dont_have_license ) ) {
return true;
}
$user_products = TD_Ian_Helper::get_user_product_ids();
if ( ! empty( $have_license ) && ! empty( $dont_have_license ) ) {
$has_any_license = ! empty( array_intersect( $user_products, $have_license ) );
$has_no_restricted_license = empty( array_intersect( $user_products, $dont_have_license ) );
return $has_any_license || $has_no_restricted_license;
}
if ( ! empty( $have_license ) ) {
return ! empty( array_intersect( $user_products, $have_license ) );
}
if ( ! empty( $dont_have_license ) ) {
return ! empty( array_intersect( $user_products, $dont_have_license ) );
}
return true;
}
// Check if the notification is already expired or not
private function is_expired( $end ) {
if ( ! $end || empty( $end ) ) {
return false;
}
$current_time = strtotime( current_time( 'Y-m-d H:i:s' ) );
return $current_time > strtotime( $end );
}
// Retrieve data from the server using the REST API
private function get( $args = [] ) {
$request_params = [
'body' => $args,
'headers' => [
'Content-Type' => 'application/json',
],
'timeout' => 30,
'sslverify' => false,
];
$notifications = wp_remote_get( $this->_url, $request_params );
if ( is_wp_error( $notifications ) ) {
return [];
}
$response_code = wp_remote_retrieve_response_code( $notifications );
if ( $response_code != 200 ) {
return [];
}
if ( is_wp_error( $notifications ) ) {
return false;
}
$notifications = json_decode( wp_remote_retrieve_body( $notifications ), true );
if ( ! is_array( $notifications ) ) {
return [];
}
return $notifications;
}
// Check if the notification already exists in the database
private function is_exist( $notification_id ) {
global $wpdb;
$table_name = $wpdb->prefix . 'td_app_notifications';
$notification = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE notification_id = %d",
$notification_id ) );
if ( $notification ) {
return true;
}
return false;
}
// Check if the transients already exist
private function is_transients_exist() {
$transient_name = 'td_app_notifications_transients';
$transient = get_transient( $transient_name );
if ( $transient ) {
return true;
}
return false;
}
// Store the transients
private function store_transients( $notifications ) {
if ( ! $notifications || ! is_array( $notifications ) || is_wp_error( $notifications ) ) {
return;
}
set_transient( 'td_app_notifications_transients', $notifications, time() + DAY_IN_SECONDS );
}
public function update_transients() {
$this->store_transients( $this->get_notification( true ) );
}
}