Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

 

Making a module fit for purpose

Introducing 9 ways to make a module fit for purpose.

Read post

This blog post introduces nine ways to make a module fit for purpose to SilverStripe newbies. For more experienced SilverStripe coders, it may serve as a 'module hack cheat sheet'.

There are a myriad of modules on addons.SilverStripe.org. Often times, you will find a module that does most of what you need, but not quite what is required for the job at hand. The steps below introduce ‘easy, lightweight, hassle-free’ solutions through to ‘advanced, invasive, and hard-work’ ways of customising a module.

1. Open the CMS
For many modules, you should be able to make them work as you see fit by editing your data in the CMS. Here are a few places to check:

  • Should any objects or pages be created? Check individual pages for setting. Don't forget the settings tab for individual pages.   
  • Are there any site wide configs to be set (see /admin/settings/ )?
  • Were any new items added to the main CMS menu options when you installed the module?

To avoid having to update every instance of your project, you can write a bit of code that will run every time you do a dev/build.  For this, the requireDefaultRecords method is ideal. Here is a basic example:

requireDefaultRecords

More elaborate database updates can be achieved by writing a BuildTask:

BuildTask

You can run this task from the /dev/tasks/ExampleBuildTask URL (or sake /dev/tasks/ExampleBuildTask from the command line) whenever required.

2. Wording Change
It is amazing what can be achieved with a simple wording change. The first step is to find out where the text is defined.  Search all files (use grep or your editor’s search functionality) will give you some quick answers.  When I searched for “log in as someone else”, I found this code snippet in our beloved LeftAndMain class.

LeftAndMain

You will also find this phrase in /framework/lang/en.yml and some other language files.

To change this phrase, you need to know what is the default locale for your site and any other likely locales set for individual users (in most cases this will be the same as the default locale).

To change the wording, add the following file: mysite/lang/en.yml to your project.  In that file, you can provide alternative wording like this:

leftandmain2

The name of the language file depends on the locale you want to update (e.g. en.yml may need to be changed to es_AR.yml (Argentine Spanish) when you are building a site offering hotel bookings in Buenos Aires). Have a look at  “i18n - setting the locale” and also an example language file.

By default, translations stored in the mysite folder have top priority (see: i18n - module priority) so there is no need to create the epic zzzzz-language-fix-folder.


3. Change configs
Most modules make use of the config layer for settings such. For example, the SiteTree class sets the generator tag content using this approach. In short, private static variables in PHP classes store configuration options and they are adjusted using the yml files. To change settings, you can add and edit these yml files.

For example, create a file mysite/_config/module_name.yml and add content like this:
modulenamefixes

This code will override the private static variable my_private_static_var in MyClass and set it to 21.

To get an idea of the options, have a look in the module README.md file, the _config folder in the root directory of the module and also search for $this->Config() and Config::inst()->get in the module code to see what configs are available. You can also use this private static discovery tool.

For more information on the Silverstripe configuration options, see the configuration documentation.


4. Can it be fixed with CSS or Javascript?

If it does not look right then obviously css and javascript are your friends. Here are some basic tricks to make quick changes.

css

Firstly, check the head of the HTML output for CSS files. If there are any CSS files that are included from the module (e.g. the CSS file points to module_name/css/FancyModuleCSS.css), then chances are that you should be able to theme this CSS file by adding a css file here: themes/themename_module_name/css/FancyModuleCSS.css.  If you create this file, it will automagically replace the module based CSS file (as long as the module author has made the CSS file “theme-able”). In this example, the name of your theme is themename — of course this could be any name you like, as set in the SSViewer (simple is the theme name in the SilverStripe installer). After the theme name you add an underscore character and then the module name, within this folder you adhere to the standard folder layout (i.e. there could be a css/templates/and javascript folder, etc.).

Alternatively, you can simply block a CSS file in your PHP code:

BlockCCSinPHP

For more information visit the theme-ing and requirements documentation. 

Javascript

