Вход Регистрация
Файл: symfony-2.7/src/Symfony/Component/Validator/Constraints/FileValidator.php
Строк: 407
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentValidatorConstraints;

use 
SymfonyComponentHttpFoundationFileFile as FileObject;
use 
SymfonyComponentHttpFoundationFileUploadedFile;
use 
SymfonyComponentValidatorContextExecutionContextInterface;
use 
SymfonyComponentValidatorConstraint;
use 
SymfonyComponentValidatorConstraintValidator;
use 
SymfonyComponentValidatorExceptionUnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class FileValidator extends ConstraintValidator
{
    const 
KB_BYTES 1000;
    const 
MB_BYTES 1000000;
    const 
KIB_BYTES 1024;
    const 
MIB_BYTES 1048576;

    private static 
$suffices = array(
        
=> 'bytes',
        
self::KB_BYTES => 'kB',
        
self::MB_BYTES => 'MB',
        
self::KIB_BYTES => 'KiB',
        
self::MIB_BYTES => 'MiB',
    );

    
/**
     * {@inheritdoc}
     */
    
public function validate($valueConstraint $constraint)
    {
        if (!
$constraint instanceof File) {
            throw new 
UnexpectedTypeException($constraint__NAMESPACE__.'File');
        }

        if (
null === $value || '' === $value) {
            return;
        }

        if (
$value instanceof UploadedFile && !$value->isValid()) {
            switch (
$value->getError()) {
                case 
UPLOAD_ERR_INI_SIZE:
                    
$iniLimitSize UploadedFile::getMaxFilesize();
                    if (
$constraint->maxSize && $constraint->maxSize $iniLimitSize) {
                        
$limitInBytes $constraint->maxSize;
                        
$binaryFormat $constraint->binaryFormat;
                    } else {
                        
$limitInBytes $iniLimitSize;
                        
$binaryFormat true;
                    }

                    list(
$sizeAsString$limitAsString$suffix) = $this->factorizeSizes(0$limitInBytes$binaryFormat);
                    if (
$this->context instanceof ExecutionContextInterface) {
                        
$this->context->buildViolation($constraint->uploadIniSizeErrorMessage)
                            ->
setParameter('{{ limit }}'$limitAsString)
                            ->
setParameter('{{ suffix }}'$suffix)
                            ->
setCode(UPLOAD_ERR_INI_SIZE)
                            ->
addViolation();
                    } else {
                        
$this->buildViolation($constraint->uploadIniSizeErrorMessage)
                            ->
setParameter('{{ limit }}'$limitAsString)
                            ->
setParameter('{{ suffix }}'$suffix)
                            ->
setCode(UPLOAD_ERR_INI_SIZE)
                            ->
addViolation();
                    }

                    return;
                case 
UPLOAD_ERR_FORM_SIZE:
                    if (
$this->context instanceof ExecutionContextInterface) {
                        
$this->context->buildViolation($constraint->uploadFormSizeErrorMessage)
                            ->
setCode(UPLOAD_ERR_FORM_SIZE)
                            ->
addViolation();
                    } else {
                        
$this->buildViolation($constraint->uploadFormSizeErrorMessage)
                            ->
setCode(UPLOAD_ERR_FORM_SIZE)
                            ->
addViolation();
                    }

                    return;
                case 
UPLOAD_ERR_PARTIAL:
                    if (
$this->context instanceof ExecutionContextInterface) {
                        
$this->context->buildViolation($constraint->uploadPartialErrorMessage)
                            ->
setCode(UPLOAD_ERR_PARTIAL)
                            ->
addViolation();
                    } else {
                        
$this->buildViolation($constraint->uploadPartialErrorMessage)
                            ->
setCode(UPLOAD_ERR_PARTIAL)
                            ->
addViolation();
                    }

                    return;
                case 
UPLOAD_ERR_NO_FILE:
                    if (
$this->context instanceof ExecutionContextInterface) {
                        
$this->context->buildViolation($constraint->uploadNoFileErrorMessage)
                            ->
setCode(UPLOAD_ERR_NO_FILE)
                            ->
addViolation();
                    } else {
                        
$this->buildViolation($constraint->uploadNoFileErrorMessage)
                            ->
setCode(UPLOAD_ERR_NO_FILE)
                            ->
addViolation();
                    }

                    return;
                case 
UPLOAD_ERR_NO_TMP_DIR:
                    if (
$this->context instanceof ExecutionContextInterface) {
                        
$this->context->buildViolation($constraint->uploadNoTmpDirErrorMessage)
                            ->
setCode(UPLOAD_ERR_NO_TMP_DIR)
                            ->
addViolation();
                    } else {
                        
$this->buildViolation($constraint->uploadNoTmpDirErrorMessage)
                            ->
setCode(UPLOAD_ERR_NO_TMP_DIR)
                            ->
addViolation();
                    }

                    return;
                case 
UPLOAD_ERR_CANT_WRITE:
                    if (
$this->context instanceof ExecutionContextInterface) {
                        
$this->context->buildViolation($constraint->uploadCantWriteErrorMessage)
                            ->
setCode(UPLOAD_ERR_CANT_WRITE)
                            ->
addViolation();
                    } else {
                        
$this->buildViolation($constraint->uploadCantWriteErrorMessage)
                            ->
setCode(UPLOAD_ERR_CANT_WRITE)
                            ->
addViolation();
                    }

                    return;
                case 
UPLOAD_ERR_EXTENSION:
                    if (
$this->context instanceof ExecutionContextInterface) {
                        
$this->context->buildViolation($constraint->uploadExtensionErrorMessage)
                            ->
setCode(UPLOAD_ERR_EXTENSION)
                            ->
addViolation();
                    } else {
                        
$this->buildViolation($constraint->uploadExtensionErrorMessage)
                            ->
setCode(UPLOAD_ERR_EXTENSION)
                            ->
addViolation();
                    }

                    return;
                default:
                    if (
$this->context instanceof ExecutionContextInterface) {
                        
$this->context->buildViolation($constraint->uploadErrorMessage)
                            ->
setCode($value->getError())
                            ->
addViolation();
                    } else {
                        
$this->buildViolation($constraint->uploadErrorMessage)
                            ->
setCode($value->getError())
                            ->
addViolation();
                    }

                    return;
            }
        }

        if (!
is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value'__toString'))) {
            throw new 
UnexpectedTypeException($value'string');
        }

        
