Sunday, February 5, 2012

Image resize filter for xupload in Yii framework

I was recently testing a wonderful AJAX upload widget xupload for Yii framework and decided that I want to resize the picture after it was uploaded. I found another extension Image that did the trick perfectly, but one question remained: where should I put image resize code, so that I wouldn't have to change the xupload code?
That's when I decided I should learn how to make filters for Yii! I made a file PostUploadFilter.php and put in protected/filters.

<?php
Yii
::import('application.extensions.image.Image');
class
PostUploadFilter extends CFilter{
protected function
preFilter($filterChain)
{

return true; // we have nothing to do here
}

protected function
postFilter($filterChain)
{

// first we need the name of our file
$model = new XUploadForm;
$model->file = CUploadedFile::getInstance($model, 'file');
$model->name = $model->file->getName();

// let's find the full path to our file
$path=realpath(Yii::app()->getBasePath()."/../images/uploads/1");
$path=$path.'\\';
// load the image, resize if it's wider than 1000px, save!
$image = new Image($path.$model->name);
if(
$image->width>1000)
$image->resize(1000,NULL);
$image->save($path.$model->name);

}
}
?>


Then I added the filter to my controller.

public function filters()
{
return array(
array(
'application.filters.PostUploadFilter + upload'),
);
}

We want the filter to work only when the "upload" action takes place, hence the "+ upload".

7 comments:

  1. It is great to see someone creating quality widgets for the Yii. We have been working on an open source CRM application that is written in PHP utilizing JQuery, Yii, and RedBeanPHP and relies heavily on test driven development. It might be one of the most complex projects on Yii to date.

    Right now, we have 1000+ unit tests running across eight server configurations. We utilize selenium as well for a nice set of functional tests too. It would be incredibly helpful to get your technical feedback and recommendations so that we can improve the application. Take a look and let me know what you think:
    http://zurmo.org

    ReplyDelete
    Replies
    1. I looked at your CRM. A noble deed you took upon yourselves. I can but imagine how much effort it will take to produce a competitive open source CRM.

      I wanted to point out some performance issues, but I saw a blog post as of today, where Jason Green announced performance improvement.
      When I click "edit" on the dashboard it takes too much time to load the form. It takes me about 0.6 seconds to receive the HTML, but the scripts take too much time to load - jquery.min.js and jquery-ui.min.js. I'm not an expert in CRM software, but you might want to try speeding that up by loading those script from Google servers.
      Good luck.

      Delete
  2. Thanks for the advice. We will be doing some additional performance tweaks as we go. We will take this into consideration. We also have the js minified into one file, but for the ajax calls we had to still use non-minified for the moment. We will be changing this in the future

    ReplyDelete
  3. Hi,

    This is exactly what I was looking for, my question is how can I use:
    path=realpath(Yii::app()->getBasePath()."/../images/uploads/".$_GET['id']);

    The url of the view is: http://localhost/yiigallery/gallery/view?id=3

    ReplyDelete
    Replies
    1. Hello. I noticed your comment only today, thus the late reply.

      In case you still haven't found a solution I would love to help you. I can't see what you want in particular from what you have written. Please post as much details about what is it that you want to achieve and/or which problems you have encountered.

      Delete
  4. Just for future reference...
    If you are dealing with xupload then you have to check if the method type doesn't equal 'delete'. In such case postUploadFilter throws an exception during the delete process.

    ReplyDelete
    Replies
    1. If you haven't noticed this line ensures that the filter is executed only with the 'upload' method:
      array('application.filters.PostUploadFilter + upload'),

      So we don't have to perform any additional checks.

      Delete