Divine Initiation
Namaste!
Note: There has been updates to the Divi theme that make some changes to the code. This tutorial was written about pre-Divi 3.0.45, but having said that, ET was careful to update in such a way that old code still maps nicely. That means that these tutorials are still germane (at least as of May 13, 2017), but we will see what future updates bring! I will be writing new tutorials to introduces the new features of Divi soon!
This tutorial is the second in a series deconstructing the code that goes into the Divi theme with the goal of being able to write our own module at the end. The first in the series was an overview of the main parts of each module. This article will look specifically at the first method of each class, the ‘init()’ function. Fair warning to those of you who know a bit of php, this tutorial goes over a lot of basic items and maybe a bit slow and wordy! For those not familiar with php, we will be getting into the thick of it and this might require a re-reading later to get all the concepts. TL;DR, the ‘function init()’ method of the module sets up and partially pre-populates all of the field variables that will be needed for the other methods in the class.
First, a couple of notes on terminology. In php, a class is an object that holds both variables and functions. Using correct terminology, variables within the class are called ‘properties’ of the object and functions are called ‘methods’ of the object. I’m going to try to use the correct terms going forward, but wanted to introduce these terms without getting all nerdy in the first article and scaring people off!
Once again, we will be walking through the standard width ‘Image’ module code, which is the first class in the Divi 3.0 main-modules.php file. This file is located in builder folder of the theme folder, Divi>>includes>>builder. Open it up to follow along (I switch between Atom, Brackets, and Sublime Text depending on whims and needs)!
So starting off, prior to the ‘init()’ function we open up the class with the line:
class ET_Builder_Module_Image extends ET_Builder_Module {...}
This says we want to instantiate a new class called ‘ET_Builder_Module_Image’. If we were making a custom module we could change this to anything we want. However, it can’t conflict with any existing class name, so it is good to prefix our class name. For example, I always prefix with SHD (Spring Hill Design) and then usually something plugin specific. So as a name for a custom image module for Divi I might use, ‘SHD_Divi_Module_Image_Extended’. Our name is followed up by ‘extends’ and ‘ET_Builder_Module;. This is a way that the core Divi builder class, ‘ET_Builder_Module’ can share properties (variables) and methods (functions()) with the individual modules and is called ‘inheritance’. Basically, this new ‘child’ class inherits everything within its ‘parent’ class. You don’t need to worry too much about this, just know that all of the Divi modules need to start this way.
Okay, next up in the code is the creation of the init() method.
function init() {...}
As with all functions, you have the keyword ‘function’ followed by the name of the function and a set of parentheses. If data is being passed into the function, the variable name would be between those parentheses. Finally, all of the code of the function is sandwiched between open ‘{‘ and close ‘}’ braces.
$this->name = esc_html__( 'Image', 'et_builder' ); $this->slug = 'et_pb_image'; $this->fb_support = true;
Moving into the method we see a lot of use of ‘$this’. What is this? It can be a little confusing, but it is a reference to the current object. Remember, classes are objects, so $this here means the ‘ET_Builder_Module_Image’ class. So, you have to keep track of where you are in the code to know exactly what ‘$this’ means. Following each ‘$this’ is a dash and greater-than sign. In php this is called the “object operator”. It allows us to do a number of things, but in this case, it is allowing access to the properties (variables) of our new class. This operator is followed by the name of the property we want to access. So, the first line says we want to access the ‘name’ property of the ‘ET_Builder_Module_Image’ class and set it equal to esc_html__( ‘Image’, ‘et_builder’ ). I’m not going to cover the esc_html__() – it is a WordPress function that cleans up the text it is passed for storage and allows for translation into different languages. However, in this case, if we were building our own custom module we would change ‘Image’ out for the name we wanted to give our module, like ‘Best Module Ever’. Next down is the slug. Again, this is a WordPress term, but basically, gives a method for the Divi builder to retrieve these modules. Importantly, it must be prefixed with’et_pb_’, contain only lowercase alphanumeric characters, underscores, not have 2 or more dashes in a row, and not end in a hyphen. I keep mine short and simple, like ‘et_pb_image_custom’. Finally, in this module, there is a fb_support variable. This refers to whether this module can be modified on the front end by the visual builder. Until I learn a lot more react.js, this will remain at false on my custom modules! There are several other variables that can appear in other modules, but those are the basic three.
$this->whitelisted_fields = array(...)
Shifting to the next section of code, we have an array property called whitelisted_fields. This variable gets assigned all of the various fields that will be presented to the user. In the next method, all of these fields will be retrieved and assigned values. If we were making a custom module we would simply add the names of the new fields here. The field names cannot have spaces, but I haven’t experimented to determined if other characters are disallowed, but I would follow the same rules as for a slug. So for example, we could add ‘pop_up_image’ to hold the URL of an image we want to be displayed on click. Note, all of the variables being stored in the array have a comma separating them, even the last one. This is not needed, but perfectly valid.
$this->fields_defaults = array( 'show_in_lightbox' => array( 'off' ),
Only two more sections to the init() method! This next section sets the ‘fields_defaults’ property equal to an array of the values we want initially set for the white_listed fields. Not all of the fields need to have values set. Basically, we set up an array where the key value is the name of the field, like ‘show_in_lightbox’ followed by the value that we want it to have stored as an array. In one of the next articles, we will go through the valid values for each type of field. Note, we are not using an equal sign to set the value of the field. We are using an equal sign followed by a greater-than sign. Don’t worry about why unless you are curious, just remember to assign values to keys within arrays using this operator. Like our simple array in the previous section, all of our items are separated by a comma and a non-needed trailing comma is added.
$this->advanced_options = array( 'border' => array(), 'custom_margin_padding' => array( 'use_padding' => false, 'css' => array( 'important' => 'all', ), ), );
The final section in the Image module init() method is assigning values to the ‘advanced_options’ variable. There is a number of potential key:value pairs to add in here that are dependent on the type of module and what fields it contains. Most of the properties that get set here are ones that get manipulate by the Divi builder behind the scenes. In the image module, there are two ‘advanced_options’ being set. The first is ‘border’. This allows the user to determine if a border is added to the image displayed on the browser. It originally starts as a yes/no box set to no. If the designer clicks it to ‘yes’ a whole host of additional possibilities slide-down. In a future article, we will go into how we toggle and collect those extra values for our own fields. However, if we look through the code of our class, we don’t see any mention in the white_listed fields for ‘border’. We have to depend on Divi to handle this and all we can do here is zero out the variable. In the case of the ‘custom_margin_padding’, there are some custom values already being added in as array values. First, ‘use_padding’ is set to false – this tells Divi not to add on any padding (duh!), but will get changed behind the scenes to ‘true’ as soon as a something is entered into one of the input boxes. Second, the property ‘css’ has an array assigned to it. This is a property that can be used to restyle elements that are being added and again, depends on what type of field/module is being used. In this case, the ‘css’ array is receiving the beloved ‘important’ key with a value of ‘all’. This means that all of the padding numbers being added in will receive an ‘!important’ modifier in the style sheet. We will delve into other key:value pairs in another article, but as another example:
'css'=> array( 'line_height' => "{$this->main_css_element} p", 'color' => "{$this->main_css_element}.et_pb_text", ),
This chunk of code from the ‘Text’ module will grab the main class of the module that was defined earlier and add a line height to all of the <p> with that class and then set the color of the text with the main class pluss the ‘et_pb_text’ class (remember, classes get prepended with a period in CSS. The ‘advanced_options’ property is a little trial-and-error, I usually search through the other modules to see if there is something that looks like I need and copy it. Another major one is ‘fonts’, that brings up all of the customization of font size, color, line height…
Although we are at the end of the Image module ‘init()’ method. I want to touch briefly on two other key:value pairs that you run across in some of the other modules. In many modules you will see, as alluded to above, an assignment to ‘main_css_element’. If defined it should use at least ‘%%order_class%%’ which the builder switches out for the main class of the correct selector that can be set in the next method of the class. Additional selectors can be tagged on such as the ‘.et_pb_text’ above. Another is ‘custom_css_options’. This is used when there are non-Divi handled CSS values to be set. A good example of this is located in the ‘Gallery’ module that you can seek out.
This is by no means a complete list of all the key:value pairs that are set in the various modules, but it should get you started in understanding the code a bit better. If you find examples you don’t understand, feel free to bring them up in the comments or drop me an email. As always any other questions or corrections are welcome!
This is the first time I even touch the main-modules.php – and I must say I’m really glad I did. Keep up the good work Bob! Thanks!
You should also keep up the good work! Thanks for the comment.
This is interesting! You say: “we have an array property called whitelisted_fields. This variable gets assigned all of the various fields that will be presented to the user. In the next method, all of these fields will be retrieved and assigned values. If we were making a custom module we would simply add the names of the new fields here.”
Does this mean that you don’t have to register new custom fields? Will Divi actually register any custom field names just because you define them here?
Hi Michael,
So, I’m going to hesitantly answer your question with a “yes”. The reason why I’m giving a hesitant answer is that the “custom fields” here is more limited than the one you would use if making your own custom WordPress theme. The custom fields in Divi have to be defined within the module class and are limited to the types that Divi recognizes unless you code your own. Basically, whitelisting the fields both registers them with Divi and sets them up so that the arrays they hold are sanitized when they receive user input. Once you whitelist them, you define what they are in the $fields array and they are ready to receive user input, much like a normal WP custom field. I hope this makes sense! The next part of this tutorial begins to dive into the $fields array.
Metta!
Bob
Nice! I was hoping that might be the case! I’ve been messing around with building divi modules a bit since I first read your post, and I’m really enjoying it! Thanks for your work here! It’s really helpful!