2008-06-20 23:10:24 +02:00
< ? php
2015-08-31 17:42:08 +02:00
/* Copyright ( C ) 2008 - 2011 Laurent Destailleur < eldy @ users . sourceforge . net >
2018-10-27 14:43:12 +02:00
* Copyright ( C ) 2008 - 2012 Regis Houssin < regis . houssin @ inodbox . com >
2015-08-31 17:42:08 +02:00
* Copyright ( C ) 2008 Raphael Bertrand ( Resultic ) < raphael . bertrand @ resultic . fr >
2016-07-23 16:37:21 +02:00
* Copyright ( C ) 2014 - 2016 Marcos García < marcosgdf @ gmail . com >
2015-05-04 09:22:55 +02:00
* Copyright ( C ) 2015 Ferran Marcet < fmarcet @ 2 byte . es >
2016-02-11 20:01:51 +01:00
* Copyright ( C ) 2015 - 2016 Raphaël Doursenaud < rdoursenaud @ gpcsolutions . fr >
2017-04-15 20:04:45 +02:00
* Copyright ( C ) 2017 Juanjo Menent < jmenent @ 2 byte . es >
2009-01-15 01:32:10 +01:00
*
2008-06-20 23:10:24 +02: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
2008-06-20 23:10:24 +02: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 />.
* or see https :// www . gnu . org /
2008-06-20 23:10:24 +02:00
*/
/**
2011-10-24 10:45:06 +02:00
* \file htdocs / core / lib / functions2 . lib . php
2008-11-16 02:09:04 +01:00
* \brief A set of functions for Dolibarr
* This file contains all rare functions .
2008-06-20 23:10:24 +02:00
*/
2013-06-16 23:15:20 +02:00
// Enable this line to trace path when function is called.
//print xdebug_print_function_stack('Functions2.lib was called');exit;
2012-06-24 19:32:19 +02:00
/**
* Same function than javascript unescape () function but in PHP .
*
2012-07-25 11:37:43 +02:00
* @ param string $source String to decode
* @ return string Unescaped string
2012-06-24 19:32:19 +02:00
*/
function jsUnEscape ( $source )
{
2020-09-07 10:18:17 +02:00
$decodedStr = " " ;
$pos = 0 ;
$len = strlen ( $source );
while ( $pos < $len ) {
$charAt = substr ( $source , $pos , 1 );
if ( $charAt == '%' ) {
$pos ++ ;
$charAt = substr ( $source , $pos , 1 );
if ( $charAt == 'u' ) {
// we got a unicode character
$pos ++ ;
$unicodeHexVal = substr ( $source , $pos , 4 );
$unicode = hexdec ( $unicodeHexVal );
$entity = " &# " . $unicode . ';' ;
$decodedStr .= utf8_encode ( $entity );
$pos += 4 ;
} else {
// we have an escaped ascii character
$hexVal = substr ( $source , $pos , 2 );
$decodedStr .= chr ( hexdec ( $hexVal ));
$pos += 2 ;
}
} else {
$decodedStr .= $charAt ;
$pos ++ ;
}
}
2020-10-31 14:32:18 +01:00
return dol_html_entity_decode ( $decodedStr , ENT_COMPAT | ENT_HTML5 );
2012-06-24 19:32:19 +02:00
}
2008-06-20 23:10:24 +02:00
2012-05-08 22:49:03 +02:00
/**
2016-05-02 09:49:58 +02:00
* Return list of modules directories . We detect directories that contains a subdirectory / core / modules
* We discard directory modules that contains 'disabled' into their name .
2012-05-08 22:49:03 +02:00
*
2012-05-09 16:40:54 +02:00
* @ param string $subdir Sub directory ( Example : '/mailings' )
* @ return array Array of directories that can contains module descriptors
2012-05-08 22:49:03 +02:00
*/
2019-01-27 15:20:16 +01:00
function dolGetModulesDirs ( $subdir = '' )
2012-05-08 22:49:03 +02:00
{
2020-09-07 10:18:17 +02:00
global $conf ;
$modulesdir = array ();
2021-02-23 22:03:23 +01:00
foreach ( $conf -> file -> dol_document_root as $type => $dirroot ) {
2020-09-07 10:18:17 +02:00
// Default core/modules dir
if ( $type === 'main' ) {
$modulesdir [ $dirroot . '/core/modules' . $subdir . '/' ] = $dirroot . '/core/modules' . $subdir . '/' ;
}
// Scan dir from external modules
$handle = @ opendir ( $dirroot );
2021-02-23 22:03:23 +01:00
if ( is_resource ( $handle )) {
while (( $file = readdir ( $handle )) !== false ) {
if ( preg_match ( '/disabled/' , $file )) {
continue ; // We discard module if it contains disabled into name.
}
if ( is_dir ( $dirroot . '/' . $file ) && substr ( $file , 0 , 1 ) <> '.' && substr ( $file , 0 , 3 ) <> 'CVS' && $file != 'includes' ) {
if ( is_dir ( $dirroot . '/' . $file . '/core/modules' . $subdir . '/' )) {
2020-09-07 10:18:17 +02:00
$modulesdir [ $dirroot . '/' . $file . '/core/modules' . $subdir . '/' ] = $dirroot . '/' . $file . '/core/modules' . $subdir . '/' ;
}
}
}
closedir ( $handle );
}
}
return $modulesdir ;
2012-05-08 22:49:03 +02:00
}
2011-08-11 03:34:54 +02:00
/**
2011-08-31 14:24:47 +02:00
* Try to guess default paper format according to language into $langs
*
2023-05-02 04:11:05 +02:00
* @ param Translate | null $outputlangs Output lang to use to autodetect output format if setup not done
* @ return string Default paper format code
2011-08-11 03:34:54 +02:00
*/
2016-08-11 15:23:00 +02:00
function dol_getDefaultFormat ( Translate $outputlangs = null )
2011-08-11 03:34:54 +02:00
{
2020-09-07 10:18:17 +02:00
global $langs ;
2013-04-29 09:25:42 +02:00
2020-09-07 10:18:17 +02:00
$selected = 'EUA4' ;
if ( ! $outputlangs ) {
$outputlangs = $langs ;
}
2013-04-29 09:25:42 +02:00
2021-02-23 22:03:23 +01:00
if ( $outputlangs -> defaultlang == 'ca_CA' ) {
$selected = 'CAP4' ; // Canada
}
if ( $outputlangs -> defaultlang == 'en_US' ) {
$selected = 'USLetter' ; // US
}
2020-09-07 10:18:17 +02:00
return $selected ;
2011-08-11 03:34:54 +02:00
}
2009-02-20 21:28:16 +01:00
/**
2010-09-29 10:09:17 +02:00
* Output content of a file $filename in version of current language ( otherwise may use an alternate language )
2011-08-31 14:24:47 +02:00
*
2012-02-04 15:20:32 +01:00
* @ param Translate $langs Object language to use for output
* @ param string $filename Relative filename to output
* @ param int $searchalt 1 = Search also in alternative languages
* @ return boolean true if OK , false if KO
2009-02-20 21:28:16 +01:00
*/
2019-01-27 15:20:16 +01:00
function dol_print_file ( $langs , $filename , $searchalt = 0 )
2009-02-20 21:28:16 +01:00
{
2020-09-07 10:18:17 +02:00
global $conf ;
// Test if file is in lang directory
2021-02-23 22:03:23 +01:00
foreach ( $langs -> dir as $searchdir ) {
2020-09-07 10:18:17 +02:00
$formfile = ( $searchdir . " /langs/ " . $langs -> defaultlang . " / " . $filename );
dol_syslog ( 'functions2::dol_print_file search file ' . $formfile , LOG_DEBUG );
2021-02-23 22:03:23 +01:00
if ( is_readable ( $formfile )) {
2020-09-07 10:18:17 +02:00
$content = file_get_contents ( $formfile );
$isutf8 = utf8_check ( $content );
2021-02-23 22:03:23 +01:00
if ( ! $isutf8 && $conf -> file -> character_set_client == 'UTF-8' ) {
print utf8_encode ( $content );
} elseif ( $isutf8 && $conf -> file -> character_set_client == 'ISO-8859-1' ) {
print utf8_decode ( $content );
} else {
print $content ;
}
2020-09-07 10:18:17 +02:00
return true ;
2021-02-23 22:03:23 +01:00
} else {
dol_syslog ( 'functions2::dol_print_file not found' , LOG_DEBUG );
}
2020-09-07 10:18:17 +02:00
if ( $searchalt ) {
// Test si fichier dans repertoire de la langue alternative
2021-02-23 22:03:23 +01:00
if ( $langs -> defaultlang != " en_US " ) {
$formfilealt = $searchdir . " /langs/en_US/ " . $filename ;
} else {
$formfilealt = $searchdir . " /langs/fr_FR/ " . $filename ;
}
2020-09-07 10:18:17 +02:00
dol_syslog ( 'functions2::dol_print_file search alt file ' . $formfilealt , LOG_DEBUG );
//print 'getcwd='.getcwd().' htmlfilealt='.$formfilealt.' X '.file_exists(getcwd().'/'.$formfilealt);
2021-02-23 22:03:23 +01:00
if ( is_readable ( $formfilealt )) {
2020-09-07 10:18:17 +02:00
$content = file_get_contents ( $formfilealt );
$isutf8 = utf8_check ( $content );
2021-02-23 22:03:23 +01:00
if ( ! $isutf8 && $conf -> file -> character_set_client == 'UTF-8' ) {
2023-02-22 18:21:00 +01:00
print mb_convert_encoding ( $content , 'UTF-8' , 'ISO-8859-1' );
2021-02-23 22:03:23 +01:00
} elseif ( $isutf8 && $conf -> file -> character_set_client == 'ISO-8859-1' ) {
2023-02-22 18:21:00 +01:00
print mb_convert_encoding ( $content , 'ISO-8859-1' , 'UTF-8' );
2021-02-23 22:03:23 +01:00
} else {
print $content ;
}
2020-09-07 10:18:17 +02:00
return true ;
2021-02-23 22:03:23 +01:00
} else {
dol_syslog ( 'functions2::dol_print_file not found' , LOG_DEBUG );
}
2020-09-07 10:18:17 +02:00
}
}
return false ;
2009-02-20 21:28:16 +01:00
}
2009-02-19 20:06:12 +01:00
/**
2011-08-31 14:24:47 +02:00
* Show informations on an object
2012-05-12 16:27:20 +02:00
* TODO Move this into html . formother
2011-08-31 14:24:47 +02:00
*
2013-11-07 21:23:29 +01:00
* @ param object $object Objet to show
2016-04-08 14:28:49 +02:00
* @ param int $usetable Output into a table
2012-02-04 14:39:47 +01:00
* @ return void
2009-02-19 20:06:12 +01:00
*/
2019-01-27 15:20:16 +01:00
function dol_print_object_info ( $object , $usetable = 0 )
2009-02-19 20:06:12 +01:00
{
2020-09-07 10:18:17 +02:00
global $langs , $db ;
// Load translation files required by the page
$langs -> loadLangs ( array ( 'other' , 'admin' ));
include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php' ;
$deltadateforserver = getServerTimeZoneInt ( 'now' );
$deltadateforclient = (( int ) $_SESSION [ 'dol_tz' ] + ( int ) $_SESSION [ 'dol_dst' ]);
//$deltadateforcompany=((int) $_SESSION['dol_tz'] + (int) $_SESSION['dol_dst']);
$deltadateforuser = round ( $deltadateforclient - $deltadateforserver );
//print "x".$deltadateforserver." - ".$deltadateforclient." - ".$deltadateforuser;
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '<table class="border tableforfield centpercent">' ;
}
2020-09-07 10:18:17 +02:00
// Import key
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> import_key )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " ImportedWithSet " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2020-09-07 10:18:17 +02:00
print $object -> import_key ;
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
// User creation (old method using already loaded object and not id is kept for backward compatibility)
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> user_creation ) || ! empty ( $object -> user_creation_id )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " CreatedBy " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
if ( is_object ( $object -> user_creation )) {
if ( $object -> user_creation -> id ) {
print $object -> user_creation -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
2020-09-07 10:18:17 +02:00
} else {
$userstatic = new User ( $db );
$userstatic -> fetch ( $object -> user_creation_id ? $object -> user_creation_id : $object -> user_creation );
2021-02-23 22:03:23 +01:00
if ( $userstatic -> id ) {
print $userstatic -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
2020-09-07 10:18:17 +02:00
}
}
// Date creation
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> date_creation )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " DateCreation " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2021-01-03 18:42:45 +01:00
print dol_print_date ( $object -> date_creation , 'dayhour' , 'tzserver' );
2021-02-23 22:03:23 +01:00
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( " CurrentHour " ) . '</span> / ' . dol_print_date ( $object -> date_creation , " dayhour " , " tzuserrel " ) . ' <span class="opacitymedium">' . $langs -> trans ( " ClientHour " ) . '</span>' ;
2021-02-23 22:03:23 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
// User change (old method using already loaded object and not id is kept for backward compatibility)
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> user_modification ) || ! empty ( $object -> user_modification_id )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " ModifiedBy " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
if ( is_object ( $object -> user_modification )) {
if ( $object -> user_modification -> id ) {
print $object -> user_modification -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
2020-09-07 10:18:17 +02:00
} else {
$userstatic = new User ( $db );
$userstatic -> fetch ( $object -> user_modification_id ? $object -> user_modification_id : $object -> user_modification );
2021-02-23 22:03:23 +01:00
if ( $userstatic -> id ) {
print $userstatic -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
2020-09-07 10:18:17 +02:00
}
}
// Date change
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> date_modification )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " DateLastModification " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2021-01-03 18:42:45 +01:00
print dol_print_date ( $object -> date_modification , 'dayhour' , 'tzserver' );
2021-02-23 22:03:23 +01:00
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( " CurrentHour " ) . '</span> / ' . dol_print_date ( $object -> date_modification , " dayhour " , " tzuserrel " ) . ' <span class="opacitymedium">' . $langs -> trans ( " ClientHour " ) . '</span>' ;
2021-02-23 22:03:23 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
// User validation (old method using already loaded object and not id is kept for backward compatibility)
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> user_validation ) || ! empty ( $object -> user_validation_id )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " ValidatedBy " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
if ( is_object ( $object -> user_validation )) {
if ( $object -> user_validation -> id ) {
print $object -> user_validation -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
2020-09-07 10:18:17 +02:00
} else {
$userstatic = new User ( $db );
$userstatic -> fetch ( $object -> user_validation_id ? $object -> user_validation_id : $object -> user_validation );
2021-02-23 22:03:23 +01:00
if ( $userstatic -> id ) {
print $userstatic -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
2020-09-07 10:18:17 +02:00
}
}
// Date validation
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> date_validation )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " DateValidation " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2021-01-03 18:42:45 +01:00
print dol_print_date ( $object -> date_validation , 'dayhour' , 'tzserver' );
2021-02-23 22:03:23 +01:00
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( " CurrentHour " ) . '</span> / ' . dol_print_date ( $object -> date_validation , " dayhour " , 'tzuserrel' ) . ' <span class="opacitymedium">' . $langs -> trans ( " ClientHour " ) . '</span>' ;
2021-02-23 22:03:23 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
// User approve (old method using already loaded object and not id is kept for backward compatibility)
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> user_approve ) || ! empty ( $object -> user_approve_id )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " ApprovedBy " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2022-08-22 15:09:38 +02:00
if ( ! empty ( $object -> user_approve ) && is_object ( $object -> user_approve )) {
2021-02-23 22:03:23 +01:00
if ( $object -> user_approve -> id ) {
print $object -> user_approve -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
2020-09-07 10:18:17 +02:00
} else {
$userstatic = new User ( $db );
$userstatic -> fetch ( $object -> user_approve_id ? $object -> user_approve_id : $object -> user_approve );
2021-02-23 22:03:23 +01:00
if ( $userstatic -> id ) {
print $userstatic -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
2020-09-07 10:18:17 +02:00
}
}
// Date approve
2022-09-22 19:10:20 +02:00
if ( ! empty ( $object -> date_approve ) || ! empty ( $object -> date_approval )) {
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " DateApprove " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2022-09-22 19:10:20 +02:00
print dol_print_date ( $object -> date_approve ? $object -> date_approve : $object -> date_approval , 'dayhour' , 'tzserver' );
2021-02-23 22:03:23 +01:00
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( " CurrentHour " ) . '</span> / ' . dol_print_date ( $object -> date_approve , " dayhour " , 'tzuserrel' ) . ' <span class="opacitymedium">' . $langs -> trans ( " ClientHour " ) . '</span>' ;
2021-02-23 22:03:23 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
// User approve
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> user_approve_id2 )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " ApprovedBy " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2020-09-07 10:18:17 +02:00
$userstatic = new User ( $db );
$userstatic -> fetch ( $object -> user_approve_id2 );
2021-02-23 22:03:23 +01:00
if ( $userstatic -> id ) {
print $userstatic -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
// Date approve
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> date_approve2 )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " DateApprove2 " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2021-01-03 18:42:45 +01:00
print dol_print_date ( $object -> date_approve2 , 'dayhour' , 'tzserver' );
2021-02-23 22:03:23 +01:00
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( " CurrentHour " ) . '</span> / ' . dol_print_date ( $object -> date_approve2 , " dayhour " , 'tzuserrel' ) . ' <span class="opacitymedium">' . $langs -> trans ( " ClientHour " ) . '</span>' ;
2021-02-23 22:03:23 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
2021-03-26 17:44:41 +01:00
// User signature
2022-07-03 12:54:58 +02:00
if ( ! empty ( $object -> user_signature ) || ! empty ( $object -> user_signature_id )) {
2021-03-26 17:44:41 +01:00
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
print $langs -> trans ( 'SignedBy' );
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
if ( is_object ( $object -> user_signature )) {
if ( $object -> user_signature -> id ) {
print $object -> user_signature -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( 'Unknown' );
}
} else {
$userstatic = new User ( $db );
2022-07-03 12:54:58 +02:00
$userstatic -> fetch ( $object -> user_signature_id ? $object -> user_signature_id : $object -> user_signature );
2021-03-26 17:44:41 +01:00
if ( $userstatic -> id ) {
print $userstatic -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( 'Unknown' );
}
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
}
// Date signature
if ( ! empty ( $object -> date_signature )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
print $langs -> trans ( 'DateSigning' );
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
print dol_print_date ( $object -> date_signature , 'dayhour' );
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( 'CurrentHour' ) . '</span> / ' . dol_print_date ( $object -> date_signature , 'dayhour' , 'tzuserrel' ) . ' <span class="opacitymedium">' . $langs -> trans ( 'ClientHour' ) . '</span>' ;
2021-03-26 17:44:41 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
}
2020-09-07 10:18:17 +02:00
// User close
2022-07-03 12:54:58 +02:00
if ( ! empty ( $object -> user_cloture ) || ! empty ( $object -> user_closing ) || ! empty ( $object -> user_closing_id )) {
2021-02-23 22:03:23 +01:00
if ( isset ( $object -> user_cloture ) && ! empty ( $object -> user_cloture )) {
$object -> user_closing = $object -> user_cloture ;
}
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " ClosedBy " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
if ( is_object ( $object -> user_closing )) {
if ( $object -> user_closing -> id ) {
print $object -> user_closing -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
2020-09-07 10:18:17 +02:00
} else {
$userstatic = new User ( $db );
2022-07-03 12:54:58 +02:00
$userstatic -> fetch ( $object -> user_closing_id ? $object -> user_closing_id : $object -> user_closing );
2021-02-23 22:03:23 +01:00
if ( $userstatic -> id ) {
print $userstatic -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
2020-09-07 10:18:17 +02:00
}
}
// Date close
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> date_cloture ) || ! empty ( $object -> date_closing )) {
if ( isset ( $object -> date_cloture ) && ! empty ( $object -> date_cloture )) {
$object -> date_closing = $object -> date_cloture ;
}
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " DateClosing " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2021-01-03 18:42:45 +01:00
print dol_print_date ( $object -> date_closing , 'dayhour' , 'tzserver' );
2021-02-23 22:03:23 +01:00
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( " CurrentHour " ) . '</span> / ' . dol_print_date ( $object -> date_closing , " dayhour " , 'tzuserrel' ) . ' <span class="opacitymedium">' . $langs -> trans ( " ClientHour " ) . '</span>' ;
2021-02-23 22:03:23 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
// User conciliate
2022-07-03 12:54:58 +02:00
if ( ! empty ( $object -> user_rappro ) || ! empty ( $object -> user_rappro_id )) {
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2022-03-25 14:43:48 +01:00
print $langs -> trans ( " ReconciledBy " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
if ( is_object ( $object -> user_rappro )) {
if ( $object -> user_rappro -> id ) {
print $object -> user_rappro -> getNomUrl ( - 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
2020-09-07 10:18:17 +02:00
} else {
$userstatic = new User ( $db );
2022-07-03 12:54:58 +02:00
$userstatic -> fetch ( $object -> user_rappro_id ? $object -> user_rappro_id : $object -> user_rappro );
2021-02-23 22:03:23 +01:00
if ( $userstatic -> id ) {
print $userstatic -> getNomUrl ( 1 , '' , 0 , 0 , 0 );
} else {
print $langs -> trans ( " Unknown " );
}
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
2020-09-07 10:18:17 +02:00
}
}
// Date conciliate
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> date_rappro )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " DateConciliating " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2021-01-03 18:42:45 +01:00
print dol_print_date ( $object -> date_rappro , 'dayhour' , 'tzserver' );
2021-02-23 22:03:23 +01:00
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( " CurrentHour " ) . '</span> / ' . dol_print_date ( $object -> date_rappro , " dayhour " , 'tzuserrel' ) . ' <span class="opacitymedium">' . $langs -> trans ( " ClientHour " ) . '</span>' ;
2021-02-23 22:03:23 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
// Date send
2021-02-23 22:03:23 +01:00
if ( ! empty ( $object -> date_envoi )) {
if ( $usetable ) {
print '<tr><td class="titlefield">' ;
}
2020-09-07 10:18:17 +02:00
print $langs -> trans ( " DateLastSend " );
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</td><td>' ;
} else {
print ': ' ;
}
2021-01-03 18:42:45 +01:00
print dol_print_date ( $object -> date_envoi , 'dayhour' , 'tzserver' );
2021-02-23 22:03:23 +01:00
if ( $deltadateforuser ) {
2022-06-28 13:14:36 +02:00
print ' <span class="opacitymedium">' . $langs -> trans ( " CurrentHour " ) . '</span> / ' . dol_print_date ( $object -> date_envoi , " dayhour " , 'tzuserrel' ) . ' <span class="opacitymedium">' . $langs -> trans ( " ClientHour " ) . '</span>' ;
2021-02-23 22:03:23 +01:00
}
if ( $usetable ) {
print '</td></tr>' ;
} else {
print '<br>' ;
}
2020-09-07 10:18:17 +02:00
}
2021-02-23 22:03:23 +01:00
if ( $usetable ) {
print '</table>' ;
}
2009-02-19 20:06:12 +01:00
}
2015-03-03 18:33:53 +01:00
/**
* Return an email formatted to include a tracking id
2015-06-08 17:13:23 +02:00
* For example myemail @ example . com becom myemail + trackingid @ example . com
2015-03-03 18:33:53 +01:00
*
2015-06-08 17:13:23 +02:00
* @ param string $email Email address ( Ex : " toto@example.com " , " John Do <johndo@example.com> " )
2015-03-03 18:33:53 +01:00
* @ param string $trackingid Tracking id ( Ex : thi123 for thirdparty with id 123 )
2016-06-23 20:19:35 +02:00
* @ return string Return email tracker string
2015-03-03 18:33:53 +01:00
*/
function dolAddEmailTrackId ( $email , $trackingid )
{
2019-11-13 19:37:08 +01:00
$tmp = explode ( '@' , $email );
return $tmp [ 0 ] . '+' . $trackingid . '@' . ( isset ( $tmp [ 1 ]) ? $tmp [ 1 ] : '' );
2015-03-03 18:33:53 +01:00
}
2009-02-19 19:57:54 +01:00
/**
2020-10-22 20:01:59 +02:00
* Return true if email has a domain name that can be resolved to MX type .
2011-08-31 14:24:47 +02:00
*
2015-06-08 17:13:23 +02:00
* @ param string $mail Email address ( Ex : " toto@example.com " , " John Do <johndo@example.com> " )
2020-10-22 20:01:59 +02:00
* @ return int - 1 if error ( function not available ), 0 = Not valid , 1 = Valid
2009-02-19 19:57:54 +01:00
*/
2009-03-25 20:12:35 +01:00
function isValidMailDomain ( $mail )
2009-02-19 19:57:54 +01:00
{
2020-09-07 10:18:17 +02:00
list ( $user , $domain ) = explode ( " @ " , $mail , 2 );
2020-10-27 18:55:55 +01:00
return ( $domain ? isValidMXRecord ( $domain ) : 0 );
2009-02-19 19:57:54 +01:00
}
2009-04-06 10:34:42 +02:00
/**
2011-08-31 14:24:47 +02:00
* Url string validation
* < http [ s ] > :// [ user [ : pass ] @ ] hostname [ port ] [ / path ] [ ? getquery ] [ anchor ]
*
2012-02-04 14:39:47 +01:00
* @ param string $url Url
2014-08-01 01:31:52 +02:00
* @ param int $http 1 : verify http is provided , 0 : not verify http
* @ param int $pass 1 : verify user and pass is provided , 0 : not verify user and pass
* @ param int $port 1 : verify port is provided , 0 : not verify port
* @ param int $path 1 : verify a path is provided " / " or " /... " or " /.../ " , 0 : not verify path
* @ param int $query 1 : verify query is provided , 0 : not verify query
* @ param int $anchor 1 : verify anchor is provided , 0 : not verify anchor
2012-02-04 14:39:47 +01:00
* @ return int 1 = Check is OK , 0 = Check is KO
2009-04-06 10:34:42 +02:00
*/
2019-01-27 15:20:16 +01:00
function isValidUrl ( $url , $http = 0 , $pass = 0 , $port = 0 , $path = 0 , $query = 0 , $anchor = 0 )
2009-04-06 10:34:42 +02:00
{
2020-09-07 10:18:17 +02:00
$ValidUrl = 0 ;
$urlregex = '' ;
// SCHEME
2021-02-23 22:03:23 +01:00
if ( $http ) {
$urlregex .= " ^(http: \ / \ /|https: \ / \ /) " ;
}
2020-09-07 10:18:17 +02:00
// USER AND PASS
2021-02-23 22:03:23 +01:00
if ( $pass ) {
$urlregex .= " ([a-z0-9+!*(),;?&= \$ _.-]+( \ :[a-z0-9+!*(),;?&= \$ _.-]+)?@) " ;
}
2020-09-07 10:18:17 +02:00
// HOSTNAME OR IP
//$urlregex .= "[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)*"; // x allowed (ex. http://localhost, http://routerlogin)
//$urlregex .= "[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)+"; // x.x
$urlregex .= " ([a-z0-9+ \$ _ \\ \ :-])+( \ .[a-z0-9+ \$ _-][a-z0-9+ \$ _-]+)* " ; // x ou x.xx (2 x ou plus)
//use only one of the above
// PORT
2021-02-23 22:03:23 +01:00
if ( $port ) {
$urlregex .= " ( \ :[0-9] { 2,5}) " ;
}
2020-09-07 10:18:17 +02:00
// PATH
2021-02-23 22:03:23 +01:00
if ( $path ) {
$urlregex .= " ( \ /([a-z0-9+ \$ _-] \ .?)+)* \ / " ;
}
2020-09-07 10:18:17 +02:00
// GET Query
2021-02-23 22:03:23 +01:00
if ( $query ) {
$urlregex .= " ( \ ?[a-z+& \$ _.-][a-z0-9;:@ \ /&%=+ \$ _.-]*) " ;
}
2020-09-07 10:18:17 +02:00
// ANCHOR
2021-02-23 22:03:23 +01:00
if ( $anchor ) {
$urlregex .= " (#[a-z_.-][a-z0-9+ \$ _.-]*) $ " ;
}
2020-09-07 10:18:17 +02:00
// check
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/' . $urlregex . '/i' , $url )) {
2020-09-07 10:18:17 +02:00
$ValidUrl = 1 ;
}
//print $urlregex.' - '.$url.' - '.$ValidUrl;
return $ValidUrl ;
2009-04-06 10:34:42 +02:00
}
2019-04-23 22:49:33 +02:00
/**
* Check if VAT numero is valid ( check done on syntax only , no database or remote access )
*
* @ param Societe $company VAT number
2019-05-22 15:37:59 +02:00
* @ return int 1 = Check is OK , 0 = Check is KO
2019-04-23 22:49:33 +02:00
*/
function isValidVATID ( $company )
{
2021-02-23 22:03:23 +01:00
if ( $company -> isInEEC ()) { // Syntax check rules for EEC countries
2020-09-07 10:18:17 +02:00
/* Disabled because some companies can have an address in Irland and a vat number in France .
2021-02-23 22:03:23 +01:00
$vatprefix = $company -> country_code ;
if ( $vatprefix == 'GR' ) $vatprefix = '(EL|GR)' ;
elseif ( $vatprefix == 'MC' ) $vatprefix = 'FR' ; // Monaco is using french VAT numbers
else $vatprefix = preg_quote ( $vatprefix , '/' ); */
2020-09-07 10:18:17 +02:00
$vatprefix = '[a-zA-Z][a-zA-Z]' ;
2021-02-23 22:03:23 +01:00
if ( ! preg_match ( '/^' . $vatprefix . '[a-zA-Z0-9\-\.]{5,14}$/i' , str_replace ( ' ' , '' , $company -> tva_intra ))) {
2020-09-07 10:18:17 +02:00
return 0 ;
}
}
return 1 ;
2019-04-23 22:49:33 +02:00
}
2009-04-06 10:34:42 +02:00
/**
2011-08-31 14:24:47 +02:00
* Clean an url string
*
2012-02-04 14:39:47 +01:00
* @ param string $url Url
2016-04-09 19:32:05 +02:00
* @ param integer $http 1 = keep both http :// and https :// , 0 : remove http :// but not https ://
2012-02-04 14:39:47 +01:00
* @ return string Cleaned url
2009-04-06 10:34:42 +02:00
*/
2019-01-27 15:20:16 +01:00
function clean_url ( $url , $http = 1 )
2009-04-06 10:34:42 +02:00
{
2020-09-07 10:18:17 +02:00
// Fixed by Matelli (see http://matelli.fr/showcases/patchs-dolibarr/fix-cleaning-url.html)
// To include the minus sign in a char class, we must not escape it but put it at the end of the class
// Also, there's no need of escape a dot sign in a class
2020-09-19 22:41:05 +02:00
$regs = array ();
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/^(https?:[\\/]+)?([0-9A-Z.-]+\.[A-Z]{2,4})(:[0-9]+)?/i' , $url , $regs )) {
2020-09-07 10:18:17 +02:00
$proto = $regs [ 1 ];
$domain = $regs [ 2 ];
$port = isset ( $regs [ 3 ]) ? $regs [ 3 ] : '' ;
//print $url." -> ".$proto." - ".$domain." - ".$port;
//$url = dol_string_nospecial(trim($url));
$url = trim ( $url );
// Si http: defini on supprime le http (Si https on ne supprime pas)
$newproto = $proto ;
2021-02-23 22:03:23 +01:00
if ( $http == 0 ) {
if ( preg_match ( '/^http:[\\/]+/i' , $url )) {
2020-09-07 10:18:17 +02:00
$url = preg_replace ( '/^http:[\\/]+/i' , '' , $url );
$newproto = '' ;
}
}
// On passe le nom de domaine en minuscule
$CleanUrl = preg_replace ( '/^' . preg_quote ( $proto . $domain , '/' ) . '/i' , $newproto . strtolower ( $domain ), $url );
return $CleanUrl ;
2021-02-23 22:03:23 +01:00
} else {
return $url ;
}
2009-04-06 10:34:42 +02:00
}
2014-10-11 23:44:50 +02:00
2014-10-11 23:46:49 +02:00
/**
* Returns an email value with obfuscated parts .
*
* @ param string $mail Email
2016-07-06 11:23:32 +02:00
* @ param string $replace Replacement character ( defaul : * )
* @ param int $nbreplace Number of replacement character ( default : 8 )
2014-10-11 23:46:49 +02:00
* @ param int $nbdisplaymail Number of character unchanged ( default : 4 )
* @ param int $nbdisplaydomain Number of character unchanged of domain ( default : 3 )
* @ param bool $displaytld Display tld ( default : true )
* @ return string Return email with hidden parts or '' ;
*/
2019-01-27 15:20:16 +01:00
function dolObfuscateEmail ( $mail , $replace = " * " , $nbreplace = 8 , $nbdisplaymail = 4 , $nbdisplaydomain = 3 , $displaytld = true )
2014-10-11 23:46:49 +02:00
{
2021-02-23 22:03:23 +01:00
if ( ! isValidEmail ( $mail )) {
return '' ;
}
2014-10-11 23:46:49 +02:00
$tab = explode ( '@' , $mail );
2019-01-27 11:55:16 +01:00
$tab2 = explode ( '.' , $tab [ 1 ]);
2014-10-11 23:46:49 +02:00
$string_replace = '' ;
$mail_name = $tab [ 0 ];
$mail_domaine = $tab2 [ 0 ];
$mail_tld = '' ;
2016-04-09 19:53:16 +02:00
$nbofelem = count ( $tab2 );
2021-02-23 22:03:23 +01:00
for ( $i = 1 ; $i < $nbofelem && $displaytld ; $i ++ ) {
2014-10-11 23:46:49 +02:00
$mail_tld .= '.' . $tab2 [ $i ];
}
2019-11-13 19:37:08 +01:00
for ( $i = 0 ; $i < $nbreplace ; $i ++ ) {
2014-10-11 23:46:49 +02:00
$string_replace .= $replace ;
}
2019-11-13 19:37:08 +01:00
if ( strlen ( $mail_name ) > $nbdisplaymail ) {
2014-10-11 23:46:49 +02:00
$mail_name = substr ( $mail_name , 0 , $nbdisplaymail );
}
2019-11-13 19:37:08 +01:00
if ( strlen ( $mail_domaine ) > $nbdisplaydomain ) {
$mail_domaine = substr ( $mail_domaine , strlen ( $mail_domaine ) - $nbdisplaydomain );
2014-10-11 23:46:49 +02:00
}
2019-11-13 19:37:08 +01:00
return $mail_name . $string_replace . $mail_domaine . $mail_tld ;
2014-10-11 23:46:49 +02:00
}
2014-10-11 23:44:50 +02:00
2008-11-16 02:09:04 +01:00
/**
2011-08-31 14:24:47 +02:00
* Return lines of an html table from an array
* Used by array2table function only
2012-02-04 14:39:47 +01:00
*
* @ param array $data Array of data
* @ param string $troptions Options for tr
* @ param string $tdoptions Options for td
* @ return string
2008-11-16 02:09:04 +01:00
*/
2019-01-27 15:20:16 +01:00
function array2tr ( $data , $troptions = '' , $tdoptions = '' )
2012-02-04 14:39:47 +01:00
{
2020-09-07 10:18:17 +02:00
$text = '<tr ' . $troptions . '>' ;
foreach ( $data as $key => $item ) {
$text .= '<td ' . $tdoptions . '>' . $item . '</td>' ;
}
$text .= '</tr>' ;
return $text ;
2008-11-16 02:09:04 +01:00
}
/**
2011-08-31 14:24:47 +02:00
* Return an html table from an array
2012-02-04 14:39:47 +01:00
*
* @ param array $data Array of data
* @ param int $tableMarkup Table markup
2012-02-15 13:55:00 +01:00
* @ param string $tableoptions Options for table
2012-02-04 14:39:47 +01:00
* @ param string $troptions Options for tr
* @ param string $tdoptions Options for td
* @ return string
2008-11-16 02:09:04 +01:00
*/
2019-01-27 15:20:16 +01:00
function array2table ( $data , $tableMarkup = 1 , $tableoptions = '' , $troptions = '' , $tdoptions = '' )
2012-02-04 14:39:47 +01:00
{
2020-09-07 10:18:17 +02:00
$text = '' ;
2021-02-23 22:03:23 +01:00
if ( $tableMarkup ) {
$text = '<table ' . $tableoptions . '>' ;
}
2020-09-07 10:18:17 +02:00
foreach ( $data as $key => $item ) {
if ( is_array ( $item )) {
$text .= array2tr ( $item , $troptions , $tdoptions );
} else {
$text .= '<tr ' . $troptions . '>' ;
$text .= '<td ' . $tdoptions . '>' . $key . '</td>' ;
$text .= '<td ' . $tdoptions . '>' . $item . '</td>' ;
$text .= '</tr>' ;
}
}
2021-02-23 22:03:23 +01:00
if ( $tableMarkup ) {
$text .= '</table>' ;
}
2020-09-07 10:18:17 +02:00
return $text ;
2008-11-16 02:09:04 +01:00
}
2008-06-20 23:10:24 +02:00
/**
2013-04-16 15:00:41 +02:00
* Return last or next value for a mask ( according to area we should not reset )
2008-06-20 23:10:24 +02:00
*
2014-12-26 04:44:15 +01:00
* @ param DoliDB $db Database handler
2012-02-04 14:39:47 +01:00
* @ param string $mask Mask to use
* @ param string $table Table containing field with counter
* @ param string $field Field containing already used values of counter
* @ param string $where To add a filter on selection ( for exemple to filter on invoice types )
* @ param Societe $objsoc The company that own the object we need a counter for
* @ param string $date Date to use for the { y },{ m },{ d } tags .
2014-10-17 10:26:34 +02:00
* @ param string $mode 'next' for next value or 'last' for last value
2014-12-26 04:44:15 +01:00
* @ param bool $bentityon Activate the entity filter . Default is true ( for modules not compatible with multicompany )
2017-08-29 19:44:35 +02:00
* @ param User $objuser Object user we need data from .
2018-07-01 16:01:30 +02:00
* @ param int $forceentity Entity id to force
2014-12-26 04:44:15 +01:00
* @ return string New value ( numeric ) or error message
2008-06-20 23:10:24 +02:00
*/
2019-01-27 15:20:16 +01:00
function get_next_value ( $db , $mask , $table , $field , $where = '' , $objsoc = '' , $date = '' , $mode = 'next' , $bentityon = true , $objuser = null , $forceentity = null )
2008-06-20 23:10:24 +02:00
{
2020-09-07 10:18:17 +02:00
global $conf , $user ;
2021-02-23 22:03:23 +01:00
if ( ! is_object ( $objsoc )) {
$valueforccc = $objsoc ;
} elseif ( $table == " commande_fournisseur " || $table == " facture_fourn " ) {
$valueforccc = dol_string_unaccent ( $objsoc -> code_fournisseur );
} else {
$valueforccc = dol_string_unaccent ( $objsoc -> code_client );
}
2020-09-07 10:18:17 +02:00
$sharetable = $table ;
2021-02-23 22:03:23 +01:00
if ( $table == 'facture' || $table == 'invoice' ) {
$sharetable = 'invoicenumber' ; // for getEntity function
}
2020-09-07 10:18:17 +02:00
// Clean parameters
2021-02-23 22:03:23 +01:00
if ( $date == '' ) {
$date = dol_now (); // We use local year and month of PHP server to search numbers
}
2020-09-07 10:18:17 +02:00
// but we should use local year and month of user
// For debugging
//dol_syslog("mask=".$mask, LOG_DEBUG);
//include_once(DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php');
//$mask='FA{yy}{mm}-{0000@99}';
//$date=dol_mktime(12, 0, 0, 1, 1, 1900);
//$date=dol_stringtotime('20130101');
$hasglobalcounter = false ;
2020-09-19 22:41:05 +02:00
$reg = array ();
2020-09-07 10:18:17 +02:00
// Extract value for mask counter, mask raz and mask offset
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/\{(0+)([@\+][0-9\-\+\=]+)?([@\+][0-9\-\+\=]+)?\}/i' , $mask , $reg )) {
2020-09-07 10:18:17 +02:00
$masktri = $reg [ 1 ] . ( ! empty ( $reg [ 2 ]) ? $reg [ 2 ] : '' ) . ( ! empty ( $reg [ 3 ]) ? $reg [ 3 ] : '' );
$maskcounter = $reg [ 1 ];
$hasglobalcounter = true ;
} else {
// setting some defaults so the rest of the code won't fail if there is a third party counter
$masktri = '00000' ;
$maskcounter = '00000' ;
}
$maskraz = - 1 ;
$maskoffset = 0 ;
$resetEveryMonth = false ;
2021-02-23 22:03:23 +01:00
if ( dol_strlen ( $maskcounter ) < 3 && empty ( $conf -> global -> MAIN_COUNTER_WITH_LESS_3_DIGITS )) {
return 'ErrorCounterMustHaveMoreThan3Digits' ;
}
2020-09-07 10:18:17 +02:00
// Extract value for third party mask counter
2020-12-20 14:31:54 +01:00
$regClientRef = array ();
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/\{(c+)(0*)\}/i' , $mask , $regClientRef )) {
2020-09-07 10:18:17 +02:00
$maskrefclient = $regClientRef [ 1 ] . $regClientRef [ 2 ];
$maskrefclient_maskclientcode = $regClientRef [ 1 ];
$maskrefclient_maskcounter = $regClientRef [ 2 ];
$maskrefclient_maskoffset = 0 ; //default value of maskrefclient_counter offset
$maskrefclient_clientcode = substr ( $valueforccc , 0 , dol_strlen ( $maskrefclient_maskclientcode )); //get n first characters of client code where n is length in mask
$maskrefclient_clientcode = str_pad ( $maskrefclient_clientcode , dol_strlen ( $maskrefclient_maskclientcode ), " # " , STR_PAD_RIGHT ); //padding maskrefclient_clientcode for having exactly n characters in maskrefclient_clientcode
$maskrefclient_clientcode = dol_string_nospecial ( $maskrefclient_clientcode ); //sanitize maskrefclient_clientcode for sql insert and sql select like
2021-02-23 22:03:23 +01:00
if ( dol_strlen ( $maskrefclient_maskcounter ) > 0 && dol_strlen ( $maskrefclient_maskcounter ) < 3 ) {
return 'ErrorCounterMustHaveMoreThan3Digits' ;
}
} else {
$maskrefclient = '' ;
}
2020-09-07 10:18:17 +02:00
// fail if there is neither a global nor a third party counter
2021-02-23 22:03:23 +01:00
if ( ! $hasglobalcounter && ( $maskrefclient_maskcounter == '' )) {
2020-09-07 10:18:17 +02:00
return 'ErrorBadMask' ;
}
// Extract value for third party type
2020-09-19 22:41:05 +02:00
$regType = array ();
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/\{(t+)\}/i' , $mask , $regType )) {
2020-09-07 10:18:17 +02:00
$masktype = $regType [ 1 ];
2022-12-14 14:53:14 +01:00
$masktype_value = dol_substr ( preg_replace ( '/^TE_/' , '' , $objsoc -> typent_code ), 0 , dol_strlen ( $regType [ 1 ])); // get n first characters of thirdparty typent_code (where n is length in mask)
2020-09-07 10:18:17 +02:00
$masktype_value = str_pad ( $masktype_value , dol_strlen ( $regType [ 1 ]), " # " , STR_PAD_RIGHT ); // we fill on right with # to have same number of char than into mask
} else {
$masktype = '' ;
$masktype_value = '' ;
}
// Extract value for user
2021-02-23 22:03:23 +01:00
$regType = array ();
2020-12-20 14:31:54 +01:00
if ( preg_match ( '/\{(u+)\}/i' , $mask , $regType )) {
2020-09-07 10:18:17 +02:00
$lastname = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' ;
2021-02-23 22:03:23 +01:00
if ( is_object ( $objuser )) {
$lastname = $objuser -> lastname ;
}
2020-09-07 10:18:17 +02:00
$maskuser = $regType [ 1 ];
$maskuser_value = substr ( $lastname , 0 , dol_strlen ( $regType [ 1 ])); // get n first characters of user firstname (where n is length in mask)
$maskuser_value = str_pad ( $maskuser_value , dol_strlen ( $regType [ 1 ]), " # " , STR_PAD_RIGHT ); // we fill on right with # to have same number of char than into mask
} else {
$maskuser = '' ;
$maskuser_value = '' ;
}
// Personalized field {XXX-1} à {XXX-9}
$maskperso = array ();
$maskpersonew = array ();
$tmpmask = $mask ;
2020-09-19 22:41:05 +02:00
$regKey = array ();
2021-02-23 22:03:23 +01:00
while ( preg_match ( '/\{([A-Z]+)\-([1-9])\}/' , $tmpmask , $regKey )) {
2020-09-07 10:18:17 +02:00
$maskperso [ $regKey [ 1 ]] = '{' . $regKey [ 1 ] . '-' . $regKey [ 2 ] . '}' ;
$maskpersonew [ $regKey [ 1 ]] = str_pad ( '' , $regKey [ 2 ], '_' , STR_PAD_RIGHT );
$tmpmask = preg_replace ( '/\{' . $regKey [ 1 ] . '\-' . $regKey [ 2 ] . '\}/i' , $maskpersonew [ $regKey [ 1 ]], $tmpmask );
}
2021-02-23 22:03:23 +01:00
if ( strstr ( $mask , 'user_extra_' )) {
2019-10-27 11:53:20 +01:00
$start = " { user_extra_ " ;
$end = " \ } " ;
2020-01-10 00:03:10 +01:00
$extra = get_string_between ( $mask , " user_extra_ " , " } " );
2019-10-27 11:53:20 +01:00
if ( ! empty ( $user -> array_options [ 'options_' . $extra ])) {
2020-01-10 00:03:10 +01:00
$mask = preg_replace ( '#(' . $start . ')(.*?)(' . $end . ')#si' , $user -> array_options [ 'options_' . $extra ], $mask );
2019-10-27 11:53:20 +01:00
}
2020-09-07 10:18:17 +02:00
}
$maskwithonlyymcode = $mask ;
$maskwithonlyymcode = preg_replace ( '/\{(0+)([@\+][0-9\-\+\=]+)?([@\+][0-9\-\+\=]+)?\}/i' , $maskcounter , $maskwithonlyymcode );
$maskwithonlyymcode = preg_replace ( '/\{dd\}/i' , 'dd' , $maskwithonlyymcode );
$maskwithonlyymcode = preg_replace ( '/\{(c+)(0*)\}/i' , $maskrefclient , $maskwithonlyymcode );
$maskwithonlyymcode = preg_replace ( '/\{(t+)\}/i' , $masktype_value , $maskwithonlyymcode );
$maskwithonlyymcode = preg_replace ( '/\{(u+)\}/i' , $maskuser_value , $maskwithonlyymcode );
2021-02-23 22:03:23 +01:00
foreach ( $maskperso as $key => $val ) {
2020-09-07 10:18:17 +02:00
$maskwithonlyymcode = preg_replace ( '/' . preg_quote ( $val , '/' ) . '/i' , $maskpersonew [ $key ], $maskwithonlyymcode );
}
$maskwithnocode = $maskwithonlyymcode ;
$maskwithnocode = preg_replace ( '/\{yyyy\}/i' , 'yyyy' , $maskwithnocode );
$maskwithnocode = preg_replace ( '/\{yy\}/i' , 'yy' , $maskwithnocode );
$maskwithnocode = preg_replace ( '/\{y\}/i' , 'y' , $maskwithnocode );
$maskwithnocode = preg_replace ( '/\{mm\}/i' , 'mm' , $maskwithnocode );
// Now maskwithnocode = 0000ddmmyyyyccc for example
// and maskcounter = 0000 for example
//print "maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode."\n<br>";
//var_dump($reg);
// If an offset is asked
2021-02-23 22:03:23 +01:00
if ( ! empty ( $reg [ 2 ]) && preg_match ( '/^\+/' , $reg [ 2 ])) {
$maskoffset = preg_replace ( '/^\+/' , '' , $reg [ 2 ]);
}
if ( ! empty ( $reg [ 3 ]) && preg_match ( '/^\+/' , $reg [ 3 ])) {
$maskoffset = preg_replace ( '/^\+/' , '' , $reg [ 3 ]);
}
2020-09-07 10:18:17 +02:00
// Define $sqlwhere
$sqlwhere = '' ;
$yearoffset = 0 ; // Use year of current $date by default
$yearoffsettype = false ; // false: no reset, 0,-,=,+: reset at offset SOCIETE_FISCAL_MONTH_START, x=reset at offset x
// If a restore to zero after a month is asked we check if there is already a value for this year.
2021-02-23 22:03:23 +01:00
if ( ! empty ( $reg [ 2 ]) && preg_match ( '/^@/' , $reg [ 2 ])) {
$yearoffsettype = preg_replace ( '/^@/' , '' , $reg [ 2 ]);
}
if ( ! empty ( $reg [ 3 ]) && preg_match ( '/^@/' , $reg [ 3 ])) {
$yearoffsettype = preg_replace ( '/^@/' , '' , $reg [ 3 ]);
}
2020-09-07 10:18:17 +02:00
//print "yearoffset=".$yearoffset." yearoffsettype=".$yearoffsettype;
2021-02-23 22:03:23 +01:00
if ( is_numeric ( $yearoffsettype ) && $yearoffsettype >= 1 ) {
2020-09-07 10:18:17 +02:00
$maskraz = $yearoffsettype ; // For backward compatibility
2021-02-23 22:03:23 +01:00
} elseif ( $yearoffsettype === '0' || ( ! empty ( $yearoffsettype ) && ! is_numeric ( $yearoffsettype ) && $conf -> global -> SOCIETE_FISCAL_MONTH_START > 1 )) {
2020-09-07 10:18:17 +02:00
$maskraz = $conf -> global -> SOCIETE_FISCAL_MONTH_START ;
2021-02-23 22:03:23 +01:00
}
2020-09-07 10:18:17 +02:00
//print "maskraz=".$maskraz; // -1=no reset
if ( $maskraz > 0 ) { // A reset is required
if ( $maskraz == 99 ) {
$maskraz = date ( 'm' , $date );
$resetEveryMonth = true ;
}
2021-02-23 22:03:23 +01:00
if ( $maskraz > 12 ) {
return 'ErrorBadMaskBadRazMonth' ;
}
2020-09-07 10:18:17 +02:00
// Define posy, posm and reg
2021-02-23 22:03:23 +01:00
if ( $maskraz > 1 ) { // if reset is not first month, we need month and year into mask
if ( preg_match ( '/^(.*)\{(y+)\}\{(m+)\}/i' , $maskwithonlyymcode , $reg )) {
2021-03-01 20:37:16 +01:00
$posy = 2 ;
$posm = 3 ;
2021-02-23 22:03:23 +01:00
} elseif ( preg_match ( '/^(.*)\{(m+)\}\{(y+)\}/i' , $maskwithonlyymcode , $reg )) {
2021-03-01 20:37:16 +01:00
$posy = 3 ;
$posm = 2 ;
2021-02-23 22:03:23 +01:00
} else {
return 'ErrorCantUseRazInStartedYearIfNoYearMonthInMask' ;
}
2020-09-07 10:18:17 +02:00
2021-02-23 22:03:23 +01:00
if ( dol_strlen ( $reg [ $posy ]) < 2 ) {
return 'ErrorCantUseRazWithYearOnOneDigit' ;
}
2020-09-07 10:18:17 +02:00
} else // if reset is for a specific month in year, we need year
{
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/^(.*)\{(m+)\}\{(y+)\}/i' , $maskwithonlyymcode , $reg )) {
2021-03-01 20:37:16 +01:00
$posy = 3 ;
$posm = 2 ;
2021-02-23 22:03:23 +01:00
} elseif ( preg_match ( '/^(.*)\{(y+)\}\{(m+)\}/i' , $maskwithonlyymcode , $reg )) {
2021-03-01 20:37:16 +01:00
$posy = 2 ;
$posm = 3 ;
2021-02-23 22:03:23 +01:00
} elseif ( preg_match ( '/^(.*)\{(y+)\}/i' , $maskwithonlyymcode , $reg )) {
2021-03-01 20:37:16 +01:00
$posy = 2 ;
$posm = 0 ;
2021-02-23 22:03:23 +01:00
} else {
return 'ErrorCantUseRazIfNoYearInMask' ;
}
2020-09-07 10:18:17 +02:00
}
// Define length
$yearlen = $posy ? dol_strlen ( $reg [ $posy ]) : 0 ;
$monthlen = $posm ? dol_strlen ( $reg [ $posm ]) : 0 ;
// Define pos
2021-02-23 22:03:23 +01:00
$yearpos = ( dol_strlen ( $reg [ 1 ]) + 1 );
2020-09-07 10:18:17 +02:00
$monthpos = ( $yearpos + $yearlen );
if ( $posy == 3 && $posm == 2 ) { // if month is before year
2021-02-23 22:03:23 +01:00
$monthpos = ( dol_strlen ( $reg [ 1 ]) + 1 );
$yearpos = ( $monthpos + $monthlen );
2020-09-07 10:18:17 +02:00
}
//print "xxx ".$maskwithonlyymcode." maskraz=".$maskraz." posy=".$posy." yearlen=".$yearlen." yearpos=".$yearpos." posm=".$posm." monthlen=".$monthlen." monthpos=".$monthpos." yearoffsettype=".$yearoffsettype." resetEveryMonth=".$resetEveryMonth."\n";
// Define $yearcomp and $monthcomp (that will be use in the select where to search max number)
$monthcomp = $maskraz ;
$yearcomp = 0 ;
2021-02-23 22:03:23 +01:00
if ( ! empty ( $yearoffsettype ) && ! is_numeric ( $yearoffsettype ) && $yearoffsettype != '=' ) { // $yearoffsettype is - or +
2020-09-07 10:18:17 +02:00
$currentyear = date ( " Y " , $date );
$fiscaldate = dol_mktime ( '0' , '0' , '0' , $maskraz , '1' , $currentyear );
$newyeardate = dol_mktime ( '0' , '0' , '0' , '1' , '1' , $currentyear );
$nextnewyeardate = dol_mktime ( '0' , '0' , '0' , '1' , '1' , $currentyear + 1 );
//echo 'currentyear='.$currentyear.' date='.dol_print_date($date, 'day').' fiscaldate='.dol_print_date($fiscaldate, 'day').'<br>';
// If after or equal of current fiscal date
2021-02-23 22:03:23 +01:00
if ( $date >= $fiscaldate ) {
2020-09-07 10:18:17 +02:00
// If before of next new year date
2021-02-23 22:03:23 +01:00
if ( $date < $nextnewyeardate && $yearoffsettype == '+' ) {
$yearoffset = 1 ;
}
2021-03-01 00:19:52 +01:00
} elseif ( $date >= $newyeardate && $yearoffsettype == '-' ) {
// If after or equal of current new year date
2021-02-23 22:03:23 +01:00
$yearoffset = - 1 ;
}
2021-03-01 00:19:52 +01:00
} elseif ( date ( " m " , $date ) < $maskraz && empty ( $resetEveryMonth )) {
// For backward compatibility
2021-02-23 22:03:23 +01:00
$yearoffset = - 1 ;
} // If current month lower that month of return to zero, year is previous year
if ( $yearlen == 4 ) {
$yearcomp = sprintf ( " %04d " , date ( " Y " , $date ) + $yearoffset );
} elseif ( $yearlen == 2 ) {
$yearcomp = sprintf ( " %02d " , date ( " y " , $date ) + $yearoffset );
} elseif ( $yearlen == 1 ) {
2022-11-23 08:36:20 +01:00
$yearcomp = substr ( date ( 'y' , $date ), 1 , 1 ) + $yearoffset ;
2021-02-23 22:03:23 +01:00
}
if ( $monthcomp > 1 && empty ( $resetEveryMonth )) { // Test with month is useless if monthcomp = 0 or 1 (0 is same as 1) (regis: $monthcomp can't equal 0)
if ( $yearlen == 4 ) {
$yearcomp1 = sprintf ( " %04d " , date ( " Y " , $date ) + $yearoffset + 1 );
} elseif ( $yearlen == 2 ) {
$yearcomp1 = sprintf ( " %02d " , date ( " y " , $date ) + $yearoffset + 1 );
}
2020-09-07 10:18:17 +02:00
$sqlwhere .= " ( " ;
2020-09-19 22:41:05 +02:00
$sqlwhere .= " (SUBSTRING( " . $field . " , " . $yearpos . " , " . $yearlen . " ) = ' " . $db -> escape ( $yearcomp ) . " ' " ;
2020-09-07 10:18:17 +02:00
$sqlwhere .= " AND SUBSTRING( " . $field . " , " . $monthpos . " , " . $monthlen . " ) >= ' " . str_pad ( $monthcomp , $monthlen , '0' , STR_PAD_LEFT ) . " ') " ;
$sqlwhere .= " OR " ;
2020-09-19 22:41:05 +02:00
$sqlwhere .= " (SUBSTRING( " . $field . " , " . $yearpos . " , " . $yearlen . " ) = ' " . $db -> escape ( $yearcomp1 ) . " ' " ;
2020-09-07 10:18:17 +02:00
$sqlwhere .= " AND SUBSTRING( " . $field . " , " . $monthpos . " , " . $monthlen . " ) < ' " . str_pad ( $monthcomp , $monthlen , '0' , STR_PAD_LEFT ) . " ') " ;
$sqlwhere .= ')' ;
2020-12-20 14:31:54 +01:00
} elseif ( $resetEveryMonth ) {
2020-09-19 22:41:05 +02:00
$sqlwhere .= " (SUBSTRING( " . $field . " , " . $yearpos . " , " . $yearlen . " ) = ' " . $db -> escape ( $yearcomp ) . " ' " ;
2020-09-07 10:18:17 +02:00
$sqlwhere .= " AND SUBSTRING( " . $field . " , " . $monthpos . " , " . $monthlen . " ) = ' " . str_pad ( $monthcomp , $monthlen , '0' , STR_PAD_LEFT ) . " ') " ;
2020-12-20 14:31:54 +01:00
} else { // reset is done on january
2021-08-28 01:45:53 +02:00
$sqlwhere .= " (SUBSTRING( " . $field . " , " . $yearpos . " , " . $yearlen . " ) = ' " . $db -> escape ( $yearcomp ) . " ') " ;
2020-09-07 10:18:17 +02:00
}
}
//print "sqlwhere=".$sqlwhere." yearcomp=".$yearcomp."<br>\n"; // sqlwhere and yearcomp defined only if we ask a reset
//print "masktri=".$masktri." maskcounter=".$maskcounter." maskraz=".$maskraz." maskoffset=".$maskoffset."<br>\n";
// Define $sqlstring
2020-11-07 20:01:28 +01:00
if ( function_exists ( 'mb_strrpos' )) {
$posnumstart = mb_strrpos ( $maskwithnocode , $maskcounter , 0 , 'UTF-8' );
2020-05-21 15:05:19 +02:00
} else {
2020-09-07 10:18:17 +02:00
$posnumstart = strrpos ( $maskwithnocode , $maskcounter );
2015-11-20 18:05:00 +01:00
} // Pos of counter in final string (from 0 to ...)
2021-02-23 22:03:23 +01:00
if ( $posnumstart < 0 ) {
return 'ErrorBadMaskFailedToLocatePosOfSequence' ;
}
2021-08-28 01:45:53 +02:00
$sqlstring = " SUBSTRING( " . $field . " , " . ( $posnumstart + 1 ) . " , " . dol_strlen ( $maskcounter ) . " ) " ;
2020-09-07 10:18:17 +02:00
// Define $maskLike
$maskLike = dol_string_nospecial ( $mask );
$maskLike = str_replace ( " % " , " _ " , $maskLike );
// Replace protected special codes with matching number of _ as wild card caracter
$maskLike = preg_replace ( '/\{yyyy\}/i' , '____' , $maskLike );
$maskLike = preg_replace ( '/\{yy\}/i' , '__' , $maskLike );
$maskLike = preg_replace ( '/\{y\}/i' , '_' , $maskLike );
$maskLike = preg_replace ( '/\{mm\}/i' , '__' , $maskLike );
$maskLike = preg_replace ( '/\{dd\}/i' , '__' , $maskLike );
$maskLike = str_replace ( dol_string_nospecial ( '{' . $masktri . '}' ), str_pad ( " " , dol_strlen ( $maskcounter ), " _ " ), $maskLike );
2021-02-23 22:03:23 +01:00
if ( $maskrefclient ) {
$maskLike = str_replace ( dol_string_nospecial ( '{' . $maskrefclient . '}' ), str_pad ( " " , dol_strlen ( $maskrefclient ), " _ " ), $maskLike );
}
if ( $masktype ) {
$maskLike = str_replace ( dol_string_nospecial ( '{' . $masktype . '}' ), $masktype_value , $maskLike );
}
if ( $maskuser ) {
$maskLike = str_replace ( dol_string_nospecial ( '{' . $maskuser . '}' ), $maskuser_value , $maskLike );
}
foreach ( $maskperso as $key => $val ) {
2020-09-07 10:18:17 +02:00
$maskLike = str_replace ( dol_string_nospecial ( $maskperso [ $key ]), $maskpersonew [ $key ], $maskLike );
}
2019-06-18 19:41:16 +02:00
2020-09-07 10:18:17 +02:00
// Get counter in database
$counter = 0 ;
$sql = " SELECT MAX( " . $sqlstring . " ) as val " ;
$sql .= " FROM " . MAIN_DB_PREFIX . $table ;
2020-09-19 22:41:05 +02:00
$sql .= " WHERE " . $field . " LIKE ' " . $db -> escape ( $maskLike ) . " ' " ;
2019-11-13 19:37:08 +01:00
$sql .= " AND " . $field . " NOT LIKE '(PROV%)' " ;
2022-11-10 17:10:51 +01:00
2022-11-10 17:19:12 +01:00
// To ensure that all variables within the MAX() brackets are integers
2022-12-01 17:39:28 +01:00
if ( getDolGlobalInt ( 'MAIN_NUMBERING_FILTER_ON_INT_ONLY' )) {
$sql .= " AND " . $db -> regexpsql ( $sqlstring , '^[0-9]+$' , true );
}
2022-11-10 17:19:12 +01:00
2021-02-23 22:03:23 +01:00
if ( $bentityon ) { // only if entity enable
2020-09-07 10:18:17 +02:00
$sql .= " AND entity IN ( " . getEntity ( $sharetable ) . " ) " ;
2021-02-23 22:03:23 +01:00
} elseif ( ! empty ( $forceentity )) {
2021-03-22 11:30:18 +01:00
$sql .= " AND entity IN ( " . $db -> sanitize ( $forceentity ) . " ) " ;
2021-02-23 22:03:23 +01:00
}
if ( $where ) {
$sql .= $where ;
}
if ( $sqlwhere ) {
2021-08-28 01:45:53 +02:00
$sql .= " AND " . $sqlwhere ;
2021-02-23 22:03:23 +01:00
}
2020-09-07 10:18:17 +02:00
//print $sql.'<br>';
2022-12-28 16:40:03 +01:00
dol_syslog ( " functions2::get_next_value mode= " . $mode , LOG_DEBUG );
2020-09-07 10:18:17 +02:00
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( $resql ) {
2020-09-07 10:18:17 +02:00
$obj = $db -> fetch_object ( $resql );
$counter = $obj -> val ;
2021-02-23 22:03:23 +01:00
} else {
dol_print_error ( $db );
}
2020-09-07 10:18:17 +02:00
// Check if we must force counter to maskoffset
2021-02-23 22:03:23 +01:00
if ( empty ( $counter )) {
$counter = $maskoffset ;
} elseif ( preg_match ( '/[^0-9]/i' , $counter )) {
2020-09-07 10:18:17 +02:00
dol_syslog ( " Error, the last counter found is ' " . $counter . " ' so is not a numeric value. We will restart to 1. " , LOG_ERR );
2023-03-23 18:37:05 +01:00
$counter = 0 ;
2021-02-23 22:03:23 +01:00
} elseif ( $counter < $maskoffset && empty ( $conf -> global -> MAIN_NUMBERING_OFFSET_ONLY_FOR_FIRST )) {
$counter = $maskoffset ;
}
2020-09-07 10:18:17 +02:00
2021-02-23 22:03:23 +01:00
if ( $mode == 'last' ) { // We found value for counter = last counter value. Now need to get corresponding ref of invoice.
2020-09-07 10:18:17 +02:00
$counterpadded = str_pad ( $counter , dol_strlen ( $maskcounter ), " 0 " , STR_PAD_LEFT );
// Define $maskLike
$maskLike = dol_string_nospecial ( $mask );
$maskLike = str_replace ( " % " , " _ " , $maskLike );
// Replace protected special codes with matching number of _ as wild card caracter
$maskLike = preg_replace ( '/\{yyyy\}/i' , '____' , $maskLike );
$maskLike = preg_replace ( '/\{yy\}/i' , '__' , $maskLike );
$maskLike = preg_replace ( '/\{y\}/i' , '_' , $maskLike );
$maskLike = preg_replace ( '/\{mm\}/i' , '__' , $maskLike );
$maskLike = preg_replace ( '/\{dd\}/i' , '__' , $maskLike );
$maskLike = str_replace ( dol_string_nospecial ( '{' . $masktri . '}' ), $counterpadded , $maskLike );
2021-02-23 22:03:23 +01:00
if ( $maskrefclient ) {
$maskLike = str_replace ( dol_string_nospecial ( '{' . $maskrefclient . '}' ), str_pad ( " " , dol_strlen ( $maskrefclient ), " _ " ), $maskLike );
}
if ( $masktype ) {
$maskLike = str_replace ( dol_string_nospecial ( '{' . $masktype . '}' ), $masktype_value , $maskLike );
}
if ( $maskuser ) {
$maskLike = str_replace ( dol_string_nospecial ( '{' . $maskuser . '}' ), $maskuser_value , $maskLike );
}
2020-09-07 10:18:17 +02:00
$ref = '' ;
$sql = " SELECT " . $field . " as ref " ;
$sql .= " FROM " . MAIN_DB_PREFIX . $table ;
2020-09-19 22:41:05 +02:00
$sql .= " WHERE " . $field . " LIKE ' " . $db -> escape ( $maskLike ) . " ' " ;
2020-09-07 10:18:17 +02:00
$sql .= " AND " . $field . " NOT LIKE '%PROV%' " ;
2021-02-23 22:03:23 +01:00
if ( $bentityon ) { // only if entity enable
2020-09-07 10:18:17 +02:00
$sql .= " AND entity IN ( " . getEntity ( $sharetable ) . " ) " ;
2021-02-23 22:03:23 +01:00
} elseif ( ! empty ( $forceentity )) {
2021-03-22 11:30:18 +01:00
$sql .= " AND entity IN ( " . $db -> sanitize ( $forceentity ) . " ) " ;
2021-02-23 22:03:23 +01:00
}
if ( $where ) {
$sql .= $where ;
}
if ( $sqlwhere ) {
2021-08-28 01:45:53 +02:00
$sql .= " AND " . $sqlwhere ;
2021-02-23 22:03:23 +01:00
}
2020-09-07 10:18:17 +02:00
2022-12-28 16:40:03 +01:00
dol_syslog ( " functions2::get_next_value mode= " . $mode , LOG_DEBUG );
2020-09-07 10:18:17 +02:00
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( $resql ) {
2020-09-07 10:18:17 +02:00
$obj = $db -> fetch_object ( $resql );
2021-02-23 22:03:23 +01:00
if ( $obj ) {
$ref = $obj -> ref ;
}
} else {
dol_print_error ( $db );
}
2020-09-07 10:18:17 +02:00
$numFinal = $ref ;
2020-12-20 14:31:54 +01:00
} elseif ( $mode == 'next' ) {
2020-09-07 10:18:17 +02:00
$counter ++ ;
2022-02-01 15:55:04 +01:00
$maskrefclient_counter = 0 ;
2020-09-07 10:18:17 +02:00
// If value for $counter has a length higher than $maskcounter chars
2021-02-23 22:03:23 +01:00
if ( $counter >= pow ( 10 , dol_strlen ( $maskcounter ))) {
2020-09-07 10:18:17 +02:00
$counter = 'ErrorMaxNumberReachForThisMask' ;
}
2021-02-23 22:03:23 +01:00
if ( ! empty ( $maskrefclient_maskcounter )) {
2020-09-07 10:18:17 +02:00
//print "maskrefclient_maskcounter=".$maskrefclient_maskcounter." maskwithnocode=".$maskwithnocode." maskrefclient=".$maskrefclient."\n<br>";
// Define $sqlstring
$maskrefclient_posnumstart = strpos ( $maskwithnocode , $maskrefclient_maskcounter , strpos ( $maskwithnocode , $maskrefclient )); // Pos of counter in final string (from 0 to ...)
2021-02-23 22:03:23 +01:00
if ( $maskrefclient_posnumstart <= 0 ) {
return 'ErrorBadMask' ;
}
2020-09-07 10:18:17 +02:00
$maskrefclient_sqlstring = 'SUBSTRING(' . $field . ', ' . ( $maskrefclient_posnumstart + 1 ) . ', ' . dol_strlen ( $maskrefclient_maskcounter ) . ')' ;
//print "x".$sqlstring;
// Define $maskrefclient_maskLike
$maskrefclient_maskLike = dol_string_nospecial ( $mask );
$maskrefclient_maskLike = str_replace ( " % " , " _ " , $maskrefclient_maskLike );
// Replace protected special codes with matching number of _ as wild card caracter
$maskrefclient_maskLike = str_replace ( dol_string_nospecial ( '{yyyy}' ), '____' , $maskrefclient_maskLike );
$maskrefclient_maskLike = str_replace ( dol_string_nospecial ( '{yy}' ), '__' , $maskrefclient_maskLike );
$maskrefclient_maskLike = str_replace ( dol_string_nospecial ( '{y}' ), '_' , $maskrefclient_maskLike );
$maskrefclient_maskLike = str_replace ( dol_string_nospecial ( '{mm}' ), '__' , $maskrefclient_maskLike );
$maskrefclient_maskLike = str_replace ( dol_string_nospecial ( '{dd}' ), '__' , $maskrefclient_maskLike );
$maskrefclient_maskLike = str_replace ( dol_string_nospecial ( '{' . $masktri . '}' ), str_pad ( " " , dol_strlen ( $maskcounter ), " _ " ), $maskrefclient_maskLike );
$maskrefclient_maskLike = str_replace ( dol_string_nospecial ( '{' . $maskrefclient . '}' ), $maskrefclient_clientcode . str_pad ( " " , dol_strlen ( $maskrefclient_maskcounter ), " _ " ), $maskrefclient_maskLike );
// Get counter in database
$maskrefclient_sql = " SELECT MAX( " . $maskrefclient_sqlstring . " ) as val " ;
$maskrefclient_sql .= " FROM " . MAIN_DB_PREFIX . $table ;
//$sql.= " WHERE ".$field." not like '(%'";
2020-09-19 22:41:05 +02:00
$maskrefclient_sql .= " WHERE " . $field . " LIKE ' " . $db -> escape ( $maskrefclient_maskLike ) . " ' " ;
2021-02-23 22:03:23 +01:00
if ( $bentityon ) { // only if entity enable
2020-09-07 10:18:17 +02:00
$maskrefclient_sql .= " AND entity IN ( " . getEntity ( $sharetable ) . " ) " ;
2021-02-23 22:03:23 +01:00
} elseif ( ! empty ( $forceentity )) {
2021-03-22 11:30:18 +01:00
$sql .= " AND entity IN ( " . $db -> sanitize ( $forceentity ) . " ) " ;
2021-02-23 22:03:23 +01:00
}
if ( $where ) {
$maskrefclient_sql .= $where ; //use the same optional where as general mask
}
if ( $sqlwhere ) {
$maskrefclient_sql .= ' AND ' . $sqlwhere ; //use the same sqlwhere as general mask
}
2021-08-28 01:45:53 +02:00
$maskrefclient_sql .= " AND (SUBSTRING( " . $field . " , " . ( strpos ( $maskwithnocode , $maskrefclient ) + 1 ) . " , " . dol_strlen ( $maskrefclient_maskclientcode ) . " ) = ' " . $db -> escape ( $maskrefclient_clientcode ) . " ') " ;
2020-09-07 10:18:17 +02:00
dol_syslog ( " functions2::get_next_value maskrefclient " , LOG_DEBUG );
$maskrefclient_resql = $db -> query ( $maskrefclient_sql );
2021-02-23 22:03:23 +01:00
if ( $maskrefclient_resql ) {
2020-09-07 10:18:17 +02:00
$maskrefclient_obj = $db -> fetch_object ( $maskrefclient_resql );
$maskrefclient_counter = $maskrefclient_obj -> val ;
2021-02-23 22:03:23 +01:00
} else {
dol_print_error ( $db );
}
2020-09-07 10:18:17 +02:00
2021-02-23 22:03:23 +01:00
if ( empty ( $maskrefclient_counter ) || preg_match ( '/[^0-9]/i' , $maskrefclient_counter )) {
$maskrefclient_counter = $maskrefclient_maskoffset ;
}
2013-06-06 21:18:50 +02:00
$maskrefclient_counter ++ ;
2020-09-07 10:18:17 +02:00
}
2010-12-14 00:50:51 +01:00
2020-09-07 10:18:17 +02:00
// Build numFinal
$numFinal = $mask ;
2010-12-14 00:50:51 +01:00
2020-09-07 10:18:17 +02:00
// We replace special codes except refclient
2021-02-23 22:03:23 +01:00
if ( ! empty ( $yearoffsettype ) && ! is_numeric ( $yearoffsettype ) && $yearoffsettype != '=' ) { // yearoffsettype is - or +, so we don't want current year
2020-09-07 10:18:17 +02:00
$numFinal = preg_replace ( '/\{yyyy\}/i' , date ( " Y " , $date ) + $yearoffset , $numFinal );
$numFinal = preg_replace ( '/\{yy\}/i' , date ( " y " , $date ) + $yearoffset , $numFinal );
$numFinal = preg_replace ( '/\{y\}/i' , substr ( date ( " y " , $date ), 1 , 1 ) + $yearoffset , $numFinal );
2020-05-21 15:05:19 +02:00
} else // we want yyyy to be current year
2012-09-23 16:25:08 +02:00
{
2020-09-07 10:18:17 +02:00
$numFinal = preg_replace ( '/\{yyyy\}/i' , date ( " Y " , $date ), $numFinal );
$numFinal = preg_replace ( '/\{yy\}/i' , date ( " y " , $date ), $numFinal );
$numFinal = preg_replace ( '/\{y\}/i' , substr ( date ( " y " , $date ), 1 , 1 ), $numFinal );
}
$numFinal = preg_replace ( '/\{mm\}/i' , date ( " m " , $date ), $numFinal );
$numFinal = preg_replace ( '/\{dd\}/i' , date ( " d " , $date ), $numFinal );
// Now we replace the counter
$maskbefore = '{' . $masktri . '}' ;
$maskafter = str_pad ( $counter , dol_strlen ( $maskcounter ), " 0 " , STR_PAD_LEFT );
2022-04-08 10:19:20 +02:00
//print 'x'.$numFinal.' - '.$maskbefore.' - '.$maskafter.'y';exit;
2020-09-07 10:18:17 +02:00
$numFinal = str_replace ( $maskbefore , $maskafter , $numFinal );
// Now we replace the refclient
2021-02-23 22:03:23 +01:00
if ( $maskrefclient ) {
2022-04-08 10:19:20 +02:00
//print "maskrefclient=".$maskrefclient." maskrefclient_counter=".$maskrefclient_counter." maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode." maskrefclient_clientcode=".$maskrefclient_clientcode." maskrefclient_maskcounter=".$maskrefclient_maskcounter."\n<br>";exit;
2020-09-07 10:18:17 +02:00
$maskrefclient_maskbefore = '{' . $maskrefclient . '}' ;
2022-04-08 10:19:20 +02:00
$maskrefclient_maskafter = $maskrefclient_clientcode ;
if ( dol_strlen ( $maskrefclient_maskcounter ) > 0 ) {
$maskrefclient_maskafter .= str_pad ( $maskrefclient_counter , dol_strlen ( $maskrefclient_maskcounter ), " 0 " , STR_PAD_LEFT );
}
2020-09-07 10:18:17 +02:00
$numFinal = str_replace ( $maskrefclient_maskbefore , $maskrefclient_maskafter , $numFinal );
2012-09-23 22:09:54 +02:00
}
2020-09-07 10:18:17 +02:00
// Now we replace the type
2021-02-23 22:03:23 +01:00
if ( $masktype ) {
2020-09-07 10:18:17 +02:00
$masktype_maskbefore = '{' . $masktype . '}' ;
$masktype_maskafter = $masktype_value ;
$numFinal = str_replace ( $masktype_maskbefore , $masktype_maskafter , $numFinal );
}
// Now we replace the user
2021-02-23 22:03:23 +01:00
if ( $maskuser ) {
2020-09-07 10:18:17 +02:00
$maskuser_maskbefore = '{' . $maskuser . '}' ;
$maskuser_maskafter = $maskuser_value ;
$numFinal = str_replace ( $maskuser_maskbefore , $maskuser_maskafter , $numFinal );
}
}
dol_syslog ( " functions2::get_next_value return " . $numFinal , LOG_DEBUG );
return $numFinal ;
2008-11-16 02:09:04 +01:00
}
2017-10-04 03:22:41 +02:00
2018-08-31 21:39:23 +02:00
/**
* Get string between
*
* @ param string $string String to test
* @ param int $start Value for start
* @ param int $end Value for end
* @ return string Return part of string
*/
2018-08-15 17:34:35 +02:00
function get_string_between ( $string , $start , $end )
{
2020-09-07 10:18:17 +02:00
$string = " " . $string ;
$ini = strpos ( $string , $start );
2021-02-23 22:03:23 +01:00
if ( $ini == 0 ) {
return " " ;
}
2020-09-07 10:18:17 +02:00
$ini += strlen ( $start );
$len = strpos ( $string , $end , $ini ) - $ini ;
return substr ( $string , $ini , $len );
2017-05-29 15:38:40 +02:00
}
2017-10-04 03:22:41 +02:00
2009-01-31 16:23:05 +01:00
/**
* Check value
2011-08-31 14:24:47 +02:00
*
2012-02-15 13:55:00 +01:00
* @ param string $mask Mask to use
* @ param string $value Value
2017-11-17 15:27:59 +01:00
* @ return int | string < 0 or error string if KO , 0 if OK
2009-01-31 16:23:05 +01:00
*/
2019-01-27 15:20:16 +01:00
function check_value ( $mask , $value )
2009-01-31 16:23:05 +01:00
{
2020-09-07 10:18:17 +02:00
$result = 0 ;
$hasglobalcounter = false ;
// Extract value for mask counter, mask raz and mask offset
2020-09-25 17:23:42 +02:00
$reg = array ();
2020-12-20 14:31:54 +01:00
if ( preg_match ( '/\{(0+)([@\+][0-9]+)?([@\+][0-9]+)?\}/i' , $mask , $reg )) {
2020-09-07 10:18:17 +02:00
$masktri = $reg [ 1 ] . ( isset ( $reg [ 2 ]) ? $reg [ 2 ] : '' ) . ( isset ( $reg [ 3 ]) ? $reg [ 3 ] : '' );
$maskcounter = $reg [ 1 ];
$hasglobalcounter = true ;
} else {
// setting some defaults so the rest of the code won't fail if there is a third party counter
$masktri = '00000' ;
$maskcounter = '00000' ;
}
$maskraz = - 1 ;
$maskoffset = 0 ;
2021-02-23 22:03:23 +01:00
if ( dol_strlen ( $maskcounter ) < 3 ) {
return 'ErrorCounterMustHaveMoreThan3Digits' ;
}
2020-09-07 10:18:17 +02:00
// Extract value for third party mask counter
2020-09-25 17:23:42 +02:00
$regClientRef = array ();
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/\{(c+)(0*)\}/i' , $mask , $regClientRef )) {
2020-09-07 10:18:17 +02:00
$maskrefclient = $regClientRef [ 1 ] . $regClientRef [ 2 ];
$maskrefclient_maskclientcode = $regClientRef [ 1 ];
$maskrefclient_maskcounter = $regClientRef [ 2 ];
$maskrefclient_maskoffset = 0 ; //default value of maskrefclient_counter offset
$maskrefclient_clientcode = substr ( '' , 0 , dol_strlen ( $maskrefclient_maskclientcode )); //get n first characters of client code to form maskrefclient_clientcode
$maskrefclient_clientcode = str_pad ( $maskrefclient_clientcode , dol_strlen ( $maskrefclient_maskclientcode ), " # " , STR_PAD_RIGHT ); //padding maskrefclient_clientcode for having exactly n characters in maskrefclient_clientcode
$maskrefclient_clientcode = dol_string_nospecial ( $maskrefclient_clientcode ); //sanitize maskrefclient_clientcode for sql insert and sql select like
2021-02-23 22:03:23 +01:00
if ( dol_strlen ( $maskrefclient_maskcounter ) > 0 && dol_strlen ( $maskrefclient_maskcounter ) < 3 ) {
return 'ErrorCounterMustHaveMoreThan3Digits' ;
}
} else {
$maskrefclient = '' ;
}
2020-09-07 10:18:17 +02:00
// fail if there is neither a global nor a third party counter
2021-02-23 22:03:23 +01:00
if ( ! $hasglobalcounter && ( $maskrefclient_maskcounter == '' )) {
2020-09-07 10:18:17 +02:00
return 'ErrorBadMask' ;
}
$maskwithonlyymcode = $mask ;
$maskwithonlyymcode = preg_replace ( '/\{(0+)([@\+][0-9]+)?([@\+][0-9]+)?\}/i' , $maskcounter , $maskwithonlyymcode );
$maskwithonlyymcode = preg_replace ( '/\{dd\}/i' , 'dd' , $maskwithonlyymcode );
$maskwithonlyymcode = preg_replace ( '/\{(c+)(0*)\}/i' , $maskrefclient , $maskwithonlyymcode );
$maskwithnocode = $maskwithonlyymcode ;
$maskwithnocode = preg_replace ( '/\{yyyy\}/i' , 'yyyy' , $maskwithnocode );
$maskwithnocode = preg_replace ( '/\{yy\}/i' , 'yy' , $maskwithnocode );
$maskwithnocode = preg_replace ( '/\{y\}/i' , 'y' , $maskwithnocode );
$maskwithnocode = preg_replace ( '/\{mm\}/i' , 'mm' , $maskwithnocode );
// Now maskwithnocode = 0000ddmmyyyyccc for example
// and maskcounter = 0000 for example
//print "maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode."\n<br>";
// If an offset is asked
2021-02-23 22:03:23 +01:00
if ( ! empty ( $reg [ 2 ]) && preg_match ( '/^\+/' , $reg [ 2 ])) {
$maskoffset = preg_replace ( '/^\+/' , '' , $reg [ 2 ]);
}
if ( ! empty ( $reg [ 3 ]) && preg_match ( '/^\+/' , $reg [ 3 ])) {
$maskoffset = preg_replace ( '/^\+/' , '' , $reg [ 3 ]);
}
2020-09-07 10:18:17 +02:00
// Define $sqlwhere
// If a restore to zero after a month is asked we check if there is already a value for this year.
2021-02-23 22:03:23 +01:00
if ( ! empty ( $reg [ 2 ]) && preg_match ( '/^@/' , $reg [ 2 ])) {
$maskraz = preg_replace ( '/^@/' , '' , $reg [ 2 ]);
}
if ( ! empty ( $reg [ 3 ]) && preg_match ( '/^@/' , $reg [ 3 ])) {
$maskraz = preg_replace ( '/^@/' , '' , $reg [ 3 ]);
}
if ( $maskraz >= 0 ) {
2020-09-07 10:18:17 +02:00
if ( $maskraz == 99 ) {
$maskraz = date ( 'm' );
$resetEveryMonth = true ;
}
2021-02-23 22:03:23 +01:00
if ( $maskraz > 12 ) {
return 'ErrorBadMaskBadRazMonth' ;
}
2020-09-07 10:18:17 +02:00
// Define reg
2021-02-23 22:03:23 +01:00
if ( $maskraz > 1 && ! preg_match ( '/^(.*)\{(y+)\}\{(m+)\}/i' , $maskwithonlyymcode , $reg )) {
return 'ErrorCantUseRazInStartedYearIfNoYearMonthInMask' ;
}
if ( $maskraz <= 1 && ! preg_match ( '/^(.*)\{(y+)\}/i' , $maskwithonlyymcode , $reg )) {
return 'ErrorCantUseRazIfNoYearInMask' ;
}
2020-09-07 10:18:17 +02:00
//print "x".$maskwithonlyymcode." ".$maskraz;
}
2020-12-20 14:31:54 +01:00
//print "masktri=".$masktri." maskcounter=".$maskcounter." maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode." maskraz=".$maskraz." maskoffset=".$maskoffset."<br>\n";
2020-09-07 10:18:17 +02:00
2020-12-20 13:54:02 +01:00
if ( function_exists ( 'mb_strrpos' )) {
2020-12-29 04:27:16 +01:00
$posnumstart = mb_strrpos ( $maskwithnocode , $maskcounter , 0 , 'UTF-8' );
2021-02-23 22:03:23 +01:00
} else {
2020-12-20 13:54:02 +01:00
$posnumstart = strrpos ( $maskwithnocode , $maskcounter );
} // Pos of counter in final string (from 0 to ...)
2021-02-23 22:03:23 +01:00
if ( $posnumstart < 0 ) {
return 'ErrorBadMaskFailedToLocatePosOfSequence' ;
}
2020-09-07 10:18:17 +02:00
2020-12-20 13:54:02 +01:00
// Check we have a number in $value at position ($posnumstart+1).', '.dol_strlen($maskcounter)
// TODO
2020-09-07 10:18:17 +02:00
2021-02-23 22:03:23 +01:00
// Check length
$len = dol_strlen ( $maskwithnocode );
if ( dol_strlen ( $value ) != $len ) {
$result = - 1 ;
}
2010-12-14 00:50:51 +01:00
2021-02-23 22:03:23 +01:00
dol_syslog ( " functions2::check_value result= " . $result , LOG_DEBUG );
return $result ;
2009-01-31 16:23:05 +01:00
}
2008-11-16 02:09:04 +01:00
/**
2011-07-04 10:38:51 +02:00
* Convert a binary data to string that represent hexadecimal value
2011-08-31 14:24:47 +02:00
*
2012-02-04 15:20:32 +01:00
* @ param string $bin Value to convert
* @ param boolean $pad Add 0
* @ param boolean $upper Convert to tupper
* @ return string x
2008-11-16 02:09:04 +01:00
*/
2019-01-27 15:20:16 +01:00
function binhex ( $bin , $pad = false , $upper = false )
2008-11-16 02:09:04 +01:00
{
2020-09-07 10:18:17 +02:00
$last = dol_strlen ( $bin ) - 1 ;
2021-02-23 22:03:23 +01:00
for ( $i = 0 ; $i <= $last ; $i ++ ) {
$x += $bin [ $last - $i ] * pow ( 2 , $i );
}
2020-09-07 10:18:17 +02:00
$x = dechex ( $x );
2021-02-23 22:03:23 +01:00
if ( $pad ) {
while ( dol_strlen ( $x ) < intval ( dol_strlen ( $bin )) / 4 ) {
$x = " 0 $x " ;
}
}
if ( $upper ) {
$x = strtoupper ( $x );
}
2020-09-07 10:18:17 +02:00
return $x ;
2008-11-16 02:09:04 +01:00
}
/**
2011-07-04 10:38:51 +02:00
* Convert an hexadecimal string into a binary string
2011-08-31 14:24:47 +02:00
*
2012-02-04 14:39:47 +01:00
* @ param string $hexa Hexadecimal string to convert ( example : 'FF' )
* @ return string bin
2008-11-16 02:09:04 +01:00
*/
function hexbin ( $hexa )
{
2020-09-07 10:18:17 +02:00
$bin = '' ;
$strLength = dol_strlen ( $hexa );
2021-02-23 22:03:23 +01:00
for ( $i = 0 ; $i < $strLength ; $i ++ ) {
2020-09-07 10:18:17 +02:00
$bin .= str_pad ( decbin ( hexdec ( $hexa [ $i ])), 4 , '0' , STR_PAD_LEFT );
}
return $bin ;
2008-11-16 02:09:04 +01:00
}
/**
2011-07-04 10:38:51 +02:00
* Retourne le numero de la semaine par rapport a une date
2011-08-31 14:24:47 +02:00
*
2012-02-04 14:39:47 +01:00
* @ param string $time Date au format 'timestamp'
2016-06-23 20:19:43 +02:00
* @ return string Number of week
2008-11-16 02:09:04 +01:00
*/
function numero_semaine ( $time )
{
2020-09-07 10:18:17 +02:00
$stime = strftime ( '%Y-%m-%d' , $time );
2010-12-14 00:50:51 +01:00
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/i' , $stime , $reg )) {
2020-09-07 10:18:17 +02:00
// Date est au format 'YYYY-MM-DD' ou 'YYYY-MM-DD HH:MM:SS'
$annee = $reg [ 1 ];
$mois = $reg [ 2 ];
$jour = $reg [ 3 ];
}
2010-12-14 00:50:51 +01:00
2020-09-07 10:18:17 +02:00
/*
2021-02-23 22:03:23 +01:00
* Norme ISO - 8601 :
* - La semaine 1 de toute annee est celle qui contient le 4 janvier ou que la semaine 1 de toute annee est celle qui contient le 1 er jeudi de janvier .
* - La majorite des annees ont 52 semaines mais les annees qui commence un jeudi et les annees bissextiles commencant un mercredi en possede 53.
* - Le 1 er jour de la semaine est le Lundi
*/
2010-12-14 00:50:51 +01:00
2020-09-07 10:18:17 +02:00
// Definition du Jeudi de la semaine
2021-02-23 22:03:23 +01:00
if ( date ( " w " , mktime ( 12 , 0 , 0 , $mois , $jour , $annee )) == 0 ) { // Dimanche
$jeudiSemaine = mktime ( 12 , 0 , 0 , $mois , $jour , $annee ) - 3 * 24 * 60 * 60 ;
} elseif ( date ( " w " , mktime ( 12 , 0 , 0 , $mois , $jour , $annee )) < 4 ) { // du Lundi au Mercredi
$jeudiSemaine = mktime ( 12 , 0 , 0 , $mois , $jour , $annee ) + ( 4 - date ( " w " , mktime ( 12 , 0 , 0 , $mois , $jour , $annee ))) * 24 * 60 * 60 ;
} elseif ( date ( " w " , mktime ( 12 , 0 , 0 , $mois , $jour , $annee )) > 4 ) { // du Vendredi au Samedi
$jeudiSemaine = mktime ( 12 , 0 , 0 , $mois , $jour , $annee ) - ( date ( " w " , mktime ( 12 , 0 , 0 , $mois , $jour , $annee )) - 4 ) * 24 * 60 * 60 ;
} else { // Jeudi
$jeudiSemaine = mktime ( 12 , 0 , 0 , $mois , $jour , $annee );
}
2020-09-07 10:18:17 +02:00
// Definition du premier Jeudi de l'annee
2021-02-23 22:03:23 +01:00
if ( date ( " w " , mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine ))) == 0 ) { // Dimanche
2020-09-07 10:18:17 +02:00
$premierJeudiAnnee = mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine )) + 4 * 24 * 60 * 60 ;
2021-02-23 22:03:23 +01:00
} elseif ( date ( " w " , mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine ))) < 4 ) { // du Lundi au Mercredi
2020-09-07 10:18:17 +02:00
$premierJeudiAnnee = mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine )) + ( 4 - date ( " w " , mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine )))) * 24 * 60 * 60 ;
2021-02-23 22:03:23 +01:00
} elseif ( date ( " w " , mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine ))) > 4 ) { // du Vendredi au Samedi
2020-09-07 10:18:17 +02:00
$premierJeudiAnnee = mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine )) + ( 7 - ( date ( " w " , mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine ))) - 4 )) * 24 * 60 * 60 ;
} else // Jeudi
{
$premierJeudiAnnee = mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine ));
}
// Definition du numero de semaine: nb de jours entre "premier Jeudi de l'annee" et "Jeudi de la semaine";
$numeroSemaine = (
(
date ( " z " , mktime ( 12 , 0 , 0 , date ( " m " , $jeudiSemaine ), date ( " d " , $jeudiSemaine ), date ( " Y " , $jeudiSemaine )))
-
date ( " z " , mktime ( 12 , 0 , 0 , date ( " m " , $premierJeudiAnnee ), date ( " d " , $premierJeudiAnnee ), date ( " Y " , $premierJeudiAnnee )))
) / 7
) + 1 ;
// Cas particulier de la semaine 53
2021-02-23 22:03:23 +01:00
if ( $numeroSemaine == 53 ) {
2020-09-07 10:18:17 +02:00
// Les annees qui commence un Jeudi et les annees bissextiles commencant un Mercredi en possede 53
2021-02-23 22:03:23 +01:00
if ( date ( " w " , mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine ))) == 4 || ( date ( " w " , mktime ( 12 , 0 , 0 , 1 , 1 , date ( " Y " , $jeudiSemaine ))) == 3 && date ( " z " , mktime ( 12 , 0 , 0 , 12 , 31 , date ( " Y " , $jeudiSemaine ))) == 365 )) {
2020-09-07 10:18:17 +02:00
$numeroSemaine = 53 ;
} else {
$numeroSemaine = 1 ;
}
}
//echo $jour."-".$mois."-".$annee." (".date("d-m-Y",$premierJeudiAnnee)." - ".date("d-m-Y",$jeudiSemaine).") -> ".$numeroSemaine."<BR>";
return sprintf ( " %02d " , $numeroSemaine );
2008-11-16 02:09:04 +01:00
}
/**
2011-07-04 10:38:51 +02:00
* Convertit une masse d ' une unite vers une autre unite
2011-08-31 14:24:47 +02:00
*
2012-02-04 14:39:47 +01:00
* @ param float $weight Masse a convertir
2014-09-27 16:00:11 +02:00
* @ param int $from_unit Unite originale en puissance de 10
2012-02-04 14:39:47 +01:00
* @ param int $to_unit Nouvelle unite en puissance de 10
* @ return float Masse convertie
2008-11-16 02:09:04 +01:00
*/
2019-01-27 15:20:16 +01:00
function weight_convert ( $weight , & $from_unit , $to_unit )
2008-11-16 02:09:04 +01:00
{
2020-09-07 10:18:17 +02:00
/* Pour convertire 320 gr en Kg appeler
2021-02-23 22:03:23 +01:00
* $f = - 3
* weigh_convert ( 320 , $f , 0 ) retournera 0.32
*
*/
2022-11-19 22:15:58 +01:00
$weight = is_numeric ( $weight ) ? $weight : 0 ;
2021-02-23 22:03:23 +01:00
while ( $from_unit <> $to_unit ) {
if ( $from_unit > $to_unit ) {
2020-09-07 10:18:17 +02:00
$weight = $weight * 10 ;
$from_unit = $from_unit - 1 ;
$weight = weight_convert ( $weight , $from_unit , $to_unit );
}
2021-02-23 22:03:23 +01:00
if ( $from_unit < $to_unit ) {
2020-09-07 10:18:17 +02:00
$weight = $weight / 10 ;
$from_unit = $from_unit + 1 ;
$weight = weight_convert ( $weight , $from_unit , $to_unit );
}
}
return $weight ;
2008-11-16 02:09:04 +01:00
}
2009-01-07 11:57:36 +01:00
/**
2011-07-04 10:38:51 +02:00
* Save personnal parameter
2011-08-31 14:24:47 +02:00
*
2012-02-04 14:39:47 +01:00
* @ param DoliDB $db Handler database
* @ param Conf $conf Object conf
2014-10-04 17:20:17 +02:00
* @ param User $user Object user
2023-01-07 04:05:59 +01:00
* @ param array $tab Array ( key => value ) with all parameters to save / update
2012-02-04 14:39:47 +01:00
* @ return int < 0 if KO , > 0 if OK
2012-01-15 19:07:01 +01:00
*
2019-03-11 01:01:15 +01:00
* @ see dolibarr_get_const (), dolibarr_set_const (), dolibarr_del_const ()
2009-01-07 11:57:36 +01:00
*/
2009-04-27 22:37:50 +02:00
function dol_set_user_param ( $db , $conf , & $user , $tab )
2009-01-07 11:57:36 +01:00
{
2020-09-07 10:18:17 +02:00
// Verification parametres
2021-02-23 22:03:23 +01:00
if ( count ( $tab ) < 1 ) {
return - 1 ;
}
2020-09-07 10:18:17 +02:00
$db -> begin ();
// We remove old parameters for all keys in $tab
$sql = " DELETE FROM " . MAIN_DB_PREFIX . " user_param " ;
2021-08-27 18:18:50 +02:00
$sql .= " WHERE fk_user = " . (( int ) $user -> id );
$sql .= " AND entity = " . (( int ) $conf -> entity );
2020-09-07 10:18:17 +02:00
$sql .= " AND param in ( " ;
$i = 0 ;
2021-02-23 22:03:23 +01:00
foreach ( $tab as $key => $value ) {
if ( $i > 0 ) {
$sql .= ',' ;
}
2020-09-07 10:18:17 +02:00
$sql .= " ' " . $db -> escape ( $key ) . " ' " ;
$i ++ ;
}
$sql .= " ) " ;
dol_syslog ( " functions2.lib::dol_set_user_param " , LOG_DEBUG );
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( ! $resql ) {
2020-09-07 10:18:17 +02:00
dol_print_error ( $db );
$db -> rollback ();
return - 1 ;
}
2021-02-23 22:03:23 +01:00
foreach ( $tab as $key => $value ) {
2020-09-07 10:18:17 +02:00
// Set new parameters
2021-02-23 22:03:23 +01:00
if ( $value ) {
2020-09-07 10:18:17 +02:00
$sql = " INSERT INTO " . MAIN_DB_PREFIX . " user_param(fk_user,entity,param,value) " ;
2021-08-27 22:42:04 +02:00
$sql .= " VALUES ( " . (( int ) $user -> id ) . " , " . (( int ) $conf -> entity ) . " , " ;
2020-09-07 10:18:17 +02:00
$sql .= " ' " . $db -> escape ( $key ) . " ',' " . $db -> escape ( $value ) . " ') " ;
dol_syslog ( " functions2.lib::dol_set_user_param " , LOG_DEBUG );
$result = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( ! $result ) {
2020-09-07 10:18:17 +02:00
dol_print_error ( $db );
$db -> rollback ();
return - 1 ;
}
$user -> conf -> $key = $value ;
//print "key=".$key." user->conf->key=".$user->conf->$key;
} else {
unset ( $user -> conf -> $key );
}
}
$db -> commit ();
return 1 ;
2009-01-07 11:57:36 +01:00
}
/**
2011-07-04 10:38:51 +02:00
* Returns formated reduction
2011-08-31 14:24:47 +02:00
*
2012-02-04 14:39:47 +01:00
* @ param int $reduction Reduction percentage
* @ param Translate $langs Output language
* @ return string Formated reduction
2009-01-07 11:57:36 +01:00
*/
2019-01-27 15:20:16 +01:00
function dol_print_reduction ( $reduction , $langs )
2009-01-07 11:57:36 +01:00
{
2020-09-07 10:18:17 +02:00
$string = '' ;
2021-02-23 22:03:23 +01:00
if ( $reduction == 100 ) {
2020-09-07 10:18:17 +02:00
$string = $langs -> transnoentities ( " Offered " );
} else {
$string = vatrate ( $reduction , true );
}
return $string ;
2009-01-07 11:57:36 +01:00
}
2009-03-09 22:59:29 +01:00
/**
2011-10-05 22:54:39 +02:00
* Return OS version .
2015-07-27 17:09:16 +02:00
* Note that PHP_OS returns only OS ( not version ) and OS PHP was built on , not necessarly OS PHP runs on .
2011-08-31 14:24:47 +02:00
*
2019-11-27 11:34:10 +01:00
* @ param string $option Option string
* @ return string OS version
2009-03-09 22:59:29 +01:00
*/
2019-11-27 11:34:10 +01:00
function version_os ( $option = '' )
2009-03-09 22:59:29 +01:00
{
2021-02-23 22:03:23 +01:00
if ( $option == 'smr' ) {
$osversion = php_uname ( 's' ) . ' ' . php_uname ( 'm' ) . ' ' . php_uname ( 'r' );
} else {
$osversion = php_uname ();
}
2020-09-07 10:18:17 +02:00
return $osversion ;
2009-03-09 22:59:29 +01:00
}
/**
2011-08-31 14:24:47 +02:00
* Return PHP version
*
* @ return string PHP version
2021-08-04 20:07:12 +02:00
* @ see versionphparray (), versioncompare ()
2009-03-09 22:59:29 +01:00
*/
function version_php ()
{
2020-09-07 10:18:17 +02:00
return phpversion ();
2009-03-09 22:59:29 +01:00
}
/**
2011-08-31 14:24:47 +02:00
* Return Dolibarr version
*
* @ return string Dolibarr version
2021-08-04 20:07:12 +02:00
* @ see versiondolibarrarray (), versioncompare ()
2009-03-09 22:59:29 +01:00
*/
function version_dolibarr ()
{
2020-09-07 10:18:17 +02:00
return DOL_VERSION ;
2009-03-09 22:59:29 +01:00
}
/**
2011-08-31 14:24:47 +02:00
* Return web server version
*
* @ return string Web server version
2009-03-09 22:59:29 +01:00
*/
function version_webserver ()
{
2020-09-07 10:18:17 +02:00
return $_SERVER [ " SERVER_SOFTWARE " ];
2009-03-09 22:59:29 +01:00
}
2010-02-27 11:11:00 +01:00
2010-02-27 23:53:27 +01:00
/**
2011-08-31 14:24:47 +02:00
* Return list of activated modules usable for document generation
*
2012-02-04 14:39:47 +01:00
* @ param DoliDB $db Database handler
* @ param string $type Type of models ( company , invoice , ... )
* @ param int $maxfilenamelength Max length of value to show
2020-10-24 09:32:39 +02:00
* @ return array | int 0 if no module is activated , or array ( key => label ) . For modules that need directory scan , key is completed with " :filename " .
2010-02-27 23:53:27 +01:00
*/
2019-01-27 15:20:16 +01:00
function getListOfModels ( $db , $type , $maxfilenamelength = 0 )
2010-02-27 23:53:27 +01:00
{
2020-09-07 10:18:17 +02:00
global $conf , $langs ;
$liste = array ();
$found = 0 ;
$dirtoscan = '' ;
$sql = " SELECT nom as id, nom as doc_template_name, libelle as label, description as description " ;
$sql .= " FROM " . MAIN_DB_PREFIX . " document_model " ;
$sql .= " WHERE type = ' " . $db -> escape ( $type ) . " ' " ;
$sql .= " AND entity IN (0, " . $conf -> entity . " ) " ;
$sql .= " ORDER BY description DESC " ;
dol_syslog ( '/core/lib/function2.lib.php::getListOfModels' , LOG_DEBUG );
2023-03-31 23:31:20 +02:00
$resql_models = $db -> query ( $sql );
if ( $resql_models ) {
$num = $db -> num_rows ( $resql_models );
2020-09-07 10:18:17 +02:00
$i = 0 ;
2021-02-23 22:03:23 +01:00
while ( $i < $num ) {
2020-09-07 10:18:17 +02:00
$found = 1 ;
2023-03-31 23:31:20 +02:00
$obj = $db -> fetch_object ( $resql_models );
2020-09-07 10:18:17 +02:00
// If this generation module needs to scan a directory, then description field is filled
// with the constant that contains list of directories to scan (COMPANY_ADDON_PDF_ODT_PATH, ...).
2021-02-23 22:03:23 +01:00
if ( ! empty ( $obj -> description )) { // A list of directories to scan is defined
2020-09-07 10:18:17 +02:00
include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php' ;
$const = $obj -> description ;
//irtoscan.=($dirtoscan?',':'').preg_replace('/[\r\n]+/',',',trim($conf->global->$const));
$dirtoscan = preg_replace ( '/[\r\n]+/' , ',' , trim ( $conf -> global -> $const ));
$listoffiles = array ();
// Now we add models found in directories scanned
$listofdir = explode ( ',' , $dirtoscan );
2021-02-23 22:03:23 +01:00
foreach ( $listofdir as $key => $tmpdir ) {
2020-09-07 10:18:17 +02:00
$tmpdir = trim ( $tmpdir );
$tmpdir = preg_replace ( '/DOL_DATA_ROOT/' , DOL_DATA_ROOT , $tmpdir );
2021-02-23 22:03:23 +01:00
if ( ! $tmpdir ) {
2021-03-01 20:37:16 +01:00
unset ( $listofdir [ $key ]);
continue ;
2021-02-23 22:03:23 +01:00
}
if ( is_dir ( $tmpdir )) {
2020-09-07 10:18:17 +02:00
// all type of template is allowed
$tmpfiles = dol_dir_list ( $tmpdir , 'files' , 0 , '' , '' , 'name' , SORT_ASC , 0 );
2021-02-23 22:03:23 +01:00
if ( count ( $tmpfiles )) {
$listoffiles = array_merge ( $listoffiles , $tmpfiles );
}
2020-09-07 10:18:17 +02:00
}
}
2021-02-23 22:03:23 +01:00
if ( count ( $listoffiles )) {
foreach ( $listoffiles as $record ) {
2020-09-07 10:18:17 +02:00
$max = ( $maxfilenamelength ? $maxfilenamelength : 28 );
$liste [ $obj -> id . ':' . $record [ 'fullname' ]] = dol_trunc ( $record [ 'name' ], $max , 'middle' );
}
} else {
$liste [ 0 ] = $obj -> label . ': ' . $langs -> trans ( " None " );
}
} else {
2021-02-23 22:03:23 +01:00
if ( $type == 'member' && $obj -> doc_template_name == 'standard' ) { // Special case, if member template, we add variant per format
2020-09-07 10:18:17 +02:00
global $_Avery_Labels ;
include_once DOL_DOCUMENT_ROOT . '/core/lib/format_cards.lib.php' ;
2021-02-23 22:03:23 +01:00
foreach ( $_Avery_Labels as $key => $val ) {
2020-09-07 10:18:17 +02:00
$liste [ $obj -> id . ':' . $key ] = ( $obj -> label ? $obj -> label : $obj -> doc_template_name ) . ' ' . $val [ 'name' ];
}
2020-10-24 09:32:39 +02:00
} else {
2020-10-27 19:46:07 +01:00
// Common usage
2020-09-07 10:18:17 +02:00
$liste [ $obj -> id ] = $obj -> label ? $obj -> label : $obj -> doc_template_name ;
}
}
$i ++ ;
}
} else {
dol_print_error ( $db );
return - 1 ;
}
2021-02-23 22:03:23 +01:00
if ( $found ) {
return $liste ;
} else {
return 0 ;
}
2010-02-27 23:53:27 +01:00
}
2010-04-13 21:56:24 +02:00
/**
2011-01-05 18:43:58 +01:00
* This function evaluates a string that should be a valid IPv4
2016-08-28 01:58:11 +02:00
* Note : For ip 169.254 . 0.0 , it returns 0 with some PHP ( 5.6 . 24 ) and 2 with some minor patchs of PHP ( 5.6 . 25 ) . See https :// github . com / php / php - src / pull / 1954.
2017-06-06 07:57:03 +02:00
*
2014-07-17 21:19:03 +02:00
* @ param string $ip IP Address
2014-07-26 14:16:09 +02:00
* @ return int 0 if not valid or reserved range , 1 if valid and public IP , 2 if valid and private range IP
2010-04-13 21:56:24 +02:00
*/
function is_ip ( $ip )
{
2014-07-26 14:16:09 +02:00
// First we test if it is a valid IPv4
2014-07-17 21:12:50 +02:00
if ( filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 )) {
2014-07-26 14:16:09 +02:00
// Then we test if it is a private range
2021-02-23 22:03:23 +01:00
if ( ! filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_NO_PRIV_RANGE )) {
return 2 ;
}
2014-07-26 14:16:09 +02:00
// Then we test if it is a reserved range
2021-02-23 22:03:23 +01:00
if ( ! filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_NO_RES_RANGE )) {
return 0 ;
}
2014-07-17 21:12:50 +02:00
2014-07-26 14:16:09 +02:00
return 1 ;
2014-07-17 21:12:50 +02:00
}
return 0 ;
2010-04-13 21:56:24 +02:00
}
2011-01-05 18:43:58 +01:00
/**
* Build a login from lastname , firstname
2011-08-31 14:24:47 +02:00
*
2012-02-04 14:39:47 +01:00
* @ param string $lastname Lastname
* @ param string $firstname Firstname
* @ return string Login
2011-01-05 18:43:58 +01:00
*/
2019-01-27 15:20:16 +01:00
function dol_buildlogin ( $lastname , $firstname )
2011-01-05 18:43:58 +01:00
{
2020-11-04 13:33:52 +01:00
global $conf ;
//$conf->global->MAIN_BUILD_LOGIN_RULE = 'f.lastname';
if ( ! empty ( $conf -> global -> MAIN_BUILD_LOGIN_RULE ) && $conf -> global -> MAIN_BUILD_LOGIN_RULE == 'f.lastname' ) { // f.lastname
$login = strtolower ( dol_string_unaccent ( dol_trunc ( $firstname , 1 , 'right' , 'UTF-8' , 1 )));
$login .= ( $login ? '.' : '' );
$login .= strtolower ( dol_string_unaccent ( $lastname ));
$login = dol_string_nospecial ( $login , '' ); // For special names
} else { // firstname.lastname
$login = strtolower ( dol_string_unaccent ( $firstname ));
$login .= ( $login ? '.' : '' );
$login .= strtolower ( dol_string_unaccent ( $lastname ));
$login = dol_string_nospecial ( $login , '' ); // For special names
}
// TODO Add a hook to allow external modules to suggest new rules
2020-09-07 10:18:17 +02:00
return $login ;
2011-04-03 20:02:18 +02:00
}
/**
* Return array to use for SoapClient constructor
2011-08-31 14:24:47 +02:00
*
2016-08-11 15:23:00 +02:00
* @ return array
2011-04-03 20:02:18 +02:00
*/
function getSoapParams ()
{
2020-09-07 10:18:17 +02:00
global $conf ;
$params = array ();
$proxyuse = ( empty ( $conf -> global -> MAIN_PROXY_USE ) ? false : true );
$proxyhost = ( empty ( $conf -> global -> MAIN_PROXY_USE ) ? false : $conf -> global -> MAIN_PROXY_HOST );
$proxyport = ( empty ( $conf -> global -> MAIN_PROXY_USE ) ? false : $conf -> global -> MAIN_PROXY_PORT );
$proxyuser = ( empty ( $conf -> global -> MAIN_PROXY_USE ) ? false : $conf -> global -> MAIN_PROXY_USER );
$proxypass = ( empty ( $conf -> global -> MAIN_PROXY_USE ) ? false : $conf -> global -> MAIN_PROXY_PASS );
$timeout = ( empty ( $conf -> global -> MAIN_USE_CONNECT_TIMEOUT ) ? 10 : $conf -> global -> MAIN_USE_CONNECT_TIMEOUT ); // Connection timeout
$response_timeout = ( empty ( $conf -> global -> MAIN_USE_RESPONSE_TIMEOUT ) ? 30 : $conf -> global -> MAIN_USE_RESPONSE_TIMEOUT ); // Response timeout
//print extension_loaded('soap');
2021-02-23 22:03:23 +01:00
if ( $proxyuse ) {
2020-09-07 10:18:17 +02:00
$params = array ( 'connection_timeout' => $timeout ,
'response_timeout' => $response_timeout ,
'proxy_use' => 1 ,
'proxy_host' => $proxyhost ,
'proxy_port' => $proxyport ,
'proxy_login' => $proxyuser ,
'proxy_password' => $proxypass ,
'trace' => 1
);
} else {
$params = array ( 'connection_timeout' => $timeout ,
'response_timeout' => $response_timeout ,
'proxy_use' => 0 ,
'proxy_host' => false ,
'proxy_port' => false ,
'proxy_login' => false ,
'proxy_password' => false ,
'trace' => 1
);
}
return $params ;
2011-04-03 20:02:18 +02:00
}
2013-06-16 23:15:20 +02:00
2013-06-19 09:26:20 +02:00
/**
2018-07-15 20:09:51 +02:00
* Return link url to an object
2013-06-19 09:26:20 +02:00
*
* @ param int $objectid Id of record
2020-01-07 13:48:44 +01:00
* @ param string $objecttype Type of object ( 'invoice' , 'order' , 'expedition_bon' , 'myobject@mymodule' , ... )
2013-06-19 09:26:20 +02:00
* @ param int $withpicto Picto to show
* @ param string $option More options
* @ return string URL of link to object id / type
*/
2019-01-27 15:20:16 +01:00
function dolGetElementUrl ( $objectid , $objecttype , $withpicto = 0 , $option = '' )
2013-06-19 09:26:20 +02:00
{
2018-08-30 17:01:22 +02:00
global $db , $conf , $langs ;
2013-06-16 23:15:20 +02:00
2019-11-13 19:37:08 +01:00
$ret = '' ;
2020-01-07 13:48:44 +01:00
$regs = array ();
2013-06-19 09:26:20 +02:00
2020-07-24 11:53:44 +02:00
// If we ask a resource form external module (instead of default path)
2020-01-07 13:48:44 +01:00
if ( preg_match ( '/^([^@]+)@([^@]+)$/i' , $objecttype , $regs )) {
$myobject = $regs [ 1 ];
$module = $regs [ 2 ];
2021-02-23 22:03:23 +01:00
} else {
2020-07-24 11:53:44 +02:00
// Parse $objecttype (ex: project_task)
$module = $myobject = $objecttype ;
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/^([^_]+)_([^_]+)/i' , $objecttype , $regs )) {
2020-07-24 11:53:44 +02:00
$module = $regs [ 1 ];
$myobject = $regs [ 2 ];
}
2013-06-19 09:26:20 +02:00
}
2019-10-12 12:31:35 +02:00
// Generic case for $classpath
2020-01-07 13:48:44 +01:00
$classpath = $module . '/class' ;
2013-06-19 09:26:20 +02:00
2019-10-12 12:31:35 +02:00
// Special cases, to work with non standard path
2013-06-19 09:26:20 +02:00
if ( $objecttype == 'facture' || $objecttype == 'invoice' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'bills' );
2013-09-11 14:18:56 +02:00
$classpath = 'compta/facture/class' ;
2020-01-10 00:03:10 +01:00
$module = 'facture' ;
$myobject = 'facture' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'commande' || $objecttype == 'order' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'orders' );
2013-09-11 14:18:56 +02:00
$classpath = 'commande/class' ;
2020-01-10 00:03:10 +01:00
$module = 'commande' ;
$myobject = 'commande' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'propal' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'propal' );
2013-06-19 09:26:20 +02:00
$classpath = 'comm/propal/class' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'supplier_proposal' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'supplier_proposal' );
2015-11-15 18:23:42 +01:00
$classpath = 'supplier_proposal/class' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'shipping' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'sendings' );
2013-09-11 14:18:56 +02:00
$classpath = 'expedition/class' ;
2020-01-07 13:48:44 +01:00
$myobject = 'expedition' ;
2013-08-09 13:48:44 +02:00
$module = 'expedition_bon' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'delivery' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'deliveries' );
2020-10-06 12:05:24 +02:00
$classpath = 'delivery/class' ;
$myobject = 'delivery' ;
2020-10-06 15:57:50 +02:00
$module = 'delivery_note' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'contract' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'contracts' );
2013-09-11 14:18:56 +02:00
$classpath = 'contrat/class' ;
2020-01-10 00:03:10 +01:00
$module = 'contrat' ;
$myobject = 'contrat' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'member' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'members' );
2013-09-11 14:18:56 +02:00
$classpath = 'adherents/class' ;
2020-01-10 00:03:10 +01:00
$module = 'adherent' ;
$myobject = 'adherent' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'cabinetmed_cons' ) {
2013-09-11 14:18:56 +02:00
$classpath = 'cabinetmed/class' ;
2020-01-10 00:03:10 +01:00
$module = 'cabinetmed' ;
$myobject = 'cabinetmedcons' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'fichinter' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'interventions' );
2013-09-11 14:18:56 +02:00
$classpath = 'fichinter/class' ;
2020-01-10 00:03:10 +01:00
$module = 'ficheinter' ;
$myobject = 'fichinter' ;
2021-09-19 00:50:23 +02:00
} elseif ( $objecttype == 'project' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'projects' );
2021-09-19 00:50:23 +02:00
$classpath = 'projet/class' ;
$module = 'projet' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'task' ) {
2021-11-11 18:23:34 +01:00
$langs -> load ( 'projects' );
2017-09-13 15:12:54 +02:00
$classpath = 'projet/class' ;
2020-01-10 00:03:10 +01:00
$module = 'projet' ;
$myobject = 'task' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'stock' ) {
2018-05-24 12:16:04 +02:00
$classpath = 'product/stock/class' ;
2020-01-10 00:03:10 +01:00
$module = 'stock' ;
$myobject = 'stock' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'inventory' ) {
2019-10-12 12:31:35 +02:00
$classpath = 'product/inventory/class' ;
2020-01-10 00:03:10 +01:00
$module = 'stock' ;
$myobject = 'inventory' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'mo' ) {
2020-01-07 20:28:21 +01:00
$classpath = 'mrp/class' ;
2020-01-10 00:03:10 +01:00
$module = 'mrp' ;
$myobject = 'mo' ;
2021-03-01 00:19:52 +01:00
} elseif ( $objecttype == 'productlot' ) {
2021-02-25 15:47:14 +01:00
$classpath = 'product/stock/class' ;
$module = 'stock' ;
$myobject = 'productlot' ;
}
2013-06-19 09:26:20 +02:00
2019-10-12 12:31:35 +02:00
// Generic case for $classfile and $classname
2021-03-01 20:37:16 +01:00
$classfile = strtolower ( $myobject );
$classname = ucfirst ( $myobject );
2020-07-24 11:53:44 +02:00
//print "objecttype=".$objecttype." module=".$module." subelement=".$subelement." classfile=".$classfile." classname=".$classname." classpath=".$classpath;
2019-10-12 12:31:35 +02:00
2013-06-19 09:26:20 +02:00
if ( $objecttype == 'invoice_supplier' ) {
2013-09-11 14:18:56 +02:00
$classfile = 'fournisseur.facture' ;
2019-11-13 19:37:08 +01:00
$classname = 'FactureFournisseur' ;
2013-08-09 13:48:44 +02:00
$classpath = 'fourn/class' ;
2019-11-13 19:37:08 +01:00
$module = 'fournisseur' ;
2020-05-21 15:05:19 +02:00
} elseif ( $objecttype == 'order_supplier' ) {
2013-09-11 14:18:56 +02:00
$classfile = 'fournisseur.commande' ;
2019-11-13 19:37:08 +01:00
$classname = 'CommandeFournisseur' ;
2013-08-09 13:48:44 +02:00
$classpath = 'fourn/class' ;
2019-11-13 19:37:08 +01:00
$module = 'fournisseur' ;
2021-02-23 22:03:23 +01:00
} elseif ( $objecttype == 'supplier_proposal' ) {
2020-10-20 16:37:15 +02:00
$classfile = 'supplier_proposal' ;
$classname = 'SupplierProposal' ;
$classpath = 'supplier_proposal/class' ;
$module = 'supplier_proposal' ;
2021-02-23 22:03:23 +01:00
} elseif ( $objecttype == 'stock' ) {
2018-05-24 12:16:04 +02:00
$classpath = 'product/stock/class' ;
2019-11-13 19:37:08 +01:00
$classfile = 'entrepot' ;
$classname = 'Entrepot' ;
2022-05-13 10:46:02 +02:00
} elseif ( $objecttype == 'facturerec' ) {
$classpath = 'compta/facture/class' ;
$classfile = 'facture-rec' ;
$classname = 'FactureRec' ;
2022-11-30 15:17:27 +01:00
$module = 'facture' ;
} elseif ( $objecttype == 'mailing' ) {
$classpath = 'comm/mailing/class' ;
$classfile = 'mailing' ;
$classname = 'Mailing' ;
2018-05-24 12:16:04 +02:00
}
2020-01-07 13:48:44 +01:00
2022-09-25 23:06:42 +02:00
if ( isModEnabled ( $module )) {
2019-11-13 19:37:08 +01:00
$res = dol_include_once ( '/' . $classpath . '/' . $classfile . '.class.php' );
2021-02-23 22:03:23 +01:00
if ( $res ) {
if ( class_exists ( $classname )) {
2018-05-24 12:16:04 +02:00
$object = new $classname ( $db );
2019-11-13 19:37:08 +01:00
$res = $object -> fetch ( $objectid );
2018-07-12 18:27:09 +02:00
if ( $res > 0 ) {
2019-11-13 19:37:08 +01:00
$ret = $object -> getNomUrl ( $withpicto , $option );
} elseif ( $res == 0 ) {
$ret = $langs -> trans ( 'Deleted' );
2018-07-12 18:27:09 +02:00
}
2018-05-24 12:16:04 +02:00
unset ( $object );
2021-02-23 22:03:23 +01:00
} else {
dol_syslog ( " Class with classname " . $classname . " is unknown even after the include " , LOG_ERR );
}
2013-06-16 23:15:20 +02:00
}
}
2013-06-19 09:26:20 +02:00
return $ret ;
2013-06-24 20:02:02 +02:00
}
2014-04-26 21:36:58 +02:00
/**
* Clean corrupted tree ( orphelins linked to a not existing parent ), record linked to themself and child - parent loop
*
2014-04-26 22:23:46 +02:00
* @ param DoliDB $db Database handler
2014-04-26 21:36:58 +02:00
* @ param string $tabletocleantree Table to clean
* @ param string $fieldfkparent Field name that contains id of parent
* @ return int Nb of records fixed / deleted
*/
function cleanCorruptedTree ( $db , $tabletocleantree , $fieldfkparent )
{
2019-11-13 19:37:08 +01:00
$totalnb = 0 ;
$listofid = array ();
$listofparentid = array ();
2014-04-26 21:36:58 +02:00
// Get list of all id in array listofid and all parents in array listofparentid
2021-08-28 01:45:53 +02:00
$sql = " SELECT rowid, " . $fieldfkparent . " as parent_id FROM " . MAIN_DB_PREFIX . $tabletocleantree ;
2014-04-26 21:36:58 +02:00
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( $resql ) {
2014-04-26 21:36:58 +02:00
$num = $db -> num_rows ( $resql );
$i = 0 ;
2021-02-23 22:03:23 +01:00
while ( $i < $num ) {
2014-04-26 21:36:58 +02:00
$obj = $db -> fetch_object ( $resql );
2019-11-13 19:37:08 +01:00
$listofid [] = $obj -> rowid ;
2021-02-23 22:03:23 +01:00
if ( $obj -> parent_id > 0 ) {
$listofparentid [ $obj -> rowid ] = $obj -> parent_id ;
}
2014-04-26 21:36:58 +02:00
$i ++ ;
}
2020-05-21 15:05:19 +02:00
} else {
2014-04-26 21:36:58 +02:00
dol_print_error ( $db );
}
2021-02-23 22:03:23 +01:00
if ( count ( $listofid )) {
2014-04-26 21:36:58 +02:00
print 'Code requested to clean tree (may be to solve data corruption), so we check/clean orphelins and loops.' . " <br> \n " ;
// Check loops on each other
2019-11-13 19:37:08 +01:00
$sql = " UPDATE " . MAIN_DB_PREFIX . $tabletocleantree . " SET " . $fieldfkparent . " = 0 WHERE " . $fieldfkparent . " = rowid " ; // So we update only records linked to themself
2014-04-26 21:36:58 +02:00
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( $resql ) {
2019-11-13 19:37:08 +01:00
$nb = $db -> affected_rows ( $sql );
2021-02-23 22:03:23 +01:00
if ( $nb > 0 ) {
2014-04-26 21:36:58 +02:00
print '<br>Some record that were parent of themself were cleaned.' ;
}
2019-11-13 19:37:08 +01:00
$totalnb += $nb ;
2014-04-26 21:36:58 +02:00
}
//else dol_print_error($db);
// Check other loops
2019-11-13 19:37:08 +01:00
$listofidtoclean = array ();
2021-02-23 22:03:23 +01:00
foreach ( $listofparentid as $id => $pid ) {
2014-04-26 21:36:58 +02:00
// Check depth
//print 'Analyse record id='.$id.' with parent '.$pid.'<br>';
2021-03-01 20:37:16 +01:00
$cursor = $id ;
$arrayidparsed = array (); // We start from child $id
2021-02-23 22:03:23 +01:00
while ( $cursor > 0 ) {
2019-11-13 19:37:08 +01:00
$arrayidparsed [ $cursor ] = 1 ;
2021-02-23 22:03:23 +01:00
if ( $arrayidparsed [ $listofparentid [ $cursor ]]) { // We detect a loop. A record with a parent that was already into child
2014-04-26 21:36:58 +02:00
print 'Found a loop between id ' . $id . ' - ' . $cursor . '<br>' ;
unset ( $arrayidparsed );
2019-11-13 19:37:08 +01:00
$listofidtoclean [ $cursor ] = $id ;
2014-04-26 21:36:58 +02:00
break ;
}
2019-11-13 19:37:08 +01:00
$cursor = $listofparentid [ $cursor ];
2014-04-26 21:36:58 +02:00
}
2021-02-23 22:03:23 +01:00
if ( count ( $listofidtoclean )) {
break ;
}
2014-04-26 21:36:58 +02:00
}
$sql = " UPDATE " . MAIN_DB_PREFIX . $tabletocleantree ;
2019-11-13 19:37:08 +01:00
$sql .= " SET " . $fieldfkparent . " = 0 " ;
2021-03-22 11:30:18 +01:00
$sql .= " WHERE rowid IN ( " . $db -> sanitize ( join ( ',' , $listofidtoclean )) . " ) " ; // So we update only records detected wrong
2014-04-26 21:36:58 +02:00
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( $resql ) {
2019-11-13 19:37:08 +01:00
$nb = $db -> affected_rows ( $sql );
2021-02-23 22:03:23 +01:00
if ( $nb > 0 ) {
2014-04-26 21:36:58 +02:00
// Removed orphelins records
print '<br>Some records were detected to have parent that is a child, we set them as root record for id: ' ;
2019-01-27 11:55:16 +01:00
print join ( ',' , $listofidtoclean );
2014-04-26 21:36:58 +02:00
}
2019-11-13 19:37:08 +01:00
$totalnb += $nb ;
2014-04-26 21:36:58 +02:00
}
//else dol_print_error($db);
// Check and clean orphelins
$sql = " UPDATE " . MAIN_DB_PREFIX . $tabletocleantree ;
2019-11-13 19:37:08 +01:00
$sql .= " SET " . $fieldfkparent . " = 0 " ;
2021-03-22 11:30:18 +01:00
$sql .= " WHERE " . $fieldfkparent . " NOT IN ( " . $db -> sanitize ( join ( ',' , $listofid ), 1 ) . " ) " ; // So we update only records linked to a non existing parent
2014-04-26 21:36:58 +02:00
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( $resql ) {
2019-11-13 19:37:08 +01:00
$nb = $db -> affected_rows ( $sql );
2021-02-23 22:03:23 +01:00
if ( $nb > 0 ) {
2014-04-26 21:36:58 +02:00
// Removed orphelins records
print '<br>Some orphelins were found and modified to be parent so records are visible again for id: ' ;
2019-01-27 11:55:16 +01:00
print join ( ',' , $listofid );
2014-04-26 21:36:58 +02:00
}
2019-11-13 19:37:08 +01:00
$totalnb += $nb ;
2014-04-26 21:36:58 +02:00
}
//else dol_print_error($db);
print '<br>We fixed ' . $totalnb . ' record(s). Some records may still be corrupted. New check may be required.' ;
return $totalnb ;
}
}
2014-03-15 16:29:33 +01:00
2014-12-08 19:05:22 +01:00
/**
2015-06-26 16:21:09 +02:00
* Convert an array with RGB value into hex RGB value .
* This is the opposite function of colorStringToArray
2014-12-08 19:05:22 +01:00
*
* @ param array $arraycolor Array
2015-06-12 14:37:27 +02:00
* @ param string $colorifnotfound Color code to return if entry not defined or not a RGB format
2015-06-26 16:21:09 +02:00
* @ return string RGB hex value ( without # before). For example: 'FF00FF', '01FF02'
2019-08-18 04:56:48 +02:00
* @ see colorStringToArray (), colorHexToRgb ()
2014-12-08 19:05:22 +01:00
*/
2019-01-27 15:20:16 +01:00
function colorArrayToHex ( $arraycolor , $colorifnotfound = '888888' )
2014-12-08 19:05:22 +01:00
{
2021-02-23 22:03:23 +01:00
if ( ! is_array ( $arraycolor )) {
return $colorifnotfound ;
}
if ( empty ( $arraycolor )) {
return $colorifnotfound ;
}
2019-01-27 11:55:16 +01:00
return sprintf ( " %02s " , dechex ( $arraycolor [ 0 ])) . sprintf ( " %02s " , dechex ( $arraycolor [ 1 ])) . sprintf ( " %02s " , dechex ( $arraycolor [ 2 ]));
2014-12-08 19:05:22 +01:00
}
/**
2015-06-12 14:37:27 +02:00
* Convert a string RGB value ( 'FFFFFF' , '255,255,255' ) into an array RGB array ( 255 , 255 , 255 ) .
2015-06-26 16:21:09 +02:00
* This is the opposite function of colorArrayToHex .
2015-06-12 14:37:27 +02:00
* If entry is already an array , return it .
2014-12-08 19:05:22 +01:00
*
* @ param string $stringcolor String with hex ( FFFFFF ) or comma RGB ( '255,255,255' )
2015-06-12 14:37:27 +02:00
* @ param array $colorifnotfound Color code array to return if entry not defined
2019-03-12 09:09:26 +01:00
* @ return array RGB hex value ( without # before). For example: FF00FF
2019-08-18 04:56:48 +02:00
* @ see colorArrayToHex (), colorHexToRgb ()
2014-12-08 19:05:22 +01:00
*/
2019-11-13 19:37:08 +01:00
function colorStringToArray ( $stringcolor , $colorifnotfound = array ( 88 , 88 , 88 ))
2014-12-08 19:05:22 +01:00
{
2021-02-23 22:03:23 +01:00
if ( is_array ( $stringcolor )) {
return $stringcolor ; // If already into correct output format, we return as is
}
2019-11-13 19:37:08 +01:00
$reg = array ();
$tmp = preg_match ( '/^#?([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])$/' , $stringcolor , $reg );
2021-02-23 22:03:23 +01:00
if ( ! $tmp ) {
2019-11-13 19:37:08 +01:00
$tmp = explode ( ',' , $stringcolor );
2021-02-23 22:03:23 +01:00
if ( count ( $tmp ) < 3 ) {
return $colorifnotfound ;
}
2014-12-08 19:05:22 +01:00
return $tmp ;
}
2019-11-13 19:37:08 +01:00
return array ( hexdec ( $reg [ 1 ]), hexdec ( $reg [ 2 ]), hexdec ( $reg [ 3 ]));
2014-12-08 19:05:22 +01:00
}
2019-02-26 17:44:16 +01:00
/**
2019-08-18 04:56:48 +02:00
* @ param string $color the color you need to valid
* @ param boolean $allow_white in case of white isn ' t valid
2019-02-26 17:44:16 +01:00
* @ return boolean
*/
2019-03-07 15:49:16 +01:00
function colorValidateHex ( $color , $allow_white = true )
2019-02-26 17:44:16 +01:00
{
2021-02-23 22:03:23 +01:00
if ( ! $allow_white && ( $color === '#fff' || $color === '#ffffff' )) {
return false ;
}
2019-03-22 14:32:15 +01:00
2021-02-23 22:03:23 +01:00
if ( preg_match ( '/^#[a-f0-9]{6}$/i' , $color )) { //hex color is valid
2020-09-07 10:18:17 +02:00
return true ;
}
return false ;
2019-02-26 17:44:16 +01:00
}
/**
2019-08-18 03:42:38 +02:00
* Change color to make it less aggressive ( ratio is negative ) or more aggressive ( ratio is positive )
*
2019-10-23 20:12:29 +02:00
* @ param string $hex Color in hex ( '#AA1122' or 'AA1122' or '#a12' or 'a12' )
* @ param integer $ratio Default =- 50. Note : 0 = Component color is unchanged , - 100 = Component color become 88 , + 100 = Component color become 00 or FF
2019-10-24 21:46:52 +02:00
* @ param integer $brightness Default = 0. Adjust brightness . - 100 = Decrease brightness by 100 % , + 100 = Increase of 100 %.
2019-08-18 03:42:38 +02:00
* @ return string New string of color
* @ see colorAdjustBrightness ()
*/
2019-10-23 20:12:29 +02:00
function colorAgressiveness ( $hex , $ratio = - 50 , $brightness = 0 )
2019-08-18 03:42:38 +02:00
{
2021-02-23 22:03:23 +01:00
if ( empty ( $ratio )) {
$ratio = 0 ; // To avoid null
}
2019-10-23 20:12:29 +02:00
2019-08-18 03:42:38 +02:00
// Steps should be between -255 and 255. Negative = darker, positive = lighter
$ratio = max ( - 100 , min ( 100 , $ratio ));
// Normalize into a six character long hex string
$hex = str_replace ( '#' , '' , $hex );
if ( strlen ( $hex ) == 3 ) {
$hex = str_repeat ( substr ( $hex , 0 , 1 ), 2 ) . str_repeat ( substr ( $hex , 1 , 1 ), 2 ) . str_repeat ( substr ( $hex , 2 , 1 ), 2 );
}
// Split into three parts: R, G and B
$color_parts = str_split ( $hex , 2 );
$return = '#' ;
foreach ( $color_parts as $color ) {
2020-01-10 00:03:10 +01:00
$color = hexdec ( $color ); // Convert to decimal
2021-02-23 22:03:23 +01:00
if ( $ratio > 0 ) { // We increase aggressivity
if ( $color > 127 ) {
$color += (( 255 - $color ) * ( $ratio / 100 ));
}
if ( $color < 128 ) {
$color -= ( $color * ( $ratio / 100 ));
}
2020-05-21 15:05:19 +02:00
} else // We decrease agressiveness
2019-08-18 03:42:38 +02:00
{
2021-02-23 22:03:23 +01:00
if ( $color > 128 ) {
$color -= (( $color - 128 ) * ( abs ( $ratio ) / 100 ));
}
if ( $color < 127 ) {
$color += (( 128 - $color ) * ( abs ( $ratio ) / 100 ));
}
2019-08-18 03:42:38 +02:00
}
2021-02-23 22:03:23 +01:00
if ( $brightness > 0 ) {
2019-10-23 20:12:29 +02:00
$color = ( $color * ( 100 + abs ( $brightness )) / 100 );
2020-05-21 15:05:19 +02:00
} else {
2019-10-23 20:12:29 +02:00
$color = ( $color * ( 100 - abs ( $brightness )) / 100 );
}
$color = max ( 0 , min ( 255 , $color )); // Adjust color to stay into valid range
2019-08-18 03:42:38 +02:00
$return .= str_pad ( dechex ( $color ), 2 , '0' , STR_PAD_LEFT ); // Make two char hex code
}
//var_dump($hex.' '.$ratio.' -> '.$return);
return $return ;
}
/**
* @ param string $hex Color in hex ( '#AA1122' or 'AA1122' or '#a12' or 'a12' )
* @ param integer $steps Step / offset added to each color component . It should be between - 255 and 255. Negative = darker , positive = lighter
* @ return string New color with format '#AA1122'
2019-10-23 17:48:55 +02:00
* @ see colorAgressiveness ()
2019-02-26 17:44:16 +01:00
*/
2019-03-04 11:15:01 +01:00
function colorAdjustBrightness ( $hex , $steps )
{
2020-09-07 10:18:17 +02:00
// Steps should be between -255 and 255. Negative = darker, positive = lighter
$steps = max ( - 255 , min ( 255 , $steps ));
// Normalize into a six character long hex string
$hex = str_replace ( '#' , '' , $hex );
if ( strlen ( $hex ) == 3 ) {
$hex = str_repeat ( substr ( $hex , 0 , 1 ), 2 ) . str_repeat ( substr ( $hex , 1 , 1 ), 2 ) . str_repeat ( substr ( $hex , 2 , 1 ), 2 );
}
// Split into three parts: R, G and B
$color_parts = str_split ( $hex , 2 );
$return = '#' ;
foreach ( $color_parts as $color ) {
$color = hexdec ( $color ); // Convert to decimal
$color = max ( 0 , min ( 255 , $color + $steps )); // Adjust color
$return .= str_pad ( dechex ( $color ), 2 , '0' , STR_PAD_LEFT ); // Make two char hex code
}
return $return ;
2019-02-26 17:44:16 +01:00
}
/**
2019-03-07 15:49:16 +01:00
* @ param string $hex color in hex
2019-02-26 17:44:16 +01:00
* @ param integer $percent 0 to 100
* @ return string
*/
2019-03-04 11:15:01 +01:00
function colorDarker ( $hex , $percent )
{
2020-09-07 10:18:17 +02:00
$steps = intval ( 255 * $percent / 100 ) * - 1 ;
return colorAdjustBrightness ( $hex , $steps );
2019-02-26 17:44:16 +01:00
}
/**
2019-03-07 15:49:16 +01:00
* @ param string $hex color in hex
2019-02-26 17:44:16 +01:00
* @ param integer $percent 0 to 100
* @ return string
*/
2019-03-04 11:15:01 +01:00
function colorLighten ( $hex , $percent )
{
2020-09-07 10:18:17 +02:00
$steps = intval ( 255 * $percent / 100 );
return colorAdjustBrightness ( $hex , $steps );
2019-02-26 17:44:16 +01:00
}
/**
2019-08-18 20:38:51 +02:00
* @ param string $hex color in hex
* @ param float $alpha 0 to 1 to add alpha channel
2020-03-06 01:18:35 +01:00
* @ param bool $returnArray true = return an array instead , false = return string
2019-08-18 20:38:51 +02:00
* @ return string | array String or array
2019-02-26 17:44:16 +01:00
*/
2019-03-04 11:15:01 +01:00
function colorHexToRgb ( $hex , $alpha = false , $returnArray = false )
{
2020-09-07 10:18:17 +02:00
$string = '' ;
$hex = str_replace ( '#' , '' , $hex );
$length = strlen ( $hex );
$rgb = array ();
$rgb [ 'r' ] = hexdec ( $length == 6 ? substr ( $hex , 0 , 2 ) : ( $length == 3 ? str_repeat ( substr ( $hex , 0 , 1 ), 2 ) : 0 ));
$rgb [ 'g' ] = hexdec ( $length == 6 ? substr ( $hex , 2 , 2 ) : ( $length == 3 ? str_repeat ( substr ( $hex , 1 , 1 ), 2 ) : 0 ));
$rgb [ 'b' ] = hexdec ( $length == 6 ? substr ( $hex , 4 , 2 ) : ( $length == 3 ? str_repeat ( substr ( $hex , 2 , 1 ), 2 ) : 0 ));
if ( $alpha !== false ) {
$rgb [ 'a' ] = floatval ( $alpha );
$string = 'rgba(' . implode ( ',' , $rgb ) . ')' ;
} else {
$string = 'rgb(' . implode ( ',' , $rgb ) . ')' ;
}
if ( $returnArray ) {
return $rgb ;
} else {
return $string ;
}
2019-02-26 17:44:16 +01:00
}
2016-07-23 16:37:21 +02:00
/**
* Applies the Cartesian product algorithm to an array
* Source : http :// stackoverflow . com / a / 15973172
*
2017-06-25 17:09:08 +02:00
* @ param array $input Array of products
* @ return array Array of combinations
2016-07-23 16:37:21 +02:00
*/
2018-08-15 17:34:35 +02:00
function cartesianArray ( array $input )
{
2020-09-07 10:18:17 +02:00
// filter out empty values
$input = array_filter ( $input );
2014-12-08 19:05:22 +01:00
2020-09-07 10:18:17 +02:00
$result = array ( array ());
2016-07-23 16:37:21 +02:00
2020-09-07 10:18:17 +02:00
foreach ( $input as $key => $values ) {
$append = array ();
2016-07-23 16:37:21 +02:00
2020-09-07 10:18:17 +02:00
foreach ( $result as $product ) {
foreach ( $values as $item ) {
$product [ $key ] = $item ;
$append [] = $product ;
}
}
2016-07-23 16:37:21 +02:00
2020-09-07 10:18:17 +02:00
$result = $append ;
}
2016-07-23 16:37:21 +02:00
2020-09-07 10:18:17 +02:00
return $result ;
2017-05-14 15:17:40 +02:00
}
2017-06-25 17:09:08 +02:00
/**
* Get name of directory where the api_ ... class . php file is stored
*
2020-06-18 01:09:30 +02:00
* @ param string $moduleobject Module object name
* @ return string Directory name
2017-06-25 17:09:08 +02:00
*/
2020-06-18 01:09:30 +02:00
function getModuleDirForApiClass ( $moduleobject )
2017-06-25 17:09:08 +02:00
{
2020-09-07 10:18:17 +02:00
$moduledirforclass = $moduleobject ;
2021-02-23 22:03:23 +01:00
if ( $moduledirforclass != 'api' ) {
$moduledirforclass = preg_replace ( '/api$/i' , '' , $moduledirforclass );
}
2020-09-07 10:18:17 +02:00
if ( $moduleobject == 'contracts' ) {
$moduledirforclass = 'contrat' ;
} elseif ( in_array ( $moduleobject , array ( 'admin' , 'login' , 'setup' , 'access' , 'status' , 'tools' , 'documents' ))) {
$moduledirforclass = 'api' ;
} elseif ( $moduleobject == 'contact' || $moduleobject == 'contacts' || $moduleobject == 'customer' || $moduleobject == 'thirdparty' || $moduleobject == 'thirdparties' ) {
$moduledirforclass = 'societe' ;
} elseif ( $moduleobject == 'propale' || $moduleobject == 'proposals' ) {
$moduledirforclass = 'comm/propal' ;
} elseif ( $moduleobject == 'agenda' || $moduleobject == 'agendaevents' ) {
$moduledirforclass = 'comm/action' ;
} elseif ( $moduleobject == 'adherent' || $moduleobject == 'members' || $moduleobject == 'memberstypes' || $moduleobject == 'subscriptions' ) {
$moduledirforclass = 'adherents' ;
} elseif ( $moduleobject == 'don' || $moduleobject == 'donations' ) {
$moduledirforclass = 'don' ;
} elseif ( $moduleobject == 'banque' || $moduleobject == 'bankaccounts' ) {
$moduledirforclass = 'compta/bank' ;
} elseif ( $moduleobject == 'category' || $moduleobject == 'categorie' ) {
$moduledirforclass = 'categories' ;
} elseif ( $moduleobject == 'order' || $moduleobject == 'orders' ) {
$moduledirforclass = 'commande' ;
} elseif ( $moduleobject == 'shipments' ) {
$moduledirforclass = 'expedition' ;
2022-12-30 16:16:29 +01:00
} elseif ( $moduleobject == 'multicurrencies' ) {
$moduledirforclass = 'multicurrency' ;
2020-09-07 10:18:17 +02:00
} elseif ( $moduleobject == 'facture' || $moduleobject == 'invoice' || $moduleobject == 'invoices' ) {
$moduledirforclass = 'compta/facture' ;
} elseif ( $moduleobject == 'project' || $moduleobject == 'projects' || $moduleobject == 'task' || $moduleobject == 'tasks' ) {
$moduledirforclass = 'projet' ;
} elseif ( $moduleobject == 'stock' || $moduleobject == 'stockmovements' || $moduleobject == 'warehouses' ) {
$moduledirforclass = 'product/stock' ;
} elseif ( $moduleobject == 'supplierproposals' || $moduleobject == 'supplierproposal' || $moduleobject == 'supplier_proposal' ) {
$moduledirforclass = 'supplier_proposal' ;
} elseif ( $moduleobject == 'fournisseur' || $moduleobject == 'supplierinvoices' || $moduleobject == 'supplierorders' ) {
$moduledirforclass = 'fourn' ;
} elseif ( $moduleobject == 'ficheinter' || $moduleobject == 'interventions' ) {
$moduledirforclass = 'fichinter' ;
} elseif ( $moduleobject == 'mos' ) {
$moduledirforclass = 'mrp' ;
2023-04-29 07:37:02 +02:00
} elseif ( $moduleobject == 'accounting' ) {
$moduledirforclass = 'accountancy' ;
2022-09-21 01:13:53 +02:00
} elseif ( in_array ( $moduleobject , array ( 'products' , 'expensereports' , 'users' , 'tickets' , 'boms' , 'receptions' ))) {
2020-09-07 10:18:17 +02:00
$moduledirforclass = preg_replace ( '/s$/' , '' , $moduleobject );
}
return $moduledirforclass ;
2017-06-25 17:09:08 +02:00
}
2017-09-07 16:23:51 +02:00
2019-04-01 19:27:34 +02:00
/**
2017-09-07 16:23:51 +02:00
* Return 2 hexa code randomly
2017-09-13 15:12:54 +02:00
*
2019-04-01 19:27:34 +02:00
* @ param int $min Between 0 and 255
* @ param int $max Between 0 and 255
* @ return string A color string '12'
2017-09-07 16:23:51 +02:00
*/
2019-04-01 19:27:34 +02:00
function randomColorPart ( $min = 0 , $max = 255 )
2018-08-15 17:34:35 +02:00
{
2020-09-07 10:18:17 +02:00
return str_pad ( dechex ( mt_rand ( $min , $max )), 2 , '0' , STR_PAD_LEFT );
2017-09-07 16:23:51 +02:00
}
2019-04-01 19:27:34 +02:00
/**
2017-09-07 16:23:51 +02:00
* Return hexadecimal color randomly
2017-09-13 15:12:54 +02:00
*
2019-04-01 19:27:34 +02:00
* @ param int $min Between 0 and 255
* @ param int $max Between 0 and 255
* @ return string A color string '123456'
*/
function randomColor ( $min = 0 , $max = 255 )
{
2020-09-07 10:18:17 +02:00
return randomColorPart ( $min , $max ) . randomColorPart ( $min , $max ) . randomColorPart ( $min , $max );
2019-04-01 19:27:34 +02:00
}
2019-04-02 20:02:43 +02:00
2021-02-23 22:03:23 +01:00
if ( ! function_exists ( 'dolEscapeXML' )) {
2020-09-07 10:18:17 +02:00
/**
* Encode string for xml usage
*
* @ param string $string String to encode
* @ return string String encoded
*/
function dolEscapeXML ( $string )
{
return strtr ( $string , array ( '\'' => ''' , '"' => '"' , '&' => '&' , '<' => '<' , '>' => '>' ));
}
2017-09-13 20:57:53 +02:00
}
2019-04-01 18:46:13 +02:00
2019-04-02 20:02:43 +02:00
2019-04-17 01:13:59 +02:00
/**
* Convert links to local wrapper to medias files into a string into a public external URL readable on internet
2019-04-18 10:12:00 +02:00
*
2019-04-17 01:13:59 +02:00
* @ param string $notetoshow Text to convert
* @ return string String
*/
function convertBackOfficeMediasLinksToPublicLinks ( $notetoshow )
{
2020-09-07 10:18:17 +02:00
global $dolibarr_main_url_root ;
// Define $urlwithroot
$urlwithouturlroot = preg_replace ( '/' . preg_quote ( DOL_URL_ROOT , '/' ) . '$/i' , '' , trim ( $dolibarr_main_url_root ));
$urlwithroot = $urlwithouturlroot . DOL_URL_ROOT ; // This is to use external domain name found into config file
//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
$notetoshow = preg_replace ( '/src="[a-zA-Z0-9_\/\-\.]*(viewimage\.php\?modulepart=medias[^"]*)"/' , 'src="' . $urlwithroot . '/\1"' , $notetoshow );
return $notetoshow ;
2019-04-17 01:13:59 +02:00
}
2020-01-23 11:47:30 +01:00
/**
* Function to format a value into a defined format for French administration ( no thousand separator & decimal separator force to ',' with two decimals )
* Function used into accountancy FEC export
*
2021-08-02 18:31:26 +02:00
* @ param float $amount Amount to format
2020-01-23 12:04:14 +01:00
* @ return string Chain with formatted upright
* @ see price2num () Format a numeric into a price for FEC files
2020-01-23 11:47:30 +01:00
*/
function price2fec ( $amount )
{
global $conf ;
// Clean parameters
2021-02-23 22:03:23 +01:00
if ( empty ( $amount )) {
$amount = 0 ; // To have a numeric value if amount not defined or = ''
}
2020-01-23 12:02:29 +01:00
$amount = ( is_numeric ( $amount ) ? $amount : 0 ); // Check if amount is numeric, for example, an error occured when amount value = o (letter) instead 0 (number)
2020-01-23 11:47:30 +01:00
2020-01-23 12:02:29 +01:00
// Output decimal number by default
$nbdecimal = ( empty ( $conf -> global -> ACCOUNTING_FEC_DECIMAL_LENGTH ) ? 2 : $conf -> global -> ACCOUNTING_FEC_DECIMAL_LENGTH );
2020-01-23 11:47:30 +01:00
2020-01-23 12:02:29 +01:00
// Output separators by default
$dec = ( empty ( $conf -> global -> ACCOUNTING_FEC_DECIMAL_SEPARATOR ) ? ',' : $conf -> global -> ACCOUNTING_FEC_DECIMAL_SEPARATOR );
$thousand = ( empty ( $conf -> global -> ACCOUNTING_FEC_THOUSAND_SEPARATOR ) ? '' : $conf -> global -> ACCOUNTING_FEC_THOUSAND_SEPARATOR );
2020-01-23 11:47:30 +01:00
// Format number
2020-01-23 12:02:29 +01:00
$output = number_format ( $amount , $nbdecimal , $dec , $thousand );
2020-01-23 11:47:30 +01:00
return $output ;
}
2020-10-07 14:58:54 +02:00
/**
* Check the syntax of some PHP code .
2020-10-07 17:17:13 +02:00
*
* @ param string $code PHP code to check .
* @ return boolean | array If false , then check was successful , otherwise an array ( message , line ) of errors is returned .
2020-10-07 14:58:54 +02:00
*/
function phpSyntaxError ( $code )
{
2021-02-23 22:03:23 +01:00
if ( ! defined ( " CR " )) {
define ( " CR " , " \r " );
}
if ( ! defined ( " LF " )) {
define ( " LF " , " \n " );
}
if ( ! defined ( " CRLF " )) {
define ( " CRLF " , " \r \n " );
}
2020-10-07 14:58:54 +02:00
2020-10-31 14:32:18 +01:00
$braces = 0 ;
$inString = 0 ;
foreach ( token_get_all ( '<?php ' . $code ) as $token ) {
2020-10-07 14:58:54 +02:00
if ( is_array ( $token )) {
switch ( $token [ 0 ]) {
case T_CURLY_OPEN :
case T_DOLLAR_OPEN_CURLY_BRACES :
2021-02-23 22:03:23 +01:00
case T_START_HEREDOC :
++ $inString ;
break ;
case T_END_HEREDOC :
-- $inString ;
break ;
2020-10-07 14:58:54 +02:00
}
2020-10-07 17:17:13 +02:00
} elseif ( $inString & 1 ) {
2020-10-07 14:58:54 +02:00
switch ( $token ) {
2020-10-07 17:17:13 +02:00
case '`' :
case '\'' :
2021-02-23 22:03:23 +01:00
case '"' :
-- $inString ;
break ;
2020-10-07 14:58:54 +02:00
}
} else {
switch ( $token ) {
2020-10-07 17:17:13 +02:00
case '`' :
case '\'' :
2021-02-23 22:03:23 +01:00
case '"' :
++ $inString ;
break ;
case '{' :
++ $braces ;
break ;
2020-10-07 14:58:54 +02:00
case '}' :
if ( $inString ) {
-- $inString ;
} else {
-- $braces ;
2021-02-23 22:03:23 +01:00
if ( $braces < 0 ) {
break 2 ;
}
2020-10-07 14:58:54 +02:00
}
break ;
}
}
}
$inString = @ ini_set ( 'log_errors' , false );
$token = @ ini_set ( 'display_errors' , true );
ob_start ();
$code = substr ( $code , strlen ( '<?php ' ));
$braces || $code = " if(0) { { $code } \n } " ;
if ( eval ( $code ) === false ) {
if ( $braces ) {
$braces = PHP_INT_MAX ;
} else {
2020-10-07 17:17:13 +02:00
false !== strpos ( $code , CR ) && $code = strtr ( str_replace ( CRLF , LF , $code ), CR , LF );
$braces = substr_count ( $code , LF );
2020-10-07 14:58:54 +02:00
}
$code = ob_get_clean ();
$code = strip_tags ( $code );
if ( preg_match ( " 'syntax error, (.+) in .+ on line ( \ d+) $ 's " , $code , $code )) {
$code [ 2 ] = ( int ) $code [ 2 ];
$code = $code [ 2 ] <= $braces
? array ( $code [ 1 ], $code [ 2 ])
2020-10-31 14:32:18 +01:00
: array ( 'unexpected $end' . substr ( $code [ 1 ], 14 ), $braces );
2021-02-23 22:03:23 +01:00
} else {
$code = array ( 'syntax error' , 0 );
}
2020-10-07 14:58:54 +02:00
} else {
ob_end_clean ();
$code = false ;
}
@ ini_set ( 'display_errors' , $token );
@ ini_set ( 'log_errors' , $inString );
return $code ;
}
2022-12-13 16:50:29 +01:00
/**
* Check the syntax of some PHP code .
*
* @ return int > 0 if OK , 0 if no Return if we accept link added from the media browser into HTML field for public usage
*/
function acceptLocalLinktoMedia ()
{
global $user ;
// If $acceptlocallinktomedia is true, we can add link media files int email templates (we already can do this into HTML editor of an email).
// Note that local link to a file into medias are replaced with a real link by email in CMailFile.class.php with value $urlwithroot defined like this:
// $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
// $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
$acceptlocallinktomedia = getDolGlobalInt ( 'MAIN_DISALLOW_MEDIAS_IN_EMAIL_TEMPLATES' ) ? 0 : 1 ;
if ( $acceptlocallinktomedia ) {
global $dolibarr_main_url_root ;
$urlwithouturlroot = preg_replace ( '/' . preg_quote ( DOL_URL_ROOT , '/' ) . '$/i' , '' , trim ( $dolibarr_main_url_root ));
// Parse $newUrl
$newUrlArray = parse_url ( $urlwithouturlroot );
$hosttocheck = $newUrlArray [ 'host' ];
$hosttocheck = str_replace ( array ( '[' , ']' ), '' , $hosttocheck ); // Remove brackets of IPv6
if ( function_exists ( 'gethostbyname' )) {
$iptocheck = gethostbyname ( $hosttocheck );
} else {
$iptocheck = $hosttocheck ;
}
//var_dump($iptocheck.' '.$acceptlocallinktomedia);
if ( ! filter_var ( $iptocheck , FILTER_VALIDATE_IP , FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE )) {
// If ip of public url is a private network IP, we do not allow this.
$acceptlocallinktomedia = 0 ;
// TODO Show a warning
}
if ( preg_match ( '/http:/i' , $urlwithouturlroot )) {
// If public url is not a https, we do not allow to add medias link. It will generate security alerts when email will be sent.
$acceptlocallinktomedia = 0 ;
// TODO Show a warning
}
if ( ! empty ( $user -> socid )) {
$acceptlocallinktomedia = 0 ;
}
}
2022-12-13 17:05:50 +01:00
//return 1;
2022-12-13 16:50:29 +01:00
return $acceptlocallinktomedia ;
}