Snippets

Create an account or login to be able to add, comment and rate snippets.

Navigation

Popular Tags

action admin ajax batch cache cli criteria css custom database date debug doctrine email filter form forms generator helper i18n javascript login model mysql navigation object pager pagination pake plugin propel query session set sql template test user validation validator view

Latest comments latest comments

This is a public source code repository where you can find, rate and comment code snippets published by others, or store you owns and categorize them with tags for easy retrieval.

Latest snippets latest snippets

How to create a cacheable xml-rpc request

Recently I needed to use the xml-rpc lib with symfony. I created a function to make cache of xml-rpc requests using the symfony's sfFileCache and it work good.

I'm using the xml-rpc library http://phpxmlrpc.sourceforge.net/

public function callCache( $methodName, $params ){
 
  // generated a key to cache file
  $key = $methodName."_".implode('_', $params->getval() );
 
 
  $cache = new sfFileCache( array( 'cache_dir' => sfConfig::get('sf_cache_dir')."/xmlrpc/" ) );
 
  // check if already exist the cache file 
 
  if( ! $cache->has( $key ) ){
 
    //init xml-rpc message/
 
    $f = new xmlrpcmsg($methodName, $params);
 
    $f->addParam($params);
 
    $c = new xmlrpc_client("/xml-rpc", $this->host, 443, 'https' );
 
    $c->setCredentials($this->username, $this->password);
 
    $c->setDebug( $this->debug );
 
 
    $response = $c->send($f);
 
 
    $cache->set( $key , serialize( $response ), 3600);
 
 
  }else{
 
 
    $response = $cache->get( $key );
 
    $response = unserialize( $response );
 
 
  }
 
 
  if( ! $response->value() ){
 
    $this->erro( $response->errno, $response->faultString() );
 
  }
 
 
  $results = php_xmlrpc_decode( $response->value() );
 
 
  $this->rows = count($results);
 
 
  $this->data = $results;
 
}
 
by nei santos on 2009-07-02, tagged cache  xmlrpc 

How to validate that at least one checkbox has been checked

I spent some time trying to figure out how to make sure that one checkbox was checked before saving a form in symfony 1.2.

