Skip to content
This repository has been archived by the owner on Nov 16, 2021. It is now read-only.

Support image cropping #439

Closed
wants to merge 38 commits into from
Closed

Support image cropping #439

wants to merge 38 commits into from

Conversation

phenaproxima
Copy link
Collaborator

@phenaproxima phenaproxima commented Aug 24, 2017

At long, long last: this addresses https://www.drupal.org/node/2690423.

This adds Crop API and Image Widget Crop to Lightning as an optional quasi-dependency of Lightning Media Image. If Image Widget Crop is installed, four crop types are created: freeform, portrait, landscape, and square (thanks @starshaped for suggesting those). Each crop type, and every crop type created thereafter, also gets an accompanying image style which is used to display that particular crop.

In new installs, or after manual updates in existing installs, the Image media type will by default use the cropping widget in both its normal form and in the media browser (which is also used by the image browser). All available crop types will be allowed, but that can be overridden per form display.

@mirodietiker had suggested using Focal Point as our cropping widget, but I decided to stick with Image Widget Crop because it is a more "traditional" form of cropping than Focal Point is, and I figure Lightning shouldn't venture too far off the reservation in terms of expected out-of-the-box CMS behavior. There is nothing in this PR to prevent people from switching to Focal Point if they want to, though.

@@ -169,7 +173,10 @@
"drupal/simple_oauth": "2.0.0-rc3",
"oomphinc/composer-installers-extender": "^1.1",
"drupal/dropzonejs": "1.0.0-alpha7",
"bower-asset/dropzone": "^5.1"
"bower-asset/dropzone": "^5.1",
"drupal/crop": "1.2.0",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to add Crop API as an explicit dependency here in order to patch it. Once the patch is committed, we can remove this dependency, since Image Widget Crop already depends on Crop API.

projects[workbench_moderation][type] = module
projects[workbench_moderation][patch][] = https://www.drupal.org/files/issues/2668006-2.patch
projects[workbench_moderation][patch][] = https://www.drupal.org/files/issues/2847078-6.patch
projects[workbench_moderation][patch][] = https://www.drupal.org/files/issues/workbench_moderation-quickedit-support-2749503-6.patch
projects[workbench_moderation][version] = 1.2
libraries[cropper][type] = library
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This library is required by Image Widget Crop and it's already on drupal.org's library packaging whitelist.

