Plugins and hierarchy


Introduction to hierarchy

Outlast Framework is built to use a hierarchical plugin system where it is easy to build, extend, and override features with separate modules.

Everything – including views, controllers, models, libraries, tag and filter definitions, etc. can be overridden in plugins or the current local application.

This may be confusing at first as you may have a few copies of similar files within a project, but fear not – below is an explanation of how to determine which is relevant and which is not.

In practice

In practice this means that if we have for example a view file in the system folder /system/app/view/admin/base.html you can completely replace the contents of this file for your application by placing the file in your app folder /app/view/admin/base.html.

The framework will now completely ignore the system base.html and use your local base.html instead.

As with view files, you can also override system models, controllers, field definitions – just about anything.

The order

Typically the hierarchy is processed in this order:

  1. System folder (first system plugins, then system apps)
  2. Plugin folders
  3. Local app folder

This means that anything in your system folder will be overridden by anything in the plugins folder which in turn will be overridden by anything in your app folder – so anything in your /app folder is king.

Changing the order

You can change the order in which plugins are loaded in the global config file /site/index.php:

$zajconf['plugin_apps'] = ['user', 'email', 'content'];

Plugins are loaded from back to front, so in the example above the wordpress plugin will be loaded first, followed by email, user, etc. In otherwords, anything found in ‘user’ will override anything similar in ‘wordpress’.

You can also change the order in which system plugins are loaded:

$zajconf['system_apps'] = ['_jquery', '_global'];

As above, the system plugins are processed from back to front. So any models or controllers in _jquery that have the same hierarchical position and file name will override the one found in _global.

Plugins as Git submodules

You can add a plugin as submodule. This allows you to easily update to the latest version while also sending updates back upstream.

To add a plugin as a submodule on SourceTree open up the repo, right click on Submodules and click Add submodule.... Fill in the Source Path with the submodule repo’s url and set the Local relative path to plugins/name_of_plugin/.

Once the submodule has been added, simply follow the usual steps to activate the plugin (update in /site/index.php).

Creating your own plugins

Modular features should be placed in their own separate plugin folders. This will allow you to reuse the code in multiple projects.

Creating plugins is really simple – basically you just need to create the subfolder in the /plugins/ folder and then register the plugin in /site/index.php:

  1. Create the folder /plugins/my_new_plugin/
  2. Register the plugin in /site/index.php here: $zajconf['plugin_apps'] = [ 'my_new_plugin'];
  3. Create the same folder as found in any plugin folders or as in you /app folder
  4. Start adding your own views, controllers, models, libraries, tags, filters, etc.

Here you will find an example folder structure for the content plugin. Notice there is no separate apps folder but everything is in root here.

Plugin assets folder

Plugin assets (css, jpg, js, etc. files) need to be placed in the plugin folder’s site subfolder. So in the example above the style.css associated with your plugin would go in the /plugins/my_new_plugin/site/style.css folder. Plugin assets can be accessed externally using the following url scheme: http://www.example.com/plugins/my_new_plugin/style.css.

Important! Plugin asset folders require a .htaccess file in their site folders with the following content to work properly:

RewriteEngine off

If needed, you can use this or the global .htaccess file to change the URL scheme.

Plugin magic methods

Plugins can have special magic methods which are triggered during events like loading and installation. Plugin magic methods must be placed in the plugin’s main controller, which is a ctl file located in either /plugins/your_plugin/controller/your_plugin.ctl.php or /plugins/your_plugin/controller/your_plugin/default.ctl.php. These controller methods can be overridden locally but the plugin controller file must exist in one of the above folders.

You can have the following magic methods (all are optional):

  • __plugin() – this magic method is called when the plugin is loaded up during a request. keep in mind that when this is called the __load() method has not yet run and any plugins loaded afterwards are not yet available – including your local app folder. This means you should not access anything here that might be overridden locally (such as loading conf files or rerouting to other controllers). The parameters passed are $request, $app, $mode.
  • __install() – this magic method is called when the install script is running. You can use it to validate the plugin’s installation and send error messages about the install if needed. If you return a string, it will be treated as an error and displayed during OFW installation. No parameters are passed.

Extending vs overriding vs decoration

Extending – You can always extend any of the classes and view files found in your plugins. Extending classes will work like any standard PHP extension, while extending view files will work according to the logic of template inheritance.

Overriding – You can also completely override files by simply copying a plugin or system version to your local /app folder. Because the app folder is more important than plugin or system folders, it will take precedence.

Decorating – You can also decorate models, controllers, and views. Unlike extension, decoration allows you to add features to the original model, controller, or view as defined in the system or one of your plugins while preserving the same name. In other words, you are not creating a new, similar object, but instead modifying the original. This is useful because any future bugfixes and enhancements to the original file will apply to your decorated version as well.

Outlast Web & Mobile Development (c) 2023 | Privacy Policy |