Building a Joomla! Content Plugin - Dynamically Generate Thumbnails

03.04.2014

Joomla! makes it incredibly easy to build custom content plugins for your site—they even give you an example plugin in every install.

Let's walk through a practical application of a content plugin. Say you've created a beautiful website for your client that incorporates images in a Category Blog view.

Great, right? Well, you've probably run into instances where clients insert images that are ridiculously large.

Since you don't have time to resize every single image for the client (and you cringe at the idea of a client with Photoshop), why not create a Joomla! content plugin to do this dynamically?

The Plugin

zimage_intro.xml

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin" group="content">
	<name>plg_content_zimage_intro</name>
	<author>Company Name</author>
	<creationDate>March 2014</creationDate>
	<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
	<authorUrl>www.website.com</authorUrl>
	<version>3.0.0</version>
	<description>PLG_CONTENT_ZIMAGE_INTRO_XML_DESCRIPTION</description>

	<files>
		<filename plugin="zimage_intro">zimage_intro.php</filename>
		<filename>index.html</filename>
	</files>
	<languages>
		<language tag="en-GB">en-GB.plg_content_zimage_intro.ini</language>
		<language tag="en-GB">en-GB.plg_content_zimage_intro.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
			
				<field name="th_height"
					type="text"
					filter="integer"
					label="Thumbnail Height"
					default="200"
					size="5" />
					
				<field name="th_width"
					type="text"
					filter="integer"
					label="Thumbnail Width"
					default="200"
					size="5" />
			
				<field name="categories"
					type="category"
					label="Categories"
					default="0"
					multiple="true"
					extension="com_content">
					
					<option value="0">All Categories</option>
					
				</field>
				
			</fieldset>
		</fields>
	</config>

</extension>

zimage_intro.php

<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.joomla
 */

defined('_JEXEC') or die;

class PlgContentZimage_intro extends JPlugin
{
	/**
	 * Article is passed by reference
	 * Method is called right before the content is saved
	 *
	 * @param   string   $context  The context of the content passed to the plugin (added in 1.6)
	 * @param   object   $article  A JTableContent object
	 * @param   boolean  $isNew    If the content is just about to be created
	 *
	 * @return  boolean   true if function not enabled, is in front-end or is new. Else true or
	 *                    false depending on success of save function.
	 *
	 * @since   1.6
	 */
	public function onContentBeforeSave($context, $article, $isNew)
	{
	
		// Check we are handling the frontend edit form.
		if ($context != 'com_content.form')
		{
			return true;
		}

		// Check this is a new article.
		if (!$isNew)
		{
			//return true;
		}
		
		$images = json_decode($article->images);
		
		//Let's check that we have an intro image set & that it actually exists
		if( !empty($images->image_intro) && file_exists(JPATH_SITE.'/'.$images->image_intro) ){
		
			jimport('joomla.filesystem.file');
			jimport( 'joomla.image.image' );
			
			if (!class_exists('JFolder')){
				jimport('joomla.filesystem.folder');
			}
			
			//Set the paths for the photo directories
			$asset_dir = JPath::clean( JPATH_SITE.'/images/intro_thumbnails/' );
			
			//Create the gallery folder
			if( !JFolder::exists( $asset_dir ) ){
				JFolder::create( $asset_dir );
				JFile::copy( JPATH_SITE.'/images/index.html', $asset_dir.'index.html');
			}
			
			//Get the native file properties
			$native_dest = JPATH_SITE.'/'.$images->image_intro;	
			$nativeProps = Jimage::getImageFileProperties( $native_dest );
			
			$thumbnail_dest = JPATH_SITE.'/images/intro_thumbnails/'.JFile::getName($native_dest);
			
			if( !file_exists($thumbnail_dest) ){
			
				//Let's only create a thumbnail version if one of the dimensions is smaller than those set in the plugin parameters
				if( $nativeProps->width > $this->params->get('th_width', '200') || $nativeProps->height > $this->params->get('th_height', '200') ){
				
					//Generate thumbnail
					$jimage	= new JImage();
					$jimage->loadFile( $native_dest );
					$thumbnail = $jimage->resize( $this->params->get('th_width', '200'), $this->params->get('th_height', '200'), true, JImage::SCALE_OUTSIDE );
					$thumbnail->toFile( $thumbnail_dest, $nativeProps->type );
					
				}
				
			}

			//Set the thumbnail as the image_intro
			$images->image_intro = 'images/intro_thumbnails/'.JFile::getName($native_dest);
			
			//Set the new $images object for the article
			$article->images = json_encode($images);
			
		}

		return true;
	}

}

Think of the above code as a starting point since you'll want to incorporate some error handling and file validation (and possibly other bits of code to improve performance).

This particular plugin does all its magic in the onContentBeforeSave content event, but you can experiment with the other events to accomplish different things.

The content events are very powerful and one of the main reasons we build most of our sites in Joomla!.

Have a question? Leave it in the comments!