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.
| Comment | File | Size | Author |
|---|---|---|---|
| #38 | 2966043-test-chrome-firefox-safari.png | 984.81 KB | tapscolam |
| #37 | 2966043-manual-test-safari.png | 91.97 KB | phenaproxima |
| #37 | 2966043-manual-test-firefox.png | 106.65 KB | phenaproxima |
| #37 | 2966043-manual-test-chrome.png | 74.89 KB | phenaproxima |
Issue fork drupal-2966043
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
Comment #2
phenaproximaComment #3
phenaproximaThe main issue has landed, so let's look into this.
Comment #5
chr.fritschTo set up a provider like Twitter, follow the "Extending" part of https://www.drupal.org/node/2966029.
Comment #6
marcoscanoLet's see how many tests this breaks.
Comment #8
a.dmitriiev commentedMaybe 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.
Comment #9
a.dmitriiev commentedComment #10
phenaproximaComment #11
mglamanI 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 OEmbedplugin. 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::richfactory method. It's not very wide, but it works.Comment #12
a.dmitriiev commentedI 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?
Comment #15
anruether@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
Comment #16
phenaproximaI 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
?inttype 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.Comment #17
chr.fritschI 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.
Comment #18
phenaproximaOK. I think we have our approach, then! This will need to be implemented and tested.
Comment #23
owenbush commentedI 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.
Also, Drupal\media\OEmbed\Resource::setDimensions() seems to already handle the ability to have a NULL height
So are additional tests required in this case?
Comment #24
marcoscanoI agree that the
inttype cast and exception in::setDimensions()would probably be enough to ensure weight and height are positive integers or NULL. While I agree a?inttypehint 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.
Comment #25
catchI 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.
Comment #26
phenaproximaFor 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": nullfield. So maybe we could just changeheighttonullin our existing Twitter fixture, and that would be enough to prove that this works as intended.Comment #27
catchModifying the existing twitter fixture sounds like a good plan.
Comment #28
phenaproximaThanks, @catch! Pushed the change to the merge request. Let's see what happens...
Comment #29
phenaproximaAlso, hiding patches in favor of the merge request. And, we have test coverage as agreed upon with @catch, so removing that tag too.
Comment #30
phenaproximaComment #31
marcoscanoI 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_heightvalue, 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 havemax_heightdefault 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).
Comment #32
catchIt 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?
Comment #33
phenaproximaIf 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_heightis 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 themax_heightandmax_widthsettings todefault_heightanddefault_width, and use them accordingly.Comment #34
phenaproximaFollow-up opened: #3223596: Rename oEmbed formatter settings to default_width and default_height. Therefore, restoring RTBC.
Comment #35
phenaproximaAnother little point of research: according to MDN, the
heightattribute 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 havemax_heightconfigured.Comment #36
larowlanI've asked around for folks running twitter oembeds via media module on a production site to manually test this if possible
Comment #37
phenaproximaNot a production site, but I tested this locally with three different browsers and they all produced very similar, and promising, results.
What I did:
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. :)
Comment #38
tapscolam commentedTested this on chrome, safari and firefox and followed the following test steps:
Please grant credit to ramya.shankaralingam and xtineroque who helped with the testing.
Comment #41
larowlanCrediting @tapscolaM, @ramya.shankaralingam and @xtineroque who helped with manual testing
Comment #43
larowlanCommitted 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