feat: initial ACRIB WordPress deployment

- WordPress 6.9.4 (es_ES) with Kadence theme
- Homepage: Hero, La Asociación, Pilares, Beneficios, Eventos, Miembros, Hazte Miembro, Contacto
- Brand identity: #13294b navy, #a12932 burgundy, #c69c48 gold
- Fonts: Raleway (headings) + Source Sans 3 (body) + Lato (UI)
- Plugins: Kadence Blocks, Polylang, Contact Form 7
- Custom CSS with full brand styling and responsive layout
- HTTPS enforced via wp-config.php proxy detection
This commit is contained in:
Malin
2026-05-19 19:25:59 +02:00
commit f3ff7b7186
6119 changed files with 1984255 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
<?php declare( strict_types=1 );
namespace KadenceWP\KadenceBlocks\Optimizer\Image\Contracts;
use KadenceWP\KadenceBlocks\Optimizer\Response\ImageAnalysis;
use WP_HTML_Tag_Processor;
/**
* Process an img tag to manipulate its markup before the HTML is send back
* to the browser.
*/
interface Processor {
/**
* Manipulates img tags.
*
* @param WP_HTML_Tag_Processor $p The HTML Tag Processor, set on the current image it's processing.
* @param string[] $critical_images The array of critical image src's.
* @param array<string, ImageAnalysis> $images The array of all collected images indexed by a unique key.
*
* @return void
*/
public function process( WP_HTML_Tag_Processor $p, array $critical_images, array $images ): void;
}

View File

@@ -0,0 +1,201 @@
<?php declare( strict_types=1 );
namespace KadenceWP\KadenceBlocks\Optimizer\Image;
use InvalidArgumentException;
use KadenceWP\KadenceBlocks\Optimizer\Enums\Viewport;
use KadenceWP\KadenceBlocks\Optimizer\Image\Contracts\Processor;
use KadenceWP\KadenceBlocks\Optimizer\Image\Traits\Image_Key_Generator_Trait;
use KadenceWP\KadenceBlocks\Optimizer\Path\Path;
use KadenceWP\KadenceBlocks\Optimizer\Path\Path_Factory;
use KadenceWP\KadenceBlocks\Optimizer\Skip_Rules\Rule_Collection;
use KadenceWP\KadenceBlocks\Optimizer\Store\Contracts\Store;
use KadenceWP\KadenceBlocks\Psr\Log\LoggerInterface;
use KadenceWP\KadenceBlocks\StellarWP\SuperGlobals\SuperGlobals as SG;
use KadenceWP\KadenceBlocks\Traits\Viewport_Trait;
use WP_HTML_Tag_Processor;
/**
* Modify HTML img tags before the HTML is sent back to the browser:
*
* - 1. Set correct lazy load attributes.
* - 2. Set the optimal sizes attribute.
*/
final class Image_Processor {
use Viewport_Trait;
use Image_Key_Generator_Trait;
private Store $store;
private Rule_Collection $rules;
private Path_Factory $path_factory;
/**
* The list of image processors.
*
* @var Processor[]
*/
private array $processors;
/**
* The logger.
*
* @var LoggerInterface
*/
private LoggerInterface $logger;
/**
* @param Store $store The optimization store.
* @param Rule_Collection $rules The rule collection.
* @param Path_Factory $path_factory The path factory.
* @param LoggerInterface $logger The logger.
* @param Processor[] $processors The list of image processors.
*/
public function __construct(
Store $store,
Rule_Collection $rules,
Path_Factory $path_factory,
LoggerInterface $logger,
array $processors
) {
$this->store = $store;
$this->rules = $rules;
$this->path_factory = $path_factory;
$this->logger = $logger;
$this->processors = $processors;
}
/**
* Begin buffering the request.
*
* @action template_redirect
*
* @return void
*/
public function start_buffering(): void {
// Process skip rules and bypass buffering.
foreach ( $this->rules->all() as $rule ) {
if ( $rule->should_skip() ) {
$this->logger->debug(
'Skipping Image Processor Buffering: skip rule',
[
'rule' => get_class( $rule ),
'request_uri' => SG::get_server_var( 'REQUEST_URI', 'unknown' ),
]
);
return;
}
}
ob_start( [ $this, 'stop_buffering' ] );
}
/**
* Modify each image using our collection of image processors.
*
* @see self::stop_buffering()
*
* @param string $html The HTML WordPress will render.
* @param Path $path The current path object.
*
* @return string
*/
public function process_images( string $html, Path $path ): string {
$analysis = $this->store->get( $path );
if ( ! $analysis ) {
return $html;
}
$device = $analysis->getDevice( Viewport::current( $this->is_mobile() ) );
$critical_images = $device ? $device->criticalImages : [];
$images = $analysis->images;
$images_by_key = [];
// Reshape the array so we can do O(1) lookups.
foreach ( $images as $image ) {
if ( isset( $image->src, $image->sizes ) ) {
$key = $this->generate_image_key( $image->src, $image->sizes );
if ( $key !== null ) {
$images_by_key[ $key ] = $image;
}
}
}
$p = new WP_HTML_Tag_Processor( $html );
// Add the kb-optimized class to the body.
if ( $p->next_tag( 'body' ) ) {
$p->add_class( 'kb-optimized' );
}
// Run each image through all image processors.
while ( $p->next_tag( 'img' ) ) {
$src = $p->get_attribute( 'src' );
$classes = $p->get_attribute( 'class' );
foreach ( $this->processors as $processor ) {
/**
* Allow short-circuiting of processing this image for the
* current processor.
*
* @param bool $should_process Whether we proceed with processing. Defaults to true.
* @param string $src The image src.
* @param string|null $classes The classes assigned to the img tag.
* @param Processor $processor The current processor instance.
* @param Path $post The current path object.
*/
$should_process = apply_filters(
'kadence_blocks_optimizer_image_processor',
true,
$src,
$classes,
$processor,
$path
);
if ( $should_process ) {
$processor->process( $p, $critical_images, $images_by_key );
}
}
}
return $p->get_updated_html();
}
/**
* Callback that receives the buffer's contents.
*
* @see wp_ob_end_flush_all()
* @action shutdown
*
* @param string $html The HTML WordPress will render.
* @param int $phase The bitmask of the PHP_OUTPUT_HANDLER_* constants.
*
* @return string The modified HTML with lazy loaded and optimal image sizes.
*/
private function stop_buffering( string $html, int $phase ): string {
if ( ! ( $phase & PHP_OUTPUT_HANDLER_FINAL ) ) {
return $html;
}
try {
$path = $this->path_factory->make();
} catch ( InvalidArgumentException $e ) {
$this->logger->error(
'Failed to get path in image processor buffering',
[
'exception' => $e,
]
);
return $html;
}
return $this->process_images( $html, $path );
}
}

