HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Simple Setting Screens With ConfigurationModule

Creating Simple Setting Screens Easily With ConfigurationModule

Introduction

Imagine you have made a great plugin and want to make it configurable. You will need settings in the config.php and it would be comfortable to have a settings screen where you can see and change the data. You will not need much to get going, just two lines in the PluginInfo array and one (really!) small function that creates a route to our settings screen.
Let's start with the PluginInfo array and than take a closer look at the function.

PluginInfo Array

Here's the code that must be part of your info array

$PluginInfo['YourPlugin'] = array(   
   ...   
   'SettingsPermission' => 'Garden.Moderation.Manage',   
   'SettingsUrl' => '/settings/yourplugin',   
   ...   
);   

We define the needed permissions here (but it's just an information as far as I know, please correct me if you know better!) and afterwards point out where the [Settings] button should send you. We will have to create that controller now, although the button is already next to the [Disable] button of our plugin in dashboards plugin list.

Creating the Setting Screen

I start by showing you the code you would need to manage a $Configuration['Plugins']['YourPlugin']['GreetingText'] = 'Hello World!'; line in your config.php. We will continue by looking on how that entry could be influenced and climax in a look at how to create other form elements than boring textboxes!

Simple Setting Screen

public function SettingsController_YourPlugin_Create($Sender) {   
   $Sender->Permission('Garden.Settings.Manage');   
   $Sender->SetData('Title', T('Your Plugins Settings'));   
   $Sender->AddSideMenu('dashboard/settings/plugins');   

   $Conf = new ConfigurationModule($Sender);   
   $Conf->Initialize(array(   
      'Plugins.YourPlugin.GreetingText'   
      ));   
   $Conf->RenderAll();   
}   

Believe it or not, that's all you have to do! Okay, line by line...
public function SettingsController_YourPlugin_Create($Sender) {
Creates a route in the SettingsController so that http://yourhomepage/settings/yourplugin will call this function
For further information search for "magic methods"

$Sender->Permission('Garden.Settings.Manage');
Ensure that only users with that permission could continue with this function
For further information search for "permissions"

$Sender->SetData('Title', T('Your Plugins Settings'));
Set's the heading of our settings screen to "Your Plugins Setting". The surrounding T() function makes this string translatable
For further reading search for "locales"

$Sender->AddSideMenu('dashboard/settings/plugins');
Adds the dashboards sidemenu to our side

$Conf = new ConfigurationModule($Sender);
Get an instance of the ConfigurationModule which does all the work for us
For further reading stay here ;)

$Conf->Initialize(array(
We have to initialize our instance with an array of what we want to be displayed

'Plugins.YourPlugin.GreetingText'
This will create an inputbox and a label for that input field. The label will be "Greeting Text" - that's the last part of our settings description split by the upper letters. The value of the input will be whatever is the value in config.php. If the key does not exist in config.php, the input field will be empty.

$Conf->RenderAll();
Renders side menu, title and form elements (including a [Save] button) to the screen

Taking More Influence on the Output

All we need to change is that line: 'Plugins.YourPlugin.GreetingText'. We can add additional information to it:
1. set an individual label
2. set a default value
3. all of the options you can set to a textbox, like for example "maxlength"

Let's do all of the above in one step and you'll see at once how that could be done. Replace the above line with the code below

'Plugins.YourPlugin.GreetingText' => array(   
   'Control' => 'textbox',   
   'LabelCode' => T('Enter the phrase you would like to greet with'),   
   'Default' => T('Hello World'),   
   'Options' => array('maxlength' => '20')   
)   

Pretty self-explanatory, isn't it? You could use LabelCode to change the label for the textbox, give a default value with Default and set additional input box attributes with an Options array.
See that Control key in our array? It's not needed here, I just wanted to prepare the next step...

Comments

  • I actually just noticed this module last week! This is an excellent write up. :D

    @R_J said:
    $Sender->AddSideMenu('dashboard/settings/plugins');
    Adds the dashboards sidemenu to our side

    The string passed into this function determines what menu group/item is highlighted when the sidemenu is rendered.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • I've missed something...

    Descriptions

    You could even add a description to each of your controls. It is as simple as adding 'Description' => 'Description text' to your array. Here's an example:

    $Conf->Initialize(array(  
       'Plugins.YourPlugin.Category' => array(  
       'Control' => 'CategoryDropdown',  
       'LabelCode' => 'Choose a category',
       'Description' => T('I\'m the example description that should explain to the admin, why he would like to select a category')
       ) 
    ));
    

    Label, description and form controls will always be rendered in the following order:
    Label
    Description
    [Form Control]

    Translate Function

    I've recommended to always use the T() function so that your texts will be translatable. As far as I can see, Gardens form class library/core/class.form.php, which is used by the ConfigurationModule, does already enclose all relevant form parameters into the T() function by itself. Using T() by yourself will be redundant, when you use it for labels.
    /!\ You'll need that function for the 'Description' part, because that will not be enclosed automatically wrapped in the T() function (a behaviour that should be changed)

  • Something useful I just noticed:

    If you want to build a settings screen but need to handle processing the submission yourself, just replace the call to Initialize() with Schema()

    public function SettingsController_MyScreen_Create($Sender) {
        $Sender->Permission('Garden.Settings.Manage');
    
        if ($Sender->Form->AuthenticatedPostBack()) {
            $FormValues = $Sender->Form->FormValues();
    
            // Handle the form submission ...
        }
    
        $Conf = new ConfigurationModule($Sender);
        $Conf->Schema([
            'Anything' => ['Control' => 'textbox', 'LabelCode' => 'My Textbox']
        ]);
        $Conf->RenderAll();
    }
    

    This way the ConfigurationModule only builds the view.

  • Hi @R_J, great tutorial! Your How_Tos are much appreciated. In reading some of the Vanilla source I noticed something in class.validation.php line 415 - the comment says:

    • @param string $RuleName The name of the rule to be added.
    • @param string $Rule The rule to be added. These are in the format of "function:FunctionName"
    • or "regex:/regex/". Any function defined here must be included before
    • the rule is enforced or the application will cause a fatal error.

    Which seems to indicate that the validation rules could be extended. For example, while I saw that there is a simple validation for integer, I did not notice a built in validation for a range of numbers (e.g.3-9). So is my novice reading of the comment indicate that one could indeed add a range check validation through the model? If so, how?

    Just a thought...

  • peregrineperegrine MVP
    edited September 2015

    http://vanillaforums.org/discussion/21149/how-to-do-i-use-addrule-or-validaterule-to-create-a-custom-rule-for-validation-purposes

    when searching this forum make sure the archived discussions box is checked otherwise you will miss out on alot of answers. Unfortunately currently valid answers will not show up because vanilla 2.0 question category is archived.
    And items that relate to vanilla 2.1 are asked in vanilla 2.0 category, so it is a mishmash. the reason why it is important to be cognizant what category you post in.

    look at the default answers

    http://vanillaforums.org/search?adv=&search=applyrule&title=&author=&cat=all&tags=&discussion_d=1&discussion_question=1&comment_c=1&comment_answer=1&page_p=1&within=1+day&date=

    vs. when archived checkbox is checked in search.

    http://vanillaforums.org/search?adv=1&search=applyrule&title=&author=&cat=all&archived=1&tags=&discussion_d=1&discussion_question=1&comment_c=1&comment_answer=1&page_p=1&within=1+day&date=

    or a reason to use google rather than vanilla search before asking questions.

    I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.

  • Wow, that's sucks (archives, search limitation, etc.)... but your pointer to the original post is on the mark- Thanks!. I feel less in the dark just to realize that Peregrine the great posted a question close enough to what I deduced from the Vanilla source. Maybe I have some hope;-)

    I wondered whether google search works on archived categories. It made sense to me that it should since they were once crawled by it, right?. However the following search did not pick up this post:

    configurationmodel rules site:vanillaforums.org

    and the search for rules without the configurationmodule term did not pick up the post in the first pages either. You really have to know what term to use to find it even with Google. So sleep well, there is no substitute to your vast knowledge ;-)

  • peregrineperegrine MVP
    edited September 2015

    I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.

Sign In or Register to comment.