 Good morning everyone. Welcome to DrupalCon. Nick Vidal, I'll be your room monitor today. And if you guys need any help, please let me know. We're going to start out a session called Rules Without the User Interface by David Kitchen from London. So I'll pass in the word. Thank you, David. Hi, good morning everyone. Hope you've all got here fine and ready to start this morning. So Rules Without the UI and how to include default rules in your module. Our agenda for the session, I'm just going to show you here. It always seems to do this slow for the first slide. So what we're going to do is I'm just going to give some introductions to myself and what we're going to talk about. Talk about the actual rules module and how you can use it in your module. We're going to have a short little break in the middle of the presentation to relax everyone and then look at a case study of how to use rules in your module. There's information about where you can find out more about using rules in your module and then time for some questions at the end. So I'm David Kitchen. As I said, I work for Commerce Guys. I started there in October last year. But we have opened the office in the UK then and that's when I started. And here are some of the modules that I worked on. I look after a module for doing European VAT. But also worked on payment gateways, recommender system and other modules including Carl on File, which is just recently being released. And a lot of these modules all use rules and at least quite a core part of Commerce and how it works. So I hope that's something that's going to talk about and pick out here. So the rules module itself is a system for providing event, condition, action programming. And it's maintained by Wolfgang Zeiger or Fago on Drupal.org. And so that's the URL for it there. And I'm sure you've all used it. And just to get on that, I just wanted to get some idea of what we've got in the audience here. So I can get a show of hands of who's written a rule using the UI. And has anyone written some of their own events or actions in rules to using them? And has anyone actually written a default rule using code and included that in the module yet? So that's good. That's what you're all here to find out about. So just going through why we want to support rules. So rules actually is really easy to use. It's non-intrusive and it unifies functionality between modules and provides good practice to learn from as well. So it's a framework for event, condition, action programming. It can be used by lots of other modules once you've started using rules. So that includes things like views, bulk operations. Once you've provided some rules, you can use, views, bulk operations can use rules to provide those operations. And you can combine with other modules to provide some really useful functionality that a site builder can use for their benefit when they're actually using a site. So I've just got this here. There's a quote from a blog post from Wunderkraut, which is I think really useful, that rules is a complex framework. To some extent it is heavy, but a fact that event, condition, action style modules are pretty common and it doesn't make sense not to have a framework for them. Rules may not be the perfect tool, but it is a good tool that can be improved. This was said in that blog post from 2011. And some of the key points about rules, it is configurable, exportable. You can clone them, reuse the components, and it provides unified functionality across systems. And you can really get some quick solutions. And even yesterday, here's an example, this was on Sunday. There was a module released, which is an API for Jenkins. And it is just basically a set of rules, actions, that can be used by any wall now to integrate with their own site build or module. And once those actions have been provided, they're really easy to then use within rules. So it provides them actions for triggering a build and creating a new job or copying an existing job within the system. And that's, so this is the whole point of using rules. Someone, if those were just actions within a module that someone has to go away and start coding and interacting with, it's a lot more work for actually building a site. So start to look at how you can support rules in your module that you're developing. The first part is a rules ink module. And this provides a data info about what your module can provide to rules. And this covers data types. So if your module provides a specific data type beyond the standards that are available, such as strings and integers, you can provide details of that here. One of the examples of those is the VAT module provides a data type, the taxes that are in commas. It exposes those as a data type in rules to use it for conditions. You can then provide events. And so this is when something is happening within your module, you can provide an event that can be used to trigger a reaction rule, conditions. So this is where you're trying to provide a simple one step condition. Rules provide some standard conditions for comparing strings or integers or Boolean values. But if you've got a complex condition, you can provide some functionality that actually reviews those. And then the actions. Generally providing the information about functions in your module and how rules can use those to create an event action from those. If you're providing entities within your module, it's really quick and easy to get some information about those entities into rules. So by just making sure your entity info and entity property info has full of set of information about create, save and delete, access callbacks, the properties that are available on the entity type. Once you've provided all that information in those hooks, the rules will pick all of those up and be able to provide those as actions for creating and saving and editing those entities in the rules actions. And of course, if you're dealing with an entity that's provided by another module, then you can use the entity info alter to add those in if they're missing from another entity type. So the core part of this, the default rules, is just like you might have done in views, providing a default view. There's a file. Just to be slightly confusing, it's got an S on defaults. But once you've got that file there with your hook default rules configurations in, that's returning an array of the rule object, you can provide those default rules in there. And there is also a default rules configuration alter hook to provide an alter rules that are being provided by another module. So the rules components. The first type of rule is the reaction rule. This is the core part. It has three parts to the rule. The event, the conditions and actions. There's always at least one event for a reaction rule, but you can have multiples. So this could be on saving an entity or creating an entity as both of them are two different events within the rules events system. Conditions, again, multiple conditions, providing the requirements that need to be passed for this rule to take place. And then the actions, again, multiple actions, taking any of the information that's gathered in the events. So if the event was saving a user, then you've got the user entity available to provide as an action. And through the conditions, you can in effect look up other bits of information. Then there are the components. And again, there is a rule, but this is without an event. So this is a combination of both conditions and actions to form a rule. Condition sets can be grouped in either an or or an anset. And these can be included on your rule or reaction rule within conditions. And very similar, there is an action set. So this is a group of actions to put together. And you can include that as an action within another rule. And this level of reusable components can be very useful for grouping together the action sets and taking that information that you've got in your conditions and providing some parameters into those action sets, depending on the conditions that have been met through the rule. Each of these, so we're starting to get here into writing them in code. And we start with creating a rule. And each of these takes for the components a set of variables. That's the input that's going to be taken into the rule. And then any output that provides, this is the data of the information that's going to come back out of that condition set or rule set. And these can be the data sets that I mentioned before, or any entity type within Drupal. So we start with creating our rule or component. We start with just the object we've created and we start adding a label, some description. The tags can be very useful to provide some information in organizing the rules within the UI. You can set a rule to be active when the module is installed or disabled. On this example, all of our payment gateway modules within Drupal Commerce are provided with the rule that comes with them disabled and a merchant can then activate the rule when they're ready to activate the payment gateway. And once you've got that, if it's a reaction rule, then you add the events to the object, conditions and actions. It's important to keep the simple the way the rules work. Rules will always stop as soon as it reaches a false condition. So it always works really well to try and keep your simplest conditions first within the condition sets. So if it's going to find a false condition, it processes it as quickly as possible to try and process any complex conditions that it's going to have to pass through. One of the things that you don't have in rules is a way of saying else or else if. So there are options of doing that by providing multiple components. So there is also a module that adds on to rules to provide some else and else if conditions. But if I give an example of creating a shipping conditions. So if we're wanting to calculate some shipping in commerce, we have a reaction rule that's based on the event of calculate shipping. This is a request within commerce that takes place during the checkout process. And we've got a rule, that's our reaction rule which is the three lines in the blue at the top. And it's got a condition to check that the order has some shippable products. Then as the action, we've got three rule components that are as the action. And each of those has a set of conditions that will step through those. So in this case, our first action is to a rule to check if the address is within the UK. And if it is, then it will provide a UK shipping price. The second, and if this was returned false, it would move on to the next rule condition, set the rule action set. So we've got two conditions in this one to say that the rule is in the EU but not in the UK. And then we can get an EU shipping price. And then finally, a question of is the address not in the UK and not in the EU? And that is a way of providing the else if conditions within the rule. So as I said, we're just going to have a intermission now. Apart from working for Commerce Guys, I'm also involved in a company in my spare time that films aeroplanes called Planes TV. So I've just got a one-minute video that I'm going to play, and it gives me a chance to drink some water and use to enjoy a video. Then we move on to a case study. Hopefully you've taken all of that information in that we've just done, had a bit of time to process it there, and we can now look at how we actually use the default rules. So I'm going to use an example. This is a module that we've just been launching, and I've been working on, which is called Exacter. It's a system for calculating sales tax in the US. And it's got three actions within the module, and these are for submitting an order for a tax calculation, committing the order, and then refunding it. So firstly, just talk about providing the action within the module. The action takes some information, which is the customer billing and shipping address, the address that the order is being shipped from, and the order itself. And once it's got that, it will send it off to the system for calculation, and that returns some data about the tax that's been calculated for the order. So within the hook rules data info that I mentioned before, we're going to provide the action information, and this includes a label for the information about the action, the parameters that I mentioned that it will take for the action, and in this case we've got the order, which is an entity provided by the type. We've got a billing address, shipping address, and from address, and these are all the address fields type. And it's grouped together, and then we have our execute callback. This is the function that the module provides that this action is going to call. Now, this is really useful. So within the UI, once a site builder comes to use this, they can configure this action to be exactly how they want it to happen, rather than making any assumptions on the system. So especially within commerce, the way that the store is set up can very verify between stores, and the actual information of where the billing address or the shipping address is held might be different. So by providing this in rules, we provide an easy way for the site to configure these decals. So to provide the default rule for this action, we need to decide when is this going to take place, and this is at the point that the customer reaches the checkout review page within the checkout process. And at this point, they've entered in their billing address and shipping address, if shipping is enabled, and have selected their shipping method to get a price for shipping. And once all of this has been collected together, it's got all the information that's needed for this action to take place. There's also a second time that this rule is going to be called, and that is when a merchant changes an order after it's already been placed. So we want to be able to recalculate this data if the order has been placed by the customer. It's been, payment has been received, but the merchant has decided, we have not got something in stock, we're going to have to cancel that line item and refund. They need to then recalculate the tax because it may have changed. So the event that we're going to use for this is going to be the order presave. This is the moment before an order is saved. We're going to be able to check some conditions on that order and then set the action that's going to take place. So here's the start of our default rules configuration. So we're creating a reaction rule in this case, providing a label, as I said, for it. We can include some information about what modules are required for this rule to be able to work. So in this case we need rules. It needs to have the commerce exacter calc module available and the entity module. And if these modules aren't available, it would disable this rule to make sure it doesn't try and run when it can't. So as I said, the events we're going to provide based on the commerce order presave. So these are all provided by different modules and in this case the commerce order module provides this event because it's all there in the entity type, so it just happens and it's there. What I actually do here is create a rules or condition set using rules or that I'm going to include within the rule at the end. So our first question is does the data is, which is the question, and we're going to check that the commerce order status is in the review status. So in this case we could have multiple values in this array that's shown here for the value. And again, we also check that the commerce order state is impending. This is the state that is after the checkout review. And just to point out there's two different, slightly different, data here. One is status and one is state. And the status is there are multiple statuses within each state. So the states for the first one is actually checkout, but then there's multiple statuses within that state. And the reason why we're providing this default rule with these default settings is that this is a general assumption. So what a merchant can do is decide to change this default rule that's been provided to them based on their configuration, which is all about this being able to provide a rule rather than making any assumptions on what's going to be there. So we then add that condition to the rule. It's the main rule that we're building up. And then some more conditions. And anyone that's been building rules will know the trap that's usually experienced the first time, and that is that you need to check that the entity has a field before the field is available. So I'm including here our conditions to check that the entity, which is the commerce order, has the billing field. And then we need to check that that billing profile that's found through the billing field has an address field. And finally, just to check that the address has been set before trying to run this rule, we check that the... the country field is not empty. So to be able to do a not condition, you can see here that the condition has another function in it, which is rules condition. And at the end of that, we can add the negate option to that condition for including it with the rule. The next stage on this slide here... Now, this is where being able to provide a default rule in code really works really well is conditions that depend on other modules being available or not. Now, if you've tried exporting rules before, you'll have noticed that they export in a JSON format, and there's a function called rules import for importing a rule in. And this is one of the ways that you can bring in default rules. But by providing some conditions using PHP within the settings, we can check to see here the common shipping module is enabled. Because if the shipping module is enabled, we're going to then check to see if the entity has a shipping profile and that the shipping profile has an address and that the address is not empty. So if the shipping module was enabled, we're going to add the action here, which is to check that the... I'm going to pass the invoice request action, pass the order, and within the billing and shipping address, we can provide the billing and shipping address. And here we don't provide the from address. I can't remember if that was showing up. I forgot to mention. When we provided the action here, you can see that just here, the actual from address is an optional field and the action doesn't require that from address. But through the development process, we wanted to be able to offer a store that had multiple warehouses, a way of saying where the from address was. So they can extend this default rule that we're providing to be able to say where the from address is. So we don't provide that in the default rule. And then finally there's the action. If the shipping module wasn't enabled, we're going to just provide the billing address in both the shipping and billing address details. One of the important parts to notice is the select bit at the end of the first part here. So this is when we're entering in an entity or a field as opposed to just a piece of data. So if this is anyone using the rules UI, you can use the data selector to find something within the rule. And to be able to provide that, we just need to provide the select information here. So this is the variables that are being passed through the rule. So finally we save that into the configuration array as a rule with the name of the rule. And that's going to be available as a default rule once this module is enabled. So you can provide some locations for finding some more information. There's some really good modules that work well with rules. As I mentioned before, there's a conditional module rules conditional. This adds the else and else if into the action zone. It works to some extent, but it's only available in the actions. And often actually you end up using rules components in there. The rules batch loop, this is a module that I did as well. Rules provides a loop functionality. So if you're dealing with a large number of objects or entities, so you've got an event that collects up a group of entities. This, for example, we've recently been working on the recurring framework for Drupal commerce. And this allows you to process recurring subscription payments. And what it will do on a daily process is collect up all the recurring subscriptions that need to take place. And loop through all of those. But by default rules will just use a for each loop effectively. But this module allows you to push that off to the Drupal batch process. And that's provided by a, you can again extend rules in the actual component types that are available. So this rules batch loop is a new component type. So if you want to extend rules, you can bring in new component types. This may be more than the or, the and condition groups. So there's a lot of extension possibilities there. Rules integrates with context, feeds, web form, the domain module. This is really useful for multi-sites systems. Menu, controlling those. There's cache actions based on rules. So this is clearing caches on a rule event. Services has an integration with rules. There's a Facebook rules module. Transformers and data transformers that allow you to convert those data types. So if you've got a integer that you've brought into rules and you want to convert that to a different data type to a string, there's ways of converting those. This, the HTTP client is quite useful. This, if you're building an integration with some other rest service where you need to post information to that. There's a HTTP client that will really quickly allow you to post that data through to them. And then as I said, views, bulk operations is really useful. If you've got a action set that will take any type of entity, you can drop those in and into your view and provide a bulk operation. So one of those examples in commerce is moving the order states. So you can select 10 orders, pass it to the rules and the rules will process those orders. So some locations for some more information. There's a quite good little book called The Tiny Book of Rules. That's a PDF that's available from Drupal.org. The links for all of these are on the session page. The Drupal.org documentation and the Node 1 have a really great selection of videos and it's quite a long session, I think, something like 10 different chapters in those videos of how to use the rule framework and a really good selection of resources for finding out more about rules and how to use them. So I move on to ask if you've got any questions. And if you do have, there's a microphone just at the front here. So the session's been recorded. And if you want to just come and cue up to the microphone, I think it's there. If you guys could form a line here to speak. Do you have any techniques that you'd suggest for debugging rules when you're building default rules to pass in with your modules? So the rules debugger, so you can, in the advanced settings for rules, you can switch on the rules debugger that will output the status of each condition that's being processed through and tell you whether it's being passed through or false. One of the problems that you often get is when you're bringing your rule that you're trying to import, if it doesn't quite understand it, it will just give up. What you can do is, I often will try building the rule first through the UI that I want to create and you can export that in the JSON format and you're going to be able to sort of, from that format, where you're trying to build the object that you're trying to build through. So that's probably the easiest way just to sort of see where you're going and it can help just to figure out what the exact condition name is, checking that the value is empty is an example of that. So to check, like that example I showed there, to check that a variable has something in it, you have to say data is not empty, double negative, but that's finding that information out shows you and the hardest bit is that adding the negate on the end is often the bit that gets lost. Perhaps it's perfectly obvious that it may not be in context of this talk, it's good to point out that you can programmatically trigger rules and actions. Yes, so any, you can invoke a rule from your module. So this is something that happens in commerce as well for invoking rules, particularly to do tax calculation. So you can invoke a rule without having to have an event. So as your module processes something this may be on entity save, you can just automatically always invoke a rule that you've got configured. And so once that's invoked, it will just trigger that off and pass through. I worry a lot about performance. One of the things you said earlier is that rule system is heavy. Can you qualify that and tell me what that means? So yes, there's the problem of having the rule system that you're adding in quite a big chunk of modules and system to your site. One of the things that certainly within commerce that we've reviewed it as, once you've got rules in and it's available there to reuse, then you've got a huge advantage. One of the examples on the blog post that I mentioned from Wonder Crown is comparing using rules for configuring and controlling the menu, metatags on a page, the page title, the blocks that are available on a page. And this all replaces a number of modules such as the page title, menu conditions, contexts, and being able to provide all of that just through one action framework, then you can cut out a lot of other modules. And so that's something that... It's weighing up those balances actions of deciding you can either go all the way in and use rules quite heavily for all sorts of things that are happening on the site build that you're working on. And if you're doing that, then you're getting the benefit of it without having all the other small modules that have events and actions that are competing and all happening at the same time. And one of the sites that I've previously worked on where you can end up with groups, multiple developers working on different stages, and you've got multiple things that are happening on, say, node save. So you've got several modules all hooking in saying at node save, I just want to check something and do something. And another one that says I want to check something and do something else somewhere else. And suddenly you're finding you'll get a performance hit because you've got all these modules all trying to do things at the same time and trying to debug and find which is the thing that's slowing it down. It becomes a trouble of trying to find all of those things, whereas if you're using rules and you've got the event node save, you can just look and see all those rules and switch them on and off and quite quickly find a thing that's actually causing that performance hit rather than having to go through all of these modules and trying to find the hooks that are being pulled in and at which stage it's happening. So that gives some ideas of ways of improving performance with rules. Yep. One thing that I haven't had the opportunity to use much and I know it's used a lot in the commerce framework are components. And I was wondering if you could talk a bit about how to create and manipulate in code components to handle complicated pieces of logic that you might not think a customer could readily configure in the UI. Yeah, I mean I can talk about that in detail with the experience of the European VAT module which uses components in quite detail. So it actually generates the rules using the information that's available about the tax rates and countries to create a set of components that are conditions to check which country an order is in and using the so you have a range of components so there's 27 countries in the EU that are all part of the VAT system and you need to check that the order is within one of those countries and some of these have small components some of them are simple just to check that the order is in a particular country but some are slightly more complicated because for example Germany there are two post codes that are not included within VAT so you start to get some more complicated things and these are provided within the rules components and then you can just provide all of those components into the main rule is it in the EU where we've been able to use that in a slightly more complex way is for business to business transactions between different countries there's a mechanism for what's called reverse charging taxes so there is no tax on the transaction and this is only where the order is in a different country to the country of the store so in this case I use the default rules altar to be able to add in a secondary module so if the store needs to enable this business functionality for business to business transactions it picks up a default rule altar that finds the relevance country rule that's a component and amends that to say not in the home country of the store and that works really well and if anyone wants some more information I can probably show that to all we can might be arranging a buff with some more information about looking at rules and components in more detail and how those can be created but those components work really well to say you can add them to a rule quite easily so just adding a component in the conditions or the actions is just simply just a case of saying I want to add this component into the rule and you've added it into the rule and as I also said about that example with the shipping calculation you can have nested components as much as you want so you've got your first reaction rule with a condition that is a component that may have components within it as well so you can nest them down by doing that you gain that being able to reuse those components as well so you may have a simple condition that is does the user have this role and you know you're going to reuse that component in multiple rules so just create that component once and then reuse the whole component rather than having to create the does the user have this role every time you want to reuse it and then if you need to change that rule you only have to change the component once not go through all of your rules and change them so this is a big advantage to using that system Can you tell us what big changes we can expect in Drupal 8? Unfortunately I can't I haven't been doing any of the work involved in any work on Drupal 8 yet so I haven't unfortunately tell you anything about that as far as I know the actual I think the main stuff in the rules process and how it works will continue but I suspect there will be in the new entity plugin configuration system so the way that they're imported and exported I'm sure will be much clearer and easy to follow Maybe Do you think rules should go into the core? I think probably moving on next it would follow through if the views has made it in now is something as I said if you start to look around modules there's so many modules that implemented their own sort of way of implementing some events and conditions so having one unified framework to be able to do that seems to be the way and that's the same views as a much longer history of doing that but it was a unified way of creating the access to the data in the database tables so I should think it will follow the same sort of flow through Another question? Yeah I find the rules UI a bit confusing particularly for users that aren't familiar with it for instance the commerce payment method system if it was a site builder he would have to understand he has to enable the rule then edit the action to configure his settings is there a way that you could pull out those configurations maybe in another custom module with like variables or something so they don't actually have to go through the UI if that makes sense? So there are some payment modules that are already looking at doing that and one of those that already has done is a UK one called SagePay that has a separate configuration page now there are some pros and cons doing that because one of the main examples that we've got at the training yesterday was talking about their payment gateway they actually have two configurations one for their recurring payments and one for their non-recurring payments two different account numbers so they need to be able to have two rules and two different settings for their payment gateway whereas if you've got one configuration page you can't do that so it's sort of deciding how you balance that so there's either an option of providing a default set of configuration or what is configurable between the different implementations so one of those examples that I've been working on with the American Express is when do you you might want to have 3D secure that's when they get the second set of questions when you're making a payment and you only need to have 3D secure checks if they're paying over $2,000 and if it's under that you're not bothered about the 3D secure checks so it's sort of questions when providing those options and that's why it's gone that way but as you say some of the lower end small merchants don't want that flexibility and just want to click and go so there's a balance between the two certainly the rules UI as I said about having to go entity has field and there's a lot of clicking in the UI for rules so on your additional modules page you had rules conditional which I apologize I know is trying to be folded back into rules itself and I was wondering if you could talk about how far along progress for that is and I guess for those who don't know what the module itself does so I'm not sure about the progress with bringing it into the core of rules but in the action set area in the action of a rule or a reaction rule you can add some effectively conditions within the actions so that will say if this condition is met within the actions then set the actions that you want to take place based on that condition but they are quite simple conditions in terms of the data comparisons that really want to fit in there and it is only one condition that you can use in your if statement for in the action so if you have some really complicated conditions that you need to use then it's using the multiple components becomes often the best way again I can't remember since I've last looked at the rules condition module I'm not sure if the you can use a condition component as the condition within the if statement if not then that's probably whether that's I think there might be that in the issue cube I don't know how far along that's got are there any more questions okay thank you David we'll be having a short coffee break and we'll be back at 10-15 thank you so just before you rush off I remind you you can come and see the commerce village you can find out about our new platform for hosting solution that's there and all of our partners that we're integrating with and finally as well just to ask you to go along and do the evaluation on the session schedule