back to Themify.me

Coding Addon Modules

Flow is built with extendable in mind. This makes the framework very flexible and it gives you the freedom to customize for your specific needs. This tutorial explains how to create custom modules for Flow.

Creating Basic Plugin

Coding Flow addon modules is similar as coding standard WordPress plugins. So first step, let’s make our plugin’s main structure. In wp-content/plugins/ directory create a new folder and name it “hello-world”, then inside that folder create a file named “hello-world.php” and paste this in:


<?php
/*
Plugin Name:  Flow Hello World
Plugin URI:   https://themifyflow.com
Version:      1.0.0
Author:       Themify
Description:  Hello World module for Themify Flow
Text Domain:  hello-world
Domain Path:  /languages
*/

After the plugin file is saved, go to WP-admin > Plugins and activate the "Hello World" plugin.

Module Definition

Back to to the plugin file “hello-world.php”, add:

defined( 'ABSPATH' ) or die;

/**
 * Load module file
 */
function tf_hello_world_load_plugin() {
	include( plugin_dir_path( __FILE__ ) . '/includes/hello-world-module.php' );
}
add_action( 'tf_modules_loaded', 'tf_hello_world_load_plugin' );
The first line checks if our plugin is loaded through WordPress, otherwise it won’t load the codes at all. The “tf_modules_loaded” action hook is called when Flow is loading the modules, so we can use this hook to load the addon. This way the code will not run if Flow framework is not active (since the “tf_modules_loaded” hook does not call in, so it won’t throw any error). In the function we simply load another php file which will hold our custom module. Create “hello-world-module.php” inside the plugin’s “/includes” directory so we can add the code for the module. Making a custom module is really easy, we only need to extend the “TF_Module” base class and override it’s methods that define the options of the module and render the output. The skeleton of the class looks like this:

<?php

class TF_Module_Hello_World extends TF_Module {
	/**
	 * Constructor.
	 */
	public function __construct() {
		parent::__construct( array(
			'name' => __( 'Hello World', 'themify-flow' ),
			'slug' => 'hello-world',
			'shortcode' => 'tf_hello_world',
			'category' => 'content'
		) );
	}

	/**
	 * Module settings field
	 * 
	 * @since 1.0.0
	 * @access public
	 * @return array
	 */
	public function fields() {
		return array();
	}

	/**
	 * Module style selectors.
	 * 
	 * Hold module style selectors to be used in Styling Panel.
	 * 
	 * @since 1.0.0
	 * @access public
	 * @return array
	 */
	public function styles() {
		return array();
	}

	/**
	 * Render main shortcode.
	 * 
	 * @since 1.0.0
	 * @access public
	 * @param array $atts 
	 * @param string $content 
	 * @return string
	 */
	public function render_shortcode( $atts, $content = null ) {
		return '';
	}
}

new TF_Module_Hello_World();

The snippet should go in the “hello-world-module.php” file. We have 4 methods in the class:

  • the __construct method registers the module
  • the “fields” method defines the options of the module
  • the “styles” method defines the options for styling the module
  • the “render_shortcode” method handles the display of the module on frontend.

The __construct function passes an array of the following keys:

  • name: This is the name of the module as seen in the admin screens when you’re editing templates.
  • slug: Internal ID of the module, should not contain spaces.
  • shortcode: The key for the shortcode used by the module, this is used only internally (Flow handles the shortcodes) however it must be unique.
  • category: The module group it belongs to. Flow by default has 5 module categories:
    • content: General category for module that handle display of actual content, like image, text, video, icon, etc.
    • global: Global site elements, such as site logo, menu, search form, widget areas, etc.
    • single: Modules that only work in the single post pages, this includes modules that display the post (post title, post content, the featured image and other post-related elements), displaying comments, post navigation links, etc.
    • archive: Modules that only work in the WordPress archive pages, like modules to display the post, category title, category description, etc.
    • page: Modules for displaying a Page page (reference: https://codex.wordpress.org/Pages), like page title, page comments, etc.
    The value for this key can either be a string or an array, so a module can belong to different categories as well.

Now if you edit a Flow template or template part, you will see the "Hello World" module available in the module panel.

screenshot

However, we are not done yet. Right now, you can add the module anywhere, but nothing will output. That is because our “render_shortcode” method returns an empty string, we can modify this method to show a “Hello World!” text:


public function render_shortcode( $atts, $content = null ) {
	return 'Hello World!';
}

And boom! There’s the module output:

screenshot

The module can now render the same text over and over again (which might just be what we need, for example think of a code that client needs to enter in the middle of their content over and over again) however how about making the module say hello to someone we choose?

Adding Module Options

Options are defined in the “fields” method, this method simply returns an array of the option fields for the module. Let’s do a simple text input so we can write the name of person we want to say hello to.

To add module options:


public function fields() {
	return array(
		'name' => array(
			'type' => 'text',
			'label' => __( 'Say hello to', 'themify-flow' ),
			'class' => 'tf_input_width_70',
		),
	);
}

This defines one option for the module, a text box named “name”. Note that Flow has a wide variety of field types, we are just showing the basic text input. Next we need to override the “render_shortcode” to show the name of the person:


public function render_shortcode( $atts, $content = null ) {
	extract( shortcode_atts( array(
		'name' => 'World',
	), $atts, $this->shortcode ) );

	return '<div class="tf_hello_world"><h1>Hello ' . $name . '!</h1></div>';
}

The “$atts” variable in that method as an array, holding all the saved options for the module. The “shortcode_atts” function call is a simple trick to set default values for our options (so there’s no warning or notice messages in PHP if the values don’t exist). The next line simply returns “Hello” and the name we have entered in the module option, wrapped in a h1 and a div tag. Done, our module now can say hello to anyone!

Adding Styling Options

Flow allows customizing the appearance of all modules with the Styling Panel. This is achieved using the “styles” method, it returns an array of CSS selectors we want to style in the module.

To set styling options:


public function styles() {
	return array(
		'tf_module_hello_world_container' => array(
			'label' => __( 'Module Container', 'themify-flow' ),
			'selector' => '.tf_hello_world',
		),
		'tf_module_hello_world_heading' => array(
			'label' => __( 'Hello Text', 'themify-flow' ),
			'selector' => 'h1',
			'basic_styling' => array( 'background', 'font', 'padding', 'margin', 'border' ),
		)
	);
}

In the above function, we have:

  • label = the text element of the element which will appear on the Styling Panel
  • selector = the CSS selector
  • basic_styling = specify what CSS options (styling properties) should appear in the "Basic" tab

screenshot

The CSS code from the Styling Panel will output in the theme generated.css file.

Download Source File

You can download the entire code for the Hello World module here.