lch/media-bundle

Symfony LchMediaBundle

1.2.21 2020-01-16 11:01 UTC

README

此包为Symfony 3提供了一种全面且代码密集的方式处理媒体。特性

  • config.yml 中定义 媒体类型
  • 提供 事件 来挂钩所有流程(CRUD)
  • 提供 表单类型 以便在管理界面中轻松交互(选择现有媒体/创建新媒体)
  • 提供Twig扩展以简化在Twig文件中的媒体显示和操作(获取URL、缩略图...)
  • 提供 验证器 以限制媒体范围(大小、分辨率等)

安装和先决条件

Imagick用于生成缩略图和图像大小集。在GUI方面,包使用 Bootstrap 4jQuery。请确保满足这两个依赖项,尤其是在管理屏幕(媒体选择/创建)上

安装时,请使用: composer require lch/media-bundle

配置和使用

  1. 一般说明
  2. 媒体类型声明
  3. Twig扩展和工具
  4. 事件
  5. 表单类型
  6. 验证器
  7. 存储策略
  8. 图像大小
  9. 实际用例
    1. 下载控制

一般说明

默认情况下,MediaBundle定义了2种类型: 图像pdf。您可以使用这些类型作为自定义类型的基类。

以下是显示的类型和可用的字段

Media relations and fields

媒体类型声明

您需要在 config.yml 中定义您的 媒体类型。您可以使用以下语法定义任意数量的类型

    lch_media:
      types:
        image:
          name:             'your_project.image.name' # the translated name for front presentation
          entity:           'YourBundle\Entity\Media\Image' # the entity to be used
          form:             'YourBundle\Form\Media\ImageType' # the form to be used when adding media
          add_view:         'YourBundle/Media/Image/fragments:add.html.twig' # the add form view to be used when adding media
          thumbnail_view:   'YourBundle/Media/Resource/fragments:thumbnail.html.twig' # the view used for displaying thumbnail
          list_item_view:   'YourBundle/Media/Resource/fragments:list.item.html.twig' # the view used for displaying list item in selection lists
          extensions:       ['jpg', 'jpeg', 'png', 'gif'] # allowed extensions
          max_items_per_page: 20 # not required, 20 per default
          thumbnail_sizes:
            news:
              width: 396
              height: 227

让我们逐个复习每个给定键的示例

实体

上述声明图像的最小类可能是

<?php
    namespace YourBundle\Bundle\Entity\Media;

    use Doctrine\ORM\Mapping as ORM;
    use Knp\DoctrineBehaviors\Model\Blameable\Blameable;
    use Knp\DoctrineBehaviors\Model\Timestampable\Timestampable;
    use Lch\MediaBundle\Entity\Image as BaseImage;

    /**
     * Image
     *
     * @ORM\Table(name="image")
     * @ORM\Entity(repositoryClass="YourBundle\Repository\Media\ImageRepository")
     */
    class Image extends BaseImage
    {
        use Blameable,
            Timestampable;
    }

它扩展了 Lch\MediaBundle\Entity\Image。如果您想从头开始,您必须从 Media 扩展并使用 Storable 行为来触发与包中文件存储相关的所有操作。

表单

最小表单类可能是

<?php
    namespace YourBundle\Form\Media;

    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    use Lch\MediaBundle\Form\ImageType as BaseImageType;

    // Extends BaseImageType here for overriding constants
    class ImageType extends BaseImageType
    {
        /**
        * BaseImageType defines a NAME constant for generic image type. You override it here with your type name
        */
        const NAME = 'your_image_type';

        /**
        * Same for root translation path to be used in your particular type case
        */
        const ROOT_TRANSLATION_PATH = 'your.back.media.form.image';

        /**
        * @inheritdoc
        */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            // Explicit parent call is required for constant overriding
            parent::buildForm($builder, $options);
        }

        /**
        * @inheritdoc
        */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'data_class' => 'YourBundle\Entity\Media\Image'
            ]);
        }

        /**
        * @inheritdoc
        */
        public function getParent()
        {
            return BaseImageType::class;
        }
    }

添加视图