I read about Global Validators (http://www.symfony-project.org/forms/1_2/en/02-Form-Validation#chapter_02_global_validators) but I couldn't find anything to fit my needs. Finally, after looking at this snipped: http://www.symfony-project.org/cookbook/1_2/en/conditional-validator , I created the validation I needed, here is the snipped to help someone in the same situation:

class SampleForm extends BaseSampleForm
{
  public function configure()
  {
 
  // add a post validator
    $this->validatorSchema->setPostValidator(
      new sfValidatorCallback(array('callback' => array($this, 'checkAtLeastOne')))
    );
 
 
    unset(
      $this['created_at'], $this['updated_at']
 
    );
  }
 
  public function checkAtLeastOne($validator, $values)
  {
    if (!$values['sunday'] && !$values['monday'] && !$values['tuesday'] && !$values['wednesday'] && !$values['thursday'] && !$values['friday'] && !$values['saturday'])
    {
      // no checkbox was checked, throw an error
      throw new sfValidatorError($validator, 'Check at least one day of the week');
    }
 
    // at least one checkbox is checked, return the clean values
    return $values;
  }
 
 
}
 
by carlos m on 2009-06-26, tagged box  check  checkbox  checked  form  global  validator 
(2 comments)

Using timers to profile functions speed

This snippet allows you to evaluate functions speed and display them in symfony debug bar.

$timer = sfTimerManager::getTimer ('ldap_request'); // Create and start a new timer
 
// do some stuff
 
$timer->addTime (); // stop and store the timer value
 
by Arnaud Didry on 2009-06-22, tagged performance  profile  speed 
(2 comments)

Case-unsensitive filters with Symfony and Doctrine

Problematic

Environnement : Symfony 1.2 - sfDoctrinePlugin

Context : doctrine:generate-admin modules

Problème : filters case-sensitive

Objective : make filters case-unsensitive

Analysis

Every classes inherited from sfFormFilter alse inherite from BaseFormFilter, which is modifyable in every project. In the Doctrine case, sfFormFilterDoctrine and BaseFormFilterDoctrine. This class "Base" is here :

lib/filter/doctrine/BaseFormFilterDoctrine.class.php
 

The aimed method is the one which works on text fields. The line we want is the line 209 of the file symfony/lib/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php :

$query->addWhere('r.' . $fieldName . ' LIKE ?', '%' . $values['text'] . '%');
 

So a solution should be the override this method replacing LIKE by ILIKE. Let's try :

Solution

Overriding the class sfFormFilterDoctrine's method addTextQuery() should give you this kind of stuff if there is no more work done on it :

# lib/filter/doctrine/BaseFormFilterDoctrine.class.php
 /**
  * Project filter form base class.
  *
  * @packagefilters
  *
  * @versionSVN: $Id: sfDoctrineFormFilterBaseTemplate.php 11675 2008-09-19 15:21:38Z fabien $
  */
 abstract class BaseFormFilterDoctrine extends sfFormFilterDoctrine
 {
   public function setup()
   {
   }
 
   // totally inspirated from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php
   // function addTextQuery()
   // line modified : 209
   // be careful on symfony updates to update this method if there are changes
   protected function addTextQuery(Doctrine_Query $query, $field, $values)
   {
     $fieldName = $this->getFieldName($field);
 
     if (is_array($values) && isset($values['is_empty']) && $values['is_empty'])
     {
       $query->addWhere('r.' . $fieldName . ' IS NULL');
     }
     else if (is_array($values) && isset($values['text']) &&  != $values['text'])
     {
       // Here is the change, with "ILIKE" instead of "LIKE"
       $query->addWhere('r.' . $fieldName . ' ILIKE ?', '%' . $values['text'] . '%');
     }
   }
 }
 

References

The original documentation in french is available here :

http://www.e-glop.net/main/Filtres_case-unsensitive_dans_Symfony

by Baptiste SIMON on 2009-06-15, tagged caseinsensitive  casesensitive  filters  ilike 

sfValidatorFileImage : a simple validator for image file (symfony 1.2)

Description :

This is a class for symfony 1.2 for images. It extends the class sfValidatorFile.

<?php
 
/**
 * sfValidatorFileImage
 *
 * Original validator for symfony 1.0 : http://snippets.symfony-project.org/snippet/259
 *
 * @package    symfony
 * @subpackage validator
 * @author     Yoann Brieux <yoann |dot¤ brieux #at] gmail ~dot} com>
 * @version    0.1
 */
class sfValidatorFileImage extends sfValidatorFile
{
  /**
   * @param array $options   An array of options
   * @param array $messages  An array of error messages
   *
   * @see sfValidatorFile
   */
  protected function configure($options = array(), $messages = array())
  {
    parent::configure($options, $messages);
 
    $this->addMessage('invalid_image', '%value% is an incorrect image file.');
    $this->addMessage('max_height', '"%value%" height is too long (%max_height% pixels max).');
    $this->addMessage('min_height', '"%value%" height is too short (%min_height% pixels min).');
    $this->addMessage('max_width', '"%value%" width is too long (%max_width% pixels max).');
    $this->addMessage('min_width', '"%value%" width is too short (%min_width% pixels min).');
 
    $this->addOption('max_height');
    $this->addOption('min_height');
    $this->addOption('max_width');
    $this->addOption('min_width');    
    $this->addOption('is_only_image',false);    
  }
 
  /**
   * @see sfValidatorFile
   */
  protected function doClean($value)
  {
    $clean = parent::doClean($value);
 
    $size = @getimagesize($clean->getTempName());
 
    if (!$size && !$this->getOption('is_only_image')) 
    {
        return $clean;
    }
 
    if (!$size){    
      throw new sfValidatorError($this, 'invalid_image', array('value' => $value['name']));
    }
 
    list($width, $height) = $size;
 
    if($this->getOption('max_height') < $height){
        throw new sfValidatorError($this, 'max_height', array('value' => $value['name'], 'max_height' => $this->getOption('max_height')));
    }
 
    if($this->getOption('min_height') > $height){
        throw new sfValidatorError($this, 'min_height', array('value' => $value['name'], 'min_height' => $this->getOption('min_height')));
    }
 
    if($this->getOption('max_width') < $width){
        throw new sfValidatorError($this, 'max_width', array('value' => $value['name'], 'max_width' => $this->getOption('max_width')));
    }
 
    if($this->getOption('min_width') > $width){
        throw new sfValidatorError($this, 'min_width', array('value' => $value['name'], 'min_width' => $this->getOption('min_width')));
    }
 
    return $clean;
  }
}
 

How to use it?

In the your form library :

    $this->validatorSchema['field'] = new sfValidatorFileImage(array(
        'required'                          =>  false,
        'path'                              =>  sfConfig::get('sf_upload_dir').'/news/',
        'max_height'                        =>  238,
        'min_height'                        =>  238,
        'max_width'                         =>  270,
        'min_width'                         =>  270,
        'mime_types'                        =>  array('image/jpeg','image/pjpeg','image/png','image/x-png','image/gif','application/x-shockwave-flash')
        )
    );
 

If the variable "is_only_image" is true and function "getimagesize" return false (is not a valid image for example), this validator cause an sfValidatorError exception with the message "[your file] is an incorrect image file."

by Yoann Brieux on 2009-06-15, tagged 12  file  files  image  images  symfony  validator  validators 

A task to extract i18n labels from a form

A piece of code that will extract the existing labels from a form into a xliff file. It will only pick out the labels that have been set by the widgetForm->setLabel() command.

example for UserForm.class.php you can extract it using:

   php symfony i18n:extract-form user
 

.

<?php
 
class i18nExtractFormTask extends sfBaseTask
{
  protected function configure()
  {
    // // add your own arguments here
    // $this->addArguments(array(
    //   new sfCommandArgument('my_arg', sfCommandArgument::REQUIRED, 'My argument'),
    // ));
 
    $this->addOptions(array(
      new sfCommandOption('application', null, sfCommandOption::PARAMETER_REQUIRED, 'The application name', 'frontend'),
      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
      new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'default'),
      new sfCommandOption('source', null, sfCommandOption::PARAMETER_REQUIRED, 'Source language', 'en'),
      // add your own options here
    ));
 
    $this->addArgument('form', sfCommandOption::PARAMETER_REQUIRED, 'Name for the form to translate');
 
 
    $this->namespace        = 'i18n';
    $this->name             = 'extract-form';
    $this->briefDescription = 'Extracts the labels from a form';
    $this->detailedDescription = <<<EOF
The [i18n-extract-form|INFO] task extracts the labels from a form class into a XLIFF file.
Call it with:
   for CoolForm.class.php you can extract it using:
 
  [php symfony i18n-extract-form cool|INFO]
EOF;
  }
 
  protected function execute($arguments = array(), $options = array())
  {
    // initialize the database connection
    $databaseManager = new sfDatabaseManager($this->configuration);
    $connection = $databaseManager->getDatabase($options['connection'] ? $options['connection'] : null)->getConnection();
 
    $sFormname = ucfirst($arguments['form']).'Form';
    $oForm = new $sFormname(false);
    $labels = $oForm->getWidgetSchema()->getLabels();
    $sfMessageSource = new sfMessageSource_XLIFF(sfConfig::get('sf_app_i18n_dir'));
    $sfMessageSource->setCulture($options['source']);
    $sfMessageSource->load($sFormname);
    $existingMessages = $sfMessageSource->read();
    $aKeys = array_keys($existingMessages);
    $aMessages = array_keys($existingMessages[$aKeys[0]]);
    $unLabeled = array();
    foreach ($labels as $name => $value)
    {
        if (!is_null($value))
        {
 
            if (!in_array($value,$aMessages))
            {
                $sfMessageSource->append($value);
                $this->logSection('i18n', "Adding: " . $value);
            }
        } else {
            $unLabeled[] = $name;
        }
    }
 
 
    // an extra service: generate code for the not yet labeled parts: still a bit buggy
    $unLabeled = array_diff($unLabeled, array("_csrf_token"));
    $unLabeled = array_values($unLabeled);
 
       $return = "Code for unlabeled fields.:\n";
       foreach ($unLabeled as $label)
       {
           $return .= "\t\"" . '$this->widgetSchema->setLabel("' . $label .'","")'."\n";
       }
  }
}
 
