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,92 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
namespace Thrive_Dashboard\Font_Library;
/**
* Class Admin
*
* This class handles the admin functionality for the font library.
*/
class Admin {
const SLUG = 'tve_dash_font_library';
const SCREEN = 'admin_page_' . self::SLUG;
/**
* Initializes the admin functionality.
*/
public function init() {
add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
}
/**
* Returns the URL for the font library admin page.
*
* @return string The URL for the font library admin page.
*/
public static function get_url () {
return admin_url( 'admin.php?page=' . self::SLUG );
}
/**
* Enqueues admin scripts and styles for the font library.
*
* @param string $screen The current admin screen.
*/
public function admin_enqueue_scripts( $screen ) {
if ( self::SCREEN !== $screen ) {
return;
}
if ( ! Main::is_wordpress_version_supported() ) {
return;
}
tve_dash_enqueue_script( 'font-library-app-script', TVE_DASH_URL . '/assets/dist/js/font-library.js', [], TVE_DASH_VERSION, true );
$this->enqueue_with_increased_specificity( TVE_DASH_PATH . '/assets/dist/css/font-library.css' );
}
/**
* Processes the CSS file for the font library. This increases specificity of all rules.
* This is necessary because we don't want to add unnecessary !important declarations
* or chain multiple classes within the CSS file. The conflicting styles are
* from thrive-dashboard/css/sass/materialize/_typography.scss. This logic
* can be removed once the Materialize CSS is removed from the plugin.
* This can be extracted to a global method if needed in the future.
*
* @param string $css_path The path to the CSS file.
* @return string The processed CSS.
*/
private function enqueue_with_increased_specificity( $css_path ) {
$css = file_get_contents( $css_path );
// Extract :root{} rule
preg_match('/:root\s*{[^}]*}/', $css, $root_matches);
$root_css = isset($root_matches[0]) ? $root_matches[0] : '';
// Remove :root{} rule from the original CSS
$css = preg_replace('/:root\s*{[^}]*}/', '', $css);
// Wrap the remaining CSS in #wpbody {}
// We want the increased specificity, while keeping the CSS code clean.
$css = $root_css . "\n#wpbody {\n" . $css . "\n}";
wp_register_style( 'font-library-app-css', false );
wp_enqueue_style( 'font-library-app-css' );
wp_add_inline_style( 'font-library-app-css', $css );
}
/**
* Includes the font library template.
*/
public static function get_template() {
require_once( TVE_DASH_PATH . '/inc/font-library/templates/font-library.php' );
}
}

View File