以下是为由包定义的通用Image定义的添加视图

    {% form_theme mediaForm 'bootstrap_3_layout.html.twig' %}

    {{ form_errors(mediaForm) }}
    {{ form_start(mediaForm) }}
        {{ form_row(mediaForm.file) }}
        {{ form_row(mediaForm.name) }}
        {{ form_row(mediaForm.alt) }}
        <div class="text-right col-xs-12">
            {{ form_row(mediaForm.submit) }}
        </div>
        {{ form_rest(mediaForm) }}
    {{ form_end(mediaForm) }}

如果您定义自己的,您必须使用 mediaForm 作为表单变量。

缩略图视图

以下是由包定义的通用Image的缩略图视图

<img src="{{ thumbnailEvent.thumbnailPath }}" alt="{{ thumbnailEvent.media.alt }}" />

注意:如 下面 所示,大多数逻辑都与 事件相关。缩略图生成就是这样的事情,因此访问缩略图数据通过事件对象进行

列表项视图

以下是由包定义的通用Image的列表项视图。您将在下面的 twig方法 中找到进一步说明

{% set attrs = "" %}
{% for key, attr in attributes %}
    {% set attrs = attrs ~ " " ~ key ~ '=' ~ attr %}
{% endfor %}
{% set size = listItemEvent.media.file.getSize()/1000 %}

<div {{ attrs }} class="{% if attributes.fullSize is defined and attributes.fullSize == true %}col-xs-12{% else %}col-xs-6 col-sm-4 col-md-3{% endif %} media"
     data-id="{{ listItemEvent.media.id }}"
     data-type="{{ getClass(listItemEvent.media) }}"
     data-url="{{ get_url(listItemEvent.media) }}"
     data-name="{{ listItemEvent.media.name }}"
     data-width="{{ listItemEvent.media.width }}"
     data-height="{{ listItemEvent.media.height }}"
     data-size="{{ size }}"
>
    <div class="col-xs-4">
        {{ get_thumbnail(listItemEvent.media) }}
    </div>
    <div class="col-xs-8">
        <p>{{ listItemEvent.media.name }}</p>
        <p><strong>{{ listItemEvent.media.width }}</strong>px x <strong>{{ listItemEvent.media.height }}</strong>px</p>
        <p><strong>{{ size }} Ko</strong></p>
    </div>
</div>

注意:如 下面 所示,大多数逻辑都与 事件相关。缩略图生成就是这样的事情,因此访问缩略图数据通过事件对象进行

扩展

在这里,您定义允许此媒体类型的扩展,作为一个数组。

缩略图大小

更多信息请参阅 专用部分

Twig扩展 & 工具

  • {{ get_list_item(media, attributes) }}:显示列表项
  • {{ get_thumbnail(media, attributes) }}:显示媒体缩略图(在getListItem中调用)
  • {{ get_thumbnail_url(media, attributes) }} : 仅返回缩略图URL(其中 get_thumbnail 将返回HTML 标签)
  • {{ get_url(media, attributes) }} : 返回指定媒体的URL。默认为直接媒体URL,但您可以轻松地在下载事件上挂载以返回更复杂的内容(例如私人资源的下载器)

以下是对上述方法的图形渲染

Media Twig extension methods

事件

以下是对bundle抛出的完整事件列表(在 Lch\Media\LchMediaEvents 中列出)

  • LchMediaEvents::DOWNLOAD : 在 MediaController 生成响应以发送文件之前触发,但 之后 进行安全检查
  • LchMediaEvents::LIST_ITEM : 当调用Twig方法 {{ getListItem(media, attributes) }} 时,由 MediaManager 触发
  • LchMediaEvents::PRE_DELETE : 在 MediaController 删除媒体之前触发
  • LchMediaEvents::PRE_PERSIST : 在 MediaController 持久化媒体之前触发
  • LchMediaEvents::PRE_SEARCH : 在每次列表调用时由 MediaManager 触发
  • LchMediaEvents::POST_DELETE : 在 MediaController 删除媒体后触发
  • LchMediaEvents::POST_PERSIST : 在 MediaController 持久化媒体后触发
  • LchMediaEvents::POST_SEARCH : 在每次列表调用时由 MediaManager 触发
  • LchMediaEvents::REVERSE_TRANSFORM : 由 AddOrChooseMediaType 表单类型使用
  • LchMediaEvents::SEARCH_FORM : 在列表调用时由 MediaManager 触发,以获取特定输入类型以便将搜索表单上下文化为媒体类型
  • LchMediaEvents::PRE_STORAGE : 在 MediaController 存储媒体文件之前触发
  • LchMediaEvents::POST_STORAGE : 在 MediaController 存储媒体文件之后触发
  • LchMediaEvents::THUMBNAIL : 当调用Twig方法 {{ getThumbnail(media, attributes) }} 时由 MediaManager 触发
  • LchMediaEvents::TRANSFORM : 由 AddOrChooseMediaType 表单类型使用
  • LchMediaEvents::URL : 在调用Twig方法 {{ getUrl(media, attributes) }} 时由 MediaManager 触发

