<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.dolibarr.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Alograg</id>
	<title>Dolibarr ERP CRM Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.dolibarr.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Alograg"/>
	<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php/Special:Contributions/Alograg"/>
	<updated>2026-10-25T14:06:44Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Module_development&amp;diff=54026</id>
		<title>Module development</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Module_development&amp;diff=54026"/>
		<updated>2022-06-22T09:37:34Z</updated>

		<summary type="html">&lt;p&gt;Alograg: /* Create your module descriptor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN origin interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- You can edit this section but do NOT remove these comments&lt;br /&gt;
     Links below will be automatically replicated on translated pages by PolyglotBot --&amp;gt;&lt;br /&gt;
[[fr:Développement_module]]&lt;br /&gt;
[[es:Desarrollo_de_un_módulo]]&lt;br /&gt;
[[de:Modul_Entwicklung]]&lt;br /&gt;
[[zh:模块开发]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Core]]&lt;br /&gt;
{{TemplateDocDevEn}}&lt;br /&gt;
&lt;br /&gt;
To create a new module/addon for Dolibarr, there is several steps. This tutorial will describe you each of them to build a module to extend Dolibarr features, like one or several of the following :&lt;br /&gt;
&lt;br /&gt;
*Add new tables in database.&lt;br /&gt;
*Add your own menu entries.&lt;br /&gt;
*Add new screens to edit new tables.&lt;br /&gt;
*Add or remove tabs on object view (invoice, product, order, event, ...).&lt;br /&gt;
*Add predefined exports for the internal export tool.&lt;br /&gt;
*Add new information widget in the home page.&lt;br /&gt;
*Add new substitutions variables.&lt;br /&gt;
*Define new permissions.&lt;br /&gt;
*Execute code automatically triggered by a particular Dolibarr action.&lt;br /&gt;
*Insert your code inside Dolibarr hooks positions.&lt;br /&gt;
*Add your numbering rule to generate the reference of objects&lt;br /&gt;
*Add a new document template.&lt;br /&gt;
*Add a new skin.&lt;br /&gt;
&lt;br /&gt;
etc...&lt;br /&gt;
&lt;br /&gt;
Following chapters presents how to do all of this manually with an easy way.&lt;br /&gt;
&lt;br /&gt;
=Module creation with the module builder=&lt;br /&gt;
From Dolibarr 9.0 it is possible to create the main pages of your module with the Module Builder. To activate it:&lt;br /&gt;
&lt;br /&gt;
*Go into the list of module and enable the module &amp;quot;Module Builder&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
[[File:Mod_builder_2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
*Then click on the &amp;quot;bug&amp;quot; image in the top right of screen.&lt;br /&gt;
&lt;br /&gt;
[[File:Mod_builder_3.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Example of Template External Module=&lt;br /&gt;
A good model to start development of external module can be found here : [https://github.com/Dolibarr/dolibarr/tree/develop/htdocs/modulebuilder/template GitHub Dolibarr Module Modèle]&lt;br /&gt;
&lt;br /&gt;
=Create your module=&lt;br /&gt;
==Create a Module descriptor for your Module (required)==&lt;br /&gt;
&#039;&#039;&#039;When it is required&#039;&#039;&#039;: Required as soon as an addon is developed, whatever its goal is (except for adding a skin).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Since Dolibarr 9.0, you should use the ModuleBuilder module provided as a standard module to generate the module descriptor&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Create your module descriptor===&lt;br /&gt;
The first step is to create a file descriptor for the module. &lt;br /&gt;
&lt;br /&gt;
*Create directory &#039;&#039;&#039;/htdocs/&#039;&#039;mymodule&#039;&#039;/core/modules&#039;&#039;&#039;. Then copy the file modMyModule.class.php from the directory &#039;&#039;&#039;htdocs/modulebuilder/template&#039;&#039;&#039; into this directory &#039;&#039;&#039;htdocs/&#039;&#039;mymodule&#039;&#039;/core/modules&#039;&#039;&#039;. Change the name of the file modMyModule.class.php to the name corresponding to the purpose of your module. Name of the file must start with initial &#039;mod&#039; and end with .class.php (for example if you want to give the name &#039;NewName&#039; to this file, then the name should be &#039;modNewName.class.php&#039;).&lt;br /&gt;
&lt;br /&gt;
Next modify the contents of this file as follows:&lt;br /&gt;
&lt;br /&gt;
*Replace all &amp;quot;modMyModule&amp;quot; with a value which corresponds to the purpose of your module. This value must always start with &#039;mod&#039; and contain only alpha characters (again, if the name given to the file was &#039;NewName&#039;, then replace all &amp;quot;modMyModule&amp;quot; with &amp;quot;modNewName&amp;quot;).&lt;br /&gt;
*Change the number in: $this-&amp;gt;numero = 100000 by a number that designates your module id. To avoid conflicts with other modules, you can consult the page that lists already reserved id numbers: [[List of modules id|List of modules id]].&lt;br /&gt;
*Modify any other variables defined in the constructor (see comment in the code skeleton for their meaning).&lt;br /&gt;
&lt;br /&gt;
Your file descriptor for your module is ready. See the next step to activate it.&lt;br /&gt;
&lt;br /&gt;
===Test your descriptor===&lt;br /&gt;
&lt;br /&gt;
Launch Dolibarr and go to page &#039;&#039;&#039;Setup-&amp;gt;module&#039;&#039;&#039;? &lt;br /&gt;
If you set the property version in the module description you should see a new line with your new module and the possibility to activate it or not. If you set the property version to &amp;quot;develop&amp;quot; or &amp;quot;experiental&amp;quot;, to see your module, you must first go into &#039;&#039;&#039;Setup-Others&#039;&#039;&#039; and set MAIN_FEATURES_LEVEL to 1 to see &amp;quot;experimental&amp;quot; modules or 2 to see &amp;quot;development&amp;quot; modules.&lt;br /&gt;
&lt;br /&gt;
==Tree of path for new module files (required)==&lt;br /&gt;
This is how your files must be organized when building a new module (the zip file must also match this rule).&lt;br /&gt;
Note: Only the second line is mandatory.&lt;br /&gt;
&lt;br /&gt;
{{TemplateModuleTreeSimple}}&lt;br /&gt;
&lt;br /&gt;
==Create your SQL tables and the PHP DAO class (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If your module needs to manage data of its own&lt;br /&gt;
&lt;br /&gt;
===Create your .sql file===&lt;br /&gt;
If your module is designed to manage data of its own, which are not available in the standard version of Dolibarr, it is necessary to define SQL tables to store the data.&lt;br /&gt;
&lt;br /&gt;
Scripts for creating tables and loading data by your own module are saved into a subdirectory sql (&#039;&#039;&#039;&amp;quot;mymodule/sql&amp;quot;&#039;&#039;&#039;) of your module. (With ModuleBuilder, the directory and all sql files will be created automatically when you will create a new Object from tab Object).&lt;br /&gt;
&lt;br /&gt;
Then check into your descriptor file, into function &#039;&#039;&#039;init&#039;&#039;&#039; that the line&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;$this-&amp;gt;_load_tables(&#039;/mymodule/sql/&#039;);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
is not commented.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Rules to follow:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Add the files about creating tables commands on the principle of a file &#039;&#039;&#039;llx_matable.sql&#039;&#039;&#039; per table, with a possibly file &#039;&#039;&#039;llx_matable.key.sql&#039;&#039;&#039; (see existing files in &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; for examples).&lt;br /&gt;
*The recommended type and name for SQL fields are defined into page [[Language_and_development_rules#Table_and_fields_structures]].&lt;br /&gt;
*To manage data, you must create a file called &#039;&#039;&#039;data.sql&#039;&#039;&#039; inside directory &#039;&#039;&#039;/mymodule/sql/&#039;&#039;&#039; that contains SQL command to add/edit/delete data.&lt;br /&gt;
*Don&#039;t use the double quote for strings (eg &#039;chaine&#039; not &amp;quot;chaine&amp;quot;) because the double quote have a specific meaning in PostGreSQL&lt;br /&gt;
&lt;br /&gt;
Example of content of a file data.sql&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
 delete from llx_const where name=&#039;MYMODULE_IT_WORKS&#039; and entity=&#039;__ENTITY__&#039;;&lt;br /&gt;
 insert into llx_const (name, value, type, note, visible, entity) values (&#039;MYMODULE_IT_WORKS&#039;,&#039;1&#039;,&#039;chaine&#039;,&#039;A constant vor my module&#039;,1,&#039;__ENTITY__&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Files must be operational for the database mysql. Rem: The files of other databases are not maintained. They will be read and converted on the fly by the driver of the other database.&lt;br /&gt;
&lt;br /&gt;
===Test your .sql files===&lt;br /&gt;
&lt;br /&gt;
Once the files ready, you can return to the page to enable Dolibarr modules and disable the module, drop those tables in the database (if they already exists) and reactivate the module. The tables should be recreated by the activation of the module. If this is not the case, check your scripts by passing them by hand, or check the Dolibarr logs.&lt;br /&gt;
&lt;br /&gt;
===Generate the PHP DAO class===&lt;br /&gt;
The DAO PHP files should have been generated by ModuleBuilder after creating an object.&lt;br /&gt;
&lt;br /&gt;
You can however create them manually by copying existing object however using ModuleBuilder is highly recommended. You should find examples into &#039;&#039;&#039;htdocs/modulebuilder/templates/class/myobject.class.php&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this class, there are already operational CRUD (Create/Read/Update/Delete) methods to perform an insert, a fetch (select), an update, a delete of a table row. Edit the file to use the correct module name, tables and place this file in the class subdirectory of the module. The Module Builder allows you to do this with just a few mouse clicks.&lt;br /&gt;
&lt;br /&gt;
==The tab management (optional)==&lt;br /&gt;
&lt;br /&gt;
===Add or remove your own tabs on object sheets===&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: To add a tab on an object (invoices, orders, proposals, member ...)&lt;br /&gt;
&lt;br /&gt;
To do this go into the file descriptor of module previously created and edit the $this-&amp;gt;tabs array:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
	// Array to add new pages in new tabs or remove existing one&lt;br /&gt;
	$this-&amp;gt;tabs = array(&#039;objecttype:+tabname1:Title1:mylangfile@mymodule:$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;read:/mymodule/mypagetab1.php?id=__ID__&#039;    // To add a new tab identified by code tabname1&lt;br /&gt;
                            &#039;objecttype:+tabname2:Title2:mylangfile@mymodule:$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;read:/mymodule/mypagetab2.php?id=__ID__&#039;,   // To add a new tab identified by code tabname2&lt;br /&gt;
                            &#039;objecttype:-tabname&#039;);                                                     // To remove an existing tab identified by code tabname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The table should contain a list of strings, each string representing a new tab. &lt;br /&gt;
The format of the string consisting of 5 parts separated by &amp;quot;:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*Part 1: The element type (object type) where the tab should appear is a value from the following:&lt;br /&gt;
{{TemplateModuleTabs}}&lt;br /&gt;
&lt;br /&gt;
*Part 2: A code to identify tab to add (start with +) or to remove (start with -)&lt;br /&gt;
*Part 3: The title of the tab. This can be a hard read or better code translation in a file lang.&lt;br /&gt;
*Part 4: The name of the file &amp;quot;*.lang&amp;quot; which contains correspondence between the code translation and language to display. If this name is followed with @mymodule, Dolibarr will search translation file &amp;quot;*.lang&amp;quot; within the module, so htdocs/mymodule/langs/code_CODE/mylangfile.lang, otherwise Dolibarr will look for file htdocs/langs/code_CODE/mylangfile.lang&lt;br /&gt;
*Part 5: A condition to test if tab must be visible. Put 1 to be always visible.&lt;br /&gt;
*Part 6: The URL of the page to display when you click on the tab. The __ID__ string will be replaced automatically by the Id of the element concerned.&lt;br /&gt;
&lt;br /&gt;
To feed the contents of the tab with data from the database, see the next chapter.&lt;br /&gt;
&lt;br /&gt;
In order to get the names  &#039;tabname&#039; of existing tabs, you have to check the names used in the function &#039;product_prepare_head&#039; of the file  &#039;core/lib/module.lib.php&#039; corresponding to section &#039;$head[$h][2]&#039;.&lt;br /&gt;
&lt;br /&gt;
===Show tabs navigation into your own pages===&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: To show all standard tabs of an object (product, tiers, etc.) on your page.&lt;br /&gt;
&lt;br /&gt;
You must follow these steps :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1. Include files you need into your file&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For each object type, there are two files to include with line&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;require_once($url_fichier) ;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is example of files to include (DOL_DOCUMENT_ROOT is often dolibarr/htdocs/) :&lt;br /&gt;
&lt;br /&gt;
*Object thirdparty (thirdparty) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/societe/class/societe.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/core/lib/company.lib.php&lt;br /&gt;
*Object product (product) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/product/class/product.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/core/lib/product.lib.php&lt;br /&gt;
*Object invoice (invoice) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/compta/facture/class/facture.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/core/lib/invoice.lib.php&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. Create and load the object to show into your tab&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create an instance of an object of the correct class and load object from the database by using the fetch method of an object in providing to this method the id you get from URL (ie : /mytab.php?id=1).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$id=GETPOST(&#039;id&#039;,&#039;int&#039;);&lt;br /&gt;
$ref=GETPOST(&#039;ref&#039;,&#039;alpha&#039;);&lt;br /&gt;
$product = new Product($db) ;&lt;br /&gt;
$result = $product-&amp;gt;fetch($id,$ref) ; // Test $result to check the database read is ok&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3. Get a list of all tabs to show for your object type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Use function XXX_prepare_head($obj), where XXX is name of object. This will return an array with all definition of tab entries to show. The parameter to put into this method is the instance of an object you want tabs.&lt;br /&gt;
&lt;br /&gt;
The resulting array has the following structure&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$head        // Array of tabs&lt;br /&gt;
$head[$h]    // Element to describe one tab.&lt;br /&gt;
$head[$h][0] // Url of page to show when you click on tab&lt;br /&gt;
$head[$h][1] // Title of tab&lt;br /&gt;
$head[$h][2] // Code name to identify the tab&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$head = product_prepare_head($product, $user) ; // parameter $user is present for some function anly&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4. show tabs into your page&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Use function dol_fiche_head() to show all tabs defined into array $head returned by XX_prepare_head().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_fiche_head($links, $active=&#039;0&#039;, $title=&#039;&#039;, $notab=0, $picto=&#039;&#039;)&lt;br /&gt;
//$links  // Tableau des onglets, appelé $head plus haut.&lt;br /&gt;
//$active // Onglet actif (mettre le nom de l&#039;onglet défini dans votre fichier de module, ou un nom contenu dans $head[$h][2]). Cet onglet sera mis en surbrillance&lt;br /&gt;
//$title  // Title to show (shown into a special tab that you can&#039;t click)&lt;br /&gt;
//$notab&lt;br /&gt;
//$picto  // Name of image to show into title. Possible values are:&lt;br /&gt;
//            product&lt;br /&gt;
//            service&lt;br /&gt;
//            company&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function will show required tabs and open an html element &#039;&#039;&amp;lt; div class=&amp;quot;&amp;quot; &amp;gt;&#039;&#039; that correspond to the area under the tabs. To close area of a tab, just use &#039;&#039;&amp;lt; /div &amp;gt;&#039;&#039; into your PHP page.&lt;br /&gt;
&lt;br /&gt;
==Create or modify PHP screens (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If the purpose of your module is to add features that require new or modified screens.&lt;br /&gt;
&lt;br /&gt;
===Create a new PHP screen===&lt;br /&gt;
You must then create your PHP pages that will show/edit data from tables using the skeleton templates provided as an example in the directory &#039;&#039;&#039;modulebuilder/myobject_page.php&#039;&#039;&#039; (For the development of a script from the command line, see [[Script development]]).&lt;br /&gt;
&lt;br /&gt;
To create a new user screen, create a subdirectory of &#039;&#039;&#039;htdocs&#039;&#039;&#039; (if not already done) for your module (in &#039;&#039;&#039;htdocs/mymodule&#039;&#039;&#039; for example) to store the pages you will create.&lt;br /&gt;
&lt;br /&gt;
Copy, into that directory, the file &#039;&#039;&#039;myobject_page.phpp&#039;&#039;&#039; that will serve as a starting point for your page file.&lt;br /&gt;
Edit the file to have a correct relative path to the main.inc.php file. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
// Load Dolibarr environment&lt;br /&gt;
$res=0;&lt;br /&gt;
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; ! empty($_SERVER[&amp;quot;CONTEXT_DOCUMENT_ROOT&amp;quot;])) $res=@include($_SERVER[&amp;quot;CONTEXT_DOCUMENT_ROOT&amp;quot;].&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME&lt;br /&gt;
$tmp=empty($_SERVER[&#039;SCRIPT_FILENAME&#039;])?&#039;&#039;:$_SERVER[&#039;SCRIPT_FILENAME&#039;];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1;&lt;br /&gt;
while($i &amp;gt; 0 &amp;amp;&amp;amp; $j &amp;gt; 0 &amp;amp;&amp;amp; isset($tmp[$i]) &amp;amp;&amp;amp; isset($tmp2[$j]) &amp;amp;&amp;amp; $tmp[$i]==$tmp2[$j]) { $i--; $j--; }&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; $i &amp;gt; 0 &amp;amp;&amp;amp; file_exists(substr($tmp, 0, ($i+1)).&amp;quot;/main.inc.php&amp;quot;)) $res=@include(substr($tmp, 0, ($i+1)).&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; $i &amp;gt; 0 &amp;amp;&amp;amp; file_exists(dirname(substr($tmp, 0, ($i+1))).&amp;quot;/main.inc.php&amp;quot;)) $res=@include(dirname(substr($tmp, 0, ($i+1))).&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
// Try main.inc.php using relative path&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../../../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../../../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res) die(&amp;quot;Include of main fails&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
As you can see, there are several tries to load the main.inc.php (or master.inc.php). The goal is to succeed in the most cases as possible. The minimum is 2 lines: one to try to load the master/main.inc.php into the dolibarr root directory and another one to try to load the file to support the case when the module is deployed into the &amp;quot;custom&amp;quot; directory. But you can have more to deal more situation. The provided example should be able to load the file main/master.inc.php in nearly all situation/setups.&lt;br /&gt;
&lt;br /&gt;
Note that you may add more &amp;quot;../&amp;quot; depending on the depth of the file relative to your module directory tree.&lt;br /&gt;
&lt;br /&gt;
It&#039;s in the main.inc.php file that is loaded technical environment variables and permissions. The following variables are objects positioned in this file:&lt;br /&gt;
&lt;br /&gt;
*$user    Object that contains the characteristics of the user + his permissions.&lt;br /&gt;
*$conf    Object that contains Dolibarr configuration.&lt;br /&gt;
*$db      Object that contains an opened connection handler to the database.&lt;br /&gt;
*$langs   Object that contains the user&#039;s language.&lt;br /&gt;
&lt;br /&gt;
Then enter your code to display the page.&lt;br /&gt;
&lt;br /&gt;
*To include a class or library dedicated to the module is done using a Dolibarr function (and not using directly include_once):&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_include_once(&#039;/mymodule/class/myclass.class.php&#039;, &#039;MyClass&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*To include classes provided with Dolibarr, use the following syntax:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
require_once DOL_DOCUMENT_ROOT.&#039;/core/class/doli.class.php&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Add some fields into existing forms===&lt;br /&gt;
You may want to provide a module that adds more fields into forms (input and view) of some elements. &lt;br /&gt;
&lt;br /&gt;
A heavy solution (but not so bad) may be to replace all pages used to create element (this means to disable the &amp;quot;New element&amp;quot; menu entry and adding yours, and disable tab that shows element to replace with a tab that is your own full page (copied/pasted from original) to do same than original page but modified to add your fields and stored added data into your own table). Go to menu [[#Define your entries in the menu (optional)]] and [[#The tab management (optional)]] if this solution suits you (this solution is more powerful since you can change everything you want into the page). &lt;br /&gt;
&lt;br /&gt;
We will describe here another solution, that works only to &amp;quot;add fields&amp;quot; at end of existing fields, using the element &amp;quot;category&amp;quot; as an example but you can convert this tutorial for invoice, proposal ...&lt;br /&gt;
&lt;br /&gt;
*First thing is to add a table, owned by your module, to store the value of new fields. This table will have only one column called &amp;quot;rowid&amp;quot; (will contain the same value than field rowid of element table) + one column for each new field you want to add. Then create a class with CRUD (Create/Read/Update/Delete) methods for this new table. For this two tasks, go back to previous chapter [[#Create your SQL tables and the PHP DAO class]].&lt;br /&gt;
*Next step is to add a hook into your module to add the new fields into the form. See chapter [[Hooks_system#Implement_the_Hook]] for generic documentation to use hooks.&lt;br /&gt;
&lt;br /&gt;
If you follow this tutorial, to be able to add fields into category forms, you must do:&lt;br /&gt;
{{ToComplete}}&lt;br /&gt;
&lt;br /&gt;
===Add/replace part of fields supported by hooks===&lt;br /&gt;
See chapter [[Hooks_system#Implement_the_Hook]] to know how to use Dolibarr existing hooks to add/replace code at Dolibarr hooks place.&lt;br /&gt;
&lt;br /&gt;
===Database access===&lt;br /&gt;
If you need to edit some data in the database inside your own table, use the PHP class generated before.&lt;br /&gt;
&lt;br /&gt;
If you to make access to tables with no dedicated PHP class available, this is always possible (for example if you want to get a list of records with a particular join or filter). In this case, this is a code samples to follow:&lt;br /&gt;
&lt;br /&gt;
To make an insert, update or delete:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$db-&amp;gt;begin();   // Start transaction&lt;br /&gt;
$db-&amp;gt;query(&amp;quot;My SQL request insert, update or delete&amp;quot;);&lt;br /&gt;
$db-&amp;gt;commit();       // Validate transaction&lt;br /&gt;
or $db-&amp;gt;rollback()  // Cancel transaction&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To read:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$resql=$db-&amp;gt;query(&amp;quot;My select request&amp;quot;);&lt;br /&gt;
if ($resql)&lt;br /&gt;
{&lt;br /&gt;
	$num = $db-&amp;gt;num_rows($resql);&lt;br /&gt;
	$i = 0;&lt;br /&gt;
	if ($num)&lt;br /&gt;
	{&lt;br /&gt;
		while ($i &amp;lt; $num)&lt;br /&gt;
		{&lt;br /&gt;
			$obj = $db-&amp;gt;fetch_object($resql);&lt;br /&gt;
			if ($obj)&lt;br /&gt;
			{&lt;br /&gt;
				// You can use here results&lt;br /&gt;
				print $obj-&amp;gt;field1;&lt;br /&gt;
				print $obj-&amp;gt;field2;&lt;br /&gt;
			}&lt;br /&gt;
			$i++;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Define style of your pages===&lt;br /&gt;
To have the look of your own pages to match the Dolibarr theme, it is necessary to use the Dolibarr CSS styles.&lt;br /&gt;
&lt;br /&gt;
You can use for example:&lt;br /&gt;
&lt;br /&gt;
*class=&amp;quot;&#039;&#039;&#039;liste_titre&#039;&#039;&#039;&amp;quot; on tags &#039;&#039;tr&#039;&#039; and &#039;&#039;td&#039;&#039; for the head row of a table.&lt;br /&gt;
*class=&amp;quot;&#039;&#039;&#039;pair&#039;&#039;&#039;&amp;quot; or class=&amp;quot;&#039;&#039;&#039;impair&#039;&#039;&#039;&amp;quot; on tags &#039;&#039;tr&#039;&#039; and &#039;&#039;td&#039;&#039; of other rows of a table.&lt;br /&gt;
*class=&amp;quot;&#039;&#039;&#039;flat&#039;&#039;&#039;&amp;quot; on all input fields (&#039;&#039;input, select, textarea&#039;&#039;...).&lt;br /&gt;
*class=&amp;quot;&#039;&#039;&#039;button&#039;&#039;&#039;&amp;quot; on HTML fields with type &#039;&#039;input type=&amp;quot;submit&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Use the Dolibarr date picker===&lt;br /&gt;
If you want to use the Dolibarr date selector (with its calendar popup) into your pages, use the following line:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $form=new Form($db);&lt;br /&gt;
 $form-&amp;gt;select_date(&#039;&#039;,&#039;mykey&#039;,0,0,0,&amp;quot;myform&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The string mykey will identify the date selector in the form. You must use different values if you use several date selectors in same page.&lt;br /&gt;
The string myform is the name of the FORM in which the selector is included (value found in the form name=&amp;quot;myform&amp;quot; in HTML page).&lt;br /&gt;
This means a date selector must be included necessarily into an html FORM.&lt;br /&gt;
&lt;br /&gt;
To get value after the POST of your form, the command is:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mydate = dol_mktime(12, 0 , 0, $GETPOST(&#039;mykeymonth&#039;, &#039;int&#039;), GETPOST(&#039;mykeyday&#039;, &#039;int&#039;), GETPOST(&#039;mykeyyear&#039;, &#039;int&#039;));&lt;br /&gt;
print strftime(&#039;%A %d %B %Y&#039;, $mydate);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add your own setup page (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If your module needs parameters, which are to be provided by the user, for proper setting up of the module.&lt;br /&gt;
&lt;br /&gt;
===Create your page to edit parameters===&lt;br /&gt;
If your module needs several parameters to be setup, you must create a page to edit options (these options will be saved in the [[Table llx_const|table &#039;&#039;&#039;llx_const&#039;&#039;&#039;]]).&lt;br /&gt;
Create a page named &#039;&#039;&#039;mymodule_setuppage.php&#039;&#039;&#039; that shows a form for possible options to update them into the above-mentioned table.&lt;br /&gt;
It is necessary to take an example from a page of the directory &#039;&#039;&#039;/admin&#039;&#039;&#039; that will show you the way to read/save your parameters.&lt;br /&gt;
Put this PHP page into the directory &#039;&#039;&#039;/admin&#039;&#039;&#039; of your module (e.g. mymodule/admin/mymodule_setuppage.php).&lt;br /&gt;
&lt;br /&gt;
===Modify the descriptor file of your module===&lt;br /&gt;
Then, within the descriptor file of your module, modify the variable &#039;&#039;&#039;config_page_url&#039;&#039;&#039; to set the name of this PHP page.&lt;br /&gt;
If the page is in the directory &#039;&#039;&#039;admin/&#039;&#039;&#039;, then the path is not required, e.g. like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;config_page_url = array(&amp;quot;mymodule_setuppage.php&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
If the page is in the directory &#039;&#039;&#039;mymodule/admin/&#039;&#039;&#039;, then like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;config_page_url = array(&amp;quot;mymodule_setuppage.php@mymodule&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Test your page===&lt;br /&gt;
Go into page &#039;&#039;&#039;Home-&amp;gt;Setup-&amp;gt;Modules&#039;&#039;&#039;, you should see a picture at the end of the line of your module to reach your setup page. Click on it, you should be able to view/edit parameters from your page.&lt;br /&gt;
&lt;br /&gt;
==Define your entries in menu (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If you have created PHP pages, it is necessary that those pages can be reached from menu entries in Dolibarr menu.&lt;br /&gt;
&lt;br /&gt;
===Define your menu entries===&lt;br /&gt;
For this, you must define into the module descriptor, the array this-&amp;gt;menu that declares all menus added by your module.&lt;br /&gt;
This array contains entries that will appear once your module is activated.&lt;br /&gt;
The example module descriptor file &#039;&#039;&#039;modMyModule.class.php&#039;&#039;&#039; contains an example to declare a top menu and also its left menu entries.&lt;br /&gt;
&lt;br /&gt;
This is the example of code to declare your own menu entries in a module descriptor file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
// Main menu entries&lt;br /&gt;
$this-&amp;gt;menu = array();			// List of menus to add&lt;br /&gt;
$r=0;&lt;br /&gt;
&lt;br /&gt;
// Add here entries to declare new menus&lt;br /&gt;
// Example to declare the Top Menu entry:&lt;br /&gt;
$this-&amp;gt;menu[$r]=array(	&#039;fk_menu&#039;=&amp;gt;0,			// Put 0 if this is a top menu&lt;br /&gt;
			&#039;type&#039;=&amp;gt;&#039;top&#039;,			// This is a Top menu entry&lt;br /&gt;
			&#039;titre&#039;=&amp;gt;&#039;MyModule top menu&#039;,&lt;br /&gt;
			&#039;mainmenu&#039;=&amp;gt;&#039;mymodule&#039;,&lt;br /&gt;
			&#039;leftmenu&#039;=&amp;gt;&#039;mymodule&#039;,&lt;br /&gt;
			&#039;url&#039;=&amp;gt;&#039;/mymodule/pagetop.php&#039;,&lt;br /&gt;
			&#039;langs&#039;=&amp;gt;&#039;mylangfile&#039;,	// Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.&lt;br /&gt;
			&#039;position&#039;=&amp;gt;100,&lt;br /&gt;
			&#039;enabled&#039;=&amp;gt;&#039;1&#039;,			// Define condition to show or hide menu entry. Use &#039;$conf-&amp;gt;mymodule-&amp;gt;enabled&#039; if entry must be visible if module is enabled.&lt;br /&gt;
			&#039;perms&#039;=&amp;gt;&#039;1&#039;,			// Use &#039;perms&#039;=&amp;gt;&#039;$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;level1-&amp;gt;level2&#039; if you want your menu with a permission rules&lt;br /&gt;
			&#039;target&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
			&#039;user&#039;=&amp;gt;2);				// 0=Menu for internal users, 1=external users, 2=both&lt;br /&gt;
$r++;&lt;br /&gt;
&lt;br /&gt;
// Example to declare a Left Menu entry:&lt;br /&gt;
$this-&amp;gt;menu[$r]=array(	&#039;fk_menu&#039;=&amp;gt;&#039;fk_mainmenu=xxx&#039;,		    // Use &#039;fk_mainmenu=xxx&#039; or &#039;fk_mainmenu=xxx,fk_leftmenu=yyy&#039; where xxx is mainmenucode and yyy is a leftmenucode of parent menu&lt;br /&gt;
			&#039;type&#039;=&amp;gt;&#039;left&#039;,			        // This is a Left menu entry&lt;br /&gt;
			&#039;titre&#039;=&amp;gt;&#039;MyModule left menu 1&#039;,&lt;br /&gt;
			&#039;mainmenu&#039;=&amp;gt;&#039;xxx&#039;,&lt;br /&gt;
			&#039;leftmenu&#039;=&amp;gt;&#039;yyy&#039;,&lt;br /&gt;
			&#039;url&#039;=&amp;gt;&#039;/mymodule/pagelevel1.php&#039;,&lt;br /&gt;
			&#039;langs&#039;=&amp;gt;&#039;mylangfile&#039;,	// Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.&lt;br /&gt;
			&#039;position&#039;=&amp;gt;100,&lt;br /&gt;
			&#039;enabled&#039;=&amp;gt;&#039;1&#039;,			// Define condition to show or hide menu entry. Use &#039;$conf-&amp;gt;mymodule-&amp;gt;enabled&#039; if entry must be visible if module is enabled.&lt;br /&gt;
			&#039;perms&#039;=&amp;gt;&#039;1&#039;,			// Use &#039;perms&#039;=&amp;gt;&#039;$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;level1-&amp;gt;level2&#039; if you want your menu with a permission rules&lt;br /&gt;
			&#039;target&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
			&#039;user&#039;=&amp;gt;2);				// 0=Menu for internal users,1=external users, 2=both&lt;br /&gt;
$r++;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To show the menu or not depending on a permission, modify property &#039;&#039;&#039;perms&#039;&#039;&#039; in the array. See chapter on permissions later to see how to add permissions.&lt;br /&gt;
&lt;br /&gt;
===Test your menu entries===&lt;br /&gt;
Disable and re-enable your module under the Dolibarr module setup page, menus entries must appear (if property &#039;enabled&#039; is declaration array is ok).&lt;br /&gt;
&lt;br /&gt;
==Add your own permissions (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If you want to add new permissions.&lt;br /&gt;
&lt;br /&gt;
The way to define permissions that will manage your module is done inside the module descriptor created previously.&lt;br /&gt;
Modify line &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;rights_class = &#039;mymodule&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
with correct value for mymodule.&lt;br /&gt;
&lt;br /&gt;
Then you must fill the array $this-&amp;gt;rights with as many entries than different permissions you need to manage.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;rights[$r][0] = 10001;&lt;br /&gt;
$this-&amp;gt;rights[$r][1] = &#039;Label by default of permission&#039;;&lt;br /&gt;
$this-&amp;gt;rights[$r][2] = &#039;r&#039;;&lt;br /&gt;
$this-&amp;gt;rights[$r][3] = 1;&lt;br /&gt;
$this-&amp;gt;rights[$r][4] = &#039;action&#039;;&lt;br /&gt;
$this-&amp;gt;rights[$r][5] = &#039;subaction&#039;;&lt;br /&gt;
$r++;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Into $this-&amp;gt;rights[$r][0], put a permission id not already used (See into menu &#039;&#039;&#039;System info&#039;&#039;&#039; on a working installation of Dolibarr to know list of id already used by standard modules.&lt;br /&gt;
Into $this-&amp;gt;rights[$r][1], put a label by default for permission (This label will be used if no translation can be found into the file &#039;&#039;&#039;admin.lang&#039;&#039;&#039; Translation key should be &amp;quot;Permission10001=My permission Label&amp;quot;).&lt;br /&gt;
Into $this-&amp;gt;rights[$r][2], types of the permission. There are three type of permission, &#039;r&#039; for read, list or expert permission, &#039;w&#039; for write or update permission and &#039;d&#039; for delete permission.&lt;br /&gt;
Into $this-&amp;gt;rights[$r][3], put 1 if this permission must be granted automatically by default to any newly created user.&lt;br /&gt;
Into $this-&amp;gt;rights[$r][4] and $this-&amp;gt;rights[$r][5], put an action and subaction string without spaces. You will be able to test if a user has the permission in your PHP source code with the sequence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;action-&amp;gt;subaction) ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Define your own box (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If your module needs to provide one or several new boxes to show on home page.&lt;br /&gt;
&lt;br /&gt;
===Define your box===&lt;br /&gt;
For this, modify the array $this-&amp;gt;boxes into the module descriptor file.&lt;br /&gt;
All you have to do is to add 2 lines for each box file you will create into directory &#039;&#039;&#039;htdocs/mymodule/core/boxes&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example:&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;boxes[0][&#039;file&#039;]=&#039;mybox0.php@mymodule&#039;&lt;br /&gt;
$this-&amp;gt;boxes[0][&#039;note&#039;]=&#039;My box 0&#039;&lt;br /&gt;
 ...&lt;br /&gt;
$this-&amp;gt;boxes[n][&#039;file&#039;]=&#039;myboxn.php@mymodule&#039;&lt;br /&gt;
$this-&amp;gt;boxes[n][&#039;note&#039;]=&#039;My box n&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then create files &#039;&#039;&#039;htdocs/mymodule/core/boxes/mybox0.php&#039;&#039;&#039;, &#039;&#039;&#039;htdocs/mymodule/core/boxes/mybox1.php&#039;&#039;&#039;... by copying an example from an existing box file (found into directory &#039;&#039;&#039;htdocs/core/boxes&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
===Test if your box is detected by Dolibarr===&lt;br /&gt;
Disable and enabled module.&lt;br /&gt;
&lt;br /&gt;
Go into menu &#039;&#039;&#039;Home - Setup - Boxes&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Your boxes must appear in the list of boxes you can activate. Activate the box and go on the home page to see if the box is showing correctly.&lt;br /&gt;
&lt;br /&gt;
==Define your own export (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If your module provides new predefined database export profiles (for its own tables or for already existing tables of another module).&lt;br /&gt;
&lt;br /&gt;
===Define export===&lt;br /&gt;
For this uncomment and modify arrays $this-&amp;gt;export_xxx in your module descriptor file.&lt;br /&gt;
&lt;br /&gt;
===Test your export===&lt;br /&gt;
Go into menu Tools -&amp;gt; Export. Your export will appear in the list of available predefined exports (if your module is enabled).&lt;br /&gt;
Choose it, you must see a list of all possible fields defined in the export arrays.&lt;br /&gt;
Choose on field and try to build an export file. If ok, try again with all fields.&lt;br /&gt;
&lt;br /&gt;
==Define your CSS styles (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If in your PHP pages, you use class styles that are not defined inside Dolibarr themes CSS (not recommanded).&lt;br /&gt;
&lt;br /&gt;
===Create and declare your style sheet===&lt;br /&gt;
Create a style sheet CSS named &#039;&#039;&#039;mymodule.css&#039;&#039;&#039; or &#039;&#039;&#039;mymodule.css.php&#039;&#039;&#039; and put it into directory &#039;&#039;&#039;htdocs/mymodule&#039;&#039;&#039;. You can have several CSS files per module.&lt;br /&gt;
Remember it&#039;s better to use existing styles already available by default into Dolibarr (The CSS file used by Dolibarr is file &#039;&#039;&#039;themes/mytheme/&#039;&#039;themename&#039;&#039;.css.php&#039;&#039;&#039;. Create your own CSS files only if you need absolutely to add not already existing styles.&lt;br /&gt;
&lt;br /&gt;
Once your style sheets are ready, declare them into your module descriptor file by modifying the property &#039;&#039;&#039;$this-&amp;gt;modules_parts&#039;&#039;&#039;.&lt;br /&gt;
Value to put here must be an array of relative URLs to your CSS files.&lt;br /&gt;
For example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;module_parts = array(&#039;css&#039; =&amp;gt; array(&#039;/mymodule/css/mymodule.css.php&#039;,&#039;/mymodule/css/myother.css&#039;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Test your style sheet===&lt;br /&gt;
Disable and enable your module.&lt;br /&gt;
&lt;br /&gt;
Go on the home page (index.php). Show the HTML source of the page.&lt;br /&gt;
&lt;br /&gt;
You should see into the HTML header, a line that declares your style sheet.&lt;br /&gt;
&lt;br /&gt;
==Add your Javascript functions (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If in your PHP pages, you use javascript functions not available in Dolibarr (in file lib_head.js)&lt;br /&gt;
&lt;br /&gt;
If you need to use your own javascript functions inside your PHP pages, it is necessary to have your functions, defined into your javascript file &#039;&#039;&#039;htdocs/mymodule/js/mymodule.js&#039;&#039;&#039;, included into the HTML HEAD section.&lt;br /&gt;
To ask Dolibarr that forge this header to include your own javascript file, you must just provide it to the llxHeader() function called by your page.&lt;br /&gt;
&lt;br /&gt;
Example for page /htdocs/mymodule/mypage.php :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$morejs=array(&amp;quot;/mymodule/js/mymodule.js&amp;quot;);&lt;br /&gt;
llxHeader(&#039;&#039;,&#039;Titre&#039;,&#039;&#039;,&#039;&#039;,&#039;&#039;,&#039;&#039;,$morejs,&#039;&#039;,0,0); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Run your own code on any Dolibarr event (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If you want to execute your own code once a common Dolibarr event has occurred (example: I want to update a table in my module when an invoice is created into Dolibarr), you must create a &#039;&#039;&#039;triggers&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
See also [[Interfaces_Dolibarr_toward_foreign_systems]]&lt;br /&gt;
and [[Interfaces_from_foreign_systems_toward_Dolibarr]]&lt;br /&gt;
&lt;br /&gt;
==Insert your code inside Dolibarr hooks positions (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: When you want to add code or replace Dolibarr code into another situation than a business event (See the previous chapter for adding code during a business event).&lt;br /&gt;
&lt;br /&gt;
See page [[Hooks_system]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Add your own numbering rules==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: When you need a new rule for generated ref of elements that are not covered by existing rules.&lt;br /&gt;
&lt;br /&gt;
See page [[Create numbering module]].&lt;br /&gt;
&lt;br /&gt;
==Add your document template (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: When you want to personalized your own generated PDF or ODT documents.&lt;br /&gt;
&lt;br /&gt;
Note: To add this feature you don&#039;t need to create a module descriptor.&lt;br /&gt;
&lt;br /&gt;
Documentation to add your own template is available on page [[Create_a_PDF_document_template]] or [[Create_an_ODT_document_template]].&lt;br /&gt;
&lt;br /&gt;
==Add your skin (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: When you want to personalized your colors/fonts/images.&lt;br /&gt;
&lt;br /&gt;
Note: To add this feature you don&#039;t need to create a module descriptor.&lt;br /&gt;
&lt;br /&gt;
To add your own skin, read page [[Skins]].&lt;br /&gt;
&lt;br /&gt;
=Some coding rules and predefined functions=&lt;br /&gt;
The coding rules to be followed are defined in the [[Developer documentation]], under section &amp;quot;General Information - Language and standards development&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
A lot of predefined features for developers are also available and described into page [[Developer documentation]] under section &amp;quot;Technical components of Dolibarr&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Create a package to distribute and install your module=&lt;br /&gt;
This process must be used to generate a package to submit it on the http://www.dolistore.com marketplace.&lt;br /&gt;
But you can use it to have a package easy to distribute on your own network.&lt;br /&gt;
&lt;br /&gt;
*Go into the directory &#039;&#039;&#039;/build&#039;&#039;&#039; and copy the file &#039;&#039;&#039;makepack-dolibarrmodules.conf&#039;&#039;&#039; into &#039;&#039;&#039;makepack-mymodule.conf&#039;&#039;&#039;. Warning, this directory may not be provided in some packages of stable versions. If so, it can be retrieved from the snapshot available for download on the Dolibarr website in area &amp;quot;Development version&amp;quot; (taken in this case the whole build directory which is autonomous and independent directory).&lt;br /&gt;
&lt;br /&gt;
Edit this file to add a list of file names for all new files you created for your module (module descriptor, new sql tables files, php page, images, etc...)&lt;br /&gt;
&lt;br /&gt;
*Run the script via Perl (need the Perl version 5.0 or later):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
perl makepack-dolibarrmodule.pl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The script asks you the name of your module, its major and minor version. A file &#039;&#039;&#039;mymodule.zip &#039;&#039;&#039; will then be manufactured containing your module ready to be deployed.&lt;br /&gt;
&lt;br /&gt;
*The person who receives your module must then place the file in the root directory of a Dolibarr installation and perform the command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar -xvf mymodule.zip&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If you want your module to be public, you can submit it (the zip file) on Dolibarr marketplace website: {{LinkToPluginDownload}} (you must create an account first and be logged to use the link &amp;quot;Submit a module/product&amp;quot;).&lt;br /&gt;
**If your module was built correctly, the file will be validated later.&lt;br /&gt;
**If quality is enough and license permits it, the code might be added inside main Dolibarr sources (except if you disagree for that).&lt;br /&gt;
&lt;br /&gt;
=Enabling/activation condition of external module on DoliStore=&lt;br /&gt;
&lt;br /&gt;
See [[Module_Dolistore_Validation_Rules|Validation Rules]]&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Alograg</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Desarrollo_de_un_m%C3%B3dulo&amp;diff=54025</id>
		<title>Desarrollo de un módulo</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Desarrollo_de_un_m%C3%B3dulo&amp;diff=54025"/>
		<updated>2022-06-22T09:30:10Z</updated>

		<summary type="html">&lt;p&gt;Alograg: /*  Crear un descriptor de Módulo (obligatorio) */ Ruta a laplantilla&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Module_development --&amp;gt;&lt;br /&gt;
