From 4d9ae5bb44bd967024c70b2dfa875ddeb7fc8fc9 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Sun, 16 Jul 2017 14:57:30 +0200
Subject: [PATCH] Work on modulebuilder

---
 htdocs/core/lib/admin.lib.php                 |   3 +-
 htdocs/langs/en_US/modulebuilder.lang         |   4 +-
 htdocs/modulebuilder/index.php                |  65 ++++-
 .../core/modules/modMyModule.class.php        | 112 +++++----
 .../modulebuilder/template/mymoduleindex.php  | 237 ++++++++++++++++++
 5 files changed, 369 insertions(+), 52 deletions(-)
 create mode 100644 htdocs/modulebuilder/template/mymoduleindex.php

diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php
index e90f006ac7e..04393fa4d29 100644
--- a/htdocs/core/lib/admin.lib.php
+++ b/htdocs/core/lib/admin.lib.php
@@ -931,7 +931,8 @@ function unActivateModule($value, $requiredby=1)
     {
         //print $dir.$modFile;
     	// TODO Replace this after DolibarrModules is moved as abstract class with a try catch to show module we try to disable has not been found or could not be loaded
-        $genericMod = new DolibarrModules($db);
+        include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php';
+    	$genericMod = new DolibarrModules($db);
         $genericMod->name=preg_replace('/^mod/i','',$modName);
         $genericMod->rights_class=strtolower(preg_replace('/^mod/i','',$modName));
         $genericMod->const_name='MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',$modName));
diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang
index 2c3744b1b93..bbaf00dcaf4 100644
--- a/htdocs/langs/en_US/modulebuilder.lang
+++ b/htdocs/langs/en_US/modulebuilder.lang
@@ -12,7 +12,7 @@ ModuleInitialized=Module initialized
 FilesForObjectInitialized=Files for new object '%s' initialized
 FilesForObjectUpdated=Files for object '%s' updated (.sql files and .class.php file)
 ModuleBuilderDescdescription=Enter here all general information that describe your module
-ModuleBuilderDescspecifications=You can enter here a long text to describe the specifications of your module that is not already structured into other tabs. So you have on hand the rules to develop. Also this text content will be included into the generated documentation (see last tab).
+ModuleBuilderDescspecifications=You can enter here a long text to describe the specifications of your module that is not already structured into other tabs. So you have within easy reach all the rules to develop. Also this text content will be included into the generated documentation (see last tab).
 ModuleBuilderDescobjects=Define here the objects you want to manage with your module. A sql file, a page to list them, to create/edit/view a card and an API will be generated.
 ModuleBuilderDescmenus=This tab is dedicated to define menu entries provided by your module.
 ModuleBuilderDescpermissions=This tab is dedicated to define the new permissions you want to provide with your module.
@@ -25,7 +25,7 @@ EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All files relat
 DangerZone=Danger zone
 BuildPackage=Build package/documentation
 BuildDocumentation=Build documentation
-ModuleIsNotActive=This module was not activated yet (go into %s to make it live)
+ModuleIsNotActive=This module was not activated yet. Ggo into %s to make it live or click here:
 ModuleIsLive=This module has been activated. Any change on it may break a current active feature.
 DescriptionLong=Long description
 EditorName=Name of editor
diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php
index eb3591fefa9..67581d921c5 100644
--- a/htdocs/modulebuilder/index.php
+++ b/htdocs/modulebuilder/index.php
@@ -24,6 +24,7 @@ if (! defined('NOSCANPOSTFORINJECTION'))   define('NOSCANPOSTFORINJECTION','1');
 
 require '../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
 
@@ -389,8 +390,6 @@ if ($dirins && $action == 'confirm_deleteproperty' && $propertykey)
     }
 }
 
-
-
 if ($dirins && $action == 'generatepackage')
 {
     $modulelowercase=strtolower($module);
@@ -449,7 +448,6 @@ if ($dirins && $action == 'generatepackage')
     }
 }
 
-
 // Save file
 if ($action == 'savefile' && empty($cancel))
 {
@@ -479,6 +477,47 @@ if ($action == 'savefile' && empty($cancel))
     }
 }
 