by Adje on 2009-06-15, tagged form  i18n  xliff 

performing custom joins and hydrations with Propel

People using Propel who want to perform custom joins and especially hydrations probably all faced the limited functionality that Propel offers for this: the probably well known doSelectJoinAll and doSelectJoinXXX methods (and similar for the count functionality)

Whenever you want to join only two related tables (or more, but not all), a related-related table (or even deeper) or a table that is related by multiple foreign-keys (like created_by and updated_by both refering to a user) you will find it gets hard to do this with the default functionality offered by Propel.

I have written a Helper/Plugin that solves this limitation, that can be downloaded from the plugin-pages: http://www.symfony-project.org/plugins/sfPropelHelperPlugin

The plugin contains:

The plugin does not change the way how to work with Propel, it will only expand the possibilities while remaining completely backwards compatible.

An example of how to use this helper:

Imagine you have a class of albums, and that every album can contain photos as well as other albums. You request all photo's sorted reversed on album name and join the related table to get the table-name in one go.

propel:
  photo:
    id:
    album_id:
    name:     varchar(50)
 
  album:
    id:
    album_id:
    name:     varchar(50)
 

php code:

$this->getContext()->getConfiguration()->loadHelpers('sfPropelPropertyPath');
 
$criteria = new Criteria();
 