表单类型

该bundle提供2种表单类型,以便简化媒体选择/创建。首先,请确保在您的admin twig文件中添加正确的表单主题文件,即 LchMediaBundle:form:fields.html.twig

AddOrChooseMediaType

以下是一个经典用法

    $builder
        ->add('myImage', AddOrChooseMediaType::class, [
                'entity_reference' => Image::class,
                'label' => static::ROOT_TRANSLATION_PATH . ".my_image.label",
                'modal_title' => static::ROOT_TRANSLATION_PATH . '.my_image.modal.title',
                'image_width' => 1499,
                'image_height' => 415,
                'required' => false,
                'attr'  => [
                    'helper' => static::ROOT_TRANSLATION_PATH . '.my_image.helper'
                ]
            ])
        ;

尽管它非常清楚,请注意 entity_reference 是您想要在这里链接的媒体类。关于验证,您可以传递

  • image_widthimage_height 以获得所需的 精确 图像大小
  • min_image_widthmax_image_widthmin_image_heightmax_image_height 以设置图像大小边界
  • min_media_weightmax_media_weight 以设置媒体大小

查看 验证器部分 以获取更多详细信息。

然后,您必须注册一个Twig命名空间,并将bundle的 field.html.twig 添加为 form_theme

twig:
    #...
    paths:
        #...
        '%kernel.project_dir%/vendor/lch/media-bundle/Resources/views': LchMediaBundle
    form_themes:
        #...
        - 'bootstrap_4_layout.html.twig'
        - '@LchMediaBundle\form\fields.html.twig'

假设您已按上述方式添加了form_theme,则twig父表单类型变为

