images/blog/correccion-php-.jpg

Si gestionas sitios en Joomla, es posible que recientemente te hayas encontrado con una situación frustrante: tu web funciona perfectamente de cara al público, pero al intentar editarla desde el frontend con SP Page Builder, la pantalla se queda en blanco o arroja un error fatal.

Este problema suele aparecer "de la nada", pero casi siempre tiene un culpable silencioso: una actualización de tu servidor a PHP 8 combinada con el plugin de optimización de imágenes DJ-WebP.

El Síntoma: Un error crítico en PHP 8

El mensaje de error específico que suele aparecer es similar a este:

imagepalettetotruecolor(): Argument #1 ($image) must be of type GdImage, false given

Básicamente, PHP 8 se ha vuelto muy estricto. El plugin intenta procesar una imagen que no existe o es temporal (algo común cuando el editor de SP Page Builder está activo), y en lugar de ignorarla, el servidor detiene todo el proceso provocando un error fatal.

La Solución: Parchear el archivo djimgtowebp.php

Hasta que los desarrolladores lancen una actualización oficial que cubra completamente la compatibilidad con PHP 8.4+, podemos aplicar un pequeño parche de seguridad manualmente. El objetivo es decirle al código: "Si la imagen falla al cargar, ignórala y sigue funcionando".

Paso 1: Localiza el archivo

Accede a tus archivos vía FTP o desde el administrador de archivos de tu hosting y busca la siguiente ruta:

/plugins/system/djimgtowebp/djimgtowebp.php

Paso 2: Aplica el código corregido

Debemos modificar la función encargada de crear la imagen para asegurarnos de que la variable no esté vacía antes de procesarla. A continuación, comparto el código completo del archivo con la corrección de seguridad ya aplicada.

Simplemente, haz una copia de seguridad de tu archivo actual, borra su contenido y pega este código íntegro:

<?php
/**
 * @version     1.0
 * @package     DJ Img To Webp
 * Fix PHP 8 compatibility by adding null checks for image creation
 */

defined('_JEXEC') or die;

jimport('joomla.plugin.plugin');
jimport('joomla.filesystem.file');

require_once JPATH_ROOT.'/plugins/system/djimgtowebp/helper.php';
require_once JPATH_ROOT.'/plugins/system/djimgtowebp/lib/autoload.php';

use WebPConvert\WebPConvert;

class PlgSystemDJImgToWebp extends JPlugin
{
    protected $_webps;

