![]() |
|
Snippets |
|
This images validations is an extention for the sfFileValidator. You can use it for validate uploaded images maximum width and height, minimum width and height and if the images have square dimensions.
<?php /** * sfFileImageValidator allows you to apply constraints to image file upload, it extend the sfFileValidator functions. * * <b>Optional parameters:</b> * * # <b>max_height</b> - [none] - Maximum images height in pixels. * # <b>max_height_error</b> - [The file height is too large] - An error message to use when * images height is too large. * # <b>max_width</b> - [none] - Maximum images width in pixels. * # <b>max_width_error</b> - [The file width is too large] - An error message to use when * images width is too large. * # <b>min_height</b> - [none] - Minimum images height in pixels. * # <b>min_height_error</b> - [The file height is too small] - An error message to use when * images height is too small. * # <b>min_width</b> - [none] - Minimum images width in pixels. * # <b>min_width_error</b> - [The file width is too small] - An error message to use when * images width is too small. * # <b>is_square</b> - [false] - The image is a square * # <b>is_square_error</b> - [The file is not a square] - An error message to use when * the images is not a square * (The width size is not equal * to the height size). * @package symfony * @subpackage validator * @author Daniel Santiago */ class sfFileImageValidator extends sfFileValidator { /** * Executes this validator. * * @param mixed A file or parameter value/array * @param error An error message reference * * @return bool true, if this validator executes successfully, otherwise false */ public function execute(&$value, &$error) { if (parent::execute($value, $error)) { list($width, $height) = @getimagesize($value['tmp_name']); // File is not a square $is_square = $this->getParameter('is_square'); if ($is_square && $width != $height) { $error = $this->getParameter('is_square_error'); return false; } // File height too large $max_height = $this->getParameter('max_height'); if ($max_height !== null && $max_height < $height) { $error = $this->getParameter('max_height_error'); return false; } // File width too large $max_width = $this->getParameter('max_width'); if ($max_width !== null && $max_width < $width) { $error = $this->getParameter('max_width_error'); return false; } // File height too small $min_height = $this->getParameter('min_height'); if ($min_height !== null && $min_height > $height) { $error = $this->getParameter('min_height_error'); return false; } // File width too small $min_width = $this->getParameter('min_width'); if ($min_width !== null && $min_width > $width) { $error = $this->getParameter('min_width_error'); return false; } return true; } } /** * Initializes this validator. * * @param sfContext The current application context * @param array An associative array of initialization parameters * * @return bool true, if initialization completes successfully, otherwise false */ public function initialize($context, $parameters = null) { // initialize parent parent::initialize($context, $parameters); // set defaults $this->getParameterHolder()->set('max_height', null); $this->getParameterHolder()->set('max_height_error', 'The file height is too large'); $this->getParameterHolder()->set('max_width', null); $this->getParameterHolder()->set('max_width_error', 'The file width is too large'); $this->getParameterHolder()->set('min_height', null); $this->getParameterHolder()->set('min_height_error', 'The file height is too small'); $this->getParameterHolder()->set('min_width', null); $this->getParameterHolder()->set('min_width_error', 'The file width is too small'); $this->getParameterHolder()->set('is_square', false); $this->getParameterHolder()->set('is_square_error', 'The file is not a square'); $this->getParameterHolder()->add($parameters); return true; } }
In the YAML validation file put this:
news{photo}: file: yes sfFileImageValidator: min_height: 100 min_height_error: 'The image height is too small, it must have minimum 100px' min_width: 120 min_width_error: 'The image width is too small, it must have minimum 120px' max_height: 960 max_height_error: 'The image height is too large, it must have maximum 960px' max_width: 450 max_width_error: 'The image width is too large, it must have maximum 450px' is_square: true is_square_error: 'The images must be a square (The height be equal to the width)' max_size: 256000 max_size_error: 'The maximum images size is 250Kb' mime_types_error: 'We only accept GIF, PNG and JPEG.' mime_types: - 'image/jpeg' - 'image/png' - 'image/gif'
This one is a port of the Imagetext plugin for Smarty. So as I won't include the credit in this snippet please check them in the Smarty plugin itself here.
In order to make it work, this is what you need : - A 'fonts' folder in your projects' data directory, in which you copy the .ttf files you need - The following helper :
function imagetext($text,$styleName=null,$params=array()) { if(!$styleName){ $styleName='default'; } if (empty($text)) { return; } // Which style is in use $style=sfConfig::get('app_imagetext_styles'); $style=$style[$styleName]; // Param values overwrite style values foreach ($params as $key=>$value) $style[$key] = $value; // Error handling if (empty($style['font'])) { throw new sfViewException("imagetext: missing 'font' parameter"); return; } if (empty($style['size'])) { throw new sfViewException("imagetext: missing 'size' parameter"); return; } if (empty($style['bgcolor'])) { $style['bgcolor'] = 'FFFFFF'; } if (empty($style['fgcolor'])) { $style['fgcolor'] = '000000'; } ### Preferences $cacheDir=sfConfig::get('sf_web_dir').DIRECTORY_SEPARATOR.'images'.DIRECTORY_SEPARATOR.'imagetext'.DIRECTORY_SEPARATOR; $cacheUrl='imagetext/'; $fontDir=sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR; $text = preg_replace("=<br( /)?>=i", "\n", $text); // Which font is in use $font = $fontDir.$style['font']; // Hash of text and all parameters for the cache function $hash = md5(implode('',$style).$text); // The url of the created image $imgFile = $cacheDir.$styleName.'_'.$hash.'.'.$style['format']; $imgUrl = $cacheUrl.$styleName.'_'.$hash.'.'.$style['format']; ### Use cached image if available if (file_exists($imgFile) && @$style['dev'] != true && @$style['dynamic'] != true) if (@$style['urlonly'] == 'true') return $imgUrl; else return @$style['prehtml'].image_tag($imgUrl,array('style'=>'border: 0 px solid #00ff00','alt'=>preg_replace("=\r\n|\r|\n|\t=", ' ', htmlspecialchars($text)))).@$style['posthtml']; ### otherwise create it // Function to get a color handler of hex values if (!function_exists('fromhex')) { function fromhex($image,$string) { sscanf($string, "%2x%2x%2x", $red, $green, $blue); return ImageColorAllocate($image,$red,$green,$blue); } } ### create a four times larger image to improve kerning // The multiplier. The bigger the better the kerning and the typeface, but the slower the creation $multi = 4; // If "pixelfont" don“t use multiplier if ($style['pixelfont'] == 1) $multi = 1; // Calculate measures of image $bbox = imagettfbbox ($style['size']*$multi, 0, $font, $text); $xcorr = 0-$bbox[6]; // northwest X $ycorr = 0-$bbox[7]; // northwest Y $box['left'] = $bbox[6]+$xcorr+$style['x']*$multi; $box['height'] = abs($bbox[5])+abs($bbox[1]); $box['width'] = abs($bbox[2])+abs($bbox[0])+$style['x']*$multi; $box['top'] = abs($bbox[5]); // Create the big image $im = imagecreate ($box['width'], $box['height']); $bgcolor = fromhex($im,$style['bgcolor']); $fgcolor = fromhex($im,$style['fgcolor']); if ($style['pixelfont'] == 1) $fgcolor = -$fgcolor; imagettftext ($im, $style['size']*$multi, 0, $box['left'], $box['top'], $fgcolor, $font, $text); // Sample down the big image $width = $style['width']+$style['addx']; $height = $style['height']+$style['addy']; // Overwrite when height oder width is given if (empty($style['width'])) $width = $box['width']/$multi+$style['addx']+$style['x']; if (empty($style['height'])) $height = $box['height']/$multi+$style['addy']+$style['y']; $ds = imagecreatetruecolor ($width, $height); $bgcolor2 = fromhex($ds,$style['bgcolor']); imageFill($ds,0,0,$bgcolor2); imagecopyresampled($ds,$im,0,$style['y'],0,0,$box['width']/$multi, $box['height']/$multi,$box['width'], $box['height']); imagetruecolortopalette($ds,0,256); imagepalettecopy($ds,$im); ImageColorTransparent($ds,$bgcolor); // write whereto? if ($style['format'] == 'gif') ImageGIF ($ds,$imgFile); else ImagePNG ($ds,$imgFile); ImageDestroy ($im); ImageDestroy ($ds); // and display if ($style['dev']) $border = 1; else $border = 0; if ($style['urlonly'] == 'true') return $imgUrl; else return $style['prehtml'].image_tag($imgUrl,array('style'=>'border: '.$border.'px solid #00ff00','alt'=>preg_replace("=\r\n|\r|\n|\t=", ' ', htmlspecialchars($text)))).$style['posthtml']; }
As you can see in this code styles can (at least 'default' MUST be) be configured in app.yml. This is an example style config :
imagetext:
styles:
default:
font: hockey.ttf
size: 18
format: png
So now you can use the helper in your templates :
<?php use_helper('imageText') ?> <? echo imagetext('This is my title') ?> <p>Some blah blah</p> <? echo imagetext('This is another headline style','anotherstyle') ?>
This helper uses GD so depending on which version you have installed, you might or might not handle PNG or GIF.
Ever wanted to have a captcha image verification, but didn't want to go through the trouble of using the jgraph lib? Me too! Here's what I came up with.
sfCaptcha.class.php in /lib
class sfCaptcha { public $securityCode; private $codeLength=6; private $imageFile= 'captchaImg.jpg'; public $fontSize = 12; public $fontColor = array("252525","8b8787","550707"); public function simpleRandString($length, $list="23456789ABDEFGHJKLMNQRTYabdefghijkmnqrty") { /* * Generates a random string with the specified length * Chars are chosen from the provided [optional] list */ mt_srand((double)microtime()*1000000); $newstring = ""; if ($length > 0) { while (strlen($newstring) < $length) { $newstring .= $list[mt_rand(0, strlen($list)-1)]; } } return $newstring; } public function generateImage() { $this->securityCode = $this->simpleRandString($this->codeLength); $img_path = dirname(__FILE__)."/../web/uploads/"; if(!is_writable($img_path) && !is_dir($img_path)){ $error = "The image path $img_path does not appear to be writable or the folder does not exist. Please verify your settings"; throw new Exception($error); } $this->img = ImageCreateFromJpeg($img_path.$this->imageFile); $img_size = getimagesize($img_path.$this->imageFile); foreach($this->fontColor as $fcolor) { $color[] = imagecolorallocate($this->img, hexdec(substr($fcolor, 1, 2)), hexdec(substr($fcolor, 3, 2)), hexdec(substr($fcolor, 5, 2)) ); } $line = imagecolorallocate($this->img,255,255,255); $line2 = imagecolorallocate($this->img,200,200,200); $fw = imagefontwidth($this->fontSize)+3; $fh = imagefontheight($this->fontSize); // create a new string with a blank space between each letter so it looks better $newstr = ""; for ($i = 0; $i < strlen($this->securityCode); $i++) { $newstr .= $this->securityCode[$i] ." "; } // remove the trailing blank $newstr = trim($newstr); // center the string $x = ($img_size[0] - strlen($newstr) * $fw ) / 2; $font[0] = 'arial.ttf'; $font[1] = 'TIMES.ttf'; $font[2] = 'COURI.ttf'; // create random lines over text for($i=0; $i <3;$i++){ $s_x = rand(40,180); $s_y = rand(5,35); $e_x = rand(($s_x-50), ($s_x+50)); $e_y = rand(5,35); $c = rand(0, (count($color)-1)); imageline($this->img, $s_x,$s_y, $e_x,$e_y, $color[$c]); } // random bg ellipses imageellipse($this->img, $s_x, $s_y, $e_x, $e_y, $line); imageellipse($this->img, $e_x, $e_y, $s_x, $s_y, $line2); // output each character at a random height and standard horizontal spacing for ($i = 0; $i < strlen($newstr); $i++) { $hz = mt_rand( 10, $img_size[1] - $fh - 5); // randomize rotation $rotate = rand(-35, 35); // randomize font size $this->fontSize = rand(14, 18); // radomize color $c = rand(0, (count($color)-1)); // imagechar( $this->img, $this->fontSize, $x + ($fw*$i), $hz, $newstr[$i], $color); imagettftext($this->img, $this->fontSize,$rotate , $x + ($fw*$i), $hz + 12, $color[0], $font[$c], $newstr[$i]); } } }
in the moduleyou want to use, in my case the user module add the following to your actions.
// replace XXX with the name of the action that is calling the form, like validateRegistration if your action is executeRegistration. // This function validates the stored captcha against the users input and returns true if they match, or returns an error back to the form if they don't. public function validateXXX() { if($this->getRequest()->getMethod() == sfRequest::POST) { $captcha = $this->getRequestParameter('captcha'); $session_captcha = $this->getUser()->getAttribute('captcha'); if($captcha != $session_captcha) { $this->getRequest()->setError('captcha', 'The code you entered did not match the one provided, please try again.'); return false; } } return true; } // action that executes the actual image public function executeGetImage() { $this->getResponse()->setContentType('image/jpeg'); $captcha = new sfCaptcha(); $captcha->generateImage(); $this->getUser()->setAttribute('captcha', $captcha->securityCode); imagejpeg($captcha->img); imageDestroy($captcha->img); }
and the in the view showing the image and form
<div class='error'><?php echo form_error('captcha') ?></div> <img src='<?php echo url_for('user/getimage'); ?>'><br> <?php echo input_tag('captcha') ?>
Note that the image source user/getimage refers to my user module and the executeGetImage() function we added above.
You'll need to add a JPG to your /web/uploads/ directory with the size of 200px w x 40px h and the name "captchaImg.jpg" (you can change the name in the sfCaptcha.classs.php file too). This is used to generate the captcha image and if you choose so you can create a background in the image that will be used. Otherwise, just leave it blank.