$sortColumn = AlbumPeer::alias(str_replace('.', '_', 'Photo.Album') , AlbumPeer::NAME); // this should be done nicer some day
$criteria->addDescendingOrderByColumn($sortColumn);
 
$objectPaths = array('Photo', 'Photo.Album'); // this can be reduced (is similar) to array('Photo.Album');
 
$criteria = addJoinsAndSelectColumns($criteria, $objectPaths);
$photos = hydrate($criteria, $objectPaths, $connection = null); // I haven't decided if I want hydrate to perform the joining as well
 
foreach ($photos as $photo)
{
  echo $photo->getAlbum()->getName()." -> ".$photo->getName()."<br>\n";
}
 

The resulting sql is:

SELECT Photo.ID, Photo.ALBUM_ID, Photo.NAME, Photo_Album.ID, Photo_Album.ALBUM_ID, Photo_Album.NAME FROM `photo` `Photo` LEFT JOIN album Photo_Album ON (Photo.ALBUM_ID=Photo_Album.ID) ORDER BY Photo_Album.NAME DESC
 

I designed so called ObjectPaths and PropertyPaths together with a colleague of mine (Frans van der Lek), to make it easier to define classes and respectively properties of the (related) classes. The Object Paths contain the name of the base-class, followed by the relation-names defined in the peer-classes. These relation-names are defined by the builder, but can be extended/modified by extending the basePeer class (getRelations)

You can extend your Classes with custom Get-methods that can be accessed with the property-paths. I will show how this all comes to use, in my next article about the sfDataSourcePlugin, that I will release soon. (A plugin that provides a generic interface to select, sort, filter and iterate-over rows, no matter if they are provided by Propel, Doctrine, an Array, an Imap connection, etc. The Datasource interface is very light (in contradiction to dbFinder (no offense)) which makes it easy to write your own implementation)

Please provide feedback, questions and if desired I can add more examples/info.

by Leon van der Ree on 2009-06-07, tagged criteria  custom  database  hydrate  join  model  propel  sfpropelhelperplugin 
(1 comment)

sfGuard Logging with Brute Force Login Prevention

For those of us who just need a bit more security out of this already awesome authentication plugin. This has been tested to work on symfony 1.2 using sfGuardPlugin version 3.1.3 stable.

The default behavior of this snippet is a log that tracks each login attempt, the IP, the username entered, and whether it was successful or not. The brute force protection's default settings will check to see if more than 5 attempts for the same username in the past 2 minutes were failed attempts. It also includes a cooldown period of 15 minutes from the last failed login attempt. All of these variables can be changed in the arguments for checkBruteForce().

The first thing we need to do is create a log for sfGuard. Do this by adding the following to the sfGuard schema and then rebuilding your models, forms, and filters:

plugins/sfGuardPlugin/config/schema.yml:

sf_guard_log:
    _attributes:    { phpName: sfGuardLog }
    id:             ~
    created_at:     ~
    ip:             { type: varchar }
    username:       { type: varchar }
    valid_login:    { type: boolean }
 

Next, we need to extend the peer class for this new sfGuardLog model to handle brute force protection.

plugins/sfGuardPlugin/lib/mode/sfGuardLoginPeer.php:

