 Good morning. How's Drupalcon so far? Yeah? Pretty good. I am not Steve Fisher. Steve Fisher cannot be here. My name is Carl Weidemann and I'm not talking about design things and patterns. I'm talking about theme preprocessed functions. So thank you for coming to my talk. This is me. I'm actually originally from Denver, Colorado Native. I actually grew up in Colorado Springs. Any button from Colorado Springs here? A few people? Alright. Word. And I live in New York City now and I'm a developer, themeer, trainer, sometimes designer. I do lots of things. I'm C4RL on Drupal.org and Twitter and various other channels on the internet. Not on Pinterest. That is not me on Pinterest but she's cool. I work for a library district here in Colorado called Anything Libraries in Adams County and I also do some work with Atten Design Group. There's a Gold sponsor here at the conference and you did all the design at the conference on the website. So this is a technical talk. This is for people who have been working with Drupal in the theme lair and are maybe a little confused on like what is happening here and how do we maybe get a little more control over these things that are given to us in the theme lair. When I first started using Drupal which I think was back in five, six or so, I was not a big fan because I felt like I had no control over anything and it wasn't until I really discovered the pre-processing layer of theming that I really began to like it. So this is not a new subject. This has been around in Drupal 6 but it's something that is really important and I hope that we'll learn something today. So if you're someone who feels like you want to have control of the markup that you want to know what's going on, I think you're in the right place. I hope you are. So this is a two-part talk. I'm going to talk about pre-processing and theory and then I'm going to give some examples and we're going to have some demo and some code on the screen. How many people have never written PHP before? Anybody? Okay. Cool. Great. So pre-processing exists to solve some theme dilemmas that we have in Drupal, just in general. We see lots of this stuff in templates and sometimes we have this feeling like well this dollar content thing, like I actually want to get inside of it. Like there's something inside of there that I need. Like when I print that out, it's not really what I want. And so one question it tries to answer is how can we create content that's actually more useful to us? Like how can we actually specify what that is a little better. A lot of times we feel like the module developers are just throwing these things over the fence and we're just catching them. We're saying like oh thank you now I have to like put this in this div over here or whatever. And not only that but how do we create context around the content itself to say there's some sort of class, there's some sort of ID, there's some sort of markup that is not content but it corresponds to something that depends on content. And how do we do it in a way that we have control over. That we're in the HTML, we're in the markup and we can have a say of what's going on. So pre-process makes content flexible. It makes theming dynamic. We can have some sense of control over what the classes are. And it also keeps the template system clean. We don't have a lot of logic in the templates. Statements like this where we are doing a lot of manipulation. The templates really are there to just provide markup and not do a lot of magic. So when does pre-process happen? This is our 10,000 foot view of the theming system. In general we have a request that comes in. Someone sends a request to their browser. And the modules interact with the database and they say hey database give me some information. Let me turn that into some return data. And then it sends it to the theme layer. This is this throwing over the fence that I talked about. And how we see this is often a one way street is that there's the processing that happens. We have some return data that has been formatted by the modules and then it's sent to the theme layer to become HTML. And we're most familiar with this in the form of templates is that we have several templates that make up a web page in Drupal. The word page is actually a really bad word because it means like 10 different things in Drupal when we say it's a page or it's a form or it's something else. And so we have different variables that occupy these templates. These are just some examples. There are many more templates than these that we use. And so we sometimes think of the theme layer as just this place where the data ends up. But what pre-processing allows us to do is it allows us to engage this step of the process between the return data and the formatted data to say like you know what I actually want to go back and be able to get more information about this stuff. I actually want to change what this is. I want to have more of a dialogue with the modules instead of just saying oh great I another dollar sign and some random thing that I have to put in HTML. Okay. So we're going to just get right into some demos right away. And I think this will make more sense once you start seeing the code. I'm using a few different tools here. We're going to be using Firebug. How many people have used Firebug? Okay. If you've never used Firebug, your life is about to get really good. Chrome also has a Web Inspector. Safari has one too. Safari was actually the first one that I used before Firebug was around. I'm also using the Devel module. How many people have used Devel? How many people have used the Devel themer thing? Okay. I'm not I don't really use that that often. But it can be useful to kind of learn about the theme system. I also have Drush installed just because clearing the cache as many of you have learned is a is a useful thing to do. And actually pretty important in this these steps. Okay. So we're going to be exploring some files here. I have a demo site that I'll be using. This is it. This is just a little custom theme that I developed here. I've got my fun Latin text for all you Latin speakers out there. And I have just a simple custom theme themes called Jupiter. And I'll show you my code base. Actually, let me open this up. So, oops. Let me actually change the colors here. I always forget to do this. One second. And maybe font's a bit bigger. Okay. Everybody see this okay? People in the back. These are imagination. Okay. Great. So, we have a custom theme. We have a page.tpl.php. Node.tpl.php. We have a few other things in here. CSS file and template.php. Everything that we do in our preprocessor, I have some examples already prepared. This is a blank file right now. Imagine it's blank. Everything that we do in the preprocessing layer happens in template.php. How many people have gone to Google and tried to do something in Drupal and they find something that says paste this in template.php and they paste it and then magic happens and everything's fixed. Have people done that? Okay. So template.php is a place for overrides, preprocessors, the things that I'm going to be talking about today. All of these functions happen in template.php and it's going to become your best friend as a themeer. Okay. So, first thing we want to do is we're going to explore a file that is actually part of Core. It's in the includes directory called theme.inc. And we're going to explore template.php and start using some of these functions here that are fundamental to preprocessing. So, within the core directory we have theme.inc. And theme.inc, in addition to some of the core modules, define information about the variables that we see in our template. So, when we first look at page.tpl.php, which is probably one of the first files we look at when we're starting to get into the market with Drupal, we say, where do all these things come from? We have all these variables. Where do they come from? We've got logo, main menu, breadcrumb, messages, node, all this stuff. We don't really have any sense of where that originates. Where some of it originates is within includes theme.inc. And you will see some functions that look like this, template underscore preprocess page, template underscore preprocess node, that's actually part of the node module now in Drupal 7, template preprocess underscore html. All of these are functions that set up those variables. And preprocessing functions look similar to these. We're essentially extending these. So, we get sent an array of variables. If you've never been in PHP before, hang tight, just kind of get this conceptually and make some friends here who will explain it to you. But we basically have this array. And if you look at this array, you can see all the API functions that are generating the variables here. So, I can see things like feed icons, main menu, secondary menu. And here's the API functions. And if you want, you can dig through this. This is the great thing about open source. We can go window shopping, look with no touch. We can find out where this stuff comes from. It's useful. So, you may find that these functions can give you some information about, okay, how, like, where does layout come from? Where does language come from? So, I recommend kind of exploring some of this stuff and looking for other functions like this. I think the node module have template preprocess node. But these are the fundamental functions that begin to create these variables. And preprocessing will then interact with what these variables do. So, we'll see this in action shortly. Okay. I'm going to be showing some examples here. The first example I'm going to do is going to use the preprocess page function. And what that allows us to do is interact with the variables that are in page.tpl.php. So, here is page.tpl.php. All right. Let me think of, let me think of a good example. So, I think what we'll do is, let's just explore what the variables are. How many people have used the functions dpm before? Anybody use dpm? Okay. dpm is good stuff. So, in the develop module, the develop module provides us some API functions that are rather nice. The one I probably use the most is dpm. There's another function called dd. How many people have used dd before? Oh, not very many. Okay. Dd is similar. I'll explain what it does in a second. Let's see what dpm does. Okay. Let me go back to my text editor. So, let's say I want to see all the variables that are available for page.tpl.php. What I will do first is in my template.php file, this is for my custom theme, which is in sites all Jupyter, is I define a function. The function's name begins with the name of my theme. It's similar to a hook. The name of my theme underscore preprocess underscore the name of the template. So, in this case, it's Jupyter preprocess page. And then the arguments, it actually just takes one argument and it's the array of the variables. And this is passed by reference. So, this actually interacts with the same variables that are defined there. And this is an array. So, we put the ampersand in front. And what we have is the ability to see what these are, to change them, to alter them, to do whatever we want to them. Let's actually just look at them. Let's just see what they are. So, this is what dpm does. dpm is a great function. What dpm does is it creates a nicely crafted output of a variable and puts it in the messages box in our theme. One thing to keep in mind with some of these preprocessor functions is that they are sometimes executing after messages has been defined in the template. And so, they may be one page request behind. So, you may refresh and you don't see anything. Refresh again. It's actually from the previous request. This is something you just have to get used to. Let's actually just see it in action here. So, I create this function. Whenever I add a new function or whenever I add a new file to my theme directory, what do I have to do? Clear the cache. Don't forget that. Even I forget it sometimes. Okay. So, I've added my function. I'm just going to dump with these variables over the screen. I like to clear my cache through Dush like this. You can clear it however you'd like. Awesome. Now, I'm going to go to my site. I'm going to refresh. In this case, here is my dpm. So, this is going to output this really nicely formatted list of variables. It's in this nice javascript drop town thing. This is an array. It has nesting here. If you haven't used dpm, this is now your best friend because now you instead of using print R or var dump or something weird, you can do this. It has a little, it has a few quirks to it. If things are passed by reference, if you know just depending on where it executes, it has a few quirks. The way difference between this and the function dd is that dd dumps to a file in your temp directory. So, sometimes if you're doing this on a production site or somewhere else, it'll dump to a file in temp called drupaldebug.txt. And that's also a nice way to do this. Sometimes this array can be really big and you want to grab this output or something like that. Okay. So, what I can do is I can dive through here and see things like, well, here's my feed icons, right? There's that variable and here's main menu and it's got an array of stuff here and I can see the hrefs and the titles. Here's tabs. You know, these are all the these are all the items that appear in my page template. I can even see the page array, which is what the new render API uses here. So, I can look in content and I can see system main and here are all the nodes that are loaded on my front page. So, I can actually go into the node objects themselves. This is what I'm talking about with some strange things. This is actually a recursive reference to a node. But I can get into every single item here. A lot of this stuff, we didn't even see reference in the documentation at the top of the template here. And so, in order to find out about it, we have to use DPM. We have to get in here and investigate. And we find that there's also things in here that we may not have known about before. We actually have access to the user object if we wanted it, you know. Now we could also use global user to do that but there's good stuff in here that we may not have known about before. So DPM is awesome. It's a great tool for module developers and theme developers alike. Keep in mind that sometimes it does have that. It is rendered after messages. Messages is what's actually being printed out here. It's rendered after that as generated. So if you have some issues with that, be careful. Another problem you might run into is if you leave this in the page template over and over again, it actually is referring to itself because messages is in this thing and you may exceed your MySQL session right buffer and then you get database errors in your theme layer and this happened to me when I gave this talk at DrupalCon San Francisco in front of about 400 people and I didn't know what was going on. So keep that in mind. Let's look at a different template. We're familiar with page.tpl.php. We also have node.tpl.php with different variables. And as we recall from this picture is that whenever we render a node, whether it be in a teaser or whether it be a singular node, there are variables that we have available to us in that template. And those are different. And those have a different function, a different preprocessor function. So let's look at node.tpl.php. I'm just going to go back to my template file, comment this out. I'm going to create a new function, jupyrup preprocess node. In general, the names of these are always the same format. We always have the name of the template at the end. It also takes vars. In order to see this work, what do I have to do? Clear the cache. And uncomment it, right? Okay. Fine. Uncomment. Okay. So clear the cache. Now this is going to output variables for a given node. So let me actually click on a node here. I'm just going to click on this one. And I think I have to refresh because it is a page request behind. And now these are actually all the variables that we would see in the node template. So I can see the version ID, node status, sticky language, Unix timestamp of what is created, all these things that are in the node template. We actually have the original raw node object here, which is available in a few places here. We also have the content array. So we can see links. We can see body. So everything that we have available to us in any template we can now see using DPM. So this is like, oh my gosh, like now I actually know what's in these templates. Now I can actually interact with what these things are. So let's start doing that. So let's just mess around with some of the variables here. So one thing that's part of node templates, this is actually a basic page node. Let me find an article node. Here we go. How many people have tried to change submitted? Remember submitted? You've got spans in here. In the template it's just dollar submitted, right? But you're like, but I have a span in there and it has a class and I want to change what that is. Why do I have markup inside of a variable, right? Now that we have access to this array, we can actually change what that does. So maybe what I want to do is in here, I want to say vars submitted. Maybe I want it to be formatted as like an interval of time. So we can say format interval. And I have access to the node object in the current time. So let's see there's the node object so I can say vars node created. And I'm going to say time current time minus this. So what I'm going to do is just I'm just going to redefine what vars submitted is. I say I don't like how it's formatted. I'm going to do it this way. So my colon. All right. I don't have my DPM in there so we won't see the output. Let me refresh here. And I scroll up and we can see that now it says 17 hours 53 minutes ago, right? I could change that to something different. I could say format dates and that needs the format and then the timestamps so I could say like in J. Is that right? It takes the date first? I don't remember. Maybe I just want date. There we go. Right? Now I have 320, 2012. So all of a sudden this variable that I was held hostage to by the module developers that I thought how am I ever going to change this? I have to use regular expressions. I have to do something silly. I don't you know do I have to parse this into something? I can just actually go to the node object and change it to whatever I want. Which is a very cool thing. I could even create my own variables in here. So let me go back to the page preprocessor. Maybe I just want to say vars greeting equals hello. And then what I can do is now that I've created a new variable that's available for me in my page template. So maybe I want to put a greeting in front of my, maybe in front of my H1 on my site name here. How about here? Now let's put a space. That may seem kind of boring but you could do things like maybe you have an array of greetings and it's something like, I guess we won't need to translate these. Let's say we have like, let me spell that right. It's hard to spell when you're in front of people. And then I could maybe say, maybe I just want a random greeting here. Maybe I have an array of greetings and I just wanted to talk randomly every time I refresh the page. So now this is just choosing from this array, I'm refreshing the page every single time. Now this isn't content, this is just like, this may be part of just something you want to do. But now you have control to define your own variables, your own new variables. And you can imagine these could be classes, these could be IDs, it could be whatever you want. And now you can interact between this system of definition and the system of output which is the template. We have the ability to actually specify the templates that are used in preprocessors. How many people know that if you create a template called node dash dash article dot tpl dot php, it will be used for all article nodes in your Drupal site. Or basic page or whatever, right? Okay, that's a fairly well known thing. What we see is in our, let's go back to our node variables here. So I'm going to go back to node dot tpl dot php. And I'm just going to dump our variables again. There is an array called theme hook suggestions. And you'll see in theme hook suggestions it's an array and it has some elements in here. And you'll see here that the first element says node underscore underscore page. It means this is actually a node that is a basic page content type. And you also see another one says node underscore underscore 349. This happens to be node 349. So what this means is if I could create templates called node underscore, node dash dash page dot tpl dot php, it would be used to format this node. I could also create one called node dash dash 349, dot tpl dot php or maybe I want to specify my own. So maybe I want something that, let's say all unpublished nodes get a special template. Here's an example. Or maybe all nodes with an odd node ID get a special template or something strange, right? What I can do is I can append a template suggestion to that. So let's call this, let's do the unpublished example. So we'll say if empty node oops bars node status. If we have an unpublished node and this is called theme hook suggestions in Drupal 7. So I'm going to just append C, G, G, S, T, I, O, N, S. I'm going to append a string called let's say node dash dash special. Oops, underscore underscore special. What this means is that now my theme is going to look for a template called node dash dash special. When we are dealing with hooks, theme hooks versus template names, there's this transposition of hyphens and underscores. We'll see how this works. So what I'll do is I'll go into my theme directory and I'll make a copy of node. Now I have a new template called node special and maybe I want something weird in here like maybe for unpublished nodes we want something really obnoxious like a big link tag that says unpublished at the top right and let's make this extra obnoxious. Now I have to do something what I have to do clear the cache. Whenever we add a new template file we need to clear the cache. Keep that in mind. Okay are we going to DPM here? It's not DPM. Let's hope this works the first time. So here's my node. I'm going to go in and edit my node, unpublish and save. Right. If I go in and I DPM my vars I should be you know I will see my new variable here in theme hook suggestions right. So there it is. So you know you can do all sorts of things with this. Now you have the ability to dynamically change which templates are used based on information about the node or any part of the node. The node content taxonomy terms, node ID, author, role of the author. I mean we can do lots of things in the preprocessed layer. It's all PHP so we can get deep in there and decide how we want it to react with our templates. Do we have a lot more control over that now? Okay. Contextual CSS. This is something that now we've kind of messed around with some of the content that appears in our templates. Let's actually change the way in which that is rendered. So suppose you have the following situation. You're building a site for a client let's say they're building a blog. It's a sports blog so they have articles about sports and part of your task they say okay we have articles on our site and there's sports articles and so what we want is we want different categories for these articles. So you set up a taxonomy term for your categories for the sports. So you have baseball articles, basketball articles, football articles, soccer. And they say what we'd like is when someone visits the site and they click on say a baseball article that the header in the banner like has baseball specific graphics. And when they are on a basketball article it has basketball like in the A graphics and so it's like we have different sites depending on what type of article. We just want that driven by taxonomy. We want to choose the taxonomy term and we want the design to change. And you say of course I can do that of course right. I always say yes. Figure it out later. So that's a question so now you think okay well what do I have to do? I have to change. I have to change a part of the markup up here. I have to put in a header graphic specific to something that's an attribute of my node. And that's very different than the world that we've lived in here is that we have this very distinct separation between what is a block and what is part of the page and what is part of the node and they kind of seem very different and distinct. So what preprocessors allow us to do is blur those lines a bit. So what's our first step here? The first step in this process is you say okay well the best way to do this would probably to be to change the class on the header div depending on what the taxonomy term is for the node that I'm viewing. So I need to be able to put a class in there. That div is in page.tpl.php. So I know I'm going to be working in a page preprocessor. I need to alter the variables that are in my page template. So let's go into template.php. I just close my text editor. Let's go into template.php and find out what variables we have to work with here. So I'm going to go to template.php for my Jupyter theme. I think I have this example set up already. Yes. To save us some time. So this is the taxonomy example. Here's my page preprocessor. There is a function in Drupal. How many people have used the function node or sorry menu get object? Anyone? Okay. Menu get object is really useful. What it does is if we're on a node, if we're viewing a node, it'll return us the node. So we say if I'm on the node and I'm running some code somewhere, just give me whatever that node is. What I'm going to do is I'm going to just grab the node and I should have fields available there. What this means is now the, now I have information in the page template about what node I'm looking at here. So I can just DPM out the node using menu get object. Let me click hash again. So I can use menu get objects. I use menu get object. It grabs node 320. It dumps out the raw node object. This is what we get from node load. Those of you who use node load. This is basically what we get from the database query here. And you'll see that I have field data here. And this works the same way in triple six if you're using cck. And I can actually go in to say like field sport. That's my taxonomy field. And I can see, you know, I here's my term ID and here's the taxonomy term itself. So I can, from the page template, I can get the node. I can dive into information about what that term is. What I'm going to do, that's the next few lines of code here, is I'm going to look at, I'm going to see, okay, have I defined a term ID in my field sport? If so, I'm going to append that using this term prefix to the classes array variable. And let me actually comment out my CSS so I don't blow everybody's mind too fast here. In our variables, you will notice if I look at page.tpl.php, there's something called on our, in this case our page ID, something called dollar classes, right? That's built up from an array called classes array. If I add things to classes array, if I add terms to that, they will all be concatenated together with spaces and I can just add classes to this. What I'm going to do, I'm going to put a class on this page wrapper. If I put a class in the page wrapper, now I can use CSS selectors to define what the background image is, of my header, of my page or whatever I want. In this case, I'm going to look at the actual term identifier, concatenate it with term dash and append that to my classes array. I'm going to do the markup first and then we'll look at the CSS. I do that. I'm going to go in with firebug. If you haven't used firebug, you're about to get really excited right now. Firebug or Chrome Web Inspector allows us to dive into our variables here. Here's my page. Let me get this up on the screen for everybody. Here's my page div. Now we can see there's term dash 1 there on the class. Let's go to a difference categorized article here. I have another category of basketball. Let me find a basketball article. Here's a basketball article. Oh, it was yelling at me for a minute there. Here's my basketball article. I'm going to inspect and here's my page ID. Now it says term 2, right? That's the taxonomy term ID. So now I have information about the node on this big wrapper up here on the page wrapper. Now what I can do is in my CSS file, the client even hired a lovely design team who's provided us with these really nice header graphics that we want to use for our article. So this should be the baseball header. Here's a basketball header. In my CSS file, now I can define background image attributes for my header divs that are inside of a term dash 1. My header div that's inside of a term dash 2. So if I save this, and this is my basketball article, I should have my basketball graphic there. If I go back to my baseball article, I have my baseball graphic there. If I go home, I don't have anything because when you get object isn't returning anything. It's not returning a node. But now I've basically just created two totally different sections of my site. I still have an error for my, let me take out the reading. Let me spell it right. So now I'm changing the markup, the context of this thing that is way outside of the node, way outside of this thing that's kind of buried in the page to change the actual markup of what we see in the classes. So we have some context in our CSS about what the content is that we're looking at. How many people think this is pretty cool? Anyone? Okay. Good. That's the idea. Okay. Next example, what do we got? Working with fields. So clients says, wow, you're really good at this. I'm really glad I hired you as my web developer because you just gave me two different themes in about 10 seconds. So they say, okay, here's our next requirement. What we want is we want to set up a article type, content type. And when the author is authoring that, we want them to have text and we want an image available. And the image field, we actually want to give the author some control over that. So we want a field based image. We don't want to have them uploading things manually and using like TinyMCE or something weird in order to place an image in their body. We want to use a field and we want to give them some control over where that is. But what we want is when we go and create this piece of content, which we'll call a better article, is we want a field for the image and then a separate field that gives us the position of the image. So when I select center, I want the image in the center. I want it 400 pixels wide. When I want left, I want it 200 pixels wide. I want it floating left with the text wrapping around it. And when I select right, I want it on the right-hand side with text wrapping around it. And I want it to be field. So when the author creates this, they can just select this and it just works. Okay, so you say no problem. Now what I have to do is I have to be able to change the CSS of what is wrapping the node in my node template. I also have to change maybe the image style because the center image style, they want it wide. They want it 400 pixels. The left and right, they want it to be 200 pixels. So I need to change the image style. I don't want to just resize it using attributes. All right. So how do we do this? This is also available in Drupal 6 through CCK. So a field example, let me just create the node first and we'll look at what the node is. So we'll say, we'll get some fun Latin text here for our, oh yeah, Latin sports blogs are so hot right now. We want to choose our image for our article. So let's get, we're still our sports blog here. Now I haven't set anything up yet. So this is just going to be the behavior of the box. One thing you'll notice that we have at our disposal is under our content types for our display. We have the ability to actually decide how that image would be formatted. What we want to do is we want to actually hide that. We don't want to leverage field UI. This is field UI. We're actually just going to let field UI just go away by field UI. We want to have control over this. We want to be able to change how this is formatted based on a different field. So it's an additional formatting here. I'm going to hide it by default. What I'm going to do next is in my node preprocessor, one of the variables we have at our disposal is node. And when we have node, we can look at the fields on the node. So let me comment out everything else here and let's just look at what node has. So I'm just going to DPM the node, clear the cache, and here's our article. So we'll just leave the position at center. We'll say this is a baseball article. Save. Okay. So here's my node object. I just DPM this out. I'm like, let's just see what our node object is. This is a new content type. We haven't used this before. This content type has our image field. It has the image position. So I'll go in here. I can see I have, here's my image field. And I can scroll through here. I have the file ID. I have the width, the height, the file name, the path, all tags, anything that's, anything that has to do with that file, I can now dive in and find. I also have this position field. And I set this up as like multi-value text so I can see I've selected center here. So now that I have these variables at my disposal, I can start interacting with them. So what I'm going to do is for a full node view, so I'm not in a teaser. Let me make this bigger. And if I have to find a position, I'm going to look at what that position is. Oh dear, my cord just came unplugged. That's not good. Hold on a second. Here we are. I'm going to look at what that position is. If it's left or right, I'm going to use a medium image style. That's just from our styles module. Otherwise I'm going to use large image style. The position I'm just going to pull in as the value of field position. So it's going to be left or right. I'm then going to use theme image style to format that. Theme image style allows us to just format an image as one of our defined image styles. So theme image style medium, theme image style large. That's just going to give me the image tag. And I'm also going to define a variable called my image position. So I define two new variables. I define something called my image which is the themed image in the right size and the position which is the value of that field. Then in my template, I have some markup here. It says if I've defined my image, give me a class called my image dash, whatever the position is, my image left, my image right, my image center, and dump out the image. And this has been formatted depending on what that left-right center is. So I save this in my CSS file. I have here's my image left, my image right, my image center. Floating left, floating right, giving some white space there. So let's see this in action. I'll refresh. So there's the center aligned. It's at the top using a large style. Author goes in, changes the position, clicks save. Now it's floating left. Different style, goes in, clicks right, clicks save, changes the position. So now we're using fields to control all the fields, fields to format other fields. And as you use the author, you don't really care what you have to do here. You just have to, you just have to select the value of the field. You can also imagine creating a separate field for captions, dumping the caption in there to have that formatted nicely under this box using, you know, like borders and things like that. So they just type in a caption, they upload their file, they choose where they want it to go, and it shows up where they want it to be. A few more examples here. One thing you may have noticed is that every template, every template in Drupal has a preprocessor. Everything. There are lots of templates. This is how they relate to each other. And we've seen this, right? If we have a template that will have some file name, that file name may have hyphens in it. The preprocessor for that template will be formatted as the name of our theme, underscore preprocess, underscore, the name of the file with the hyphens replaced with underscores. So any template you see, you can create a preprocessor for the variables that appear in that template. Anything. Okay, here's some sexier examples that I thought of. Views in box. So let's say you have a view on your site of recent content. And so you just created a table view. You have that's ordered by last updated date. And you have this, you know, you have this field that says new or updated. But let's say you want these rows to look different. Like when you look at Gmail, what new messages, have a white row with bold text? So the CSS for that row is different than the CSS for a different row. So let's say you want that for a Drupal site. Let's say you want all nodes that you haven't seen that look like that. Views, if you look in, I'm not going to spend a lot of time on this, but under views, if you edit a view, there's this thing that says theme information. Anybody ever clicked on this thing before? This tells you all the templates that are available for you to use. They overwrite each other. You can look at the documentation for this, but we have a lot of control over what these do in Drupal. So a view is built up of a bunch of templates just as, you know, the entire markup of a given page is built by many different templates. So what I can do is for my inbox, I'll show you this example. So there is a template called viewsviewtable.tpl.php. It looks like this. All these template files appear in like the views module, the node module. All templates actually come from the modules themselves. Themes just override these templates. So if you're looking for a template, look, you know, you'll find it in the codebase of the module. So here's what views does for a table view, right? It's got some TRs. It's got some loops. It's got some classes there. If you DPM enough, you kind of figure out how things work here. What you'll see is that we have a variable called row classes. And row classes correspond to the classes that are on each row of our table. And so what I'm going to do is there's a field in our view. We have all these items, item one, item two, item three. That has a value called history time stamp. History time stamp is something that tells us, I believe, when the node was, when we last saw the node, when our user last saw that. And we also have another field called node comment statistics last updated. That tells us when the field was last updated. So we were going to add a class of new if we haven't seen it before. So history time stamp is empty. We're going to put a new class on row classes. If history time stamp is less than when the field was last updated, we're going to put an updated class there. In our CSS file, oops, we have, I think these are just the same. Oh, the colors are slightly different. So for a views table with a new row, we're going to use a different font weight and different background color. So what do I got to do? Go to the cache. I've now registered that function. I refresh this. Now it's changed the class of each of these. I can go in and inspect these. So you'll see that now in my TRs, I've got new, new, new, new, new for a lot of these. I can go in and maybe I edit this. Save. Go back to the inbox. So I've already seen that one now. Right? Class goes away. Let me log in as a different user in a different browser. Or actually, I'll just log out. I have another user called Carl. Any Drush fans in the audience? Anyone use Drush ULI before? It gives you the, I forgot my password link to a user and just log in as them automatically. So now I'm logging in as Carl. Carl goes to the inbox. Oh, these are all new for Carl because I just created them. So maybe they go in and edit this. Save the class, right? Here's his green. Different color. All right, I have one more example. This is kind of like the scary example, like what you can do. What you'll soon realize is that you as the femur have the power because you are the last step before the browser and you can do whatever you want. Here's kind of an example of that. People who are services people and back-end performance people are going to chew me out for this example. Don't do this. This is just kind of like, what if? We have a template called HTML.php. HTML.tpl.php is the entire HTML response. Doc type, head, body, everything. We could override that if we want to. Let's say your client says we need this working tomorrow. We need something that if someone has put in the query string, JSON equals one or JSON equals true. We actually don't want to return HTML. We want to return JSON. We need a fast JSON API. We have to connect to the service. They need our content in JSON or XML or something weird. You're like, I don't have time to install the services module and figure out how to configure it. Like, I just don't have time. So what you could do, which I don't recommend doing because it's kind of sketchy, is say, all right, if I have a JSON parameter in my query string and I'm looking at a node, I've used menu get object. I'm going to put a new theme hook suggestion here called HTML.json. I'm going to add an HTTP header that's going to tell the browser to output this as JSON. And I'm going to JSON and code the node as an array and set it up as vars.json. And then in my new template, HTML.json.tpl.php, I'm just going to dump that thing. Don't do this. Oops. Clear the cache. So, here's my HTML node. Here's my JSON node, right? JSON API, really cheap. Now, why is this a bad idea? Because I'm doing the whole Drupal Bootstab process. I'm rendering all the blocks. I'm doing all my other stuff. Like, it's doing all that normally. I'm just saying, like, oh, all that markup you just generated, that's not important. Let's just give them this. But, in a pinch, you could do something like this. And this really shows the power of the preprocessed layer. You have to be careful, because you now have the power to do whatever you want. But sometimes, you want to be careful that you're not doing too much in the theme layer, that you're not over-abusing the theme layer more than you absolutely need to. The theme layer is really useful. Pre-processing is very, very useful. But you want to make sure that you are dealing with things that are indeed theme-related, that are design-related, that are layout-related, and not explicitly content-related. I get some questions often about other, like, user-interface-driven toys in order to do this kind of thing. People say, well, why don't you use DisplaySuite? Why don't you use Panels? Why don't you use maybe, like, the Omega theme with, like, Context and Delta Module? How many people have messed around with some of this stuff? Anybody? Okay. This is good stuff, too. And this is useful if you want to kind of click around your browser and have that relationship with Drupal. If you're more of a person who prefers this kind of relationship with Drupal, you may find that pre-processing is a lighter-weight world. Now, every time you want to change something, yes, you're diving in the code. But remember, this is the control-free people, right? We want to, legally, I code. Code is good. We want to get into the HTML. We want to change that class exactly. We want those classes in a different order. We want the wrappers to look in the way we want them to look. So if you feel like these things, these are excellent tools. You may find that everything I just did, like with that image example, you could actually achieve with DisplaySuite through some configuration. So in Drupal, there's five different ways to do one thing. These are some other things to keep in mind. They haven't been as robust and long as long as pre-processing. Important things to remember. DPM could delay. It could not appear on the page request. That's true with other templates, like if the node template and things like that. So if you don't see it on the first request, you may appear on the second request. Clear the cache. Clear the cache. Clear the cache. Clear the cache. Clear the cache. Another thing I didn't really bring up here but may as more subtle is, like, be careful with the output that you're dumping in your templates. Look at the function's check markup, check plane. I think there's one called XSS Admin or something like this. These are API functions. Look at api.drupal.org. These are things that make sure that, like, oh, I just wanted to print out this variable. Well, maybe that variable, you want to, like, sanitize it. You want to make sure that people, like, in the filtering system, that people aren't putting, like, JavaScript in your node body. I mean, we have the power in the pre-process layer to just dump the raw node body, but that's not the filtered output. So keep those in mind. Be safe about the stuff that you're dumping to the screen. Okay, this is when I open up for questions. I think we have about five minutes. Maybe a little longer for questions. I'll push it a little bit. I always do. And take the survey. If you have questions, there's a mic in the middle of the room. So if you want to go up there, you can do that, or you can just yell. You can yell. Yes. Yes, good question. I always get asked that. So I understand. The examples will be posted. What I'll do is I'll put a comment on the node, on the conference site. I'll have links to the theme that I did, and maybe the database dump and that stuff. And the slides. Yes, question. Yeah, it was more of a comment. There's also an inspector for Chrome. If you don't like Firebug, Firefox actually now has a native inspector. And sometimes I open them both up at once and things get crazy. But Chrome has a good inspector. It's excellent. It's a little different. I'm more used to Firebug. Safari also has one, too. Yes, that's a good point. Someone has brought up the API functions field get item and field get value, which can help with multi-value fields and multilingual sites. And in the world of Drupal 6, we didn't have that luxury. So that's something new in Drupal 7. Lots of API functions for us. Anyone else? Yes, there. Yeah, the question is the DPM looks similar to develop. You can't use DPM unless you have the develop module installed. It's actually an API function within develop. That's why we need develop. So get the develop module. Otherwise, you can't use DD or DPM. But it's the same type of... When you get that develop tab, when you're looking at a node, it's basically the same thing. But you can look at any variable, not just the node output. Yes. So the question is, can you override the node edit form? Yes. There are two kind of caveats to that. If you're using an administrative theme, it's gonna be in a different template.php. So if you're using a core administrative theme, then maybe you don't want to mess with that template. Another thing is that it's using different theme functions, like theme field. And it's using lots of the render API. By the way, I didn't really talk about render and show and hide. I kind of like this way of living better than render and show and hide. If you're into render and show and hide, there's a lot of debate about that right now in the future of Drupal. It's actually a bof this afternoon at 3.45 in room MHB1E, where people are gonna be talking about that stuff. But something to consider. So yes, you can. You may actually want to look at panels though, because panels you can actually define like the node edit form. You could actually change how that looks. So, yeah. Yes. How much overhead does this cause? It kind of depends what you want to do. I could do whatever I want in the preprocess functions. That could be doing very expensive operations. I could be doing a very expensive API call. I could be loading things that take a long time if I'm doing like loading lots of nodes, for example. I think the answer to that is just use best practices in terms of static caching and also caching the output of the pages. Have caching turn on your site. If you have a lot of authenticated users, then make sure that you're just thinking about the variables that they need to see and loading them in a way that is lightweight. And always do performance benchmarking. Because humans have a very bad tendency of anticipating the wrong types of things that they need to load. And they think, oh, I need to optimize this part when it's in fact something else. So always benchmark and turn on the cache. Anyone else? Okay. One more. Yes. Yes. Sure, the question is how different is this in Drupal 6? Not very much. There are a few differences in what variables are available, but all the theory is the same. Theme functions are called slightly differently. When you call a theme function, it used to be you would hand it sequential arguments. Now all those arguments are in a single array. That's really well documented on the Drupal dot org. But all the theory is the same. Okay, I think that's all. Thank you for coming. Joy Drupal Kahn. And we'll see you around. I'll be around here if you have more questions.