$path $value instanceof FileObject $value->getPathname() : (string) $value;

        if (!
is_file($path)) {
            if (
$this->context instanceof ExecutionContextInterface) {
                
$this->context->buildViolation($constraint->notFoundMessage)
                    ->
setParameter('{{ file }}'$this->formatValue($path))
                    ->
setCode(File::NOT_FOUND_ERROR)
                    ->
addViolation();
            } else {
                
$this->buildViolation($constraint->notFoundMessage)
                    ->
setParameter('{{ file }}'$this->formatValue($path))
                    ->
setCode(File::NOT_FOUND_ERROR)
                    ->
addViolation();
            }

            return;
        }

        if (!
is_readable($path)) {
            if (
$this->context instanceof ExecutionContextInterface) {
                
$this->context->buildViolation($constraint->notReadableMessage)
                    ->
setParameter('{{ file }}'$this->formatValue($path))
                    ->
setCode(File::NOT_READABLE_ERROR)
                    ->
addViolation();
            } else {
                
$this->buildViolation($constraint->notReadableMessage)
                    ->
setParameter('{{ file }}'$this->formatValue($path))
                    ->
setCode(File::NOT_READABLE_ERROR)
                    ->
addViolation();
            }

            return;
        }

        
$sizeInBytes filesize($path);

        if (
=== $sizeInBytes) {
            if (
$this->context instanceof ExecutionContextInterface) {
                
$this->context->buildViolation($constraint->disallowEmptyMessage)
                    ->
setParameter('{{ file }}'$this->formatValue($path))
                    ->
setCode(File::EMPTY_ERROR)
                    ->
addViolation();
            } else {
                
$this->buildViolation($constraint->disallowEmptyMessage)
                    ->
setParameter('{{ file }}'$this->formatValue($path))
                    ->
setCode(File::EMPTY_ERROR)
                    ->
addViolation();
            }

            return;
        }

        if (
$constraint->maxSize) {
            
$limitInBytes $constraint->maxSize;

            if (
$sizeInBytes $limitInBytes) {
                list(
$sizeAsString$limitAsString$suffix) = $this->factorizeSizes($sizeInBytes$limitInBytes$constraint->binaryFormat);
                if (
$this->context instanceof ExecutionContextInterface) {
                    
$this->context->buildViolation($constraint->maxSizeMessage)
                        ->
setParameter('{{ file }}'$this->formatValue($path))
                        ->
setParameter('{{ size }}'$sizeAsString)
                        ->
setParameter('{{ limit }}'$limitAsString)
                        ->
setParameter('{{ suffix }}'$suffix)
                        ->
setCode(File::TOO_LARGE_ERROR)
                        ->
addViolation();
                } else {
                    
$this->buildViolation($constraint->maxSizeMessage)
                        ->
setParameter('{{ file }}'$this->formatValue($path))
                        ->
setParameter('{{ size }}'$sizeAsString)
                        ->
setParameter('{{ limit }}'$limitAsString)
                        ->
setParameter('{{ suffix }}'$suffix)
                        ->
setCode(File::TOO_LARGE_ERROR)
                        ->
addViolation();
                }

                return;
            }
        }

        if (
$constraint->mimeTypes) {
            if (!
$value instanceof FileObject) {
                
$value = new FileObject($value);
            }

            
$mimeTypes = (array) $constraint->mimeTypes;
            
$mime $value->getMimeType();

            foreach (
$mimeTypes as $mimeType) {
                if (
$mimeType === $mime) {
                    return;
                }

                if (
$discrete strstr($mimeType'/*'true)) {
                    if (
strstr($mime'/'true) === $discrete) {
                        return;
                    }
                }
            }

            if (
$this->context instanceof ExecutionContextInterface) {
                
$this->context->buildViolation($constraint->mimeTypesMessage)
                    ->
setParameter('{{ file }}'$this->formatValue($path))
                    ->
setParameter('{{ type }}'$this->formatValue($mime))
                    ->
setParameter('{{ types }}'$this->formatValues($mimeTypes))
                    ->
setCode(File::INVALID_MIME_TYPE_ERROR)
                    ->
addViolation();
            } else {
                
$this->buildViolation($constraint->mimeTypesMessage)
                    ->
setParameter('{{ file }}'$this->formatValue($path))
                    ->
setParameter('{{ type }}'$this->formatValue($mime))
                    ->
setParameter('{{ types }}'$this->formatValues($mimeTypes))
                    ->
setCode(File::INVALID_MIME_TYPE_ERROR)
                    ->
addViolation();
            }
        }
    }

    private static function 