The Javascript instructions are similar to the CSS instructions above, except that themed Javascript files do not automatically replace files in the module. For javascript, you will need to block and manually include your replacement file, like this:

MyPageWhichExtendModulePageController

Of course, you can also simply add Javascript or CSS to interact with the CSS/JS from the module.

Pro Tip:
If you have trouble with the sequence of the requirements being blocked and included, look at the extension calls onBeforeInit and onAfterInit to make it work.

5. Can it be fixed with HTML?

Just like we themed CSS files, you can also theme a template file. Firstly, check the source of the output HTML to see what file needs theme-ing. Searching in files for a class or a unique snippet of html that you would like to change is usually the fastest way to find the template file. You can also add the following to the mysite/_config/module-name.yml file:

 module name

Once you have found the file in the module, you can create the equivalent in the theme folder (e.g. themes/themename_module_name/templates/Includes/MySnippet.ss). This new file will then be used instead of the original MySnippet.ss file in the module.

For more information have a look at the templating documentation

6. Is there a module that can add the functionality?

It is definitely worthwhile to find out what other modules require the module you are trying to adjust. Some of these other modules may actually add the functionality you are looking for already. Here is an example of the modules that require the SilverStripe blog. You can replace SilverStripe:blog in the URI with your module at hand.

Of course, it also pays to have a look at addons.SilverStripe.org and also ask the Silverstripe Community to see if anyone else has done something similar to what you need to do.

7. Extend a class
If none of the options listed so far are any good, then it is time for the real McCoy

… class MyClass extends ModuleClass ….  

Most of the time this works a treat, but here are a few issues you may encounter:

(1) The class is hard-coded in the module.  For example, in the module there is a line:

$obj = ModuleClass::create();

which results in your objects being created as ModuleClasses rather than a MyClasses. For example, if you extend Member as MyMember, then you still may end up with Member objects in the database that do not have the functionality you added in the MyMember class.  See recommendation 9 for a possible solution to this problem (replacing a class).

(2) In other cases, the class name is used in the HTML/CSS which means that default formatting does not work anymore. This is usually fairly easy to fix, but definitely something to watch for as in some circumstances this can create an unexpected challenge.

(3) If you are extending a page type then make sure to hide the original page type using the static variable hide_ancestor

8. Call in the Decorators

There are two key classes in SilverStripe that allow you to “decorate” classes. Basically these are what the future calls PHP Traits, or what we may call clipons or mixins. They add functionality to a class without extending it in the traditional way. Creating a class extension comes in two steps:

1. create your extension 

createyourextension

 2. add your extension to the original class using the config layer (yml files)

configlayer

DataExtensions can decorate any class that extends  DataObject and Extensions can decorate any instance of Object (almost every class in the SilverStripe Framework has Object as a (distant) ancestor).

To find out where the “hooks” are, do a search for ->extend in the module you are working on. Most key methods will have an extend call, like the updateCMSFields call (or hook) in the getCMSFields method. Many private static configuration variables, such as $db, $has_many, $field_labels, etc…, in DataExtensions are added to the DataObject being extended.

For more information, have a look at the extensions documentation

9. Create a custom class

A lesser known option is that you replace a module class with your own class, as opposed to extending it. The injector documentation explains how this works. Here is an example on how to replace a class, ModuleClass, with a custom class  MyClass

customclass

Still no luck?
Other methods to consider include:



About the author
Nicolaas Francken

Nicolaas is the Founder and Director of Sunny Side Up, a Wellington based agency that builds websites using the highly praised SilverStripe CMS, especially e-commerce applications. He is also 'the man behind hundreds of modules'.

Post your comment

Comments

  • Thank you for posting these hacks of including a model in Silverstripe for newbies. Silverstripe is an awesome CMS , it helped me develop a website without any hassle.

    Posted by Amelia Roster, 03/10/2016 8:01pm (8 years ago)

RSS feed for comments on this page | RSS feed for all comments