Problem/Motivation

The oEmbed system requires all non-link resources (i.e., photos, videos, rich text) to have an explicit, non-zero width and a height defined, and throws exceptions (in \Drupal\media\OEmbed\Resource::__construct()) if they don't. This is in keeping with the oEmbed specification. However, some oEmbed providers, like Twitter and Instagram, disobey this rule because the assets they serve contain live text, and may be responsive, so they can't really have a known, predefined height. Therefore, they will be incompatible with our oEmbed implementation.

Proposed resolution

Loosen our adherence to the oEmbed standard in order to support remote assets with dynamic heights.

Remaining tasks

Figure out the best approach, write a patch with tests, and commit it.

User interface changes

None.

API changes

None, really. The oEmbed resource value object will become a slightly more permissive, but I'm not sure this qualifies as an API change.

Data model changes

Likely none.

Issue fork drupal-2966043

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

phenaproxima created an issue. See original summary.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Title: [PP-1] Handle oEmbed resources without an explicit height » Handle oEmbed resources without an explicit height
Status: Postponed » Active

The main issue has landed, so let's look into this.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

chr.fritsch’s picture

Issue tags: +DrupalEurope

To set up a provider like Twitter, follow the "Extending" part of https://www.drupal.org/node/2966029.

marcoscano’s picture

StatusFileSize
new624 bytes

Let's see how many tests this breaks.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

a.dmitriiev’s picture

Maybe it is good idea to allow the modules to alter the resource data. Because anyway the source for Twitter or Instagram should be created manually and core is not providing it, the developer in his/her module can decide what height or width to set to the resource if it is not present.

The patch is attached.

a.dmitriiev’s picture

Status: Active » Needs review
phenaproxima’s picture

Issue tags: +oembed
mglaman’s picture

I don't see how this alter will fix issues for oEmbed support of Twitter statuses, per #3005539: Building rich oembed resource requires width and height. The developer adding the resources shouldn't need to do extra work for the embedding of remote objects, as that's the whole point of oEmbed - it should "just work".

EDIT:

Also, instead of an alter this means we do need a Twitter extends OEmbed plugin. We'll need a series of contrib that add provider-specific workarounds, then.

EDIT 2:

For what it is worth, Twitter embeds work fine if $resource->setDimensions($width, $height); is commented out in theResource::rich factory method. It's not very wide, but it works.

a.dmitriiev’s picture

I think Twitter is anyway not allowed by default in the core, or I am missing something? Remote videos with Youtube and Vimeo are only ones that are allowed, right?

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

anruether’s picture

@a.dmitriiev It is not supported by core, but there is oembed_providers which extends core to use a wide range of oembed providers. See the related issue #3164271: Read height of Facebook/Twitter/Insta posts

phenaproxima’s picture

I asked for a few opinions and hopefully those people will post their thoughts in this issue.

This is a tricky one. IMHO, core is probably being a bit too restrictive when it comes to the height; maybe we should change it so that it only throws an exception if the height is a non-numeric, non-null value. That strikes me as a fairly harmless change, and would make the oEmbed system a little less prickly in real-world scenarios.

Beyond that, we do need some way for developers to specify a height for resources that don't include one, but I'm not sure an alter hook is the appropriate mechanism for that. Something like #3009003: Expose oEmbed resource object to iframe template might be a good way to offer some flexibility to module developers and themers.

