Statuses—Other Media [ 232 ] Changes to the view Since all of the media types we are going to support require at least one additional database eld in a table that extends the statuses table, we are going to need to display any additional elds on the post status form. The standard type of status doesn't require additional elds, and new media types that we haven't discussed, which we may wish to support in the future, may require more than one additional eld. To support a varying number of additional elds depending on the type, we could use some JavaScript (in this case, we will use the jQuery framework) to change the form depending on the context of the status. Beneath the main status box, we can add radio buttons for each of the status types, and depending on the one the user selects, the JavaScript can show or hide the additional elds, making the form more relevant. Template Our update status template needs a few changes: • We need to set the enctype on the form, so that we can upload les (for posting images) • We need radio buttons for the new types of statuses • We need additional elds for those statuses The changes are highlighted in the following code segment: <p>Tell your network what you are up to</p> <form action="profile/statuses/{profile_user_id}" method="post" enctype="multipart/form-data"> <textarea id="status" name="status"></textarea> <br /> <input type="radio" name="status_type" id="status_checker_update" class="status_checker" value="update" />Update <input type="radio" name="status_type" id="status_checker_video" class="status_checker" value="video" />Video <input type="radio" name="status_type" id="status_checker_image" class="status_checker" value="image" />Image <input type="radio" name="status_type" id="status_checker_link" class="status_checker" value="link" />Link <br /> <div class="video_input extra_field"> <label for="video_url" class="">YouTube URL</label> <input type="text" id="" name="video_url" class="" /><br /> </div> <div class="image_input extra_field"> This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 8 [ 233 ] <label for="image_file" class="">Upload image</label> <input type="file" id="" name="image_file" class="" /><br /> </div> <div class="link_input extra_field"> <label for="link_url" class="">Link</label> <input type="text" id="" name="link_url" class="" /><br /> <label for="link_description" class="">Description</label> <input type="text" id="" name="link_description" class="" /><br /> </div> <input type="submit" id="updatestatus" name="updatestatus" value="Update" /> </form> These changes also need to be made to the post template, for posting on another user's prole. jQuery to enhance the user experience For accessibility purposes, we need this form to function regardless of whether the user has JavaScript enabled on their browser. To that end, we should use JavaScript to hide the unused form elements. So, even if the user has JavaScript disabled, they can still use all aspects of the form. We can then use JavaScript to enhance the user experience, toggling which aspects of the form are hidden or shown. <script type="text/javascript"> $(function() { First, we hide all of the extended status elds. $('.extra_field').hide(); $("input[name='status_type']").change(function(){ When the user changes the type of status, we hide all of the extended elds. $('.extra_field').hide(); We then show the elds directly related to the status type they have chosen. $('.'+ $("input[name='status_type']:checked").val() + '_input').show(); }); }); </script> This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Statuses—Other Media [ 234 ] View in action If we now take a look at our status updates page for our prole, we have some radio buttons that we can use to toggle elements of the form. Images To process images as a new status type, we will need a new database table and a new model to extend from the main status model. We will also need some new views, and to change the prole and status stream controllers (though we will make those changes after adding the three new status types). Database table The database table for images simply needs two elds: Field Type Description ID Integer, Primary key To relate to the main statuses table Image Varchar The image lename These two elds will be connected to the statuses table via a left join, to bring in the image lename for statuses that are images. This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 8 [ 235 ] Model The model needs to extend our statuses model, providing setters for any new elds, call the parent constructor, call the parent setTypeReference method to inform that it is an image, call the parent save method to save the status, and then insert a new record into the image status table with the image information. Class, variable, and constructor Firstly, we dene the class as an extension of the status class. We then dene a variable for the image, and construct the object. The constructor calls the parent setTypeReference method to ensure it generates the correct type ID for an image, and then calls the parent constructor so it too has reference to the registry object. This le is saved as /models/imagestatus.php. <?php /** * Image status object * extends the base status object */ class Imagestatus extends status { private $image; /** * Constructor * @param Registry $registry * @param int $id * @return void */ public function __construct( Registry $registry, $id = 0 ) { $this->registry = $registry; parent::setTypeReference('image'); parent::__construct( $this->registry, $id ); } To call a method from an object's parent class, we use the parent keyword, followed by the scope resolution operator, followed by the method we wish to call. This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Statuses—Other Media [ 236 ] Processing the image upload When dealing with image uploads, resizing, and saving, there are different PHP functions that should be used depending on the type of the image. To make this easier and to provide a centralized place for dealing with image uploads and other image-related tasks, we should create a library le ( lib/images/imagemanager. class.php ) to make this easier. Let's discuss what an image manager library le should do to make our lives easier: • Process uploading of an image from $_POST data ° Verify the type of le and the le extension • Process images from the le system so that we can modify them • Display an image to the browser • Resize an image • Rescale an image by resizing either the x or y co-ordinate, and scaling the other co-ordinate proportionally • Get image information such as size and name • Save the changes to the image The following is the code required to perform the above-mentioned tasks: <?php /** * Image manager class * @author Michael Peacock */ class Imagemanager { /** * Type of the image */ private $type = ''; /** * Extensions that the user can upload */ private $uploadExtentions = array( 'png', 'jpg', 'jpeg', 'gif' ); /** * Mime types of files the user can upload */ private $uploadTypes = array( 'image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png' ); This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 8 [ 237 ] /** * The image itself */ private $image; /** * The image name */ private $name; public function __construct(){} We need a method to load a local image, so that we can work with images saved on the servers le system. /** * Load image from local file system * @param String $filepath * @return void */ public function loadFromFile( $filepath ) { Based on the path to the image, we can get information on the image including the type of image (getimagesize gives us an array of information on the image; the second element in the array is the type). $info = getimagesize( $filepath ); $this->type = $info[2]; We can then compare the image type to various PHP constants, and depending on the image type (JPEG, GIF, or PNG) we use the appropriate imagecreatefrom function. if( $this->type == IMAGETYPE_JPEG ) { $this->image = imagecreatefromjpeg($filepath); } elseif( $this->type == IMAGETYPE_GIF ) { $this->image = imagecreatefromgif($filepath); } elseif( $this->type == IMAGETYPE_PNG ) { $this->image = imagecreatefrompng($filepath); } } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Statuses—Other Media [ 238 ] We require a couple of getter methods to return the height or width of the image. /** * Get the image width * @return int */ public function getWidth() { return imagesx($this->image); } /** * Get the height of the image * @return int */ public function getHeight() { return imagesy($this->image); } We use a simple resize method that resizes the image to the dimensions we request. /** * Resize the image * @param int $x width * @param int $y height * @return void */ public function resize( $x, $y ) { $new = imagecreatetruecolor($x, $y); imagecopyresampled($new, $this->image, 0, 0, 0, 0, $x, $y, $this->getWidth(), $this->getHeight()); $this->image = $new; } Here we use a scaling function that takes a height parameter to resize to and scales the width accordingly. /** * Resize the image, scaling the width, based on a new height * @param int $height * @return void */ public function resizeScaleWidth( $height ) { This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 8 [ 239 ] $width = $this->getWidth() * ( $height / $this->getHeight() ); $this->resize( $width, $height ); } Similar to the above method, this method takes a width parameter, resizes the width, and rescales the height based on the width. /** * Resize the image, scaling the height, based on a new width * @param int $width * @return void */ public function resizeScaleHeight( $width ) { $height = $this->getHeight() * ( $width / $this->getWidth() ); $this->resize( $width, $height ); } The following is another scaling function, this time to rescale the image to a percentage of its current size: /** * Scale an image * @param int $percentage * @return void */ public function scale( $percentage ) { $width = $this->getWidth() * $percentage / 100; $height = $this->getheight() * $percentage / 100; $this->resize( $width, $height ); } To output the image to the browser from PHP, we need to check the type of the image, set the appropriate header based off the type, and then use the appropriate image function to render the image. After calling this method, we need to call exit() to ensure the image is displayed correctly. /** * Display the image to the browser - called before output is sent, exit() should be called straight after. * @return void */ public function display() { if( $this->type == IMAGETYPE_JPEG ) This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Statuses—Other Media [ 240 ] { $type = 'image/jpeg'; } elseif( $this->type == IMAGETYPE_GIF ) { $type = 'image/gif'; } elseif( $this->type == IMAGETYPE_PNG ) { $type = 'image/png'; } header('Content-Type: ' . $type ); if( $this->type == IMAGETYPE_JPEG ) { imagejpeg( $this->image ); } elseif( $this->type == IMAGETYPE_GIF ) { imagegif( $this->image ); } elseif( $this->type == IMAGETYPE_PNG ) { imagepng( $this->image ); } } To load an image from $_POST data, we need to know the post eld the image is being sent through, the directory we wish to place the image in, and any additional prex we may wish to add to the image's name (to prevent conicts with images with the same name). /** * Load image from postdata * @param String $postfield the field the image was uploaded via * @param String $moveto the location for the upload * @param String $name_prefix a prefix for the filename * @return boolean */ public function loadFromPost( $postfield, $moveto, $name_prefix='' ) { This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 8 [ 241 ] Before doing anything, we should check that the le requested is actually a le that has been uploaded (and that this isn't a malicious user trying to access other les). if( is_uploaded_file( $_FILES[ $postfield ]['tmp_name'] ) ) { $i = strrpos( $_FILES[ $postfield ]['name'], '.'); if (! $i ) { //'no extention'; return false; } else { We then check that the extension of the le is in our allowed extensions array. $l = strlen( $_FILES[ $postfield ]['name'] ) - $i; $ext = strtolower ( substr( $_FILES[ $postfield ]['name'], $i+1, $l ) ); if( in_array( $ext, $this->uploadExtentions ) ) { Next, we check if the le type is an allowed le type. if( in_array( $_FILES[ $postfield ]['type'], $this->uploadTypes ) ) { Then, we move the le, as it has already been uploaded to our server's temp folder, to our own uploads directory and load it into our image manager class for any further processing we wish to make. $name = str_replace( ' ', '', $_FILES[ $postfield ]['name'] ); $this->name = $name_prefix . $name; $path = $moveto . $name_prefix.$name; move_uploaded_file( $_FILES[ $postfield ]['tmp_name'] , $path ); $this->loadFromFile( $path ); return true; } else { // 'invalid type'; return false; } } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com . ); if( $this->type == IMAGETYPE_JPEG ) { imagejpeg( $this->image ); } elseif( $this->type == IMAGETYPE_GIF ) { imagegif( $this->image ); } elseif( $this->type == IMAGETYPE_PNG. imagecreatetruecolor($x, $y); imagecopyresampled($new, $this->image, 0, 0, 0, 0, $x, $y, $this->getWidth(), $this->getHeight()); $this->image = $new; } Here we use a scaling function. $width = $this->getWidth() * $percentage / 100; $height = $this->getheight() * $percentage / 100; $this->resize( $width, $height ); } To output the image to the browser from PHP, we need