[[en:Module_development]]&lt;br /&gt;
[[fr:Développement_module]]&lt;br /&gt;
[[de:Modul_Entwicklung]]&lt;br /&gt;
[[zh:模块开发]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Básico]]&lt;br /&gt;
{{TemplateDocDesarrollo}}&lt;br /&gt;
Para crear un nuevo módulo hay distintas fases a seguir. Este tutorial tiene como meta describir cada una de estas fases con el fin de ayudar a comprender las posibilidades de Dolibarr, como por ejemplo añadir una o varias de las siguientes funcionalidades:&lt;br /&gt;
&lt;br /&gt;
*Añadir nuevas tablas a la base de datos.&lt;br /&gt;
*Añadir sus propias entradas en los menús.&lt;br /&gt;
*Añadir pantallas de edición/consulta de nuevas tablas.&lt;br /&gt;
*Añadir o eliminar pestañas en las páginas de vista/edición de objetos (factura, producto, pedido, evento, etc.)&lt;br /&gt;
*Añadir exportaciones predefinidas a la función “Exportar”.&lt;br /&gt;
*Añadir variables de substitución&lt;br /&gt;
*Añadir nuevas cajas a la página de inicio.&lt;br /&gt;
*Definir nuevos permisos.&lt;br /&gt;
*Activar código automático sobre una acción particular de Dolibarr.&lt;br /&gt;
*Insertar nuestro código mediante los hooks de Dolibarr&lt;br /&gt;
*Añadir un módulo de numeración&lt;br /&gt;
*Añadir un modelo de documento&lt;br /&gt;
*Añadir un nuevo tema&lt;br /&gt;
&lt;br /&gt;
etc.&lt;br /&gt;
&lt;br /&gt;
=[[File:Art.png]] Crear un módulo=&lt;br /&gt;
Los capítulos siguientes describen las acciones a realizar para crear un módulo Dolibarr. Los primeros capítulos son obligatorios cualquiera que sea la vocación de los módulos, los siguientes dependerán de lo que deba hacer el módulo&lt;br /&gt;
&lt;br /&gt;
==[[File:Art.png]] Crear un descriptor de Módulo (obligatorio)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo&#039;&#039;&#039;: Obligatorio cada vez que se desarrolla una extensión, cualquiera que sea su finalidad.&lt;br /&gt;
&lt;br /&gt;
===Crear su descriptor===&lt;br /&gt;
La primera fase es la de crear un fichero descriptor del módulo. Para ello:&lt;br /&gt;
&lt;br /&gt;
*Crear el directorio &#039;&#039;&#039;/htdocs/&#039;&#039;mimodulo&#039;&#039;/core/modules&#039;&#039;&#039;. Seguidamente ir al directorio &#039;&#039;&#039;htdocs/modulebuilder/template&#039;&#039;&#039; y copiar el archivo modMyModule.class.php en el directorio &#039;&#039;&#039;htdocs/&#039;&#039;mimodulo&#039;&#039;/core/modules&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A continuación, modificar el contenido del archivo, reemplazando:&lt;br /&gt;
&lt;br /&gt;
*los &amp;quot;modMyModule&amp;quot; por un valor que corresponda a la finalidad de su módulo. Este valor debe siempre comenzar por mod.&lt;br /&gt;
&lt;br /&gt;
ATENCIÓN: El MiModulo debe estar compuesto por una serie de caracteres, siendo los únicos permitidos [A-Za-z_] con longuitud max de MyModule de 12 caracteres.&lt;br /&gt;
&lt;br /&gt;
*$this-&amp;gt;numero = 100000 por un número de módulo que esté libre. Ver [[List of modules id|Listado de los id de módulos]]&lt;br /&gt;
*Modificar eventualmente otras variables definidas por los desarrolladores (ver el comentario en el código del esqueleto para ver su significado)&lt;br /&gt;
*Crear el directorio /htdocs/mimodulo/&lt;br /&gt;
&lt;br /&gt;
Ahora su fichero descriptor está configurado.&lt;br /&gt;
&lt;br /&gt;
===Probar su descriptor===&lt;br /&gt;
Ejecute Dolibarr y vaya a la página &amp;quot;Configuración &amp;gt; Módulo&amp;quot;. Debería aparecer una nueva línea con su nuevo módulo y la posibilidad de activarlo o no (eche un vistazo a todas las pestañas de cada categoría para encontrarlo). Es el valor $this-&amp;gt;special el que determina en qué pestaña se encuentra su módulo.&lt;br /&gt;
&lt;br /&gt;
==[[File:Art.png]] Árbol de un nuevo módulo==&lt;br /&gt;
Crear un directorio &#039;mimodulo&#039; que contendrá los archivos del módulo. Este directorio debe de estar en el directorio &#039;&#039;&#039;htdocs&#039;&#039;&#039; y contendrá los siguientes subdirectorios:&lt;br /&gt;
{{TemplateModuleTreeSimple}}&lt;br /&gt;
&lt;br /&gt;
==[[File:Art.png]] Crear sus tablas SQL y la clase PHP con los métodos de acceso (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si su módulo necesita gestionar sus propios datos.&lt;br /&gt;
&lt;br /&gt;
===Crear sus ficheros .sql===&lt;br /&gt;
Si su módulo de verdad requiere administrar datos que no existen en la base de datos en la versión estándar de Dolibarr, será necesario definir ciertas tablas SQL para registrar esos datos.&lt;br /&gt;
&lt;br /&gt;
Revisa que en el descriptor de archivo (mymodule/core/modules/mymodule.class.php) la línea&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;_load_tables(&#039;/mymodule/sql/&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
esté descomentada y correctamente configurada.&lt;br /&gt;
&lt;br /&gt;
Cree un subdirectorio sql en el directorio de su módulo (por ejemplo, htdocs/mimodulo/sql), con el fin de colocar los scripts sql que va a crear. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Regla a respetar:&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
*Agregue los archivos de orden de creación de sus tablas siguiendo el principio de un fichero &#039;&#039;&#039;llx_mitabla.sql&#039;&#039; por tabla, eventualmente acompañado del archivo &#039;&#039;&#039;&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;llx_mitabla.key.sql&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039; (ver los archivos existentes en &#039;&#039;install/mysql/tables&#039;&#039;, para tomar ejemplo).&lt;br /&gt;
*The recommended type and name for SQL fields are defined into page [[Language_and_development_rules#Table_and_fields_structures]].&lt;br /&gt;
*En términos de orden de gestión de datos, todos deben estar en un archivo llamado &#039;&#039;&#039;data.sql&#039;&#039;&#039; situado en la misma carpeta &#039;&#039;&#039;/mimodulo/sql/&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ejemplo de contenido de un fichero data.sql&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
 delete from llx_const where name=&#039;MYMODULE_IT_WORKS&#039; and entity=&#039;__ENTITY__&#039;;&lt;br /&gt;
 insert into llx_const (name, value, type, note, visible, entity) values (&#039;MYMODULE_IT_WORKS&#039;,&#039;1&#039;,&#039;chaine&#039;,&#039;A constant vor my module&#039;,1,&#039;__ENTITY__&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Las órdenes SQL de los archivos deben de ser operacionales para la base de datos &#039;&#039;&#039;mysql&#039;&#039;&#039;.&lt;br /&gt;
Nota: Los archivos de otras bases de datos no se mantienen. Se leen y se convierten al vuelo por el driver de la base de datos.&lt;br /&gt;
&lt;br /&gt;
===Probar su archivo .sql===&lt;br /&gt;
Una vez que los archivos estén listos, puede volver a Dolibarr para desactivar el módulo, eliminar las tablas de la base de datos y reactivar el módulo. Las tablas deben ser recreadas por la activación del módulo. Si no es así, verifique sus scripts o consulte los logs Dolibarr.&lt;br /&gt;
&lt;br /&gt;
===Generar la clase PHP de acceso (DAO)===&lt;br /&gt;
Una vez que sus tablas estén creadas en la base de datos, vaya al directorio &#039;&#039;&#039;dev/skeletons&#039;&#039;&#039;, copie el archivo &#039;&#039;&#039;build_class_from_table.php&#039;&#039;&#039; en el directorio sql/ de su módulo module, y ejecute el script&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 php build_class_from_table.php nombretabla&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nota: Si el comando no funciona, intente con php-cli en lugar de php.&lt;br /&gt;
&lt;br /&gt;
Esto genera un archivo &#039;&#039;&#039;out.nombretabla.class.php&#039;&#039;&#039; que contiene la clase de gestión de la tabla “nombretabla”. En esta clase se encuentran los métodos CRUD (Create/Read/Update/Delete) ya operativos para hacer un &#039;&#039;insert&#039;&#039;, un &#039;&#039;fetch&#039;&#039; (&#039;&#039;select&#039;&#039;), un &#039;&#039;update&#039;&#039;, y un &#039;&#039;delete&#039;&#039; de una línea de la tabla. Suprima justo el &amp;quot;out&amp;quot; del nombre del archivo y póngalo en un subdirectorio de &#039;&#039;&#039;htdocs&#039;&#039;&#039; propio en su módulo (Por ejemplo en &#039;&#039;&#039;htdocs/mimodulo&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Un archivo &#039;&#039;&#039;out.nombretabla_script.php&#039;&#039;&#039; se genera igualmente y contiene un ejemplo de código para utilizar la clase para cada uno de los cuatro métodos CRUD.&lt;br /&gt;
&lt;br /&gt;
==Visualización de pestañas (opcional)==&lt;br /&gt;
&lt;br /&gt;
===Añadir o eliminar pestañas en las fichas entidad===&lt;br /&gt;
&#039;&#039;&#039;Cuándo&#039;&#039;&#039; : Para añadir su propia pestaña en las pestañas estándar de una ficha entidad (factura, pedido, presupuesto, miembro...)&lt;br /&gt;
&lt;br /&gt;
Para ello, vaya al archivo descriptor del módulo creado anteriormente y modifique la tabla $this-&amp;gt;tabs:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
	// Array to add new pages in new tabs or remove existing one&lt;br /&gt;
	$this-&amp;gt;tabs = array(&#039;objecttype:+tabname1:Title1:@mymodule:/mymodule/mynewtab1.php?id=__ID__&#039;,  // To add a new tab identified by code tabname1&lt;br /&gt;
                            &#039;objecttype:+tabname2:Title2:@mymodule:/mymodule/mynewtab2.php?id=__ID__&#039;,  // To add another new tab identified by code tabname2&lt;br /&gt;
                            &#039;objecttype:-tabname&#039;);                                                     // To remove an existing tab identified by code tabname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La tabla debe contener una lista de cadena, cada cadena representa una nueva pestaña.&lt;br /&gt;
El formato de la cadena se compone de 4 partes separadas por &amp;quot;:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*Parte 1: El código de la entidad (objecttype) en la que debe aparecer la pestaña siendo el valor de ella misma:&lt;br /&gt;
{{TemplateModuleTabs-es}}&lt;br /&gt;
&lt;br /&gt;
*Parte 2: El título de la pestaña. Puede ser una etiqueta directa o mejor un código de traducción de un archivo lang.&lt;br /&gt;
*Parte 3: El nombre del archivo .lang (sin la extensión .lang) que contiene la correspondencia entre el código de traducción y la etiqueta a mostrar. Si el nombre empieza con @, Dolibarr buscará el archivo en el directorio lang del propio módulo, es decir, htdocs/mimodulo/langs/code_CODE/mimodulo.lang, de lo contrario Dolibarr buscará el archivo de en /langs/code_CODE/mimodulo.lang&lt;br /&gt;
&lt;br /&gt;
*Parte 4: La url de la página a mostrar cuando se haga click en las pestaña. La cadena __ID__ será reemplazada automáticamente por el Id de la entidad concerniente.&lt;br /&gt;
&lt;br /&gt;
Para alimentar el contenido de la pestaña con los datos de la base de datos, vea el capítulo siguiente.&lt;br /&gt;
&lt;br /&gt;
===Añadir pestañas de una ficha entidad en su propia página===&lt;br /&gt;
&#039;&#039;&#039;Cuándo&#039;&#039;&#039; : Para mostrar las pestañas estándar de ficha entidad (producto, tercero, etc.) en su propia pestaña de una entidad.&lt;br /&gt;
&lt;br /&gt;
Hay que hacer lo siguiente :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1. Incluir los archivos que definen las funciones útiles dentro de sus archivos&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Para cada ficha entidad, hay que incluir dos archivos con la instrucción&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;require_once($url_fichier) ;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aquí le mostramos la lista de estos archivos (DOL_DOCUMENT_ROOT correspondiente al directorio &#039;&#039;&#039;dolibarr/htdocs/&#039;&#039;&#039;) :&lt;br /&gt;
&lt;br /&gt;
*Entidad tercero (thirdparty) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/societe/class/societe.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/core/lib/company.lib.php&lt;br /&gt;
*Entidad producto (product) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/product.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/lib/product.lib.php&lt;br /&gt;
*Entidad factura (invoice) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/facture.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/lib/invoice.lib.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. Crear y cargar el objeto a mostrar en su pestaña&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Crear el objeto de la clase deseada, y recuperar los datos del objeto a partir de la base de datos. Para ello deberá utilizar las funciones fetch() de la clase correspondiente, pasando el parámetro del indentificador del objeto que recupera desde la url (ej : /mononglet.php?id=1).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ejemplo :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$id=$_GET[&amp;quot;id&amp;quot;];&lt;br /&gt;
$product = new Product($db) ;&lt;br /&gt;
$result = $product-&amp;gt;fetch($id) ; //Tester $result pour vérifier que l&#039;accès à la base s&#039;est bien passé&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3. Recuperar la lista de pestañas correspondientes a la entidad seleccionada&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Usar la función XXX_prepare_head($obj), donde XXX es le nombre de la entidad, para crear una tabla que contiene las definiciones de las pestañas a mostrar. El parámetro a pasar es el objeto del que desea mostrar las pestañas.&lt;br /&gt;
&lt;br /&gt;
La tabla devuelta se compone de la siguiente manera :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$head        // Tableau des onglets&lt;br /&gt;
$head[$h]    // Élément décrivant un onglet. Il y aura autant de $h que d&#039;onglets à afficher&lt;br /&gt;
$head[$h][0] // Url de la page affichée quand on clique sur l&#039;onglet&lt;br /&gt;
$head[$h][1] // Titre de l&#039;ongLet&lt;br /&gt;
$head[$h][2] // Code de l&#039;onglet, à utiliser pour choisir quel onglet sera &#039;actif&#039; (voir paragraphe suivant)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ejemplo :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$head = product_prepare_head($product, $user) ; //le paramètre $user n&#039;est pas présent sur certaines fonctions&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4. Mostrar las pestañas en su pestaña&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Use la función dol_fiche_head() que muestra las pestañas contenidas en la tabla $head devuelta por XX_prepare_head().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_fiche_head($links, $active=&#039;0&#039;, $title=&#039;&#039;, $notab=0, $picto=&#039;&#039;)&lt;br /&gt;
$links  // Tableau des onglets, appelé $head plus haut.&lt;br /&gt;
$active // Onglet actif (mettre le nom de l&#039;onglet défini dans votre fichier de module, ou un nom contenu dans $head[$h][2]). Cet onglet sera mis en surbrillance&lt;br /&gt;
$title  // ?&lt;br /&gt;
$notab  // Mettre ce paramètre à 1 permet de ne pas afficher de zone bleue en dessous des onglets.&lt;br /&gt;
$picto  // Nom de l&#039;image à utiliser au début de la barre des onglet. Les choix suivant sont possibles :&lt;br /&gt;
//            product&lt;br /&gt;
//            service&lt;br /&gt;
//            company&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta función muestra las pestañas deseadas y abre un elemento &#039;&#039;&amp;lt; div class=&amp;quot;&amp;quot; &amp;gt;&#039;&#039; que corresponde a la zona azul bajo las pestañas (si el parámetro $notab = 0). Para cerrar la zona azul, simplemente cierre el elemento &#039;&#039;&amp;lt; /div &amp;gt;&#039;&#039; en el código PHP.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Nota&#039;&#039;:&lt;br /&gt;
Para más detalles, consulte la [http://www.dolibarr.fr/doxygen/ documentación Doxygen] o directamente el código de Dolibarr.&lt;br /&gt;
&lt;br /&gt;
==Crear sus páginas pantalla PHP (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si su módulo consiste en añadir funcionalidades que necesitan nuevas pantallas.&lt;br /&gt;
&lt;br /&gt;
===Crear una página pantalla PHP===&lt;br /&gt;
Debe crear a continuación pantallas PHP que se basen en los datos de sus tablas utilizando los esqueletos como ejemplo del directorio &#039;&#039;&#039;modulebuilder&#039;&#039;&#039;. (Para el desarrollo de un script en línea de comandos, ver [[Desarrollo de scripts]]).&lt;br /&gt;
&lt;br /&gt;
Para crear una nueva página de usuario, cree un subdirectorio de &#039;&#039;&#039;htdocs&#039;&#039;&#039; (si es que no existe ya) propio en su módulo (En &#039;&#039;&#039;htdocs/mimodulo&#039;&#039;&#039;, por ejemplo), con el fin de ubicar en él las páginas que va a crear.&lt;br /&gt;
&lt;br /&gt;
Copie allí el archivo &#039;&#039;&#039;myobject_page.php&#039;&#039;&#039;, que va a servir de punto de partida a su página. Modifique el archivo para que la ruta relativa de&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
// Load Dolibarr environment&lt;br /&gt;
$res=0;&lt;br /&gt;
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; ! empty($_SERVER[&amp;quot;CONTEXT_DOCUMENT_ROOT&amp;quot;])) $res=@include($_SERVER[&amp;quot;CONTEXT_DOCUMENT_ROOT&amp;quot;].&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME&lt;br /&gt;
$tmp=empty($_SERVER[&#039;SCRIPT_FILENAME&#039;])?&#039;&#039;:$_SERVER[&#039;SCRIPT_FILENAME&#039;];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1;&lt;br /&gt;
while($i &amp;gt; 0 &amp;amp;&amp;amp; $j &amp;gt; 0 &amp;amp;&amp;amp; isset($tmp[$i]) &amp;amp;&amp;amp; isset($tmp2[$j]) &amp;amp;&amp;amp; $tmp[$i]==$tmp2[$j]) { $i--; $j--; }&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; $i &amp;gt; 0 &amp;amp;&amp;amp; file_exists(substr($tmp, 0, ($i+1)).&amp;quot;/main.inc.php&amp;quot;)) $res=@include(substr($tmp, 0, ($i+1)).&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; $i &amp;gt; 0 &amp;amp;&amp;amp; file_exists(dirname(substr($tmp, 0, ($i+1))).&amp;quot;/main.inc.php&amp;quot;)) $res=@include(dirname(substr($tmp, 0, ($i+1))).&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
// Try main.inc.php using relative path&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../../../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../../../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res) die(&amp;quot;Include of main fails&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sea la correcta, en función de la profundidad del directorio en el que se encuentra el archivo (quitando o añadiendo &amp;quot;../&amp;quot;). Es en el &amp;quot;main&amp;quot; donde se carga el entorno técnico y las habilitaciones. Los objetos variables se posicionan ahora:&lt;br /&gt;
&lt;br /&gt;
*$user – El objeto que contiene las características del usuario y sus derechos.&lt;br /&gt;
*$conf – El objeto que contiene la configuración de Dolibarr.&lt;br /&gt;
*$db – El objeto que contiene el gestor de conexión abierto a la base de datos.&lt;br /&gt;
*$langs – El objeto que contiene el idioma del usuario.&lt;br /&gt;
&lt;br /&gt;
*La inclusión de una clase o una biblioteca dedicada al módulo, sin saber a dónde se llamará el archivo, se realiza mediante una función de Dolibarr (no directamente mediante include_once):&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ejemplo :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_include_once(&#039;/mimodulo/class/miclass.class.php&#039;, &#039;MiClass&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Las clases de llamadas Dolibarr utilice la siguiente sintaxis:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ejemplo :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
require_once DOL_DOCUMENT_ROOT.&#039;/core/class/doli.class.php&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Acceso a la base de datos===&lt;br /&gt;
Si necesita realizar modificaciones en su tabla de la base de datos, utilice la clase generada más arriba.&lt;br /&gt;
&lt;br /&gt;
Si de todos modos quiere acceder a las tablas sin objeto PHP dedicado, esto es posible (por ejemplo para recuperar una lista de registros). En ese caso, piense en seguir estos ejemplos.&lt;br /&gt;
&lt;br /&gt;
Para un &#039;&#039;insert&#039;&#039;, &#039;&#039;update&#039;&#039; o &#039;&#039;delete&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $db-&amp;gt;begin();   // Debut transaction&lt;br /&gt;
 $db-&amp;gt;query(&amp;quot;Ma requete insert, update ou delete&amp;quot;);&lt;br /&gt;
 $db-&amp;gt;commit();       // Valide&lt;br /&gt;
 o $db-&amp;gt;rollback()  // Annule&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para una lectura:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $resql=$db-&amp;gt;query(&amp;quot;Ma requete select&amp;quot;);&lt;br /&gt;
 if ($resql)&lt;br /&gt;
 {&lt;br /&gt;
         $num = $db-&amp;gt;num_rows($resql);&lt;br /&gt;
         $i = 0;&lt;br /&gt;
         if ($num)&lt;br /&gt;
         {&lt;br /&gt;
                 while ($i &amp;lt; $num)&lt;br /&gt;
                 {&lt;br /&gt;
                         $obj = $db-&amp;gt;fetch_object($resql);&lt;br /&gt;
                         if ($obj)&lt;br /&gt;
                         {&lt;br /&gt;
                                 // You can use here results&lt;br /&gt;
                                 print $obj-&amp;gt;field1;&lt;br /&gt;
                                 print $obj-&amp;gt;field2;&lt;br /&gt;
                         }&lt;br /&gt;
                         $i++;&lt;br /&gt;
                 }&lt;br /&gt;
         }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Definición de estilos===&lt;br /&gt;
Para que el aspecto de la página guarde coherencia con el tema Dolibarr, es necesario utilizar los estilos CSS de Dolibarr.&lt;br /&gt;
&lt;br /&gt;
Por ejemplo:&lt;br /&gt;
&lt;br /&gt;
*class=&amp;quot;liste_titre&amp;quot;1 en las etiquetas tr y td para una línea de título de tabla.&lt;br /&gt;
*class=”pair” o class=”impair” en las etiquetas tr y td de las líneas de datos de la tabla.&lt;br /&gt;
*class=”flat” en todos los campos en los que se teclea (input, select, textarea...)&lt;br /&gt;
*class=”button” en los objetos de tipo input type=”submit”.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Utilizar el selector de fechas de Dolibarr===&lt;br /&gt;
Si quiere, puede beneficiarse del selector de fechas en las pantallas Dolibarr. Para ello, utilice la siguiente línea:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $form=new Form($db);&lt;br /&gt;
 $form-&amp;gt;select_date(&#039;&#039;,&#039;mykey&#039;,0,0,0,&amp;quot;myform&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La cadena &amp;quot;mikey&amp;quot; identifica el campo fecha. Hace falta introducir un valor diferente en caso de que haya varios campos. La cadena &amp;quot;myform&amp;quot; es el nombre del campo &amp;quot;FORM&amp;quot; (en el formulario, name=&amp;quot;myform&amp;quot; de la página html). La visualización de un selector de fecha debe por tanto estar integrada en un formulario html.&lt;br /&gt;
&lt;br /&gt;
Para recuperar el valor, a la herencia de POST, el comando es:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $mydate = dol_mktime(12, 0 , 0, $_POST[&#039;mykeymonth&#039;], $_POST[&#039;mykeyday&#039;], $_POST[&#039;mykeyyear&#039;]);&lt;br /&gt;
 print strftime(&#039;%A %d %B %Y&#039;, $mydate);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Definir su página de configuración (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si su módulo ofrece varias opciones parametrizables.&lt;br /&gt;
&lt;br /&gt;
===Crear su página de edición de configuración===&lt;br /&gt;
Si su módulo ofrece varias opciones parametrizables, es necesario crear una página PHP para editar las opciones (que serán guardadas en la [[Table llx_const|tabla &#039;&#039;&#039;llx_const&#039;&#039;&#039;]]). Cree una página PHP llamada &#039;&#039;&#039;mimodulo_setuppage.php&#039;&#039;&#039;, que registre las opciones posibles y las ponga al día. Es necesario tomar como ejemplo una página de &#039;&#039;&#039;/admin&#039;&#039;&#039; que le muestre el método para leer o guardar en la base de datos su opción. Coloque esta página de configuración también en el directorio &#039;&#039;&#039;/admin&#039;&#039;&#039;. A continuación, en el descriptor del módulo, modifique la variable para indicar el nombre de esta página PHP (no es necesario modificar la ruta, ya que la página estará forzosamente en el directorio &#039;&#039;&#039;/admin&#039;&#039;&#039;).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $this-&amp;gt;config_page_url = array(&amp;quot;monmodule_setuppage.php&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Probar su página===&lt;br /&gt;
Vaya a la página &#039;&#039;&#039;Configuración &amp;gt; módulo&#039;&#039;&#039;. Debería aparecer un icono que permite acceder a la página de configuración, y debería poder modificar estas opciones y verlas en la base de datos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Definir sus entradas de menú (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si ha creado páginas PHP, es necesario que estas pantallas sean accesibles desde el menú Dolibarr.&lt;br /&gt;
&lt;br /&gt;
===Definir sus entradas de menú===&lt;br /&gt;
Para ello, hace falta definir en el archivo descriptor de menú de tabla this-&amp;gt;menu, que declara los menús.&lt;br /&gt;
Esta tabla contiene todas las entradas que aparecerán en los menús una vez que el módulo sea activado. Los archivos de descriptor de módulo contienen un ejemplo de cómo se declara el menú superior, así como las entradas correspondientes en el menú de la derecha&lt;br /&gt;
&lt;br /&gt;
He aquí un ejemplo de declaración de entradas de menú en el fichero descriptor:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
// Main menu entries&lt;br /&gt;
$this-&amp;gt;menu = array();			// List of menus to add&lt;br /&gt;
$r=0;&lt;br /&gt;
&lt;br /&gt;
// Add here entries to declare new menus&lt;br /&gt;
// Example to declare the Top Menu entry:&lt;br /&gt;
$this-&amp;gt;menu[$r]=array(	&#039;fk_menu&#039;=&amp;gt;0,			// Put 0 if this is a top menu&lt;br /&gt;
			&#039;type&#039;=&amp;gt;&#039;top&#039;,			// This is a Top menu entry&lt;br /&gt;
			&#039;titre&#039;=&amp;gt;&#039;MyModule top menu&#039;,&lt;br /&gt;
			&#039;mainmenu&#039;=&amp;gt;&#039;mymodule&#039;,&lt;br /&gt;
			&#039;leftmenu&#039;=&amp;gt;&#039;mymodule&#039;,&lt;br /&gt;
			&#039;url&#039;=&amp;gt;&#039;/mymodule/pagetop.php&#039;,&lt;br /&gt;
			&#039;langs&#039;=&amp;gt;&#039;mylangfile&#039;,	// Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.&lt;br /&gt;
			&#039;position&#039;=&amp;gt;100,&lt;br /&gt;
			&#039;enabled&#039;=&amp;gt;&#039;1&#039;,			// Define condition to show or hide menu entry. Use &#039;$conf-&amp;gt;mymodule-&amp;gt;enabled&#039; if entry must be visible if module is enabled.&lt;br /&gt;
			&#039;perms&#039;=&amp;gt;&#039;1&#039;,			// Use &#039;perms&#039;=&amp;gt;&#039;$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;level1-&amp;gt;level2&#039; if you want your menu with a permission rules&lt;br /&gt;
			&#039;target&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
			&#039;user&#039;=&amp;gt;2);				// 0=Menu for internal users, 1=external users, 2=both&lt;br /&gt;
$r++;&lt;br /&gt;
&lt;br /&gt;
// Example to declare a Left Menu entry:&lt;br /&gt;
$this-&amp;gt;menu[$r]=array(	&#039;fk_menu&#039;=&amp;gt;&#039;fk_mainmenu=xxx&#039;,		    // Use &#039;fk_mainmenu=xxx&#039; or &#039;fk_mainmenu=xxx,fk_leftmenu=yyy&#039; where xxx is mainmenucode and yyy is a leftmenucode of parent menu&lt;br /&gt;
			&#039;type&#039;=&amp;gt;&#039;left&#039;,			        // This is a Left menu entry&lt;br /&gt;
			&#039;titre&#039;=&amp;gt;&#039;MyModule left menu 1&#039;,&lt;br /&gt;
			&#039;mainmenu&#039;=&amp;gt;&#039;xxx&#039;,&lt;br /&gt;
                        &#039;leftmenu&#039;=&amp;gt;&#039;yyy&#039;,&lt;br /&gt;
			&#039;url&#039;=&amp;gt;&#039;/mymodule/pagelevel1.php&#039;,&lt;br /&gt;
			&#039;langs&#039;=&amp;gt;&#039;mylangfile&#039;,	// Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.&lt;br /&gt;
			&#039;position&#039;=&amp;gt;100,&lt;br /&gt;
			&#039;enabled&#039;=&amp;gt;&#039;1&#039;,			// Define condition to show or hide menu entry. Use &#039;$conf-&amp;gt;mymodule-&amp;gt;enabled&#039; if entry must be visible if module is enabled.&lt;br /&gt;
			&#039;perms&#039;=&amp;gt;&#039;1&#039;,			// Use &#039;perms&#039;=&amp;gt;&#039;$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;level1-&amp;gt;level2&#039; if you want your menu with a permission rules&lt;br /&gt;
			&#039;target&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
			&#039;user&#039;=&amp;gt;2);				// 0=Menu for internal users,1=external users, 2=both&lt;br /&gt;
$r++;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para condicionar el acceso al menú segun los permisos, modificar la propiedad &#039;&#039;&#039;perms&#039;&#039;&#039; de la tabla. Ver el capítulo sobre permisos, un poco más abajo, para saber como realizar los permisos.&lt;br /&gt;
&lt;br /&gt;
===Probar sus entradas de menú===&lt;br /&gt;
Desactive y reactive su módulo bajo Dolibarr. Las entradas del menú deberían aparecer después de hacerlo (si la condición &#039;enabled&#039; está activada).&lt;br /&gt;
&lt;br /&gt;
==Definir sus propios permisos (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si quiere añadir nuevos permisos.&lt;br /&gt;
&lt;br /&gt;
La definición de permisos que gestionará su módulo se hace en el archivo descriptor creado en la primera fase. Modifique la línea $this-&amp;gt;rights_class = &#039;facture&#039; para que diga:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $this-&amp;gt;rights_class = &#039;mimodulo&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A continuación, rellene la tabla $this-&amp;gt;rights con tantas entradas como permisos diferentes vaya a definir:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $this-&amp;gt;rights[$r][0] = 10001;&lt;br /&gt;
 $this-&amp;gt;rights[$r][1] = &#039;Texto por defecto de mi permiso&#039;;&lt;br /&gt;
 $this-&amp;gt;rights[$r][3] = 1;&lt;br /&gt;
 $this-&amp;gt;rights[$r][4] = &#039;accion&#039;;&lt;br /&gt;
 $this-&amp;gt;rights[$r][5] = &#039;subaccion&#039;;&lt;br /&gt;
 $r++;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En $this-&amp;gt;rights[$r][0], introduzca un id de permiso que no haya sido ocupado ya (para saber qué id están siendo ya utilizadas, ver el menú &#039;&#039;&#039;Información del Sistema&#039;&#039;&#039; en una instalación de Dolibarr que esté funcionando. En $this-&amp;gt;rights[$r][3], introduzca 1 si este permiso se atribuye por defecto a los usuarios según son creados. En $this-&amp;gt;rights[$r][1] introduzca un texto por defecto -que será mostrado si no se encuentra traducción para su permiso en el archivo &#039;&#039;&#039;admin.lang&#039;&#039;&#039;). En $this-&amp;gt;rights[$r][4] y $this-&amp;gt;rights[$r][5], introduzca una cadena de acción y subacción sin espacios. Después puede probar si un usuario tiene los permisos bien, introduciendo la siguiente secuencia en el código PHP:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 if ($user-&amp;gt;rights-&amp;gt;mimodulo-&amp;gt;accion-&amp;gt;subaccion) ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Definir sus propios paneles (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si su módulo tiene uno o varios paneles.&lt;br /&gt;
&lt;br /&gt;
===Defina sus paneles===&lt;br /&gt;
Para ello, modifique las tablas $this-&amp;gt;boxes del archivo descriptor de módulo. Es suficiente con añadir 2 líneas por cada archivo de panel que se encuentre en el directorio &#039;&#039;&#039;htdocs/mimodulo/core/boxes&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ejemplo:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;boxes[0][&#039;file&#039;]=&#039;mabox0.php@mimodulo&#039;&lt;br /&gt;
$this-&amp;gt;boxes[0][&#039;note&#039;]=&#039;Mi panel 0&#039;&lt;br /&gt;
 ...&lt;br /&gt;
$this-&amp;gt;boxes[n][&#039;file&#039;]=&#039;maboxn.php@mimodulo&#039;&lt;br /&gt;
$this-&amp;gt;boxes[n][&#039;note&#039;]=&#039;Mi panel n&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A continuación cree los archivos &#039;&#039;&#039;htdocs/mimodulo/core/boxes/mabox0.php&#039;&#039;&#039;, &#039;&#039;&#039;htdocs/mimodulo/core/boxes/mabox1.php&#039;&#039;&#039;...  tomando como ejemplo los paneles existentes (en el directorio htdocs/core/boxes)&lt;br /&gt;
&lt;br /&gt;
===Pruebe sus paneles en Dolibarr===&lt;br /&gt;
Vaya al menú &#039;&#039;&#039;Inico – Configuración – Paneles&#039;&#039;&#039;. Sus paneles deben aparecer en la lista de paneles activables. Actívelos, vaya a la página de bienvenida y verifique que se muestran correctamente.&lt;br /&gt;
&lt;br /&gt;
==Definir sus propias exportaciones (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si su módulo incorpora exportaciones predefinidas de datos (tanto para sus propias tablas o para otras tablas existentes de otros módulos de Dolibarr)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Definir la exportación===&lt;br /&gt;
Para ello, descomente y modifique las tablas $this-&amp;gt;export_xxx  de su archivo descriptor de módulo.&lt;br /&gt;
&lt;br /&gt;
===Probar la exportación===&lt;br /&gt;
Vaya al menú &amp;quot;Herramientas &amp;gt; Exportar&amp;quot; de Dolibarr. Su exportación debería aparecer en la lista de exportaciones predefinidas disponibles (si su módulo ha sido activado correctamente). Deberían aparecer, para que pudiera elegirlos, los campos que definió en la fase anterior en las tablas correspondientes. Seleccione algunos campos y pruebe a generar un archivo de exportación.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Definir sus estilos CSS (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si en sus pantallas PHP utiliza clases de estilos distintas a las de los temas de Dolibarr (no recomendado).&lt;br /&gt;
&lt;br /&gt;
Esta funcionalidad todavía no es operativa en la versión 2.4., a pesar de estar ya descrita.&lt;br /&gt;
&lt;br /&gt;
===Crear y declarar su hoja de estilos===&lt;br /&gt;
Crear un archivo de estilos llamada &#039;&#039;&#039;mimodulo.css&#039;&#039;&#039; o &#039;&#039;&#039;mimodule.css.php&#039;&#039;&#039; y guardarla en el directorio &#039;&#039;&#039;&#039;&#039;mimodulo&#039;&#039;&#039;&#039;&#039; dentro de &#039;&#039;&#039;htdocs&#039;&#039;&#039;. Solo puede haber un archivo css propio a cada módulo.&lt;br /&gt;
Recordamos que es mejor usar los estilos ya existentes en Dolibarr (el archivo css usado por Dolibarr es el archivo &#039;&#039;&#039;themes/nomtheme/&#039;&#039;nombretema&#039;&#039;.css.php&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Una vez su hoja de estilos esté disponible, declárela en su archivo descriptor de módulo modificando la propiedad &#039;&#039;&#039;$this-&amp;gt;module_parts&#039;&#039;&#039;.&lt;br /&gt;
El valor a indicar debe ser la ruta URL relativa de su archivo css.&lt;br /&gt;
Por ejemplo&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;module_parts = array(&#039;css&#039; =&amp;gt; array(&#039;/mimodulo/css/mimodulo.css.php&#039;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Probar su hoja de estilos===&lt;br /&gt;
Desactivar y reactivar su módulo.&lt;br /&gt;
&lt;br /&gt;
Ir la página de inicio de Dolibarr. Ver el código de la página HTML.&lt;br /&gt;
&lt;br /&gt;
Debería ver en el encabezado HTML, una línea de declaración de su hoja de estilos.&lt;br /&gt;
&lt;br /&gt;
==Definir sus funciones Javascript (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuando&#039;&#039;&#039;: Si en sus pantallas en PHP utiliza funciones de Javascript no disponibles en estandard (archivo lib_head.js)&lt;br /&gt;
&lt;br /&gt;
Si en sus pantallas en PHP utiliza funciones javascript, es necesario asegurarse de que las funciones declaradas en un archivo javascript &#039;&#039;&#039;htdocs/mimodulo/js/monmodule.js&#039;&#039;&#039; sea cargado en la cabecera del head html.&lt;br /&gt;
&lt;br /&gt;
Para pedir a Dolibarr que gestione en la generación de la sección header la inclusión de uno de sus archivos javascript, es necesario proporcionar como parámetro a la función llxHeader(), al inicio de su página, la URL hacia el js a incluir.&lt;br /&gt;
&lt;br /&gt;
Ejemplo para la página /htdocs/mimodulo/mapage.php :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
require(&#039;../main.inc.php&#039;);&lt;br /&gt;
$morejs=array(&amp;quot;/mimomulo/js/monmodule.js&amp;quot;);&lt;br /&gt;
llxHeader(&#039;&#039;,&#039;Titulo&#039;,&#039;&#039;,&#039;&#039;,&#039;&#039;,&#039;&#039;,$morejs,&#039;&#039;,0,0); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ejecutar código sobre un evento Dolibarr (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo:&#039;&#039;&#039; Si quiere que se ejecuten acciones particulares al activar ciertas acciones estandar de Dolibarr (por ejemplo, si deseáramos actualizar una tabla de mi módulo cada vez que se crea una factura en Dolibarr), hará falta crear un archivo &#039;&#039;&#039;disparador (triggers)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Véase también [[Interfaces Dolibarr hacia el exterior]] e [[Interfaces del Exterior hacia Dolibarr]]&lt;br /&gt;
&lt;br /&gt;
==Insertar su código usando los hooks de Dolibarr (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo&#039;&#039;&#039;: Cuando desee cambiar o añadir otro tipo de código en un evento de negociado (véase lel capítulo anterior para esto).&lt;br /&gt;
&lt;br /&gt;
Véase la página [[El sistema Hooks]].&lt;br /&gt;
&lt;br /&gt;
==Añadir un módulo de numeración (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo&#039;&#039;&#039;: Si quiere añadir una regla de numeración no cubierta por los módulos por defecto.&lt;br /&gt;
&lt;br /&gt;
Véase la página [[Crear un módulo de numeración]].&lt;br /&gt;
&lt;br /&gt;
==Añadir un nuevo módulo de documento (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo&#039;&#039;&#039;: Si quiere añadir un nuevo modelo de documento.&lt;br /&gt;
&lt;br /&gt;
La documentación relativa a la generación de documentos desde los modelos se encuentra disponible en la página [[Crear un modelo de documento PDF]] o [[Crear un modelo de documento ODT]].&lt;br /&gt;
&lt;br /&gt;
==Añadir un tema (opcional)==&lt;br /&gt;
&#039;&#039;&#039;Cuándo&#039;&#039;&#039;: Si quiere un interface con colores personalizados.&lt;br /&gt;
&lt;br /&gt;
Véase la página [[Temas]].&lt;br /&gt;
&lt;br /&gt;
=[[File:Art.png]] Algunas reglas de código=&lt;br /&gt;
Las reglas de código a seguir se definen en la [[Documentación Desarrolladores| Documentación para desarrolladores]], concretamente en la sección &amp;quot;Lenguaje&amp;quot; del capítulo de &amp;quot;Información General&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=[[File:Art.png]] Crear un paquete para liberar e instalar su módulo=&lt;br /&gt;
Este proceso debe ser usado para fabricar un paquete con el fin de enviarlo a la tienda oficial http://www.dolistore.com.&lt;br /&gt;
&lt;br /&gt;
También puede usarlo para distribuir fácilmente su módulo vía su propio método de distribución.&lt;br /&gt;
&lt;br /&gt;
*Vaya al directorio &#039;&#039;&#039;/build&#039;&#039;&#039; y copie el archivo &#039;&#039;&#039;makepack-dolibarrmodules.conf&#039;&#039;&#039; como &#039;&#039;&#039;makepack-mimodulo.conf&#039;&#039;&#039;. Cuidado: este directorio puede no ser suministrado en los paquetes de versión estables. Si es el caso, puede bajarte la última snapshot en la sección de Downloads del sitio de Dolibarr con el nombre “Development Version” (tome en este caso todos los directorios que sean autónomos e independientes de la versión).&lt;br /&gt;
&lt;br /&gt;
Teclee en este archivo la lista de nombres de los nuevos archivos que ha creado para su módulo (descriptor de módulo, nuevos ficheros sql de tablas, páginas php, imágenes, etc...)&lt;br /&gt;
&lt;br /&gt;
*Lance el script vía Perl (necesita la versión 5.0. o superiores de Perl)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 perl makepack-dolibarrmodule.pl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
El script le pide el nombre de su módulo, su versión mayor y menor. Se va a crear un fichero &#039;&#039;&#039;mimodulo.zip&#039;&#039;&#039;, que incluirá su módulo listo para ser liberado.&lt;br /&gt;
&lt;br /&gt;
*La persona que reciba su módulo deberá ubicar el archivo en el directorio raíz de Dolibarr y ejecutar el comando:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 tar -xvf monmodule.zip&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Si  desea que su módulo sea aprovechado por todos, puede enviarlo (el fichero zip) al sitio web de Dolibarr, en la sección de descargas: {{LinkToPluginDownload}} (debe de haber creado una cuenta y estar logeado para que aparezca el link &amp;quot;Submit a product&amp;quot;).&lt;br /&gt;
**Si su módulo está correctamente realizado, será rápidamente validado.&lt;br /&gt;
**Si la calidad es suficiente, la licencia lo permite y la funcionalidad del módulo es de interés general, el código podrá añadirse al código fuente de Dolibarr (salvo que no lo desee).&lt;/div&gt;</summary>
		<author><name>Alograg</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Module_development&amp;diff=54024</id>
		<title>Module development</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Module_development&amp;diff=54024"/>
		<updated>2022-06-22T08:51:33Z</updated>

		<summary type="html">&lt;p&gt;Alograg: /* Create a Module descriptor for your Module (required) */ Path to template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN origin interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- You can edit this section but do NOT remove these comments&lt;br /&gt;
     Links below will be automatically replicated on translated pages by PolyglotBot --&amp;gt;&lt;br /&gt;
[[fr:Développement_module]]&lt;br /&gt;
[[es:Desarrollo_de_un_módulo]]&lt;br /&gt;
[[de:Modul_Entwicklung]]&lt;br /&gt;
[[zh:模块开发]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Core]]&lt;br /&gt;
{{TemplateDocDevEn}}&lt;br /&gt;
&lt;br /&gt;
To create a new module/addon for Dolibarr, there is several steps. This tutorial will describe you each of them to build a module to extend Dolibarr features, like one or several of the following :&lt;br /&gt;
&lt;br /&gt;
*Add new tables in database.&lt;br /&gt;
*Add your own menu entries.&lt;br /&gt;
*Add new screens to edit new tables.&lt;br /&gt;
*Add or remove tabs on object view (invoice, product, order, event, ...).&lt;br /&gt;
*Add predefined exports for the internal export tool.&lt;br /&gt;
*Add new information widget in the home page.&lt;br /&gt;
*Add new substitutions variables.&lt;br /&gt;
*Define new permissions.&lt;br /&gt;
*Execute code automatically triggered by a particular Dolibarr action.&lt;br /&gt;
*Insert your code inside Dolibarr hooks positions.&lt;br /&gt;
*Add your numbering rule to generate the reference of objects&lt;br /&gt;
*Add a new document template.&lt;br /&gt;
*Add a new skin.&lt;br /&gt;
&lt;br /&gt;
etc...&lt;br /&gt;
&lt;br /&gt;
Following chapters presents how to do all of this manually with an easy way.&lt;br /&gt;
&lt;br /&gt;
=Module creation with the module builder=&lt;br /&gt;
From Dolibarr 9.0 it is possible to create the main pages of your module with the Module Builder. To activate it:&lt;br /&gt;
&lt;br /&gt;
*Go into the list of module and enable the module &amp;quot;Module Builder&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
[[File:Mod_builder_2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
*Then click on the &amp;quot;bug&amp;quot; image in the top right of screen.&lt;br /&gt;
&lt;br /&gt;
[[File:Mod_builder_3.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=Example of Template External Module=&lt;br /&gt;
A good model to start development of external module can be found here : [https://github.com/Dolibarr/dolibarr/tree/develop/htdocs/modulebuilder/template GitHub Dolibarr Module Modèle]&lt;br /&gt;
&lt;br /&gt;
=Create your module=&lt;br /&gt;
==Create a Module descriptor for your Module (required)==&lt;br /&gt;
&#039;&#039;&#039;When it is required&#039;&#039;&#039;: Required as soon as an addon is developed, whatever its goal is (except for adding a skin).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Since Dolibarr 9.0, you should use the ModuleBuilder module provided as a standard module to generate the module descriptor&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Create your module descriptor===&lt;br /&gt;
The first step is to create a file descriptor for the module. &lt;br /&gt;
&lt;br /&gt;
*Create directory &#039;&#039;&#039;/htdocs/&#039;&#039;mymodule&#039;&#039;/core/modules&#039;&#039;&#039;. Then copy the file modMyModule.class.php from the directory htdocs/modulebuilder/template into this directory &#039;&#039;&#039;htdocs/&#039;&#039;mymodule&#039;&#039;/core/modules&#039;&#039;&#039;. Change the name of the file modMyModule.class.php to the name corresponding to the purpose of your module. Name of the file must start with initial &#039;mod&#039; and end with .class.php (for example if you want to give the name &#039;NewName&#039; to this file, then the name should be &#039;modNewName.class.php&#039;).&lt;br /&gt;
&lt;br /&gt;
Next modify the contents of this file as follows:&lt;br /&gt;
&lt;br /&gt;
*Replace all &amp;quot;modMyModule&amp;quot; with a value which corresponds to the purpose of your module. This value must always start with &#039;mod&#039; and contain only alpha characters (again, if the name given to the file was &#039;NewName&#039;, then replace all &amp;quot;modMyModule&amp;quot; with &amp;quot;modNewName&amp;quot;).&lt;br /&gt;
*Change the number in: $this-&amp;gt;numero = 100000 by a number that designates your module id. To avoid conflicts with other modules, you can consult the page that lists already reserved id numbers: [[List of modules id|List of modules id]].&lt;br /&gt;
*Modify any other variables defined in the constructor (see comment in the code skeleton for their meaning).&lt;br /&gt;
&lt;br /&gt;
Your file descriptor for your module is ready. See the next step to activate it.&lt;br /&gt;
&lt;br /&gt;
===Test your descriptor===&lt;br /&gt;
&lt;br /&gt;
Launch Dolibarr and go to page &#039;&#039;&#039;Setup-&amp;gt;module&#039;&#039;&#039;? &lt;br /&gt;
If you set the property version in the module description you should see a new line with your new module and the possibility to activate it or not. If you set the property version to &amp;quot;develop&amp;quot; or &amp;quot;experiental&amp;quot;, to see your module, you must first go into &#039;&#039;&#039;Setup-Others&#039;&#039;&#039; and set MAIN_FEATURES_LEVEL to 1 to see &amp;quot;experimental&amp;quot; modules or 2 to see &amp;quot;development&amp;quot; modules.&lt;br /&gt;
&lt;br /&gt;
==Tree of path for new module files (required)==&lt;br /&gt;
This is how your files must be organized when building a new module (the zip file must also match this rule).&lt;br /&gt;
Note: Only the second line is mandatory.&lt;br /&gt;
&lt;br /&gt;
{{TemplateModuleTreeSimple}}&lt;br /&gt;
&lt;br /&gt;
==Create your SQL tables and the PHP DAO class (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If your module needs to manage data of its own&lt;br /&gt;
&lt;br /&gt;
===Create your .sql file===&lt;br /&gt;
If your module is designed to manage data of its own, which are not available in the standard version of Dolibarr, it is necessary to define SQL tables to store the data.&lt;br /&gt;
&lt;br /&gt;
Scripts for creating tables and loading data by your own module are saved into a subdirectory sql (&#039;&#039;&#039;&amp;quot;mymodule/sql&amp;quot;&#039;&#039;&#039;) of your module. (With ModuleBuilder, the directory and all sql files will be created automatically when you will create a new Object from tab Object).&lt;br /&gt;
&lt;br /&gt;
Then check into your descriptor file, into function &#039;&#039;&#039;init&#039;&#039;&#039; that the line&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;$this-&amp;gt;_load_tables(&#039;/mymodule/sql/&#039;);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
is not commented.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Rules to follow:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Add the files about creating tables commands on the principle of a file &#039;&#039;&#039;llx_matable.sql&#039;&#039;&#039; per table, with a possibly file &#039;&#039;&#039;llx_matable.key.sql&#039;&#039;&#039; (see existing files in &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; for examples).&lt;br /&gt;
*The recommended type and name for SQL fields are defined into page [[Language_and_development_rules#Table_and_fields_structures]].&lt;br /&gt;
*To manage data, you must create a file called &#039;&#039;&#039;data.sql&#039;&#039;&#039; inside directory &#039;&#039;&#039;/mymodule/sql/&#039;&#039;&#039; that contains SQL command to add/edit/delete data.&lt;br /&gt;
*Don&#039;t use the double quote for strings (eg &#039;chaine&#039; not &amp;quot;chaine&amp;quot;) because the double quote have a specific meaning in PostGreSQL&lt;br /&gt;
&lt;br /&gt;
Example of content of a file data.sql&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
 delete from llx_const where name=&#039;MYMODULE_IT_WORKS&#039; and entity=&#039;__ENTITY__&#039;;&lt;br /&gt;
 insert into llx_const (name, value, type, note, visible, entity) values (&#039;MYMODULE_IT_WORKS&#039;,&#039;1&#039;,&#039;chaine&#039;,&#039;A constant vor my module&#039;,1,&#039;__ENTITY__&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Files must be operational for the database mysql. Rem: The files of other databases are not maintained. They will be read and converted on the fly by the driver of the other database.&lt;br /&gt;
&lt;br /&gt;
===Test your .sql files===&lt;br /&gt;
&lt;br /&gt;
Once the files ready, you can return to the page to enable Dolibarr modules and disable the module, drop those tables in the database (if they already exists) and reactivate the module. The tables should be recreated by the activation of the module. If this is not the case, check your scripts by passing them by hand, or check the Dolibarr logs.&lt;br /&gt;
&lt;br /&gt;
===Generate the PHP DAO class===&lt;br /&gt;
The DAO PHP files should have been generated by ModuleBuilder after creating an object.&lt;br /&gt;
&lt;br /&gt;
You can however create them manually by copying existing object however using ModuleBuilder is highly recommended. You should find examples into &#039;&#039;&#039;htdocs/modulebuilder/templates/class/myobject.class.php&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this class, there are already operational CRUD (Create/Read/Update/Delete) methods to perform an insert, a fetch (select), an update, a delete of a table row. Edit the file to use the correct module name, tables and place this file in the class subdirectory of the module. The Module Builder allows you to do this with just a few mouse clicks.&lt;br /&gt;
&lt;br /&gt;
==The tab management (optional)==&lt;br /&gt;
&lt;br /&gt;
===Add or remove your own tabs on object sheets===&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: To add a tab on an object (invoices, orders, proposals, member ...)&lt;br /&gt;
&lt;br /&gt;
To do this go into the file descriptor of module previously created and edit the $this-&amp;gt;tabs array:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
	// Array to add new pages in new tabs or remove existing one&lt;br /&gt;
	$this-&amp;gt;tabs = array(&#039;objecttype:+tabname1:Title1:mylangfile@mymodule:$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;read:/mymodule/mypagetab1.php?id=__ID__&#039;    // To add a new tab identified by code tabname1&lt;br /&gt;
                            &#039;objecttype:+tabname2:Title2:mylangfile@mymodule:$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;read:/mymodule/mypagetab2.php?id=__ID__&#039;,   // To add a new tab identified by code tabname2&lt;br /&gt;
                            &#039;objecttype:-tabname&#039;);                                                     // To remove an existing tab identified by code tabname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The table should contain a list of strings, each string representing a new tab. &lt;br /&gt;
The format of the string consisting of 5 parts separated by &amp;quot;:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*Part 1: The element type (object type) where the tab should appear is a value from the following:&lt;br /&gt;
{{TemplateModuleTabs}}&lt;br /&gt;
&lt;br /&gt;
*Part 2: A code to identify tab to add (start with +) or to remove (start with -)&lt;br /&gt;
*Part 3: The title of the tab. This can be a hard read or better code translation in a file lang.&lt;br /&gt;
*Part 4: The name of the file &amp;quot;*.lang&amp;quot; which contains correspondence between the code translation and language to display. If this name is followed with @mymodule, Dolibarr will search translation file &amp;quot;*.lang&amp;quot; within the module, so htdocs/mymodule/langs/code_CODE/mylangfile.lang, otherwise Dolibarr will look for file htdocs/langs/code_CODE/mylangfile.lang&lt;br /&gt;
*Part 5: A condition to test if tab must be visible. Put 1 to be always visible.&lt;br /&gt;
*Part 6: The URL of the page to display when you click on the tab. The __ID__ string will be replaced automatically by the Id of the element concerned.&lt;br /&gt;
&lt;br /&gt;
To feed the contents of the tab with data from the database, see the next chapter.&lt;br /&gt;
&lt;br /&gt;
In order to get the names  &#039;tabname&#039; of existing tabs, you have to check the names used in the function &#039;product_prepare_head&#039; of the file  &#039;core/lib/module.lib.php&#039; corresponding to section &#039;$head[$h][2]&#039;.&lt;br /&gt;
&lt;br /&gt;
===Show tabs navigation into your own pages===&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: To show all standard tabs of an object (product, tiers, etc.) on your page.&lt;br /&gt;
&lt;br /&gt;
You must follow these steps :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1. Include files you need into your file&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For each object type, there are two files to include with line&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;require_once($url_fichier) ;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is example of files to include (DOL_DOCUMENT_ROOT is often dolibarr/htdocs/) :&lt;br /&gt;
&lt;br /&gt;
*Object thirdparty (thirdparty) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/societe/class/societe.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/core/lib/company.lib.php&lt;br /&gt;
*Object product (product) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/product/class/product.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/core/lib/product.lib.php&lt;br /&gt;
*Object invoice (invoice) :&lt;br /&gt;
**DOL_DOCUMENT_ROOT/compta/facture/class/facture.class.php&lt;br /&gt;
**DOL_DOCUMENT_ROOT/core/lib/invoice.lib.php&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. Create and load the object to show into your tab&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create an instance of an object of the correct class and load object from the database by using the fetch method of an object in providing to this method the id you get from URL (ie : /mytab.php?id=1).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$id=GETPOST(&#039;id&#039;,&#039;int&#039;);&lt;br /&gt;
$ref=GETPOST(&#039;ref&#039;,&#039;alpha&#039;);&lt;br /&gt;
$product = new Product($db) ;&lt;br /&gt;
$result = $product-&amp;gt;fetch($id,$ref) ; // Test $result to check the database read is ok&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3. Get a list of all tabs to show for your object type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Use function XXX_prepare_head($obj), where XXX is name of object. This will return an array with all definition of tab entries to show. The parameter to put into this method is the instance of an object you want tabs.&lt;br /&gt;
&lt;br /&gt;
The resulting array has the following structure&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$head        // Array of tabs&lt;br /&gt;
$head[$h]    // Element to describe one tab.&lt;br /&gt;
$head[$h][0] // Url of page to show when you click on tab&lt;br /&gt;
$head[$h][1] // Title of tab&lt;br /&gt;
$head[$h][2] // Code name to identify the tab&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$head = product_prepare_head($product, $user) ; // parameter $user is present for some function anly&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4. show tabs into your page&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Use function dol_fiche_head() to show all tabs defined into array $head returned by XX_prepare_head().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_fiche_head($links, $active=&#039;0&#039;, $title=&#039;&#039;, $notab=0, $picto=&#039;&#039;)&lt;br /&gt;
//$links  // Tableau des onglets, appelé $head plus haut.&lt;br /&gt;
//$active // Onglet actif (mettre le nom de l&#039;onglet défini dans votre fichier de module, ou un nom contenu dans $head[$h][2]). Cet onglet sera mis en surbrillance&lt;br /&gt;
//$title  // Title to show (shown into a special tab that you can&#039;t click)&lt;br /&gt;
//$notab&lt;br /&gt;
//$picto  // Name of image to show into title. Possible values are:&lt;br /&gt;
//            product&lt;br /&gt;
//            service&lt;br /&gt;
//            company&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function will show required tabs and open an html element &#039;&#039;&amp;lt; div class=&amp;quot;&amp;quot; &amp;gt;&#039;&#039; that correspond to the area under the tabs. To close area of a tab, just use &#039;&#039;&amp;lt; /div &amp;gt;&#039;&#039; into your PHP page.&lt;br /&gt;
&lt;br /&gt;
==Create or modify PHP screens (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If the purpose of your module is to add features that require new or modified screens.&lt;br /&gt;
&lt;br /&gt;
===Create a new PHP screen===&lt;br /&gt;
You must then create your PHP pages that will show/edit data from tables using the skeleton templates provided as an example in the directory &#039;&#039;&#039;modulebuilder/myobject_page.php&#039;&#039;&#039; (For the development of a script from the command line, see [[Script development]]).&lt;br /&gt;
&lt;br /&gt;
To create a new user screen, create a subdirectory of &#039;&#039;&#039;htdocs&#039;&#039;&#039; (if not already done) for your module (in &#039;&#039;&#039;htdocs/mymodule&#039;&#039;&#039; for example) to store the pages you will create.&lt;br /&gt;
&lt;br /&gt;
Copy, into that directory, the file &#039;&#039;&#039;myobject_page.phpp&#039;&#039;&#039; that will serve as a starting point for your page file.&lt;br /&gt;
Edit the file to have a correct relative path to the main.inc.php file. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
// Load Dolibarr environment&lt;br /&gt;
$res=0;&lt;br /&gt;
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; ! empty($_SERVER[&amp;quot;CONTEXT_DOCUMENT_ROOT&amp;quot;])) $res=@include($_SERVER[&amp;quot;CONTEXT_DOCUMENT_ROOT&amp;quot;].&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME&lt;br /&gt;
$tmp=empty($_SERVER[&#039;SCRIPT_FILENAME&#039;])?&#039;&#039;:$_SERVER[&#039;SCRIPT_FILENAME&#039;];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1;&lt;br /&gt;
while($i &amp;gt; 0 &amp;amp;&amp;amp; $j &amp;gt; 0 &amp;amp;&amp;amp; isset($tmp[$i]) &amp;amp;&amp;amp; isset($tmp2[$j]) &amp;amp;&amp;amp; $tmp[$i]==$tmp2[$j]) { $i--; $j--; }&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; $i &amp;gt; 0 &amp;amp;&amp;amp; file_exists(substr($tmp, 0, ($i+1)).&amp;quot;/main.inc.php&amp;quot;)) $res=@include(substr($tmp, 0, ($i+1)).&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; $i &amp;gt; 0 &amp;amp;&amp;amp; file_exists(dirname(substr($tmp, 0, ($i+1))).&amp;quot;/main.inc.php&amp;quot;)) $res=@include(dirname(substr($tmp, 0, ($i+1))).&amp;quot;/main.inc.php&amp;quot;);&lt;br /&gt;
// Try main.inc.php using relative path&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res &amp;amp;&amp;amp; file_exists(&amp;quot;../../../main.inc.php&amp;quot;)) $res=@include(&amp;quot;../../../main.inc.php&amp;quot;);&lt;br /&gt;
if (! $res) die(&amp;quot;Include of main fails&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
As you can see, there are several tries to load the main.inc.php (or master.inc.php). The goal is to succeed in the most cases as possible. The minimum is 2 lines: one to try to load the master/main.inc.php into the dolibarr root directory and another one to try to load the file to support the case when the module is deployed into the &amp;quot;custom&amp;quot; directory. But you can have more to deal more situation. The provided example should be able to load the file main/master.inc.php in nearly all situation/setups.&lt;br /&gt;
&lt;br /&gt;
Note that you may add more &amp;quot;../&amp;quot; depending on the depth of the file relative to your module directory tree.&lt;br /&gt;
&lt;br /&gt;
It&#039;s in the main.inc.php file that is loaded technical environment variables and permissions. The following variables are objects positioned in this file:&lt;br /&gt;
&lt;br /&gt;
*$user    Object that contains the characteristics of the user + his permissions.&lt;br /&gt;
*$conf    Object that contains Dolibarr configuration.&lt;br /&gt;
*$db      Object that contains an opened connection handler to the database.&lt;br /&gt;
*$langs   Object that contains the user&#039;s language.&lt;br /&gt;
&lt;br /&gt;
Then enter your code to display the page.&lt;br /&gt;
&lt;br /&gt;
*To include a class or library dedicated to the module is done using a Dolibarr function (and not using directly include_once):&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_include_once(&#039;/mymodule/class/myclass.class.php&#039;, &#039;MyClass&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*To include classes provided with Dolibarr, use the following syntax:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example :&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
require_once DOL_DOCUMENT_ROOT.&#039;/core/class/doli.class.php&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Add some fields into existing forms===&lt;br /&gt;
You may want to provide a module that adds more fields into forms (input and view) of some elements. &lt;br /&gt;
&lt;br /&gt;
A heavy solution (but not so bad) may be to replace all pages used to create element (this means to disable the &amp;quot;New element&amp;quot; menu entry and adding yours, and disable tab that shows element to replace with a tab that is your own full page (copied/pasted from original) to do same than original page but modified to add your fields and stored added data into your own table). Go to menu [[#Define your entries in the menu (optional)]] and [[#The tab management (optional)]] if this solution suits you (this solution is more powerful since you can change everything you want into the page). &lt;br /&gt;
&lt;br /&gt;
We will describe here another solution, that works only to &amp;quot;add fields&amp;quot; at end of existing fields, using the element &amp;quot;category&amp;quot; as an example but you can convert this tutorial for invoice, proposal ...&lt;br /&gt;
&lt;br /&gt;
*First thing is to add a table, owned by your module, to store the value of new fields. This table will have only one column called &amp;quot;rowid&amp;quot; (will contain the same value than field rowid of element table) + one column for each new field you want to add. Then create a class with CRUD (Create/Read/Update/Delete) methods for this new table. For this two tasks, go back to previous chapter [[#Create your SQL tables and the PHP DAO class]].&lt;br /&gt;
*Next step is to add a hook into your module to add the new fields into the form. See chapter [[Hooks_system#Implement_the_Hook]] for generic documentation to use hooks.&lt;br /&gt;
&lt;br /&gt;
If you follow this tutorial, to be able to add fields into category forms, you must do:&lt;br /&gt;
{{ToComplete}}&lt;br /&gt;
&lt;br /&gt;
===Add/replace part of fields supported by hooks===&lt;br /&gt;
See chapter [[Hooks_system#Implement_the_Hook]] to know how to use Dolibarr existing hooks to add/replace code at Dolibarr hooks place.&lt;br /&gt;
&lt;br /&gt;
===Database access===&lt;br /&gt;
If you need to edit some data in the database inside your own table, use the PHP class generated before.&lt;br /&gt;
&lt;br /&gt;
If you to make access to tables with no dedicated PHP class available, this is always possible (for example if you want to get a list of records with a particular join or filter). In this case, this is a code samples to follow:&lt;br /&gt;
&lt;br /&gt;
To make an insert, update or delete:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$db-&amp;gt;begin();   // Start transaction&lt;br /&gt;
$db-&amp;gt;query(&amp;quot;My SQL request insert, update or delete&amp;quot;);&lt;br /&gt;
$db-&amp;gt;commit();       // Validate transaction&lt;br /&gt;
or $db-&amp;gt;rollback()  // Cancel transaction&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To read:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$resql=$db-&amp;gt;query(&amp;quot;My select request&amp;quot;);&lt;br /&gt;
if ($resql)&lt;br /&gt;
{&lt;br /&gt;
	$num = $db-&amp;gt;num_rows($resql);&lt;br /&gt;
	$i = 0;&lt;br /&gt;
	if ($num)&lt;br /&gt;
	{&lt;br /&gt;
		while ($i &amp;lt; $num)&lt;br /&gt;
		{&lt;br /&gt;
			$obj = $db-&amp;gt;fetch_object($resql);&lt;br /&gt;
			if ($obj)&lt;br /&gt;
			{&lt;br /&gt;
				// You can use here results&lt;br /&gt;
				print $obj-&amp;gt;field1;&lt;br /&gt;
				print $obj-&amp;gt;field2;&lt;br /&gt;
			}&lt;br /&gt;
			$i++;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Define style of your pages===&lt;br /&gt;
To have the look of your own pages to match the Dolibarr theme, it is necessary to use the Dolibarr CSS styles.&lt;br /&gt;
&lt;br /&gt;
You can use for example:&lt;br /&gt;
&lt;br /&gt;
*class=&amp;quot;&#039;&#039;&#039;liste_titre&#039;&#039;&#039;&amp;quot; on tags &#039;&#039;tr&#039;&#039; and &#039;&#039;td&#039;&#039; for the head row of a table.&lt;br /&gt;
*class=&amp;quot;&#039;&#039;&#039;pair&#039;&#039;&#039;&amp;quot; or class=&amp;quot;&#039;&#039;&#039;impair&#039;&#039;&#039;&amp;quot; on tags &#039;&#039;tr&#039;&#039; and &#039;&#039;td&#039;&#039; of other rows of a table.&lt;br /&gt;
*class=&amp;quot;&#039;&#039;&#039;flat&#039;&#039;&#039;&amp;quot; on all input fields (&#039;&#039;input, select, textarea&#039;&#039;...).&lt;br /&gt;
*class=&amp;quot;&#039;&#039;&#039;button&#039;&#039;&#039;&amp;quot; on HTML fields with type &#039;&#039;input type=&amp;quot;submit&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Use the Dolibarr date picker===&lt;br /&gt;
If you want to use the Dolibarr date selector (with its calendar popup) into your pages, use the following line:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
 $form=new Form($db);&lt;br /&gt;
 $form-&amp;gt;select_date(&#039;&#039;,&#039;mykey&#039;,0,0,0,&amp;quot;myform&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The string mykey will identify the date selector in the form. You must use different values if you use several date selectors in same page.&lt;br /&gt;
The string myform is the name of the FORM in which the selector is included (value found in the form name=&amp;quot;myform&amp;quot; in HTML page).&lt;br /&gt;
This means a date selector must be included necessarily into an html FORM.&lt;br /&gt;
&lt;br /&gt;
To get value after the POST of your form, the command is:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mydate = dol_mktime(12, 0 , 0, $GETPOST(&#039;mykeymonth&#039;, &#039;int&#039;), GETPOST(&#039;mykeyday&#039;, &#039;int&#039;), GETPOST(&#039;mykeyyear&#039;, &#039;int&#039;));&lt;br /&gt;
print strftime(&#039;%A %d %B %Y&#039;, $mydate);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add your own setup page (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If your module needs parameters, which are to be provided by the user, for proper setting up of the module.&lt;br /&gt;
&lt;br /&gt;
===Create your page to edit parameters===&lt;br /&gt;
If your module needs several parameters to be setup, you must create a page to edit options (these options will be saved in the [[Table llx_const|table &#039;&#039;&#039;llx_const&#039;&#039;&#039;]]).&lt;br /&gt;
Create a page named &#039;&#039;&#039;mymodule_setuppage.php&#039;&#039;&#039; that shows a form for possible options to update them into the above-mentioned table.&lt;br /&gt;
It is necessary to take an example from a page of the directory &#039;&#039;&#039;/admin&#039;&#039;&#039; that will show you the way to read/save your parameters.&lt;br /&gt;
Put this PHP page into the directory &#039;&#039;&#039;/admin&#039;&#039;&#039; of your module (e.g. mymodule/admin/mymodule_setuppage.php).&lt;br /&gt;
&lt;br /&gt;
===Modify the descriptor file of your module===&lt;br /&gt;
Then, within the descriptor file of your module, modify the variable &#039;&#039;&#039;config_page_url&#039;&#039;&#039; to set the name of this PHP page.&lt;br /&gt;
If the page is in the directory &#039;&#039;&#039;admin/&#039;&#039;&#039;, then the path is not required, e.g. like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;config_page_url = array(&amp;quot;mymodule_setuppage.php&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
If the page is in the directory &#039;&#039;&#039;mymodule/admin/&#039;&#039;&#039;, then like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;config_page_url = array(&amp;quot;mymodule_setuppage.php@mymodule&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Test your page===&lt;br /&gt;
Go into page &#039;&#039;&#039;Home-&amp;gt;Setup-&amp;gt;Modules&#039;&#039;&#039;, you should see a picture at the end of the line of your module to reach your setup page. Click on it, you should be able to view/edit parameters from your page.&lt;br /&gt;
&lt;br /&gt;
==Define your entries in menu (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If you have created PHP pages, it is necessary that those pages can be reached from menu entries in Dolibarr menu.&lt;br /&gt;
&lt;br /&gt;
===Define your menu entries===&lt;br /&gt;
For this, you must define into the module descriptor, the array this-&amp;gt;menu that declares all menus added by your module.&lt;br /&gt;
This array contains entries that will appear once your module is activated.&lt;br /&gt;
The example module descriptor file &#039;&#039;&#039;modMyModule.class.php&#039;&#039;&#039; contains an example to declare a top menu and also its left menu entries.&lt;br /&gt;
&lt;br /&gt;
This is the example of code to declare your own menu entries in a module descriptor file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
// Main menu entries&lt;br /&gt;
$this-&amp;gt;menu = array();			// List of menus to add&lt;br /&gt;
$r=0;&lt;br /&gt;
&lt;br /&gt;
// Add here entries to declare new menus&lt;br /&gt;
// Example to declare the Top Menu entry:&lt;br /&gt;
$this-&amp;gt;menu[$r]=array(	&#039;fk_menu&#039;=&amp;gt;0,			// Put 0 if this is a top menu&lt;br /&gt;
			&#039;type&#039;=&amp;gt;&#039;top&#039;,			// This is a Top menu entry&lt;br /&gt;
			&#039;titre&#039;=&amp;gt;&#039;MyModule top menu&#039;,&lt;br /&gt;
			&#039;mainmenu&#039;=&amp;gt;&#039;mymodule&#039;,&lt;br /&gt;
			&#039;leftmenu&#039;=&amp;gt;&#039;mymodule&#039;,&lt;br /&gt;
			&#039;url&#039;=&amp;gt;&#039;/mymodule/pagetop.php&#039;,&lt;br /&gt;
			&#039;langs&#039;=&amp;gt;&#039;mylangfile&#039;,	// Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.&lt;br /&gt;
			&#039;position&#039;=&amp;gt;100,&lt;br /&gt;
			&#039;enabled&#039;=&amp;gt;&#039;1&#039;,			// Define condition to show or hide menu entry. Use &#039;$conf-&amp;gt;mymodule-&amp;gt;enabled&#039; if entry must be visible if module is enabled.&lt;br /&gt;
			&#039;perms&#039;=&amp;gt;&#039;1&#039;,			// Use &#039;perms&#039;=&amp;gt;&#039;$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;level1-&amp;gt;level2&#039; if you want your menu with a permission rules&lt;br /&gt;
			&#039;target&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
			&#039;user&#039;=&amp;gt;2);				// 0=Menu for internal users, 1=external users, 2=both&lt;br /&gt;
$r++;&lt;br /&gt;
&lt;br /&gt;
// Example to declare a Left Menu entry:&lt;br /&gt;
$this-&amp;gt;menu[$r]=array(	&#039;fk_menu&#039;=&amp;gt;&#039;fk_mainmenu=xxx&#039;,		    // Use &#039;fk_mainmenu=xxx&#039; or &#039;fk_mainmenu=xxx,fk_leftmenu=yyy&#039; where xxx is mainmenucode and yyy is a leftmenucode of parent menu&lt;br /&gt;
			&#039;type&#039;=&amp;gt;&#039;left&#039;,			        // This is a Left menu entry&lt;br /&gt;
			&#039;titre&#039;=&amp;gt;&#039;MyModule left menu 1&#039;,&lt;br /&gt;
			&#039;mainmenu&#039;=&amp;gt;&#039;xxx&#039;,&lt;br /&gt;
			&#039;leftmenu&#039;=&amp;gt;&#039;yyy&#039;,&lt;br /&gt;
			&#039;url&#039;=&amp;gt;&#039;/mymodule/pagelevel1.php&#039;,&lt;br /&gt;
			&#039;langs&#039;=&amp;gt;&#039;mylangfile&#039;,	// Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.&lt;br /&gt;
			&#039;position&#039;=&amp;gt;100,&lt;br /&gt;
			&#039;enabled&#039;=&amp;gt;&#039;1&#039;,			// Define condition to show or hide menu entry. Use &#039;$conf-&amp;gt;mymodule-&amp;gt;enabled&#039; if entry must be visible if module is enabled.&lt;br /&gt;
			&#039;perms&#039;=&amp;gt;&#039;1&#039;,			// Use &#039;perms&#039;=&amp;gt;&#039;$user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;level1-&amp;gt;level2&#039; if you want your menu with a permission rules&lt;br /&gt;
			&#039;target&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
			&#039;user&#039;=&amp;gt;2);				// 0=Menu for internal users,1=external users, 2=both&lt;br /&gt;
$r++;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To show the menu or not depending on a permission, modify property &#039;&#039;&#039;perms&#039;&#039;&#039; in the array. See chapter on permissions later to see how to add permissions.&lt;br /&gt;
&lt;br /&gt;
===Test your menu entries===&lt;br /&gt;
Disable and re-enable your module under the Dolibarr module setup page, menus entries must appear (if property &#039;enabled&#039; is declaration array is ok).&lt;br /&gt;
&lt;br /&gt;
==Add your own permissions (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If you want to add new permissions.&lt;br /&gt;
&lt;br /&gt;
The way to define permissions that will manage your module is done inside the module descriptor created previously.&lt;br /&gt;
Modify line &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;rights_class = &#039;mymodule&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
with correct value for mymodule.&lt;br /&gt;
&lt;br /&gt;
Then you must fill the array $this-&amp;gt;rights with as many entries than different permissions you need to manage.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;rights[$r][0] = 10001;&lt;br /&gt;
$this-&amp;gt;rights[$r][1] = &#039;Label by default of permission&#039;;&lt;br /&gt;
$this-&amp;gt;rights[$r][2] = &#039;r&#039;;&lt;br /&gt;
$this-&amp;gt;rights[$r][3] = 1;&lt;br /&gt;
$this-&amp;gt;rights[$r][4] = &#039;action&#039;;&lt;br /&gt;
$this-&amp;gt;rights[$r][5] = &#039;subaction&#039;;&lt;br /&gt;
$r++;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Into $this-&amp;gt;rights[$r][0], put a permission id not already used (See into menu &#039;&#039;&#039;System info&#039;&#039;&#039; on a working installation of Dolibarr to know list of id already used by standard modules.&lt;br /&gt;
Into $this-&amp;gt;rights[$r][1], put a label by default for permission (This label will be used if no translation can be found into the file &#039;&#039;&#039;admin.lang&#039;&#039;&#039; Translation key should be &amp;quot;Permission10001=My permission Label&amp;quot;).&lt;br /&gt;
Into $this-&amp;gt;rights[$r][2], types of the permission. There are three type of permission, &#039;r&#039; for read, list or expert permission, &#039;w&#039; for write or update permission and &#039;d&#039; for delete permission.&lt;br /&gt;
Into $this-&amp;gt;rights[$r][3], put 1 if this permission must be granted automatically by default to any newly created user.&lt;br /&gt;
Into $this-&amp;gt;rights[$r][4] and $this-&amp;gt;rights[$r][5], put an action and subaction string without spaces. You will be able to test if a user has the permission in your PHP source code with the sequence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($user-&amp;gt;rights-&amp;gt;mymodule-&amp;gt;action-&amp;gt;subaction) ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Define your own box (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If your module needs to provide one or several new boxes to show on home page.&lt;br /&gt;
&lt;br /&gt;
===Define your box===&lt;br /&gt;
For this, modify the array $this-&amp;gt;boxes into the module descriptor file.&lt;br /&gt;
All you have to do is to add 2 lines for each box file you will create into directory &#039;&#039;&#039;htdocs/mymodule/core/boxes&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Example:&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;boxes[0][&#039;file&#039;]=&#039;mybox0.php@mymodule&#039;&lt;br /&gt;
$this-&amp;gt;boxes[0][&#039;note&#039;]=&#039;My box 0&#039;&lt;br /&gt;
 ...&lt;br /&gt;
$this-&amp;gt;boxes[n][&#039;file&#039;]=&#039;myboxn.php@mymodule&#039;&lt;br /&gt;
$this-&amp;gt;boxes[n][&#039;note&#039;]=&#039;My box n&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then create files &#039;&#039;&#039;htdocs/mymodule/core/boxes/mybox0.php&#039;&#039;&#039;, &#039;&#039;&#039;htdocs/mymodule/core/boxes/mybox1.php&#039;&#039;&#039;... by copying an example from an existing box file (found into directory &#039;&#039;&#039;htdocs/core/boxes&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
===Test if your box is detected by Dolibarr===&lt;br /&gt;
Disable and enabled module.&lt;br /&gt;
&lt;br /&gt;
Go into menu &#039;&#039;&#039;Home - Setup - Boxes&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Your boxes must appear in the list of boxes you can activate. Activate the box and go on the home page to see if the box is showing correctly.&lt;br /&gt;
&lt;br /&gt;
==Define your own export (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If your module provides new predefined database export profiles (for its own tables or for already existing tables of another module).&lt;br /&gt;
&lt;br /&gt;
===Define export===&lt;br /&gt;
For this uncomment and modify arrays $this-&amp;gt;export_xxx in your module descriptor file.&lt;br /&gt;
&lt;br /&gt;
===Test your export===&lt;br /&gt;
Go into menu Tools -&amp;gt; Export. Your export will appear in the list of available predefined exports (if your module is enabled).&lt;br /&gt;
Choose it, you must see a list of all possible fields defined in the export arrays.&lt;br /&gt;
Choose on field and try to build an export file. If ok, try again with all fields.&lt;br /&gt;
&lt;br /&gt;
==Define your CSS styles (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If in your PHP pages, you use class styles that are not defined inside Dolibarr themes CSS (not recommanded).&lt;br /&gt;
&lt;br /&gt;
===Create and declare your style sheet===&lt;br /&gt;
Create a style sheet CSS named &#039;&#039;&#039;mymodule.css&#039;&#039;&#039; or &#039;&#039;&#039;mymodule.css.php&#039;&#039;&#039; and put it into directory &#039;&#039;&#039;htdocs/mymodule&#039;&#039;&#039;. You can have several CSS files per module.&lt;br /&gt;
Remember it&#039;s better to use existing styles already available by default into Dolibarr (The CSS file used by Dolibarr is file &#039;&#039;&#039;themes/mytheme/&#039;&#039;themename&#039;&#039;.css.php&#039;&#039;&#039;. Create your own CSS files only if you need absolutely to add not already existing styles.&lt;br /&gt;
&lt;br /&gt;
Once your style sheets are ready, declare them into your module descriptor file by modifying the property &#039;&#039;&#039;$this-&amp;gt;modules_parts&#039;&#039;&#039;.&lt;br /&gt;
Value to put here must be an array of relative URLs to your CSS files.&lt;br /&gt;
For example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;module_parts = array(&#039;css&#039; =&amp;gt; array(&#039;/mymodule/css/mymodule.css.php&#039;,&#039;/mymodule/css/myother.css&#039;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Test your style sheet===&lt;br /&gt;
Disable and enable your module.&lt;br /&gt;
&lt;br /&gt;
Go on the home page (index.php). Show the HTML source of the page.&lt;br /&gt;
&lt;br /&gt;
You should see into the HTML header, a line that declares your style sheet.&lt;br /&gt;
&lt;br /&gt;
==Add your Javascript functions (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If in your PHP pages, you use javascript functions not available in Dolibarr (in file lib_head.js)&lt;br /&gt;
&lt;br /&gt;
If you need to use your own javascript functions inside your PHP pages, it is necessary to have your functions, defined into your javascript file &#039;&#039;&#039;htdocs/mymodule/js/mymodule.js&#039;&#039;&#039;, included into the HTML HEAD section.&lt;br /&gt;
To ask Dolibarr that forge this header to include your own javascript file, you must just provide it to the llxHeader() function called by your page.&lt;br /&gt;
&lt;br /&gt;
Example for page /htdocs/mymodule/mypage.php :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$morejs=array(&amp;quot;/mymodule/js/mymodule.js&amp;quot;);&lt;br /&gt;
llxHeader(&#039;&#039;,&#039;Titre&#039;,&#039;&#039;,&#039;&#039;,&#039;&#039;,&#039;&#039;,$morejs,&#039;&#039;,0,0); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Run your own code on any Dolibarr event (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: If you want to execute your own code once a common Dolibarr event has occurred (example: I want to update a table in my module when an invoice is created into Dolibarr), you must create a &#039;&#039;&#039;triggers&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
See also [[Interfaces_Dolibarr_toward_foreign_systems]]&lt;br /&gt;
and [[Interfaces_from_foreign_systems_toward_Dolibarr]]&lt;br /&gt;
&lt;br /&gt;
==Insert your code inside Dolibarr hooks positions (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: When you want to add code or replace Dolibarr code into another situation than a business event (See the previous chapter for adding code during a business event).&lt;br /&gt;
&lt;br /&gt;
See page [[Hooks_system]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Add your own numbering rules==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: When you need a new rule for generated ref of elements that are not covered by existing rules.&lt;br /&gt;
&lt;br /&gt;
See page [[Create numbering module]].&lt;br /&gt;
&lt;br /&gt;
==Add your document template (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: When you want to personalized your own generated PDF or ODT documents.&lt;br /&gt;
&lt;br /&gt;
Note: To add this feature you don&#039;t need to create a module descriptor.&lt;br /&gt;
&lt;br /&gt;
Documentation to add your own template is available on page [[Create_a_PDF_document_template]] or [[Create_an_ODT_document_template]].&lt;br /&gt;
&lt;br /&gt;
==Add your skin (optional)==&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;: When you want to personalized your colors/fonts/images.&lt;br /&gt;
&lt;br /&gt;
Note: To add this feature you don&#039;t need to create a module descriptor.&lt;br /&gt;
&lt;br /&gt;
To add your own skin, read page [[Skins]].&lt;br /&gt;
&lt;br /&gt;
=Some coding rules and predefined functions=&lt;br /&gt;
The coding rules to be followed are defined in the [[Developer documentation]], under section &amp;quot;General Information - Language and standards development&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
A lot of predefined features for developers are also available and described into page [[Developer documentation]] under section &amp;quot;Technical components of Dolibarr&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Create a package to distribute and install your module=&lt;br /&gt;
This process must be used to generate a package to submit it on the http://www.dolistore.com marketplace.&lt;br /&gt;
But you can use it to have a package easy to distribute on your own network.&lt;br /&gt;
&lt;br /&gt;
*Go into the directory &#039;&#039;&#039;/build&#039;&#039;&#039; and copy the file &#039;&#039;&#039;makepack-dolibarrmodules.conf&#039;&#039;&#039; into &#039;&#039;&#039;makepack-mymodule.conf&#039;&#039;&#039;. Warning, this directory may not be provided in some packages of stable versions. If so, it can be retrieved from the snapshot available for download on the Dolibarr website in area &amp;quot;Development version&amp;quot; (taken in this case the whole build directory which is autonomous and independent directory).&lt;br /&gt;
&lt;br /&gt;
Edit this file to add a list of file names for all new files you created for your module (module descriptor, new sql tables files, php page, images, etc...)&lt;br /&gt;
&lt;br /&gt;
*Run the script via Perl (need the Perl version 5.0 or later):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
perl makepack-dolibarrmodule.pl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The script asks you the name of your module, its major and minor version. A file &#039;&#039;&#039;mymodule.zip &#039;&#039;&#039; will then be manufactured containing your module ready to be deployed.&lt;br /&gt;
&lt;br /&gt;
*The person who receives your module must then place the file in the root directory of a Dolibarr installation and perform the command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar -xvf mymodule.zip&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If you want your module to be public, you can submit it (the zip file) on Dolibarr marketplace website: {{LinkToPluginDownload}} (you must create an account first and be logged to use the link &amp;quot;Submit a module/product&amp;quot;).&lt;br /&gt;
**If your module was built correctly, the file will be validated later.&lt;br /&gt;
**If quality is enough and license permits it, the code might be added inside main Dolibarr sources (except if you disagree for that).&lt;br /&gt;
&lt;br /&gt;
=Enabling/activation condition of external module on DoliStore=&lt;br /&gt;
&lt;br /&gt;
See [[Module_Dolistore_Validation_Rules|Validation Rules]]&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Alograg</name></author>
	</entry>
</feed>