Updated: Comment #34
This issue will not provide a patch. It's only an architectural meta issue.
Terms/definitions
- effect: An
ImageEffect
plugin belonging to anImageStyle
. - operation: An
ImageToolkitOperation
plugin belonging to anImageToolkit
(WIP, see #2073759: Convert toolkit operations to plugins ).
Problem/Motivation
Moving the image system to Drupal 8 was a huge undertaking. Most of image components were converted to classes and plugins. Now the whole system is more flexible, extensible and modern. However, while this part of core is starting to be "in shape" and contributors are trying to port their image modules (most of them modules that are providing new effects) to D8, we've found that some parts of the image system still lacks in terms of API consistency, extensibility, flexibility and DX.
Problems:
- Developers are not able to add custom operations to an image toolkit. Based on the current design they can only extend a toolkit and implement new operations. For example if they want to add new operations to GD toolkit, they need to extend GD toolkit. Other modules may want to add other operations to the same GD toolkit and they need to extend too GD (but which one?). In Drupal 7 this was achieved also in a non-canonical way: contrib modules were declaring functions like
image_{toolkit}_{effect}()
but code was able to callimage_toolkit_invoke()
and get rid of what toolkit was active. - In the current design,
\Drupal\Core\Image\ImageInterface
defines some basic image manipulation methods (resize, scale, crop, scaleAndCrop, desaturate), that hand over the processing to the underlying image toolkit. This makes possible to process effects directly from the image object:$image->scale(100, 200);
. However, contrib cannot use the same logic without extending a new class from\Drupal\Core\Image\Image
and adding a new e.g.::blur()
method. Also, the image toolkit associated to the Image object is not accessible from contrib effects, making it even more complex to access image manipulation functions. Developers need a way to hook into image system rather than extend it for any new effect/operation. - Right now most of the
\Drupal\Core\Image\ImageInterface
effects have a corresponding operation in toolkit, making difficult for developers to understand what belongs to\Drupal\Core\Image\Image
abstract layer and what to the toolkit layer. - There are parts of
\Drupal\Core\Image\ImageInterface
that have GD toolkit logic likeImageInterface::setResource()
. The image resource is something defined and handled by PHP GD extension and should not defined in the image model. ImageMagick, for example, has no resource. We need to cleanup the API and let each toolkit define its tools in the right place. - What about effect collision? How we'll handle the case when a contrib wants to add his own version of GD crop? I know, I know, it's developer responsibility but anyway we need to provide a rule for plugin selection.
\Drupal\Core\Image\Image
layer effects still contain some logic that is toolkit-agnostic. This refers mainly to normalizing dimensions, coordinates, etc. Example:\Drupal\Core\Image\Image::scale()
effect is computing the height when only width is provided. Partially those tasks are deferred to an utility component:\Drupal\Component\Utility\Image
but most of this algebra is still performed in the image layer.- Image requirements (
image_requirements()
) are GD specific and hardcoded inimage.install
. A Drupal installation that uses ImageMagick as default toolkit will still get requirements for GD.
Proposed resolution
- [fixed] Contrib modules will be able to implement new toolkits as plugins.
- Contrib modules will be able to add new operations to toolkits. Collisions will be solved in UI but set also by code.
- Core and contributed operations will be accessible from image object with a unified interface:
$image->apply('scale', array('width' => 100, 'height'=> '200'));
. - Move dimension and coordinates computing into utility component
\Drupal\Component\Utility\Image
and free toolkits from performing such tasks. - [fixed] Toolkit plugins will provide system requirements to be passed to image system.
- Image toolkit operations may provide requirements too.
Remaining tasks
- Agree on this architecture switch.
- Fix child issues.
User interface changes
Will be defined by each child issue.
API changes
Will be defined by each child issue.
Related Issues
- #2073759: Convert toolkit operations to plugins
- #2103635: Remove effects from ImageInterface
- #2103621: Move GD logic from ImageInterface to toolkit
- #2105621: Inject config factory service into image toolkit manager
- #2048827: Move Image toolkit API from system.module to Drupal\Core
- #1069140: Requirements should be provided by image toolkit
- #2106903: Image toolkit operations may provide requirements
- #2084985: Modules cannot add data to ConfigEntity exports without swapping out the entity class
- #2098247: Provide a hook for ImageStyle::createDerivative
- #1826362: Add style to be applied as an argument for effect callbacks
- #2108307: Provide an abstract layer for image operations geometry
- #2108077: ImageToolkit annotation object left under system module
- #2108339: Image toolkit getter
- #2109343: Unify effect/operation verb naming in image style, image, toolkit, toolkit operation
- #2109375: Provide sane defaults for toolkit operation arguments
- #2109459: Review image test suite
- #2109465: Review docs in image system & image module code
- #2110409: GDToolkit & friends are not conforming naming conventions standard
- #2110499: Unify the call and interfaces of image toolkit operations
- #2111263: Toolkit setup form displays settings for multiple toolkits
- #2122605: Remove isAvailable() from ImageToolkitInterface