{% block css %}
    {{ parent() }}
    {# Media #}
    <link rel="stylesheet" href="{{ asset('bundles/lchmedia/css/media.css') }}" type="text/css" />
{% endblock css %}


{% block your_content %}
{ form_start(form) }}
    {{ form_errors(form) }}
    {# ... #}
    {{ form_row(form.myImage) }}
    {# ... #}
{% endblock your_content %}

{% block scripts %}
    {{ parent() }}
        {# Routing : needed for interaction in the media popin #}
        <script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
        <script src="{{ path('fos_js_routing_js', {'callback': 'fos.Router.setData'}) }}"></script>

        {# Medias #}
        <script src="{{ asset('bundles/lchmedia/js/isotope.js') }}"></script>
        <script src="{{ asset('bundles/lchmedia/js/jquery.media.js') }}"></script>
        <script src="{{ asset('bundles/lchmedia/js/media-search.js') }}"></script>
{% endblock scripts %}

您必须添加这些3个javascript文件才能使一切正常工作。

  • 列表使用 isotope 来实现优雅的项目展示
  • 所有逻辑(列表/创建)都通过jQuery插件 jquery.media.js 处理
  • media-search.js 包含围绕搜索的JS逻辑(外部化以用于特定库页面)
结果(自定义样式后)

父表单中的按钮选择器: 媒体按钮

点击按钮后,会弹出包含媒体选择器的媒体弹出窗口,其中选择器限于您提供的(限于entity_reference媒体选择器

您也可以从这里添加媒体(限于您提供的entity_reference,并使用您提供的formadd_viewconfig.yml中为媒体类型设置)媒体添加

注意:如您在LchMediaBundle:form:fields.html.twig中看到的那样,我们给所有相关的HTML输入ID后缀了一个随机唯一数字,因此可以安全地在同一表单中允许使用多个媒体类型.

添加或选择多个媒体类型

此类型用于选择一组媒体。它只使AddOrChooseMediaType可重复

    $builder
        ->add('resources', AddOrChooseMultipleMediasType::class, [
            'label' => static::ROOT_TRANSLATION_PATH . '.public_documents.label',
            'allow_add' => true,
            'allow_delete' => true,
            'prototype' => true,
            'entry_type' => AddOrChooseMediaType::class,
            'entry_options' => [
                'entity_reference' => Resource::class,
                'label' => "your_project.test.label",
                'modal_title' => static::ROOT_TRANSLATION_PATH . '.public_documents.document.modal.title',
                'attr'  => [
                    'helper' => static::ROOT_TRANSLATION_PATH . '.public_documents.document.helper'
                ]
            ],
            'attr' => array(
                'class' => 'public-documents',
                'helper' => static::ROOT_TRANSLATION_PATH . '.public_documents.helper',
            ),
        ])
    ;

我们建议使用出色的Symfony collection插件轻松处理集合。我们还需要详细阐述JS部分,所以现在您必须在动态添加媒体按钮时重复执行随机数字更改

以下示例与上述AddOrChooseMultipleMediasType链接(使用symfony collection)

    $('.public-documents').collection({
            up: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-chevron-up"></i></a>',
            down: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-chevron-down"></i></a>',
            add: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-plus"></i></a>',
            remove: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-minus"></i></a>',
            duplicate: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-duplicate"></i></a>',

            // Change the random number to ensure uniqueness
            after_add: function(collection, element) {
                var $mediaSelector = element.find('.media-selector-container');
                
                // Renew random ID on just added media selector
                $mediaSelector.lchMedia('renewRandomId');

                return true;
            }
        })
    );
结果(自定义样式后)

可重复媒体选择器: 媒体按钮

验证器

您将在Lch\MediaBundle\Validator中找到几个内置验证器

  • HasAllowedFileExtension:基于配置的扩展检查
  • Weight:最小/最大,精确重量
  • 图像
    • ImageSize:用于图像大小检查(宽度,高度,最小宽度,最小高度)

所有验证器都在类和属性级别上工作。因此,您需要一次在媒体类上定义它们

    <?php

    namespace YourBundle\Entity\Media;

    use Doctrine\ORM\Mapping as ORM;
    use Knp\DoctrineBehaviors\Model\Blameable\Blameable;
    use Knp\DoctrineBehaviors\Model\Timestampable\Timestampable;
    use Lch\MediaBundle\Behavior\MediaTaggable;
    use Lch\MediaBundle\Behavior\Storable;
    use Lch\MediaBundle\Entity\Media;
    use Lch\MediaBundle\Validator\Constraints as MediaAsset;

    /**
     * Resource
     *
     * @ORM\Table(name="resource")
     * @ORM\Entity(repositoryClass="YourBundle\Repository\Media\ResourceRepository")
     * @MediaAsset\HasAllowedFileExtension()
     * @MediaAsset\MediaWeight()
     */
    class Resource extends Media
    {
        // Remember to use the Storable to ensure physical file is correctly stored
        use Storable,           
            ;
    }

存储策略

待办事项

图像大小

使用Imagick,该组件执行2件事

  1. 为所有图像生成缩略图
  2. 为PDF文件生成可查看的缩略图(列表项和预览器的缩略图)

使用正确的键(thumbnail_sizes)在config.yml中声明媒体类型,您可以生成所需的任何数量的缩略图。

注意:到目前为止,我们使用图像的更长维度,并将另一个维度调整为保持同质性变换。因此,生成的图像可能不是精确的良好分辨率。待完善...

实际用例

下载控制

  1. 声明媒体(参见以上
  2. 注册监听器/订阅者到LchMediaEvents::STORAGE以更改您的媒体存储(例如:添加一个"/private/"子文件夹)
  3. 添加匹配的路由,强制Symfony处理请求
 ipc_media_download:
     path: /uploads/resources/{id}
     defaults: { _controller: LchMediaBundle:Media:download, class: '%lch_media.types.resource.entity%' }
     methods:  [ GET ]
  1. 添加一个投票者以限制服务
  2. 选项:注册监听器/订阅者到LchMediaEvents::DOWNLOAD以控制要提供的内容(添加水印...)

待办事项:待完善,包括详细的事件使用示例