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,243 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Logo_REST
*/
class TCB_Logo_REST {
public static $namespace = 'tcb/v1';
public static $route = '/logo';
public static $rename_route = '/rename_logo';
public function __construct() {
$this->register_routes();
}
/**
* Registers the route for adding/deleting/editing/renaming new logos.
*/
public static function register_routes() {
register_rest_route( static::$namespace, static::$route, array(
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => [ 'TCB_Logo_REST', 'add' ],
'permission_callback' => [ 'TCB_Logo_REST', 'route_permission' ],
),
) );
register_rest_route( static::$namespace, static::$route . '/(?P<id>[\d]+)', array(
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => [ 'TCB_Logo_REST', 'update' ],
'permission_callback' => [ 'TCB_Logo_REST', 'route_permission' ],
),
array(
'methods' => WP_REST_Server::DELETABLE,
'callback' => [ 'TCB_Logo_REST', 'delete' ],
'permission_callback' => [ 'TCB_Logo_REST', 'route_permission' ],
),
) );
register_rest_route( static::$namespace, static::$route . static::$rename_route . '/(?P<id>[\d]+)', array(
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => [ 'TCB_Logo_REST', 'rename_logo' ],
'permission_callback' => [ 'TCB_Logo_REST', 'route_permission' ],
),
) );
}
/**
* Add a new logo.
*
* @param WP_REST_Request $request Full data about the request.
*
* @return WP_Error|WP_REST_Response
*/
public static function add( $request ) {
$attachment_id = $request->get_param( 'attachment_id' );
$name = $request->get_param( 'name' );
$scope = $request->get_param( 'scope' );
/* added logos are active by default */
$active = 1;
/* default is 0, only the two initial logos have this value set to 1 */
$default = 0;
$logos = TCB_Logo::get_logos();
/* search for an already existing logo with the same $attachment_id */
foreach ( $logos as $index => $logo ) {
if ( $attachment_id && (int) $logo['attachment_id'] === (int) $attachment_id ) {
$new_logo = $logo;
break;
}
}
if ( ! isset( $new_logo ) ) {
$logo_id = count( $logos );
$new_logo = [
'id' => $logo_id,
'attachment_id' => $attachment_id,
'name' => $name,
'default' => $default,
'active' => $active,
'scope' => $scope,
];
/* add the new logo to the logo array */
$logos[] = $new_logo;
/* update inside the DB */
update_option( TCB_Logo::OPTION_NAME, $logos );
}
/* return the new logo ID */
return new WP_REST_Response( $new_logo, 200 );
}
/**
* Update an existing logo.
*
* @param WP_REST_Request $request Full data about the request.
*
* @return WP_REST_Response
*/
public static function update( $request ) {
$id = (int) $request->get_param( 'id' );
/* also cover the case where ID is 0 */
if ( isset( $id ) ) {
$index = - 1;
$logos = TCB_Logo::get_logos();
/* look for the logo data in the array */
foreach ( $logos as $key => $logo_data ) {
if ( $id === $logo_data['id'] ) {
$index = $key;
break;
}
}
/* if we found the ID in the array, update it with the new params */
if ( $index !== - 1 ) {
$attachment_id = $request->get_param( 'attachment_id' );
/* update data in the array */
$logos[ $index ]['attachment_id'] = $attachment_id;
/* update data inside the DB */
update_option( TCB_Logo::OPTION_NAME, $logos );
return new WP_REST_Response( 'success', 200 );
}
}
return new WP_REST_Response( 'Error on updating the logo - the ID was not sent, or the logo was not found in the array.', 500 );
}
/**
* Delete an existing logo.
*
* @param WP_REST_Request $request Full data about the request.
*
* @return WP_Error|WP_REST_Response
*/
public static function delete( $request ) {
$id = (int) $request->get_param( 'id' );
if ( ! empty( $id ) ) {
$index = - 1;
$logos = TCB_Logo::get_logos();
/* look for the logo data in the array */
foreach ( $logos as $key => $logo_data ) {
if ( $id === $logo_data['id'] ) {
$index = $key;
break;
}
}
/* if we found the ID in the array, update it with the new params */
if ( $index !== - 1 ) {
/* make the logo inactive */
$logos[ $index ]['active'] = 0;
/* update inside the DB */
update_option( TCB_Logo::OPTION_NAME, $logos );
return new WP_REST_Response( 'success', 200 );
}
}
return new WP_REST_Response( 'Error on deleting the logo - ID was not sent, or the logo was not found in the array.', 500 );
}
/**
* Rename a logo.
*
* @param WP_REST_Request $request Full data about the request.
*
* @return WP_Error|WP_REST_Response
*/
public static function rename_logo( $request ) {
$id = (int) $request->get_param( 'id' );
if ( isset( $id ) ) {
$index = - 1;
$logos = TCB_Logo::get_logos();
/* look for the logo data in the array */
foreach ( $logos as $key => $logo_data ) {
if ( $id === $logo_data['id'] ) {
$index = $key;
break;
}
}
/* if we found the ID in the array, update it with the new name */
if ( $index !== - 1 ) {
$name = $request->get_param( 'name' );
/* update data in the array */
$logos[ $index ]['name'] = $name;
/* update data inside the DB */
update_option( TCB_Logo::OPTION_NAME, $logos );
return new WP_REST_Response( 'success', 200 );
}
}
return new WP_REST_Response( 'Error on renaming the logo - the ID was not sent, or the logo was not found in the array.', 500 );
}
/**
* Check if a given request has access to route
*
* @param WP_REST_Request $request Full data about the request.
*
* @return WP_Error|bool
*/
public static function route_permission( $request ) {
return TCB_Product::has_external_access();
}
}
new TCB_Logo_REST();