@@ -0,0 +1,198 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
namespace Thrive_Dashboard\Font_Library;
use WP_REST_Response;
/**
* Class Endpoint
*
* This class handles the REST API endpoints for the font library.
*/
class Endpoint {
private $strategy;
/**
* Font_Library_Endpoint constructor.
*
* @param object $strategy The font strategy to use.
*/
public function __construct( $strategy ) {
$this->strategy = $strategy;
}
/**
* Initializes the REST API endpoints.
*/
public function init() {
add_action('rest_api_init', function () {
register_rest_route('theme/v1', '/fonts', array(
'methods' => 'GET',
'callback' => [ $this, 'get_fonts' ],
'permission_callback' => function () {
return current_user_can( 'edit_posts' );
},
));
register_rest_route('theme/v1', '/fonts', array(
'methods' => 'POST',
'callback' => [ $this, 'set_fonts' ],
'permission_callback' => function () {
return current_user_can('edit_posts');
},
));
});
// Since init hook is already called, we can directly call the function to set font capabilities.
$this->set_font_capabilities();
}
/**
* Sets the capabilities for the font post type.
* Unregisters the 'wp_font_family' post type and re-registers it with modified capabilities.
* This is necessary to ensure that anyone who can edit posts can read the installed fonts.
*/
private function set_font_capabilities() {
global $wp_post_types;
// Ensure the post type is registered before modifying
if ( ! isset( $wp_post_types['wp_font_family'] ) ) {
return;
}
// Get the existing args of 'post'
$post_args = (array) $wp_post_types['wp_font_family'];
// Unregister 'post' before re-registering
unregister_post_type('wp_font_family');
// Modify capabilities
$post_args['cap']->read = 'edit_posts';
// Re-register the post with modified args
register_post_type('wp_font_family', $post_args);
}
/**
* Retrieves the fonts using the current strategy.
*
* @return WP_REST_Response The response containing the fonts.
*/
public function get_fonts() {
$fonts = $this->strategy->get_fonts();
return new WP_REST_Response( array_values( $fonts ), 200 );
}
/**
* Sets the fonts using the current strategy.
*
* @param WP_REST_Request $request The request containing the fonts to set.
* @return WP_REST_Response The response after setting the fonts.
*/
public function set_fonts( $request ) {
$fonts = $request['fonts'];
if ( ! is_array( $fonts ) ) {
return new WP_REST_Response( 'Invalid request', 400 );
}
// Merge the existing fonts with the new fonts.
// Make sure they're unique by the slug key and
// the current fonts will override the existing ones.
$existing_fonts = $this->strategy->get_fonts();
$fonts = array_merge( $existing_fonts, $fonts );
// Remove duplicate fonts, empty fonts and uninstalled fonts.
$fonts = $this->filter_duplicate_fonts( $fonts );
$fonts = $this->filter_empty_fonts( $fonts );
$fonts = $this->filter_uninstalled_fonts( $fonts );
$result = $this->strategy->set_fonts( $fonts );
return new WP_REST_Response( $result, 200 );
}
/**
* Filters out fonts that are not installed on the server.
* This could happen when a font is deleted when the theme is not active.
*
* @param array $fonts The fonts to filter.
*
* @return array The filtered fonts.
*/
private function filter_uninstalled_fonts( $fonts ) {
$installed_slugs = $this->get_installed_fonts();
$fonts = array_filter( $fonts, function( $font ) use ( $installed_slugs ) {
return in_array( $font['slug'], $installed_slugs );
} );
return array_values( $fonts );
}
/**
* Retrieves the installed fonts.
*
* @return array The installed font slugs.
*/
private function get_installed_fonts() {
$page = 1;
$per_page = 100;
$slugs = [];
do {
$installed_fonts = tve_send_wp_rest_request( '/wp/v2/font-families', [ 'per_page' => $per_page, 'page' => $page ] );
$slugs = array_merge(
$slugs,
array_map( function( $font ) {
return $font['font_family_settings']['slug'] ?? '';
}, $installed_fonts )
);
$page++;
// Just a safety measure to avoid infinite loops. This should never happen.
if ( $page > 10 ) {
break;
}
} while ( count( $installed_fonts ) === $per_page ); // If the count is less than the per_page, we've reached the end.
return $slugs;
}
/**
* Filters out fonts with empty fontFaces.
*
* @param array $fonts The fonts to filter.
*
* @return array The filtered fonts.
*/
private function filter_empty_fonts( $fonts ) {
$fonts = array_filter( $fonts, function( $font ) {
return ! empty( $font[ 'fontFace' ] );
} );
return array_values( $fonts );
}
/**
* Filters out duplicate fonts.
*
* @param array $fonts The fonts to filter.
*
* @return array The filtered fonts.
*/
private function filter_duplicate_fonts( $fonts ) {
$fonts = array_reduce( $fonts, function( $acc, $font ) {
$acc[ $font['slug'] ] = $font;
return $acc;
}, [] );
return array_values( $fonts );
}
}

View File