function lightning_media_field_widget_info_alter(array &$info) {
if (isset($info['entity_browser_entity_reference'])) {
Override::pluginClass($info['entity_browser_entity_reference'], EntityReferenceBrowserWidget::class);
function lightning_media_field_widget_third_party_settings_form(WidgetInterface $widget) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these changes constitute a major refactor of how we were customizing the behavior of image widgets. This is a far more stable way to achieve what we were previously doing with plugin hijacking.

/** @var \Drupal\ckeditor\Ajax\AddStyleSheetCommand $command */
$command = new $command_class($query->get('editor'), $style_sheets);
if ($style_sheets) {
$command = new AddStyleSheetCommand($query->get('editor'), $style_sheets);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is gardening. Lightning Media has a hard dependency on the CKEditor module, so there was no need to gingerly check anything.

if (isset($info['image_widget_crop'])) {
// We cannot import the class with a use statement, because it will blow up
// if Image Widget Crop is not installed.
Override::pluginClass($info['image_widget_crop'], \Drupal\lightning_media_image\Plugin\Field\FieldWidget\ImageCropWidget::class);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get the behavior I wanted, I had no choice but to hijack the cropping widget plugin.

$value = parent::getSetting($key);

// If no crop types are chosen, allow all of them.
if ($key == 'crop_list' && empty($value)) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default behavior of this widget is to only allow crop types which are explicitly enabled for that specific form display. Syncing that with new or deleted crop types would be a complicated pain in the ass from both a DX and UX perspective, so I overrode it. Site builders will still be able to explicitly allow only certain crop types for a particular form display.

/**
* Cosmetic enhancements for the Entity Browser entity reference widget.
*/
class EntityReferenceBrowserWidget extends BaseEntityReferenceBrowserWidget {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been replaced by a hook implementation in lightning_media.module, so that we don't need to bother with plugin hijacking.

use Behat\Mink\Exception\UnsupportedDriverActionException;
use Drupal\DrupalExtension\Context\MinkContext;

trait AwaitTrait {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is gardening of the tests. It's a lot nicer than having to pull in MinkContext and call iWaitForAjaxToFinish().

* @return \Behat\Mink\Element\NodeElement|null
* The details element, or NULL if it was not found.
*/
public function findCollapsible($summary_text) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is replaced by DetailsTrait::assertDetails().

@@ -1,2 +1,3 @@
entity_json: true
bundle_docs: false
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops. We should have had this in a previous PR, but I guess we forgot. No harm done.

plugin_id: entity_operations
moderation_state:
id: moderation_state
click_sort_column: target_id
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the result of a previous PR which moved the operations field. Again, I think we just forgot to merge updated config then. NBD.

@@ -16,7 +16,22 @@ Feature: Image media assets
Then I should be visiting a media entity
And I should see "Foobaz"

@image @javascript @b23435a5
@13eacffd
Scenario: Cropping should be allowed when creating an image
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be really difficult to test the actual cropping, and that's squarely in Image Widget Crop's wheelhouse anyway. I figure it's good enough to ensure that the crop widget is showing up where and when we expect it to.

@balsama
Copy link
Contributor

balsama commented Sep 5, 2017

This is excellent and very thorough. Thank you.

I have some questions strictly related to the UI. Some are almost definitely not related to Lightning's implementation, but we should investigate:

  1. I feel like four options out of the box is a little overwhelming. I think the largest use case is an arbitrary crop. Can we only enable "Freeform" out of the box? We can leave them defined, but I think it would be best to enable one type on the Media Image image field at least.
  2. It's not clear to me what the settings at /admin/config/media/crop-widget do. Are they just defaults for new fields that use crop. I tried to modify the settings there thinking it would edit Media: Image before I realized that those settings are on the field itself. Perhaps we could open an issue for Image Widget Crop to clarify what that form does.
  3. /admin/config/media/crop drop-buttons have a link to manage moderation. Is this the case for all entity lists like this? Can we disable it for non-moderated entity types?
  4. The "This crop affects multiple images" warning message seems to be displayed on every image, regardless of whether it's being used or not.

Again, this is great. Thanks so much for this.

@phenaproxima
Copy link
Collaborator Author

  1. Fixed. The Image media type will use Freeform only, by default.

  2. I took a quick check and TBH it's not clear to me either. I imagine they'd be treated as the default settings for new fields, but the crop widget itself does not appear to pull default settings from configuration or anything. Maybe it's a vestigial part of Image Widget Crop? In any event, it's an issue with Image Widget Crop, not Lightning. So I'm open to creating an issue (or including a patch) to either document or remove those settings.

  3. I suspect this is an oversight in Workbench Moderation itself. Crop types (config entities) are "bundles" of crops (which are content entities), and I think Workbench Moderation is picking up on that pattern and assuming that moderation is a thing that crop types may want. We can suppress that behavior for crop types specifically, but I would rather whitelist than blacklist. I think we could open a follow-up PR to add an administrative UI to Lightning Workflow which will allow you to say which bundle entity types can have moderation applied. That would solve this problem permanently and generically.

  4. I don't really understand that warning, TBH. There is a setting on the field which can disable that warning, though it's not clear in which contexts. I could set that as the default. What do you think?

@balsama
Copy link
Contributor

balsama commented Sep 6, 2017

  1. Cool. Looks like the tests and manual update steps need to be updated (manual update steps documentation and lightning_dev)
  2. Let's open that issue when we get a chance, but not block on it
  3. Let's open that issue against Lighting before merging this
  4. Yes, let's turn off that setting. I'd rather not see that warning at all if possible.

@phenaproxima
Copy link
Collaborator Author

  1. Done.
  2. Okay. That sounds like a plan to me.
  3. Opened #447.
  4. The setting in question now defaults to FALSE.

@balsama
Copy link
Contributor

balsama commented Sep 6, 2017

Awesome. Let's let this build out to cloud one more time for a quick manual test. Will be here when complete: http://lightningnightlyfpce6h2qzh.devcloud.acquia-sites.com/

@balsama
Copy link
Contributor

balsama commented Sep 6, 2017

Shoot. Disabling everything but Freeform causes another UX issue. The others still exist as crop types and each has an associated view mode so the user is still presented with NINE options when embedding. Three of which are identical. (And it's probably not immediately obvious to the user that they could just go enable them on the field)

I like the idea of providing sane defaults, but to keep this as un-intrusive as possible while still providing much needed functionality, let's just ice the config for everything but freeform entirely.

@balsama
Copy link
Contributor

balsama commented Sep 6, 2017

Hm. Still see a "Crop thumbnail" image style that I didn't see before this PR (in addition to the "Cropped: Freeform" style that I expected to be there. Fresh install: http://lightningnightlyfpce6h2qzh.devcloud.acquia-sites.com/admin/config/media/image-styles

@balsama
Copy link
Contributor

balsama commented Sep 7, 2017

Committed in 0665e16 with the following CI tweaks:

  • Bumped Travis CI php version to 7.0.22 because symfony/browser-kit requires >=7.0.8 if using php 7.0
  • Pinned Drupal Console to 1.0.1 because 1.0.2 returns a non-zero exit code for update:execute if there are no pending updates

@balsama balsama closed this Sep 7, 2017
@phenaproxima phenaproxima deleted the image-cropping branch September 7, 2017 17:38
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
2 participants