 Veliko. Znamenjamo, kako zelo in izgleda distribucije v Drupal 7. Imam Andrea Pescepti, in Antonio de Marco izgleda. Vsi je z Núvole. 100% Drupal company, basite v Belgu, v Brascii, in v Italiji, v Parma. Núvole, zelo, zelo v Klausi, v Italiji. If you are just curious about our name. Our clients are in Europe and in the US. And we work with a distributed team. We don't maintain a distribution ourselves, but we work a lot with existing Drupal distributions. And actually as you will see later, we build every project as if it were a distribution. Our work is mostly with international organizations, especially in Brussels. This one, for example, is a screenshot of a customized open atrium installation that we built for a European project. As you can see, we built mapping integration there. And they are using it for a network of experts of international education and for storing rich user profiles and interacting in private groups. This is another project we just started for another international organization. This time it is a cooperation between Europe and Latin America. In the education sector. And they are sharing techniques through a customized open atrium platform. So to come to the presentation, we are first introducing what a Drupal distribution is. It is not immediately clear. For us, a Drupal distribution is what you see here. A prepackaged Drupal installation that is meant to address a specific use case. This does not include all cases of distributions, and we are getting to it in a couple of minutes. Popular distributions in this sense are open atrium that is currently maintained by phase two. It is well-known. It is a platform for collaboration, collaboration tool for groups. And it is also very suitable for customization and advanced customization. And this is what we mostly do. It is still on Drupal 6, as most distributions in these examples. Managing news is an aggregator of news and feeds from different sources and with all different standards. Again, maintained by phase two currently. Then Cod is a very popular distribution, is a conference organizing distribution. Everything you need to organize a conference based on Drupal. Videola is a platform for a video solution and streaming. Open publish is again another well-known distribution meant to manage a news site with everything ready for publication of news. And open public is currently the only one in this set of examples that has a stable release for Drupal 7. And it is meant for a governmental organization. So again, you see that all of these are Drupal, but in each case Drupal has been heavily customized and preconfigured to turn it into a product. Not something to work on, but a prepackaged product with a set of standard characteristics that are, for example, that a product must be preconfigured, completely preconfigured. I mean, it must come as an out-of-the-box solution for us. So this is our idea of distributions. Something that is heavily preconfigured at the point that you just need to install it and it will be preconfigured out of the box. It is repeatable. You can install it as many times as you wish. Completely packaged and repeatable exactly on multiple instances. And then, of course, if you have a product, then there is a product lifecycle. So you have to maintain this product because people will be installing it and needing future upgrades or new features. And you will need to design an upgrade path. People will be installing OpenATrium 1.0 and at a certain point, you will need to provide them with OpenATrium 1.1 or something that they can upgrade to. And this is a burden for the developer in the idea of packaging a full product. Now, some of these features apply to installation profiles, too. In the sense we will use in this presentation, we are distinguishing installation profiles and distributions. For us, an installation profile is something that is repeatable, of course. You shape a dropel with a set of models with a minimal reconfiguration. But how much configuration you put there is really the difference for us because one could well say that from a syntactical point of view, this is the standard dropel installation, this is a distribution. Just a distribution with nothing more than dropel core. But syntactically, here you have everything that is needed to call it a distribution. Of course, what forbids to call it a distribution in our interpretation is that you are left alone. Just when you have installed dropel, you don't have something that is working out of the box. It's something you are supposed to work on. So syntactically, there is no difference between an installation profile, even the default installation profile, and the distribution. But here is the key difference. When you are shipping a distribution profile, your focus is developers, people who will be able to work on this profile. You just provide them tools. And then it's up to them to build stuff with it. And it's a platform they can build upon. While the distribution is ready to use. Someone with, say, very little dropel knowledge or just with site building, standard site building knowledge will find something that is working out of the box, and he can start immediately and then maybe customize it, but focus is on final user. All of this, of course, is perfectly standard dropel. It is a dropel core, a set of modules, themes, in general, what we call code, and configuration. And again, what we are focusing on to call it a distribution is this last part, configuration. Configuration is hard to store. It's not natural to store in dropel, because the point of your dropel is that traditionally configuration is stored in database. But here is the main obstacle, where when you are trying to ship something that contains configuration, you cannot ship a configuration as a database dump, not conveniently. If you need a huge list of drawbacks, you can find them here. We can review them quickly, but it should be rather obvious. First, you have severe limits on repeatability. Our product is meant to be repeatable. We want to be able to install it anywhere where dropel supports it, and if we are shipping with a dump, we are hard coding a choice of database engine, possibly. We are hard coding table prefixes, and our user that wants a different table prefix just work around it, or we can find weird ways to adapt our database. And if we ship with a database dump, we don't start clean. We start from a dirty state, from something that is something we have been working on, and at a certain point we dumped for everybody to get an exact copy of what we have. And then, of course, especially since we are talking about products here, it will be extremely difficult to upgrade. If the newer version of our distributions carries a database dump, we are going to destroy everything the user created in between to completely break the upgrade path for our users, because in database now they will have a mix of configuration and content. Also for developers it is very hard to maintain because, especially for us, we work in a distributed team, so we need a workflow that does not assume that people are just close to each other. They can work freely, and they cannot lock a database and tell each other, please do not touch anything while I'm working on this feature. Of course, a database is a problem in this case, and it is very easy to lose control, ultimately. So, the idea is that the distribution must and we will see how store all configuration in code. We have to. There is no way we can ship with the database dump and still call it a product in a proper way. Storing configuration in code has benefits that, of course, correspond to the drawbacks we've seen before for database dumps. And, moreover, we have everything that is generated by PHP code that is database agnostic, so we are not making any assumptions on what users are doing. We have a clean installation procedure and we can define a clear upgrade path, so we will be able to guide our users to an upgrade of our distribution without interfering with their existing content. And also for developers, this is much easier to maintain because when everything is in PHP code, it's much easier to inspect for developers, so I can see very quickly what a colleague is working on or what he changed, when he changed it, and if there is a conflict, we can solve it by simple comparison, standard source file way. And content and settings this way are completely separated. So after this introduction to distribution set products, as products we can go on and look at how to build the distribution. Okay, so let's start to build the distribution. Distribution, as Andrea said, is a product, so you must think about the name for it, give it maybe a logo and then start to package content together. So let's meet our distribution, Drupalissimo. So there is, it's just not actual distribution, it's just distribution, we are going to use it for our examples during our presentation. So I would strap the project then. I need two things. I need to get my code from different locations, put it together to make the base for our distribution and then I need an installation profile to manage my installation process. So the first one, we're going to do using a make file. Make file, so the distribution buildings blocks are the core, of course. Then you have different modules. You can have contributed modules, custom modules that you would write for your distribution or even patched modules. So when you apply some patches to fix some problems, then teams, several teams, somebody depending on somebody else and then external libraries. All these building blocks comes from different locations. They may come from drupal.org, from GitHub, for example, or from other sources like the external library, like OpenLayers or jQuery. So we need a convenient way to then fetch all these codes automatically coming from different locations. And this is where Drashmake comes into play. So the best way to package code is to use Drashmake. What is Drashmake? It's a Drash extension that allows you to describe the code you are going to use for your project using just a simple dot info syntax. So a syntax we are all familiar with as dupal developers. And it allows you to do it just with one line, command line of Drash. So single info file to describe the modules, the dependencies, and then also the patches that you would apply to the modules you download. It can download it, it can build for you all the distribution just with one line command. And then is also a really nice way to keep an index of your project. So to see which modules are you using, especially useful for the distributed team, for example. So, let's have a close up. For a distribution we usually need to make file. The distro make file, which will pack the core and the profile, and then the drupalissimo make file, which is the make file of our distribution specifically. So the distro make package then decor and the profile. So let's see how it looks like. So the distro file syntax you have some directives, for example, specify the core that you are working on, the drupal core. Then you say, OK, download for me drupal project, the core of it is, and then the version is 7.7. As you can see, then you can also apply patches to drupal core. This is actually a real life example taken from buildkit, and these patches are to make some elements, some components in names or input filters, et cetera. So then you can download the drupal core and apply some patches to it directly. And this is the command line that does it. So you have like dash make, distro.make, and then the directory where the distribution will be stored. As you can see, the result of this command is the drupal project is downloaded and then patches are applied as a report in patches.txt to keep track of the patch that you applied to your distribution. So where is my installation profile now? Because so far we just patched the drupal core. So there it is. You have to also specify of course the location of your installation profile. The installation profile is another element that the make file would download. So here is the declaration into the make file. So there it is. In the first bracket you have the name of the installation profile which is drupalisim in our case. The type is a profile. So drupal will know that it will store the code downloaded by this directive inside the profile directory. Then you have also the different type of the load. So let's see what we get when we get this installation profile. The installation profile will have a distro make, so it's on file. And then also another make file, drupalisim.make, which is the make file of the distribution. One interesting feature of Drushmake is that it act recursively. So when it downloads a package, when it finds another make file it will also execute that one. So in this way you just need to make distro make and name of the directory. And then it will also download all the components specified into the drupalisim.make file which is then your distribution file. So let's have a close up of the distribution of the make file. So it looks like again an info file. So you have the models of your distribution with the version you would like to download. So it comes, libraries, patches to models. And then also of course the features of your distribution, so the main components that you may download from git repositories, for example. In this case, in this example we have only two features. So the drupalisimo core, which is the core features of our project which stores all the project-wide configuration let's say, and then the drupalisimo blog which is a blog feature that we would like to enable in our project. So there is a project in drupal.org called buildkit. Buildkit is a startup distribution which basically package all the modules and themes and configuration that you may need when you start a new project. But it also gives you the possibility to reuse its make file in your distribution as a starting point. This is possible because that's a buildkit page. This is possible because crash make actually allows you to include other make file inside your distribution. This can keep your make files really clean. For example, your distro make now would look like this. You just include the buildkit distro make which has the core download and the patches to the core that we saw before. And then basically just add your profile your drupalisimo profile where to get it, and that's your distro make file. Same thing goes for the drupalisimo.make so for your distribution make file. You can include the distribution make of buildkit, and then you can just extend it with the features or even other modules, other patches etc. So this helps also to keep to also start up a distribution really easily without copy pasting from other make files and possibly making mistakes etc. So the second part now, the installation profile because so far we just patched the content we just got the code base for our project. We need to install now our drupal distribution. So we need an installation profile. Installation profiles are made of three files, one info file which lists the dependency of your distribution which means that the profile will enable all these dependencies for you. Then an install file that behaves exactly like the install of your modules. So it performs installation tasks and also upgrades. This is also a very important point for drupal 7 distributions. And then there is also a dot profile file that is fully customizable makes your installation profile form fully customizable exposing some APIs. So let's have a look to drupalisimo.info. Info file, really the same as any modules. So you can specify your core dependencies your contrib dependencies and then your features as well. This means that after you have run the drashmake so that loading all this code then you are now ready to install this code using your installation profile. Thanks to the info file drupal will enable all these dependencies so you will have all your modules enabled. Now let's have a look out to customize the installation profile procedure for the final user to really go smoothly through it. You may want to add some new steps or to prefill some forms or to add some interaction forms for the users for your specific use case. So for doing these installation profiles expose you APIs. Like for example normal form alter so you can really behave like you are in a module even though you are in a profile. So you can alter for example the install configuration form. In this example we just prefill some form input fields to help the user to go quicker through the installation process. And this is the result. Basically you have the site name prefill drupalissimo then you have site email addresses etc. User name admin so you can speed up the process. Then what you can do also is to add installation tasks to the installation profile for the small ticks you saw on the sidebar. Here we have two tasks create taxonomy terms which will obviously create taxonomy terms for our distribution and then also the configuration task that will configure our site features. These tasks end up there on the sidebar so the user will go also through these steps. In these steps you can also put forms for user interaction to ask user some information about specific features of your distribution. For example the create term creation task performs simple term creation so it just fetch a vocabulary and then creates like the default terms that you may need into your distribution. This is also specifically useful when you need to make assumption about a term that is already present in your distribution in order to configure it for example to use it as a context reaction or something like that. So this is the way to do it so when the installation profile will come through this step then it will create your starting taxonomy term. In the same you go for the site features configuration. Here you want to add for example a user role like editor. You make some operation in your features you revert some components like variables for user permission and you enable also the custom team. You want to ship already with the team not with garland probably. So you have your Drupalissimo team inside your distribution so you want also to enable the team and that's the place to do. So as an installation task you may enable also any of the team. So far we've seen how to get basically to even if you have seen features popping around in popping out times but we haven't introduced it completely and this section is actually about again having a full configure product so how to ship with full configuration using this very nice tool that is a model called features and is the best way to configure. So if we want to have content types and views in context with ship with our distribution we will generate features that package this information. A feature itself can be defined as a collection of elements that satisfy a certain use case. And actually features produces models that the output of feature is producing a model that will store configuration for your website. So you can see it as a way to export configuration into PHP code. So this is the missing link from earlier talks that links how to have configuration in database and how to have it in PHP code. Configuration in database is organized in a very inconvenient way for one who would like to package it in a logical way by features because in database you have all views together using the same tables more or less context are together image styles are together and this is exactly the opposite of what we would like to obtain. What we would like to obtain is our distribution will have a feature called news that will contain everything necessary for this modular functionality. It will contain the definition of content type text that are related to news views that are related to news and image styles that are related to news. So we just need to put things together in another way. Creating a feature is rather simple. There is a graphical user interface in the model that you can use for a start. You just define basic fields and you can see there is the right hand side there is an edit component select where you just select what components you would like to put in a feature. So if you are building a feature for news, everything related to news will go there. There is also a nice auto detection mechanism for dependencies that will try to guess and install it and then you just get the button to download your feature. At the end you will get something like this. So a set of PHP files that store information about a certain piece of functionality for your site. It has an info file because features are modules. Let's have a look at this info file. Again, you see the dependencies that are modules that need to be enabled when enabling the feature or need to be enabled just before enabling it. And then a set of exportable things that are put in code. You can see here permission, variables and so on. This is not their values, just what we are putting in code. So the next question is once we know how to create a feature how to fetch configuration from database and put it in PHP code what's the most logical way to package it? The most logical way is not the trivial one that is I will just try to find everything in my website or content types, views and context and put it in one feature. I will just create a big feature that I will call all with everything in it. This is not working. This is not working because the idea behind features is to be as modular as possible. So while it may work, it is not the way to do it. So we want to divide the site functionality into independent pieces, just think about it and then we will put the several features together to build a site. There is another option that is building transversal features but we do not support it. The idea is that one could imagine having a feature that is called site permissions and dump all site permissions there. See. This is not right because it is not modular. Of course it is a transversal feature where you have all site permission across all content types for instance and it's better to bundle permissions with the functionality they belong to. So if I have feature news the permission related to the news content type who can edit news, who can create new news items should be packaged with that feature and not in a transversal feature. And if you have Michelin's permissions like access content in general you can have a site specific features for this very generic permissions that do not belong to any modular piece of functionality. So here is an example of an info file for our Drupalissimo blog feature and as you can see everything related to blogs is there. So here you find all fields all images that image styles that we are going to use in a blog all permissions that are related to blog posts and everything that is part of this functionality. You enable it and it's there you disable it and everything disappears. So it's completely modular. It helps a lot when building features to use naming conventions. This will allow you to use features very effectively. You might have noticed it before but we are seeing it in a minute again there's a kit the specification called kit that will guide you in choosing proper names for all elements you are exporting into features. The idea is to build compatible features and interoperable features. You need a lot of conventions in this word and conventions are very good when you are programming this style you will still have a lot of flexibility but if you adhere to certain naming conventions your life will be much easier. For instance you have a code namespace. In this feature I will generate a unique identifier for that feature. I'm creating a blog feature for Drupalissimo I will call it Drupalissimo blog meaning that the module file will have this name and then internally I can shorten it to just blog just functionality of my website so not this particular Drupalissimo blog but the blog functionality of my website. I'm supposed to use one blog functionality in my website and for example the listing view for my blog posts would be called blog listing again use this name as a prefix for everything belonging to it so it will make things much easier to find. If you are using recent blog posts as a name of a view you are getting lost very soon it's much easier to prefix everything with the code namespace of what we are using just use it as a namespace So far we've seen how to create a feature and design it in abstract but we are missing a point that is how to develop a feature once we have created it while developing we will be changing it and the feature has a nice standard mechanism for it supports two operations that are very handy during development that is update it will export the current configuration into PHP code so everything you put in a feature will be regenerated when you update that feature you get newer PHP code corresponding to the current configuration and the revert operation is more or less the opposite and it will enforce the configuration that is stored in your PHP code so whatever you have done after the PHP code and the database were synchronized it will be in a way overridden by this revert will be reverted actually go back to the status that was stored in PHP code and every component of a feature like a view, a context can live in the database in code or both so your blog listing view in code somewhere will or will not depending on technical differences in database or will be in both and will be possibly different in both so features needs to keep track of everything and it uses this concept of component state component state is default if the object is not in database or database entry is matching perfectly the state of component in code so what your real configuration is what is stored in code, this is the stable situation not changed anything if I have something different in database than in code the state is overridden to be more precise, this means that the database object was changed and the code is unchanged from the latest check that features did so features know that something has changed and it knows that what has changed is the database so I have overridden what I have in PHP code here it would be natural to update the feature to enforce the current configuration say I edited the view and I wanted the modified view to go in my feature then I will update it and the new code will match my current configuration or I will revert it and go back there is a third state in its review that means that feature detected that I changed both the database and the code and this means I have to manually review it because both states are different from the latest state it has seen and it does not know who must win between changes I made in database and changes I made in code if someone wonders how can features keep track of it it's with MD5 hashes current code for the component the most recent prior code state differing from the current code state so the last thing I saw that is different from what I have now and this will detect an SVN update or any operation that changed code and then the normal component state that is just what's in database or what's effective in this moment to be more precise with these MD5 hashes features can know what changed and can propose me to to work properly not to lose what I did another distinction we need to make is between hard and soft configuration there is some stuff that we have to go into feature some configuration that we will not put into features for example viewer context is part of the hard configuration meaning if the site administrator changes it he will consciously be overriding my feature his configuration will be different from the product I shipped and then he knows that he might be at risk in upgrades because I will assume that we are starting from my unmodified features on the other hand there is a soft configuration stuff that is meant to be overridden say the default team I can have a product and ship 3 teams with it then it's up to the site administrator to choose one and the upgrade process should not be broken by this and the trick is not to store these in features but to store it in the installation profile so that altering it will not change the feature state and when the site administrator checks his features they will not be overridden because we are allowing this to be overridden it's a so called soft configuration this is upgrade safe look here you have already seen this slide part of this slide we are doing it as part of the installation profile now this explains why we embedded some configuration in the installation profile to be overridden and then there is something that goes beyond configuration like taxonomy terms and other stuff that we still want to distribute in our product and again you can do it in the installation profile I have already seen this so basically these two slides explain what you have seen before in the installation profile using for carrying some configuration we do it this way because it's a configuration that applies in a different way than the configuration we store in features an interesting thing is that the feature can have its own make file too in the set of files defining the features there can be a make file can make the feature truly modular by specifying everything that is needed to build these features so all modules that are needed to build these features libraries and I can really package functionality here not only in terms of configuration but also in terms of dependencies and these dependencies should be chosen in a way that allows to export everything not all country modules are ready for this even though it's getting better and better and you should prefer modules that can export their configuration in code otherwise it is possible with tricks or standard tools like strong arm or C tools to make a module configuration exportable so you are not completely limited and you can do something to export configuration and we've seen I think all the process of getting to build a distribution and how to package everything in a distribution from make file to country modules configuration and possibly some initial content so far exactly we saw how to package and to build a distribution let's see how to arrive to our first 1.0 release so how to develop and maintain distribution so the main problem in that is upgrading process a distribution must be upgradable means that if a user downloads 1.0 then a new release is out there like 1.1 then from 1.0 to 1.1 there must be a clear upgrade path so of course we cannot do it with migrating content because it is wrong so it exposes hooks to do that which are the updates hooks and for example you can upgrade your features so since features are modules then you can use the update N where N is the number of schema of the feature and you can place it in the install file of the feature is to manage the features update process changes with your development team as we will see in a second same goes for the profiles profiles drives the installation profile drives the life of your distribution so everything that is a structure update of the whole platform must go into the hookup date of the install file of the installation profile this is exactly again to manage distribution update process as well as to enable new features in order to structure update or to share changes with your development team so now we go to the core of the way we develop with features which is also really bound to the way distributions work which is the code driven development workflow your mantra must be keep everything in code so everything must be in code you never have to assume the state of the database or of the platform itself so they have really to work independently for each other so the first thing they both run the installation process so the installation process is to make sure that you have two developers working on two policy distributions developer A and developer B they are not necessarily on the same place so they have really bad way to communicate and I think they both run the installation process so they install the platform from scratch so they start from the same state of the distribution then the developer A enables the block features and enables it while the developer B does something else so since profiles behave like modules means that they can run up they tooks so the developer A can actually share the change of enabling the new feature platform with the developer B just writing an upgrade path using the hook update N this means that the developer B will then download developer A will commit the block feature of course and the upgrade path it just work on and then the developer B will download the latest code base it will run an update a Drupal update and then the state of this database will then now include also the block features that was enabled by developer A this is a way to share changes without sharing actually the database so the two database states they can run in parallel there is no content overlapping or problem of synchronization etc developer A can have his own content, test content developer B can have his own test content too and they just share the meaningful contents writing upgrade path for them so for example now the developer B made a mistake he was working on editor role and then he wants to remove it so what he does he removes the editor role in the upgrade path sharing this change with developer A this is why because you can never assume the state of the other developers database so maybe the developer A downloaded the database dump where the editor role was there or the editor role was put in place since the installation profile as we see so now we decided to not have an editor role anymore in our distribution so that's the way how to share this change so always work with Drupal APIs never rely on database dumps so now the developer B commits this removing editor role change and then the developer B just continues to work he wants to patch a module for example, the admin module is because he found the back so he downloads a patch from the Drupal it just goes ahead and they patch the module then he continues to work then he wants to add an open ID account for the administrator to be able to log in with his open ID so the way to do it it's again writing an upgrade path in order to share this change so he writes the upgrade path 703 and then just using the Drupal 7 APIs in this case the APIs of open ID modules then he enables the open ID account for the user1, which is the admin user another thing, he just patched the module patched the admin module this is a very important thing because now the code of the admin module is not anymore in line with the main master branch of the Drupal development so we must keep track of this change of this patching also in order for the other developers to know that that module was actually patched so if they need to upgrade that module to a newer version, they need to mind that patch so the rule that both developer agree on was to always check the drashmake file when we want to upgrade modules for example or simply the logs of their SVN update or whatever version control system they use to see that the file changed so we need to record this patch in our make file this is also, it's two folds so you can, it's useful to share this information with your development team, but it's also useful when a third developer will join, then the make file will patch that module according to that patch so the code base will be consistent with the code base of the other two developers so now the developer be commits his changes as you can see the marker of this upgrade is a bit different from the other one why, because it's a bit more important upgrade, it's not a development upgrade it's a structure upgrade something that must be part of the installation profile as well, something that you must ship with for example now when the developer joins, then he gets the admin module patched because it's in the make file and also gets all the modules and upgrades patch that were made available of course the update N is not enough because exactly when the developer see will install is a copy of the distribution, all the upgrade N hooks will not be run by Drupal, because Drupal at the fresh install moment, Drupal assumes that all the upgrade path or the upgrade update N hooks are old hooks are not something that must be applied, so you need to store the meaningful changes that you want to store in your distribution you need to place them into the install hook, and this is what we call the structure upgrade so structure updates are the one who goes, who are part then of the installation profile, so 0102 were just development updates between developer A and developer B while 03 becomes important structure updates which goes into the installation profile now the developer see when the developer see will run an installation from scratch it will also get the open ID associated with the admin account so the state of developer C is exactly the same as the state of developer A developer B to start from from scratch, so it can install the project and then start to develop so you can really do a lot of stuff with the upgrade process in your distribution for example, let's have a look to one of the most popular distribution of that which is open atrium what they actually did in the upgrade path they were altering comments tables altering to switch the needs of the distribution or even the node table adding a key node type for optimizing search and this kind of stuff or they have also installed new features so when they enabled the first time the atrium groups or atrium members features they were sharing this change in this way these are all not scratch updates while for example the 6003 it's a scratch update something that must be replicated also at installation process because you want always the system table to be updated or in this way so now we also prepared actually a quick reference sheets which can be downloaded downloaded from our blog or also can be handed out, we have 15 here so the first comes after presentation we get a free copy of it you have like the most it's a quick reference for the most useful drash comments that you may run when you work in a called the development workflow or also naming convention tips how you would work with the standing and overriding your features etc and also how to work with controller features and other tips that we find useful during our workflow and we want to share with all of you if you are not able to get one here you can always download it from our blog you can go to visit our blog or you can check also our trains in we have a training about open atrium customization and the code development workflow so thank you very much if you want to take the service and then thank you guys so if you have any questions we have a microphone here so if you wish to come down or speak up we can so the question is if I can put own custom code in the module file of a feature if I do that what happens if it is our practice to do it or not yeah we always do consider features as modules so we really develop a feature in not in the sense of only storing the configuration but also developing new functionality inside the features so yeah okay so briefly the question is using a code driven development is harder it needs that you look at the Drupal API you study functions so where and at least it is as deeper learning curve and the question is if that is effective or not I'd say yes in the long term it is going to be absolutely effective and it may happen that in some installed projects you employ a mix of code driven development and in existing database to make things quicker when you have a stable structure and you export it into code the fundamental function you can carry a development database with you as long as it is controlled and we do it in a few projects so in the end this is a solution that is quite effective and fast so thank you for the other questions you can ask us privately because it's lunchtime now and just come here and come here for the code driven cheat sheets too