@@ -0,0 +1,133 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
namespace Thrive_Dashboard\Font_Library;
/**
* Class Main
*
* This class handles the font library functionality.
* It initializes the appropriate strategy based on the theme's support for theme.json
* and sets up REST API routes and admin scripts.
*/
class Main {
/**
* The admin class.
*
* @var Admin
*/
private $admin;
/**
* The public endpoint class.
*
* @var Endpoint
*/
public $endpoint;
/**
* Initializes the font library with a given strategy.
*
* @param object $strategy The font strategy to use.
*/
public function init() {
// Modules.
$this->admin = new Admin();
$this->admin->init();
if ( ! self::is_wordpress_version_supported() ) {
return;
}
$this->endpoint = new Endpoint( $this->get_font_storage_strategy() );
$this->endpoint->init();
// Actions.
add_action( 'wp_head', [ $this, 'define_font_sources' ] );
}
/**
* Retrieves the font storage strategy based on the theme's support for theme.json.
* If the theme supports theme.json, the REST API strategy is used, otherwise the theme mod strategy is used.
*
* @return object The font storage strategy.
*/
public function get_font_storage_strategy() {
static $strategy = null;
if ( null !== $strategy ) {
return $strategy;
}
if ( function_exists( 'wp_theme_has_theme_json' ) && wp_theme_has_theme_json() ) {
$strategy = new Rest_Api_Font_Strategy();
} else {
$strategy = new Theme_Mod_Font_Strategy();
}
return $strategy;
}
/**
* Defines the Font library font sources in the head of the document.
*
* @return void
*/
public function define_font_sources() {
$fonts = $this->get_font_storage_strategy()->get_fonts();
if ( empty( $fonts ) ) {
return;
}
// Generate font face rules for all the fonts into a single string.
$font_faces = array_reduce( $fonts, function( $styles, $font ) {
return $styles . $this->generate_font_face_rules( $font['fontFace'] );
}, '' );
// Enqueue the generated CSS as inline styles.
wp_register_style('thrive-font-library-fonts', false);
wp_enqueue_style('thrive-font-library-fonts');
wp_add_inline_style('thrive-font-library-fonts', $font_faces);
}
/**
* Generates CSS font-face rules for given font faces
*
* @param array $font_faces Array of font face definitions
* @return string Generated CSS rules
*/
private function generate_font_face_rules( $font_faces ) {
return array_reduce(
$font_faces,
function( $rules, $face ) {
return $rules . sprintf(
'@font-face{font-family:%s;font-style:%s;font-weight:%s;src:url("%s");}',
$face['fontFamily'],
$face['fontStyle'],
$face['fontWeight'],
$face['src']
);
},
''
);
}
/**
* Checks if the current WordPress version is supported.
* The WP Core feature was introduced in 6.5.
*
* @see https://make.wordpress.org/core/2024/03/14/new-feature-font-library/
*
* @return bool True if the version is supported, false otherwise.
*/
public static function is_wordpress_version_supported() {
global $wp_version;
return version_compare( $wp_version, '6.5', '>=' );
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
namespace Thrive_Dashboard\Font_Library;
use Thrive_Dashboard\Font_Library\Interfaces\Font_Strategy;
class Rest_Api_Font_Strategy implements Font_Strategy {
/**
* The theme mod font strategy.
*
* This will be used to get the fonts on the frontend
* when we don't have access to the REST API. This also doesn't
* provide access to any details other than the fonts list.
*
* @var Theme_Mod_Font_Strategy
*/
private $theme_mod_cache;
public function __construct() {
$this->theme_mod_cache = new Theme_Mod_Font_Strategy();
}
/**
* Retrieves the fonts using the REST API.
*
* @return array The fonts.
*/
public function get_fonts() {
$global_styles = $this->get_global_styles();
if ( is_wp_error( $global_styles ) || empty( $global_styles['settings'] ) || ! is_array( $global_styles['settings'] ) ) {
return $this->theme_mod_cache->get_fonts();
}
$fonts = $global_styles['settings']['typography']['fontFamilies']['custom'] ?? [];
return $fonts;
}
/**
* Sets the fonts using the REST API.
*
* @param array $fonts The fonts to set.
*
* @return array The updated global styles.
*/
public function set_fonts( $fonts ) {
$global_styles = $this->get_global_styles();
if ( ! is_array( $global_styles['settings'] ) || empty( $global_styles['settings'] ) ) {
$global_styles['settings'] = [];
}
$global_styles['settings']['typography']['fontFamilies']['custom'] = $fonts;
$this->set_global_styles( $global_styles );
$this->theme_mod_cache->set_fonts( $fonts );
return $global_styles;
}
/**
* Retrieves the global styles endpoint.
*
* @return string|null The global styles endpoint.
*/
private function get_global_styles_endpoint() {
$themes = tve_send_wp_rest_request( '/wp/v2/themes' );
if ( is_wp_error( $themes ) ) {
return null;
}
$active_theme = array_filter($themes, function($theme) {
return $theme['status'] === 'active';
});
$active_theme = reset($active_theme);
$global_styles_link = isset($active_theme['_links']['wp:user-global-styles'][0]['href']) ? $active_theme['_links']['wp:user-global-styles'][0]['href'] : null;
return $global_styles_link;
}
/**
* Retrieves the global styles.
*
* @return array The global styles.
*/
private function get_global_styles() {
$global_styles_link = $this->get_global_styles_endpoint();
if ( empty( $global_styles_link ) ) {
return [];
}
return tve_send_wp_rest_request( $global_styles_link );
}
/**
* Sets the global styles.
*
* @param array $global_styles The global styles to set.
*
* @return array The updated global styles.
*/
private function set_global_styles( $global_styles ) {
$global_styles_link = $this->get_global_styles_endpoint();
if ( empty( $global_styles_link ) ) {
return false;
}
return tve_send_wp_rest_request( $global_styles_link, $global_styles, 'POST' );
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
namespace Thrive_Dashboard\Font_Library;
use Thrive_Dashboard\Font_Library\Interfaces\Font_Strategy;
class Theme_Mod_Font_Strategy implements Font_Strategy {
const THEME_MOD_KEY = 'thrive_active_fonts';
/**
* Retrieves the fonts using the theme mod.
*
* @return array The fonts.
*/
public function get_fonts() {
$fonts = get_theme_mod( self::THEME_MOD_KEY, [] );
return $fonts;
}
/**
* Sets the fonts using the theme mod.
*
* @param array $fonts The fonts to set.
*
* @return array The updated fonts.
*/
public function set_fonts( $fonts ) {
return set_theme_mod( self::THEME_MOD_KEY, $fonts );
}
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
namespace Thrive_Dashboard\Font_Library\Interfaces;
interface Font_Strategy {
/**
* Retrieves the fonts.
*
* @return array The fonts.
*/
public function get_fonts();
/**
* Sets the fonts.
*
* @param array $fonts The fonts to set.
*
* @return array The updated fonts.
*/
public function set_fonts( $fonts );
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if (! defined('ABSPATH') ) {
exit; // Silence is golden!
}
/**
* Load the header template. This is the simplest way to include the header template
* as the dashboard is a part of both themes and plugins.
*/
require_once TVE_DASH_PATH . '/templates/header.phtml';
$dashboard_link = admin_url('admin.php?page=tve_dash_section');
?>
<div class="tvd-content flow">
<!-- Breadcrumbs -->
<div class="tvd-breadcrumbs">
<a class="tvd-breadcrumb" href="<?php echo esc_url( $dashboard_link ); ?>">
<?php echo esc_html__('Thrive Dashboard', 'thrive-dash'); ?>
</a>
<span class="tvd-breadcrumb"><?php echo esc_html__('Thrive Font Library', 'thrive-dash'); ?></span>
</div>
<?php if ( tve_font_library()::is_wordpress_version_supported() ) { ?>
<!-- The Application -->
<div id="font-library-app"></div>
<?php } else { ?>
<div class="tvd-font-library-version-notice">
<h1>Font Library</h1>
<p class="text--secondary">
<?php echo esc_html__('The Font Library requires WordPress version 6.5 or higher. Please upgrade your WordPress version to continue.', 'thrive-dash'); ?>
<a href="https://www.wpbeginner.com/beginners-guide/ultimate-guide-to-upgrade-wordpress-for-beginners-infograph/" target="_blank"><?php echo esc_html__('Learn more', 'thrive-dash'); ?></a>
</p>
</div>
<?php } ?>
<!-- Bottom Navigation -->
<div class="tvd-bottom-navigation">
<a class="tvd-btn button--back" href="<?php echo esc_url( $dashboard_link ); ?>">
<?php echo esc_html__('Back to Dashboard', 'thrive-dash'); ?>
</a>
</div>
</div>
<style>
/**
* NOTE:
* 1. Currently, there is only support for one :root block in the CSS.
* This is a limitation of the current implementation of the CSS parser.
* See - thrive-dashboard/inc/font-library/classes/Admin::enqueue_with_increased_specificity()
* This means that if you have multiple :root blocks in your CSS, only the first one will be used.
*
* 2. The following CSS variables are used in the FontLibrary component.
* Though these colors are supposed to be defined in a global CSS file, they are defined here momentarily.
* Creating a global CSS palette will be beyond the scope of this feature.
* This will be addressed in a future iteration, probably as part of the REVAMP.
*/
:root {
/* Green - Primary */
--color--primary: #4BB35E;
/* Red - Error */
--color--red: #fb5c55;
/* Grey - Neutral */
--color--neutral-white: #ffffff;
--color--neutral-lightest: #f3f6f6;
--color--neutral-lighter: #eaefef;
--color--neutral-light: #cdd3d8;
--color--neutral: #a9a9a9;
--color--neutral-dark: #898989;
--color--neutral-darker: #808080;
--color--neutral-black: #000000;
--tab-active-indicator-color: var(--color--primary);
--separator-color: var(--color--neutral-lighter);
--modal-layer: 100;
}
/*
* Page level styles - header, spacing, etc.
* These styles are added here to avoid adding a new file for a few lines of CSS.
* The few lines constraint must be maintained. If the styles grow, they should be moved to a separate file.
* Do not add any styles irrelevant to this current template.
*/
#wpcontent {
padding-inline-start: 0;
--breadcrumb-color: var(--color--neutral-darker);
--breadcrumb-color-active: var(--color--neutral-black);
/*
* Since #wpcontent padding is set to 0, we can remove the negative margin from the header.
*/
.tvd-header {
margin-inline-start: 0;
}
}
.tvd-btn {
min-height: unset;
line-height: 30px;
min-width: 130px;
}
.tvd-content {
--flow-space: 20px;
}
/* Both the sections have the same padding. */
#font-library-app,
.tvd-bottom-navigation {
padding-inline: 24px;
}
.button--back {
background-color: var(--color--neutral);
}
.tvd-font-library-version-notice {
margin: 20px;
padding: 20px;
background-color: #fff;
color: var(--color--neutral-black);
}
</style>