Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SonataMediaBundle: How to add svg file extension

I need to add .svg file extension to my configuration.

At the moment in my project I have other extensions as (pdf, images)

I made the following changes

  1. Added a new svg_file to the context
  2. Added the file provider (In the end of configuration file)
  3. Added the svg in allowed_extensions
  4. Added the image/svg+xml in allowed_mime_types

Now, I can upload the svg file but the problem is that the user can upload other file extensions for example pdf etc..

How can avoid it? Or find a proper way for the form validation?

The Sonata documentations:

  • ADVANCED CONFIGURATION

  • Media context

helped me, but not for the form validation.

What I'm missing?


I changed the follows files:

#app/config/sonata_config.yml

sonata_media:
default_context: images_file
db_driver: doctrine_orm # or doctrine_mongodb, doctrine_phpcr
contexts:
    pdf_file:
        providers:
            - sonata.media.provider.file
        formats: ~
    images_file:
        providers:
            - sonata.media.provider.image
        formats:
            1x: { width: 870 , height: 412 , quality: 80 }
            2x: { width: 1740 , height: 824 , quality: 50 }
    svg_file:
        providers:
            - sonata.media.provider.file
        formats: ~
    cdn:
        server:
          path: /uploads/media # http://media.sonata-project.org/

    filesystem:
        local:
           directory:  %kernel.root_dir%/../web/uploads/media
           create:     false

    providers:
        file:
           service:    sonata.media.provider.file
           resizer:    false
           filesystem: sonata.media.filesystem.local
           cdn:        sonata.media.cdn.server
           generator:  sonata.media.generator.default
           thumbnail:  sonata.media.thumbnail.format
           allowed_extensions: ['pdf', 'txt', 'rtf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pttx', 'odt', 'odg', 'odp', 'ods', 'odc', 'odf', 'odb', 'csv', 'xml','svg']
           allowed_mime_types: ['application/pdf', 'application/x-pdf', 'application/rtf', 'text/html', 'text/rtf', 'text/plain', 'image/svg+xml']

Form File:

use Sonata\AdminBundle\Admin\Admin;
class CustomAdmin extends Admin
{
/**
 * @param FormMapper $formMapper
 */
protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->add(
            'NormalLogo',
            'sonata_type_model_list',
            array('required' => false),
            array(
                'link_parameters' => array('context' => 'images_file', 'provider' => 'sonata.media.provider.image'),
            )
        )
        ->add(
            'SvgLogo',
            'sonata_type_model_list',
            array('required' => false),
            array(
                'link_parameters' => array('context' => 'svg_file', 'provider' => 'sonata.media.provider.file'),
            )
        )
        ->add('overriddenBy', 'sonata_type_model',
            array(
                'empty_value' => 'Not overridden',
                'btn_add' => false,
                'btn_list' => false,
                'btn_delete' => false,
                'btn_catalogue' => false,
            )
        );
}
}
like image 283
Reyela Avatar asked Oct 20 '22 13:10

Reyela


1 Answers

You can create your own provider for SVG files only to do this you need to define a service first for your SVG provider

parameters:
    application_sonata_media.svg_class: Application\Sonata\MediaBundle\Provider\SVGProvider
services:
    sonata.media.provider.svg:
          class: %application_sonata_media.svg_class%
          tags:
              - { name: sonata.media.provider }
          arguments:
              - sonata.media.provider.svg
              - @sonata.media.filesystem.local
              - @sonata.media.cdn.server
              - @sonata.media.generator.default
              - @sonata.media.thumbnail.format
              - allowed_extensions: ['svg']
              - allowed_mime_types: ['image/svg+xml']

Using sonata you can generate extended bundles using EASYEXTENDS BUNDLE by default it generates extended bundle in src/Application/Sonata/MediaBundle but you can specify other destination as well.Now create above service in extended media bundle's services.yml and import in main config.yml.If you want to add more mime types or extensions you can define in above service allowed_mime_types: ['image/svg+xml','application/pdf']

imports:
    - { resource: @ApplicationSonataMediaBundle/Resources/config/services.yml }

Now create your provider class in your extended media bundle as SVGProvider and extend your provider class with sonata media's FileProvider

<?php
namespace Application\Sonata\MediaBundle\Provider;

use Sonata\MediaBundle\Provider\FileProvider as BaseFileProvider;
use Gaufrette\Filesystem;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Validator\ErrorElement;
use Sonata\MediaBundle\CDN\CDNInterface;
use Sonata\MediaBundle\Generator\GeneratorInterface;
use Sonata\MediaBundle\Metadata\MetadataBuilderInterface;
use Sonata\MediaBundle\Model\MediaInterface;
use Sonata\MediaBundle\Thumbnail\ThumbnailInterface;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotNull;

class SVGProvider extends BaseFileProvider {
    protected $allowedMimeTypes;
    protected $allowedExtensions;
    protected $metadata;

    public function __construct( $name, Filesystem $filesystem, CDNInterface $cdn, GeneratorInterface $pathGenerator, ThumbnailInterface $thumbnail, array $allowedExtensions = array(), array $allowedMimeTypes = array(), MetadataBuilderInterface $metadata = null ) {
        parent::__construct( $name, $filesystem, $cdn, $pathGenerator, $thumbnail );

        $this->allowedExtensions = $allowedExtensions;
        $this->allowedMimeTypes  = $allowedMimeTypes;
        $this->metadata          = $metadata;
    }

    public function buildCreateForm( FormMapper $formMapper ) {
        $formMapper->add( 'binaryContent', 'file', array(
            'label'       => 'Upload SVG file only',
            'constraints' => array(
                new NotBlank(),
                new NotNull(),
            ),
        ) );
    }

    /**
     * {@inheritdoc}
     */
    public function validate( ErrorElement $errorElement, MediaInterface $media ) {

        if ( ! $media->getBinaryContent() instanceof \SplFileInfo ) {
            return;
        }

        if ( $media->getBinaryContent() instanceof UploadedFile ) {
            $fileName = $media->getBinaryContent()->getClientOriginalName();
        } elseif ( $media->getBinaryContent() instanceof File ) {
            $fileName = $media->getBinaryContent()->getFilename();
        } else {
            throw new \RuntimeException( sprintf( 'Invalid binary content type: %s', get_class( $media->getBinaryContent() ) ) );
        }

        if ( ! in_array( strtolower( pathinfo( $fileName, PATHINFO_EXTENSION ) ), $this->allowedExtensions ) ) {
            $errorElement
                ->with( 'binaryContent' )
                ->addViolation( 'Invalid extensions' )
                ->end();
        }

        if ( ! in_array( $media->getBinaryContent()->getMimeType(), $this->allowedMimeTypes ) ) {
            $errorElement
                ->with( 'binaryContent' )
                ->addViolation( 'Invalid mime type : ' . $media->getBinaryContent()->getMimeType() )
                ->end();
        }
    }
}

Here you can override base class functions and define your own functionality as you wish for example you want to add some validations to file input you can customize validate() function to change attributes for file input field you can define it in buildCreateForm() method

Now in your admin if you want to allow only SVG to upload you can define your own provider which allows only SVG files

protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->add(
            'SvgLogo',
            'sonata_type_model_list',
            array('required' => false),
            array(
                'link_parameters' => array('context' => 'svg_file', 'provider' => 'sonata.media.provider.svg'),
            )
        )
}
like image 82
M Khalid Junaid Avatar answered Oct 28 '22 00:10

M Khalid Junaid