    function onAfterRender()
    {
        $app = JFactory::getApplication();
        $user = JFactory::getUser();

        if (JFactory::getDocument()->getType() !== 'html' || !$app->isClient('site')) {
            return;
        }

        $gdInfo = gd_info();
        if(!isset($gdInfo['WebP Support']) OR !$gdInfo['WebP Support']) return;

        if($this->menuItemIsExcluded()) return;

        if (DJWebPHelper::browserSupportWebp()) {
            $sHtml = $app->getBody();
            $filters =(array) $this->params->get('filters');

            $webp_purge = $app->input->get('webp_purge', false, 'bool');
            $purge = false;
            if ($webp_purge ) {
                $purge = true;
            }

            $debugData = array();

            if(is_countable($filters) && count($filters)) {
                foreach ($filters as $filter) {
                    if ($filter->directory) {
                        $extensions = $filter->extensions;
                        $quality = $filter->quality;
                        $stored_time = $filter->stored_time;
                        $excluded = $filter->excluded;
                        $excludedArr = strlen($excluded) ? explode(';', $excluded) : array();

                        $debugData[$filter->directory] = array();
                        $debugTarget =  &$debugData[$filter->directory];

                        if (substr($filter->directory, 0, 1) === '/') {
                            $filter->directory = substr($filter->directory, 1);
                        }

                        if (substr($filter->directory, -1) === '/') {
                            $filter->directory = substr($filter->directory, 0, -1);
                        }

                        if(count($extensions)) {
                            $regexPath = str_replace("/", "\/", $filter->directory);
                            $sHtml = preg_replace_callback(
                                '/' . $regexPath . '\/\S+(?:' . implode( '|',$extensions) . ')\b/',
                                function ($match) use ($quality, $stored_time, $excludedArr,  $purge, &$debugTarget, $regexPath, $extensions) {
                                    $img = $match[0];
                                    $imgInfo = pathinfo($img);
                                    $extensionsArr = explode("|",implode( '|',$extensions));
                                    if (!in_array($imgInfo['extension'],$extensionsArr)) {
                                        return $img;
                                    }
                                    $newImg = $this->imgToWebp($img, $quality, $excludedArr,  $stored_time, $purge, $regexPath, $match);
                                    
                                    $debugTarget[] = array(
                                        'source' => $img,
                                        'target' => $newImg
                                    );

                                    return $newImg ? $newImg : $img;
                                },
                                $sHtml
                            );
                        }
                    }
                }
            }

            if($this->params->get('debug')) {
                $sHtml .= '
' . print_r($debugData, true) . '
'; } $app->setBody($sHtml); } } private function menuItemIsExcluded() { $app = JFactory::getApplication(); $excludedMenuItems = $this->params->get('excludedMenus', array(), 'array'); $activeMenu = $app->getMenu()->getActive(); if(isset($activeMenu->id)) return in_array($activeMenu->id, $excludedMenuItems); else return false; } private function isExcludedDirectory($image, $excluded) { $exist = false; foreach ($excluded as $exclude) { if( strpos( $image, $exclude ) !== false) { $exist = true; break; } } return $exist; } private function exifOrientationRotate($imgObject, $imgPath, $imgMime) { if (function_exists('exif_read_data') && $imgMime == 'image/jpeg') { $file_exif = @exif_read_data($imgPath); if (!is_array($file_exif) || !isset($file_exif['Orientation'])) { return $imgObject; } switch ($file_exif['Orientation']) { case 3: $degrees = 180; break; case 6: $degrees = 270; break; case 8: $degrees = 90; break; default: $degrees = 0; } if ($degrees > 0) { $imgObject = imagerotate($imgObject, $degrees, 0xffffff); } } return $imgObject; } private function imgToWebp($image, $quality = 100, $excluded = array(), $stored_time = 5, $purgePrevious = false, $regexPath = '', $fullRegex = '') { $imgPath = JPATH_ROOT . '/' . $image; $imgInfo = pathinfo($imgPath); $imgHash = md5($imgPath); if(!isset($imgInfo['extension']) || !$imgInfo['extension']) return; if(count($excluded)) { if(in_array($image, $excluded) || $this->isExcludedDirectory($image, $excluded)) { return; } } if(JFile::exists($imgPath)) { if ((mime_content_type($imgPath) != 'image/jpeg') && (mime_content_type($imgPath) != 'image/png')) { return; } if (!isset($this->_webps[$imgHash])) { $newImagePath = $imgInfo['dirname'] . '/'; if ($this->params->get('includeFileExtension') == '1' ) { $newImage = $newImagePath . $imgInfo['filename'] . '_'. $imgInfo['extension'] . '.webp'; } else { $newImage = $newImagePath . $imgInfo['filename'] . '.webp'; } if (JFile::exists($newImage) && $stored_time != '0') { $fileCreated = filemtime($newImage); if($fileCreated && (((time() - $fileCreated) / 3600) >= $stored_time || $purgePrevious)) { JFile::delete($newImage); } } if (!JFile::exists($newImage)) { if (JFile::exists($imgPath)) { if($this->params->get('mode') !== '') { // --- FIX START: Secure image creation --- $img = null; switch (strtolower($imgInfo['extension'])) { case 'png' : $img = @imagecreatefrompng($imgPath); break; case 'jpg' : case 'jpeg' : $img = @imagecreatefromjpeg($imgPath); } // If image creation failed, abort to avoid PHP 8 Fatal Error if (!$img) { return; } // --- FIX END --- if (!JFolder::exists($newImagePath)) { JFolder::create($newImagePath); } imagepalettetotruecolor($img); imagealphablending($img, true); imagesavealpha($img, true); $img = $this->exifOrientationRotate($img, $imgPath, mime_content_type($imgPath)); imagewebp($img, $newImage, $quality); if (function_exists('imagedestroy')) { imagedestroy($img); } } elseif ($this->params->get('mode') == 'library' ) { $options = array( 'converters' => array($this->params->get('method', 'gd')), 'convert' => ['quality' => $quality] ); WebPConvert::convert($imgPath, $newImage, $options); } } } $newFile = str_replace(JPATH_ROOT . '/', "", $newImage); $this->_webps[$imgHash] = $newFile; } return $this->_webps[$imgHash]; } } public function onAjaxDJImgToWebp() { $app = JFactory::getApplication(); $like = trim($app->input->get('like', null, 'string')); $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('m.id AS value, m.title AS text') ->from($db->quoteName('#__menu', 'm')) ->where($db->quoteName('m.title') . ' LIKE ' . $db->quote('%' . $db->escape($like) . '%')) ->where('m.menutype <> ' . $db->quote('main')) ->where('m.published = 1'); $query->order('title ASC'); $db->setQuery($query); $results = $db->loadObjectList(); echo json_encode($results); $app->close(); } } 

Nota importante: Recuerda que si actualizas el plugin en el futuro, este archivo se sobrescribirá y el error podría volver si el desarrollador no ha incluido una solución oficial. Te recomiendo guardar este artículo en favoritos por si necesitas volver a aplicar el parche.

Artículos relacionados:

¿Quieres que te avisemos de lo más reciente?

Si quieres recibir en tu correo las nuevas publicaciones, solo tienes que decirlo.

Contenido que es posible que te interese:

Colaboraciones, amigos y partners

logo paco guio
logo joomla madrid
Logo de joomla day España

Este sitio esta aalojado en un servidor que utilliza energías verdes - verificado por thegreenwebfoundation.org