2004-10-20 00:24:10 +02:00
< ? php
2014-08-21 11:32:39 +02:00
/* Copyright ( C ) 2003 - 2007 Rodolphe Quiedeville < rodolphe @ quiedeville . org >
* Copyright ( C ) 2004 Sebastien Di Cintio < sdicintio @ ressource - toi . org >
* Copyright ( C ) 2004 Benoit Mortier < benoit . mortier @ opensides . be >
* Copyright ( C ) 2004 Eric Seigne < eric . seigne @ ryxeo . com >
* Copyright ( C ) 2005 - 2013 Laurent Destailleur < eldy @ users . sourceforge . net >
2018-10-27 14:43:12 +02:00
* Copyright ( C ) 2005 - 2012 Regis Houssin < regis . houssin @ inodbox . com >
2014-08-21 11:32:39 +02:00
* Copyright ( C ) 2014 Raphaël Doursenaud < rdoursenaud @ gpcsolutions . fr >
2018-08-30 18:12:02 +02:00
* Copyright ( C ) 2018 Josep Lluís Amador < joseplluis @ lliuretic . cat >
2024-03-05 17:12:36 +01:00
* Copyright ( C ) 2019 - 2024 Frédéric France < frederic . france @ free . fr >
2024-03-11 17:57:54 +01:00
* Copyright ( C ) 2024 MDW < mdeweerd @ users . noreply . github . com >
2003-11-15 18:41:07 +01:00
*
* 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
2013-01-16 15:36:08 +01:00
* the Free Software Foundation ; either version 3 of the License , or
2003-11-15 18:41:07 +01:00
* ( 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
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
2003-11-15 18:41:07 +01:00
*/
2005-04-09 17:52:07 +02:00
/**
2014-08-21 12:16:13 +02:00
* \file htdocs / core / modules / DolibarrModules . class . php
* \brief File of parent class of module descriptor class files
2008-10-06 09:39:52 +02:00
*/
2004-08-15 14:40:18 +02:00
2005-04-09 17:52:07 +02:00
/**
2014-08-21 12:16:13 +02:00
* Class DolibarrModules
*
* Parent class for module descriptor class files
2008-10-06 09:39:52 +02:00
*/
2018-08-29 22:06:05 +02:00
class DolibarrModules // Can not be abstract, because we need to instantiate it into unActivateModule to be able to disable a module whose files were removed.
2003-11-15 18:41:07 +01:00
{
2020-09-08 21:27:28 +02:00
/**
2024-01-13 15:50:02 +01:00
* @ var DoliDB Database handler
2020-09-08 21:27:28 +02:00
*/
public $db ;
/**
* @ var int Module unique ID
* @ see https :// wiki . dolibarr . org / index . php / List_of_modules_id
*/
public $numero ;
/**
* @ var string Publisher name
* @ since 4.0 . 0
*/
public $editor_name ;
/**
* @ var string URL of module at publisher site
* @ since 4.0 . 0
*/
public $editor_url ;
/**
2024-03-11 15:20:56 +01:00
* @ var string Family
2020-09-08 21:27:28 +02:00
* @ see $familyinfo
*
* Native values : 'crm' , 'financial' , 'hr' , 'projects' , 'products' , 'ecm' , 'technic' , 'other' .
* Use familyinfo to declare a custom value .
*/
public $family ;
/**
2024-03-10 01:53:04 +01:00
* @ var array < string , array { position : string , label : string } > Custom family information
2020-09-08 21:27:28 +02:00
* @ see $family
*
* e . g .:
* array (
* 'myownfamily' => array (
* 'position' => '001' ,
* 'label' => $langs -> trans ( " MyOwnFamily " )
* )
* );
*/
public $familyinfo ;
/**
* @ var string Module position on 2 digits
*/
public $module_position = '50' ;
/**
* @ var string Module name
*
* Only used if Module [ ID ] Name translation string is not found .
*
* You can use the following code to automatically derive it from your module ' s class name :
* preg_replace ( '/^mod/i' , '' , get_class ( $this ))
*/
public $name ;
/**
* @ var string [] Paths to create when module is activated
*
* e . g .: array ( '/mymodule/temp' )
*/
public $dirs = array ();
/**
* @ var array Module boxes
*/
public $boxes = array ();
/**
* @ var array Module constants
*/
public $const = array ();
/**
* @ var array Module cron jobs entries
*/
public $cronjobs = array ();
/**
2023-06-26 15:34:09 +02:00
* @ var array Module access rights
2020-09-08 21:27:28 +02:00
*/
public $rights ;
/**
2023-06-26 15:34:09 +02:00
* @ var int 1 = Admin is always granted of permission of modules ( even when module is disabled )
*/
public $rights_admin_allowed ;
/**
* @ var string Module access rights family
2020-09-08 21:27:28 +02:00
*/
public $rights_class ;
/**
* @ var array | int Module menu entries ( 1 means the menu entries are not declared into module descriptor but are hardcoded into menu manager )
*/
public $menu = array ();
/**
2024-03-15 10:46:20 +01:00
* @ var array { triggers ? : int < 0 , 1 > , login ? : int < 0 , 1 > , substitutions ? : int < 0 , 1 > , menus ? : int < 0 , 1 > , theme ? : int < 0 , 1 > , tpl ? : int < 0 , 1 > , barcode ? : int < 0 , 1 > , models ? : int < 0 , 1 > , printing ? : int < 0 , 1 > , css ? : string [], js ? : string [], hooks ? : array { data ? : string [], entity ? : string }, moduleforexternal ? : int < 0 , 1 > , websitetemplates ? : int < 0 , 1 > , contactelement ? : int < 0 , 1 > } Module parts
2020-09-08 21:27:28 +02:00
* array (
* // Set this to 1 if module has its own trigger directory (/mymodule/core/triggers)
* 'triggers' => 0 ,
* // Set this to 1 if module has its own login method directory (/mymodule/core/login)
* 'login' => 0 ,
* // Set this to 1 if module has its own substitution function file (/mymodule/core/substitutions)
* 'substitutions' => 0 ,
* // Set this to 1 if module has its own menus handler directory (/mymodule/core/menus)
* 'menus' => 0 ,
* // Set this to 1 if module has its own theme directory (/mymodule/theme)
* 'theme' => 0 ,
* // Set this to 1 if module overwrite template dir (/mymodule/core/tpl)
* 'tpl' => 0 ,
* // Set this to 1 if module has its own barcode directory (/mymodule/core/modules/barcode)
* 'barcode' => 0 ,
* // Set this to 1 if module has its own models directory (/mymodule/core/modules/xxx)
* 'models' => 0 ,
* // Set this to relative path of css file if module has its own css file
* 'css' => '/mymodule/css/mymodule.css.php' ,
* // Set this to relative path of js file if module must load a js on all pages
* 'js' => '/mymodule/js/mymodule.js' ,
* // Set here all hooks context managed by module
* 'hooks' => array ( 'hookcontext1' , 'hookcontext2' )
* )
*/
public $module_parts = array ();
/**
* @ var string Module documents ?
* @ deprecated Seems unused anywhere
*/
public $docs ;
/**
* @ var string ?
* @ deprecated Seems unused anywhere
*/
public $dbversion = " - " ;
/**
* @ var string Error message
*/
public $error ;
2023-01-09 12:09:16 +01:00
/**
* @ var string [] Array of Errors messages
*/
public $errors ;
2020-09-08 21:27:28 +02:00
/**
* @ var string Module version
* @ see http :// semver . org
*
* The following keywords can also be used :
* 'development'
* 'experimental'
* 'dolibarr' : only for core modules that share its version
* 'dolibarr_deprecated' : only for deprecated core modules
*/
public $version ;
2021-04-18 20:12:24 +02:00
/**
* Module last version
* @ var string $lastVersion
*/
public $lastVersion = '' ;
/**
* true indicate this module need update
* @ var bool $needUpdate
*/
public $needUpdate = false ;
2020-09-08 21:27:28 +02:00
/**
* @ var string Module description ( short text )
*
* Only used if Module [ ID ] Desc translation string is not found .
*/
public $description ;
/**
* @ var string Module description ( long text )
* @ since 4.0 . 0
*
* HTML content supported .
*/
public $descriptionlong ;
2023-01-09 11:56:43 +01:00
/**
2023-01-09 12:09:16 +01:00
* @ var array dictionaries description
2023-01-09 11:56:43 +01:00
*/
public $dictionaries ;
/**
2023-01-09 12:09:16 +01:00
* @ var array tabs description
2023-01-09 11:56:43 +01:00
*/
public $tabs ;
2020-09-08 21:27:28 +02:00
// For exports
/**
* @ var string Module export code
*/
public $export_code ;
/**
2024-03-11 12:56:55 +01:00
* @ var string [] Module export label
2020-09-08 21:27:28 +02:00
*/
public $export_label ;
2022-12-28 03:48:29 +01:00
public $export_icon ;
2023-03-14 09:36:58 +01:00
/**
* @ var array export enabled
*/
public $export_enabled ;
2020-09-08 21:27:28 +02:00
public $export_permission ;
public $export_fields_array ;
public $export_TypeFields_array ; // Array of key=>type where type can be 'Numeric', 'Date', 'Text', 'Boolean', 'Status', 'List:xxx:login:rowid'
public $export_entities_array ;
2023-06-28 12:05:51 +02:00
public $export_aggregate_array ;
2023-03-14 09:36:58 +01:00
public $export_examplevalues_array ;
2022-12-28 03:48:29 +01:00
public $export_help_array ;
2020-09-08 21:27:28 +02:00
public $export_special_array ; // special or computed field
public $export_dependencies_array ;
public $export_sql_start ;
public $export_sql_end ;
public $export_sql_order ;
// For import
/**
* @ var string Module import code
*/
public $import_code ;
/**
2024-03-11 12:56:55 +01:00
* @ var string [] Module import label
2020-09-08 21:27:28 +02:00
*/
public $import_label ;
2022-12-28 03:59:29 +01:00
public $import_icon ;
public $import_entities_array ;
public $import_tables_array ;
2023-03-14 09:36:58 +01:00
public $import_tables_creator_array ;
2022-12-28 03:59:29 +01:00
public $import_fields_array ;
public $import_fieldshidden_array ;
public $import_convertvalue_array ;
public $import_regex_array ;
public $import_examplevalues_array ;
public $import_updatekeys_array ;
2023-06-29 13:16:44 +02:00
public $import_run_sql_after_array ;
2023-06-26 23:10:44 +02:00
public $import_TypeFields_array ;
public $import_help_array ;
2020-09-08 21:27:28 +02:00
/**
* @ var string Module constant name
*/
public $const_name ;
/**
* @ var bool Module can ' t be disabled
*/
public $always_enabled ;
2021-07-19 13:46:50 +02:00
/**
* @ var bool Module is disabled
*/
public $disabled ;
2020-09-08 21:27:28 +02:00
/**
* @ var int Module is enabled globally ( Multicompany support )
*/
public $core_enabled ;
/**
* @ var string Name of image file used for this module
*
* If file is in theme / yourtheme / img directory under name object_pictoname . png use 'pictoname'
* If file is in module / img directory under name object_pictoname . png use 'pictoname@module'
*/
public $picto ;
/**
2022-12-30 12:15:18 +01:00
* @ var string [] | string List of config pages ( Old modules uses a string . New one must use an array )
2020-09-08 21:27:28 +02:00
*
* Name of php pages stored into module / admin directory , used to setup module .
2022-12-30 12:15:18 +01:00
* e . g .: array ( " setup.php@mymodule " )
2020-09-08 21:27:28 +02:00
*/
public $config_page_url ;
/**
2024-03-05 17:12:36 +01:00
* @ var array List of module class names that must be enabled if this module is enabled . e . g .: array ( 'modAnotherModule' , 'FR' => 'modYetAnotherModule' )
* Another example : array ( 'always' => array ( " modBanque " , " modFacture " , " modProduct " , " modCategorie " ), 'FR' => array ( 'modBlockedLog' ));
2019-09-12 00:03:51 +02:00
* @ see $requiredby
2020-09-08 21:27:28 +02:00
*/
public $depends ;
/**
* @ var string [] List of module class names to disable if the module is disabled .
* @ see $depends
*/
public $requiredby ;
/**
* @ var string [] List of module class names as string this module is in conflict with .
* @ see $depends
*/
public $conflictwith ;
/**
* @ var string [] Module language files
*/
public $langfiles ;
/**
* @ var array < string , string > Array of warnings to show when we activate the module
*
* array ( 'always' = 'text' ) or array ( 'FR' = 'text' )
*/
public $warnings_activation ;
/**
* @ var array < string , string > Array of warnings to show when we activate an external module
*
* array ( 'always' = 'text' ) or array ( 'FR' = 'text' )
*/
public $warnings_activation_ext ;
2023-06-26 23:02:17 +02:00
/**
* @ var array < string , string > Array of warnings to show when we disable the module
*
* array ( 'always' = 'text' ) or array ( 'FR' = 'text' )
*/
public $warnings_unactivation ;
2020-09-08 21:27:28 +02:00
/**
* @ var array Minimum version of PHP required by module .
2022-09-27 20:48:47 +02:00
* e . g .: PHP ≥ 7.0 = array ( 7 , 0 )
2020-09-08 21:27:28 +02:00
*/
public $phpmin ;
2023-02-09 00:47:33 +01:00
public $phpmax ;
2020-09-08 21:27:28 +02:00
/**
* @ var array Minimum version of Dolibarr required by module .
* e . g .: Dolibarr ≥ 3.6 = array ( 3 , 6 )
*/
public $need_dolibarr_version ;
2023-06-28 12:05:51 +02:00
public $need_javascript_ajax ;
2023-02-09 00:47:33 +01:00
public $enabled_bydefault ;
2020-09-08 21:27:28 +02:00
/**
2024-02-22 13:27:04 +01:00
* @ var bool | int Whether to hide the module .
2020-09-08 21:27:28 +02:00
*/
public $hidden = false ;
2021-12-28 19:36:44 +01:00
/**
* @ var string url to check for module update
*/
public $url_last_version ;
2020-09-08 21:27:28 +02:00
/**
* Constructor . Define names , constants , directories , boxes , permissions
*
* @ param DoliDB $db Database handler
*/
public function __construct ( $db )
{
$this -> db = $db ;
}
// We should but can't set this as abstract because this will make dolibarr hang
// after migration due to old module not implementing. We must wait PHP is able to make
// a try catch on Fatal error to manage this correctly.
// We need constructor into function unActivateModule into admin.lib.php
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Enables a module .
2024-01-13 19:48:20 +01:00
* Inserts all information into database .
2020-09-08 21:27:28 +02:00
*
2021-02-06 11:56:27 +01:00
* @ param array $array_sql SQL requests to be executed when enabling module
* @ param string $options String with options when disabling module :
2021-02-15 20:13:38 +01:00
* - 'noboxes' = Do all actions but do not insert boxes
* - 'newboxdefonly' = Do all actions but for boxes , insert def of boxes only and not boxes activation
2021-02-06 11:56:27 +01:00
* @ return int 1 if OK , 0 if KO
2020-09-08 21:27:28 +02:00
*/
protected function _init ( $array_sql , $options = '' )
{
// phpcs:enable
global $conf ;
$err = 0 ;
$this -> db -> begin ();
// Insert activation module constant
if ( ! $err ) {
$err += $this -> _active ();
}
// Insert new pages for tabs (into llx_const)
if ( ! $err ) {
$err += $this -> insert_tabs ();
}
2024-03-14 12:39:42 +01:00
// Insert activation of module's parts. Copy website templates into doctemplates.
2020-09-08 21:27:28 +02:00
if ( ! $err ) {
$err += $this -> insert_module_parts ();
}
// Insert constant defined by modules (into llx_const)
if ( ! $err && ! preg_match ( '/newboxdefonly/' , $options )) {
$err += $this -> insert_const (); // Test on newboxdefonly to avoid to erase value during upgrade
}
2021-02-15 20:13:38 +01:00
// Insert boxes def (into llx_boxes_def) and boxes setup (into llx_boxes)
2020-09-08 21:27:28 +02:00
if ( ! $err && ! preg_match ( '/noboxes/' , $options )) {
$err += $this -> insert_boxes ( $options );
}
// Insert cron job entries (entry in llx_cronjobs)
if ( ! $err ) {
$err += $this -> insert_cronjobs ();
}
// Insert permission definitions of module into llx_rights_def. If user is admin, grant this permission to user.
if ( ! $err ) {
$err += $this -> insert_permissions ( 1 , null , 1 );
}
// Insert specific menus entries into database
if ( ! $err ) {
$err += $this -> insert_menus ();
}
// Create module's directories
if ( ! $err ) {
$err += $this -> create_dirs ();
}
// Execute addons requests
$num = count ( $array_sql );
2021-02-23 22:03:23 +01:00
for ( $i = 0 ; $i < $num ; $i ++ ) {
2020-09-08 21:27:28 +02:00
if ( ! $err ) {
$val = $array_sql [ $i ];
$sql = $val ;
$ignoreerror = 0 ;
if ( is_array ( $val )) {
$sql = $val [ 'sql' ];
$ignoreerror = $val [ 'ignoreerror' ];
}
// Add current entity id
$sql = str_replace ( '__ENTITY__' , $conf -> entity , $sql );
2022-12-28 16:40:03 +01:00
dol_syslog ( get_class ( $this ) . " ::_init ignoreerror= " . $ignoreerror , LOG_DEBUG );
2020-09-08 21:27:28 +02:00
$result = $this -> db -> query ( $sql , $ignoreerror );
if ( ! $result ) {
if ( ! $ignoreerror ) {
2023-12-04 12:07:31 +01:00
$this -> error = $this -> db -> lasterror ();
$err ++ ;
2020-09-08 21:27:28 +02:00
} else {
2023-12-04 12:07:31 +01:00
dol_syslog ( get_class ( $this ) . " ::_init Warning " . $this -> db -> lasterror (), LOG_WARNING );
2020-09-08 21:27:28 +02:00
}
}
}
}
// Return code
if ( ! $err ) {
$this -> db -> commit ();
return 1 ;
} else {
$this -> db -> rollback ();
return 0 ;
}
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Disable function . Deletes the module constants and boxes from the database .
*
* @ param string [] $array_sql SQL requests to be executed when module is disabled
* @ param string $options Options when disabling module :
*
* @ return int 1 if OK , 0 if KO
*/
protected function _remove ( $array_sql , $options = '' )
{
// phpcs:enable
$err = 0 ;
$this -> db -> begin ();
// Remove activation module line (constant MAIN_MODULE_MYMODULE in llx_const)
if ( ! $err ) {
$err += $this -> _unactive ();
}
// Remove activation of module's new tabs (MAIN_MODULE_MYMODULE_TABS_XXX in llx_const)
if ( ! $err ) {
$err += $this -> delete_tabs ();
}
// Remove activation of module's parts (MAIN_MODULE_MYMODULE_XXX in llx_const)
if ( ! $err ) {
$err += $this -> delete_module_parts ();
}
// Remove constants defined by modules
if ( ! $err ) {
$err += $this -> delete_const ();
}
// Remove list of module's available boxes (entry in llx_boxes)
if ( ! $err && ! preg_match ( '/(newboxdefonly|noboxes)/' , $options )) {
$err += $this -> delete_boxes (); // We don't have to delete if option ask to keep boxes safe or ask to add new box def only
}
// Remove list of module's cron job entries (entry in llx_cronjobs)
if ( ! $err ) {
$err += $this -> delete_cronjobs ();
}
// Remove module's permissions from list of available permissions (entries in llx_rights_def)
if ( ! $err ) {
$err += $this -> delete_permissions ();
}
// Remove module's menus (entries in llx_menu)
if ( ! $err ) {
$err += $this -> delete_menus ();
}
// Remove module's directories
if ( ! $err ) {
$err += $this -> delete_dirs ();
}
// Run complementary sql requests
2023-11-28 09:18:16 +01:00
$num = count (( array ) $array_sql );
2021-02-23 22:03:23 +01:00
for ( $i = 0 ; $i < $num ; $i ++ ) {
2020-09-08 21:27:28 +02:00
if ( ! $err ) {
dol_syslog ( get_class ( $this ) . " ::_remove " , LOG_DEBUG );
$result = $this -> db -> query ( $array_sql [ $i ]);
if ( ! $result ) {
$this -> error = $this -> db -> error ();
$err ++ ;
}
}
}
// Return code
if ( ! $err ) {
$this -> db -> commit ();
return 1 ;
} else {
$this -> db -> rollback ();
return 0 ;
}
}
/**
* Gives the translated module name if translation exists in admin . lang or into language files of module .
* Otherwise return the module key name .
*
* @ return string Translated module name
*/
public function getName ()
{
global $langs ;
$langs -> load ( " admin " );
2023-12-27 12:12:20 +01:00
if ( $langs -> transnoentitiesnoconv ( " Module " . $this -> numero . " Name " ) != " Module " . $this -> numero . " Name " ) {
2020-09-08 21:27:28 +02:00
// If module name translation exists
return $langs -> transnoentitiesnoconv ( " Module " . $this -> numero . " Name " );
} else {
// If module name translation using it's unique id does not exist, we try to use its name to find translation
if ( is_array ( $this -> langfiles )) {
2021-02-23 22:03:23 +01:00
foreach ( $this -> langfiles as $val ) {
if ( $val ) {
$langs -> load ( $val );
2020-09-08 21:27:28 +02:00
}
}
}
2023-12-27 12:12:20 +01:00
if ( $langs -> trans ( " Module " . $this -> name . " Name " ) != " Module " . $this -> name . " Name " ) {
2020-09-08 21:27:28 +02:00
// If module name translation exists
return $langs -> transnoentitiesnoconv ( " Module " . $this -> name . " Name " );
}
// Last chance with simple label
return $langs -> transnoentitiesnoconv ( $this -> name );
}
}
/**
* Gives the translated module description if translation exists in admin . lang or the default module description
*
* @ return string Translated module description
*/
public function getDesc ()
{
global $langs ;
$langs -> load ( " admin " );
2023-12-27 12:12:20 +01:00
if ( $langs -> transnoentitiesnoconv ( " Module " . $this -> numero . " Desc " ) != " Module " . $this -> numero . " Desc " ) {
2020-09-08 21:27:28 +02:00
// If module description translation exists
return $langs -> transnoentitiesnoconv ( " Module " . $this -> numero . " Desc " );
} else {
// If module description translation does not exist using its unique id, we can use its name to find translation
if ( is_array ( $this -> langfiles )) {
2021-02-23 22:03:23 +01:00
foreach ( $this -> langfiles as $val ) {
if ( $val ) {
$langs -> load ( $val );
2020-09-08 21:27:28 +02:00
}
}
}
2023-12-27 12:12:20 +01:00
if ( $langs -> transnoentitiesnoconv ( " Module " . $this -> name . " Desc " ) != " Module " . $this -> name . " Desc " ) {
2020-09-08 21:27:28 +02:00
// If module name translation exists
return $langs -> trans ( " Module " . $this -> name . " Desc " );
}
// Last chance with simple label
return $langs -> trans ( $this -> description );
}
}
/**
* Gives the long description of a module . First check README - la_LA . md then README . md
* If no markdown files found , it returns translated value of the key -> descriptionlong .
*
* @ return string Long description of a module from README . md of from property .
*/
public function getDescLong ()
{
global $langs ;
$langs -> load ( " admin " );
include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php' ;
include_once DOL_DOCUMENT_ROOT . '/core/lib/geturl.lib.php' ;
2024-03-10 01:53:04 +01:00
$content = '' ;
2020-09-08 21:27:28 +02:00
$pathoffile = $this -> getDescLongReadmeFound ();
2021-02-23 22:03:23 +01:00
if ( $pathoffile ) { // Mostly for external modules
2024-03-24 06:37:09 +01:00
$content = file_get_contents ( $pathoffile , false , null , 0 , 1024 * 1024 ); // Max size loaded 1Mb
2020-09-08 21:27:28 +02:00
if (( float ) DOL_VERSION >= 6.0 ) {
@ include_once DOL_DOCUMENT_ROOT . '/core/lib/parsemd.lib.php' ;
$content = dolMd2Html (
$content ,
'parsedown' ,
array (
'doc/' => dol_buildpath ( strtolower ( $this -> name ) . '/doc/' , 1 ),
'img/' => dol_buildpath ( strtolower ( $this -> name ) . '/img/' , 1 ),
'images/' => dol_buildpath ( strtolower ( $this -> name ) . '/images/' , 1 ),
)
);
2023-04-22 01:01:08 +02:00
$content = preg_replace ( '/<a href="/' , '<a target="_blank" rel="noopener noreferrer" href="' , $content );
2020-09-08 21:27:28 +02:00
} else {
$content = nl2br ( $content );
}
} else {
// Mostly for internal modules
if ( ! empty ( $this -> descriptionlong )) {
if ( is_array ( $this -> langfiles )) {
2021-02-23 22:03:23 +01:00
foreach ( $this -> langfiles as $val ) {
if ( $val ) {
$langs -> load ( $val );
2020-09-08 21:27:28 +02:00
}
}
}
$content = $langs -> transnoentitiesnoconv ( $this -> descriptionlong );
}
}
return $content ;
}
/**
* Return path of file if a README file was found .
*
* @ return string Path of file if a README file was found .
*/
public function getDescLongReadmeFound ()
{
global $langs ;
$filefound = false ;
// Define path to file README.md.
// First check README-la_LA.md then README-la.md then README.md
$pathoffile = dol_buildpath ( strtolower ( $this -> name ) . '/README-' . $langs -> defaultlang . '.md' , 0 );
if ( dol_is_file ( $pathoffile )) {
$filefound = true ;
}
if ( ! $filefound ) {
$tmp = explode ( '_' , $langs -> defaultlang );
$pathoffile = dol_buildpath ( strtolower ( $this -> name ) . '/README-' . $tmp [ 0 ] . '.md' , 0 );
if ( dol_is_file ( $pathoffile )) {
$filefound = true ;
}
}
if ( ! $filefound ) {
$pathoffile = dol_buildpath ( strtolower ( $this -> name ) . '/README.md' , 0 );
if ( dol_is_file ( $pathoffile )) {
$filefound = true ;
}
}
return ( $filefound ? $pathoffile : '' );
}
/**
* Gives the changelog . First check ChangeLog - la_LA . md then ChangeLog . md
*
* @ return string Content of ChangeLog
*/
public function getChangeLog ()
{
global $langs ;
$langs -> load ( " admin " );
include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php' ;
include_once DOL_DOCUMENT_ROOT . '/core/lib/geturl.lib.php' ;
$filefound = false ;
// Define path to file README.md.
// First check ChangeLog-la_LA.md then ChangeLog.md
$pathoffile = dol_buildpath ( strtolower ( $this -> name ) . '/ChangeLog-' . $langs -> defaultlang . '.md' , 0 );
if ( dol_is_file ( $pathoffile )) {
$filefound = true ;
}
if ( ! $filefound ) {
$pathoffile = dol_buildpath ( strtolower ( $this -> name ) . '/ChangeLog.md' , 0 );
if ( dol_is_file ( $pathoffile )) {
$filefound = true ;
}
}
2021-02-23 22:03:23 +01:00
if ( $filefound ) { // Mostly for external modules
2020-09-08 21:27:28 +02:00
$content = file_get_contents ( $pathoffile );
if (( float ) DOL_VERSION >= 6.0 ) {
@ include_once DOL_DOCUMENT_ROOT . '/core/lib/parsemd.lib.php' ;
2023-04-30 15:13:04 +02:00
2024-03-10 01:53:04 +01:00
$content = dolMd2Html ( $content , 'parsedown' , array ( 'doc/' => dol_buildpath ( strtolower ( $this -> name ) . '/doc/' , 1 )));
2020-09-08 21:27:28 +02:00
} else {
$content = nl2br ( $content );
}
2024-03-20 20:02:09 +01:00
} else {
$content = '' ;
2020-09-08 21:27:28 +02:00
}
return $content ;
}
/**
* Gives the publisher name
*
* @ return string Publisher name
*/
public function getPublisher ()
{
return $this -> editor_name ;
}
/**
* Gives the publisher url
*
* @ return string Publisher url
*/
public function getPublisherUrl ()
{
return $this -> editor_url ;
}
/**
* Gives module version ( translated if param $translated is on )
* For 'experimental' modules , gives 'experimental' translation
* For 'dolibarr' modules , gives Dolibarr version
*
2023-01-13 14:09:54 +01:00
* @ param int $translated 1 = Special version keys are translated , 0 = Special version keys are not translated
* @ return string Module version
2020-09-08 21:27:28 +02:00
*/
public function getVersion ( $translated = 1 )
{
global $langs ;
$langs -> load ( " admin " );
$ret = '' ;
$newversion = preg_replace ( '/_deprecated/' , '' , $this -> version );
if ( $newversion == 'experimental' ) {
$ret = ( $translated ? $langs -> transnoentitiesnoconv ( " VersionExperimental " ) : $newversion );
} elseif ( $newversion == 'development' ) {
$ret = ( $translated ? $langs -> transnoentitiesnoconv ( " VersionDevelopment " ) : $newversion );
} elseif ( $newversion == 'dolibarr' ) {
$ret = DOL_VERSION ;
} elseif ( $newversion ) {
$ret = $newversion ;
} else {
$ret = ( $translated ? $langs -> transnoentitiesnoconv ( " VersionUnknown " ) : 'unknown' );
}
if ( preg_match ( '/_deprecated/' , $this -> version )) {
$ret .= ( $translated ? ' (' . $langs -> transnoentitiesnoconv ( " Deprecated " ) . ')' : $this -> version );
}
return $ret ;
}
2021-05-02 13:13:55 +02:00
/**
* Gives the module position
*
2024-02-13 09:14:28 +01:00
* @ return string Module position ( an external module should never return a value lower than 100000. 1 - 100000 are reserved for core )
2021-05-02 13:13:55 +02:00
*/
public function getModulePosition ()
{
if ( in_array ( $this -> version , array ( 'dolibarr' , 'experimental' , 'development' ))) { // core module
return $this -> module_position ;
} else { // external module
if ( $this -> module_position >= 100000 ) {
return $this -> module_position ;
} else {
2024-02-13 09:14:28 +01:00
$position = intval ( $this -> module_position ) + 100000 ;
return strval ( $position );
2021-05-02 13:13:55 +02:00
}
}
}
2020-09-08 21:27:28 +02:00
/**
2022-05-03 12:08:24 +02:00
* Tells if module is core or external .
* 'dolibarr' and 'dolibarr_deprecated' is core
* 'experimental' and 'development' is core
2020-09-08 21:27:28 +02:00
*
* @ return string 'core' , 'external' or 'unknown'
*/
public function isCoreOrExternalModule ()
{
if ( $this -> version == 'dolibarr' || $this -> version == 'dolibarr_deprecated' ) {
return 'core' ;
}
if ( ! empty ( $this -> version ) && ! in_array ( $this -> version , array ( 'experimental' , 'development' ))) {
return 'external' ;
}
if ( ! empty ( $this -> editor_name ) || ! empty ( $this -> editor_url )) {
return 'external' ;
}
if ( $this -> numero >= 100000 ) {
return 'external' ;
}
return 'unknown' ;
}
/**
* Gives module related language files list
*
* @ return string [] Language files list
*/
public function getLangFilesArray ()
{
return $this -> langfiles ;
}
/**
* Gives translated label of an export dataset
*
* @ param int $r Dataset index
*
* @ return string Translated databaset label
*/
public function getExportDatasetLabel ( $r )
{
global $langs ;
$langstring = " ExportDataset_ " . $this -> export_code [ $r ];
if ( $langs -> trans ( $langstring ) == $langstring ) {
// Translation not found
return $langs -> trans ( $this -> export_label [ $r ]);
} else {
// Translation found
return $langs -> trans ( $langstring );
}
}
/**
* Gives translated label of an import dataset
*
* @ param int $r Dataset index
*
* @ return string Translated dataset label
*/
public function getImportDatasetLabel ( $r )
{
global $langs ;
$langstring = " ImportDataset_ " . $this -> import_code [ $r ];
//print "x".$langstring;
if ( $langs -> trans ( $langstring ) == $langstring ) {
// Translation not found
return $langs -> transnoentitiesnoconv ( $this -> import_label [ $r ]);
} else {
// Translation found
return $langs -> transnoentitiesnoconv ( $langstring );
}
}
/**
* Gives the last date of activation
*
* @ return int | string Date of last activation or '' if module was never activated
*/
public function getLastActivationDate ()
{
global $conf ;
$err = 0 ;
$sql = " SELECT tms FROM " . MAIN_DB_PREFIX . " const " ;
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " = ' " . $this -> db -> escape ( $this -> const_name ) . " ' " ;
2023-10-14 16:23:28 +02:00
$sql .= " AND entity IN (0, " . (( int ) $conf -> entity ) . " ) " ;
2020-09-08 21:27:28 +02:00
dol_syslog ( get_class ( $this ) . " ::getLastActiveDate " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( ! $resql ) {
2020-09-08 21:27:28 +02:00
$err ++ ;
} else {
$obj = $this -> db -> fetch_object ( $resql );
if ( $obj ) {
return $this -> db -> jdate ( $obj -> tms );
}
}
return '' ;
}
/**
* Gives the last author of activation
*
* @ return array Array array ( 'authorid' => Id of last activation user , 'lastactivationdate' => Date of last activation )
*/
public function getLastActivationInfo ()
{
global $conf ;
$err = 0 ;
2019-03-02 20:49:53 +01:00
2017-10-07 13:09:31 +02:00
$sql = " SELECT tms, note FROM " . MAIN_DB_PREFIX . " const " ;
2020-01-18 16:17:07 +01:00
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " = ' " . $this -> db -> escape ( $this -> const_name ) . " ' " ;
$sql .= " AND entity IN (0, " . $conf -> entity . " ) " ;
2018-11-06 12:13:16 +01:00
2020-09-08 21:27:28 +02:00
dol_syslog ( get_class ( $this ) . " ::getLastActiveDate " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( ! $resql ) {
2020-09-08 21:27:28 +02:00
$err ++ ;
} else {
$obj = $this -> db -> fetch_object ( $resql );
if ( $obj ) {
2022-05-08 15:18:34 +02:00
$tmp = array ();
if ( $obj -> note ) {
$tmp = json_decode ( $obj -> note , true );
}
2021-11-23 23:27:07 +01:00
return array (
2023-01-12 10:10:28 +01:00
'authorid' => empty ( $tmp [ 'authorid' ]) ? '' : $tmp [ 'authorid' ],
'ip' => empty ( $tmp [ 'ip' ]) ? '' : $tmp [ 'ip' ],
2021-11-23 23:27:07 +01:00
'lastactivationdate' => $this -> db -> jdate ( $obj -> tms ),
'lastactivationversion' => ( ! empty ( $tmp [ 'lastactivationversion' ]) ? $tmp [ 'lastactivationversion' ] : 'unknown' ),
);
2020-09-08 21:27:28 +02:00
}
}
return array ();
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Insert constants for module activation
*
* @ return int Error count ( 0 if OK )
*/
protected function _active ()
{
// phpcs:enable
global $conf , $user ;
$err = 0 ;
// Common module
$entity = (( ! empty ( $this -> always_enabled ) || ! empty ( $this -> core_enabled )) ? 0 : $conf -> entity );
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " const " ;
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " = ' " . $this -> db -> escape ( $this -> const_name ) . " ' " ;
$sql .= " AND entity IN (0, " . $entity . " ) " ;
dol_syslog ( get_class ( $this ) . " ::_active delete activation constant " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
if ( ! $resql ) {
$err ++ ;
}
2021-11-23 23:27:07 +01:00
$note = json_encode (
array (
'authorid' => ( is_object ( $user ) ? $user -> id : 0 ),
'ip' => ( empty ( $_SERVER [ 'REMOTE_ADDR' ]) ? '' : $_SERVER [ 'REMOTE_ADDR' ]),
'lastactivationversion' => $this -> version ,
)
);
2020-09-08 21:27:28 +02:00
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " const (name, value, visible, entity, note) VALUES " ;
2021-09-02 13:25:00 +02:00
$sql .= " ( " . $this -> db -> encrypt ( $this -> const_name );
$sql .= " , " . $this -> db -> encrypt ( '1' );
$sql .= " , 0, " . (( int ) $entity );
2020-09-08 21:27:28 +02:00
$sql .= " , ' " . $this -> db -> escape ( $note ) . " ') " ;
dol_syslog ( get_class ( $this ) . " ::_active insert activation constant " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( ! $resql ) {
$err ++ ;
2020-09-08 21:27:28 +02:00
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Module deactivation
*
* @ return int Error count ( 0 if OK )
*/
protected function _unactive ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
// Common module
$entity = (( ! empty ( $this -> always_enabled ) || ! empty ( $this -> core_enabled )) ? 0 : $conf -> entity );
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " const " ;
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " = ' " . $this -> db -> escape ( $this -> const_name ) . " ' " ;
$sql .= " AND entity IN (0, " . $entity . " ) " ;
dol_syslog ( get_class ( $this ) . " ::_unactive " , LOG_DEBUG );
$this -> db -> query ( $sql );
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps,PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
2021-12-07 14:14:13 +01:00
* Create tables and keys required by module :
2022-05-08 15:18:34 +02:00
* - Files table . sql or table - module . sql with create table instructions
* - Then table . key . sql or table - module . key . sql with create keys instructions
2024-01-13 19:48:20 +01:00
* - Then data_xxx . sql ( usually provided by external modules only )
* - Then update_xxx . sql ( usually provided by external modules only )
2022-05-08 15:18:34 +02:00
* Files must be stored in subdirectory 'tables' or 'data' into directory $reldir ( Example : '/install/mysql/' or '/module/sql/' )
2022-02-06 13:06:12 +01:00
* This function may also be called by :
2022-05-08 15:18:34 +02:00
* - _load_tables ( '/install/mysql/' , 'modulename' ) into the this -> init () of core module descriptors .
2022-02-06 13:06:12 +01:00
* - _load_tables ( '/mymodule/sql/' ) into the this -> init () of external module descriptors .
2020-09-08 21:27:28 +02:00
*
2022-05-08 15:18:34 +02:00
* @ param string $reldir Relative directory where to scan files . Example : '/install/mysql/' or '/module/sql/'
2021-12-07 14:14:13 +01:00
* @ param string $onlywithsuffix Only with the defined suffix
2024-03-20 23:38:28 +01:00
* @ return int < 0 , 1 > Return integer <= 0 if KO , > 0 if OK
2020-09-08 21:27:28 +02:00
*/
2021-12-07 14:14:13 +01:00
protected function _load_tables ( $reldir , $onlywithsuffix = '' )
2020-09-08 21:27:28 +02:00
{
// phpcs:enable
global $conf ;
$error = 0 ;
$dirfound = 0 ;
2024-03-20 23:38:28 +01:00
$ok = 1 ;
2020-09-08 21:27:28 +02:00
if ( empty ( $reldir )) {
return 1 ;
}
include_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php' ;
2021-02-23 22:03:23 +01:00
foreach ( $conf -> file -> dol_document_root as $dirroot ) {
2024-03-20 23:38:28 +01:00
if ( $ok == 1 ) {
2022-05-08 15:18:34 +02:00
$dirsql = $dirroot . $reldir ;
2020-09-08 21:27:28 +02:00
$ok = 0 ;
2022-05-08 15:18:34 +02:00
// We will loop on xxx/, xxx/tables/, xxx/data/
$listofsubdir = array ( '' , 'tables/' , 'data/' );
if ( $this -> db -> type == 'pgsql' ) {
$listofsubdir [] = '../pgsql/functions/' ;
}
2020-09-08 21:27:28 +02:00
2022-05-08 15:18:34 +02:00
foreach ( $listofsubdir as $subdir ) {
$dir = $dirsql . $subdir ;
$handle = @ opendir ( $dir ); // Dir may not exists
if ( is_resource ( $handle )) {
$dirfound ++ ;
// Run llx_mytable.sql files, then llx_mytable_*.sql
$files = array ();
while (( $file = readdir ( $handle )) !== false ) {
$files [] = $file ;
2021-12-07 14:14:13 +01:00
}
2022-05-08 15:18:34 +02:00
sort ( $files );
foreach ( $files as $file ) {
if ( $onlywithsuffix ) {
if ( ! preg_match ( '/\-' . preg_quote ( $onlywithsuffix , '/' ) . '\./i' , $file )) {
//print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded<br>'."\n";
continue ;
} else {
//print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it<br>'."\n";
}
}
if ( preg_match ( '/\.sql$/i' , $file ) && ! preg_match ( '/\.key\.sql$/i' , $file ) && substr ( $file , 0 , 4 ) == 'llx_' ) {
2023-11-27 11:39:32 +01:00
$result = run_sql ( $dir . $file , ! getDolGlobalString ( 'MAIN_DISPLAY_SQL_INSTALL_LOG' ) ? 1 : 0 , '' , 1 );
2022-05-08 15:18:34 +02:00
if ( $result <= 0 ) {
$error ++ ;
}
2020-09-08 21:27:28 +02:00
}
}
2022-05-08 15:18:34 +02:00
rewinddir ( $handle );
2020-09-08 21:27:28 +02:00
2022-05-08 15:18:34 +02:00
// Run llx_mytable.key.sql files (Must be done after llx_mytable.sql) then then llx_mytable_*.key.sql
$files = array ();
while (( $file = readdir ( $handle )) !== false ) {
$files [] = $file ;
2021-12-07 14:14:13 +01:00
}
2022-05-08 15:18:34 +02:00
sort ( $files );
foreach ( $files as $file ) {
if ( $onlywithsuffix ) {
if ( ! preg_match ( '/\-' . preg_quote ( $onlywithsuffix , '/' ) . '\./i' , $file )) {
//print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded<br>'."\n";
continue ;
} else {
//print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it<br>'."\n";
}
}
if ( preg_match ( '/\.key\.sql$/i' , $file ) && substr ( $file , 0 , 4 ) == 'llx_' ) {
2023-11-27 11:39:32 +01:00
$result = run_sql ( $dir . $file , ! getDolGlobalString ( 'MAIN_DISPLAY_SQL_INSTALL_LOG' ) ? 1 : 0 , '' , 1 );
2022-05-08 15:18:34 +02:00
if ( $result <= 0 ) {
$error ++ ;
}
2020-09-08 21:27:28 +02:00
}
}
2022-05-08 15:18:34 +02:00
rewinddir ( $handle );
2020-09-08 21:27:28 +02:00
2022-05-08 15:18:34 +02:00
// Run functions-xxx.sql files (Must be done after llx_mytable.key.sql)
$files = array ();
while (( $file = readdir ( $handle )) !== false ) {
$files [] = $file ;
2021-12-07 14:14:13 +01:00
}
2022-05-08 15:18:34 +02:00
sort ( $files );
foreach ( $files as $file ) {
if ( $onlywithsuffix ) {
if ( ! preg_match ( '/\-' . preg_quote ( $onlywithsuffix , '/' ) . '\./i' , $file )) {
//print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded<br>'."\n";
continue ;
} else {
//print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it<br>'."\n";
}
}
if ( preg_match ( '/\.sql$/i' , $file ) && ! preg_match ( '/\.key\.sql$/i' , $file ) && substr ( $file , 0 , 9 ) == 'functions' ) {
2023-11-27 11:39:32 +01:00
$result = run_sql ( $dir . $file , ! getDolGlobalString ( 'MAIN_DISPLAY_SQL_INSTALL_LOG' ) ? 1 : 0 , '' , 1 );
2022-05-08 15:18:34 +02:00
if ( $result <= 0 ) {
$error ++ ;
}
2020-09-08 21:27:28 +02:00
}
}
2022-05-08 15:18:34 +02:00
rewinddir ( $handle );
2020-09-08 21:27:28 +02:00
2022-05-08 15:18:34 +02:00
// Run data_xxx.sql files (Must be done after llx_mytable.key.sql)
$files = array ();
while (( $file = readdir ( $handle )) !== false ) {
2023-12-04 12:07:31 +01:00
$files [] = $file ;
2022-05-08 15:18:34 +02:00
}
sort ( $files );
foreach ( $files as $file ) {
if ( $onlywithsuffix ) {
if ( ! preg_match ( '/\-' . preg_quote ( $onlywithsuffix , '/' ) . '\./i' , $file )) {
//print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded<br>'."\n";
continue ;
} else {
//print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it<br>'."\n";
}
}
if ( preg_match ( '/\.sql$/i' , $file ) && ! preg_match ( '/\.key\.sql$/i' , $file ) && substr ( $file , 0 , 4 ) == 'data' ) {
2023-11-27 11:39:32 +01:00
$result = run_sql ( $dir . $file , ! getDolGlobalString ( 'MAIN_DISPLAY_SQL_INSTALL_LOG' ) ? 1 : 0 , '' , 1 );
2022-05-08 15:18:34 +02:00
if ( $result <= 0 ) {
$error ++ ;
}
2021-12-07 14:14:13 +01:00
}
}
2022-05-08 15:18:34 +02:00
rewinddir ( $handle );
// Run update_xxx.sql files
$files = array ();
while (( $file = readdir ( $handle )) !== false ) {
2023-12-04 12:07:31 +01:00
$files [] = $file ;
2022-05-08 15:18:34 +02:00
}
sort ( $files );
foreach ( $files as $file ) {
if ( $onlywithsuffix ) {
if ( ! preg_match ( '/\-' . preg_quote ( $onlywithsuffix , '/' ) . '\./i' , $file )) {
//print 'File '.$file.' does not match suffix '.$onlywithsuffix.' so it is discarded<br>'."\n";
continue ;
} else {
//print 'File '.$file.' match suffix '.$onlywithsuffix.' so we keep it<br>'."\n";
}
}
if ( preg_match ( '/\.sql$/i' , $file ) && ! preg_match ( '/\.key\.sql$/i' , $file ) && substr ( $file , 0 , 6 ) == 'update' ) {
2023-11-27 11:39:32 +01:00
$result = run_sql ( $dir . $file , ! getDolGlobalString ( 'MAIN_DISPLAY_SQL_INSTALL_LOG' ) ? 1 : 0 , '' , 1 );
2022-05-08 15:18:34 +02:00
if ( $result <= 0 ) {
$error ++ ;
}
2020-09-08 21:27:28 +02:00
}
}
2022-05-08 15:18:34 +02:00
closedir ( $handle );
}
2020-09-08 21:27:28 +02:00
}
if ( $error == 0 ) {
$ok = 1 ;
}
}
}
if ( ! $dirfound ) {
2024-03-20 19:56:20 +01:00
dol_syslog ( " A module wants to load sql files from " . $reldir . " but this directory was not found. " , LOG_WARNING );
2020-09-08 21:27:28 +02:00
}
return $ok ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Adds boxes
*
* @ param string $option Options when disabling module ( 'newboxdefonly' = insert only boxes definition )
*
* @ return int Error count ( 0 if OK )
*/
public function insert_boxes ( $option = '' )
{
// phpcs:enable
include_once DOL_DOCUMENT_ROOT . '/core/class/infobox.class.php' ;
global $conf ;
$err = 0 ;
if ( is_array ( $this -> boxes )) {
dol_syslog ( get_class ( $this ) . " ::insert_boxes " , LOG_DEBUG );
$pos_name = InfoBox :: getListOfPagesForBoxes ();
2021-02-23 22:03:23 +01:00
foreach ( $this -> boxes as $key => $value ) {
2020-09-08 21:27:28 +02:00
$file = isset ( $this -> boxes [ $key ][ 'file' ]) ? $this -> boxes [ $key ][ 'file' ] : '' ;
$note = isset ( $this -> boxes [ $key ][ 'note' ]) ? $this -> boxes [ $key ][ 'note' ] : '' ;
$enabledbydefaulton = isset ( $this -> boxes [ $key ][ 'enabledbydefaulton' ]) ? $this -> boxes [ $key ][ 'enabledbydefaulton' ] : 'Home' ;
2021-01-02 22:12:19 +01:00
if ( empty ( $file )) {
$file = isset ( $this -> boxes [ $key ][ 1 ]) ? $this -> boxes [ $key ][ 1 ] : '' ; // For backward compatibility
2020-09-08 21:27:28 +02:00
}
2021-01-02 22:12:19 +01:00
if ( empty ( $note )) {
$note = isset ( $this -> boxes [ $key ][ 2 ]) ? $this -> boxes [ $key ][ 2 ] : '' ; // For backward compatibility
2020-09-08 21:27:28 +02:00
}
// Search if boxes def already present
$sql = " SELECT count(*) as nb FROM " . MAIN_DB_PREFIX . " boxes_def " ;
$sql .= " WHERE file = ' " . $this -> db -> escape ( $file ) . " ' " ;
$sql .= " AND entity = " . $conf -> entity ;
2021-01-02 22:12:19 +01:00
if ( $note ) {
$sql .= " AND note =' " . $this -> db -> escape ( $note ) . " ' " ;
2020-09-08 21:27:28 +02:00
}
$result = $this -> db -> query ( $sql );
if ( $result ) {
$obj = $this -> db -> fetch_object ( $result );
if ( $obj -> nb == 0 ) {
$this -> db -> begin ();
if ( ! $err ) {
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " boxes_def (file, entity, note) " ;
$sql .= " VALUES (' " . $this -> db -> escape ( $file ) . " ', " ;
$sql .= $conf -> entity . " , " ;
$sql .= $note ? " ' " . $this -> db -> escape ( $note ) . " ' " : " null " ;
$sql .= " ) " ;
dol_syslog ( get_class ( $this ) . " ::insert_boxes " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( ! $resql ) {
$err ++ ;
2020-09-08 21:27:28 +02:00
}
}
if ( ! $err && ! preg_match ( '/newboxdefonly/' , $option )) {
$lastid = $this -> db -> last_insert_id ( MAIN_DB_PREFIX . " boxes_def " , " rowid " );
2021-02-23 22:03:23 +01:00
foreach ( $pos_name as $key2 => $val2 ) {
2021-01-02 22:12:19 +01:00
//print 'key2='.$key2.'-val2='.$val2."<br>\n";
if ( $enabledbydefaulton && $val2 != $enabledbydefaulton ) {
continue ; // Not enabled by default onto this page.
2020-09-08 21:27:28 +02:00
}
2021-08-27 22:42:04 +02:00
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " boxes (box_id, position, box_order, fk_user, entity) " ;
$sql .= " VALUES ( " . (( int ) $lastid ) . " , " . (( int ) $key2 ) . " , '0', 0, " . (( int ) $conf -> entity ) . " ) " ;
2020-09-08 21:27:28 +02:00
2022-12-28 16:40:03 +01:00
dol_syslog ( get_class ( $this ) . " ::insert_boxes onto page " . $key2 . " = " . $val2 , LOG_DEBUG );
2020-09-08 21:27:28 +02:00
$resql = $this -> db -> query ( $sql );
2021-01-02 22:12:19 +01:00
if ( ! $resql ) {
$err ++ ;
2020-09-08 21:27:28 +02:00
}
}
}
if ( ! $err ) {
$this -> db -> commit ();
} else {
2021-01-02 22:12:19 +01:00
$this -> error = $this -> db -> lasterror ();
$this -> db -> rollback ();
2020-09-08 21:27:28 +02:00
}
}
// else box already registered into database
} else {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
}
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Removes boxes
*
* @ return int Error count ( 0 if OK )
*/
public function delete_boxes ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
if ( is_array ( $this -> boxes )) {
2021-02-23 22:03:23 +01:00
foreach ( $this -> boxes as $key => $value ) {
2020-09-08 21:27:28 +02:00
//$titre = $this->boxes[$key][0];
2021-07-19 17:51:06 +02:00
if ( empty ( $this -> boxes [ $key ][ 'file' ])) {
$file = isset ( $this -> boxes [ $key ][ 1 ]) ? $this -> boxes [ $key ][ 1 ] : '' ; // For backward compatibility
2021-08-17 19:28:26 +02:00
} else {
2021-07-19 17:51:06 +02:00
$file = $this -> boxes [ $key ][ 'file' ];
2021-08-17 19:28:26 +02:00
}
2021-08-17 21:58:06 +02:00
2020-09-08 21:27:28 +02:00
//$note = $this->boxes[$key][2];
// TODO If the box is also included by another module and the other module is still on, we should not remove it.
// For the moment, we manage this with hard coded exception
//print "Remove box ".$file.'<br>';
if ( $file == 'box_graph_product_distribution.php' ) {
2022-08-23 20:02:37 +02:00
if ( isModEnabled ( " product " ) || isModEnabled ( " service " )) {
2020-12-07 11:42:35 +01:00
dol_syslog ( " We discard deleting module " . $file . " because another module still active requires it. " );
2020-09-08 21:27:28 +02:00
continue ;
}
}
if ( $this -> db -> type == 'sqlite3' ) {
// sqlite doesn't support "USING" syntax.
// TODO: remove this dependency.
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " boxes " ;
$sql .= " WHERE " . MAIN_DB_PREFIX . " boxes.box_id IN ( " ;
$sql .= " SELECT " . MAIN_DB_PREFIX . " boxes_def.rowid " ;
$sql .= " FROM " . MAIN_DB_PREFIX . " boxes_def " ;
$sql .= " WHERE " . MAIN_DB_PREFIX . " boxes_def.file = ' " . $this -> db -> escape ( $file ) . " ') " ;
$sql .= " AND " . MAIN_DB_PREFIX . " boxes.entity = " . $conf -> entity ;
} else {
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " boxes " ;
$sql .= " USING " . MAIN_DB_PREFIX . " boxes, " . MAIN_DB_PREFIX . " boxes_def " ;
$sql .= " WHERE " . MAIN_DB_PREFIX . " boxes.box_id = " . MAIN_DB_PREFIX . " boxes_def.rowid " ;
$sql .= " AND " . MAIN_DB_PREFIX . " boxes_def.file = ' " . $this -> db -> escape ( $file ) . " ' " ;
$sql .= " AND " . MAIN_DB_PREFIX . " boxes.entity = " . $conf -> entity ;
}
dol_syslog ( get_class ( $this ) . " ::delete_boxes " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
if ( ! $resql ) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " boxes_def " ;
$sql .= " WHERE file = ' " . $this -> db -> escape ( $file ) . " ' " ;
2020-12-07 11:42:35 +01:00
$sql .= " AND entity = " . $conf -> entity ; // Do not use getEntity here, we want to delete only in current company
2020-09-08 21:27:28 +02:00
dol_syslog ( get_class ( $this ) . " ::delete_boxes " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
if ( ! $resql ) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
}
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Adds cronjobs
*
* @ return int Error count ( 0 if OK )
*/
public function insert_cronjobs ()
{
// phpcs:enable
include_once DOL_DOCUMENT_ROOT . '/core/class/infobox.class.php' ;
global $conf ;
$err = 0 ;
if ( is_array ( $this -> cronjobs )) {
dol_syslog ( get_class ( $this ) . " ::insert_cronjobs " , LOG_DEBUG );
2021-02-23 22:03:23 +01:00
foreach ( $this -> cronjobs as $key => $value ) {
2020-09-08 21:27:28 +02:00
$entity = isset ( $this -> cronjobs [ $key ][ 'entity' ]) ? $this -> cronjobs [ $key ][ 'entity' ] : $conf -> entity ;
$label = isset ( $this -> cronjobs [ $key ][ 'label' ]) ? $this -> cronjobs [ $key ][ 'label' ] : '' ;
$jobtype = isset ( $this -> cronjobs [ $key ][ 'jobtype' ]) ? $this -> cronjobs [ $key ][ 'jobtype' ] : '' ;
$class = isset ( $this -> cronjobs [ $key ][ 'class' ]) ? $this -> cronjobs [ $key ][ 'class' ] : '' ;
$objectname = isset ( $this -> cronjobs [ $key ][ 'objectname' ]) ? $this -> cronjobs [ $key ][ 'objectname' ] : '' ;
$method = isset ( $this -> cronjobs [ $key ][ 'method' ]) ? $this -> cronjobs [ $key ][ 'method' ] : '' ;
$command = isset ( $this -> cronjobs [ $key ][ 'command' ]) ? $this -> cronjobs [ $key ][ 'command' ] : '' ;
$parameters = isset ( $this -> cronjobs [ $key ][ 'parameters' ]) ? $this -> cronjobs [ $key ][ 'parameters' ] : '' ;
$comment = isset ( $this -> cronjobs [ $key ][ 'comment' ]) ? $this -> cronjobs [ $key ][ 'comment' ] : '' ;
$frequency = isset ( $this -> cronjobs [ $key ][ 'frequency' ]) ? $this -> cronjobs [ $key ][ 'frequency' ] : '' ;
$unitfrequency = isset ( $this -> cronjobs [ $key ][ 'unitfrequency' ]) ? $this -> cronjobs [ $key ][ 'unitfrequency' ] : '' ;
$priority = isset ( $this -> cronjobs [ $key ][ 'priority' ]) ? $this -> cronjobs [ $key ][ 'priority' ] : '' ;
$datestart = isset ( $this -> cronjobs [ $key ][ 'datestart' ]) ? $this -> cronjobs [ $key ][ 'datestart' ] : '' ;
$dateend = isset ( $this -> cronjobs [ $key ][ 'dateend' ]) ? $this -> cronjobs [ $key ][ 'dateend' ] : '' ;
$status = isset ( $this -> cronjobs [ $key ][ 'status' ]) ? $this -> cronjobs [ $key ][ 'status' ] : '' ;
$test = isset ( $this -> cronjobs [ $key ][ 'test' ]) ? $this -> cronjobs [ $key ][ 'test' ] : '' ; // Line must be enabled or not (so visible or not)
// Search if cron entry already present
$sql = " SELECT count(*) as nb FROM " . MAIN_DB_PREFIX . " cronjob " ;
2022-06-30 13:25:42 +02:00
//$sql .= " WHERE module_name = '".$this->db->escape(empty($this->rights_class) ?strtolower($this->name) : $this->rights_class)."'";
$sql .= " WHERE label = ' " . $this -> db -> escape ( $label ) . " ' " ;
/* if ( $class ) {
2020-09-08 21:27:28 +02:00
$sql .= " AND classesname = ' " . $this -> db -> escape ( $class ) . " ' " ;
}
if ( $objectname ) {
$sql .= " AND objectname = ' " . $this -> db -> escape ( $objectname ) . " ' " ;
}
if ( $method ) {
$sql .= " AND methodename = ' " . $this -> db -> escape ( $method ) . " ' " ;
}
if ( $command ) {
$sql .= " AND command = ' " . $this -> db -> escape ( $command ) . " ' " ;
}
2022-05-19 09:45:37 +02:00
if ( $parameters ) {
$sql .= " AND params = ' " . $this -> db -> escape ( $parameters ) . " ' " ;
2022-06-30 13:25:42 +02:00
} */
2021-06-09 15:36:47 +02:00
$sql .= " AND entity = " . (( int ) $entity ); // Must be exact entity
2020-09-08 21:27:28 +02:00
$now = dol_now ();
$result = $this -> db -> query ( $sql );
if ( $result ) {
$obj = $this -> db -> fetch_object ( $result );
if ( $obj -> nb == 0 ) {
$this -> db -> begin ();
if ( ! $err ) {
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " cronjob (module_name, datec, datestart, dateend, label, jobtype, classesname, objectname, methodename, command, params, note, " ;
2021-02-23 22:03:23 +01:00
if ( is_int ( $frequency )) {
$sql .= ' frequency,' ;
}
if ( is_int ( $unitfrequency )) {
$sql .= ' unitfrequency,' ;
}
if ( is_int ( $priority )) {
$sql .= ' priority,' ;
}
if ( is_int ( $status )) {
$sql .= ' status,' ;
}
2020-09-08 21:27:28 +02:00
$sql .= " entity, test) " ;
$sql .= " VALUES ( " ;
2023-12-04 12:07:31 +01:00
$sql .= " ' " . $this -> db -> escape ( empty ( $this -> rights_class ) ? strtolower ( $this -> name ) : $this -> rights_class ) . " ', " ;
2020-09-08 21:27:28 +02:00
$sql .= " ' " . $this -> db -> idate ( $now ) . " ', " ;
$sql .= ( $datestart ? " ' " . $this -> db -> idate ( $datestart ) . " ' " : " ' " . $this -> db -> idate ( $now ) . " ' " ) . " , " ;
$sql .= ( $dateend ? " ' " . $this -> db -> idate ( $dateend ) . " ' " : " NULL " ) . " , " ;
$sql .= " ' " . $this -> db -> escape ( $label ) . " ', " ;
$sql .= " ' " . $this -> db -> escape ( $jobtype ) . " ', " ;
$sql .= ( $class ? " ' " . $this -> db -> escape ( $class ) . " ' " : " null " ) . " , " ;
$sql .= ( $objectname ? " ' " . $this -> db -> escape ( $objectname ) . " ' " : " null " ) . " , " ;
$sql .= ( $method ? " ' " . $this -> db -> escape ( $method ) . " ' " : " null " ) . " , " ;
$sql .= ( $command ? " ' " . $this -> db -> escape ( $command ) . " ' " : " null " ) . " , " ;
$sql .= ( $parameters ? " ' " . $this -> db -> escape ( $parameters ) . " ' " : " null " ) . " , " ;
$sql .= ( $comment ? " ' " . $this -> db -> escape ( $comment ) . " ' " : " null " ) . " , " ;
2021-02-23 22:03:23 +01:00
if ( is_int ( $frequency )) {
$sql .= " ' " . $this -> db -> escape ( $frequency ) . " ', " ;
2020-09-08 21:27:28 +02:00
}
2021-02-23 22:03:23 +01:00
if ( is_int ( $unitfrequency )) {
$sql .= " ' " . $this -> db -> escape ( $unitfrequency ) . " ', " ;
2020-09-08 21:27:28 +02:00
}
2021-02-23 22:03:23 +01:00
if ( is_int ( $priority )) {
$sql .= " ' " . $this -> db -> escape ( $priority ) . " ', " ;
2020-09-08 21:27:28 +02:00
}
2021-02-23 22:03:23 +01:00
if ( is_int ( $status )) {
2022-06-30 13:25:42 +02:00
$sql .= (( int ) $status ) . " , " ;
2020-09-08 21:27:28 +02:00
}
$sql .= $entity . " , " ;
$sql .= " ' " . $this -> db -> escape ( $test ) . " ' " ;
$sql .= " ) " ;
$resql = $this -> db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( ! $resql ) {
$err ++ ;
2020-09-08 21:27:28 +02:00
}
}
if ( ! $err ) {
$this -> db -> commit ();
} else {
$this -> error = $this -> db -> lasterror ();
$this -> db -> rollback ();
}
}
// else box already registered into database
} else {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
}
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Removes boxes
*
* @ return int Error count ( 0 if OK )
*/
public function delete_cronjobs ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
if ( is_array ( $this -> cronjobs )) {
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " cronjob " ;
2023-12-04 12:07:31 +01:00
$sql .= " WHERE module_name = ' " . $this -> db -> escape ( empty ( $this -> rights_class ) ? strtolower ( $this -> name ) : $this -> rights_class ) . " ' " ;
2020-09-08 21:27:28 +02:00
$sql .= " AND entity = " . $conf -> entity ;
$sql .= " AND test = '1' " ; // We delete on lines that are not set with a complete test that is '$conf->module->enabled' so when module is disabled, the cron is also removed.
2023-12-04 12:07:31 +01:00
// For crons declared with a '$conf->module->enabled', there is no need to delete the line, so we don't loose setup if we reenable module.
2020-09-08 21:27:28 +02:00
dol_syslog ( get_class ( $this ) . " ::delete_cronjobs " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
if ( ! $resql ) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Removes tabs
*
* @ return int Error count ( 0 if OK )
*/
public function delete_tabs ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " const " ;
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " like ' " . $this -> db -> escape ( $this -> const_name ) . " _TABS_%' " ;
$sql .= " AND entity = " . $conf -> entity ;
dol_syslog ( get_class ( $this ) . " ::delete_tabs " , LOG_DEBUG );
if ( ! $this -> db -> query ( $sql )) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Adds tabs
*
* @ return int Error count ( 0 if ok )
*/
public function insert_tabs ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
if ( ! empty ( $this -> tabs )) {
dol_syslog ( get_class ( $this ) . " ::insert_tabs " , LOG_DEBUG );
$i = 0 ;
2021-02-23 22:03:23 +01:00
foreach ( $this -> tabs as $key => $value ) {
if ( is_array ( $value ) && count ( $value ) == 0 ) {
continue ; // Discard empty arrays
2020-09-08 21:27:28 +02:00
}
$entity = $conf -> entity ;
$newvalue = $value ;
if ( is_array ( $value )) {
$newvalue = $value [ 'data' ];
2021-02-23 22:03:23 +01:00
if ( isset ( $value [ 'entity' ])) {
$entity = $value [ 'entity' ];
2020-09-08 21:27:28 +02:00
}
}
if ( $newvalue ) {
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " const ( " ;
$sql .= " name " ;
$sql .= " , type " ;
$sql .= " , value " ;
$sql .= " , note " ;
$sql .= " , visible " ;
$sql .= " , entity " ;
$sql .= " ) " ;
$sql .= " VALUES ( " ;
2021-09-02 13:25:00 +02:00
$sql .= $this -> db -> encrypt ( $this -> const_name . " _TABS_ " . $i );
2020-09-08 21:27:28 +02:00
$sql .= " , 'chaine' " ;
2021-09-02 13:25:00 +02:00
$sql .= " , " . $this -> db -> encrypt ( $newvalue );
2020-09-08 21:27:28 +02:00
$sql .= " , null " ;
$sql .= " , '0' " ;
2021-09-03 21:25:17 +02:00
$sql .= " , " . (( int ) $entity );
2020-09-08 21:27:28 +02:00
$sql .= " ) " ;
$resql = $this -> db -> query ( $sql );
if ( ! $resql ) {
2023-12-04 12:07:31 +01:00
dol_syslog ( $this -> db -> lasterror (), LOG_ERR );
2020-09-08 21:27:28 +02:00
if ( $this -> db -> lasterrno () != 'DB_ERROR_RECORD_ALREADY_EXISTS' ) {
$this -> error = $this -> db -> lasterror ();
$this -> errors [] = $this -> db -> lasterror ();
$err ++ ;
break ;
}
}
}
$i ++ ;
}
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Adds constants
*
* @ return int Error count ( 0 if OK )
*/
public function insert_const ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
2021-02-23 22:03:23 +01:00
if ( empty ( $this -> const )) {
return 0 ;
2020-09-08 21:27:28 +02:00
}
2024-03-05 00:15:33 +01:00
dol_syslog ( __METHOD__ , LOG_DEBUG );
2020-09-08 21:27:28 +02:00
2021-02-23 22:03:23 +01:00
foreach ( $this -> const as $key => $value ) {
2020-09-08 21:27:28 +02:00
$name = $this -> const [ $key ][ 0 ];
$type = $this -> const [ $key ][ 1 ];
$val = $this -> const [ $key ][ 2 ];
$note = isset ( $this -> const [ $key ][ 3 ]) ? $this -> const [ $key ][ 3 ] : '' ;
$visible = isset ( $this -> const [ $key ][ 4 ]) ? $this -> const [ $key ][ 4 ] : 0 ;
$entity = ( ! empty ( $this -> const [ $key ][ 5 ]) && $this -> const [ $key ][ 5 ] != 'current' ) ? 0 : $conf -> entity ;
// Clean
2021-02-23 22:03:23 +01:00
if ( empty ( $visible )) {
$visible = '0' ;
2020-09-08 21:27:28 +02:00
}
2021-02-23 22:03:23 +01:00
if ( empty ( $val ) && $val != '0' ) {
$val = '' ;
2020-09-08 21:27:28 +02:00
}
2023-05-10 16:33:07 +02:00
$sql = " SELECT count(*) as nb " ;
2020-09-08 21:27:28 +02:00
$sql .= " FROM " . MAIN_DB_PREFIX . " const " ;
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " = ' " . $this -> db -> escape ( $name ) . " ' " ;
2021-06-09 15:36:47 +02:00
$sql .= " AND entity = " . (( int ) $entity );
2020-09-08 21:27:28 +02:00
$result = $this -> db -> query ( $sql );
if ( $result ) {
$row = $this -> db -> fetch_row ( $result );
2021-02-23 22:03:23 +01:00
if ( $row [ 0 ] == 0 ) { // If not found
2020-09-08 21:27:28 +02:00
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " const (name,type,value,note,visible,entity) " ;
$sql .= " VALUES ( " ;
2021-09-02 13:25:00 +02:00
$sql .= $this -> db -> encrypt ( $name );
2020-09-19 22:41:05 +02:00
$sql .= " ,' " . $this -> db -> escape ( $type ) . " ' " ;
2021-09-02 13:25:00 +02:00
$sql .= " , " . (( $val != '' ) ? $this -> db -> encrypt ( $val ) : " '' " );
2020-09-08 21:27:28 +02:00
$sql .= " , " . ( $note ? " ' " . $this -> db -> escape ( $note ) . " ' " : " null " );
2020-09-19 22:41:05 +02:00
$sql .= " ,' " . $this -> db -> escape ( $visible ) . " ' " ;
2020-09-08 21:27:28 +02:00
$sql .= " , " . $entity ;
$sql .= " ) " ;
if ( ! $this -> db -> query ( $sql )) {
$err ++ ;
}
} else {
2024-03-05 00:15:33 +01:00
dol_syslog ( __METHOD__ . " constant ' " . $name . " ' already exists " , LOG_DEBUG );
2020-09-08 21:27:28 +02:00
}
} else {
$err ++ ;
}
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Removes constants tagged 'deleteonunactive'
*
2023-12-06 15:46:39 +01:00
* @ return int Return integer < 0 if KO , 0 if OK
2020-09-08 21:27:28 +02:00
*/
public function delete_const ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
2021-02-23 22:03:23 +01:00
if ( empty ( $this -> const )) {
return 0 ;
2020-09-08 21:27:28 +02:00
}
2021-02-23 22:03:23 +01:00
foreach ( $this -> const as $key => $value ) {
2020-09-08 21:27:28 +02:00
$name = $this -> const [ $key ][ 0 ];
$deleteonunactive = ( ! empty ( $this -> const [ $key ][ 6 ])) ? 1 : 0 ;
if ( $deleteonunactive ) {
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " const " ;
2020-09-19 22:41:05 +02:00
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " = ' " . $this -> db -> escape ( $name ) . " ' " ;
2020-09-08 21:27:28 +02:00
$sql .= " AND entity in (0, " . $conf -> entity . " ) " ;
dol_syslog ( get_class ( $this ) . " ::delete_const " , LOG_DEBUG );
if ( ! $this -> db -> query ( $sql )) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
}
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Adds access rights
*
2021-12-09 11:07:38 +01:00
* @ param int $reinitadminperms If 1 , we also grant them to all admin users
* @ param int $force_entity Force current entity
* @ param int $notrigger 1 = Does not execute triggers , 0 = execute triggers
* @ return int Error count ( 0 if OK )
2020-09-08 21:27:28 +02:00
*/
public function insert_permissions ( $reinitadminperms = 0 , $force_entity = null , $notrigger = 0 )
{
// phpcs:enable
global $conf , $user ;
$err = 0 ;
$entity = ( ! empty ( $force_entity ) ? $force_entity : $conf -> entity );
dol_syslog ( get_class ( $this ) . " ::insert_permissions " , LOG_DEBUG );
// Test if module is activated
$sql_del = " SELECT " . $this -> db -> decrypt ( 'value' ) . " as value " ;
$sql_del .= " FROM " . MAIN_DB_PREFIX . " const " ;
$sql_del .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " = ' " . $this -> db -> escape ( $this -> const_name ) . " ' " ;
$sql_del .= " AND entity IN (0, " . $entity . " ) " ;
$resql = $this -> db -> query ( $sql_del );
if ( $resql ) {
$obj = $this -> db -> fetch_object ( $resql );
2021-12-09 11:07:38 +01:00
2020-09-08 21:27:28 +02:00
if ( $obj !== null && ! empty ( $obj -> value ) && ! empty ( $this -> rights )) {
2021-12-09 11:07:38 +01:00
include_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php' ;
2020-09-08 21:27:28 +02:00
// If the module is active
2021-02-23 22:03:23 +01:00
foreach ( $this -> rights as $key => $value ) {
2021-12-09 11:07:38 +01:00
$r_id = $this -> rights [ $key ][ 0 ]; // permission id in llx_rights_def (not unique because primary key is couple id-entity)
2020-09-08 21:27:28 +02:00
$r_desc = $this -> rights [ $key ][ 1 ];
$r_type = isset ( $this -> rights [ $key ][ 2 ]) ? $this -> rights [ $key ][ 2 ] : '' ;
2020-11-01 20:02:12 +01:00
$r_def = empty ( $this -> rights [ $key ][ 3 ]) ? 0 : $this -> rights [ $key ][ 3 ];
2020-09-08 21:27:28 +02:00
$r_perms = $this -> rights [ $key ][ 4 ];
$r_subperms = isset ( $this -> rights [ $key ][ 5 ]) ? $this -> rights [ $key ][ 5 ] : '' ;
2021-12-09 11:07:38 +01:00
$r_modul = empty ( $this -> rights_class ) ? strtolower ( $this -> name ) : $this -> rights_class ;
2020-09-08 21:27:28 +02:00
2021-02-23 22:03:23 +01:00
if ( empty ( $r_type )) {
$r_type = 'w' ;
}
2020-09-08 21:27:28 +02:00
// Search if perm already present
$sql = " SELECT count(*) as nb FROM " . MAIN_DB_PREFIX . " rights_def " ;
2021-03-30 17:53:25 +02:00
$sql .= " WHERE id = " . (( int ) $r_id ) . " AND entity = " . (( int ) $entity );
2020-09-08 21:27:28 +02:00
$resqlselect = $this -> db -> query ( $sql );
if ( $resqlselect ) {
$objcount = $this -> db -> fetch_object ( $resqlselect );
if ( $objcount && $objcount -> nb == 0 ) {
if ( dol_strlen ( $r_perms )) {
if ( dol_strlen ( $r_subperms )) {
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " rights_def " ;
$sql .= " (id, entity, libelle, module, type, bydefault, perms, subperms) " ;
$sql .= " VALUES " ;
2020-09-19 22:41:05 +02:00
$sql .= " ( " . $r_id . " , " . $entity . " ,' " . $this -> db -> escape ( $r_desc ) . " ',' " . $this -> db -> escape ( $r_modul ) . " ',' " . $this -> db -> escape ( $r_type ) . " ', " . $r_def . " ,' " . $this -> db -> escape ( $r_perms ) . " ',' " . $this -> db -> escape ( $r_subperms ) . " ') " ;
2020-09-08 21:27:28 +02:00
} else {
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " rights_def " ;
$sql .= " (id, entity, libelle, module, type, bydefault, perms) " ;
$sql .= " VALUES " ;
2020-09-19 22:41:05 +02:00
$sql .= " ( " . $r_id . " , " . $entity . " ,' " . $this -> db -> escape ( $r_desc ) . " ',' " . $this -> db -> escape ( $r_modul ) . " ',' " . $this -> db -> escape ( $r_type ) . " ', " . $r_def . " ,' " . $this -> db -> escape ( $r_perms ) . " ') " ;
2020-09-08 21:27:28 +02:00
}
} else {
2023-12-04 12:07:31 +01:00
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " rights_def " ;
$sql .= " (id, entity, libelle, module, type, bydefault) " ;
$sql .= " VALUES " ;
$sql .= " ( " . $r_id . " , " . $entity . " ,' " . $this -> db -> escape ( $r_desc ) . " ',' " . $this -> db -> escape ( $r_modul ) . " ',' " . $this -> db -> escape ( $r_type ) . " ', " . $r_def . " ) " ;
2020-09-08 21:27:28 +02:00
}
$resqlinsert = $this -> db -> query ( $sql , 1 );
if ( ! $resqlinsert ) {
if ( $this -> db -> errno () != " DB_ERROR_RECORD_ALREADY_EXISTS " ) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
break ;
2021-02-23 22:03:23 +01:00
} else {
dol_syslog ( get_class ( $this ) . " ::insert_permissions record already exists " , LOG_INFO );
2020-09-08 21:27:28 +02:00
}
}
$this -> db -> free ( $resqlinsert );
}
$this -> db -> free ( $resqlselect );
}
// If we want to init permissions on admin users
if ( $reinitadminperms ) {
$sql = " SELECT rowid FROM " . MAIN_DB_PREFIX . " user WHERE admin = 1 " ;
dol_syslog ( get_class ( $this ) . " ::insert_permissions Search all admin users " , LOG_DEBUG );
2021-12-09 11:07:38 +01:00
2020-09-08 21:27:28 +02:00
$resqlseladmin = $this -> db -> query ( $sql , 1 );
2021-12-09 11:07:38 +01:00
2020-09-08 21:27:28 +02:00
if ( $resqlseladmin ) {
$num = $this -> db -> num_rows ( $resqlseladmin );
$i = 0 ;
2021-02-23 22:03:23 +01:00
while ( $i < $num ) {
2021-12-09 11:07:38 +01:00
$obj2 = $this -> db -> fetch_object ( $resqlseladmin );
2022-11-01 14:00:08 +01:00
dol_syslog ( get_class ( $this ) . " ::insert_permissions Add permission id " . $r_id . " to user id= " . $obj2 -> rowid );
2020-09-08 21:27:28 +02:00
2021-12-09 11:07:38 +01:00
$tmpuser = new User ( $this -> db );
$result = $tmpuser -> fetch ( $obj2 -> rowid );
2020-09-08 21:27:28 +02:00
if ( $result > 0 ) {
$tmpuser -> addrights ( $r_id , '' , '' , 0 , 1 );
} else {
dol_syslog ( get_class ( $this ) . " ::insert_permissions Failed to add the permission to user because fetch return an error " , LOG_ERR );
}
2023-12-04 12:07:31 +01:00
$i ++ ;
2020-09-08 21:27:28 +02:00
}
} else {
dol_print_error ( $this -> db );
}
}
}
2021-02-23 22:03:23 +01:00
if ( $reinitadminperms && ! empty ( $user -> admin )) { // Reload permission for current user if defined
2020-09-08 21:27:28 +02:00
// We reload permissions
$user -> clearrights ();
$user -> getrights ();
}
}
$this -> db -> free ( $resql );
} else {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Removes access rights
*
* @ return int Error count ( 0 if OK )
*/
public function delete_permissions ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " rights_def " ;
2023-12-04 12:07:31 +01:00
$sql .= " WHERE module = ' " . $this -> db -> escape ( empty ( $this -> rights_class ) ? strtolower ( $this -> name ) : $this -> rights_class ) . " ' " ;
2020-09-08 21:27:28 +02:00
$sql .= " AND entity = " . $conf -> entity ;
dol_syslog ( get_class ( $this ) . " ::delete_permissions " , LOG_DEBUG );
if ( ! $this -> db -> query ( $sql )) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Adds menu entries
*
* @ return int Error count ( 0 if OK )
*/
public function insert_menus ()
{
// phpcs:enable
2023-03-29 14:30:32 +02:00
global $conf , $user ;
2020-09-08 21:27:28 +02:00
2021-02-15 20:13:38 +01:00
if ( ! is_array ( $this -> menu ) || empty ( $this -> menu )) {
return 0 ;
2020-09-08 21:27:28 +02:00
}
include_once DOL_DOCUMENT_ROOT . '/core/class/menubase.class.php' ;
dol_syslog ( get_class ( $this ) . " ::insert_menus " , LOG_DEBUG );
$err = 0 ;
2023-03-29 14:30:32 +02:00
// Common module
$entity = (( ! empty ( $this -> always_enabled ) || ! empty ( $this -> core_enabled )) ? 0 : $conf -> entity );
2020-09-08 21:27:28 +02:00
$this -> db -> begin ();
2021-02-23 22:03:23 +01:00
foreach ( $this -> menu as $key => $value ) {
2020-09-08 21:27:28 +02:00
$menu = new Menubase ( $this -> db );
$menu -> menu_handler = 'all' ;
//$menu->module=strtolower($this->name); TODO When right_class will be same than module name
2022-11-01 14:00:08 +01:00
$menu -> module = ( empty ( $this -> rights_class ) ? strtolower ( $this -> name ) : $this -> rights_class );
2020-09-08 21:27:28 +02:00
if ( ! $this -> menu [ $key ][ 'fk_menu' ]) {
$menu -> fk_menu = 0 ;
} else {
$foundparent = 0 ;
$fk_parent = $this -> menu [ $key ][ 'fk_menu' ];
2022-11-01 14:00:08 +01:00
$reg = array ();
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/^r=/' , $fk_parent )) { // old deprecated method
2020-09-08 21:27:28 +02:00
$fk_parent = str_replace ( 'r=' , '' , $fk_parent );
if ( isset ( $this -> menu [ $fk_parent ][ 'rowid' ])) {
$menu -> fk_menu = $this -> menu [ $fk_parent ][ 'rowid' ];
$foundparent = 1 ;
}
} elseif ( preg_match ( '/^fk_mainmenu=([a-zA-Z0-9_]+),fk_leftmenu=([a-zA-Z0-9_]+)$/' , $fk_parent , $reg )) {
$menu -> fk_menu = - 1 ;
$menu -> fk_mainmenu = $reg [ 1 ];
$menu -> fk_leftmenu = $reg [ 2 ];
$foundparent = 1 ;
} elseif ( preg_match ( '/^fk_mainmenu=([a-zA-Z0-9_]+)$/' , $fk_parent , $reg )) {
$menu -> fk_menu = - 1 ;
$menu -> fk_mainmenu = $reg [ 1 ];
$menu -> fk_leftmenu = '' ;
$foundparent = 1 ;
}
if ( ! $foundparent ) {
$this -> error = " ErrorBadDefinitionOfMenuArrayInModuleDescriptor " ;
dol_syslog ( get_class ( $this ) . " ::insert_menus " . $this -> error . " " . $this -> menu [ $key ][ 'fk_menu' ], LOG_ERR );
$err ++ ;
}
}
$menu -> type = $this -> menu [ $key ][ 'type' ];
$menu -> mainmenu = isset ( $this -> menu [ $key ][ 'mainmenu' ]) ? $this -> menu [ $key ][ 'mainmenu' ] : ( isset ( $menu -> fk_mainmenu ) ? $menu -> fk_mainmenu : '' );
$menu -> leftmenu = isset ( $this -> menu [ $key ][ 'leftmenu' ]) ? $this -> menu [ $key ][ 'leftmenu' ] : '' ;
$menu -> title = $this -> menu [ $key ][ 'titre' ];
2021-02-07 21:56:57 +01:00
$menu -> prefix = isset ( $this -> menu [ $key ][ 'prefix' ]) ? $this -> menu [ $key ][ 'prefix' ] : '' ;
2020-09-08 21:27:28 +02:00
$menu -> url = $this -> menu [ $key ][ 'url' ];
2021-02-07 21:56:57 +01:00
$menu -> langs = isset ( $this -> menu [ $key ][ 'langs' ]) ? $this -> menu [ $key ][ 'langs' ] : '' ;
2020-09-08 21:27:28 +02:00
$menu -> position = $this -> menu [ $key ][ 'position' ];
$menu -> perms = $this -> menu [ $key ][ 'perms' ];
$menu -> target = isset ( $this -> menu [ $key ][ 'target' ]) ? $this -> menu [ $key ][ 'target' ] : '' ;
$menu -> user = $this -> menu [ $key ][ 'user' ];
$menu -> enabled = isset ( $this -> menu [ $key ][ 'enabled' ]) ? $this -> menu [ $key ][ 'enabled' ] : 0 ;
$menu -> position = $this -> menu [ $key ][ 'position' ];
2023-03-29 14:30:32 +02:00
$menu -> entity = $entity ;
2020-09-08 21:27:28 +02:00
if ( ! $err ) {
$result = $menu -> create ( $user ); // Save menu entry into table llx_menu
if ( $result > 0 ) {
$this -> menu [ $key ][ 'rowid' ] = $result ;
} else {
$this -> error = $menu -> error ;
dol_syslog ( get_class ( $this ) . '::insert_menus result=' . $result . " " . $this -> error , LOG_ERR );
$err ++ ;
break ;
}
}
}
if ( ! $err ) {
$this -> db -> commit ();
} else {
dol_syslog ( get_class ( $this ) . " ::insert_menus " . $this -> error , LOG_ERR );
$this -> db -> rollback ();
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Removes menu entries
*
* @ return int Error count ( 0 if OK )
*/
public function delete_menus ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
//$module=strtolower($this->name); TODO When right_class will be same than module name
2023-12-04 12:07:31 +01:00
$module = empty ( $this -> rights_class ) ? strtolower ( $this -> name ) : $this -> rights_class ;
2020-09-08 21:27:28 +02:00
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " menu " ;
$sql .= " WHERE module = ' " . $this -> db -> escape ( $module ) . " ' " ;
2023-03-29 14:30:32 +02:00
$sql .= " AND entity IN (0, " . $conf -> entity . " ) " ;
2020-09-08 21:27:28 +02:00
dol_syslog ( get_class ( $this ) . " ::delete_menus " , LOG_DEBUG );
$resql = $this -> db -> query ( $sql );
if ( ! $resql ) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Creates directories
*
* @ return int Error count ( 0 if OK )
*/
public function create_dirs ()
{
// phpcs:enable
global $langs , $conf ;
$err = 0 ;
2023-11-20 23:45:35 +01:00
$name = '' ;
2020-09-08 21:27:28 +02:00
if ( isset ( $this -> dirs ) && is_array ( $this -> dirs )) {
2021-02-23 22:03:23 +01:00
foreach ( $this -> dirs as $key => $value ) {
2020-09-08 21:27:28 +02:00
$addtodatabase = 0 ;
2021-02-23 22:03:23 +01:00
if ( ! is_array ( $value )) {
$dir = $value ; // Default simple mode
2020-09-08 21:27:28 +02:00
} else {
$constname = $this -> const_name . " _DIR_ " ;
$dir = $this -> dirs [ $key ][ 1 ];
$addtodatabase = empty ( $this -> dirs [ $key ][ 2 ]) ? '' : $this -> dirs [ $key ][ 2 ]; // Create constante in llx_const
$subname = empty ( $this -> dirs [ $key ][ 3 ]) ? '' : strtoupper ( $this -> dirs [ $key ][ 3 ]); // Add submodule name (ex: $conf->module->submodule->dir_output)
$forcename = empty ( $this -> dirs [ $key ][ 4 ]) ? '' : strtoupper ( $this -> dirs [ $key ][ 4 ]); // Change the module name if different
2021-02-23 22:03:23 +01:00
if ( ! empty ( $forcename )) {
$constname = 'MAIN_MODULE_' . $forcename . " _DIR_ " ;
2020-09-08 21:27:28 +02:00
}
2021-02-23 22:03:23 +01:00
if ( ! empty ( $subname )) {
$constname = $constname . $subname . " _ " ;
2020-09-08 21:27:28 +02:00
}
$name = $constname . strtoupper ( $this -> dirs [ $key ][ 0 ]);
}
// Define directory full path ($dir must start with "/")
2023-11-27 11:39:32 +01:00
if ( ! getDolGlobalString ( 'MAIN_MODULE_MULTICOMPANY' ) || $conf -> entity == 1 ) {
2021-02-23 22:03:23 +01:00
$fulldir = DOL_DATA_ROOT . $dir ;
} else {
$fulldir = DOL_DATA_ROOT . " / " . $conf -> entity . $dir ;
2020-09-08 21:27:28 +02:00
}
// Create dir if it does not exists
if ( ! empty ( $fulldir ) && ! file_exists ( $fulldir )) {
if ( dol_mkdir ( $fulldir , DOL_DATA_ROOT ) < 0 ) {
2023-12-04 12:07:31 +01:00
$this -> error = $langs -> trans ( " ErrorCanNotCreateDir " , $fulldir );
dol_syslog ( get_class ( $this ) . " ::_init " . $this -> error , LOG_ERR );
$err ++ ;
2020-09-08 21:27:28 +02:00
}
}
// Define the constant in database if requested (not the default mode)
2023-08-06 00:24:03 +02:00
if ( ! empty ( $addtodatabase ) && ! empty ( $name )) {
2020-09-08 21:27:28 +02:00
$result = $this -> insert_dirs ( $name , $dir );
2021-02-23 22:03:23 +01:00
if ( $result ) {
$err ++ ;
2020-09-08 21:27:28 +02:00
}
}
}
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Adds directories definitions
*
* @ param string $name Name
* @ param string $dir Directory
*
* @ return int Error count ( 0 if OK )
*/
public function insert_dirs ( $name , $dir )
{
// phpcs:enable
global $conf ;
$err = 0 ;
$sql = " SELECT count(*) " ;
$sql .= " FROM " . MAIN_DB_PREFIX . " const " ;
2020-09-19 22:41:05 +02:00
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " = ' " . $this -> db -> escape ( $name ) . " ' " ;
2020-09-08 21:27:28 +02:00
$sql .= " AND entity = " . $conf -> entity ;
dol_syslog ( get_class ( $this ) . " ::insert_dirs " , LOG_DEBUG );
$result = $this -> db -> query ( $sql );
if ( $result ) {
$row = $this -> db -> fetch_row ( $result );
if ( $row [ 0 ] == 0 ) {
2021-09-02 13:25:00 +02:00
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " const (name, type, value, note, visible, entity) " ;
$sql .= " VALUES ( " . $this -> db -> encrypt ( $name ) . " , 'chaine', " . $this -> db -> encrypt ( $dir ) . " , ' " . $this -> db -> escape ( " Directory for module " . $this -> name ) . " ', '0', " . (( int ) $conf -> entity ) . " ) " ;
2020-09-08 21:27:28 +02:00
dol_syslog ( get_class ( $this ) . " ::insert_dirs " , LOG_DEBUG );
$this -> db -> query ( $sql );
}
} else {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Removes directories
*
* @ return int Error count ( 0 if OK )
*/
public function delete_dirs ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " const " ;
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " LIKE ' " . $this -> db -> escape ( $this -> const_name ) . " _DIR_%' " ;
$sql .= " AND entity = " . $conf -> entity ;
dol_syslog ( get_class ( $this ) . " ::delete_dirs " , LOG_DEBUG );
if ( ! $this -> db -> query ( $sql )) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
return $err ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
2024-02-22 17:30:54 +01:00
* Save configuration for generic features .
* This also generate website templates if the module provide some .
2020-09-08 21:27:28 +02:00
*
* @ return int Error count ( 0 if OK )
*/
public function insert_module_parts ()
{
// phpcs:enable
2024-02-12 16:43:46 +01:00
global $conf , $langs ;
2020-09-08 21:27:28 +02:00
$error = 0 ;
2023-10-13 15:00:51 +02:00
if ( is_array ( $this -> module_parts )) {
if ( empty ( $this -> module_parts [ 'icon' ]) && ! empty ( $this -> picto ) && preg_match ( '/^fa\-/' , $this -> picto )) {
$this -> module_parts [ 'icon' ] = $this -> picto ;
}
2021-02-23 22:03:23 +01:00
foreach ( $this -> module_parts as $key => $value ) {
if ( is_array ( $value ) && count ( $value ) == 0 ) {
continue ; // Discard empty arrays
2020-09-08 21:27:28 +02:00
}
2024-02-12 02:52:35 +01:00
// If module brings website templates, we must generate the zip like we do whenenabling the website module
if ( $key == 'websitetemplates' && $value == 1 ) {
$srcroot = dol_buildpath ( '/' . strtolower ( $this -> name ) . '/doctemplates/websites' );
// Copy templates in dir format (recommended) into zip file
$docs = dol_dir_list ( $srcroot , 'directories' , 0 , 'website_.*$' );
foreach ( $docs as $cursorfile ) {
$src = $srcroot . '/' . $cursorfile [ 'name' ];
$dest = DOL_DATA_ROOT . '/doctemplates/websites/' . $cursorfile [ 'name' ];
2024-02-22 17:30:54 +01:00
dol_delete_file ( $dest . '.zip' );
2024-02-12 02:52:35 +01:00
// Compress it
global $errormsg ;
$errormsg = '' ;
$result = dol_compress_dir ( $src , $dest . '.zip' , 'zip' );
if ( $result < 0 ) {
$error ++ ;
$this -> error = ( $errormsg ? $errormsg : $langs -> trans ( 'ErrorFailToCreateZip' , $dest ));
$this -> errors [] = ( $errormsg ? $errormsg : $langs -> trans ( 'ErrorFailToCreateZip' , $dest ));
}
}
2024-03-14 12:39:42 +01:00
// Copy also the preview website_xxx.jpg file
$docs = dol_dir_list ( $srcroot , 'files' , 0 , 'website_.*\.jpg$' );
foreach ( $docs as $cursorfile ) {
$src = $srcroot . '/' . $cursorfile [ 'name' ];
$dest = DOL_DATA_ROOT . '/doctemplates/websites/' . $cursorfile [ 'name' ];
dol_copy ( $src , $dest );
}
2024-02-12 02:52:35 +01:00
}
2020-09-08 21:27:28 +02:00
$entity = $conf -> entity ; // Reset the current entity
$newvalue = $value ;
2021-09-03 11:00:14 +02:00
2020-09-08 21:27:28 +02:00
// Serialize array parameters
if ( is_array ( $value )) {
// Can defined other parameters
// Example when $key='hooks', then $value is an array('data'=>array('hookcontext1','hookcontext2'), 'entity'=>X)
if ( isset ( $value [ 'data' ]) && is_array ( $value [ 'data' ])) {
$newvalue = json_encode ( $value [ 'data' ]);
2021-02-23 22:03:23 +01:00
if ( isset ( $value [ 'entity' ])) {
$entity = $value [ 'entity' ];
2020-09-08 21:27:28 +02:00
}
} elseif ( isset ( $value [ 'data' ]) && ! is_array ( $value [ 'data' ])) {
$newvalue = $value [ 'data' ];
2021-02-23 22:03:23 +01:00
if ( isset ( $value [ 'entity' ])) {
$entity = $value [ 'entity' ];
2020-09-08 21:27:28 +02:00
}
2021-09-02 13:25:00 +02:00
} else { // when hook is declared with syntax 'hook'=>array('hookcontext1','hookcontext2',...)
2020-09-08 21:27:28 +02:00
$newvalue = json_encode ( $value );
}
}
2023-10-13 15:00:51 +02:00
if ( ! empty ( $newvalue )) {
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " const ( " ;
$sql .= " name " ;
$sql .= " , type " ;
$sql .= " , value " ;
$sql .= " , note " ;
$sql .= " , visible " ;
$sql .= " , entity " ;
$sql .= " ) " ;
$sql .= " VALUES ( " ;
$sql .= " " . $this -> db -> encrypt ( $this -> const_name . " _ " . strtoupper ( $key ), 1 );
$sql .= " , 'chaine' " ;
$sql .= " , " . $this -> db -> encrypt ( $newvalue , 1 );
$sql .= " , null " ;
$sql .= " , '0' " ;
$sql .= " , " . (( int ) $entity );
$sql .= " ) " ;
dol_syslog ( get_class ( $this ) . " ::insert_module_parts for key= " . $this -> const_name . " _ " . strtoupper ( $key ), LOG_DEBUG );
$resql = $this -> db -> query ( $sql , 1 );
if ( ! $resql ) {
if ( $this -> db -> lasterrno () != 'DB_ERROR_RECORD_ALREADY_EXISTS' ) {
2023-12-04 12:07:31 +01:00
$error ++ ;
$this -> error = $this -> db -> lasterror ();
2023-10-13 15:00:51 +02:00
} else {
2023-12-04 12:07:31 +01:00
dol_syslog ( get_class ( $this ) . " ::insert_module_parts for " . $this -> const_name . " _ " . strtoupper ( $key ) . " Record already exists. " , LOG_WARNING );
2023-10-13 15:00:51 +02:00
}
2020-09-08 21:27:28 +02:00
}
}
}
}
return $error ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Removes generic parts
*
* @ return int Error count ( 0 if OK )
*/
public function delete_module_parts ()
{
// phpcs:enable
global $conf ;
$err = 0 ;
2023-10-13 15:00:51 +02:00
if ( is_array ( $this -> module_parts )) {
2022-05-03 23:54:40 +02:00
dol_syslog ( get_class ( $this ) . " ::delete_module_parts " , LOG_DEBUG );
2023-10-13 15:00:51 +02:00
if ( empty ( $this -> module_parts [ 'icon' ]) && ! empty ( $this -> picto ) && preg_match ( '/^fa\-/' , $this -> picto )) {
$this -> module_parts [ 'icon' ] = $this -> picto ;
}
2021-02-23 22:03:23 +01:00
foreach ( $this -> module_parts as $key => $value ) {
2020-09-08 21:27:28 +02:00
// If entity is defined
2021-02-23 22:03:23 +01:00
if ( is_array ( $value ) && isset ( $value [ 'entity' ])) {
$entity = $value [ 'entity' ];
2023-07-23 19:48:59 +02:00
} else {
$entity = $conf -> entity ;
2020-09-08 21:27:28 +02:00
}
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " const " ;
$sql .= " WHERE " . $this -> db -> decrypt ( 'name' ) . " LIKE ' " . $this -> db -> escape ( $this -> const_name ) . " _ " . strtoupper ( $key ) . " ' " ;
2021-06-09 15:36:47 +02:00
$sql .= " AND entity = " . (( int ) $entity );
2020-09-08 21:27:28 +02:00
if ( ! $this -> db -> query ( $sql )) {
$this -> error = $this -> db -> lasterror ();
$err ++ ;
}
}
}
return $err ;
}
/**
* Function called when module is enabled .
* The init function adds tabs , constants , boxes , permissions and menus ( defined in constructor ) into Dolibarr database .
* It also creates data directories
*
2021-02-15 20:13:38 +01:00
* @ param string $options Options when enabling module ( '' , 'newboxdefonly' , 'noboxes' , 'menuonly' )
* 'noboxes' = Do not insert boxes 'newboxdefonly' = For boxes , insert def of boxes only and not boxes activation
2020-09-08 21:27:28 +02:00
* @ return int 1 if OK , 0 if KO
*/
public function init ( $options = '' )
{
return $this -> _init ( array (), $options );
}
/**
* Function called when module is disabled .
* The remove function removes tabs , constants , boxes , permissions and menus from Dolibarr database .
* Data directories are not deleted
*
* @ param string $options Options when enabling module ( '' , 'noboxes' )
* @ return int 1 if OK , 0 if KO
*/
public function remove ( $options = '' )
{
return $this -> _remove ( array (), $options );
}
/**
* Return Kanban view of a module
*
* @ param string $codeenabledisable HTML code for button to enable / disable module
* @ param string $codetoconfig HTML code to go to config page
* @ return string HTML code of Kanban view
*/
2021-04-18 22:13:37 +02:00
public function getKanbanView ( $codeenabledisable = '' , $codetoconfig = '' )
2020-09-08 21:27:28 +02:00
{
global $conf , $langs ;
// Define imginfo
$imginfo = " info " ;
2021-02-23 22:03:23 +01:00
if ( $this -> isCoreOrExternalModule () == 'external' ) {
2020-09-08 21:27:28 +02:00
$imginfo = " info_black " ;
}
$const_name = 'MAIN_MODULE_' . strtoupper ( preg_replace ( '/^mod/i' , '' , get_class ( $this )));
$version = $this -> getVersion ( 0 );
$versiontrans = '' ;
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/development/i' , $version )) {
$versiontrans .= 'warning' ;
}
if ( preg_match ( '/experimental/i' , $version )) {
$versiontrans .= 'warning' ;
}
if ( preg_match ( '/deprecated/i' , $version )) {
$versiontrans .= 'warning' ;
}
2020-08-03 15:17:37 +02:00
2023-08-04 04:37:10 +02:00
$return = '
2021-04-18 20:12:24 +02:00
< div class = " box-flex-item info-box-module'
2023-10-16 21:15:03 +02:00
. ( getDolGlobalString ( $const_name ) ? '' : ' --disabled' )
2021-04-18 20:12:24 +02:00
. ( $this -> isCoreOrExternalModule () == 'external' ? ' --external' : '' )
. ( $this -> needUpdate ? ' --need-update' : '' )
. ' " >
2020-04-06 15:12:42 +02:00
< div class = " info-box info-box-sm info-box-module " >
2023-10-16 21:15:03 +02:00
< div class = " info-box-icon'.(!getDolGlobalString( $const_name ) ? '' : ' info-box-icon-module-enabled'.( $versiontrans ? ' info-box-icon-module-warning' : '')).' " > ' ;
2020-03-27 01:59:17 +01:00
$alttext = '' ;
//if (is_array($objMod->need_dolibarr_version)) $alttext.=($alttext?' - ':'').'Dolibarr >= '.join('.',$objMod->need_dolibarr_version);
//if (is_array($objMod->phpmin)) $alttext.=($alttext?' - ':'').'PHP >= '.join('.',$objMod->phpmin);
2021-02-23 22:03:23 +01:00
if ( ! empty ( $this -> picto )) {
if ( preg_match ( '/^\//i' , $this -> picto )) {
2023-08-04 04:37:10 +02:00
$return .= img_picto ( $alttext , $this -> picto , 'class="inline-block valignmiddle"' , 1 );
2021-02-23 22:03:23 +01:00
} else {
2023-08-04 04:37:10 +02:00
$return .= img_object ( $alttext , $this -> picto , 'class="inline-block valignmiddle"' );
2021-02-23 22:03:23 +01:00
}
2020-05-21 15:05:19 +02:00
} else {
2023-08-04 04:37:10 +02:00
$return .= img_object ( $alttext , 'generic' , 'class="inline-block valignmiddle"' );
2020-03-27 01:59:17 +01:00
}
2020-05-14 15:42:37 +02:00
if ( $this -> isCoreOrExternalModule () == 'external' || preg_match ( '/development|experimental|deprecated/i' , $version )) {
2021-04-18 20:12:24 +02:00
$versionTitle = $langs -> trans ( " Version " ) . ' ' . $this -> getVersion ( 1 );
2021-04-18 22:38:18 +02:00
if ( $this -> needUpdate ) {
2024-03-10 01:53:04 +01:00
$versionTitle .= '<br>' . $langs -> trans ( 'ModuleUpdateAvailable' ) . ' : ' . $this -> lastVersion ;
2021-04-18 20:12:24 +02:00
}
2023-08-04 04:37:10 +02:00
$return .= '<span class="info-box-icon-version' . ( $versiontrans ? ' ' . $versiontrans : '' ) . ' classfortooltip" title="' . dol_escape_js ( $versionTitle ) . '" >' ;
$return .= $this -> getVersion ( 1 );
$return .= '</span>' ;
2020-05-14 15:27:10 +02:00
}
2020-04-08 17:04:23 +02:00
2023-08-04 04:37:10 +02:00
$return .= ' </ div >
2023-10-16 21:15:03 +02:00
< div class = " info-box-content info-box-text-module'.(!getDolGlobalString( $const_name ) ? '' : ' info-box-module-enabled'.( $versiontrans ? ' info-box-content-warning' : '')).' " >
2020-05-27 22:35:55 +02:00
< span class = " info-box-title " > '.$this->getName().' </ span >
2020-05-10 21:07:49 +02:00
< span class = " info-box-desc twolinesmax opacitymedium " title = " '.dol_escape_htmltag( $this->getDesc ()).' " > '.nl2br($this->getDesc()).' </ span > ' ;
2020-03-27 01:59:17 +01:00
2023-08-04 04:37:10 +02:00
$return .= '<div class="valignmiddle inline-block info-box-more">' ;
2020-08-03 16:31:52 +02:00
//if ($versiontrans) print img_warning($langs->trans("Version").' '.$this->getVersion(1)).' ';
2023-10-20 21:01:59 +02:00
$return .= '<a class="valignmiddle inline-block" href="javascript:document_preview(\'' . DOL_URL_ROOT . '/admin/modulehelp.php?id=' . (( int ) $this -> numero ) . '\',\'text/html\',\'' . dol_escape_js ( $langs -> trans ( " Module " )) . '\')">' . img_picto (( $this -> isCoreOrExternalModule () == 'external' ? $langs -> trans ( " ExternalModule " ) . ' - ' : '' ) . $langs -> trans ( " ClickToShowDescription " ), $imginfo ) . '</a>' ;
2023-08-04 04:37:10 +02:00
$return .= '</div><br>' ;
$return .= '<div class="valignmiddle inline-block info-box-actions">' ;
$return .= '<div class="valignmiddle inline-block info-box-setup">' ;
$return .= $codetoconfig ;
$return .= '</div>' ;
$return .= '<div class="valignmiddle inline-block marginleftonly marginrightonly">' ;
$return .= $codeenabledisable ;
$return .= '</div>' ;
$return .= '</div>' ;
$return .= '
2020-03-27 01:59:17 +01:00
</ div ><!-- /. info - box - content -->
</ div ><!-- /. info - box -->
</ div > ' ;
2023-08-04 04:37:10 +02:00
return $return ;
2020-09-08 21:27:28 +02:00
}
2021-04-18 20:12:24 +02:00
/**
2021-04-20 11:56:26 +02:00
* Check for module update
2021-04-18 22:13:37 +02:00
* TODO : store results for $this -> url_last_version and $this -> needUpdate
2021-04-20 11:56:26 +02:00
* Add a cron task to monitor for updates
2021-04-18 22:13:37 +02:00
*
2023-12-06 15:46:39 +01:00
* @ return int Return integer < 0 if Error , 0 == no update needed , > 0 if need update
2021-04-18 20:12:24 +02:00
*/
2021-04-18 22:40:34 +02:00
public function checkForUpdate ()
{
2021-04-18 20:12:24 +02:00
require_once DOL_DOCUMENT_ROOT . '/core/lib/geturl.lib.php' ;
if ( ! empty ( $this -> url_last_version )) {
$lastVersion = getURLContent ( $this -> url_last_version , 'GET' , '' , 1 , array (), array ( 'http' , 'https' ), 0 ); // Accept http or https links on external remote server only
2021-04-18 22:13:37 +02:00
if ( isset ( $lastVersion [ 'content' ]) && strlen ( $lastVersion [ 'content' ]) < 30 ) {
// Security warning : be careful with remote data content, the module editor could be hacked (or evil) so limit to a-z A-Z 0-9 _ . -
$this -> lastVersion = preg_replace ( " /[^a-zA-Z0-9_ \ . \ -]+/ " , " " , $lastVersion [ 'content' ]);
if ( version_compare ( $this -> lastVersion , $this -> version ) > 0 ) {
2021-04-18 20:12:24 +02:00
$this -> needUpdate = true ;
return 1 ;
2021-04-18 22:38:18 +02:00
} else {
2021-04-18 20:12:24 +02:00
$this -> needUpdate = false ;
return 0 ;
}
2021-04-18 22:38:18 +02:00
} else {
2021-04-18 20:12:24 +02:00
return - 1 ;
}
}
return 0 ;
}
2003-11-15 18:41:07 +01:00
}