View File

@@ -0,0 +1,66 @@
<?php declare( strict_types=1 );
namespace KadenceWP\KadenceBlocks\Optimizer\Image\Processors;
use KadenceWP\KadenceBlocks\Optimizer\Image\Contracts\Processor;
use KadenceWP\KadenceBlocks\Optimizer\Response\ImageAnalysis;
use WP_HTML_Tag_Processor;
final class Lazy_Load_Processor implements Processor {
/**
* A queue of URLs that are above the fold.
*
* @var string[]|null
*/
private ?array $critical_image_queue = null;
/**
* Add or remove the appropriate lazy loading attributes. It's important to note that WordPress
* may have already added a loading=lazy attribute to an image that shouldn't have it.
*
* @param WP_HTML_Tag_Processor $p The HTML Tag Processor, set on the current image it's processing.
* @param string[] $critical_images The list of the above the fold image URLs.
* @param array<string, ImageAnalysis> $images The array of all collected images indexed by a unique key.
*
* @return void
*/
public function process( WP_HTML_Tag_Processor $p, array $critical_images, array $images ): void {
$src = (string) $p->get_attribute( 'src' );
// Don't lazy load data URLs.
if ( str_starts_with( $src, 'data:' ) ) {
return;
}
// Initialize the queue on first run.
if ( ! isset( $this->critical_image_queue ) ) {
$this->critical_image_queue = $critical_images;
}
// Check if this image is next in our critical queue.
if ( $this->critical_image_queue ) {
$queue_index = array_search( $src, $this->critical_image_queue, true );
if ( $queue_index !== false ) {
// Remove lazy loading for critical image.
if ( 'lazy' === $p->get_attribute( 'loading' ) ) {
$p->remove_attribute( 'loading' );
}
// Remove this occurrence from the queue.
unset( $this->critical_image_queue[ $queue_index ] );
return;
}
}
// Below the fold logic (or after all critical images processed).
$p->set_attribute( 'loading', 'lazy' );
// If WordPress somehow added a high fetch priority, remove it.
if ( 'high' === $p->get_attribute( 'fetchpriority' ) ) {
$p->remove_attribute( 'fetchpriority' );
}
}
}