moreDecimalsThan($double$numberOfDecimals)
    {
        return 
strlen((string) $double) > strlen(round($double$numberOfDecimals));
    }

    
/**
     * Convert the limit to the smallest possible number
     * (i.e. try "MB", then "kB", then "bytes")
     */
    
private function factorizeSizes($size$limit$binaryFormat)
    {
        if (
$binaryFormat) {
            
$coef self::MIB_BYTES;
            
$coefFactor self::KIB_BYTES;
        } else {
            
$coef self::MB_BYTES;
            
$coefFactor self::KB_BYTES;
        }

        
$limitAsString = (string) ($limit $coef);

        
// Restrict the limit to 2 decimals (without rounding! we
        // need the precise value)
        
while (self::moreDecimalsThan($limitAsString2)) {
            
$coef /= $coefFactor;
            
$limitAsString = (string) ($limit $coef);
        }

        
// Convert size to the same measure, but round to 2 decimals
        
$sizeAsString = (string) round($size $coef2);

        
// If the size and limit produce the same string output
        // (due to rounding), reduce the coefficient
        
while ($sizeAsString === $limitAsString) {
            
$coef /= $coefFactor;
            
$limitAsString = (string) ($limit $coef);
            
$sizeAsString = (string) round($size $coef2);
        }

        return array(
$sizeAsString$limitAsStringself::$suffices[$coef]);
    }
}
Онлайн: 1
Реклама