-
Notifications
You must be signed in to change notification settings - Fork 9
English plugin dev 3 1
Sometimes plugins need additional information to act. Here is how to make a configuration panel in the Setting→Plugin screen
Some plugins need basic data to function. This include API keys and secrets, or account ids on web services.
Others use this information to tweaking their behavior, or on which item to act on.
i.e. MultiBlog plugin setting screen
We will use MyPlugin03 as the basis of this chapter, and create a configurable tag <MTHellowWorld2>.
We will actually make two configuration screen, one system-wide, and the other blog-wide.
For configuring the plugin, you should be able to go to Settings→Plugins, (either in the System overview mode or inside a blog) click on the plugin, (conveniently named “Sample Plugin 1.00”) and then choose Settings.
In that panel, you will see a single text box, with the writing below it “Please input the word, ‘Hello, xxx!’”
Enter some word, and click “Save”.
Expected (very expected) screen:
This tag will output “Hello xx!”, depending on the settings.
- Should have ability to set the name system-level
- Should have ability to set the name blog-level
- If neither blog-level nor system-level is set, use the default: “World”.
- When rendering the tag, the function should use:
- Blog level settings, if set
- Otherwise, system level settings, is set
- Otherwise, the default, “World”
id: MyPlugin08 key: MyPlugin08 name: <__trans phrase="Sample Plugin plugin config"> version: 1.0 description: <__trans phrase="_PLUGIN_DESCRIPTION"> author_name: <__trans phrase="_PLUGIN_AUTHOR"> author_link: http://www.example.com/about/ doc_link: http://www.example.com/docs/ l10n_class: MyPlugin08::L10N blog_config_template: word_setting_blog.tmpl system_config_template: word_setting_system.tmpl settings: word_setting_blog: default: scope: blog word_setting_system: default: scope: system tags: function: HelloWorld2: $MyPlugin08::MyPlugin08::Tags::_hdlr_hello_world_2
- “blog_config_template” and “system_config_template” entries are notifying MT that this plugin have blog-level and system-level configuration screens.
- The “Settings” entry tells MT which values this plugin needs. Here we define two type of settings: one system-level, and one blog-level so every blog can have its own settings. both of them have a blank default
The settings panel template, to be used in the blog-wide plugin configuration. This file should be located in “MyPlugin08/tmpl/word_setting_blog.tmpl”, and is used to set “word_setting_blog”.
<mtapp:setting id="word_setting_blog" label="<__trans phrase='_MyPlugin08_Word'>" hint="<__trans phrase="Please input the word, 'Hello, xxx!'">" show_hint=1> <input type="text" name="word_setting_blog" id="word_setting_blog" value="<mt:Var name="word_setting_blog">" /> </mtapp:setting>
The template will output the following HTML code in the plugin configuration screen.
(of course, we tidied it a bit)
<!-- Plugin Config --> <div id="plugin17-config" class="config"> <form method="post" action="/cgi-bin/mt/mt.cgi" id="plugin-17-form"> <input type="hidden" name="__mode" value="save_plugin_config" /> <input type="hidden" name="blog_id" value="2" /> <input type="hidden" name="return_args" value="__mode=cfg_plugins&_type=blog&blog_id=2&id=2" /> <input type="hidden" name="plugin_sig" value="MyPlugin08" /> <input type="hidden" name="magic_token" value="(cut)" /> <fieldset> <div id="word_setting_blog-field" class="field field-left-label "> <div class="field-header"> <label id="word_setting_blog-label" for="word_setting_blog">Word</label> </div> <div class="field-content "> <input type="text" name="word_setting_blog" id="word_setting_blog" value="" /> <div class="hint">Please input the word, 'Hello, xxx!'</div> </div> </div> </fieldset> <div class="actions-bar settings-actions-bar last-child"> <button mt:mode="save_plugin_config" type="submit" class="save action primary-button first-child last-child">Save Changes</button> </div> </form> </div>
The settings panel template, to be used in the system-wide plugin configuration. This file should be located in “MyPlugin08/tmpl/word_setting_blog.tmpl”, and is used to set “word_setting_system”.
<mtapp:setting id="word_setting_system" label="<__trans phrase='_MyPlugin08_Word'>" hint="<__trans phrase="Please input the word, 'Hello, xxx!'">" show_hint=1> <input type="text" name="word_setting_system" id="word_setting_system" value="<mt:Var name="word_setting_system">" /> </mtapp:setting>
The template will output the following HTML code in the plugin configuration screen.
(of course, we tidied it a bit)
<!-- Plugin Config --> <div id="plugin17-config" class="config ui-tabs-panel ui-widget-content ui-corner-bottom last-child"> <form class="first-child last-child" method="post" action="/cgi-bin/mt/mt.cgi" id="plugin-17-form"> <input class="first-child hidden" name="__mode" value="save_plugin_config" type="hidden"> <input class="hidden" name="return_args" value="__mode=cfg_plugins&_type=blog&blog_id=0&id=2"> <input class="hidden" name="plugin_sig" value="MyPlugin08" type="hidden"> <input class="hidden" name="magic_token" value="(cut)" type="hidden"> <fieldset> <div id="word_setting_system-field" class="field field-left-label first-child last-child"> <div class="field-header first-child"> <label class="first-child last-child" id="word_setting_system-label" for="word_setting_system">Word</label> </div> <div class="field-content last-child"> <input class="first-child text" name="word_setting_system" id="word_setting_system" value="" type="text"> <div class="hint last-child">Please input the word, 'Hello, xxx!'</div> </div> </div> </fieldset> <div class="actions-bar settings-actions-bar last-child"> <button mt:mode="save_plugin_config" type="submit" class="save action primary-button first-child last-child">Save Changes</button> </div> </form> </div>
Now your configuration screens are functional and ready
This Tags.pm is very similar to MyPlugin03, so we will explain only the difference
package MyPlugin08::Tags; use strict; sub _hdlr_hello_world_2 { my ($ctx, $args) = @_; my $blog_id = 'blog:' . $ctx->stash('blog_id'); my $plugin = MT->component('MyPlugin08'); my $word_blog = $plugin->get_config_value('word_setting_blog', $blog_id); my $word_sys = $plugin->get_config_value('word_setting_system', 'system'); my $word_default = MT->translate('world'); my $word = $word_blog ? $word_blog : ( $word_sys ? $word_sys : $word_default ); return MT->translate( 'Hello, [_1]!', $word ); } 1;
- We take out of the stash the blog_id, as we need to get blog-level configuration. from it, we built a scope string for the blog, i.e.
"blog:12"
- For getting plugin configuration, we need plugin object. This is by calling
MT->component('MyPlugin08')
- Then we retrieve the configuration, using the plugin’s get_config_value function, that receive the config key, (word_setting_blog and word_setting_system in our case) and the scope-string of this config.
- Setting
$word_default
to be used as default, is the translation of the word “world”- In templates, we use the
<__trans>
tag, but in Perl code we use theMT->translate()
command
- In templates, we use the
- Using the ternary operator, we check the blog settings, system settings and default in the correct order
- Outputting “Hello $word!”
The PHP version have a very similar structure as the Perl version, but uglier because it is PHP, and sometimes needs intermediate steps.
<?php function smarty_function_mthelloworld2($args, &$ctx) { $mt = MT::get_instance(); $blog_id = 'blog:' . $ctx->stash('blog_id'); $cfg = $mt->db()->fetch_plugin_data('MyPlugin08', 'configuration:' . $blog_id); $word_blog = $cfg['word_setting_blog']; $cfg = $mt->db()->fetch_plugin_data('MyPlugin08', 'configuration'); $word_sys = $cfg['word_setting_system']; $word_default = $mt->translate('world'); $word = $word_blog ? $word_blog : ( $word_sys ? $word_sys : $word_default ); return $mt->translate( 'Hello, [_1]!', $word ); } ?>
- Getting MT instance by calling
MT::get_instance()
- Taking the blog_id from the stash, and building blog scope string
- We use
$mt->db()->fetch_plugin_data
to fetch the whole configuration data for this plugin and for this scope, twice. (once for every scope, blog-level and system level)- the we extract the variable that is of interest to us from the fetched configuration data
- Setting
$word_default
to the translated “word”- In templates we use the
<__trans>
tag to translate strings, and in PHP we use the$mt->translate()
command
- In templates we use the
- Using the ternary operator, we check the blog settings, system settings and default in the correct order
- Outputting “Hello $word!”
The PHP system have a L10N system similar to the Perl side, we just need to init it first. the “init..php” files are loaded on PHP startup, and can be used to abuse the system. and load our L10N files.
<?php $lang = substr(strtolower($this->config('DefaultLanguage')), 0, 2); if (!@include_once("lib/l10n_$lang.php")) { include_once("lib/l10n_en.php"); } ?>
The language file to be loaded is set using the first two characters from the DefaultLanguage configuration. If no such file exists, we simply load the English version “l10n_en.php”
これらのコードはプラグインのハンドラ関数に直接書けばよいのですが、複雑なプラグインで関数が増えてくると毎回書かなくてはならないので、初期化時に読み込むようにします。
This PHP plugin does not require English lexicon. so $Lexicon_en
is empty
<?php global $Lexicon_en; $Lexicon_en = array( ); ?>
The Japanese lexicon, stored in $Lexicon_ja
<?php global $Lexicon_ja; $Lexicon_ja = array( 'world' => '世界', 'Hello, [_1]!' => 'こんにちは、[_1]!', ); ?>
$MT_DIR/ |__ plugins/ |__ MyPlugin08/ |__ config.yaml |__ lib/ | |_ MyPlugin08/ | |__ L10N.pm | |_ L10N/ | | |_ en_us.pm | | |_ ja.pm | |_ Tags.pm |__ php/ | |_function.mthelloworld2.php | |_init.MyPlugin08.php | |_lib/ | |_ l10n_en.php | |_ l10n_ja.php |__ t/ | |_00-compile.t | |_01-tags.t |__ tmpl/ |_word_setting_blog.tmpl |_word_setting_system.tmpl
Add the tag immediately below the “alpha-inner” div element
<div id="alpha"> <div id="alpha-inner"> <p><mt:HelloWorld2></p>
Settings combination map:
System Settings | Blog Settings | Output |
Hello, world! | ||
system | Hello, system! | |
blog | Hello, blog! | |
system | blog | Hello, blog! |
Notice that blog settings are overriding the system-level settings. Of course, it is also possible to make the plugin prefer the system-level settings, but this is very rare and special notice in this case is in order.
The method that was presented above is pretty simple: Plain template, with MT populates the values and saving changes.
But what if you need to dynamically change it? populate dynamic values?
We don’t have to use a plain file for the setting – we can have a callback. in the config.yaml put:
blog_config_template: code: $Plugin::module::handler
And that callback will be called with the following parameters:
my ($plugin, $params, $scope) = @_;
The return value of the function will be used as a template for the settings tab, and the $params
hashref will be used as variables for the template. You can either return the template text, or a MT::Template object.
For loading a template from the plugin tmpl directory, use: return $plugin->load_tmpl("filename.tmpl");
After the settings are saved, the following callback is called: (starting MT 5.12)
callbacks: save_config_filter.PluginID: $Plugin::Module::handler
With parameters:
my ( $cb, $plugin, $data ) = @_;
This is a filter callback – meaning that you need to either return 1 to accept the settings, or $plugin->error('...')
to reject them.
Of course, it is possible to config your plugin using environment variable, and bypass the whole configurtion screen stuff. However, once you have users and each have his own special configuration, using configuration screens is better.
Also, it will make life easier to you, and it is just a few minutes of work to setup these screens. so you really should be a masochist not to use them. Or a BOFH. or something.