Silverstripe Custom Validator on Uploadfield

一曲冷凌霜 提交于 2019-12-24 02:24:22

问题


I am using foresight.js to load hi-res images for retina devices. Foresight attempts to replace lo-res images with 2x-pixel density images. Since foresight attempts to replace lo-res images before the page has rendered, it is not possible for me to use the GD image resizing methods in the template for my resized images. So, I am allowing the SS 3.1 cms user to upload one large image and having the system re-size it after upload - leaving a 1x and 2x image in the assets folder.

My question is how can I set a custom validation error message if the cms user does not upload a large enough image?

Here is the code that resizes the image on upload.

class ResampledImage extends Image {
    static $default_lores_x = 250;
    static $default_lores_y = 250;
    static $default_hires_x = 500;
    static $default_hires_y = 500;
    static $default_assets_dir = 'Uploads';
    static $hires_flag = '2x';

    function getLoResX() {
        return ( static::$lores_x ) ? static::$lores_x : self::$default_lores_x;    
    }

    function getLoResY() {
        return ( static::$lores_y ) ? static::$lores_y : self::$default_lores_y;
    }

    function getHiResX() {
        return ( static::$hires_x ) ? static::$hires_x : self::$default_hires_x;
    }

    function getHiResY() {
        return ( static::$hires_y ) ? static::$hires_y : self::$default_hires_y;
    }

    function getAssetsDir() {
        return ( static::$assets_dir ) ? static::$assets_dir : self::$default_assets_dir;
    }

    function onAfterUpload() {
        $this->createResampledImages();
    }

    function onAfterWrite() {
        $this->createResampledImages();
    }

    function createResampledImages() {
        $extension = strtolower($this->getExtension());
        if( $this->getHeight() >= $this->getHiResX() || $this->getWidth() >= $this->getHiResY() ) {
        $original = $this->getFullPath();
        $resampled = $original. '.tmp.'. $extension;    

        $orig_title = $this->getTitle();
        $path_to_hires = Director::baseFolder() . '/' . ASSETS_DIR . '/' . $this->getAssetsDir();
        $hires =  $path_to_hires . '/' . $orig_title . self::$hires_flag . '.' . $extension;

        $gd_lg = new GD($original);
        $gd_sm = new GD($original);

        if ( $gd_lg->hasImageResource() ) {
            $gd_lg = $gd_lg->resizeRatio($this->getHiResX(), $this->getHiResY());

            if ( $gd_lg ) 
                $gd_lg->writeTo($hires);
        }

        if($gd_sm->hasImageResource()) {
            $gd_sm = $gd_sm->resizeRatio($this->getLoResX(), $this->getLoResY());

            if($gd_sm) {
                $gd_sm->writeTo($resampled);
                unlink($original);
                rename($resampled, $original);
            }
        }
    }
}  

Looking at UploadField::setFileEditValidator() it appears that I can designate a method on my extended Image class to use as a Validator so that I can check for $this->getWidth() and $this->getHeight() and return an error if they are not large enough.

Is this possible?

I tried adding the following method to ResampledImage, but this was unsuccessful:

function MyValidator() {
    $valid = true;

    if ( $this->getHeight() < $this->getHiResX() || $this->getWidth() < $this->getHiResY() ) {
        $this->validationError("Thumbnail",'Please upload a larger image');
        $valid = false;
    }

    return $valid;
}

回答1:


I think the fileEditValidator is acutally used after the image has been uploaded and is for the EditForm when displayed/edited.

Seems that what you are looking for is validate the Upload. You can set a custom Upload_Validator with setValidator($validator) on your UploadField.

So what I would try is create a custom validator class (maybe named CustomUploadValidator) that extends Upload_Validator (source can be found in the Upload.php file in the framework). So, something along those lines:

$myValidator = new CustomUploadValidator();
$uploadField->setValidator($myValidator);

In your custom validator class maybe create a method isImageLargeEnough() which you would call in the validate() method:

public function validate() {

    if(!$this->isImageLargeEnough()) {
        $this->errors[] = 'Image size is not large enough';
        return false;
    }

    return parent::validate();
}

In your isImageLargeEnough() you can access the uploaded image through $this->tmpFile. So maybe do something like:

public function isImageLargeEnough()
{
    $imageSize = getimagesize( $this->tmpFile["tmp_name"] );
    if ($imageSize !== false)
    {
        if ( $imageSize[0] < 500 || $imageSize[1] < 500 )
        {
            return false;
        }
    }       
    return true;
}

Here the min width/height are hard coded to 500, but you can probably implement a setMinImageSizes method that stores those on a variable in your custom validator class. which could be called like $uploadField->getValidator()->setMinImageSize(543, 876);

None of this is actually tested, but hopefully it can give you some pointers on what to look for.



来源:https://stackoverflow.com/questions/18242663/silverstripe-custom-validator-on-uploadfield

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!