So here's a proposed plan of action: in this issue, let's just remove the height restriction and allow it to be either NULL, or a numeric value. (Now that we're using PHP 7.3+ for Drupal 9, we could probably accomplish this merely by applying a ?int type hint). Then, once #3009003: Expose oEmbed resource object to iframe template lands, developers should be able to set the height of the oEmbed iframe as needed when rendering a resource that doesn't provide it.

chr.fritsch’s picture

I agree with @phenaproxima. I think setting the height to NULL by default should make the oEmbed system a bit more friendly.

Nevertheless, displaying an iframe without an explicit height is tricky and will not look nice. So this is only one part of the solution.

phenaproxima’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

OK. I think we have our approach, then! This will need to be implemented and tested.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

owenbush made their first commit to this issue’s fork.

owenbush’s picture

Status: Needs work » Needs review

I have created an MR which marks the height of photos, rich, and video as optional.

From what I can tell Drupal\Tests\media\Unit\ResourceTest::testSetDimensions() already covers the ability to set a rich item with a NULL height.

...
'NULL height' => [
  'rich',
  NULL,
  10,
],
'NULL width and height' => [
  'rich',
  NULL,
  NULL,
],
...

Also, Drupal\media\OEmbed\Resource::setDimensions() seems to already handle the ability to have a NULL height

protected function setDimensions($width, $height) {
    if ((isset($width) && $width <= 0) || (isset($height) && $height <= 0)) {
      throw new \InvalidArgumentException('The dimensions must be NULL or numbers greater than zero.');
    }
    $this->width = isset($width) ? (int) $width : NULL;
    $this->height = isset($height) ? (int) $height : NULL;
}

So are additional tests required in this case?

marcoscano’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs tests

I agree that the int type cast and exception in ::setDimensions() would probably be enough to ensure weight and height are positive integers or NULL. While I agree a ?int typehint could also work here, none of the other parameters currently have it, and I think it would be out of scope to refactor all of them.

I think this is good to go from my perspective.

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

I think this could use a test - we have oembed test fixtures in core already, and could add one without an explicit height and make sure it can be parsed.

phenaproxima’s picture

For added realism, actually -- what if we just modified one of our existing fixtures?

For example, core/modules/media/tests/fixtures/oembed/rich_twitter.json. It has a line that says "height": 360. If you actually fetch a real tweet from Twitter right now (for example, https://publish.twitter.com/oembed?url=https://twitter.com/onnlyfeels/st...), you'll see that it has a "height": null field. So maybe we could just change height to null in our existing Twitter fixture, and that would be enough to prove that this works as intended.

catch’s picture

Modifying the existing twitter fixture sounds like a good plan.

phenaproxima’s picture

Status: Needs work » Needs review

Thanks, @catch! Pushed the change to the merge request. Let's see what happens...

phenaproxima’s picture

Issue summary: View changes
Issue tags: -Needs tests

Also, hiding patches in favor of the merge request. And, we have test coverage as agreed upon with @catch, so removing that tag too.

phenaproxima’s picture

Issue summary: View changes
marcoscano’s picture

Status: Needs review » Reviewed & tested by the community

I am personally OK with the approach and the test changes.

One issue that came up when discussing this in slack, is that by setting a non-null formatter max_height value, we fix the test failure here, but I'm not sure if we wouldn't be hiding the potential scenario where a formatter _hasn't_ been configured (so it would have max_height default to 0), _and_ a provider returns no height. Not sure if this is in scope for this ticket?

Tentatively moving to RTBC since I am personally not really too concerned about this edge-case, but no strong opinions.
(assuming the tests go green).

catch’s picture

It doesn't feel like we need test coverage for this, but what's the consequences on an actual site if something like that happens, do we need a follow-up?

phenaproxima’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs followup

but what's the consequences on an actual site if something like that happens

If that happens, I think the generated iframe (that contains the oEmbed content) will simply not have a height attribute. I'm not sure how that will render; maybe it varies from browser to browser? In my Firefox, using this code pen, it seems to have defaulted to a specific height: https://www.w3schools.com/TAGS/tryit.asp?filename=tryhtml_iframe_height. So, maybe nothing to worry about?

In looking at \Drupal\media\Plugin\Field\FieldFormatter\OEmbedFormatter::viewElements(), it looks like max_height is never really used to constrain the height of a resource, as its name would seem to suggest. It's used more like a default value instead. So I think what we should do is open a follow-up to rename the max_height and max_width settings to default_height and default_width, and use them accordingly.

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs followup
Related issues: +#3223596: Rename oEmbed formatter settings to default_width and default_height
phenaproxima’s picture

Another little point of research: according to MDN, the height attribute of an iframe will default to 150. Don't know if this is consistently implemented across browsers, but it would seem to support the hypothesis that iframes without an explicit height will still have some sort of height, which means that it's not a catastrophe if the formatter doesn't have max_height configured.

larowlan’s picture

I've asked around for folks running twitter oembeds via media module on a production site to manually test this if possible

phenaproxima’s picture

Not a production site, but I tested this locally with three different browsers and they all produced very similar, and promising, results.

What I did:

  1. Checked out the MR branch and installed from the Standard profile, then enabled the Media module.
  2. Hacked the OEmbedDeriver class so that the remote_video media source would allow Twitter as a provider.
  3. Confirmed that the oEmbed formatter for the remote_video media type did not define a height.
  4. Added a remote_video media item that used a tweet URL (https://twitter.com/ericwbailey/status/1418208693330399239) which I knew in advance had a NULL height (the tweet's oEmbed version is at https://publish.twitter.com/oembed?url=https://twitter.com/ericwbailey/s...).
  5. Enabled standalone media URLs in Drupal.
  6. Looked at the tweet media entity in Safari, Firefox (logged in), and Chrome. Screenshots attached.

In each browser, the iframe had a sensible default height. Obviously this isn't a comprehensive test covering all supported browsers, but given these results, I figure we maybe shouldn't block this too long on manual tests from production sites, if nobody steps up to the plate. :)

tapscolam’s picture

StatusFileSize
new984.81 KB

Tested this on chrome, safari and firefox and followed the following test steps:

  • Took screenshots before applying the patch
  • Applied this patch via composer.json
  • Cleared caches

Please grant credit to ramya.shankaralingam and xtineroque who helped with the testing.

larowlan’s picture

Crediting @tapscolaM, @ramya.shankaralingam and @xtineroque who helped with manual testing

  • larowlan committed f87d33a on 9.3.x
    Issue #2966043 by phenaproxima, owenbush, a.dmitriiev, marcoscano,...
larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed f87d33a and pushed to 9.3.x. Thanks!

Added and published a change record too. Please amend if I've missed anything https://www.drupal.org/node/3225613

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.