+// Enable module
+if ($action == 'set' && $user->admin)
+{
+	$param='module='.$module;
+	$value = GETPOST('value','alpha');
+	$resarray = activateModule($value);
+	if (! empty($resarray['errors'])) setEventMessages('', $resarray['errors'], 'errors');
+	else
+	{
+		//var_dump($resarray);exit;
+		if ($resarray['nbperms'] > 0)
+		{
+			$tmpsql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."user WHERE admin <> 1";
+			$resqltmp=$db->query($tmpsql);
+			if ($resqltmp)
+			{
+				$obj=$db->fetch_object($resqltmp);
+				//var_dump($obj->nb);exit;
+				if ($obj && $obj->nb > 1)
+				{
+					$msg = $langs->trans('ModuleEnabledAdminMustCheckRights');
+					setEventMessages($msg, null, 'warnings');
+				}
+			}
+			else dol_print_error($db);
+		}
+	}
+	header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
+	exit;
+}
+
+// Disable module
+if ($action == 'reset' && $user->admin)
+{
+	$param='module='.$module;
+	$value = GETPOST('value','alpha');
+	$result=unActivateModule($value);
+	if ($result) setEventMessages($result, null, 'errors');
+	header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
+	exit;
+}
 
 
 /*
@@ -674,8 +713,24 @@ elseif (! empty($module))
         $h=0;
 
         $modulelowercase=strtolower($module);
+        $const_name = 'MAIN_MODULE_'.strtoupper($module);
 
+        $param='&tab='.$tab.'&module='.$module;
         $urltomodulesetup='<a href="'.DOL_URL_ROOT.'/admin/modules.php?search_keyword='.urlencode($module).'">'.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").'</a>';
+        $linktoenabledisable='';
+        if (! empty($conf->global->$const_name))	// If module is already activated
+        {
+        	$linktoenabledisable.='<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=reset&value=mod' . $module . $param . '">';
+        	$linktoenabledisable.=img_picto($langs->trans("Activated"),'switch_on');
+        	$linktoenabledisable.='</a>';
+        }
+        else
+        {
+        	$linktoenabledisable.='<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=set&value=mod' . $module . $param . '">';
+        	$linktoenabledisable.=img_picto($langs->trans("Disabled"),'switch_off');
+        	$linktoenabledisable.="</a>\n";
+        }
+
         $modulestatusinfo=img_info('').' '.$langs->trans("ModuleIsNotActive", $urltomodulesetup);
         if (! empty($conf->$module->enabled))
         {
@@ -727,7 +782,9 @@ elseif (! empty($module))
         $head2[$h][2] = 'buildpackage';
         $h++;
 
-        print $modulestatusinfo.'<br><br>';
+        print $modulestatusinfo;
+        print ' '.$linktoenabledisable;
+        print '<br><br>';
 
         dol_fiche_head($head2, $tab, '', -1, '');
 
diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php
index d91b4c6a495..8c7da67b7ab 100644
--- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php
+++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php
@@ -87,7 +87,7 @@ class modMyModule extends DolibarrModules
 		$this->module_parts = array(
 		                        	'triggers' => 1,                                 	// Set this to 1 if module has its own trigger directory (core/triggers)
 									'login' => 0,                                    	// Set this to 1 if module has its own login method directory (core/login)
-									'substitutions' => 0,                            	// Set this to 1 if module has its own substitution function file (core/substitutions)
+									'substitutions' => 1,                            	// Set this to 1 if module has its own substitution function file (core/substitutions)
 									'menus' => 0,                                    	// Set this to 1 if module has its own menus handler directory (core/menus)
 									'theme' => 0,                                    	// Set this to 1 if module has its own theme directory (theme)
 		                        	'tpl' => 0,                                      	// Set this to 1 if module overwrite template dir (core/tpl)
@@ -110,8 +110,8 @@ class modMyModule extends DolibarrModules
 		$this->depends = array();		// List of module class names as string that must be enabled if this module is enabled
 		$this->requiredby = array();	// List of module ids to disable if this one is disabled
 		$this->conflictwith = array();	// List of module class names as string this module is in conflict with
-		$this->phpmin = array(5,0);					// Minimum version of PHP required by module
-		$this->need_dolibarr_version = array(3,0);	// Minimum version of Dolibarr required by module
+		$this->phpmin = array(5,3);					// Minimum version of PHP required by module
+		$this->need_dolibarr_version = array(4,0);	// Minimum version of Dolibarr required by module
 		$this->langfiles = array("mymodule@mymodule");
 		$this->warnings_activation = array();                     // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','ES'='textes'...)
 		$this->warnings_activation_ext = array();                 // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','ES'='textes'...)
@@ -121,7 +121,9 @@ class modMyModule extends DolibarrModules
 		// Example: $this->const=array(0=>array('MYMODULE_MYNEWCONST1','chaine','myvalue','This is a constant to add',1),
 		//                             1=>array('MYMODULE_MYNEWCONST2','chaine','myvalue','This is another constant to add',0, 'current', 1)
 		// );
-		$this->const = array();
+		$this->const = array(
+			1=>array('MYMODULE_MYCONSTANT', 'chaine', 'avalue', 'This is a constant to add', 1, 'allentities', 1)
+		);
 
 		// Array to add new pages in new tabs
 		// Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__',  					// To add a new tab identified by code tabname1
@@ -183,7 +185,9 @@ class modMyModule extends DolibarrModules
 
 
 		// Cronjobs
-		$this->cronjobs = array();			// List of cron jobs entries to add
+		$this->cronjobs = array(
+			0=>array('label'=>'MyJob label', 'jobtype'=>'method', 'class'=>'/mymodule/class/mymodulemyjob.class.php', 'objectname'=>'MyModuleMyJob', 'method'=>'myMethod', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'test'=>true)
+		);			// List of cron jobs entries to add
 		// Example: $this->cronjobs=array(0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'test'=>true),
 		//                                1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'test'=>true)
 		// );
@@ -219,57 +223,75 @@ class modMyModule extends DolibarrModules
 		$r=0;
 
 		// Add here entries to declare new menus
-		//
+
 		// Example to declare a new Top Menu entry and its Left menu entry:
-		// $this->menu[$r]=array(	'fk_menu'=>'',			                // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
-		//							'type'=>'top',			                // This is a Top menu entry
-		//							'titre'=>'MyModule top menu',
-		//							'mainmenu'=>'mymodule',
-		//							'leftmenu'=>'mymodule',
-		//							'url'=>'/mymodule/pagetop.php',
-		//							'langs'=>'mylangfile@mymodule',	        // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
-		//							'position'=>100,
-		//							'enabled'=>'$conf->mymodule->enabled',	// Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled.
-		//							'perms'=>'1',			                // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules
-		//							'target'=>'',
-		//							'user'=>2);				                // 0=Menu for internal users, 1=external users, 2=both
+		/* BEGIN MODULEBUILDER TOPMENU */
+		$this->menu[$r]=array(	'fk_menu'=>'',			                // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
+								'type'=>'top',			                // This is a Top menu entry
+								'titre'=>'MyModule',
+								'mainmenu'=>'mymodule',
+								'leftmenu'=>'',
+								'url'=>'/mymodule/mymoduleindex.php',
+								'langs'=>'mymodule@mymodule',	        // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
+								'position'=>1000,
+								'enabled'=>'$conf->mymodule->enabled',	// Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled.
+								'perms'=>'1',			                // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules
+								'target'=>'',
+								'user'=>2);				                // 0=Menu for internal users, 1=external users, 2=both
 		// $r++;
