I like baseball, I like the Indians. I like embedding content. Why MLB.tv likes to make their stuff not easily embeddable is beyond me. I think [mlbtv id=28142247]
is way easier to deal with if I’m using the visual editor. I grabbed the default sizes from their settings.
<?php // MLB.TV Shortcode - Better code by Konstantin Kovshenin // [mlbtv id="###" width="480" height="270"] function mlbtv_shortcode( $attr, $content = '' ) { $attr = shortcode_atts( array( 'id' => null, 'width' => 400, 'height' => 224, ), $attr ); $attr = array_map( 'absint', $attr ); $url = add_query_arg( array( 'content_id' => $attr['id'], 'width' => $attr['width'], 'height' => $attr['height'], 'property' => 'mlb', ), 'http://wapc.mlb.com/shared/video/embed/embed.html' ); return sprintf( '<iframe src="%s" width="%d" height="%d" frameborder="0">Your browser does not support iframes.</iframe>', esc_url( $url ), $attr['width'], $attr['height'] ); } add_shortcode( 'mlbtv', 'mlbtv_shortcode' );
[mlbtv id=28142247]
Looks just fine.
Comments
21 responses to “Shortcode: MLB.TV”
Don’t forget to escape your attributes!
Elaboration?
I know about http://codex.wordpress.org/Function_Reference/esc_attr but I wasn’t really terribly worried about it since I’m just tossing this up as a thing I needed on short notice. And I know that the ID is always a number string right now, but may become numbers and letters…
You should always be terribly worried about security π Numbers and letters are fine, but consider something like:
[mlbtv id=’28142247″ onmouseover=”alert(document.cookie);”‘]
So users without unfiltered_html caps can suddenly write javascript, that’s not nice π
Which on this site is … me π I don’t hand out admin-keys like Oprah, after all!
But just as a point, you know it’s okay to explain what you mean in code too π I mean, saying ‘Escape your attrributes’ is great advice. A link to how one does that is even better π Extra points for explaining why it’s important and how it works. I’m sure someone read this and went “He said words, but what do they mean?”
For me… I think I know what you’re saying. In theory, all I would need is this for my attributes, right?
$id = esc_attr( $id );
Correct, sorry for not being more helpful the first time!
It wasn’t unhelpful π Now I’m wondering if there’s a more efficient way to loop through the attributes without having to call that for each one…
You can use
array_map( 'esc_attr', $atts );
, however, your attributes are used inside the URL as well, so you might want to sanitize them. Also, I like explicit escaping as late as possible, so I’d normally squeeze in a bunch of calls toesc_attr
right in that return statement, or maybe use printf to tidy it up a little. I also try to never useextract
because it’s very implicit and hard to read. So off the top of my head:$attr = shortcode_atts( ..., $attr );
$attr = array_map( 'absint', $attr );
$url = add_query_arg( array(
'content_id' => $attr['id'],
'width' => $attr['width'],
'height' => $attr['height'],
'property' => 'mlb',
), 'http://wapc.mlb.com/shared/video/embed/embed.html' );
return sprintf( 'Your browser does not support iframes.', esc_url( $url ), $attr['width'], $attr['height'] );
I would also set the default width attribute to the $content_width global. Hope this make a little bit more sense π
Sorry for the code disaster. Here:
https://gist.github.com/kovshenin/5852083
Ahhhh! That is so neat! Now I know more about better shortcodes *runs off to make others better too*
I have a lot to learn about URL parsing in plugins π
Follow up question…
What if the URL looks like this:
http://www.cbs.com/e/'.$id.'/cbs/1/
Can you use the same methodology?
In that case I would use
sprintf
to construct the$url
, similar to how I construct the output.Such abuse of shortcodes. Why not just add a normal embed handler?
Code to do exactly this here:
https://gist.github.com/Otto42/5853020
Advantages:
– It uses the normal embed routines, so it will work with just the URL on a line by itself if you have that option enabled.
– It picks the correct embed width based on your embed width settings, or the content_width of the theme, dynamically adapting to your theme’s space.
– If you want to be specific about width, you can use the embed shortcode, like so:
[embed width=123]http://wapc.mlb.com/play/?content_id=28142247#[/embed]
– No extra weird shortcode madness.
I use shortcodes in part because where I tend to end up with these is not usually a simple embed.
I have other sites where the embed works for most people, but there’s no direct link to ‘click here and go to the video’s page’ (which IMO is idiotic of them, but hey, I ain’t CBS). So I want this:
VIDEO
(Click Here if the video don’t show)
And I don’t know how to do that with a simple oEmbed call.
The embed handler I posted above isn’t actually making an oembed call.
It just returns the same iframe that your own shortcode returns. If you have it return a link, you get a link. And so on. The embed system is a specialized shortcase case, basically.
wp_embed_register_handler basically adds a new regular expression match to the embed handling code. The results of the preg_match get passed to the callback as the first argument. The attributes for the embed get passed as the second argument. The URL being embedded is the third, and any raw attributes from the embed shortcode are the fourth argument. Nothing to do with oembed, wp_embed_register_handler is just a way to extend the built-in embed system and [embed] shortcode with support for additional URL types.
Here, I whipped up an embed handler for shows on cbs.com for you, since you mentioned it above.
https://gist.github.com/Otto42/5854277
I used this URL and the embed code it gives for my example:
http://www.cbs.com/shows/under-the-dome/video/ztl_DOHYKxdlRYuC_XeaJwcUZZtowQu_/under-the-dome-dean-norris-rachelle-lefevre/
Probably will work with any of the shows on their site. Because the URL doesn’t contain enough information to build the embed code, I have it go fetch the page and get the relevant code out of their OpenGraph video metadata. With some minor reworking to fit the parameters, it works perfectly well. The final return code is stored as postmeta using the oembed cache key, so that WordPress itself will handle the cleanup on post-save.
The real issue with CBS is they’re idiots and like to (a) change the embed params without warning and (b) delete their embedded videos. They’re on my shit list and I’m at the point where I just rip their media because I can’t actually trust them anymore. Which totally defeats their purpose.
Hey, CBS: We WANT to legit embed your media. But if you share and then take away, we find workarounds.
Well, removing content is as may be, but regardless, I used the og:video tag for the embed there, so unless they’re screwing themselves over on Facebook as well, it should work fine.
Side-thought. Can I filter embeds? So like even if a video doesn’t show, it would always link back to ‘source’? I think embed_oembed_html would be what I’d want for that….
Err.. that question is worded oddly enough to make me think I need to write a tutorial on this. π
Embeds != oEmbeds. They’re similar, and part of the same thing, but not the same thing.
Embeds = the embed shortcode and the process by which a link on a line by itself can become an embedded “thing”.
oEmbed = a protocol used by *some* of the supported embeds by which WordPress asks the system being embedded for the embed code directly.
So for example, when I post a YouTube link, then the Embed handlers find the link and process it, then call the oEmbed code, which actually talks to YouTube and gets the embed code from them, then returns it to the Embed handler, which returns it back to the post, which then replaces the link with it.
The normal approach is to display the link as-a-link if the oEmbed process fails. It’s possible to use the code in the system to do this for normal Embeds, and I did just that in the cbs.com I wrote and linked to above. See the various calls to $wp_embed->maybe_make_link().
The embed_oembed_html filter won’t suit your purposes, because that filters the return value from an oembed response. Which you’re not actually doing here, because neither cbs.com nor mlb.tv supports oembed.
I think you should write a tutorial! π When was your last one anyway?
I actually asked about the link and embed_oembed_html for a different bit of code. The side I use a lot of video on is still 3.5.2 and I use your HTML5 Video Shortcode to let me put in
[html5video mp4="video.mp4" webm="video.webm"]
and it works great. I also added in a link at the bottom ala ‘Can’t see this?’I know video embeds are coming in 3.6 (heh) and I plan to switch to them with a simple search/replace for html5video/video – cause I’m smart. Or lucky. Whatever. The point is I want to keep my bit at the bottom, so if I can use the embed_oembed_html code for it, I want to since I have some … non-technical people who visit that site, and they often need a direct link for their weefy old browsers. (How weefy? This year was the first time I stopped getting regular hits from Netscape Navigator and WebTV)
So right, and now you hit the actual reason why I made a fancy ass shortcode. And remember, this is because CBS is stupid beyond belief.
https://gist.github.com/Ipstenu/c1754062415c5959d7af
That’s the code I’m using, which allows me to:
1) Create a credit link
2) Have a ‘can’t see this?’ that points to a local video (because of CBS deleting/moving videos – Yes, they change URLs on the fly, I hate it)
3) Cope with the two different types of video they inconsistently push.
They also have two different ‘active’ video sources: cbspressexpress has its own stupid embed.
(We won’t get into how they also delete their youtube video – I don’t think they understand what the Internet is for.)
Oh and I added this to the bottom of your code:
<p>Credit: <a href=".$url." rel="nofollow">CBS Video</a></p>
That’s as much of a direct link as I need for everyone (secret revealed time! CBS videos aren’t viewable if you’re not in the US, but if you go directly to their webpage and use Hola Unblocker you can see their stuff. Do not ask me why that works.