/*
    Auther: Christopher Lewis (chris@bluehousegroup.com)
 
    Check for brute force login attempts
 
    Case I
     1. Get all logins for this username in the past N minutes
     2. If P or more of them are fails, this is likely a brute force attempt, return true
 
    Case II
     1. Get last P logins
     2. Are they all fails? AND Are they all within the same window of N minutes? AND Was the last attempt within the past Q minutes?
        If all are true, return true
 
    Where:
     N = $attempt_window
     P = $allowed_fail_count
     Q = $cooldown_window
  */
  public static function checkBruteForce($username, $attempt_window = 2, $cooldown_window = 15, $allowed_fail_count = 5)
  {
    //Case I...
 
    $N_minutes_ago_timestamp = strtotime("$attempt_window minutes ago");
    $N_minutes_ago_sqltime = date('Y-m-d H:i:s', $N_minutes_ago_timestamp);
 
    $c = new Criteria();
    $c->add(sfGuardLogPeer::USERNAME, $username);
    $c->add(sfGuardLogPeer::CREATED_AT, $N_minutes_ago_sqltime, Criteria::GREATER_THAN);
    $entries = sfGuardLogPeer::doSelect($c);
 
    $failed_count = 0;
    foreach($entries as $log) { if($log->getValidLogin() == false) { $failed_count++; } }
 
    if($failed_count >= $allowed_fail_count) { return true; }
 
    //Case II...
 
    $all_fails = false; $all_in_window = false; $last_attempt_recent = false;
 
    //Are they all fails?
    $c = new Criteria();
    $c->add(sfGuardLogPeer::USERNAME, $username);
    $c->addDescendingOrderByColumn(sfGuardLogPeer::ID);
    $c->setLimit($allowed_fail_count);
 
    $failed_count = 0; $timestamps = array();
    $entries = sfGuardLogPeer::doSelect($c);
    foreach($entries as $pos => $log)
    {
      if($log->getValidLogin() == false) { $failed_count++; }
      array_push($timestamps, strtotime($log->getCreatedAt()));
    }
 
    if($failed_count >= $allowed_fail_count) { $all_fails = true; }
    else { return false; }
 
    //Are they all within the same window of N minutes?
    sort($timestamps);
    $time_a = $timestamps[0];
    $time_b = $timestamps[(count($timestamps) - 1)];
    $window_in_secs = $time_b - $time_a;
    $window_in_mins = $window_in_secs / 60;
 
    if($window_in_mins <= $attempt_window) { $all_in_window = true; }
    else { return false; }
 
    //Was the last attempt less than Q minutes ago?
    $Q_minutes_ago_timestamp = strtotime("$allowed_fail_count minutes ago");
    $last_attempt_timestamp = strtotime($entries[0]->getCreatedAt());
    if($Q_minutes_ago_timestamp <= $last_attempt_timestamp) { $last_attempt_recent = true; }
    else { return false; }
 
    //If all are true, return true
    if($all_fails == true && $all_in_window == true && $last_attempt_recent == true) { return true; }
 
    return false;  
  }
 

Last, we'll need to overload the executeSignin action in the sfGuardAuth module to include our new logging and security features:

plugins/sfGuardPlugin/modules/sfGuardAuth/actions.class.php

public function executeSignin($request)
  {
    $user = $this->getUser();
    if($user->isAuthenticated())
    {
      return $this->redirect('@homepage');
    }
 
    $class = sfConfig::get('app_sf_guard_plugin_signin_form', 'sfGuardFormSignin');
    $this->form = new $class();
 
    if($request->isMethod('post'))
    {
      $this->form->bind($request->getParameter('signin'));
      $values = $this->form->getValues();
 
      //Log attempts
      $log = new sfGuardLog();
      $log->setIp($_SERVER['REMOTE_ADDR']);
      $log->setUsername($request->getParameter('signin[username]'));
 
      //Check for brute force attempt
      $is_brute_force = sfGuardLogPeer::checkBruteForce($request->getParameter('signin[username]'));
 
      if($this->form->isValid() && !($is_brute_force))
      { 
        $this->getUser()->signin($values['user'], array_key_exists('remember', $values) ? $values['remember'] : false);
 
        //Used to disable concurrent logins       
        $this->getUser()->getGuardUser()->setSession(session_id());
        $this->getUser()->getGuardUser()->save();
 
        // always redirect to a URL set in app.yml
        // or to the referer
        // or to the homepage
        $signinUrl = sfConfig::get('app_sf_guard_plugin_success_signin_url', $user->getReferer('@homepage'));
 
        $log->setValidLogin(true);
        $log->save();
 
        return $this->redirect($signinUrl);
      }
      else
      { 
        $log->setValidLogin(false);
        $log->save();
      }
    }
  }
 
