 Thank you for having me. This has been pretty incredible to see such a large word camp here in Philly, first ever word camp US. This is pretty amazing. So those of you who don't know me, my name is Andy Nason. I am one of the lead developers of WordPress, doing that for about five or six years now. I also separately currently as my full-time job work for a group called the US Digital Service. This is a talk only in my personal capacity. I am not a covert internet assassin. Thank you, Michael. And I'll be talking about purely WordPress stuff. If you want to talk about government stuff, by all means, you can find me later. So today, I'm going to be talking about advanced topics in WordPress development. For those of you who have seen me talk before, you might have recognized this title. This is my version of the TBA. In this particular case, one of the reasons why is because I'm able to kind of get an idea for what is happening in the community at a particular point and potentially bring it together for something that is particularly pertinent for that time. So there are a number of things happening recently. And also earlier this week, some of the core committers got together in New York and talked about vision and project philosophies. So today, I would like to talk a little bit about how users must be able to trust the software that they use. We have all always had a situation, I'm sure, where you've tried out a new editor or a new tool. And at some point, you stop using that tool. And a lot of times when you stop using that tool, it's because something happened that you didn't expect. Usually, you lost your data. I don't know how many times that I have used an editor, lost my data, and nope, not using that anymore. You don't exactly want to keep using it at that point. This is a fairly important piece. Your content is supposed to be sacred. And if the tools that you're using just don't care about that, well, that doesn't really make it a very good editor. That's kind of the very first thing. Also, with WordPress, if WordPress breaks, you are probably all still here. But the vast majority of users, they're gone. They're completely gone. They don't care how it broke. They don't care why it broke. They might not know that they're using WordPress. They certainly don't know about PHP. They're just gone. We've lost them. So that user trust is really, really important to establish and to hold. So WordPress has done a lot of really interesting things over the last few years. So for example, with automatic updates. We're at this point, and I love being able to continue to update this number, we owe it to 25% of the internet to keep WordPress sites secure, as many of them as possible. So with automatic updates, we have to make sure that they work. We have to make sure that they're consistent. We have to make sure that they don't break the person's site and they're only doing good as much as possible. This actually isn't true. It's actually 100%. Because at that scale, you're pretty much always hitting a WordPress site on your day to day. This is just the way it works. I think it's one out of every six people on the planet use Google every day. It's got to be pretty close to that for stumbling across a WordPress site as well. In practice, for automatic updates, the real world chance of failure is about 99 out of a couple of million. That is a 99.996% success rate. Pretty good. I think that the WordPress team would love to get it to perfect 100. But this is really important. We actually delayed shipping WordPress 2.7 by about a week, because we're only at about 91 or so. And we ended up going from about 91.19 to 3.9s plus in a matter of a week with just some simple improvements because we realized how important it was that if we were gonna launch a major feature like this and basically, in many ways, it was telling the community, don't worry, trust us. We got this. We're not gonna break any sites. And I don't know if you've read any comment, threads, and WP Tavern, but there were some concerns. This was a pretty important thing that we had to think about. Another situation where this has happened is with autosaves. So autosaves have been in WordPress for quite some time. But in WordPress 3.6, we focused a lot of our time on trying to make autosaves even better, making it so your content really cannot be lost. It's going to be somewhere. If your computer suddenly just boom shuts down, it's still somewhere, potentially. So essentially, we're trying to make sure that WordPress is trying to protect your content from cats on a keyboard or east quarter joke, anyone, no, maybe, and track Wi-Fi. Have you ever noticed, by the way, that it's written in PHP? Have you ever noticed that? Anyway, okay, it is, in fact. And then it comes to another piece, which is background compatibility. And this has come up a lot lately, and especially one of the interesting things where I find this come up is some recent conversations around Clipso, which is the new pretty amazing dashboard from WordPress.com, and how, by rewriting pretty much from scratch, they're able to focus on a lot of really interesting, really, really awesome improvements because they weren't hindered. And I think this is interesting because it opens up a good question as to why is WordPress backwards compatible? There are a number of reasons for this. One is we don't want to be burdened in users. We don't want users to ever experience pain when they don't necessarily need to. Because, quite frankly, it's probably gonna be less painful if we handle this edge case than if we pass that off to potentially millions of people or tens of thousands of developers or whatever it may be. Ultimately, I hope that we're a little better at debugging our own tools. And this is one of these problems over and over again where you end up having, in many cases, you have libraries that will break something and they'll say, but it's easier for us to maintain. I'm like, okay, how hard was it to maintain? Because now you have just caused X number of people to upgrade all your stuff. Not saying that everything in the world should be perfectly backwards compatible is not what I'm saying at all. But I am saying that backwards compatibility is one of the most important drivers of WordPress growth. It works everywhere, pretty much everywhere. So for example, PHP 7 just released yesterday. Many extensions are not yet updated, but the extensions that WordPress needs, which is one, works. So WordPress can already or tomorrow work on PHP 7, just as an example, or yesterday, I guess. But this kind of back to compatibility is actually a huge driver of growth. Why? Because it doesn't prevent people from upgrading. Many users, they have no idea what all of these things mean. They don't know what MySQL is. They don't know what PHP is. They find a plug-in that answers their call, and if it works, great, if it doesn't, oops, and that's about as far as they will get. All they really want to really focus on doing is they want to be able to publish on the internet. WordPress lets them do that. If WordPress at any point becomes too complex for a user to publish on the internet, they're probably going to stop using WordPress. So in the case of backwards compatibility, we have to be really careful because we want to really try and build smarter. So for example, backwards compatibility, it's kind of interesting, Helen mentioned this earlier, where it's kind of the two-way street. It's not just making it so previous stuff breaks, but also there's the forwards aspect, the forwards-looking aspect of. You want to make sure that you're not kind of like putting your feet in cement later on. So maybe we might not make another change for two more years, but we want to make sure we're at least going in the right general direction to avoid that. Of course, in WordPress, there are a lot of case studies for this, and I had quite a bit of fun researching them for the last few weeks. They're this comment. If you know WordPress well, you will know that this is probably a bit of a lie. This comment in the exact form appears in the code base like five times. Some of them date back to like very early days of WordPress, but at the same time, well it hasn't been removed yet in many cases because it hasn't been a burden. Because if it is a burden for future development, it probably would get stricken, but there's no real reason. It's sitting there, it's harmless, it's not causing any of the bugs, it has no other side effects. Maybe it could just stay there. Maybe it's a little bit of extra technical debt that we're taking on, for sure. WordPress is not short of that, but that's not necessarily a bad thing. And also we try and be pragmatic, and we have said before that WordPress never breaks any changes, that's a lie. Totally break things all of the time. The difference is that we're very careful about it. And usually it happens after a bit of a delay. Good example of this is that I'm gonna talk about media in a little bit, and the current media library, pretty great, old media library, still kind of around. Doesn't have all of that new functionality still. We're not deliberately bringing back stuff into that old interface. And so what we're trying to do is we're just trying to be as much as possible just careful and say, if we're going to break this thing, let's at least not have it fatal error and perhaps trying to figure out what is the most graceful way for this to fall back. This is a help screen, which is not all that useful as a help screen. Going back to WordPress 3.2 or so. And what we ended up doing is we changed it. Now this was just like one giant thing of text that was filterable in the admin. Not very effective to work with. We changed it to this other thing. It had a sidebar and a footer and a bunch of different tabs. And what we ended up doing is we were able to still handle this in a nice, easy, backwards compatible way. We still ran the old filter. If anyone and added any more help to it, we just appended it to the bottom in a new tab. Additional information. That way, anything that a plugin was still doing was not being lost into the ether. It was still there in some way. Was it perfect? No, if we wanted to handle this in a backwards compatible way, we wouldn't have launched it. We would have left it as is. It's not always what it means. We have other random things in core, like setting superglobals, which is not really something you should do, but some plugin was looking for this value and activating a plugin. So this is a thing that's been existing in WordPress core for like five years. It's pretty harmless because, well, it's there. It does this thing, but it otherwise doesn't really cause any side effects or any other problems. Few releases ago, press this was written. Really, really fantastic effort to improve the book Mark Lit. And from scratch, completely from scratch. And this happens sometimes at WordPress. For the most part, a lot of features are not rewritten from scratch. And yet, it all still worked with all the other things it integrated with. It had a number of URL arguments that could be passed in. It had all the old book Mark Lits and the new book Mark Lits, and it just worked. And that's kind of a nice graceful way to handle this. You can go back even further than that to WordPress 3.0, which merged in Multisite, which was originally WordPress Mew. If you've been around since 2009, 2010. Actually, this is funny. Matt Mullenweg announced that WordPress Mew was being merged in to WordPress 3.0 on stage at WordCamp San Francisco 2009. I was not yet involved in the WordPress community, but all of the other lead developers were, and they didn't hear about it either. And so this is one of these things where it's like we have this thing that we want to do, now we have to go about doing it. That's also not a bad way to think about software in many cases. The programming is kind of like a, it's the means to the end. The goal was stop maintaining this separate fork that was 99% duplicative and 1% could be better. And instead, try and make it so we could perhaps improve the whole ecosystem and bring this functionality to WordPress. So I was involved for this cycle and we spent months trying to figure out all the different things that we had to merge and bring in together. And in this particular case, we ended up turning off a lot of stuff. This is like random things like global terms and, oh God, global categories, which is not global terms, even though it sounds like it's the same thing and there's like a bunch of really random stuff that we just like slowly shut off. And by the time you got up there, they were gone. So it was a bit of an upgrade path, for the most part, didn't affect a lot of people. And even the ones that it did, it failed fairly gracefully. All new installs didn't have all this extra cough, all the old installs still did. So a lot of times we're making these case-by-case decisions. Sometimes it's a little harder to handle. Sometimes we have little comments like this. This is actually in WordPress right now. We're like, this is random thing that we needed to handle, probably going back like to 2005, 2006, but it's easier to handle it than to just break the site entirely. This ends up happening a few times. This is also probably my favorite comment in WordPress. And then what follows is a thing that is not really decipherable. So maybe not the best example. In some other cases where this compatibility is a thing is that when WordPress 3.2 came out and the PHP minimum requirement bumped to 5.2, we realized great, we can use JSON now. Problem is a very, very, very small percentage of sites did not have JSON enabled. I'm not entirely sure how these servers functioned, but they did. The problem is that 0.012% of sites is still in the tens of thousands of sites. They didn't do anything wrong, so there's now a library in core, you can find it if you try, that parses JSON in PHP for these sites. Never gets loaded otherwise, it just sits there. But it took us a day to find the library, test it out, write the little compact code, put a shim in, it's done. And that was not a lot of time, and it was totally worth it because then we never need to worry about this problem again. Suddenly, we are portable with even more servers, we don't need to worry about this, there's gonna be no more support, we've cut down the amount of support that we have to deal with. And plugins, of course, can go ahead and use JSON without really being worried about like, do we need to fall back for this? Cause that would be kind of, that would be kind of lame. Who's been around in WordPress since plugins didn't exist? Number of hands. So this is really great file called myhacks.php. It used to sit in the root. And what would happen is, it would just be included if it existed. And then eventually it ended up getting shut off. There was the option, there was a check box in the UI until like five years ago to turn on legacy myhacks.php support, which no idea what that means. So that's gone. But yet if the option is still set and the file is still there, it still pulls it in. This actually code right now WordPress that will pull this file in. You're like, well, that's kind of a waste. Okay, well, right now it's one line of code and basically one CPU cycle cause it's looking up a value in cache before continuing. So it's not really causing a whole lot of problems here. And if you look at the startup for WordPress, there are probably a lot of other larger things that you could target to make it faster. This is probably not it. But someone from automatic said, you know what, I wanna clean this up, I wanna remove this. I said, okay, great. Question, how much do you think it's used? I was like, I have no idea. So he ended up looking to see how many WordPress sites this is a few years ago had it installed. And he only found it on six of them, but that's still six. But my favorite thing about this is that it included both co-founders of WordPress, which in fairness, they haven't even been using WordPress for quite a while. So it's potentially understandable. So rather than breaking it, it's just still there. I don't know what's in these files, but it's still there. It doesn't really cause any harm. It still sits in core. Another thing that I worked on in particular was a WP theme. This was in WordPress 3.4. It was a complete replacement of this gigantic, ridiculous, multi-dimensional associative array of theme data, which it usually needed on average, like half a percent of the data on any page load. So obviously, of course, we calculated and loaded the whole thing. It was so big that on WordPress.com it couldn't fit into a cache bucket. So they had to chunk it up. Wouldn't fit in a memcached. And so we ended up doing a complete replacement of this. And it was way more performant. It was orders of magnitude faster. It added support for a dozen new features, including things like internationalized theme headers. The customizer came in this release. Custom headers and backgrounds all happened in this case. And there were no reports of breakage, which is funny because we were passing around the filters and the functions and everything else. This theme object, which was array, and then suddenly it was an object and nothing broke. The reason why nothing broke is because everything became a magical PHP object, which is not to be confused with the rest of all the objects in PHP. So this is thing called array object. If you haven't heard of it before, it's pretty cool. This is just an example of one of the interfaces it implements. We could do something like this, where that's actually supposed to be offset get. Type O in my slide, first problem. And you can go ahead and actually, this is an array, right? Like we're calling it as if it's an array, but it's not. And it spits out hello world. This is just something that PHP could automatically do. So now suddenly, we can take the return value of when the theme was an array and then when the theme is an object with decorated methods. And then also when the object gets cast to an array because some of their array of WordPress is doing this. And we're able to kind of like standardize all of this in one go pretty easily. There's also this thing called magic methods in PHP. So you might have seen a magic getter before, where this is for properties in this case. So world as a property doesn't exist yet. We can go ahead and call this. So this took this entire effort. It was one person six days, about 12,000 lines of WordPress where we ran. And nothing broke in the end. This whole API, which it was not an API to begin with, let's face it, was upgraded into a real one. Nothing broke. The whole thing made it a lot easier for things like the customizer and media and a lot of things to be written in the ensuing years. And it was just a really nice way to be able to ship a new thing into WordPress. So in this case, we're able to upgrade an entire API in place. We're able to enable the user facing features. We made sites faster. And these are a bit in order of what preference is, right? We were also able to empower developers to build new things, standardized all the craziness under the hood, and didn't break anything. Not bad for six days of work. In WordPress 3.5, there was media. Now, media, you've heard this a few times this weekend, taking a PHP interface and completely replacing it with a JavaScript interface. There have been a few talks about this. REST API, Calypso, a lot of things here. Now, when we tackled this, we didn't really set out to break plugins, obviously. That is actually never our intention, at least not on purpose. But so what we ended up doing is that we realized that because of the ecosystem, because of a desire to kind of handle this gracefully, a lot of things still went back through PHP, because in many cases, it had to, for example, go into the database, whatever it might be. So when you send a link to the editor or you upload a post, of course, it gets processed by PHP before it gets sent there, and we're able to still do things like fire filters off when we needed to. And so any plugin that was doing anything crazy on these random send editor, media, whatever hooks, that there were a lot of plugins in the library doing a lot of these things, we were able to handle this completely transparently without any problems, even though we were completely gutting the interface, left it for dead and build a new one in Backbone. There were some things like attachment fields to edit and attachment fields to save that ended up creating these giant arrays of HTML that would print out your fields. So the new library automatically handled this by default. It was like, oh, you registered some fields previously. Well, I guess I need to render these in JavaScript instead and then save them with an AJAX call. Simple, effective, took a little bit of time on our end and took absolutely no time on a plugin author's end. And they were able to then suddenly use the new functionality of media without any problem. So this kind of like fully transparent to the user and to the developer is really important. Another example is, you guys remember this? Good old days. This is the old media library from, this is 2.5 to 3.4, give or take. And you can see the tabs at the top, from computer, from URL, media library, and these were set in PHP. There's a filter called media upload tab, still exists today, can still use it if you wanted to, but we still kept it in WordPress. We got rid of the labels but they weren't useful. And we got rid of everything when we were done. So we ended up with an empty array. Unless a plugin added something. So if a plugin wanted to, a plugin can today, not saying I recommend this, but a plugin can right now add a bunch of tabs. And then suddenly this is the new media library and they'll show up. That's it. And then the best thing is that they will actually, if you go to one of those tabs, it will render the original tab in an iframe firing the old PHP hooks and give you back your old media UI. Completely seamless, fully integrated, new interface, new technology stack, JavaScript, not PHP, didn't affect the user at all, didn't break the plugins at all and from start to finish we were done in two days to that entire piece. So this of course made it so when you upgraded to 3.5, you didn't need to really worry about all this stuff. It was pretty great. A number of smaller edge cases, things we didn't try to, that we didn't realize we were breaking of course. There were a lot of situations that we were considering, how can we meet all these requirements in a sane way, in a pragmatic way and when we can't, when can we just kind of like shove it off to the side and don't worry about it anymore but make sure that the site doesn't break in the process. Vastly improved user experience. Placed the whole PHP driven thing with the JavaScript thing. The media handling was way better. Developers had more tools to do things and we didn't need to break anything. So hypothetically, conceivably, we could migrate the WordPress dashboard to JavaScript and still actually keep a lot of things compatible. Hypothetically, maybe. And then I'll close with talking about how a lot of the times, especially when dealing with these kinds of things, documenting the decision is of course really important. So there's a lot of places in this case in WordPress where we documented on the handbook or what was the codex in the code of course, sometimes in a commit message but not everything really belongs just purely in documentation because in a project that is as large as WordPress, you're gonna have situations where three or four years later, you, and I don't mean someone else, I mean you will come by and have a completely different answer to the same question and you will be wrong because you three or four years ago was smarter. This happens to me a lot. Like wow, that's a really smart comment, you scroll up. Oh, I wrote it, yes. Right? And so that can be interesting. How do you actually document these things? WordPress in many cases tries as much as possible to codify these design decisions in its testing framework. So for example, four or five years from now, someone decides I'm going to go ahead and change this thing and it was written in this way eight, nine years ago and it was someone proposed like can we change it? And the answer was like no and here's why and I did a lot of research. In a lot of cases, the ticket will just then be closed. This happens in all software. They're like nope, not a good idea, the ticket will be closed. What if we enforced that as part of our unit test? A failing unit test could just trigger an immediate review. It can say like, well there, take it over here, you're about to break it. Actually you just did, right? There are different ways to approach this. So one of my favorite ones is that I don't know if you ever noticed this but if you're looking at a post object or a common object these are strings, not integers. And if for some reason we change these to integers which we've tried to do at least twice and every single time we'd get a ton of bug reports saying like, hey by the way you broke this thing because I was doing a strict comparison here and here and whatever and then by the way WordPress broke over here and Drupal broke over here and a lot of things went wrong, right? So we have a unit test that just enforces that. It's simple, this is not hard but it's a thing that we need to consider. If you saw Gary Pendergas talk this morning about what would usually called Trojan Emoji now, thank you Brian Krogegaard for coining that one. Where we have a situation where there's actually a type of serialized class that cannot be serialized in WordPress, like it will break. If this ever got added into core, like this special kind of serialized class got added to support foreign core, we would be immediately committing to WordPress core a remote code execution vulnerability. That's not good, so there's a unit test for that. There's also little comments like this, like double serialization is required for backup probability, which is true. Also the world will end, see the security release. This is sitting in WordPress right now. And then finally, more recently, there was this HTML embed, WordPress O embed, this is a new feature in WordPress 4.4, I'm sure you'll hear about it tomorrow. And there's this giant, I'll see this, you go to YouTube, like copy and paste the embed code, paste it in, things like that. Well, there was this like problem where we have this code in this JavaScript file that then got inlined and WordPress in its infinite wisdom on older sites would change it. So you're gonna see the change there, the ampersands change to hex. So that's not good. So now we have nested if statements instead. We removed all of the ampersands out of this file, which is not exactly the most effective way to write JavaScript. So how do you enforce such a decision like this? How do you prevent someone else or yourself, a few years later being like, wow, we should probably remove all these nested ifs. Someone forgot that there was a thing called and. So there's this comment at the top of the file as of yesterday, this file cannot have ampersands in it. This is to ensure it can be embedded in older versions of WordPress, see this commit. Well, that's good, but this is a pretty bad thing. And I don't usually read the comments at the top of the file. And I'm not gonna comment every single situation where there could be an if statement that could be optimized. So we wrote a unit test, pretty simple. It checks to make sure there's no ampersands in the file. Simple, easy, codified, cannot break this. Except for the fact that this file is also uglified. Uglified.js, it runs all sorts of compression and optimization algorithms. So you can turn off optimization of conditionals. The problem, of course, is that there is no setting in uglify, I'm really glad for this, that says do not use ampersands, because that would be kind of weird. But we cannot use ampersands. So we now need to test the compressed JavaScript, and I'm just gonna show you this briefly. I don't think you'll be able to see it too well. Yeah, that's a nasty regex right there. This is now in our unit tests. It's not in WordPress, it's okay. And in this case, what it's doing is it's actually very much carefully checking to make sure that this minified file does not have an ampersand in it, no matter what. So TravisCI will pick this up and it'll flag it and it'll say like whoa, pause, you just broke everything. And by everything I made a very random HTML embed feature that not a whole lot of people use because it's only on older versions of WordPress, blah, blah, blah. But that's not all. In addition to the unit test, we wrote four paragraphs explaining exactly what's going on. And if you wanna take a look, it's 35762, that was the chain set that added all this code. I'm not gonna leave this up for you to read it. So that is codifying your decision, putting it directly into there. So going back to philosophies, which I mentioned earlier, we have a number of these core development philosophies available on WordPress.org. They were written many years ago before I got involved in the project. They're really great. I think that they personally have affected me a lot in how I think that products should be designed. There's a lot of these. You've heard of a lot of these decisions on options and working well out of the box and things of that nature. But backwards compatibility is actually missing out of this. It's not there. And the reason why I think it's not there personally is because I think that it's only the means to an end. I think that the end goal is that we should make it so your users can actually trust your software. So if we want to break things, that's okay. The philosophy is not never break something. The philosophy is make sure your users can trust your software. In reality, the ability to establish and then maintain that trust, it's essentially a contractual relationship with users and developers. We don't get a whole lot out of it if we do it well. But if we don't do it well, we're not really gonna have that user or developer for that much longer. So I think in this case, it's really just very critical as much as possible to respect the trust that user places with your software and to really consider all the different things that you can possibly do to make it. So that is okay. Thank you very much. I have, I think, about six or seven minutes for questions if you wanna come up to the mic up in the aisle. All right, Sealer. Not really, anything? Wow. It's my 47th WordCamp. I've never had no questions. When it comes to PHP versions, I think you're totally right in the decision with 5.2. But obviously at some point, we have to make that decision. So I'm wondering if you have an idea in your mind and more specifically, like you're interested in coming up with a pattern, like a rolling pattern after X number of years, we deprecate support for this version. So the problem with that, with the idea of a rolling pattern is that PHP just recently changed its own supported versions. So particularly with seven and with each of the major versions there's a lot of flux there. We're now five, four is now end of life and then a year each, everything will start going away. I think PHP five points or PHP seven is end of life in like 2018, I get that right. I don't think that our minimum requirement will be seven by 2018, just throwing that out there. So I think a lot of this is maybe wait and see to see how the whole ecosystem reacts. But I'm sure that Matt will talk about this tomorrow, I'm not saying ask him about it, but I know they'll probably end up talking about how we spent the last year trying to engage with hosts. Deon Hulse in particular worked a lot on this to try and understand a little bit how they can upgrade more. There's a number of really cool success stories there as well. So I don't know exactly. I would like to stop supporting 5.2, but at the same time there's a few million websites that are still running 5.2. Personally, I care more about the older versions of WordPress than I do about the older versions of PHP. And even on 4.3, the latest version for the moment for WordPress, something like I wanna say like six or seven percent of sites are running 5.2 still. So that's, I mean, that's a few million sites right there. And we wouldn't wanna just break it just so we could start using namespaces as cool as they are. I'm curious when you talk about replacing a really big feature like the media library or something like that, when you're trying to maintain backward compatibility, what's the process? Do you just start out by building, like this is what we think would be the coolest thing and then going backward and figuring out where the backward compatibility needs to fit in or do you start with like these other things that we need to maintain and then going forward? What does that process look like? So in my experience, it has usually been the first one. It is like we want to build this thing, we do not wanna be constricted in what we're building. And then let's figure out where we might need to make some adjustments. There have also been some times when we've slipped fatal errors into core on purpose for like a few betas or RCs just to see if anyone would, see if anyone was using that particular feature, see how many reports we might get, maybe to like let them know maybe stop using this thing. We're not gonna leave it there, of course, but there are a lot of, we might accidentally, that's why we have unit tests for this stuff. And so there are little things like that that we try and maybe, that we try and watch, but in media's case in particular, this really was like we're gonna build the thing and then we're gonna like shim in anything that we possibly can. And this happened with, I only talked about like two things, like post-parenting, menu order when you're rearranging galleries. We did a lot of random little stuff that was able to, in many cases, continue to support a lot of the crazy plugins that were in the media landscape, like some of the gallery plugins and things like that, but we realized that it can be a little easier to banding them. That said, it can be helpful to fully size up what you feel like you might need to support. But two problems with that, one, it might not be possible to do so. And two, if you do that, you might really constrain yourself from being able to think about what the next product is, which I think is a lot more important than how it's the best way to technically implement it. Any other questions? All right, thank you very much.