-		//
+		/* END MODULEBUILDER TOPMENU */
+
 		// Example to declare a Left Menu entry into an existing Top menu entry:
-		// $this->menu[$r]=array(	'fk_menu'=>'fk_mainmenu=xxx',		    // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
-		//							'type'=>'left',			                // This is a Left menu entry
-		//							'titre'=>'MyModule left menu',
-		//							'mainmenu'=>'xxx',
-		//							'leftmenu'=>'mymodule',
-		//							'url'=>'/mymodule/pagelevel2.php',
-		//							'langs'=>'mylangfile@mymodule',	        // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
-		//							'position'=>100,
-		//							'enabled'=>'$conf->mymodule->enabled',  // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
-		//							'perms'=>'1',			                // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules
-		//							'target'=>'',
-		//							'user'=>2);				                // 0=Menu for internal users, 1=external users, 2=both
-		// $r++;
+		/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT
+		$this->menu[$r]=array(	'fk_menu'=>'fk_mainmenu=mymodule',	    // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
+								'type'=>'left',			                // This is a Left menu entry
+								'titre'=>'List MyObject',
+								'mainmenu'=>'mymodule',
+								'leftmenu'=>'mymodule',
+								'url'=>'/mymodule/myobject_list.php',
+								'langs'=>'mymodule@mymodule',	        // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
+								'position'=>1100,
+								'enabled'=>'$conf->mymodule->enabled',  // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
+								'perms'=>'1',			                // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules
+								'target'=>'',
+								'user'=>2);				                // 0=Menu for internal users, 1=external users, 2=both
+		$r++;
+		$this->menu[$r]=array(	'fk_menu'=>'fk_mainmenu=mymodule&fk_leftmenu=mymodule',	    // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
+								'type'=>'left',			                // This is a Left menu entry
+								'titre'=>'New MyObject',
+								'mainmenu'=>'mymodule',
+								'leftmenu'=>'mymodule',
+								'url'=>'/mymodule/myobject_page.php?action=create',
+								'langs'=>'mymodule@mymodule',	        // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
+								'position'=>1101,
+								'enabled'=>'$conf->mymodule->enabled',  // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
+								'perms'=>'1',			                // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules
+								'target'=>'',
+								'user'=>2);				                // 0=Menu for internal users, 1=external users, 2=both
+		$r++;
+		END MODULEBUILDER LEFTMENU MYOBJECT */
 
 
 		// Exports
 		$r=1;
 
 		// Example:
-		// $this->export_code[$r]=$this->rights_class.'_'.$r;
-		// $this->export_label[$r]='MyModule';	// Translation key (used only if key ExportDataset_xxx_z not found)
-        // $this->export_enabled[$r]='1';                               // Condition to show export in list (ie: '$user->id==3'). Set to 1 to always show when module is enabled.
-        // $this->export_icon[$r]='generic:MyModule';					// Put here code of icon then string for translation key of module name
-		// $this->export_permission[$r]=array(array("mymodule","level1","level2"));
-		// $this->export_fields_array[$r]=array('s.rowid'=>"IdCompany",'s.nom'=>'CompanyName','s.address'=>'Address','s.zip'=>'Zip','s.town'=>'Town','s.fk_pays'=>'Country','s.phone'=>'Phone','s.siren'=>'ProfId1','s.siret'=>'ProfId2','s.ape'=>'ProfId3','s.idprof4'=>'ProfId4','s.code_compta'=>'CustomerAccountancyCode','s.code_compta_fournisseur'=>'SupplierAccountancyCode','f.rowid'=>"InvoiceId",'f.facnumber'=>"InvoiceRef",'f.datec'=>"InvoiceDateCreation",'f.datef'=>"DateInvoice",'f.total'=>"TotalHT",'f.total_ttc'=>"TotalTTC",'f.tva'=>"TotalVAT",'f.paye'=>"InvoicePaid",'f.fk_statut'=>'InvoiceStatus','f.note'=>"InvoiceNote",'fd.rowid'=>'LineId','fd.description'=>"LineDescription",'fd.price'=>"LineUnitPrice",'fd.tva_tx'=>"LineVATRate",'fd.qty'=>"LineQty",'fd.total_ht'=>"LineTotalHT",'fd.total_tva'=>"LineTotalTVA",'fd.total_ttc'=>"LineTotalTTC",'fd.date_start'=>"DateStart",'fd.date_end'=>"DateEnd",'fd.fk_product'=>'ProductId','p.ref'=>'ProductRef');
-		// $this->export_TypeFields_array[$r]=array('t.date'=>'Date', 't.qte'=>'Numeric', 't.poids'=>'Numeric', 't.fad'=>'Numeric', 't.paq'=>'Numeric', 't.stockage'=>'Numeric', 't.fadparliv'=>'Numeric', 't.livau100'=>'Numeric', 't.forfait'=>'Numeric', 's.nom'=>'Text','s.address'=>'Text','s.zip'=>'Text','s.town'=>'Text','c.code'=>'Text','s.phone'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','s.code_compta'=>'Text','s.code_compta_fournisseur'=>'Text','s.tva_intra'=>'Text','f.facnumber'=>"Text",'f.datec'=>"Date",'f.datef'=>"Date",'f.date_lim_reglement'=>"Date",'f.total'=>"Numeric",'f.total_ttc'=>"Numeric",'f.tva'=>"Numeric",'f.paye'=>"Boolean",'f.fk_statut'=>'Status','f.note_private'=>"Text",'f.note_public'=>"Text",'fd.description'=>"Text",'fd.subprice'=>"Numeric",'fd.tva_tx'=>"Numeric",'fd.qty'=>"Numeric",'fd.total_ht'=>"Numeric",'fd.total_tva'=>"Numeric",'fd.total_ttc'=>"Numeric",'fd.date_start'=>"Date",'fd.date_end'=>"Date",'fd.special_code'=>'Numeric','fd.product_type'=>"Numeric",'fd.fk_product'=>'List:product:label','p.ref'=>'Text','p.label'=>'Text','p.accountancy_code_sell'=>'Text');
-		// $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company','s.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company','f.rowid'=>"invoice",'f.facnumber'=>"invoice",'f.datec'=>"invoice",'f.datef'=>"invoice",'f.total'=>"invoice",'f.total_ttc'=>"invoice",'f.tva'=>"invoice",'f.paye'=>"invoice",'f.fk_statut'=>'invoice','f.note'=>"invoice",'fd.rowid'=>'invoice_line','fd.description'=>"invoice_line",'fd.price'=>"invoice_line",'fd.total_ht'=>"invoice_line",'fd.total_tva'=>"invoice_line",'fd.total_ttc'=>"invoice_line",'fd.tva_tx'=>"invoice_line",'fd.qty'=>"invoice_line",'fd.date_start'=>"invoice_line",'fd.date_end'=>"invoice_line",'fd.fk_product'=>'product','p.ref'=>'product');
-		// $this->export_dependencies_array[$r]=array('invoice_line'=>'fd.rowid','product'=>'fd.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them
+		/* BEGIN MODULEBUILDER EXPORT MYOBJECT
+		$this->export_code[$r]=$this->rights_class.'_'.$r;
+		$this->export_label[$r]='MyModule';	                         // Translation key (used only if key ExportDataset_xxx_z not found)
+        $this->export_enabled[$r]='1';                               // Condition to show export in list (ie: '$user->id==3'). Set to 1 to always show when module is enabled.
+        $this->export_icon[$r]='generic:MyModule';					 // Put here code of icon then string for translation key of module name
+		//$this->export_permission[$r]=array(array("mymodule","level1","level2"));
+        $this->export_fields_array[$r]=array('t.rowid'=>"Id",'t.ref'=>'Ref','t.label'=>'Label','t.datec'=>"DateCreation",'t.tms'=>"DateUpdate");
+		$this->export_TypeFields_array[$r]=array('t.rowid'=>'Numeric', 't.ref'=>'Text', 't.label'=>'Label', 't.datec'=>"Date", 't.tms'=>"Date");
+		// $this->export_entities_array[$r]=array('t.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company','s.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company','f.rowid'=>"invoice",'f.facnumber'=>"invoice",'f.datec'=>"invoice",'f.datef'=>"invoice",'f.total'=>"invoice",'f.total_ttc'=>"invoice",'f.tva'=>"invoice",'f.paye'=>"invoice",'f.fk_statut'=>'invoice','f.note'=>"invoice",'fd.rowid'=>'invoice_line','fd.description'=>"invoice_line",'fd.price'=>"invoice_line",'fd.total_ht'=>"invoice_line",'fd.total_tva'=>"invoice_line",'fd.total_ttc'=>"invoice_line",'fd.tva_tx'=>"invoice_line",'fd.qty'=>"invoice_line",'fd.date_start'=>"invoice_line",'fd.date_end'=>"invoice_line",'fd.fk_product'=>'product','p.ref'=>'product');
+		// $this->export_dependencies_array[$r]=array('invoice_line'=>'fd.rowid','product'=>'fd.rowid');   // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them
 		// $this->export_sql_start[$r]='SELECT DISTINCT ';
-		// $this->export_sql_end[$r]  =' FROM ('.MAIN_DB_PREFIX.'facture as f, '.MAIN_DB_PREFIX.'facturedet as fd, '.MAIN_DB_PREFIX.'societe as s)';
-		// $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)';
-		// $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture';
-		// $this->export_sql_order[$r] .=' ORDER BY s.nom';
+		// $this->export_sql_end[$r]  =' FROM '.MAIN_DB_PREFIX.'myobject as t';
+		// $this->export_sql_order[$r] .=' ORDER BY t.ref';
 		// $r++;
+		END MODULEBUILDER EXPORT MYOBJECT */
+
 	}
 
 	/**
diff --git a/htdocs/modulebuilder/template/mymoduleindex.php b/htdocs/modulebuilder/template/mymoduleindex.php
new file mode 100644
index 00000000000..f1c92659f9b
--- /dev/null
+++ b/htdocs/modulebuilder/template/mymoduleindex.php
@@ -0,0 +1,237 @@
+<?php
+/* Copyright (C) 2001-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
+ * Copyright (C) 2004-2015 Laurent Destailleur  <eldy@users.sourceforge.net>
+ * Copyright (C) 2005-2012 Regis Houssin        <regis.houssin@capnetworks.com>
+ * Copyright (C) 2015      Jean-François Ferry	<jfefe@aternatik.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ *	\file       htdocs/mymodule/template/mymoduleindex.php
+ *	\ingroup    mymodule
+ *	\brief      Home page of mymodule top menu
+ */
+
+// Load Dolibarr environment
+$res=0;
+// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
+if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php");
+// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME
+$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1;
+while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; }
+if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php");
+if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php");
+// Try main.inc.php using relative path
+if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php");
+if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php");
+if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php");
+if (! $res) die("Include of main fails");
+
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
+
+if (! $user->rights->mymodule->read) accessforbidden();
+
+$langs->load("mymodule@mymodule");
+
+$action=GETPOST('action', 'alpha');
+
+// Securite acces client
+$socid=GETPOST('socid','int');
+if (isset($user->societe_id) && $user->societe_id > 0)
+{
+	$action = '';
+	$socid = $user->societe_id;
+}
+
+$max=5;
+$now=dol_now();
+
+
+/*
+ * Actions
+ */
+
+// None
+
+
+/*
+ * View
+ */
+
+$form = new Form($db);
+$formfile = new FormFile($db);
+
+llxHeader("",$langs->trans("MyModuleArea"));
+
+print load_fiche_titre($langs->trans("MyModuleArea"),'','mymodule.png@mymodule');
+
+print '<div class="fichecenter"><div class="fichethirdleft">';
+
+
+/* BEGIN MODULEBUILDER DRAFT MYOBJECT
+// Draft MyObject
+if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read)
+{
+	$langs->load("orders");
+
+	$sql = "SELECT c.rowid, c.ref, c.ref_client, c.total_ht, c.tva as total_tva, c.total_ttc, s.rowid as socid, s.nom as name, s.client, s.canvas";
+    $sql.= ", s.code_client";
+	$sql.= " FROM ".MAIN_DB_PREFIX."commande as c";
+	$sql.= ", ".MAIN_DB_PREFIX."societe as s";
+	if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
+	$sql.= " WHERE c.fk_soc = s.rowid";
+	$sql.= " AND c.fk_statut = 0";
+	$sql.= " AND c.entity IN (".getEntity('commande').")";
+	if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
+	if ($socid)	$sql.= " AND c.fk_soc = ".$socid;
+
+	$resql = $db->query($sql);
+	if ($resql)
+	{
+		$total = 0;
+		$num = $db->num_rows($resql);
+
+		print '<table class="noborder" width="100%">';
+		print '<tr class="liste_titre">';
+		print '<th colspan="3">'.$langs->trans("DraftOrders").($num?' <span class="badge">'.$num.'</span>':'').'</th></tr>';
+
+		$var = true;
+		if ($num > 0)
+		{
+			$i = 0;
+			while ($i < $num)
+			{
+
+				$obj = $db->fetch_object($resql);
+				print '<tr class="oddeven"><td class="nowrap">';
+                $orderstatic->id=$obj->rowid;
+                $orderstatic->ref=$obj->ref;
+                $orderstatic->ref_client=$obj->ref_client;
+                $orderstatic->total_ht = $obj->total_ht;
+                $orderstatic->total_tva = $obj->total_tva;
+                $orderstatic->total_ttc = $obj->total_ttc;
+                print $orderstatic->getNomUrl(1);
+                print '</td>';
+				print '<td class="nowrap">';
+				$companystatic->id=$obj->socid;
+				$companystatic->name=$obj->name;
+				$companystatic->client=$obj->client;
+                $companystatic->code_client = $obj->code_client;
+                $companystatic->code_fournisseur = $obj->code_fournisseur;
+                $companystatic->canvas=$obj->canvas;
+				print $companystatic->getNomUrl(1,'customer',16);
+				print '</td>';
+				print '<td align="right" class="nowrap">'.price($obj->total_ttc).'</td></tr>';
+				$i++;
+				$total += $obj->total_ttc;
+			}
+			if ($total>0)
+			{
+
+				print '<tr class="liste_total"><td>'.$langs->trans("Total").'</td><td colspan="2" align="right">'.price($total)."</td></tr>";
+			}
+		}
+		else
+		{
+
+			print '<tr class="oddeven"><td colspan="3" class="opacitymedium">'.$langs->trans("NoOrder").'</td></tr>';
+		}
+		print "</table><br>";
+
+		$db->free($resql);
+	}
+	else
+	{
+		dol_print_error($db);
+	}
+}
+END MODULEBUILDER DRAFT MYOBJECT */
+
+
+print '</div><div class="fichetwothirdright"><div class="ficheaddleft">';
+
+
+$NBMAX=3;
+$max=3;
+
+/* BEGIN MODULEBUILDER LASTMODIFIED MYOBJECT
+// Last modified myobject
+if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read)
+{
+	$sql = "SELECT s.rowid, s.nom as name, s.client, s.datec, s.tms, s.canvas";
+    $sql.= ", s.code_client";
+	$sql.= " FROM ".MAIN_DB_PREFIX."societe as s";
+	if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
+	$sql.= " WHERE s.client IN (1, 2, 3)";
+	$sql.= " AND s.entity IN (".getEntity($companystatic->element, 1).")";
+	if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
+	if ($socid)	$sql.= " AND s.rowid = $socid";
+	$sql .= " ORDER BY s.tms DESC";
+	$sql .= $db->plimit($max, 0);
+
+	$resql = $db->query($sql);
+	if ($resql)
+	{
+		$num = $db->num_rows($resql);
+		$i = 0;
+
+		print '<table class="noborder" width="100%">';
+		print '<tr class="liste_titre">';
+		print '<th colspan="2">';
+		if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) print $langs->trans("BoxTitleLastCustomersOrProspects",$max);
+        else if (! empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) print $langs->trans("BoxTitleLastModifiedProspects",$max);
+		else print $langs->trans("BoxTitleLastModifiedCustomers",$max);
+		print '</th>';
+		print '<th align="right">'.$langs->trans("DateModificationShort").'</th>';
+		print '</tr>';
+		if ($num)
+		{
+			while ($i < $num)
+			{
+				$objp = $db->fetch_object($resql);
+				$companystatic->id=$objp->rowid;
+				$companystatic->name=$objp->name;
+				$companystatic->client=$objp->client;
+                $companystatic->code_client = $objp->code_client;
+                $companystatic->code_fournisseur = $objp->code_fournisseur;
+                $companystatic->canvas=$objp->canvas;
+				print '<tr class="oddeven">';
+				print '<td class="nowrap">'.$companystatic->getNomUrl(1,'customer',48).'</td>';
+				print '<td align="right" nowrap>';
+				print $companystatic->getLibCustProspStatut();
+				print "</td>";
+				print '<td align="right" nowrap>'.dol_print_date($db->jdate($objp->tms),'day')."</td>";
+				print '</tr>';
+				$i++;
+
+
+			}
+
+			$db->free($resql);
+		}
+		else
+		{
+			print '<tr class="oddeven"><td colspan="3" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
+		}
+		print "</table><br>";
+	}
+}
+*/
+
+print '</div></div></div>';
+
+llxFooter();
+
+$db->close();
-- 
GitLab