by Christopher Lewis on 2009-06-03, tagged authentication  brute  login  plugins  security  sfguard 

Case-insensitive URLs/routes

This works for symfony 1.2 and might be backwards compatible with 1.1 and 1.0, but I haven't tested it with those versions.

Place this file in an appropriate directory (eg. apps/myapp/lib/routing):

sfRegexExtendedRoute.class.php:

<?php
 
class sfRegexExtendedRoute extends sfRoute
{
  protected function compile()
  {
    $return = parent::compile();
 
    // Case-insensitive matching (default symfony behaviour = NOT case-insensitive).
    if (isset($this->options['case_sensitive']) && !$this->options['case_sensitive'])
    {
      // Make sure $this->regex is in the form "#...#[???]"
      // and that [???] does not already include "i" (the case-insensitive flag).
      if (($parts = explode('#', strrev($this->regex)))
          && 3 <= ($num_parts = count($parts))
          && '' == $parts[$num_parts-1]
          && false === strpos($parts[0], 'i'))
      {
        $this->regex .= 'i';
      }
    }
 
    return $return;
  }
}
 

Add the option case_sensitive: false in the route you want to make case-insensitive and set its class to sfRegexExtendedRoute:

apps/myapp/config/routing.yml:

...
my_route:
  url:      /my/case/insensitive/url/:whatever
  options:  { case_sensitive: false }
  class:    sfRegexExtendedRoute
...
 

Clear your cache:

> php symfony cc
 

Your url matching for that route should now be case-insensitive.

Changing case_sensitive: false to case_sensitive: true in routing.yml will revert the matching for that route back to (symfony default) case-sensitive matching.

by Nickolas Daskalou on 2009-05-24, tagged caseinsensitive  casesensistive  expression  regex  regular  route  routes  routing 

admin Generator and Thumnail generation in file uploads with symfony 1.2

Hello to the desperate,

As you might have probably already mentioned, the old way, how to produce thumbnails stopped working. This is because of the brand new admin generator, using an all new model based on forms, which doesn't support the old methods.

this is the new way, how to get it working again:

put this into your generator.yml file (take care for the correct identation, do not use tabs!!):

      edit:
        title: Photo uploads 
        fields:
          foto:
            type:       admin_input_file_tag
            upload_dir: /uploads/pictures/
            params:     include_link=/uploads/pictures/ include_remove=true
 

and then enhance the file lib/form/YourclassForm.php with the following method:

  protected function processUploadedFile($field, $filename = null, $values = null) {
    // first of all do what this is supposed to do
    $fn = parent::processUploadedFile($field, $filename, $values);
    // and now we can finally start doing additional stuff after the upload *hurra*
    if ($fn != "") {
        // if there is a file, that has been saved
        // multidimensional array that defines the sub-directories to store the thumbnails in
        $thumbnails[]=array('dir' => '90x90', 'width' => 90, 'height' => 90);
        $thumbnails[]=array('dir' => '200x200', 'width' => 200, 'height' => 200);
 
        foreach ($thumbnails as $thumbParam)
        {
          $currentFile = sfConfig::get('sf_upload_dir').'/pictures/'.$thumbParam['dir'].'/'. $fn;
          if (is_file($currentFile)) unlink($currentFile);
        }
        foreach ($thumbnails as $thumbParam)
        {
            $thumbnail = new sfThumbnail($thumbParam['width'], $thumbParam['height'],true,false); 
            $thumbnail->loadFile(sfConfig::get('sf_upload_dir')."/pictures/".$fn);
            $thumbnail->save(sfConfig::get('sf_upload_dir').'/pictures/'.$thumbParam['dir'].'/'.$fn, 'image/jpeg');
        }
    }
    // do not forget to return the value of the parent-function, otherwise it stops working
    return $fn;
  }  
 

Hope, you can use that snippet!

lg Christoph

by Christoph Christ on 2009-05-07, tagged admin  file  generator  sfthumbnail  symfony  uploads 
(1 comment)