          --o Programming third party plugins in WIKINDX o--

 ---:::---:::---:::---:::---:::---:::---:::---:::---:::---:::---:::---

There are two types of plugin, menu plugins and in-line plugins. Menu   
plugins are accessed via the WIKINDX menu system while in-line plugins  
appear in the main body of the WIKINDX.                                 

To get your plugins working, a few conditions are required:

 * All modules must go in a folder within the wikindx/components/plugins/      
   directory.                                                          

 * This module folder must have a main PHP file called index.php, a  
   config.php file and a plugintype.txt file -- you add further files  
   as you like.                                                        

 * If the folder is called 'test', the class name in                 
   wikindx/components/plugins/test/index.php must be called test_MODULE.         

 * plugintype.txt should have one line which comprises either of the 
   case-sensitive words 'menu' or 'inline'.                            

 * index.php and config.php must be writeable by the web server      
   user (this allows administrators to manage plugins via the wikindx  
   interface rather than having to edit the files directly).
   
 * config.php should have the public variable $wikindxVersion.  e.g.  public
   $wikindxVersion = 8; From WIKINDX 5.8, compatible plugins are required to
   explicitly state their compatibility with the constant
   WIKINDX_COMPONENTS_COMPATIBLE_VERSION["plugin"]. This is a value that matches
   an internal core version that could be validate for more than one public version.
   In the plugin's config.php, set $wikindxVersion to match
   WIKINDX_COMPONENTS_COMPATIBLE_VERSION["plugin"] in order to state compatibility.
   Incompatible plugins will not load. They will still be present
   and editable in the Admin|Components interface.

The plugin directory may optionally have a file called description.txt  
which may be used as a README providing instructions and credits. The   
first line of this file must be the title of the plugin (and is used to 
display available plugins when administering plugins in WIKINDX) but    
the remaining lines can be whatever you wish.

If you have your message texts in a separate file, then users can opt to 
change language localization as for other parts of WIKINDX.  In the example 
given below, both the file and the class are called 'testMessages_en'.  The 
'_xx' suffix of a new file and class for another language should follow the 
name of a language folder in wikindx/components/languages/. New localization
 files should go into the same plugin folder as the xxx_en file.

For creating or upgrading the db structure of the objects used by yours plugin,
create a folder "dbschema" (lowercase) in your plugin directory. In "dbschema"
create one directory for each database driver supported (lowercase) (currently
mysqli only). In each driver directory, create one directory "full" (lowercase)
and one directory "update" (lowercase).

full and update directories may contain one or more SQL file to run one the first
execution off Wikindx or on upgrade stage, in alphabetical order.

To run the SQL code for a creation call the function
createDbSchema(<plugindirrame>) of the UPDATEDATABASE class.

To run the SQL code for an upgrade call the function
updateDbSchema(<plugindirrame>, <versionnumberstring>) of the UPDATEDATABASE class.

###############################
MENU PLUGINS

Menu plugins have one or more menu items inserted in the WIKINDX menu   
specified in the plugin. These types of plugins are intended for cases  
where the main display table of the WIKINDX is completely dedicated to  
the plugin.                                                             

  * The constructor of a menu plugin must appear as:

   public function __construct($menuInit = FALSE)
   {
      if($menuInit)
      {
         // set $this->menus
         // set $this->authorize
         return;
      }
      // Do something else
   }

  * The constructor must set $this->menus. This is a multi-dimensional  
    public array where you define which menu(s) the module should insert  
    itself into, what is the label for the menu item and which method     
    within our class do we run when the menu option is selected.          

  * The constructor must set the public parameter $this->authorize as   
    either 0 (public readonly access), 1 (login required) or 2 (admin only). 
    This should come from your config.php file (see below). 

  * Both $this-Menus and $this->authorize should only be set when       
    $menuInit is TRUE in which case the constructor should return after   
    they have been set without doing anything else ($menuInit is set      
    automatically to TRUE by the wikindx/core/navigation/MENU class).    

