Environment
- Template: Gazette 2.0.5 (
shaper_gazette) with Helix Ultimate framework plugin 2.2.10 - SP Page Builder 6.10.0 (Pro)
- Joomla 5.4.10, PHP 8.3, MySQL 8.4
- News site with thousands of Joomla articles; the homepage is an SP Page Builder page that uses the Gazette addons Articles, Articles Slider and Articles Vertical Slider. Many articles have no featured image (or no generated
_small/_medium/_largesizes).
The problem
The Gazette template ships its own SP Page Builder addons in templates/shaper_gazette/sppagebuilder/addons/. Their site.php files read $item->image_small, $item->image_medium and $item->image_large directly, without checking that the property exists.
Those properties are optional. In SP Page Builder's article helper (components/com_sppagebuilder/helpers/articles.php, the "Featured Image" block), they are only created when:
- the article has a featured image (
helix_ultimate_imageorspfeatured_imagein its attributes), and - the matching resized file (
<name>_small.<ext>,<name>_medium.<ext>,<name>_large.<ext>) exists on disk.
Only image_thumbnail always gets a value (it falls back to the original image). So for every article without a featured image, or whose resized copies were never generated, the addons read a property that isn't there. On PHP 8 each read raises Warning: Undefined property: stdClass::$image_small (or $image_medium / $image_large). It happens once per article per render, so on a busy homepage the error log fills with the same warnings.
A visible side effect: in the slider addons, the missing value is concatenated into the inline style, so the HTML contains style="background-image: url();" for every slide without an image. We see this on our homepage today, in the Articles Slider.
Affected reads in the shipped 2.0.5 files:
sppagebuilder/addons/articles/site.php, inside the thumbnail block (if ($article_layout != "modern" && $article_layout != "masonry" && !$hide_thumbnail)): every non-K2 branch assigns$image = $item->image_small;/$item->image_medium;/$item->image_large;directly. The K2 branch just above already guards withisset(...) && ..., so the Joomla branches are inconsistent with it.sppagebuilder/addons/articles_slider/site.php, in the items loop:$bgimage = 'style="background-image: url('/ . $item->image_medium . ');"';when$slider_style == "bg_image", and'<img src="' . $item->image_small . '" ...'when it isn't.sppagebuilder/addons/articles_vertical_slider/site.php, in the items loop: the same two patterns ($item->image_mediumfor the background,$item->image_smallfor the<img>).
The Thumb Gallery addon in the same folder already does this correctly (isset($item->image_large) && $item->image_large, and so on), so the fix is just to apply the same pattern to the other three.
Suggested fix
Read the optional sizes with a null-coalescing default, and only output the style or <img> when there is a value. This is backwards-compatible: articles that have images render exactly as now.
1. articles/site.php, non-K2 branches. Replace each direct read with a defaulted one, e.g.
} elseif ($article_layout == "horizontal" || ($article_layout == "creative" && $key > 1)) {
$image = $item->image_small ?? '';
} elseif ($article_layout == "simple" && $item->post_format == 'video' && $key == 0) {
$image = $item->image_medium ?? '';
}
// ...same for every other branch: $item->image_large ?? '', $item->image_medium ?? ''
The code that follows already handles an empty $image.
2. articles_slider/site.php and 3. articles_vertical_slider/site.php, items loop:
$bgimage = '';
if ($slider_style == "bg_image" && !empty($item->image_medium)) {
$bgimage = 'style="background-image: url('/ . $item->image_medium . ');"';
}
and for the non-background style:
if ($slider_style != "bg_image" && !empty($item->image_small)) {
$output .= '<div class="sppb-article-img-wrapper">';
$output .= '<img src="' . $item->image_small . '" class="' . $lazyestload_class . '" data-src="' . $item->image_small . '" alt="image">';
$output .= '</div>';
}
Optional improvement: a fallback chain with a placeholder image. Instead of outputting nothing, the addons could pick the first image that exists:
- the requested size (
image_small/image_medium/image_large); image_thumbnail, which the helper always sets when there is a featured image (it falls back to the original upload). This covers articles whose resized copies were never generated.- a placeholder image chosen in a new optional setting (a media field in the addon settings, or once in the template options so it applies to all addons);
- nothing, as in the guarded code above.
For example:
$image = $item->image_medium ?? $item->image_thumbnail ?? $placeholder;
where $placeholder is the configured image, or '' when none is set.
To keep current behaviour, the placeholder setting should be empty by default. Sites that leave it empty get the plain guarded output (no warnings, no empty url();). Sites that set it keep a consistent grid or slider layout when an article has no picture, which matters most for the background-image slider styles, where an imageless slide otherwise has no visual at all. The placeholder <img> should keep the article title as its alt text, like the other images.
What we already applied locally (it stopped the repeated warnings from these two addons on our site):
articles/site.php, horizontal/creative branch:} elseif ($article_layout == "horizontal" || ($article_layout == "creative" && $key > 1)) { if (isset($item->image_small)) { $image = $item->image_small; }articles_vertical_slider/site.php, items loop:if (property_exists($item, 'image_medium') && $slider_style == "bg_image") { $bgimage = 'style="background-image: url('/ . $item->image_medium . ');"'; }Our local patch covers only the branches our layouts use. The suggested fix above covers every branch in all three files.
Impact
- Affects every Gazette site whose SP Page Builder pages list articles without a featured image or without generated image sizes, which is common on news sites and for older content.
- On PHP 8 the reads are warnings, not notices, so they reach the error log on default settings, once per article on every uncached page render.
- In the sliders, the empty
url();style is invalid output for every imageless slide. - The fix is a few one-line changes that follow the pattern Thumb Gallery already uses, with no change for articles that have images.
- Right now any site that patches these files loses the fix on every template update, so a vendor fix would let us drop our local patch.