 Okay, so this is a packed room. It's good to see. So, good morning and welcome to today's session, when to build your own custom field types in Drupal 9. My name is Thiago Cimois, I work for the European University Foundation. And side note, this is my first presentation at my first Drupal con, I'm very happy to see a full room and also a little bit intimidated. Thank you. So, a little bit about me, so my name is Thiago Cimois, I'm Portuguese. I have one of those odd careers that you may find in this community. So I have a background in physics, a passion for bicycles and bicycle repair, and now job in programming. Essentially I'm a problem solver. I've been doing web development since 2011 and shortly after I discovered Drupal and so I've been building Drupal sites ever since. And over the last couple of years I've started developing Drupal modules, which has been a very nice experience. So my work at the European University Foundation, I'm a back-end developer, I build a lot of sites with Drupal, we develop Drupal models, mostly for the purposes of our own sites and applications, and we even maintain our own Drupal installation profile. European University Foundation is a network of 70 universities across 30 countries in Europe. The main focus of the foundation is digital higher education, as well as entrepreneurship and employability, policy innovation, active citizenship, and quality mobility for all. Over the years, the UF has been involved in many, many projects. The foremost of which, in my opinion, are the Erasmus Without Paper initiative, the Erasmus Plus app, the online learning agreement platform, and the My Academic IDE project. If you have questions about those, I'll be happy to answer after the session. So let me ask you, how many in the room have built sites with Drupal? Can I get a show of hands, please? Make sense? And how many of you would consider yourselves to be site builders, primarily? And how many of you fashion yourself developers? Yep, that's more or less on the money. So we'll start by outlining what was essentially my process, because I started as a site builder and I moved out to churning out a lot of custom code. So in the beginning, this is all I wanted to do. I wanted to use the features of Drupal Core, contributed modules, but I didn't want to maintain my own code. And sure enough, in order to follow that path, it's very nice to know your Drupal Core features because after all we're talking about a fully-featured CMS, built primarily around content entities, which are fieldable, and those fields are used to store the actual data, and they can also be leveraged to build additional functionality, which is great. And we also have a vast ecosystem of contributed modules, many of which ship with new field types, and some of them even extend existing field types, either from Core or from Contrib. This little screen grab was taken yesterday, and that's a very large number of modules that you can explore if you're into this kind of thing. But then there is the other side of the coin, when Core and Contrib are just not enough for our purposes. And so we have to understand the limitations. We have to know which use cases Drupal Core covers, we have to understand that certain contributed modules are designed for specific needs, not always actively maintained, not always with security coverage, and indeed at the end of the day, our own particular requirements may be considered an edge case. So we also have to understand our own limitations and our own projects. So we might want to combine some modules, but they might not work together. We might get to 90% of our needs, but no further. Some modules by design require you to write additional custom code, such as plugin implementations and the sort. And if you use too many modules, you might hurt performance and you might have a negative impact on usability as well. So with this in mind, I would like to explore some common patterns in site building. And you may see some familiar things here. I'll start very abstract and talk about structured categories. So this is when you have one or more content types that must be associated with some sort of category. These are predefined, don't change very often, but they might. They might have a description that an editor must be able to change over time. There might be a hierarchical structure, let's call it at least two levels. The assignment of such category must be possible at top or deepest level, or you might want to force your users to choose your deepest level, and you might build functionality around it, like if you, that is scope to one of those specific categories or more. And this is what I'm talking about was structured categories. I hope I'm not giving a lot of CSS headaches right now. So if you want to do something like this, you might obviously look into Drupal Core first, if you have a list text field, you can have your predefined categories, but you have nothing else essentially, so this would not be an acceptable solution. If you go with taxonomy term references, you can have your predefined vocabularies, you can let editors manage that particular vocabulary, you have your description, you can even have more fields. You have the hierarchical structure built in, but you can still select any level that you have, so you can't force the selection of deepest level, and you should not be using content as configuration, because it makes it very hard to reproduce your site or application across different environments. So this is close, but not quite there. If we start adding contributed modules to the mix, you might find something interesting like config terms, which is essentially a clone of taxonomy, so config based, as you can see, instead of numeric IDs, you will find machine names. We still have the problem of level selection, but in general, this is an acceptable solution for many use cases. Just not quite the one we're talking about here. And of course, if you can combine more things, so you stick to your taxonomy terms, you add your simple hierarchical selects and use default content, then you can force selection of deepest level, you can ship your content as configuration, even though you still need a custom module to ship it, but in general, this would cover the thing. So for this pattern, we can find solutions. If we take yet another pattern, where we have a multi-value field that has multiple properties, you have a certain type of data, two or more properties. Normally, each one of those individually, you could find a field for it. The content type, of course, must allow multiple instances of this. That's your multi-value field. And this is an integral part of your content type, and you also have something like if you're relying on one or more of these properties. And of course, if you're thinking multi-property, latitude and longitude will be an excellent example. Of course, you don't have to build it. Someone else already did, and it's been around for a while, it's called Geofield. Then there used to be field collection back in the Drupal seven days, which was then superseded by paragraphs. I would ask another show of hands. Who knows what paragraphs are? That simplifies matters, thank you very much. So we're talking conceptually about a sub-entity, which is in each part of our content item, and it's fieldable as well, so you can have any sort of combinations, have vast ecosystem, easy to set up. But it's still an entity reference, so if you're using JSON API responses, you're going to have relationships inside of attributes. If your use case is simple, this might feel like overkill, and it can have an impact on performance. On that topic, I won't make the point, but I would invite everyone to see this presentation from Drupal Gov four years ago, where the presenter goes and explores some issues that they found in large Drupal projects that had very significant performance issues due to their structures being too reliant on entity references. There's also things like double field, so if your need is just two fields, you're usually okay, but doesn't really support entity references. And of course, as the project page has stated for many, many years, no triple field, no quadruple field, just go ahead and generate a field with rush. So with those patterns in mind, which I imagine are familiar to you, we're gonna explore a little example use case with this wonderful acronym here, and this is referencing the common European framework of reference for languages. So what is this? So this is essentially a way to organize the level of proficiency of a given person in a particular language. It is organized by level groups, has individual levels, and has descriptions. So if you want to know more, there's the Wikipedia, you can find it. This is a use case that is very common in the sites that we build. And so if we were to take this and convert it to concrete requirements, if I want to model the CFRIL, sorry. Then I would need to provide a field tag to store this proficiency level. I would provide predefined options for that standard, so A1, A2, B1, B2, et cetera. Optionally add the option of native speaker, which is the highest possible level of proficiency in a language. Allow the selection of a group, so you can select group B, or force you to select either B1 or B2. Allow configuration of labels and descriptions. So you saw the descriptions earlier, and actually I'll come back. These are the descriptions of the levels, but if you're setting up something along the lines of a language course catalog, then you might want to rewrite these and make a bit more focused to your customer, the prospective language students that you have. So then, on top of that, we also want to provide some views integration whereby you can filter things as you normally can and also sort them. Since, after all, this is a hierarchy in more than one way. So how would we build something like this? Well, usually in preparation for these things, I start very simple. Your standard installation of Drupal should get you going, and ideally you should test things on a standard installation. Dresch 11 for code generation, as was mentioned earlier in the double field page, Dresch is great for code generation. In the past, we've also used Drupal console. That seems a bit stale these days. We usually add some modules to help us with our process, obviously the VEL, and I have a soft spot for the symphony var dumper. The configuration inspector, we've done a serious effort to make sure that all our configuration on our modules follows the scheme appropriately. We also use upgrade status to let us know if we are need ready for Drupal 10, and admin toolbar, because admin toolbar. Then we can generate a custom module using Dresch generate. If you haven't tried it, I invite you to have a look and, well, generate all the things and see how they are done. The command line interface will ask you many questions. Usually my go-to is generate always two things. Say no to everything on the first, say yes to everything on the second, and mix and match as you need it. So then we can generate a service. We'll just create the service class to provide a list of our level groups and our individual levels. We can generate a field type plugin. In this case, we would add two properties to it, a value property to store our keys and a weight property to store numeric value. This facilitates sorting down the line. We could generate a configurable field widget. Now we normally, you saw earlier my select lists. This is typically the way that we apply this. So you can allow the selection of your top level or you can force the selection of your deepest level and you should also have an option for each field configuration to allow the native speaker option to be included in your select options. After that, we can generate configurable field formatter plugins. So if you've ever done one of those, you know that you can simply output things from the formatter itself so you can output the raw value. So this could be your key or the corresponding label of the key. And well, if you want to be friends with your front-end developers, then you might want to also include a default formatter to render this field as a tweak template because of course this facilitates the life of a themeer greatly. And definitely use dependency injection. So this already exists. This is part of something that we have built before and I've just described the way that we build it. That and many more things. This is part of an effort that we did to model the Erasmus without paper specifications into the Drupal paradigm with custom entity types and custom field types. And sure enough, we do have a service to provide these things. We have your field type, field widget, field formatters and tweak template. So I'd invite you all to check that. And I would just make a side note. I had prepared a number of hypotheticals for this presentation and well, at the last minute talking to the colleagues, we figured that beyond just creating some example that I could show you, we figured why not actually take something useful. Something that is already in use indeed across a number of sites and applications that we currently manage and that we feel can be reused as well. So the point being that we're still missing a few things but we're going to finish the module and publish it by the end of DrupalCon because we feel it would be most appropriate. So the things that we're still going to add are of course the configurable descriptions as I mentioned earlier, which I still not done. Views integration, test coverage of course and we will be refactoring as we always are. So if anyone wants to join that party, you are more than welcome. You can check out many other things that we have done over the past. These include not just the Erasmus OutPaper specifications I was talking earlier, but also a few more generic use cases. Also related to authentication, or how to serve or open ID connect and those sorts of things. And if you want to get a little bit of useful documentation, of course the Drupal documentation, of course our usual guides, so our most trusted assets here, of course the local development guide, our development tools, how to create modules, create the custom field types, defining our own configuration, which we use for this and many other things. Always very helpful to be familiar with the Drupal APIs, of course for this purpose the field types, field widgets and field formatters are a must, form render elements, because who doesn't love form API? And of course you would need those for the field widgets, render arrays also very useful for your field formatters. And ultimately there are some specific things that can be very useful here. One of them would be the computed field property classes. You remember that earlier I mentioned I want to store a key, but also a weight. Well I don't want the user to define that weight, so I might just make it a computed property. And of course if you want to include any of these new field types as base fields in your custom entities, then you also have good resources for that. And ultimately the dependency injection in Drupal 8 plugins was a bit of a headache for us, but fortunately the good people at Chromatic made a really nice write up on this topic. It's short, but it's very useful. So I mentioned a few of these modules, which are very helpful when we're trying to solve those site building patterns that I was mentioning earlier. I would also recommend you have a look at the code that is included in those other modules. The country module is one of my favorites. Of course that just provides a list of countries as included in Drupal Core. The custom language field does the same with the languages, but allows you through configuration to add a few more. The address module by the commerce guys, which again it's a multi property field type and it follows an address standard that escapes my mind right now. Physical fields, which includes units and unit conversion. And then of course, because double field wouldn't do triple field, someone did. And there are a couple of other solutions that are popping up on my radar, like field compose and flex fields. We've also used computed field for a few cases in the past. And I've found it very educational to explore the code, try out these modules, see how they work because they are usually a very good source of ideas, a source of inspiration for us. So in conclusion, I'm sorry you didn't get to see any live coding, but that usually goes very wrong. Our main conclusions of this were, we've had to get to know Drupal Core and the contrib space. Of course this comes with experience. I work with colleagues that are much newer to Drupal and they usually come to me just because I'm at this point a living encyclopedia of the contrib space because I've tried to use everything. We have to really understand our project's requirements so we don't fall into some very annoying pitfalls. It's very good to go with core and contrib as far as you can. In fact, I've heard and seen many projects of a very large scale where the development team actually sticks to this approach. But of course having enough resources you can also go back and you can see what's missing from the contrib modules that you're using. You can contribute back. You can help solve issues, fix bugs and so on. But it's fine to really go custom. You have a lot of resources at your disposal not just in the Drupal documentation but your good old stack exchange and so on. And in general, do not be afraid to write your own code. Just remember to test it. They say it's useful. And of course if you prefer to stick to only contributed modules, why not contribute your own? Which is in any case what we are planning to do. Speaking of contributions, I would like to remind you that we have the ongoing general contribution, the first time contribution workshop. So be sure to pitch in if you can. And I'll try to. And that concludes our presentation today. Thank you very much. So at this point if you have any questions I'd be happy to take them. Thank you. Wait, Yak. So when you say go with contrib as much as possible there's of course a caveat here which is on one end if you use a lot of contrib then your exposure when migrating from Drupal 8 to Drupal 9, Drupal 9 to Drupal 10, 10 to 11, whatever starts growing. So there must be like a point where you say I want to use as much contrib as possible but also I want this code to be maintainable. How do you, other than the functionality do you have any other elements that you use to choose which contrib modules you're going to use? Well, on the one hand, and I'm guilty of this, we have those situations when all you have is a hammer, everything looks like a nail. So obviously the problem is if we are used to some particular paradigms and some particular patterns we always try to imagine our application in that way. So that's one of the things we try to avoid. There are some contrib modules that do exactly what you need and little more. There are some other cases where to put something together you would need to combine a lot of them. Of course, there is no holy grail for this. There is no right answer that will fit every case but my rule of thumb is if I have something that comes close to what I need then I'll go with contrib as much as possible. And when I say as much as possible is avoid custom coding as much as possible but I don't mean throwing 20 contrib modules is to solve one particular problem. It always depends on the needs of the project and if you already have a lot of contrib in your project then you might want to avoid it altogether. In terms of migration, one of the things that we try to see is how actively a module is maintained. Can we understand it? So if need be, can we patch it by ourselves? Or if we feel that it's not actively maintained, if it doesn't have security coverage and so on, usually we might steer clear. Even recently we had a case that we could have just gone with something in contrib and built on that but because there was a slight change in terms of what the module did and what we were trying to do, we just decided to build something from scratch because also the contrib module was not actively maintained anymore. The last release had something like two years. So we figured if we start now, if we build it ourselves and if we build it properly, it's easier to maintain and well, we are responsible for our own migrations of our own codes. Anyone else? So what kind of testing do you usually recommend for custom fields? This is the part when I said that I should do a lot more testing. It really depends on the case. And I haven't done that much. We need a lot more test coverage than the things that we've done. But we, I mean, our biggest issue is the problems that we've been solving are fairly simple. And as long as you rely on something that is tried and true, like field plugins, you're generally okay. My biggest concern is usually if I'm working on something that is user facing, I try to do my functional tests, try to test my forms and make sure that everything is on the up and up. But generally I haven't had many cases where you have to do very strange custom storage or things like this. Usually I don't connect to many systems so I don't go too deep into the thing. Right now we are undergoing, in our team, very heavy process of trying to add test coverage to a number of platforms that have been sustaining bigger systems so we really want to keep them as stable and tested as possible. So we have some, I mean, we have all kinds. Not too much unit testing, a lot of kernel testing, some functional testing. I can't give you percentages but this is usually how we've been doing things. Hi, thank you for your talk. Going back to the point about using Contra as much as possible. How do you manage, as you're also not over-cluttering the project with so many control modules? Thank you. Well, it goes to the earlier point. If you are throwing one control module that usually does more than one thing, to every little problem you have, it's gonna go too big anyway. So I think one of the typical issues that we had for a while was, for example, field level permissions. If you want to restrict access to a particular field by users with certain permissions. And there's a module for that, field permissions. But we figured there was too much for what we were trying to do. It brought in a lot of configuration, a lot of things and we can simply include that snippet of code in something that we were already putting together. So again, if you have a complicated case, it makes sense. So for example, I would not try to reinvent the group module, for example, because it's huge. But I would be very careful on whether to use it. I would not go that far unless I really need at least half of the functionality that it provides. Because otherwise you have something extremely heavy in the system and you're not really taking advantage of everything. Of course, even in a contrib space, you might find lightweight alternatives. There's something like permissions by field and things like this. Our permission by reference, I forget. But again, as I mentioned earlier, it's every site, every application is a snowflake and it's unique in its own way. What we've tried to do is when we build functionality for our own platforms and they always have some common functionality at some level. So we started creating our own modules that respond to that use case in particular. I'm not going to say they're the most lightweight of modules because they are certainly not. But they cover that specific use case or that's actually more than one. It's a group of use cases if you will. But we included just enough configuration that if I drop it in one site, I can just pick a couple of things it would work like I needed to. Usually they play well together because we developed them all. It's easier that way. But yeah, one thing is sticking to contrib. The other thing is overdoing contrib. But like we could be talking about contrib or we can talk about anything else. If you don't need it, you might not want to include it. In fact, our in Drupal installation profile does switch a lot of things off that usually ship with the standard profile in Drupal. If we don't use them, then there's no point having it switched on. I wanted to know some of the drawbacks that you find using paragraphs. For me, the biggest thing I think is that whenever you edit a node that has paragraphs, it'll make a new revision of it even if you don't change the fields in the paragraph. So if you have hundreds of fields of paragraphs, it can be a performance problem. And yeah, so what other issues have you found like using paragraphs that you'd favor using custom fields for that issue? Well, I do have a horror story that I will not share on camera, but I have seen something really, really aggressive, like a table with six and a half million entries. That's a lot. That's a lot. Obviously that was a performance hit. I think it took me about 45 minutes to restart the SQL file on the machine. It was not this one, granted, but still. That was one of the issues. Now I understand why that decision was made, where it was made. But it's, I mean, if we had to do it all over again, obviously we would go custom fields. And I've actually put together a custom field that has 16 properties. It may seem like overkill, but conceptually it's consistent. And it's there. There are fields that are also revisionable. We also have that, but there is a lot less overhead than using paragraphs. Now for me, paragraphs, I've always enjoyed, I've used it in a lot of cases, but it's usually if we're building your website for publications. So obviously if you want to allow your users to compose pages with structured content, it's the perfect use case. It works very well. But if you're building an application that is going to store a lot of data, this might not be the way to go. And also we're missing out on the good things of paragraphs because you can have different paragraph types. You can nest them. You can field them in any way that you want. You can style them in anything, anywhere that you want. But all of this came precisely because we had to model some things. And we went with custom entities in custom fields. Not on a whim. I actually tried like a month. Can I model this using just core and throw in the paragraphs as well? But we got to a point that it was just pointless. We were wrestling and going against what these tools are designed to do anyway. And if they offer the opportunity for us to tweak something, do exactly what we want and how we want it and nothing more, then yes, we do get a good performance gain. We avoid a lot of headaches. There was one drawback. And this goes back to the first question. Who gets to maintain it? Well, if you create your own module, you get to maintain it. The advantage, of course, contributing it to the community is first of all, you will have more eyes on and perhaps other people take interest in it. Perhaps other people have use cases that require extending its functionality. So you might get a little bit more assistance on that. So in that respect, it's a bit more sustainable. But yeah, in general, if you can, why not code something for your specific use case? I know that Drupal gets a bad rep in terms of development platform. At least I think it was the Stack Exchange surveys were not kind. But to be honest, I found that the documentation is getting better. The Drupal itself is getting much more consistent. And I would say try. I know that my first contact was daunting, but right now I feel a lot better. I still like site building, to be honest. A lot easier if you have to click on things instead of writing your own code and then going back and forth and putting all the semicolons back where you missed them. But yeah. OK, so thank you very much.