View File

@@ -0,0 +1,514 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
defined( 'TCB_TABLET_THRESHOLD' ) || define( 'TCB_TABLET_THRESHOLD', 768 );
defined( 'TCB_DESKTOP_THRESHOLD' ) || define( 'TCB_DESKTOP_THRESHOLD', 1024 );
/**
* Class TCB_Logo
*
* Implementation of the Logo Element, featuring image optimization and art direction with the <picture> tag - load multiple image versions depending on the device type.
*/
class TCB_Logo {
/* component name */
const COMPONENT = 'logo';
/* identifier used as a class name */
const IDENTIFIER = 'tcb-logo';
/* shortcode tag in which the logo HTML is wrapped */
const SHORTCODE_TAG = 'tcb_logo';
/* name of the option in the DB where the logo data is stored */
const OPTION_NAME = 'tcb_logo_data';
const DELETED_PLACEHOLDER_SRC = 'editor/css/images/logo_deleted_placeholder.png';
/* list of devices that can have their own logo images ( desktop, tablet, mobile were shortened like this in order to work with mediaAttr() in JS ) */
private static $all_devices = [ 'd', 't', 'm' ];
/**
* TCB_Logo constructor.
*/
public function __construct() {
$this->hooks();
}
/**
* Add actions and filters.
*/
private function hooks() {
add_action( 'init', [ $this, 'init_shortcode' ] );
add_filter( 'tcb_main_frame_localize', [ $this, 'add_localize_params' ] );
add_filter( 'tcb_content_allowed_shortcodes', [ $this, 'tcb_content_allowed_shortcodes' ] );
}
/**
* Add data to the main frame localize parameters.
*
* @param $data
*
* @return mixed
*/
public function add_localize_params( $data ) {
$logos = static::get_logos();
$active_logos = array_filter( $logos, function ( $logo ) {
return (int) $logo['active'] === 1;
} );
/* get the src for each attachment ID */
foreach ( $active_logos as $key => $logo ) {
$logo_data = static::get_attachment_data( $logo['id'], $logo );
$active_logos[ $key ]['src'] = $logo_data['src'];
$active_logos[ $key ]['width'] = $logo_data['width'];
$active_logos[ $key ]['height'] = $logo_data['height'];
$active_logos[ $key ]['data-alt'] = empty( $logo_data['data-alt'] ) ? '' : $logo_data['data-alt'];
}
$data['logo'] = array(
'routes' => array(
'base' => get_rest_url( get_current_blog_id(), 'tcb/v1/logo' ),
'rename_logo' => get_rest_url( get_current_blog_id(), 'tcb/v1/logo/rename_logo' ),
),
/* only localize the active logos */
'sources' => array_values( $active_logos ),
'deleted_placeholder' => tve_editor_url( static::DELETED_PLACEHOLDER_SRC ),
'is_ttb_active' => tve_dash_is_ttb_active(),
'is_ta_active' => tve_dash_is_plugin_active( 'thrive-apprentice' ),
);
return $data;
}
/**
* Render the element. Inside the editor, render a simplified version without responsive stuff.
* On the frontend, render a <source> tag for each logo chosen for a responsive device screen.
*
* @param array $attr
* @param bool $render_fallback
*
* @return string
*/
public static function render_logo( $attr = [], $render_fallback = false ) {
/* if the desktop logo ID is not set, use id = 0 as default and set it in the attr */
if ( ! isset( $attr['data-id-d'] ) ) {
$attr['data-id-d'] = 0;
}
$desktop_id = (int) $attr['data-id-d'];
$logos = static::get_logos();
/* set the desktop source as a fallback; get only the src here, since this is an all-browser compatible version */
$fallback_data = static::get_attachment_data( $desktop_id, isset( $logos[ $desktop_id ] ) ? $logos[ $desktop_id ] : null );
/* If we do not have alt in attr, we read it from fallback data */
if ( empty( $attr['data-alt'] ) ) {
$attr['data-alt'] = empty( $fallback_data['data-alt'] ) ? '' : $fallback_data['data-alt'];
}
$img_attr = array(
'src' => $fallback_data['src'],
'height' => $fallback_data['height'],
'width' => $fallback_data['width'],
'alt' => $attr['data-alt'],
'style' => ! empty( $attr['data-img-style'] ) ? $attr['data-img-style'] : '',
);
/**
* Handle logo image loading
*/
if ( isset( $attr['loading'] ) ) {
$img_attr['loading'] = $attr['loading'];
unset( $attr['loading'] );
} else {
$img_attr['class'] = 'tve-not-lazy-loaded';
}
/* GIFs aren't compatible with srcset, so we use the fallback version */
if ( ! empty( $img_attr['src'] ) && substr( $img_attr['src'], - 4 ) === '.gif' ) {
$render_fallback = true;
}
/* in the editor or when doing ajax ( when the logo is in a symbol ) or when doing rest ( when you add new headers/footers and start from cloud templates ) or when we set a flag, return the desktop src only */
if ( TCB_Utils::in_editor_render() || wp_doing_ajax() || TCB_Utils::is_rest() || $render_fallback ) {
$content = TCB_Utils::wrap_content( '', 'img', '', '', $img_attr );
} else {
/* if the fallback data is empty and we're outside the editor, return an empty string ( this case happens when the logo was deleted ) */
if ( empty( $fallback_data['src'] ) ) {
$content = '';
} else {
$content = static::get_picture_element( $attr, $img_attr );
}
}
$logo_url = apply_filters( 'tcb_logo_site_url', '' );
/* We have to process the shortcode here because we cannot send it as a param inside another shortcode ( logo ) */
if ( ! empty( $attr['data-dynamic-link'] ) ) {
$shortcode = "{$attr['data-dynamic-link']} id={$attr['data-shortcode-id']}";
if ( ! empty( $attr['data-custom-redirect'] ) ) {
$shortcode .= " logout-redirect={$attr['data-custom-redirect']}";
}
$attr['href'] = do_shortcode( "[{$shortcode}]" );
}
/* embed the img in a link instead of wrapping it in a div (if an url exists) */
if ( empty( $attr['href'] ) ) {
if ( empty( $logo_url ) || ! empty( $attr['data-remove-href'] ) ) {
unset( $attr['href'] );
} else {
$attr['href'] = $logo_url;
}
}
$href = isset( $attr['href'] ) ? $attr['href'] : '';
/**
* Allows filtering the final value of the `href` logo attribute
*
* @param string $href current url
* @param array $attr array of shortcode attributes
*/
$href = apply_filters( 'tcb_logo_url', $href, $attr );
if ( ! empty( $href ) ) {
$attr['href'] = $href;
}
return TCB_Utils::wrap_content( $content, 'a', '', static::get_classes( $attr ), static::get_attr( $attr ) );
}
/**
* Get the picture element containing the sources. ( For info on how this works, see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture )
*
* @param array $attr
* @param array $img_attr
*
* @return string
*/
public static function get_picture_element( $attr, $img_attr ) {
$picture_content = '';
foreach ( static::$all_devices as $device ) {
if ( isset( $attr[ 'data-id-' . $device ] ) ) {
$id = (int) $attr[ 'data-id-' . $device ];
$media_attr = [
'srcset' => static::get_srcset( $id ),
];
/* add media rules to restrict where each source is displayed */
switch ( $device ) {
case 'd':
$media_attr['media'] = '(min-width:' . TCB_DESKTOP_THRESHOLD . 'px)';
break;
case 't':
$media_attr['media'] = '(min-width:' . TCB_TABLET_THRESHOLD . 'px) and (max-width:' . TCB_DESKTOP_THRESHOLD . 'px)';
break;
case 'm':
$media_attr['media'] = '(max-width:' . ( TCB_TABLET_THRESHOLD - 1 ) . 'px)';
break;
default:
break;
}
$picture_content .= TCB_Utils::wrap_content( '', 'source', '', '', $media_attr );
}
}
/* add the fallback img */
$picture_content .= TCB_Utils::wrap_content( '', 'img', '', '', $img_attr );
/* wrap it in the <picture> tag and return */
return TCB_Utils::wrap_content( $picture_content, 'picture' );
}
/**
* Get all the attachment data for this logo ID. If the logo ID is not found or we don't have an attachment ID, return placeholder data instead.
*
* @param int $id
* @param array $logo
*
* @return array
*/
public static function get_attachment_data( $id, $logo = null ) {
$attachment_id = static::get_attachment_id( $id );
if ( empty( $attachment_id ) ) {
/* get the placeholder for this id ( it can differ depending on the ID : 0 and 1 have their own placeholder ) */
$data = static::get_placeholder_data( $id, $logo );
} else {
$attachment_data = wp_get_attachment_image_src( $attachment_id, 'full' );
if ( empty( $attachment_data[0] ) ) {
$data = static::get_placeholder_data( $id );
} else {
$data = array(
'src' => $attachment_data[0],
'width' => $attachment_data[1],
'height' => $attachment_data[2],
'data-alt' => trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
);
}
}
return $data;
}
/**
* For the given logo ID, look for the attachment ID and return it. If it's not found, return null.
*
* @param int $id
*
* @return mixed|null
*/
public static function get_attachment_id( $id ) {
$logos = static::get_logos();
$index = - 1;
/* look for the logo ID in the array of logo data */
foreach ( $logos as $key => $logo_data ) {
if ( $id === $logo_data['id'] ) {
$index = $key;
break;
}
}
$attachment_id = null;
/* if the logo ID was not found, render the placeholder */
if ( $index !== - 1 ) {
/* if we found the key for the logo ID, get the src */
$logo_data = $logos[ $index ];
/* if the logo is active or it's light or dark, start looking for the image ID */
if ( $logo_data['active'] || $id === 0 || $id === 1 ) {
if ( ! empty( $logo_data['attachment_id'] ) ) {
$attachment_id = $logo_data['attachment_id'];
}
}
}
return $attachment_id;
}
/**
* Get the image source for this logo ID. It can be a placeholder too
*
* @param $id
*
* @return mixed
*/
public static function get_src( $id ) {
$attachment_data = static::get_attachment_data( $id );
return $attachment_data['src'];
}
/**
* Get the srcset attribute for this logo ID. If empty, return the normal source instead.
*
* @param $id
*
* @return bool|mixed|string
*/
public static function get_srcset( $id ) {
$attachment_id = static::get_attachment_id( $id );
if ( ! empty( $attachment_id ) ) {
/* get the full srcset so the browser can pick the best image size for the current screen */
$srcset = wp_get_attachment_image_srcset( $attachment_id );
}
if ( empty( $srcset ) ) {
/* if the srcset is empty (this happens for SVGs and for small images) or we don't want the srcset, get the src instead */
$srcset = static::get_src( $id );
}
return $srcset;
}
/**
* Return the placeholder data according to the ID.
* For id = 0 or 1, return the light/dark placeholder, for any other ID, return a 'logo has been deleted' placeholder.
*
* @param int $id
* @param array $logo
*
* @return array
*/
public static function get_placeholder_data( $id, $logo = null ) {
$data = [
'height' => '',
'width' => '',
];
$is_default_logo = ! empty( $logo ) && isset( $logo['scope'] ) && $logo['scope'] === 'tva';
if ( $id === 0 || ( $is_default_logo && $logo['name'] === 'Dark' ) ) {
$data['src'] = tve_editor_url( 'editor/css/images/logo_placeholder_dark.svg' );
} elseif ( $id === 1 || ( $is_default_logo && $logo['name'] === 'Light' ) ) {
$data['src'] = tve_editor_url( 'editor/css/images/logo_placeholder_light.svg' );
} else {
/* If we're in the editor, render a <logo image deleted> image. On the frontend, leave it blank. */
$data['src'] = TCB_Utils::in_editor_render() ? tve_editor_url( static::DELETED_PLACEHOLDER_SRC ) : '';
}
$data['is_placeholder'] = 1;
return $data;
}
/**
* Get the src directly ( called from TTB )
*
* @param int $id
*
* @return mixed
*/
public static function get_placeholder_src( $id = 0 ) {
$data = static::get_placeholder_data( $id );
return $data['src'];
}
/**
* Add the two initial logos and their placeholders ( these exist without having to be added manually and cannot be deleted ).
*
* @return array
*/
public static function initialize_default_logos() {
$logos = [
0 => [
'id' => 0,
'attachment_id' => '',
'active' => 1,
'default' => 1,
'name' => 'Dark',
],
1 => [
'id' => 1,
'attachment_id' => '',
'active' => 1,
'default' => 1,
'name' => 'Light',
],
];
/* update inside the DB */
update_option( static::OPTION_NAME, $logos );
return $logos;
}
/**
* Get the logo data. ( get_option() is cached, so it's ok to call this lots of times ).
*
* @param bool $apply_filter
*
* @return mixed|void
*/
public static function get_logos( $apply_filter = true ) {
$logos = get_option( static::OPTION_NAME );
/* if the option is empty, then we have to initialize the logo array with the default values */
if ( empty( $logos ) ) {
/* initialize the default logos */
$logos = static::initialize_default_logos();
}
if ( $apply_filter ) {
/**
* Allow other plugins to alter the logo list.
* Used in Thrive Apprentice plugin to modify the default light and dark logo when the system edits an apprentice page
*/
$logos = apply_filters( 'tcb_get_logos', $logos );
}
return $logos;
}
/**
* @param $attr
*
* @return string
*/
private static function get_classes( $attr ) {
$class = [ static::IDENTIFIER, THRIVE_WRAPPER_CLASS ];
/* set responsive/animation classes, if they are present */
if ( ! empty( $attr['class'] ) ) {
$class[] = $attr['class'];
}
return implode( ' ', $class );
}
/**
* @param $attr
*
* @return array
*/
private static function get_attr( $attr ) {
/* if we're not in the editor or not doing ajax ( for symbols ), remove the logo ID dataset */
if ( ! TCB_Utils::in_editor_render() && ! wp_doing_ajax() ) {
foreach ( static::$all_devices as $device ) {
unset( $attr[ 'data-id-' . $device ] );
}
}
/* we don't need to save this since it's stored in the image */
unset( $attr['data-alt'] );
return $attr;
}
/**
* Add the logo shortcode.
*/
public function init_shortcode() {
add_shortcode( static::SHORTCODE_TAG, function ( $attr, $content, $tag ) {
/**
* Ability to modify logo attributes before render.
*
* Used in thrive apprentice to modify the image URL for apprentice pages
*
* @param array $attributes
*/
$attr = apply_filters( 'tcb_logo_attributes', TCB_Post_List_Shortcodes::parse_attr( $attr, $tag ) );
return TCB_Logo::render_logo( $attr );
} );
}
/**
* We need to add our shortcodes to this array in order for them to be processed in the editor.
* If we're on the frontend, we don't have to do this.
*
* @param $shortcodes
*
* @return array
*/
public function tcb_content_allowed_shortcodes( $shortcodes ) {
if ( is_editor_page_raw( true ) ) {
$shortcodes = array_merge( $shortcodes, [ static::SHORTCODE_TAG ] );
}
return $shortcodes;
}
/**
* Register REST Routes for the Logo.
*/
public static function rest_api_init() {
require_once TVE_TCB_ROOT_PATH . 'inc/classes/logo/class-tcb-logo-rest.php';
}
}
new TCB_Logo();