You should also have a config.php file (see the example below) which    
defines the access level for the plugin and in which menu(s) the plugin 
is displayed. These values can be altered through the WIKINDX Admin|Components 
interface and so you must have a public $menus array and a public       
$authorize variable.                                                    

Unless using the basic GLOBALS::buildOutputString() method, you must    
use the templating system that WIKINDX uses and return the template     
string to the calling process. Furthermore, in the interests of         
compatibility and future WIKINDX upgrades, you should use the WIKINDX   
functions where possible.                                               

Constructor parameters could be $db and $vars that are the database object (see   
the wikindx/core/sql/SQL class) and an array of all input values from  
the web browser form or querystring.                                   

$this->authorize controls the display of the module item in the menu
system according to user permissions.

An example of a menu plugin is given below.

###############################
IN-LINE PLUGINS

WIKINDX provides four in-line plugin containers -- these are inserted   
as per the template design and so are dependent for positioning, and    
indeed appearance, upon the template designer.                          

The four containers are:

 * inline1
 * inline2
 * inline3
 * inline4

An example of an in-line plugin is given below.

########################

/*
**********************
*
* MENU plugin example
*
**********************
*/

/**
* EXAMPLE: wikindx/components/plugins/test/config.php
*/
<?php
class test_CONFIG
{
	public $menus = array('plugin2', 'wikindx');
/**
* $authorize
* 
* 0 (public readonly access)
* 1 (login required)
* 2 (admin only)
*/
	public $authorize = 1;
	public $wikindxVersion = 5.8;
}
?>

/*****
*	TEST plugin -- English messages.
*
* '###' is dynamic text to be inserted. e.g. $this->messages->text('helpMePlease', 'method') will replace '###' with 'method' in $this->text['helpMePlease'].
*
*****/
class testMessages_en
{
public $text;

// Constructor
	public function __construct()
	{
		$this->loadMessages();
	}
	public function loadMessages()
	{
		$this->text = array(
/**
* Menu items
*/
		"testSub"	=>		"Test plugin...",
		"menu1"		=>		"Test Command 1",
		"menu2"		=>		"Test Command 2",
		"menuHelp"	=>		"Test plugin Help",
/**
* Other messages
*/
		'heading'	=>	'Test Plugin Example',
		'command1'	=>	'This is command 1',
		'command2'	=>	'This is command 2',
		'noMethod'	=>	'No method was input. Try the Wikindx menu instead',
		'thisModule'	=>	'this module',
		'noHelp'	=>	'No help here. Try ### instead.',
		"helpMePlease"	=>	'The method is ### and here I am.  Sadly, I cannot help.',	
		);
	}
}
?>