View File

@@ -0,0 +1,51 @@
<?php declare( strict_types=1 );
namespace KadenceWP\KadenceBlocks\Optimizer\Image\Processors;
use KadenceWP\KadenceBlocks\Optimizer\Image\Contracts\Processor;
use KadenceWP\KadenceBlocks\Optimizer\Image\Traits\Image_Key_Generator_Trait;
use KadenceWP\KadenceBlocks\Optimizer\Response\ImageAnalysis;
use WP_HTML_Tag_Processor;
final class Sizes_Attribute_Processor implements Processor {
use Image_Key_Generator_Trait;
/**
* Set the optimal sizes attribute for the image.
*
* @param WP_HTML_Tag_Processor $p The HTML Tag Processor, set on the current image it's processing.
* @param string[] $critical_images The array of critical image src's.
* @param array<string, ImageAnalysis> $images The array of all collected images indexed by a unique key.
*
* @return void
*/
public function process( WP_HTML_Tag_Processor $p, array $critical_images, array $images ): void {
// The analyzer doesn't collect images without a srcset.
$srcset = $p->get_attribute( 'srcset' );
if ( ! $srcset ) {
return;
}
$src = $p->get_attribute( 'src' );
$sizes = $p->get_attribute( 'sizes' );
$key = $this->generate_image_key( $src, $sizes );
if ( null === $key ) {
return;
}
$image = $images[ $key ] ?? false;
if ( ! $image instanceof ImageAnalysis ) {
return;
}
// Update the sizes attribute with our optimal sizes.
if ( $image->optimalSizes ) {
$p->set_attribute( 'sizes', $image->optimalSizes );
}
}
}

View File

@@ -0,0 +1,32 @@
<?php declare( strict_types=1 );
namespace KadenceWP\KadenceBlocks\Optimizer\Image;
use KadenceWP\KadenceBlocks\Optimizer\Image\Processors\Lazy_Load_Processor;
use KadenceWP\KadenceBlocks\Optimizer\Image\Processors\Sizes_Attribute_Processor;
use KadenceWP\KadenceBlocks\StellarWP\ProphecyMonorepo\Container\Contracts\Provider as Provider_Contract;
final class Provider extends Provider_Contract {
public function register(): void {
$this->container->singleton( Lazy_Load_Processor::class, Lazy_Load_Processor::class );
$this->container->singleton( Image_Processor::class, Image_Processor::class );
$this->container->when( Image_Processor::class )
->needs( '$processors' )
->give(
fn(): array => [
// Add additional image processors here.
$this->container->get( Lazy_Load_Processor::class ),
$this->container->get( Sizes_Attribute_Processor::class ),
]
);
add_action(
'template_redirect',
$this->container->callback( Image_Processor::class, 'start_buffering' ),
1,
0
);
}
}

View File

@@ -0,0 +1,28 @@
<?php declare( strict_types=1 );
namespace KadenceWP\KadenceBlocks\Optimizer\Image\Traits;
trait Image_Key_Generator_Trait {
/**
* Generate a unique key for indexing image data.
*
* @param string|null|bool $src The image source URL.
* @param string|null|bool $sizes The image sizes attribute.
*
* @return string|null A unique key or null if inputs are missing or non-string.
*/
private function generate_image_key( $src, $sizes ): ?string {
// Only allow actual strings.
if ( ! is_string( $src ) || ! is_string( $sizes ) ) {
return null;
}
// Bypass empty attributes.
if ( $src === '' || $sizes === '' ) {
return null;
}
return md5( $src . '|' . $sizes );
}
}