How to create a plugin

Discussion in 'Tutorials' started by Mark, Feb 15, 2011.

  1. Mark
    • Staff

    Mark Administrator Staff Member

    Plugin code is regular PHP code, and should be written as if editing the VisioList scripts directly.

    When creating a plugin, you should bear in mind that your code will have access to all variables and classes that are exposed at the point where the hook is placed. You also need to ensure proper security measures are in place.


    A few guidlines to follow when creating plugins.

    1) all plugins must be put in the /plugins/ directory.

    2) The name of the plugin folder should be in CamelCase (aka medial case)
    -example: ThisIsCamelCase

    3) each plugin should start with the following files:

    info.php - A file outlining the name of the plugin, the author name/contact, support URL, and a line for database changes.

    here is a typical plugin info.php file:
    PHP:
    <?php
    //info.php
    // You must give a name for your Plugin.
    $pluginname 'My Amazing Plugin';
    $author 'Me';
    $email 'me@mydomain.com';
    //The url is where the user is to be sent for updates, this must be on the Visiolist Community
    $url 'http://www.visiolist.com/community/YOUR-THREAD-ID';
    // The version # is used for update notifications
    $version '0.1';
    //If ANY changes need to be made to the database set install to 1, else keep 1
    $install 0;
    ?>
    If your plugin makes changes to the database, you will need an install.php file. Here is a sample:

    install.php
    PHP:
    <?php
            $DB
    ->query("ALTER TABLE {$CONF['sql_prefix']}_settings ADD something VARCHAR( 255 ) NULL"__FILE____LINE__);

    ?>
    index.html - a blank file

    now that you have the required files, its time to try running some code via a new plugin. For this example we'll add a simple line of text to our members stats pages.

    if you open sources/details.php you will see the available hook locations:

    PHP:
    eval (PluginManager::getPluginManager ()->pluginHooks ('details_compile_details'));
    this particular plugin comes after all of the stats are compiled, so from here our plugin has access to all variables defined before it. Notice the unique name of this hook location: details_compile_details.

    We want to insert some code in this location, so we create a new file called details_compile_details.php and place it in our plugin/myplugin/ directory.

    in this file we are going to add a "template variable" and a line of simple text, just to illustrate how this works:

    Code:
    $TMPL['myplugin_text'] = 'Hello World!';
    
    great! now all we need to do is make it show up in the template. There are 2 options for this:

    option 1) open stats.html template and add our new template tag {$myplugin_text}
    OR
    option 2) use the template hooks. To use this option we add an additional line to our details_compile_details.php file:

    Code:
    $TMPL['myplugin_text'] = 'Hello World!';
    $TMPL['stats_before_stats'] .= $TMPL['myplugin_text'];
    
    now our line of text will automatically be inserted into your stats pages, just before the stats tables. NO file edits required!

    just to recap, here is how the file structure for our sample plugin might look:

    /plugins/MyPlugin/info.php
    /plugins/MyPlugin/index.html
    /plugins/MyPlugin/stats_compile_stats.php

    if you want to share this plugin, simple zip all of the files/folders into MyPlugin.zip. Now it can uploaded & installed through the admin panel.



    Using Plugin Templates

    one really nice feature of the VisioList plugin system is the plugin templates. Take the example above, instead of having our content/markup defined directly in the PHP we can create a new HTML template for it

    so to use the template option we open our stats_compile_stats.php and use the following code instead of our original 2 lines:
    PHP:
        $TMPL['myplugin_text'] = 'Hello World!';
        
    $TMPL['stats_before_stats'] .= $this->do_plugin_skin('./plugins/MyPlugin','my_line_of_text');
    Next, we create a new file called my_line_of_text.html and upload it to /plugins/MyPlugin/my_line_of_text.html

    inside this new "template" my_line_of_text.html we can put our HTML markup and use our template tags as we would in any other template. for example:

    Code:
    <div class="something">
    <b>This is my plugin text:</b> {$myplugin_text}
    </div>
    
    this will work on any skin, each can have its own CSS definitions!




    Posting your plugin in the forum

    Your post must include the following for Version update notifications

    VERSION 0.1#

    The word version must be in UPPERCASE with a space before the number. Immediately following the number must be a # symbol.

    In your post, give as clear of installation instructions as possible. Also describe what the plugin does, post screenshots where applicable.



    well that was a quick and dirty look at how to create plugins, alter the database using plugin installer, bundle your plugin for distribution, use plugin templates, and use template hooks to make your plugin super easy to install.

    Enjoy and happy coding!
    Last edited by a moderator: Dec 28, 2014
    Basti likes this.
  2. Mark
    • Staff

    Mark Administrator Staff Member

    As of today plugins will now ship with language abstraction. here is a quick look at how this works.

    in your plugin folder, create a file called english.php

    for every phrase your plugin will use, you must create a "language variable" which looks like this:

    PHP:
    $LNG['Twitter_header'] = 'Twitter';
    It is very important for you to prefix your language variables with the name of your plugin, this will prevent other plugins from overwriting your definitions. In the above example we use 'Twitter' as the prefix since this is part of the Twitter plugin. To keep things consistent we recommend you use the exact name of your plugin folder as the prefix.

    here is an example of a full english.php to get you started plugins:

    PHP:
    if (!defined('VISIOLIST')) {
      die(
    "This file cannot be accessed directly.");
    }
     
    // When you make a new translation, fill out the following four variables to
    // get credit for you work.
    $translation 'English';
    $translator_name 'Your Name';
    $translator_email 'Your Email';
    $translator_url 'Your Website URL';
     
    $LNG['Twitter_header'] = 'Twitter';
     
    $LNG['Twitter_admin_no_count'] = 'No Count';
    $LNG['Twitter_admin_post_profile'] = 'New sites advertised on your twitter profile';
    $LNG['Twitter_admin_buttons'] = 'Stats Page Tweet Buttons';
     
    ?>
    in PHP files the language variables are called like $LNG['Twitter_admin_buttons'], while it HTML template files they are used like: {$lng->Twitter_admin_buttons}

    to add translations, simple make a new file called french.php (or whatever the name of your language) and replace the value of each variable with the appropriate translation. By default VisioList will load the english language first, then load the language file as set in the admin settings if it exists.

    enjoy!
  3. reficul

    reficul New Member

    Hello, I try do play with plugin system and I've a question to do.
    There are a way to overlay original code.

    Ex:
    I try to make a plugin that add 2 more custom fields for my site and in join_process_form
    the query is:

    PHP:
    $DB->query("INSERT INTO {$CONF['sql_prefix']}_sites (username, password, url, short_url, title, description, category, banner_url, email, join_date, active, openid, user_ip,owner)
                      VALUES ('
    {$TMPL['username']}', '{$password}', '{$TMPL['url']}', '{$short_url}', '{$TMPL['title']}', '{$TMPL['description']}', '{$TMPL['category']}', '{$TMPL['banner_url']}', '{$TMPL['email']}', '{$join_date}', {$CONF['active_default']}, 0, '{$user_ip}','{$TMPL['username']}')"__FILE____LINE__);
    and I need to add my two custom fields in the insert query, there is a way or I need to make 2 query?
  4. Basti
    • Staff

    Basti Administrator Staff Member

    Join fields via plugin system is quite big if you want it totally complete. see the attached plugin for ip and port fields for join form etc etc. You can use it as a guide to see which files you need and what to put in it

    Regarding your question, its done via a update query, see join_insert_data.php from the attached plugin

    Attached Files:

  5. reficul

    reficul New Member

    Thx Basti, I'm near to share some plugins now.

    I've a problem with custom field, I've setup 2 select box, but when I select the right value it update category field and not my custom field. :confused:
  6. Basti
    • Staff

    Basti Administrator Staff Member

    Properbly gave it the same name attribute? Might help to see the actual code
  7. reficul

    reficul New Member

    This is the code in my plugin_join_fields.html

    HTML:
    <div>
    <span class="{$error_style_language}" style="float: left; margin-right: 2em;">
      <label for="join_language">{$lng->plugin_langsoft_language}</label><br />
      <!-- <input type="text" name="server_ip" size="20" value="{$server_ip}" id="join_server_ip" /> -->
      <Select name="language" size="20" id="join_language">
                <option value="ca"> Catalan </option>
                <option value="cs"> Czech </option>
                <option value="da"> Danish </option>
                <option value="de"> German </option>
                <option Selected value="en"> English </option>
                <option value="es"> Spanish </option>
                <option value="et"> Estonian </option>
                <option value="eu"> Euskara </option>
                <option value="fi"> Finnish </option>
                <option value="fr"> French </option>
                <option value="hr"> Croatian </option>
                <option value="hu"> Hungarian </option>
                <option value="it"> Italian </option>
                <option value="ja"> Japanese </option>
                <option value="ko"> Korean </option>
                <option value="lt"> Lithuanian </option>
                <option value="nl"> Dutch </option>
                <option value="no"> Norwegian </option>
                <option value="pl"> Polish </option>
                <option value="pt"> Portuguese </option>
                <option value="pt_BR"> Portuguese (Brazil) </option>
                <option value="ro"> Romanian </option>
                <option value="ru"> Russian </option>
                <option value="sl"> Slovenian </option>
                <option value="sr"> Serbian </option>
                <option value="sv"> Swedish </option>
                <option value="tr"> Turkish </option>
                <option value="uk"> Ukrainian </option>
          </Select>
      {$error_language}
    </span>
    <span class="{$error_style_software}" style="float: left;">
      <label for="join_software">{$lng->plugin_langsoft_software}</label><br />
      <!-- <input type="text" name="port" size="10" value="{$port}" id="join_port" /> -->
      <Select name="software" size="50" id="join_software">
                <option value="ipb" Selected> Invision Board </option>
                <option value="vB"> vBulletin </option>
                <option value="xF"> XenForo </option>
                <option value="bb"> Burning Board </option>
                <option value="phpBB"> phpBB </option>
                <option value="punBB"> punBB </option>
                <option value="SMF"> SMF </option>
                <option value="other"> Other </option>
          </Select>
      {$error_software}
    </span>
    </div>
    <br class="cb"/><br />
  8. Basti
    • Staff

    Basti Administrator Staff Member

    hmm, ok so i understand it correctly? you select any option from this dropdown, then on submit your custom field doesnt have any value, but the category now use the value youve selected with your new dropdown?

    Then have a look and your join_*.php files

    If you just mean that category box updates its value without you submitting anything. It might be a jquery bug.
    See parabola join_form.html . Somehow jquery´s ui themeroller doesnt like label tags before the select tags. Seems to function correctly only if enclosed by label tags like it is in that file
  9. reficul

    reficul New Member

    It's this the problem.
  10. reficul

    reficul New Member

    This is a video:


    and this is my join_fields.php
    Code:
    $TMPL['join_website_extra'] .= $this->do_plugin_skin('./plugins/LangSoft','langsoft_join_fields');
  11. Basti
    • Staff

    Basti Administrator Staff Member

    Yea i believe this is a jquery bug.
    try setting your select html to this instead and then lets see what happens

    Code:
    <label>my label text:<br />
    <select name=".....
        <options.....
    </select>
    </label>
    also note, no label for="

    Experienced myself odd jquery behavour when not wrapping the label around the select. About 70% sure this might be the issue
  12. reficul

    reficul New Member

    I make this edit
    HTML:
    <div>
    <span class="{$error_style_language}" style="float: left; margin-right: 2em;">
      <label>{$lng->plugin_langsoft_language}<br />
      <Select name="language" size="20" id="join_language">
                <option value="ca"> Catalan </option>
                <option value="cs"> Czech </option>
                <option value="da"> Danish </option>
                <option value="de"> German </option>
                <option Selected value="en"> English </option>
                <option value="es"> Spanish </option>
                <option value="et"> Estonian </option>
                <option value="eu"> Euskara </option>
                <option value="fi"> Finnish </option>
                <option value="fr"> French </option>
                <option value="hr"> Croatian </option>
                <option value="hu"> Hungarian </option>
                <option value="it"> Italian </option>
                <option value="ja"> Japanese </option>
                <option value="ko"> Korean </option>
                <option value="lt"> Lithuanian </option>
                <option value="nl"> Dutch </option>
                <option value="no"> Norwegian </option>
                <option value="pl"> Polish </option>
                <option value="pt"> Portuguese </option>
                <option value="pt_BR"> Portuguese (Brazil) </option>
                <option value="ro"> Romanian </option>
                <option value="ru"> Russian </option>
                <option value="sl"> Slovenian </option>
                <option value="sr"> Serbian </option>
                <option value="sv"> Swedish </option>
                <option value="tr"> Turkish </option>
                <option value="uk"> Ukrainian </option>
          </Select></label>
      {$error_language}
    </span>
    <span class="{$error_style_software}" style="float: left;">
      <label>{$lng->plugin_langsoft_software}<br />
      <Select name="software" size="50" id="join_software">
                <option value="ipb" Selected> Invision Board </option>
                <option value="vB"> vBulletin </option>
                <option value="xF"> XenForo </option>
                <option value="bb"> Burning Board </option>
                <option value="phpBB"> phpBB </option>
                <option value="punBB"> punBB </option>
                <option value="SMF"> SMF </option>
                <option value="other"> Other </option>
          </Select></label>
      {$error_software}
    </span>
    </div>
    <br class="cb"/><br />
    But It doesn't works.
    Also I notice that the option with selected attribute dont show as default option.
  13. Basti
    • Staff

    Basti Administrator Staff Member

    selected="selected" , but properbly wont change anything

    Also a bug within jquery. Nothing to do but wait for a fix, or remove class="uiform" from the form tag in join_form.html to use no jquery enhanced form.

    Ill give this a try myself today, curious if something is wrong in the code or if its a jquery bug as well, maybe doesnt allow multiple selects ( jqueryui on select is really buggy )
  14. Basti
    • Staff

    Basti Administrator Staff Member

    Ok i playedaround a bit with the jquery which handles this and it indeed was a bug. Please unzip the attached file and upload it into "js" folder, replacing the old one.
    Next thing for you to do:
    1. remove the size attribute from your form
    2. label has to be around the select tags like we tried allready
    3. for your option value= you should use full words. These are used to display on pageload

    Attached Files:

  15. reficul

    reficul New Member

    Ok It works. Thank you!!
    I've a warning after submission:

    Schermata 05-2456067 alle 08.48.23.png

    any advice on this?
  16. Basti
    • Staff

    Basti Administrator Staff Member

    it tells you whats wrong, there is an unexpected { in classes.php
    most likely from your plugin which ads to that file.
  17. reficul

    reficul New Member

    uhm, I investigate later, now I need another help! :D
    I learn that to grab a settings value I need to use $CONF['setting_name'] array
    but to grab my custom fields stored in the DB?

    Table VL_sites -> Language and software fields, there are a cached array with this or I need to re-run a query?
  18. Basti
    • Staff

    Basti Administrator Staff Member

    The $CONF var is only for the settings table.

    if you want for example to output the language in stats
    you could do 2 things.

    1. simply write in your skin stats.html / or even in table_top_row.html
    Code:
    {$language}
    Where "language" is the name of the database field
    The core allready fetches all the userdata so its as easy as this

    2. do it via the plugin
    for that you can create stats_build_page.php
    Code:
    $TMPL['user_language'] = $this->do_plugin_skin('./plugins/YourPluginName','stats_language');
    
    next create stats_language.html within your plugin and write {$language} + additional html in there
    then Place {$user_language} into stats.html of your skin where you want it to appear.

    This way you would have it seperated from the main code

    For a simple plugin like this it doesnt really matter how you do it, i personally like to write all within the plugin html files
  19. Andrew

    Andrew New Member

    How would I target a plugin to display only on the homepage?
  20. Mark
    • Staff

    Mark Administrator Staff Member

    PHP:
    if(empty($FORM['a']) && empty($FORM['app']) && empty($FORM['method']) && empty($FORM['cat'])){
    //this must be the front page
    }
    However in 0.9 release we now have the option to use
    PHP:
    if(isset($isfront)) {
    //this must be the front page
    }

Share This Page