/**
* EXAMPLE: wikindx/components/plugins/test/index.php
*/
<?php
class test_MODULE
{
private $db;
private $vars;
private $html;
private $messages;
public $authorize;
public $menus;

// constructor
	public function __construct($menuInit = FALSE)
	{
		include_once(__DIR__ . DIRECTORY_SEPARATOR . "config.php");
		$config = new test_CONFIG();
		include_once("core/messages/PLUGINMESSAGES.php");
// plugin folder name and generic message filename
		$this->messages = new PLUGINMESSAGES('test', 'testMessages');
		$this->session = FACTORY_SESSION::getInstance();
		$this->authorize = $config->authorize;
		if($menuInit)
		{
			$this->makeMenu($config->menus);
			return; // Need do nothing more as this is simply menu initialisation.
		}

		$authorize = FACTORY_AUTHORIZE::getInstance();
		if(!$authorize->isPluginExecutionAuthorised($this->authorize)) // not authorised
			FACTORY_CLOSENOMENU::getInstance(); // die

		$this->db = FACTORY_DB::getInstance();
		$this->vars = GLOBALS::getVars();
	}
/**
* Make the menu items
*
* $this->menus must exist and be public and can be in two forms:
* 1. a simple menu array without hierarchy under one of the available WIKINDX menu headings
* or
* 2. a menu of one submenu or more.
*
* Top level menu labels are: "wikindx", "res", "search", "text", "admin", "plugin1", "plugin2", "plugin3".
* "admin" is only available when logged in as admin, "text" will only show if there are metadata (quotes etc.) 
* and the three 'pluginX' menu trees only show if they are populated.  
* Typically, you will insert a submenu into one of the pluginX menus.
*
* The command to be executed when the user selects that option is the value of each member of the sub array and must be a public method (see below).
* In order to see the menu command when building and testing your menus, you must have declared the command's public method.
* Only in the case of a submenu (see $menu2 below) must the first element of the submenu tree have a FALSE value.
*/
	private function makeMenu($menuArray)
	{
// This first example shows 3 commands appearing simply in two menus -- solely for demonstration purposes
		$menus1 = array(
			$menuArray[1] => // top level menu label
				array(
				$this->messages->text('menu1') 		=>	"command1", // menu item label and command
				$this->messages->text('menu2')		=>	"command2"
				 ),
			$menuArray[0] 	=> // top level menu label
				array($this->messages->text('menuHelp')	=>	"helpMe"),
		);
// This second example shows 3 commands appearing under one menu as a submenu -- the example uses this configuration
// 'xxxpluginSub' must be a unique name otherwise you risk overwriting other plugins
		$menus2 = array(
			$menuArray[0] => 
				array('testpluginSub' => array(
				$this->messages->text('testSub') => FALSE,
				$this->messages->text('menu1')		=>	"command1",
				$this->messages->text('menu2')		=>	"command2",
				$this->messages->text('menuHelp')	=>	"helpMe"
				),
			),
		);
		$this->menus = $menus1;
	}
/**
* The name of this public function must be the same as one of the array values in a sub array of $this->menu
*/
	public function command1()
	{
		GLOBALS::setTplVar('heading', $this->messages->text('heading'));
		$pString = \HTML\p($this->messages->text('command1'));
		if(array_key_exists('method', $this->vars))
			$pString .= $this->{$this->vars['method']}();
		else
			$pString .= $this->messages->text('noMethod');
		GLOBALS::setTplVar('content', $pString);
	}
/**
* The name of this public function must be the same as one of the array values in a sub array of $this->menu
*/
	public function command2()
	{
		GLOBALS::setTplVar('heading', $this->messages->text('heading'));
		GLOBALS::setTplVar('content', $pString);
	}
/**
* The name of this public function must be the same as one of the array values in a sub array of $this->menu
*/
	public function helpMe()
	{
		GLOBALS::setTplVar('heading', $this->messages->text('heading'));
		$link = \HTML\a("link", $this->messages->text('thisModule'), 
			htmlentities("index.php?action=test_command1&method=helpMePlease"));
		$pString = $this->messages->text('noHelp', $link);
		GLOBALS::setTplVar('content', $pString);
	}
/**
* A private method not referenced in the menus
*/
	private function helpMePlease()
	{
		return $this->messages->text('helpMePlease', \HTML\em($this->vars['method']));
	}
}
?>


/*
**********************
*
* IN-LINE plugin example
*
**********************
*/

<?php
/*
* Example of an in-line plugin.  This inserts the phrase 'Hello sailor!' wherever the template 
* designer has placed the 'inline1' container. In the default template that comes with WIKINDX, 
* 'inline1' appears in content.tpl in the paging display and will print 'Hello sailor!' in bold in front 
* of paging links when displaying lists.
*/
class inline1_MODULE
{
// constructor
	public function __construct()
	{
		GLOBALS::setTplVar('inline1', \HTML\strong('Hello sailor!'));
	}
}
?>

---:::---:::---:::---:::---:::---:::---:::---:::---:::---:::---:::---


-- 
Mark Grimshaw-Aagaard
The WIKINDX Team February 2020
sirfragalot@users.sourceforge.net
