2011-01-23 18:04:53 +00:00
< ? php
2018-10-19 16:20:06 +00:00
/* Copyright ( C ) 2003 - 2005 Rodolphe Quiedeville < rodolphe @ quiedeville . org >
* Copyright ( C ) 2004 - 2010 Laurent Destailleur < eldy @ users . sourceforge . net >
* Copyright ( C ) 2004 Eric Seigne < eric . seigne @ ryxeo . com >
2018-10-27 12:43:12 +00:00
* Copyright ( C ) 2005 - 2012 Regis Houssin < regis . houssin @ inodbox . com >
2018-10-19 16:20:06 +00:00
* Copyright ( C ) 2015 Marcos García < marcosgdf @ gmail . com >
add hook on printColDescContent (#35741)
* add hook on printColDescContent
Allow to add more informations on pdf description with hook management.
sample hook use :
public function printColDescContent($parameters, &$object, &$action)
{
$pdf = $parameters['pdf'];
if ($object->name == 'sponge mydiscount') {
//var_dump($parameters, $object, $action); exit;
$pdf->MultiCell(0, 3, "xxxxx", 0, 'L', 0, 1, '', '', true);
return 1;
}
}
* Add hook support to printColDescContent method
2025-10-26 13:43:40 +00:00
* Copyright ( C ) 2016 - 2025 Charlene Benke < charlene @ patas - monkey . com >
2026-02-04 13:49:13 +00:00
* Copyright ( C ) 2018 - 2026 Frédéric France < frederic . france @ free . fr >
2020-04-14 20:47:40 +00:00
* Copyright ( C ) 2020 Josep Lluís Amador < joseplluis @ lliuretic . cat >
2025-02-08 17:30:42 +00:00
* Copyright ( C ) 2024 - 2025 MDW < mdeweerd @ users . noreply . github . com >
2024-05-28 21:54:44 +00:00
* Copyright ( C ) 2024 Mélina Joum < melina . joum @ altairis . fr >
2024-10-04 07:13:44 +00:00
* Copyright ( C ) 2024 Nick Fragoulis
2011-01-23 18:04:53 +00: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 14:36:08 +00:00
* the Free Software Foundation ; either version 3 of the License , or
2011-01-23 18:04:53 +00: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 19:55:30 +00:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
* or see https :// www . gnu . org /
2011-01-23 18:04:53 +00:00
*/
/**
2011-03-08 09:59:41 +00:00
* \file htdocs / core / class / commondocgenerator . class . php
2011-01-23 18:04:53 +00:00
* \ingroup core
* \brief File of parent class for documents generators
*/
/**
2023-08-05 22:24:03 +00:00
* Parent class for documents ( PDF , ODT , ... ) generators
2011-01-23 18:04:53 +00:00
*/
2011-08-22 22:11:53 +00:00
abstract class CommonDocGenerator
2011-01-23 18:04:53 +00:00
{
2023-02-08 11:18:46 +00:00
/**
* @ var string Model name
*/
public $name = '' ;
2023-08-05 22:41:59 +00:00
/**
2024-08-17 17:32:52 +00:00
* @ var string Version , possible values are : 'development' , 'experimental' , 'dolibarr' , 'dolibarr_deprecated' or a version string like 'x.y.z' '' | 'development' | 'dolibarr' | 'experimental' Version
2023-08-05 22:41:59 +00:00
*/
public $version = '' ;
2018-09-21 06:49:05 +00:00
/**
* @ var string Error code ( or message )
*/
2019-11-13 18:35:39 +00:00
public $error = '' ;
2018-09-21 06:49:05 +00:00
2020-10-07 13:01:28 +00:00
/**
* @ var string [] Array of error strings
*/
public $errors = array ();
2018-10-18 19:47:10 +00:00
2025-12-21 12:32:32 +00:00
/**
* @ var string [] Array of warnings strings
*/
public $warnings = array ();
2018-10-06 10:34:51 +00:00
/**
2020-10-07 13:01:28 +00:00
* @ var DoliDB Database handler .
*/
2015-07-06 14:59:03 +00:00
protected $db ;
2016-09-23 08:51:31 +00:00
2020-10-07 13:01:28 +00:00
/**
2025-06-19 08:10:42 +00:00
* @ var ? ExtraFields object
2020-10-07 13:01:28 +00:00
*/
2020-02-23 09:09:47 +00:00
public $extrafieldsCache ;
2016-09-23 08:51:31 +00:00
2021-02-09 07:35:22 +00:00
/**
* @ var int If set to 1 , save the fullname of generated file with path as the main doc when generating a doc with this template .
*/
public $update_main_doc_field ;
2022-04-30 15:47:45 +00:00
/**
2024-01-13 18:48:20 +00:00
* @ var string The name of constant to use to scan ODT files ( Example : 'COMMANDE_ADDON_PDF_ODT_PATH' )
2022-04-30 15:47:45 +00:00
*/
public $scandir ;
2023-02-01 21:14:37 +00:00
/**
* @ var string model description ( short text )
*/
public $description ;
2023-02-01 21:10:20 +00:00
/**
2024-10-13 14:45:42 +00:00
* @ var array { 0 : float , 1 : float }
2023-02-01 21:10:20 +00:00
*/
public $format ;
2023-02-28 14:15:04 +00:00
/**
* @ var string pdf , odt , etc
*/
public $type ;
2024-09-29 01:10:45 +00:00
/**
* @ var float page height
*/
2022-05-18 10:40:44 +00:00
public $page_hauteur ;
2024-09-29 01:10:45 +00:00
/**
* @ var float page wicth
*/
2022-05-18 10:40:44 +00:00
public $page_largeur ;
2024-09-29 01:10:45 +00:00
/**
* @ var float left margin
*/
2022-05-18 10:40:44 +00:00
public $marge_gauche ;
2024-09-29 01:10:45 +00:00
/**
* @ var float right margin
*/
2022-05-18 10:40:44 +00:00
public $marge_droite ;
2024-09-29 01:10:45 +00:00
/**
* @ var float top margin
*/
2022-05-18 10:40:44 +00:00
public $marge_haute ;
2024-09-29 01:10:45 +00:00
/**
* @ var float bottom margin
*/
2022-05-18 10:40:44 +00:00
public $marge_basse ;
2024-10-04 07:13:44 +00:00
/**
* @ var int corner radius
*/
public $corner_radius ;
2024-09-29 01:10:45 +00:00
/**
* @ var int < 0 , 1 > option logo
*/
2022-05-18 10:40:44 +00:00
public $option_logo ;
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2022-05-18 10:40:44 +00:00
public $option_tva ;
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2022-05-18 10:40:44 +00:00
public $option_multilang ;
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2022-05-18 10:40:44 +00:00
public $option_freetext ;
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2022-05-18 10:40:44 +00:00
public $option_draft_watermark ;
2024-10-13 14:45:42 +00:00
/**
* @ var string
*/
2023-04-27 21:01:34 +00:00
public $watermark ;
2022-05-18 10:40:44 +00:00
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2022-05-18 10:40:44 +00:00
public $option_modereg ;
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2022-05-18 10:40:44 +00:00
public $option_condreg ;
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2022-05-18 10:40:44 +00:00
public $option_escompte ;
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2022-05-18 10:40:44 +00:00
public $option_credit_note ;
2024-10-13 14:45:42 +00:00
/**
* @ var array < string , float >
*/
2023-08-29 18:49:23 +00:00
public $tva ;
2024-10-13 14:45:42 +00:00
/**
* @ var array < string , array { amount : float } >
*/
2023-08-29 18:49:23 +00:00
public $tva_array ;
2024-03-10 00:55:56 +00:00
/**
* Local tax rates Array [ tax_type ][ tax_rate ]
*
* @ var array < int , array < string , float >>
*/
2023-08-29 18:49:23 +00:00
public $localtax1 ;
2024-03-10 00:55:56 +00:00
/**
* Local tax rates Array [ tax_type ][ tax_rate ]
*
* @ var array < int , array < string , float >>
*/
2023-08-29 18:49:23 +00:00
public $localtax2 ;
2023-08-27 18:31:09 +00:00
/**
* @ var int Tab Title Height
*/
public $tabTitleHeight ;
/**
2024-10-13 14:45:42 +00:00
* @ var array { align ? : 'R' | 'C' | 'L' , padding ? : array < float | int > } default title fields style
2023-08-27 18:31:09 +00:00
*/
public $defaultTitlesFieldsStyle ;
/**
2024-10-13 14:45:42 +00:00
* @ var array { align ? : 'R' | 'C' | 'L' , padding ? : array < float | int > } default content fields style
2023-08-27 18:31:09 +00:00
*/
public $defaultContentsFieldsStyle ;
2023-08-10 09:29:09 +00:00
/**
* @ var Societe Issuer of document
*/
2022-05-18 10:40:44 +00:00
public $emetteur ;
2023-05-31 07:31:22 +00:00
/**
2024-03-22 23:02:52 +00:00
* @ var array { 0 : int , 1 : int } Minimum version of PHP required by module .
2023-05-31 07:31:22 +00:00
* e . g .: PHP ≥ 7.1 = array ( 7 , 1 )
*/
public $phpmin = array ( 7 , 1 );
2023-05-01 11:09:09 +00:00
/**
2025-03-11 00:42:49 +00:00
* @ var array < string , array { rank : int , width : float | false , status : bool | int < 0 , 1 > , border - left ? : bool , title : array { textkey : string , label ? : string , align ? : string , padding ? : array { 0 : float , 1 : float , 2 : float , 3 : float }}, content ? : array { align ? : string , padding ? : array { 0 : float , 1 : float , 2 : float , 3 : float }}} > Array of document table columns
2023-05-01 11:09:09 +00:00
*/
public $cols ;
2024-10-08 20:44:36 +00:00
/**
* @ var array < string , array { page : int , y : float | int } > Array of position data
*/
public $afterColsLinePositions ;
2023-08-05 22:24:03 +00:00
/**
2024-03-22 23:02:52 +00:00
* @ var array { fullpath : string } Array with result of doc generation . content is array ( 'fullpath' => $file )
2023-08-05 22:24:03 +00:00
*/
public $result ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-04 18:39:00 +00:00
public $posxlabel ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-04 18:39:00 +00:00
public $posxup ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-08-10 09:29:09 +00:00
public $posxref ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-08-10 09:29:09 +00:00
public $posxpicture ; // For picture
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-08-10 09:29:09 +00:00
public $posxdesc ; // For description
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-08-10 09:29:09 +00:00
public $posxqty ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-08-10 09:29:09 +00:00
public $posxpuht ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-02 19:23:15 +00:00
public $posxtva ;
2024-10-13 14:45:42 +00:00
/**
* @ var float | int
*/
2023-09-09 11:42:54 +00:00
public $posxtotalht ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-09 11:42:54 +00:00
public $postotalht ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-11 16:02:50 +00:00
public $posxunit ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-11 16:02:50 +00:00
public $posxdiscount ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-11 16:02:50 +00:00
public $posxworkload ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-11 16:02:50 +00:00
public $posxtimespent ;
2024-10-13 14:45:42 +00:00
/**
* @ var float
*/
2023-09-11 16:02:50 +00:00
public $posxprogress ;
2024-10-13 14:45:42 +00:00
/**
* @ var bool
*/
2023-09-02 19:23:15 +00:00
public $atleastonephoto ;
2024-10-13 14:45:42 +00:00
/**
* @ var int < 0 , 1 >
*/
2023-09-02 19:23:15 +00:00
public $atleastoneratenotnull ;
2024-10-13 14:45:42 +00:00
/**
* @ var bool | int < 0 , 1 >
*/
2023-09-02 19:23:15 +00:00
public $atleastonediscount ;
2022-04-30 15:47:45 +00:00
2015-07-06 11:18:51 +00:00
/**
* Constructor
*
* @ param DoliDB $db Database handler
2020-10-07 13:01:28 +00:00
*/
public function __construct ( $db )
{
$this -> db = $db ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Define array with couple substitution key => substitution value
*
* @ param User $user User
* @ param Translate $outputlangs Language object for output
2025-11-12 08:36:40 +00:00
* @ return array < string , float | string > Array of substitution key -> code
2020-10-07 13:01:28 +00:00
*/
public function get_substitutionarray_user ( $user , $outputlangs )
{
// phpcs:enable
2020-11-13 23:48:13 +00:00
global $conf , $extrafields ;
2020-10-07 13:01:28 +00:00
2024-02-09 14:58:49 +00:00
$logotouse = $conf -> user -> dir_output . '/' . get_exdir ( 0 , 0 , 0 , 0 , $user , 'user' ) . 'photos/' . getImageFileNameForSize ( $user -> photo , '_small' );
2020-10-07 13:01:28 +00:00
2020-11-13 23:48:13 +00:00
$array_user = array (
2026-01-20 12:56:52 +00:00
'myuser_lastname' => ( string ) $user -> lastname ,
'myuser_firstname' => ( string ) $user -> firstname ,
2024-03-10 00:55:56 +00:00
'myuser_fullname' => $user -> getFullName ( $outputlangs , 1 ),
2026-01-20 12:56:52 +00:00
'myuser_login' => ( string ) $user -> login ,
'myuser_phone' => ( string ) $user -> office_phone ,
'myuser_address' => ( string ) $user -> address ,
'myuser_zip' => ( string ) $user -> zip ,
'myuser_town' => ( string ) $user -> town ,
'myuser_country' => ( string ) $user -> country ,
'myuser_country_code' => ( string ) $user -> country_code ,
'myuser_state' => ( string ) $user -> state ,
'myuser_state_code' => ( string ) $user -> state_code ,
'myuser_fax' => ( string ) $user -> office_fax ,
'myuser_mobile' => ( string ) $user -> user_mobile ,
'myuser_email' => ( string ) $user -> email ,
'myuser_logo' => ( string ) $logotouse ,
'myuser_job' => ( string ) $user -> job ,
2024-03-10 00:55:56 +00:00
'myuser_web' => '' , // url not exist in $user object
'myuser_birth' => dol_print_date ( $user -> birth , 'day' , 'gmt' ),
'myuser_dateemployment' => dol_print_date ( $user -> dateemployment , 'day' , 'tzuser' ),
'myuser_dateemploymentend' => dol_print_date ( $user -> dateemploymentend , 'day' , 'tzuser' ),
2026-01-20 12:56:52 +00:00
'myuser_gender' => ( string ) $user -> gender ,
2020-10-07 13:01:28 +00:00
);
2020-11-13 23:48:13 +00:00
// Retrieve extrafields
if ( is_array ( $user -> array_options ) && count ( $user -> array_options )) {
2024-03-14 20:14:23 +00:00
if ( empty ( $extrafields -> attributes [ $user -> table_element ])) {
$extrafields -> fetch_name_optionals_label ( $user -> table_element );
}
2020-11-13 23:48:13 +00:00
$array_user = $this -> fill_substitutionarray_with_extrafields ( $user , $array_user , $extrafields , 'myuser' , $outputlangs );
}
return $array_user ;
}
/**
* Define array with couple substitution key => substitution value
*
* @ param Adherent $member Member
* @ param Translate $outputlangs Language object for output
2025-11-12 08:36:40 +00:00
* @ return array < string , float | string > Array of substitution key -> code
2020-11-13 23:48:13 +00:00
*/
public function getSubstitutionarrayMember ( $member , $outputlangs )
{
global $conf , $extrafields ;
2020-11-15 22:58:35 +00:00
if ( $member -> photo ) {
2024-06-05 12:55:07 +00:00
$logotouse = $conf -> member -> dir_output . '/' . get_exdir ( 0 , 0 , 0 , 1 , $member , 'user' ) . '/photos/' . $member -> photo ;
2020-11-15 22:58:35 +00:00
} else {
2020-12-01 01:41:19 +00:00
$logotouse = DOL_DOCUMENT_ROOT . '/public/theme/common/nophoto.png' ;
2020-11-15 22:58:35 +00:00
}
2020-11-13 23:48:13 +00:00
$array_member = array (
2026-01-20 22:16:24 +00:00
'mymember_lastname' => ( string ) $member -> lastname ,
'mymember_firstname' => ( string ) $member -> firstname ,
2020-11-13 23:48:13 +00:00
'mymember_fullname' => $member -> getFullName ( $outputlangs , 1 ),
2026-01-20 22:16:24 +00:00
'mymember_login' => ( string ) $member -> login ,
'mymember_address' => ( string ) $member -> address ,
'mymember_zip' => ( string ) $member -> zip ,
'mymember_town' => ( string ) $member -> town ,
'mymember_country_code' => ( string ) $member -> country_code ,
'mymember_country' => ( string ) $member -> country ,
'mymember_state_code' => ( string ) $member -> state_code ,
'mymember_state' => ( string ) $member -> state ,
'mymember_phone_perso' => ( string ) $member -> phone_perso ,
'mymember_phone_pro' => ( string ) $member -> phone ,
'mymember_phone_mobile' => ( string ) $member -> phone_mobile ,
'mymember_email' => ( string ) $member -> email ,
2020-11-13 23:48:13 +00:00
'mymember_logo' => $logotouse ,
2026-01-20 22:16:24 +00:00
'mymember_gender' => ( string ) $member -> gender ,
2020-11-13 23:48:13 +00:00
'mymember_birth_locale' => dol_print_date ( $member -> birth , 'day' , 'tzuser' , $outputlangs ),
'mymember_birth' => dol_print_date ( $member -> birth , 'day' , 'tzuser' ),
);
// Retrieve extrafields
if ( is_array ( $member -> array_options ) && count ( $member -> array_options )) {
$array_member = $this -> fill_substitutionarray_with_extrafields ( $member , $array_member , $extrafields , 'mymember' , $outputlangs );
}
return $array_member ;
2020-10-07 13:01:28 +00:00
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Define array with couple substitution key => substitution value
*
* @ param Societe $mysoc Object thirdparty
* @ param Translate $outputlangs Language object for output
2024-09-22 22:37:30 +00:00
* @ return array < string , mixed > Array of substitution key -> code
2020-10-07 13:01:28 +00:00
*/
public function get_substitutionarray_mysoc ( $mysoc , $outputlangs )
{
// phpcs:enable
global $conf ;
2021-02-23 21:03:23 +00:00
if ( empty ( $mysoc -> forme_juridique ) && ! empty ( $mysoc -> forme_juridique_code )) {
2024-09-05 14:05:37 +00:00
$mysoc -> forme_juridique = getFormeJuridiqueLabel (( string ) $mysoc -> forme_juridique_code );
2020-10-07 13:01:28 +00:00
}
2021-02-23 21:03:23 +00:00
if ( empty ( $mysoc -> country ) && ! empty ( $mysoc -> country_code )) {
2020-10-07 13:01:28 +00:00
$mysoc -> country = $outputlangs -> transnoentitiesnoconv ( " Country " . $mysoc -> country_code );
}
2021-02-23 21:03:23 +00:00
if ( empty ( $mysoc -> state ) && ! empty ( $mysoc -> state_code )) {
2024-08-13 18:39:40 +00:00
$state_id = dol_getIdFromCode ( $this -> db , $mysoc -> state_code , 'c_departements' , 'code_departement' , 'rowid' );
$mysoc -> state = getState ( $state_id , '0' );
2020-10-07 13:01:28 +00:00
}
$logotouse = $conf -> mycompany -> dir_output . '/logos/thumbs/' . $mysoc -> logo_small ;
return array (
2024-03-10 00:55:56 +00:00
'mycompany_logo' => $logotouse ,
'mycompany_name' => $mysoc -> name ,
'mycompany_email' => $mysoc -> email ,
'mycompany_phone' => $mysoc -> phone ,
'mycompany_fax' => $mysoc -> fax ,
'mycompany_address' => $mysoc -> address ,
'mycompany_zip' => $mysoc -> zip ,
'mycompany_town' => $mysoc -> town ,
'mycompany_country' => $mysoc -> country ,
'mycompany_country_code' => $mysoc -> country_code ,
'mycompany_state' => $mysoc -> state ,
'mycompany_state_code' => $mysoc -> state_code ,
'mycompany_web' => $mysoc -> url ,
'mycompany_juridicalstatus' => $mysoc -> forme_juridique ,
'mycompany_managers' => $mysoc -> managers ,
'mycompany_capital' => $mysoc -> capital ,
'mycompany_barcode' => $mysoc -> barcode ,
'mycompany_idprof1' => $mysoc -> idprof1 ,
'mycompany_idprof2' => $mysoc -> idprof2 ,
'mycompany_idprof3' => $mysoc -> idprof3 ,
'mycompany_idprof4' => $mysoc -> idprof4 ,
'mycompany_idprof5' => $mysoc -> idprof5 ,
'mycompany_idprof6' => $mysoc -> idprof6 ,
'mycompany_vatnumber' => $mysoc -> tva_intra ,
'mycompany_socialobject' => $mysoc -> socialobject ,
'mycompany_note_private' => $mysoc -> note_private ,
2020-10-07 13:01:28 +00:00
//'mycompany_note_public'=>$mysoc->note_public, // Only private not exists for "mysoc" but both for thirdparties
);
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Define array with couple substitution key => substitution value
2021-10-05 09:03:51 +00:00
* For example { company_name }, { company_name_alias }
2020-10-07 13:01:28 +00:00
*
2025-11-09 00:19:31 +00:00
* @ param ? Societe $object Object
2020-10-07 13:01:28 +00:00
* @ param Translate $outputlangs Language object for output
* @ param string $array_key Name of the key for return array
2024-09-22 22:37:30 +00:00
* @ return array < string , mixed > Array of substitution key -> code
2020-10-07 13:01:28 +00:00
*/
public function get_substitutionarray_thirdparty ( $object , $outputlangs , $array_key = 'company' )
{
// phpcs:enable
2023-08-09 16:18:20 +00:00
global $extrafields ;
2020-10-07 13:01:28 +00:00
2024-09-25 20:52:25 +00:00
if ( ! is_object ( $object )) {
return array ();
}
2021-02-23 21:03:23 +00:00
if ( empty ( $object -> country ) && ! empty ( $object -> country_code )) {
2020-10-07 13:01:28 +00:00
$object -> country = $outputlangs -> transnoentitiesnoconv ( " Country " . $object -> country_code );
}
2021-02-23 21:03:23 +00:00
if ( empty ( $object -> state ) && ! empty ( $object -> state_code )) {
2024-08-13 18:39:40 +00:00
$state_id = dol_getIdFromCode ( $this -> db , $object -> state_code , 'c_departements' , 'code_departement' , 'rowid' );
$object -> state = getState ( $state_id , '0' );
2020-10-07 13:01:28 +00:00
}
$array_thirdparty = array (
2026-01-20 22:16:24 +00:00
'company_name' => ( string ) $object -> name ,
'company_name_alias' => ( string ) $object -> name_alias ,
'company_email' => ( string ) $object -> email ,
'company_phone' => ( string ) $object -> phone ,
'company_fax' => ( string ) $object -> fax ,
'company_address' => ( string ) $object -> address ,
'company_zip' => ( string ) $object -> zip ,
'company_town' => ( string ) $object -> town ,
'company_country' => ( string ) $object -> country ,
'company_country_code' => ( string ) $object -> country_code ,
'company_state' => ( string ) $object -> state ,
'company_state_code' => ( string ) $object -> state_code ,
'company_web' => ( string ) $object -> url ,
'company_barcode' => ( string ) $object -> barcode ,
'company_vatnumber' => ( string ) $object -> tva_intra ,
'company_customercode' => ( string ) $object -> code_client ,
'company_suppliercode' => ( string ) $object -> code_fournisseur ,
'company_customeraccountancycode' => ( string ) $object -> code_compta_client ,
'company_supplieraccountancycode' => ( string ) $object -> code_compta_fournisseur ,
'company_juridicalstatus' => ( string ) $object -> forme_juridique ,
'company_outstanding_limit' => ( string ) $object -> outstanding_limit ,
'company_capital' => ( string ) $object -> capital ,
2024-08-07 00:53:45 +00:00
'company_capital_formated' => price ( $object -> capital , 0 , '' , 1 , - 1 ),
2026-01-20 22:16:24 +00:00
'company_idprof1' => ( string ) $object -> idprof1 ,
'company_idprof2' => ( string ) $object -> idprof2 ,
'company_idprof3' => ( string ) $object -> idprof3 ,
'company_idprof4' => ( string ) $object -> idprof4 ,
'company_idprof5' => ( string ) $object -> idprof5 ,
'company_idprof6' => ( string ) $object -> idprof6 ,
'company_note_public' => ( string ) $object -> note_public ,
'company_note_private' => ( string ) $object -> note_private ,
'company_default_bank_iban' => ( is_object ( $object -> bank_account ) ? ( string ) $object -> bank_account -> iban : '' ),
'company_default_bank_bic' => ( is_object ( $object -> bank_account ) ? ( string ) $object -> bank_account -> bic : '' )
2020-10-07 13:01:28 +00:00
);
// Retrieve extrafields
2021-02-23 21:03:23 +00:00
if ( is_array ( $object -> array_options ) && count ( $object -> array_options )) {
2020-10-07 13:01:28 +00:00
$object -> fetch_optionals ();
$array_thirdparty = $this -> fill_substitutionarray_with_extrafields ( $object , $array_thirdparty , $extrafields , $array_key , $outputlangs );
}
2014-04-30 08:36:23 +00:00
return $array_thirdparty ;
}
2014-05-01 14:43:40 +00:00
2020-10-07 13:01:28 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2014-04-30 08:36:23 +00:00
/**
2019-10-11 21:08:33 +00:00
* Define array with couple substitution key => substitution value
2014-04-30 08:36:23 +00:00
*
2018-10-24 01:30:06 +00:00
* @ param Contact $object contact
2014-04-30 08:36:23 +00:00
* @ param Translate $outputlangs object for output
2020-04-23 13:50:42 +00:00
* @ param string $array_key Name of the key for return array
2024-09-22 22:37:30 +00:00
* @ return array < string , mixed > Array of substitution key -> code
2014-04-30 08:36:23 +00:00
*/
2020-10-07 13:01:28 +00:00
public function get_substitutionarray_contact ( $object , $outputlangs , $array_key = 'object' )
{
// phpcs:enable
2026-02-12 14:18:31 +00:00
global $extrafields ;
2014-05-01 14:43:40 +00:00
2021-02-23 21:03:23 +00:00
if ( empty ( $object -> country ) && ! empty ( $object -> country_code )) {
2020-03-12 11:45:44 +00:00
$object -> country = $outputlangs -> transnoentitiesnoconv ( " Country " . $object -> country_code );
2014-04-30 08:36:23 +00:00
}
2021-02-23 21:03:23 +00:00
if ( empty ( $object -> state ) && ! empty ( $object -> state_code )) {
2024-08-13 18:39:40 +00:00
$state_id = dol_getIdFromCode ( $this -> db , $object -> state_code , 'c_departements' , 'code_departement' , 'rowid' );
$object -> state = getState ( $state_id , '0' );
2014-04-30 08:36:23 +00:00
}
2014-05-01 14:43:40 +00:00
2020-04-10 08:59:32 +00:00
$array_contact = array (
$array_key . '_fullname' => $object -> getFullName ( $outputlangs , 1 ),
$array_key . '_lastname' => $object -> lastname ,
$array_key . '_firstname' => $object -> firstname ,
$array_key . '_address' => $object -> address ,
$array_key . '_zip' => $object -> zip ,
$array_key . '_town' => $object -> town ,
$array_key . '_state_id' => $object -> state_id ,
$array_key . '_state_code' => $object -> state_code ,
$array_key . '_state' => $object -> state ,
$array_key . '_country_id' => $object -> country_id ,
$array_key . '_country_code' => $object -> country_code ,
$array_key . '_country' => $object -> country ,
$array_key . '_poste' => $object -> poste ,
$array_key . '_socid' => $object -> socid ,
2026-02-12 14:18:31 +00:00
$array_key . '_statut' => $object -> statut ? $object -> statut : $object -> status ,
2020-04-10 08:59:32 +00:00
$array_key . '_code' => $object -> code ,
$array_key . '_email' => $object -> email ,
$array_key . '_phone_pro' => $object -> phone_pro ,
$array_key . '_phone_perso' => $object -> phone_perso ,
$array_key . '_phone_mobile' => $object -> phone_mobile ,
$array_key . '_fax' => $object -> fax ,
2026-02-12 15:27:30 +00:00
$array_key . '_birthday_locale' => ( ! empty ( $object -> birthday ) ? dol_print_date ( $object -> birthday , 'day' , false , $outputlangs ) : '' ),
2020-04-10 08:59:32 +00:00
$array_key . '_birthday' => $object -> birthday ,
$array_key . '_default_lang' => $object -> default_lang ,
$array_key . '_note_public' => $object -> note_public ,
$array_key . '_note_private' => $object -> note_private ,
$array_key . '_civility' => $object -> civility ,
2014-04-30 08:36:23 +00:00
);
2014-05-01 14:43:40 +00:00
2020-10-07 13:01:28 +00:00
// Retrieve extrafields
2021-02-23 21:03:23 +00:00
if ( is_array ( $object -> array_options ) && count ( $object -> array_options )) {
2020-10-07 13:01:28 +00:00
$object -> fetch_optionals ();
2014-06-06 14:08:42 +00:00
2020-10-07 13:01:28 +00:00
$array_contact = $this -> fill_substitutionarray_with_extrafields ( $object , $array_contact , $extrafields , $array_key , $outputlangs );
}
2014-04-30 08:36:23 +00:00
return $array_contact ;
}
2014-05-01 14:43:40 +00:00
2013-03-23 17:04:46 +00:00
2020-10-07 13:01:28 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Define array with couple substitution key => substitution value
*
* @ param Translate $outputlangs Language object for output
2024-09-22 22:37:30 +00:00
* @ return array < string , mixed > Array of substitution key -> code
2020-10-07 13:01:28 +00:00
*/
public function get_substitutionarray_other ( $outputlangs )
{
// phpcs:enable
global $conf ;
$now = dol_now ( 'gmt' ); // gmt
$array_other = array (
// Date in default language
2024-03-10 00:55:56 +00:00
'current_date' => dol_print_date ( $now , 'day' , 'tzuser' ),
'current_datehour' => dol_print_date ( $now , 'dayhour' , 'tzuser' ),
'current_server_date' => dol_print_date ( $now , 'day' , 'tzserver' ),
'current_server_datehour' => dol_print_date ( $now , 'dayhour' , 'tzserver' ),
2020-10-07 13:01:28 +00:00
// Date in requested output language
2024-03-10 00:55:56 +00:00
'current_date_locale' => dol_print_date ( $now , 'day' , 'tzuser' , $outputlangs ),
'current_datehour_locale' => dol_print_date ( $now , 'dayhour' , 'tzuser' , $outputlangs ),
'current_server_date_locale' => dol_print_date ( $now , 'day' , 'tzserver' , $outputlangs ),
'current_server_datehour_locale' => dol_print_date ( $now , 'dayhour' , 'tzserver' , $outputlangs ),
2020-10-07 13:01:28 +00:00
);
2013-03-29 15:18:55 +00:00
2018-02-24 13:23:52 +00:00
2021-02-23 21:03:23 +00:00
foreach ( $conf -> global as $key => $val ) {
if ( isASecretKey ( $key )) {
$newval = '*****forbidden*****' ;
} else {
$newval = $val ;
}
2020-10-07 13:01:28 +00:00
$array_other [ '__[' . $key . ']__' ] = $newval ;
}
2018-02-24 13:23:52 +00:00
2020-10-07 13:01:28 +00:00
return $array_other ;
}
2013-06-08 16:12:32 +00:00
2014-05-07 11:22:02 +00:00
2020-10-07 13:01:28 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2014-05-07 11:22:02 +00:00
/**
* Define array with couple substitution key => substitution value
2023-07-22 11:29:00 +00:00
* Note that vars into substitutions array are formatted .
2014-05-07 11:22:02 +00:00
*
2024-02-07 18:36:23 +00:00
* @ param CommonObject $object Main object to use as data source
2014-05-07 11:22:02 +00:00
* @ param Translate $outputlangs Lang object to use for output
2020-10-07 13:01:28 +00:00
* @ param string $array_key Name of the key for return array
2024-09-22 22:37:30 +00:00
* @ return array < string , mixed > Array of substitution
2014-05-07 11:22:02 +00:00
*/
2019-02-25 21:27:04 +00:00
public function get_substitutionarray_object ( $object , $outputlangs , $array_key = 'object' )
2014-05-07 11:22:02 +00:00
{
2020-10-07 13:01:28 +00:00
// phpcs:enable
2024-01-04 14:23:46 +00:00
global $extrafields ;
2013-03-23 17:04:46 +00:00
2025-08-12 02:08:20 +00:00
$totalpaid = $totaldeposits = $totalcreditnotes = '' ;
2019-11-13 18:35:39 +00:00
$already_payed_all = 0 ;
2021-11-08 02:21:15 +00:00
2021-02-23 21:03:23 +00:00
if ( $object -> element == 'facture' ) {
2024-02-07 18:36:23 +00:00
/** @var Facture $object */
2024-09-13 01:09:23 +00:00
'@phan-var-force Facture $object' ;
2019-11-13 18:35:39 +00:00
$invoice_source = new Facture ( $this -> db );
2021-02-23 21:03:23 +00:00
if ( $object -> fk_facture_source > 0 ) {
2014-05-07 11:22:02 +00:00
$invoice_source -> fetch ( $object -> fk_facture_source );
}
2025-08-12 02:08:20 +00:00
$totalpaid = $object -> getSommePaiement ();
$totaldeposits = $object -> getSumDepositsUsed ();
$totalcreditnotes = $object -> getSumCreditNotesUsed ();
$already_payed_all = $totalpaid + $totaldeposits + $totalcreditnotes ;
2014-05-07 11:22:02 +00:00
}
2013-03-23 17:04:46 +00:00
2024-09-13 01:09:23 +00:00
// Ignore notice for deprecated date - @phan-suppress-next-line PhanUndeclaredProperty
2023-01-30 10:36:00 +00:00
$date = ( isset ( $object -> element ) && $object -> element == 'contrat' && isset ( $object -> date_contrat )) ? $object -> date_contrat : ( isset ( $object -> date ) ? $object -> date : null );
2023-06-10 23:09:34 +00:00
2024-09-13 01:09:23 +00:00
if ( $object instanceof CommandeFournisseur ) {
2023-06-10 14:41:43 +00:00
$object -> date_validation = $object -> date_valid ;
$object -> date_commande = $object -> date ;
}
2019-11-13 18:35:39 +00:00
$resarray = array (
2024-03-10 00:55:56 +00:00
$array_key . '_id' => $object -> id ,
2022-06-07 17:27:43 +00:00
$array_key . '_ref' => ( property_exists ( $object , 'ref' ) ? $object -> ref : '' ),
2024-10-13 14:45:42 +00:00
$array_key . '_label' => ( property_exists ( $object , 'label' ) ? $object -> label : '' ), // @phan-suppress-current-line PhanUndeclaredProperty
2022-06-07 17:27:43 +00:00
$array_key . '_ref_ext' => ( property_exists ( $object , 'ref_ext' ) ? $object -> ref_ext : '' ),
2024-03-10 00:55:56 +00:00
$array_key . '_ref_customer' => ( ! empty ( $object -> ref_client ) ? $object -> ref_client : ( empty ( $object -> ref_customer ) ? '' : $object -> ref_customer )),
2024-10-13 14:45:42 +00:00
$array_key . '_ref_supplier' => ( ! empty ( $object -> ref_fournisseur ) ? $object -> ref_fournisseur : ( empty ( $object -> ref_supplier ) ? '' : $object -> ref_supplier )), // @phan-suppress-current-line PhanUndeclaredProperty
2024-03-10 00:55:56 +00:00
$array_key . '_source_invoice_ref' => (( empty ( $invoice_source ) || empty ( $invoice_source -> ref )) ? '' : $invoice_source -> ref ),
2021-11-08 02:21:15 +00:00
// Dates
2024-03-10 00:55:56 +00:00
$array_key . '_hour' => dol_print_date ( $date , 'hour' ),
$array_key . '_date' => dol_print_date ( $date , 'day' ),
$array_key . '_date_rfc' => dol_print_date ( $date , 'dayrfc' ),
$array_key . '_date_limit' => ( ! empty ( $object -> date_lim_reglement ) ? dol_print_date ( $object -> date_lim_reglement , 'day' ) : '' ),
$array_key . '_date_limit_rfc' => ( ! empty ( $object -> date_lim_reglement ) ? dol_print_date ( $object -> date_lim_reglement , 'dayrfc' ) : '' ),
2024-10-13 14:45:42 +00:00
$array_key . '_date_end' => ( ! empty ( $object -> fin_validite ) ? dol_print_date ( $object -> fin_validite , 'day' ) : '' ), // @phan-suppress-current-line PhanUndeclaredProperty
2024-03-10 00:55:56 +00:00
$array_key . '_date_creation' => dol_print_date ( $object -> date_creation , 'day' ),
$array_key . '_date_modification' => ( ! empty ( $object -> date_modification ) ? dol_print_date ( $object -> date_modification , 'day' ) : '' ),
$array_key . '_date_validation' => ( ! empty ( $object -> date_validation ) ? dol_print_date ( $object -> date_validation , 'dayhour' ) : '' ),
$array_key . '_date_approve' => ( ! empty ( $object -> date_approve ) ? dol_print_date ( $object -> date_approve , 'day' ) : '' ),
$array_key . '_date_delivery_planed' => ( ! empty ( $object -> delivery_date ) ? dol_print_date ( $object -> delivery_date , 'day' ) : '' ),
$array_key . '_date_close' => ( ! empty ( $object -> date_cloture ) ? dol_print_date ( $object -> date_cloture , 'dayhour' ) : '' ),
$array_key . '_payment_mode_code' => $object -> mode_reglement_code ,
$array_key . '_payment_mode' => ( $outputlangs -> transnoentitiesnoconv ( 'PaymentType' . $object -> mode_reglement_code ) != 'PaymentType' . $object -> mode_reglement_code ? $outputlangs -> transnoentitiesnoconv ( 'PaymentType' . $object -> mode_reglement_code ) : $object -> mode_reglement ),
$array_key . '_payment_term_code' => $object -> cond_reglement_code ,
2025-06-10 00:24:08 +00:00
$array_key . '_payment_term' => ( $outputlangs -> transnoentitiesnoconv ( 'PaymentCondition' . $object -> cond_reglement_code ) != 'PaymentCondition' . $object -> cond_reglement_code ? $outputlangs -> transnoentitiesnoconv ( 'PaymentCondition' . $object -> cond_reglement_code ) : $object -> cond_reglement_doc ),
2021-11-08 02:21:15 +00:00
2022-06-07 17:27:43 +00:00
$array_key . '_incoterms' => ( method_exists ( $object , 'display_incoterms' ) ? $object -> display_incoterms () : '' ),
2021-11-08 02:21:15 +00:00
2024-03-10 00:55:56 +00:00
$array_key . '_total_ht_locale' => price ( $object -> total_ht , 0 , $outputlangs ),
2024-10-13 14:45:42 +00:00
$array_key . '_total_vat_locale' => ( ! empty ( $object -> total_vat ) ? price ( $object -> total_vat , 0 , $outputlangs ) : price ( $object -> total_tva , 0 , $outputlangs )), // @phan-suppress-current-line PhanUndeclaredProperty
2024-03-10 00:55:56 +00:00
$array_key . '_total_localtax1_locale' => price ( $object -> total_localtax1 , 0 , $outputlangs ),
$array_key . '_total_localtax2_locale' => price ( $object -> total_localtax2 , 0 , $outputlangs ),
$array_key . '_total_ttc_locale' => price ( $object -> total_ttc , 0 , $outputlangs ),
2021-11-08 02:21:15 +00:00
2024-03-10 00:55:56 +00:00
$array_key . '_total_ht' => price2num ( $object -> total_ht ),
2024-10-13 14:45:42 +00:00
$array_key . '_total_vat' => ( ! empty ( $object -> total_vat ) ? price2num ( $object -> total_vat ) : price2num ( $object -> total_tva )), // @phan-suppress-current-line PhanUndeclaredProperty
2024-03-10 00:55:56 +00:00
$array_key . '_total_localtax1' => price2num ( $object -> total_localtax1 ),
$array_key . '_total_localtax2' => price2num ( $object -> total_localtax2 ),
$array_key . '_total_ttc' => price2num ( $object -> total_ttc ),
2021-11-08 02:21:15 +00:00
$array_key . '_multicurrency_code' => $object -> multicurrency_code ,
$array_key . '_multicurrency_tx' => price2num ( $object -> multicurrency_tx ),
$array_key . '_multicurrency_total_ht' => price2num ( $object -> multicurrency_total_ht ),
$array_key . '_multicurrency_total_tva' => price2num ( $object -> multicurrency_total_tva ),
$array_key . '_multicurrency_total_ttc' => price2num ( $object -> multicurrency_total_ttc ),
$array_key . '_multicurrency_total_ht_locale' => price ( $object -> multicurrency_total_ht , 0 , $outputlangs ),
$array_key . '_multicurrency_total_tva_locale' => price ( $object -> multicurrency_total_tva , 0 , $outputlangs ),
$array_key . '_multicurrency_total_ttc_locale' => price ( $object -> multicurrency_total_ttc , 0 , $outputlangs ),
2024-03-10 00:55:56 +00:00
$array_key . '_note_private' => $object -> note_private ,
$array_key . '_note_public' => $object -> note_public ,
$array_key . '_note' => $object -> note_public , // For backward compatibility
2021-11-08 02:21:15 +00:00
// Payments
2025-08-12 02:08:20 +00:00
$array_key . '_already_payed_locale' => price ( $totalpaid , 0 , $outputlangs ),
$array_key . '_already_payed' => price2num ( $totalpaid ),
$array_key . '_already_deposit_locale' => price ( $totaldeposits , 0 , $outputlangs ),
$array_key . '_already_deposit' => price2num ( $totaldeposits ),
$array_key . '_already_creditnote_locale' => price ( $totalcreditnotes , 0 , $outputlangs ),
$array_key . '_already_creditnote' => price2num ( $totalcreditnotes ),
2021-11-08 02:21:15 +00:00
2024-03-10 00:55:56 +00:00
$array_key . '_already_payed_all_locale' => price ( price2num ( $already_payed_all , 'MT' ), 0 , $outputlangs ),
$array_key . '_already_payed_all' => price2num ( $already_payed_all , 'MT' ),
2021-11-08 02:21:15 +00:00
// Remain to pay with all known information (except open direct debit requests)
2024-03-10 00:55:56 +00:00
$array_key . '_remain_to_pay_locale' => price ( price2num ( $object -> total_ttc - $already_payed_all , 'MT' ), 0 , $outputlangs ),
$array_key . '_remain_to_pay' => price2num ( $object -> total_ttc - $already_payed_all , 'MT' )
2014-05-07 11:22:02 +00:00
);
2013-03-23 17:04:46 +00:00
2026-06-21 19:38:15 +00:00
if ( in_array ( $object -> element , array ( 'facture' , 'invoice' , 'supplier_invoice' , 'facture_fournisseur' , 'commande' ))) {
2023-08-11 08:58:04 +00:00
$bank_account = null ;
if ( property_exists ( $object , 'fk_account' ) && $object -> fk_account > 0 ) {
require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php' ;
$bank_account = new Account ( $this -> db );
2025-09-17 12:11:32 +00:00
$bank_account -> fetch (( int ) $object -> fk_account );
2023-08-11 08:58:04 +00:00
}
$resarray [ $array_key . '_bank_iban' ] = ( empty ( $bank_account ) ? '' : $bank_account -> iban );
$resarray [ $array_key . '_bank_bic' ] = ( empty ( $bank_account ) ? '' : $bank_account -> bic );
$resarray [ $array_key . '_bank_label' ] = ( empty ( $bank_account ) ? '' : $bank_account -> label );
$resarray [ $array_key . '_bank_number' ] = ( empty ( $bank_account ) ? '' : $bank_account -> number );
2024-10-24 10:38:41 +00:00
$resarray [ $array_key . '_bank_proprio' ] = ( empty ( $bank_account ) ? '' : $bank_account -> owner_name );
2024-03-10 00:55:56 +00:00
$resarray [ $array_key . '_bank_address' ] = ( empty ( $bank_account ) ? '' : $bank_account -> address );
$resarray [ $array_key . '_bank_state' ] = ( empty ( $bank_account ) ? '' : $bank_account -> state );
$resarray [ $array_key . '_bank_country' ] = ( empty ( $bank_account ) ? '' : $bank_account -> country );
2023-08-10 13:46:10 +00:00
}
2023-08-11 08:58:04 +00:00
2021-11-10 14:16:36 +00:00
if ( method_exists ( $object , 'getTotalDiscount' ) && in_array ( get_class ( $object ), array ( 'Propal' , 'Proposal' , 'Commande' , 'Facture' , 'SupplierProposal' , 'CommandeFournisseur' , 'FactureFournisseur' ))) {
2017-08-18 09:30:13 +00:00
$resarray [ $array_key . '_total_discount_ht_locale' ] = price ( $object -> getTotalDiscount (), 0 , $outputlangs );
$resarray [ $array_key . '_total_discount_ht' ] = price2num ( $object -> getTotalDiscount ());
} else {
$resarray [ $array_key . '_total_discount_ht_locale' ] = '' ;
$resarray [ $array_key . '_total_discount_ht' ] = '' ;
}
2024-12-16 10:10:52 +00:00
if ( $object -> element == 'facture' || $object -> element == 'invoice_supplier' ) {
if ( $object -> type == 0 ) {
$resarray [ $array_key . '_type_label' ] = $outputlangs -> transnoentities ( " PdfInvoiceTitle " );
} else {
$resarray [ $array_key . '_type_label' ] = ( empty ( $object )) ? '' : $object -> getLibType ( 0 );
}
}
2017-09-30 13:40:17 +00:00
// Fetch project information if there is a project assigned to this object
2021-02-23 21:03:23 +00:00
if ( $object -> element != " project " && ! empty ( $object -> fk_project ) && $object -> fk_project > 0 ) {
if ( ! is_object ( $object -> project )) {
2024-10-26 20:43:44 +00:00
$object -> fetchProject ();
2017-09-30 13:40:17 +00:00
}
2018-02-14 20:14:24 +00:00
2017-09-30 13:40:17 +00:00
$resarray [ $array_key . '_project_ref' ] = $object -> project -> ref ;
$resarray [ $array_key . '_project_title' ] = $object -> project -> title ;
$resarray [ $array_key . '_project_description' ] = $object -> project -> description ;
$resarray [ $array_key . '_project_date_start' ] = dol_print_date ( $object -> project -> date_start , 'day' );
$resarray [ $array_key . '_project_date_end' ] = dol_print_date ( $object -> project -> date_end , 'day' );
2023-02-08 15:41:06 +00:00
} else { // empty replacement
2024-03-10 00:55:56 +00:00
$resarray [ $array_key . '_project_ref' ] = '' ;
2023-02-08 15:41:06 +00:00
$resarray [ $array_key . '_project_title' ] = '' ;
$resarray [ $array_key . '_project_description' ] = '' ;
$resarray [ $array_key . '_project_date_start' ] = '' ;
$resarray [ $array_key . '_project_date_end' ] = '' ;
2017-09-30 13:40:17 +00:00
}
2014-05-07 11:22:02 +00:00
// Add vat by rates
2021-02-23 21:03:23 +00:00
if ( is_array ( $object -> lines ) && count ( $object -> lines ) > 0 ) {
2019-01-24 20:08:13 +00:00
$totalUp = 0 ;
2021-11-11 13:55:59 +00:00
// Set substitution keys for different VAT rates
2021-02-23 21:03:23 +00:00
foreach ( $object -> lines as $line ) {
2021-11-11 13:55:59 +00:00
// $line->tva_tx format depends on database field accuracy, no reliable. This is kept for backward compatibility
2021-02-23 21:03:23 +00:00
if ( empty ( $resarray [ $array_key . '_total_vat_' . $line -> tva_tx ])) {
$resarray [ $array_key . '_total_vat_' . $line -> tva_tx ] = 0 ;
}
2020-03-12 11:45:44 +00:00
$resarray [ $array_key . '_total_vat_' . $line -> tva_tx ] += $line -> total_tva ;
$resarray [ $array_key . '_total_vat_locale_' . $line -> tva_tx ] = price ( $resarray [ $array_key . '_total_vat_' . $line -> tva_tx ]);
2020-10-07 13:01:28 +00:00
// $vatformated is vat without not expected chars (so 20, or 8.5 or 5.99 for example)
2020-03-12 11:45:44 +00:00
$vatformated = vatrate ( $line -> tva_tx );
2021-02-23 21:03:23 +00:00
if ( empty ( $resarray [ $array_key . '_total_vat_' . $vatformated ])) {
$resarray [ $array_key . '_total_vat_' . $vatformated ] = 0 ;
}
2020-03-12 11:45:44 +00:00
$resarray [ $array_key . '_total_vat_' . $vatformated ] += $line -> total_tva ;
$resarray [ $array_key . '_total_vat_locale_' . $vatformated ] = price ( $resarray [ $array_key . '_total_vat_' . $vatformated ]);
2019-02-13 10:32:00 +00:00
2019-01-24 20:08:13 +00:00
$totalUp += $line -> subprice * $line -> qty ;
}
2019-02-13 10:32:00 +00:00
2021-08-08 10:35:52 +00:00
// Calculate total up and total discount percentage
2021-06-20 03:11:46 +00:00
// Note that this added fields does not match a field into database in Dolibarr (Dolibarr manage discount on lines not as a global property of object)
2019-01-24 20:08:13 +00:00
$resarray [ 'object_total_up' ] = $totalUp ;
$resarray [ 'object_total_up_locale' ] = price ( $resarray [ 'object_total_up' ], 0 , $outputlangs );
2021-11-10 14:16:36 +00:00
if ( method_exists ( $object , 'getTotalDiscount' ) && in_array ( get_class ( $object ), array ( 'Propal' , 'Proposal' , 'Commande' , 'Facture' , 'SupplierProposal' , 'CommandeFournisseur' , 'FactureFournisseur' ))) {
2019-11-13 18:35:39 +00:00
$totalDiscount = $object -> getTotalDiscount ();
2019-09-02 07:44:59 +00:00
} else {
2019-11-13 18:35:39 +00:00
$totalDiscount = 0 ;
2019-09-02 07:44:59 +00:00
}
if ( ! empty ( $totalUp ) && ! empty ( $totalDiscount )) {
$resarray [ 'object_total_discount' ] = round ( 100 / $totalUp * $totalDiscount , 2 );
2019-01-24 20:08:13 +00:00
$resarray [ 'object_total_discount_locale' ] = price ( $resarray [ 'object_total_discount' ], 0 , $outputlangs );
2019-09-02 07:44:59 +00:00
} else {
2019-11-13 18:35:39 +00:00
$resarray [ 'object_total_discount' ] = '' ;
$resarray [ 'object_total_discount_locale' ] = '' ;
2017-08-18 09:35:20 +00:00
}
2014-05-07 11:22:02 +00:00
}
2019-02-13 10:32:00 +00:00
2014-05-07 11:22:02 +00:00
// Retrieve extrafields
2021-02-23 21:03:23 +00:00
if ( is_array ( $object -> array_options ) && count ( $object -> array_options )) {
2018-02-21 13:48:25 +00:00
$object -> fetch_optionals ();
2014-05-07 11:22:02 +00:00
2019-01-27 10:55:16 +00:00
$resarray = $this -> fill_substitutionarray_with_extrafields ( $object , $resarray , $extrafields , $array_key , $outputlangs );
2014-05-07 11:22:02 +00:00
}
2023-06-11 00:14:21 +00:00
2014-05-07 11:22:02 +00:00
return $resarray ;
}
2020-10-07 13:01:28 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2014-05-07 11:22:02 +00:00
/**
* Define array with couple substitution key => substitution value
2023-07-22 11:29:00 +00:00
* Note that vars into substitutions array are formatted .
2014-05-07 11:22:02 +00:00
*
2024-06-10 23:06:52 +00:00
* @ param CommonObjectLine $line Object line
* @ param Translate $outputlangs Translate object to use for output
* @ param int $linenumber The number of the line for the substitution of " object_line_pos "
2024-09-22 22:37:30 +00:00
* @ return array < string , mixed > Return a substitution array
2014-05-07 11:22:02 +00:00
*/
2020-02-24 13:55:02 +00:00
public function get_substitutionarray_lines ( $line , $outputlangs , $linenumber = 0 )
2014-05-07 11:22:02 +00:00
{
2020-10-07 13:01:28 +00:00
// phpcs:enable
2019-11-13 18:35:39 +00:00
$resarray = array (
2020-02-24 13:55:02 +00:00
'line_pos' => $linenumber ,
2024-03-10 00:55:56 +00:00
'line_fulldesc' => doc_getlinedesc ( $line , $outputlangs ),
'line_product_ref' => ( empty ( $line -> product_ref ) ? '' : $line -> product_ref ),
'line_product_label' => ( empty ( $line -> product_label ) ? '' : $line -> product_label ),
'line_product_type' => ( empty ( $line -> product_type ) ? '' : $line -> product_type ),
'line_product_barcode' => ( empty ( $line -> product_barcode ) ? '' : $line -> product_barcode ),
'line_product_desc' => ( empty ( $line -> product_desc ) ? '' : $line -> product_desc ),
'line_desc' => $line -> desc ,
2025-09-21 21:22:33 +00:00
'line_vatrate' => vatrate ( $line -> tva_tx , true , ( int ) $line -> info_bits ),
2024-03-10 00:55:56 +00:00
'line_up' => price2num ( $line -> subprice ),
'line_up_locale' => price ( $line -> subprice , 0 , $outputlangs ),
2024-03-28 00:51:33 +00:00
'line_total_up' => price2num ( $line -> subprice * ( float ) $line -> qty ),
'line_total_up_locale' => price ( $line -> subprice * ( float ) $line -> qty , 0 , $outputlangs ),
2024-03-10 00:55:56 +00:00
'line_qty' => $line -> qty ,
2025-08-20 17:05:07 +00:00
'line_qty_locale' => price ( $line -> qty ),
2024-03-10 00:55:56 +00:00
'line_discount_percent' => ( $line -> remise_percent ? $line -> remise_percent . '%' : '' ),
'line_price_ht' => price2num ( $line -> total_ht ),
'line_price_ttc' => price2num ( $line -> total_ttc ),
'line_price_vat' => price2num ( $line -> total_tva ),
'line_price_ht_locale' => price ( $line -> total_ht , 0 , $outputlangs ),
'line_price_ttc_locale' => price ( $line -> total_ttc , 0 , $outputlangs ),
'line_price_vat_locale' => price ( $line -> total_tva , 0 , $outputlangs ),
2020-10-07 13:01:28 +00:00
'line_multicurrency_code' => price2num ( $line -> multicurrency_code ),
'line_multicurrency_subprice' => price2num ( $line -> multicurrency_subprice ),
'line_multicurrency_total_ht' => price2num ( $line -> multicurrency_total_ht ),
'line_multicurrency_total_tva' => price2num ( $line -> multicurrency_total_tva ),
'line_multicurrency_total_ttc' => price2num ( $line -> multicurrency_total_ttc ),
'line_multicurrency_subprice_locale' => price ( $line -> multicurrency_subprice , 0 , $outputlangs ),
'line_multicurrency_total_ht_locale' => price ( $line -> multicurrency_total_ht , 0 , $outputlangs ),
'line_multicurrency_total_tva_locale' => price ( $line -> multicurrency_total_tva , 0 , $outputlangs ),
'line_multicurrency_total_ttc_locale' => price ( $line -> multicurrency_total_ttc , 0 , $outputlangs ),
2014-05-07 11:22:02 +00:00
);
2018-02-14 20:14:24 +00:00
2024-10-13 14:45:42 +00:00
if ( property_exists ( $line , 'ref_fourn' )) {
$resarray [ 'line_product_ref_fourn' ] = $line -> ref_fourn ; // for supplier doc lines @phan-suppress-current-line PhanUndeclaredProperty
} else {
$resarray [ 'line_product_ref_fourn' ] = '' ;
}
$vat_specs = array (
'line_localtax1_rate' => 'localtax1_tx' ,
'line_localtax2_rate' => 'localtax2_tx' ,
);
2025-03-24 14:16:44 +00:00
foreach ( $vat_specs as $vat_key => $vat_spec ) {
if ( property_exists ( $line , $vat_spec )) {
2025-03-24 14:42:07 +00:00
// @phan-suppress-next-line PhanUndeclaredProperty
2025-03-24 14:16:44 +00:00
$resarray [ $vat_key ] = vatrate ( $line -> $vat_spec );
2024-10-13 14:45:42 +00:00
}
}
// Dates (fields not available on all line classes)
$date_specs = array (
array ( 'line_date_start' , 'date_start' , 'day' , 'auto' , null ),
array ( 'line_date_start_locale' , 'date_start' , 'day' , 'tzserver' , $outputlangs ),
array ( 'line_date_start_rfc' , 'date_start' , 'dayrfc' , 'auto' , null ),
2024-11-08 13:47:45 +00:00
array ( 'line_date_start_real' , 'date_start_real' , 'day' , 'auto' , null ),
array ( 'line_date_start_real_locale' , 'date_start_real' , 'day' , 'tzserver' , $outputlangs ),
array ( 'line_date_start_real_rfc' , 'date_start_real' , 'dayrfc' , 'auto' , null ),
2024-10-13 14:45:42 +00:00
array ( 'line_date_end' , 'date_end' , 'day' , 'auto' , null ),
array ( 'line_date_end_locale' , 'date_end' , 'day' , 'tzserver' , $outputlangs ),
array ( 'line_date_end_rfc' , 'date_end' , 'dayrfc' , 'auto' , null )
);
foreach ( $date_specs as $date_spec ) {
2025-02-06 10:39:56 +00:00
$propertyname = $date_spec [ 1 ];
if ( property_exists ( $line , $propertyname )) {
2025-02-07 09:46:13 +00:00
// @phan-suppress-next-line PhanUndeclaredProperty
2025-02-06 10:39:56 +00:00
$resarray [ $date_spec [ 0 ]] = dol_print_date ( $line -> $propertyname , $date_spec [ 2 ], $date_spec [ 3 ], $date_spec [ 4 ]);
2024-10-13 14:45:42 +00:00
}
}
2020-10-07 13:01:28 +00:00
// Units
2022-12-30 11:45:22 +00:00
if ( getDolGlobalInt ( 'PRODUCT_USE_UNITS' )) {
2025-08-21 09:02:48 +00:00
$resarray [ 'line_unit' ] = $line -> getLabelOfUnit ( 'long' , $outputlangs );
$resarray [ 'line_unit_short' ] = $line -> getLabelOfUnit ( 'short' , $outputlangs );
//$resarray['line_unit_code'] = $line->getLabelOfUnit('code', $outputlangs);
2020-10-07 13:01:28 +00:00
}
2015-01-12 17:18:43 +00:00
// Retrieve extrafields
2020-04-23 13:50:42 +00:00
$extrafieldkey = $line -> table_element ;
2020-03-12 11:45:44 +00:00
$array_key = " line " ;
2015-01-12 17:18:43 +00:00
require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php' ;
$extrafields = new ExtraFields ( $this -> db );
2019-10-06 12:41:52 +00:00
$extrafields -> fetch_name_optionals_label ( $extrafieldkey , true );
2018-02-21 13:48:25 +00:00
$line -> fetch_optionals ();
2015-01-12 17:18:43 +00:00
2020-10-07 13:01:28 +00:00
$resarray = $this -> fill_substitutionarray_with_extrafields ( $line , $resarray , $extrafields , $array_key , $outputlangs );
2019-11-02 16:38:19 +00:00
2020-10-07 13:01:28 +00:00
// Check if the current line belongs to a supplier order
2021-02-23 21:03:23 +00:00
if ( get_class ( $line ) == 'CommandeFournisseurLigne' ) {
2020-10-07 13:01:28 +00:00
// Add the product supplier extrafields to the substitutions
$extrafields -> fetch_name_optionals_label ( " product_fournisseur_price " );
$extralabels = $extrafields -> attributes [ " product_fournisseur_price " ][ 'label' ];
2020-03-10 08:02:38 +00:00
2021-02-23 21:03:23 +00:00
if ( ! empty ( $extralabels ) && is_array ( $extralabels )) {
2020-03-10 08:02:38 +00:00
$columns = " " ;
2021-02-23 21:03:23 +00:00
foreach ( $extralabels as $key => $label ) {
2020-03-10 08:02:38 +00:00
$columns .= " $key , " ;
}
2021-02-23 21:03:23 +00:00
if ( $columns != " " ) {
2020-03-10 08:02:38 +00:00
$columns = substr ( $columns , 0 , strlen ( $columns ) - 2 );
2022-01-27 09:19:35 +00:00
$resql = $this -> db -> query ( " SELECT " . $columns . " FROM " . $this -> db -> prefix () . " product_fournisseur_price_extrafields AS ex INNER JOIN " . $this -> db -> prefix () . " product_fournisseur_price AS f ON ex.fk_object = f.rowid WHERE f.ref_fourn = ' " . $this -> db -> escape ( $line -> ref_supplier ) . " ' " );
2020-03-10 08:02:38 +00:00
2021-02-23 21:03:23 +00:00
if ( $this -> db -> num_rows ( $resql ) > 0 ) {
2020-03-10 08:02:38 +00:00
$resql = $this -> db -> fetch_object ( $resql );
2021-02-23 21:03:23 +00:00
foreach ( $extralabels as $key => $label ) {
2022-12-30 17:43:43 +00:00
$resarray [ 'line_product_supplier_' . $key ] = $resql -> $key ;
2020-03-10 08:02:38 +00:00
}
}
}
}
2020-10-07 13:01:28 +00:00
}
2018-02-14 20:14:24 +00:00
2025-01-03 12:25:20 +00:00
// Check if the current line belongs to a shipment
if ( get_class ( $line ) == 'ExpeditionLigne' ) {
$resarray [ 'line_qty_shipped' ] = $line -> qty_shipped ;
$resarray [ 'line_qty_asked' ] = $line -> qty_asked ;
$resarray [ 'line_weight' ] = empty ( $line -> weight ) ? '' : $line -> weight * $line -> qty_shipped . ' ' . measuringUnitString ( 0 , 'weight' , $line -> weight_units );
$resarray [ 'line_length' ] = empty ( $line -> length ) ? '' : $line -> length * $line -> qty_shipped . ' ' . measuringUnitString ( 0 , 'size' , $line -> length_units );
$resarray [ 'line_surface' ] = empty ( $line -> surface ) ? '' : $line -> surface * $line -> qty_shipped . ' ' . measuringUnitString ( 0 , 'surface' , $line -> surface_units );
$resarray [ 'line_volume' ] = empty ( $line -> volume ) ? '' : $line -> volume * $line -> qty_shipped . ' ' . measuringUnitString ( 0 , 'volume' , $line -> volume_units );
}
2018-02-12 20:38:51 +00:00
// Load product data optional fields to the line -> enables to use "line_options_{extrafield}"
2021-02-23 21:03:23 +00:00
if ( isset ( $line -> fk_product ) && $line -> fk_product > 0 ) {
2018-02-14 20:14:24 +00:00
$tmpproduct = new Product ( $this -> db );
$result = $tmpproduct -> fetch ( $line -> fk_product );
2024-04-06 11:28:58 +00:00
if ( ! empty ( $tmpproduct -> array_options ) && is_array ( $tmpproduct -> array_options )) {
foreach ( $tmpproduct -> array_options as $key => $label ) {
$resarray [ " line_product_ " . $key ] = $label ;
}
2021-02-23 21:03:23 +00:00
}
2023-02-08 15:41:06 +00:00
} else {
// Set unused placeholders as blank
$extrafields -> fetch_name_optionals_label ( " product " );
2023-12-11 11:07:33 +00:00
if ( $extrafields -> attributes [ " product " ][ 'count' ] > 0 ) {
$extralabels = $extrafields -> attributes [ " product " ][ 'label' ];
2023-02-08 15:41:06 +00:00
2023-12-11 11:07:33 +00:00
foreach ( $extralabels as $key => $label ) {
$resarray [ 'line_product_options_' . $key ] = '' ;
}
2023-02-08 15:41:06 +00:00
}
2018-02-14 20:14:24 +00:00
}
2015-01-12 17:18:43 +00:00
return $resarray ;
2014-05-07 11:22:02 +00:00
}
2014-01-15 23:07:45 +00:00
2020-10-07 13:01:28 +00:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Define array with couple substitution key => substitution value
2023-07-22 11:29:00 +00:00
* Note that vars into substitutions array are formatted .
2020-10-07 13:01:28 +00:00
*
* @ param Expedition $object Main object to use as data source
* @ param Translate $outputlangs Lang object to use for output
2023-12-21 12:43:19 +00:00
* @ param string $array_key Name of the key for return array
2024-09-22 22:37:30 +00:00
* @ return array < string , mixed > Array of substitution
2020-10-07 13:01:28 +00:00
*/
public function get_substitutionarray_shipment ( $object , $outputlangs , $array_key = 'object' )
{
// phpcs:enable
2024-01-04 14:23:46 +00:00
global $extrafields ;
include_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php' ;
2026-01-20 12:56:52 +00:00
$object -> list_delivery_methods (( int ) $object -> shipping_method_id );
2024-03-23 00:12:31 +00:00
$calculatedVolume = (( float ) $object -> trueWidth * ( float ) $object -> trueHeight * ( float ) $object -> trueDepth );
2013-07-19 15:27:22 +00:00
2020-10-07 13:01:28 +00:00
$array_shipment = array (
2024-03-10 00:55:56 +00:00
$array_key . '_id' => $object -> id ,
$array_key . '_ref' => $object -> ref ,
$array_key . '_ref_ext' => $object -> ref_ext ,
$array_key . '_ref_customer' => $object -> ref_customer ,
2025-01-05 13:05:50 +00:00
$array_key . '_date_delivery' => dol_print_date ( $object -> date_delivery , 'day' ), // note: for shipment, delivery and reception: date_delivery, for orders: delivery_date
2024-03-10 00:55:56 +00:00
$array_key . '_hour_delivery' => dol_print_date ( $object -> date_delivery , 'hour' ),
$array_key . '_date_creation' => dol_print_date ( $object -> date_creation , 'day' ),
$array_key . '_total_ht' => price ( $object -> total_ht ),
$array_key . '_total_vat' => price ( $object -> total_tva ),
$array_key . '_total_ttc' => price ( $object -> total_ttc ),
2020-10-07 13:01:28 +00:00
$array_key . '_total_discount_ht' => price ( $object -> getTotalDiscount ()),
2024-03-10 00:55:56 +00:00
$array_key . '_note_private' => $object -> note_private ,
$array_key . '_note' => $object -> note_public ,
$array_key . '_tracking_number' => $object -> tracking_number ,
$array_key . '_tracking_url' => $object -> tracking_url ,
$array_key . '_shipping_method' => $object -> listmeths [ 0 ][ 'libelle' ],
2025-02-08 17:30:42 +00:00
$array_key . '_weight' => $object -> trueWeight . ' ' . measuringUnitString ( 0 , 'weight' , $object -> weight_units ),
2024-03-10 00:55:56 +00:00
$array_key . '_width' => $object -> trueWidth . ' ' . measuringUnitString ( 0 , 'size' , $object -> width_units ),
$array_key . '_height' => $object -> trueHeight . ' ' . measuringUnitString ( 0 , 'size' , $object -> height_units ),
$array_key . '_depth' => $object -> trueDepth . ' ' . measuringUnitString ( 0 , 'size' , $object -> depth_units ),
$array_key . '_size' => $calculatedVolume . ' ' . measuringUnitString ( 0 , 'volume' ),
2020-10-07 13:01:28 +00:00
);
// Add vat by rates
2021-02-23 21:03:23 +00:00
foreach ( $object -> lines as $line ) {
if ( empty ( $array_shipment [ $array_key . '_total_vat_' . $line -> tva_tx ])) {
$array_shipment [ $array_key . '_total_vat_' . $line -> tva_tx ] = 0 ;
}
2020-10-07 13:01:28 +00:00
$array_shipment [ $array_key . '_total_vat_' . $line -> tva_tx ] += $line -> total_tva ;
}
// Retrieve extrafields
2021-02-23 21:03:23 +00:00
if ( is_array ( $object -> array_options ) && count ( $object -> array_options )) {
2020-10-07 13:01:28 +00:00
$object -> fetch_optionals ();
$array_shipment = $this -> fill_substitutionarray_with_extrafields ( $object , $array_shipment , $extrafields , $array_key , $outputlangs );
}
2025-11-19 13:49:16 +00:00
// Add info from $object->origin_object which has been loaded by fetch() of shipment
if ( $object -> origin_type == 'commande' && is_object ( $object -> origin_object ) && ! empty ( $object -> origin_object -> ref )) {
$originOrder = $object -> origin_object ;
'@phan-var-force Commande $originOrder' ;
$array_shipment [ 'order_ref' ] = $originOrder -> ref ;
$array_shipment [ 'order_ref_customer' ] = $originOrder -> ref_customer ;
2020-12-06 18:01:09 +00:00
}
2025-01-06 16:01:47 +00:00
// Load dim data
$tmparray = $object -> getTotalWeightVolume ();
$totalWeight = $tmparray [ 'weight' ];
$totalVolume = $tmparray [ 'volume' ];
$totalOrdered = $tmparray [ 'ordered' ];
$totalToShip = $tmparray [ 'toship' ];
// Set trueVolume and volume_units not currently stored into database
if ( $object -> trueWidth && $object -> trueHeight && $object -> trueDepth ) {
2025-02-08 17:30:42 +00:00
$object -> trueVolume = $object -> trueWidth * $object -> trueHeight * $object -> trueDepth ;
$object -> volume_units = $object -> size_units * 3 ;
2025-01-06 16:01:47 +00:00
}
$array_shipment [ $array_key . '_total_ordered' ] = ( string ) $totalOrdered ;
$array_shipment [ $array_key . '_total_toship' ] = ( string ) $totalToShip ;
if ( $object -> trueWeight ) {
2026-01-20 12:56:52 +00:00
$array_shipment [ $array_key . '_total_weight' ] = ( empty ( $totalWeight )) ? '' : showDimensionInBestUnit ( $object -> trueWeight , ( int ) $object -> weight_units , " weight " , $outputlangs );
2025-01-06 16:01:47 +00:00
} elseif ( ! empty ( $totalWeight )) {
2025-02-08 17:30:42 +00:00
$array_shipment [ $array_key . '_total_weight' ] = showDimensionInBestUnit ( $totalWeight , 0 , " weight " , $outputlangs , - 1 , 'no' , 1 );
2025-01-06 16:01:47 +00:00
} else {
2025-02-08 17:30:42 +00:00
$array_shipment [ $array_key . '_total_weight' ] = " " ;
2025-01-06 16:01:47 +00:00
}
if ( ! empty ( $object -> trueVolume )) {
if ( $object -> volume_units < 50 ) {
2025-02-08 17:30:42 +00:00
$array_shipment [ $array_key . '_total_volume' ] = ( empty ( $totalVolume )) ? '' : showDimensionInBestUnit ( $object -> trueVolume , $object -> volume_units , " volume " , $outputlangs );
2025-01-06 16:01:47 +00:00
} else {
2025-02-08 17:30:42 +00:00
$array_shipment [ $array_key . '_total_volume' ] = ( empty ( $totalVolume )) ? '' : price ( $object -> trueVolume , 0 , $outputlangs , 0 , 0 ) . ' ' . measuringUnitString ( 0 , " volume " , $object -> volume_units );
2025-01-06 16:01:47 +00:00
}
} elseif ( ! empty ( $totalVolume )) {
2025-02-08 17:30:42 +00:00
$array_shipment [ $array_key . '_total_volume' ] = showDimensionInBestUnit ( $totalVolume , 0 , " volume " , $outputlangs , - 1 , 'no' , 1 );
2025-01-06 16:01:47 +00:00
} else {
2025-02-08 17:30:42 +00:00
$array_shipment [ $array_key . '_total_volume' ] = " " ;
2025-01-06 16:01:47 +00:00
}
2020-10-07 13:01:28 +00:00
return $array_shipment ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Define array with couple substitution key => substitution value
2025-11-12 08:44:39 +00:00
* @ phpstan - template T
2020-10-07 13:01:28 +00:00
*
2025-11-12 08:44:39 +00:00
* @ phpstan - param T $object
2025-02-06 11:01:21 +00:00
* @ param array < string , CommonObject | float | int | string >| CommonObject $object Dolibarr Object
2025-02-06 10:39:56 +00:00
* @ param Translate $outputlangs Language object for output
* @ param boolean | int $recursive Want to fetch child array or child object .
* @ return array < string , mixed > Array of substitution key -> code
2020-10-07 13:01:28 +00:00
*/
2022-06-07 17:59:33 +00:00
public function get_substitutionarray_each_var_object ( & $object , $outputlangs , $recursive = 1 )
2020-10-07 13:01:28 +00:00
{
// phpcs:enable
$array_other = array ();
2025-02-06 11:01:21 +00:00
if (( is_array ( $object ) && count ( $object )) || is_object ( $object )) {
// Loop on each entry of array or on each property of object
2020-10-07 13:01:28 +00:00
foreach ( $object as $key => $value ) {
2022-06-07 17:59:33 +00:00
if ( in_array ( $key , array ( 'db' , 'fields' , 'lines' , 'modelpdf' , 'model_pdf' ))) { // discard some properties
continue ;
}
2020-10-07 13:01:28 +00:00
if ( ! empty ( $value )) {
if ( ! is_array ( $value ) && ! is_object ( $value )) {
$array_other [ 'object_' . $key ] = $value ;
2022-06-07 17:27:43 +00:00
} elseif ( is_array ( $value ) && $recursive ) {
2022-06-07 17:59:33 +00:00
$tmparray = $this -> get_substitutionarray_each_var_object ( $value , $outputlangs , 0 );
2024-04-06 11:28:58 +00:00
if ( ! empty ( $tmparray ) && is_array ( $tmparray )) {
foreach ( $tmparray as $key2 => $value2 ) {
$array_other [ 'object_' . $key . '_' . preg_replace ( '/^object_/' , '' , $key2 )] = $value2 ;
}
2022-06-07 17:59:33 +00:00
}
2022-06-07 17:27:43 +00:00
} elseif ( is_object ( $value ) && $recursive ) {
2022-06-07 17:59:33 +00:00
$tmparray = $this -> get_substitutionarray_each_var_object ( $value , $outputlangs , 0 );
2024-04-06 11:28:58 +00:00
if ( ! empty ( $tmparray ) && is_array ( $tmparray )) {
foreach ( $tmparray as $key2 => $value2 ) {
$array_other [ 'object_' . $key . '_' . preg_replace ( '/^object_/' , '' , $key2 )] = $value2 ;
}
2022-06-07 17:59:33 +00:00
}
2020-10-07 13:01:28 +00:00
}
}
}
}
2022-06-07 17:59:33 +00:00
2020-10-07 13:01:28 +00:00
return $array_other ;
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Fill array with couple extrafield key => extrafield value
2023-07-22 11:29:00 +00:00
* Note that vars into substitutions array are formatted .
2020-10-07 13:01:28 +00:00
*
2026-01-28 13:58:18 +00:00
* @ param CommonObject $object Object with extrafields ( must have $object -> array_options filled )
2026-02-04 13:49:13 +00:00
* @ param array < string , null | int | float | string > $array_to_fill Substitution array
2026-01-28 13:58:18 +00:00
* @ param ExtraFields $extrafields ExtraFields object
* @ param string $array_key Prefix for name of the keys into returned array
* @ param Translate $outputlangs Lang object to use for output
* @ return array < string , float | string > Substitution array
2020-10-07 13:01:28 +00:00
*/
public function fill_substitutionarray_with_extrafields ( $object , $array_to_fill , $extrafields , $array_key , $outputlangs )
{
// phpcs:enable
2013-03-07 02:24:22 +00:00
global $conf ;
2020-02-28 23:13:42 +00:00
2023-12-11 11:07:33 +00:00
if ( $extrafields -> attributes [ $object -> table_element ][ 'count' ] > 0 ) {
2021-02-23 21:03:23 +00:00
foreach ( $extrafields -> attributes [ $object -> table_element ][ 'label' ] as $key => $label ) {
2023-07-22 11:29:00 +00:00
$formatedarrayoption = $object -> array_options ;
2021-02-23 21:03:23 +00:00
if ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ] == 'price' ) {
2023-07-22 11:29:00 +00:00
$formatedarrayoption [ 'options_' . $key ] = price2num ( $formatedarrayoption [ 'options_' . $key ]);
$formatedarrayoption [ 'options_' . $key . '_currency' ] = price ( $formatedarrayoption [ 'options_' . $key ], 0 , $outputlangs , 0 , 0 , - 1 , $conf -> currency );
2020-02-28 23:13:42 +00:00
//Add value to store price with currency
2023-07-22 11:29:00 +00:00
$array_to_fill = array_merge ( $array_to_fill , array ( $array_key . '_options_' . $key . '_currency' => $formatedarrayoption [ 'options_' . $key . '_currency' ]));
2021-02-23 21:03:23 +00:00
} elseif ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ] == 'select' ) {
2023-07-22 11:29:00 +00:00
$valueofselectkey = $formatedarrayoption [ 'options_' . $key ];
2022-07-24 11:44:47 +00:00
if ( array_key_exists ( $valueofselectkey , $extrafields -> attributes [ $object -> table_element ][ 'param' ][ $key ][ 'options' ])) {
2023-07-22 11:29:00 +00:00
$formatedarrayoption [ 'options_' . $key ] = $extrafields -> attributes [ $object -> table_element ][ 'param' ][ $key ][ 'options' ][ $valueofselectkey ];
2022-07-24 11:44:47 +00:00
} else {
2023-07-22 11:29:00 +00:00
$formatedarrayoption [ 'options_' . $key ] = '' ;
2022-07-24 11:44:47 +00:00
}
2020-05-21 13:05:19 +00:00
} elseif ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ] == 'checkbox' ) {
2023-07-22 11:29:00 +00:00
$valArray = explode ( ',' , $formatedarrayoption [ 'options_' . $key ]);
2020-03-12 11:45:44 +00:00
$output = array ();
2021-02-23 21:03:23 +00:00
foreach ( $extrafields -> attributes [ $object -> table_element ][ 'param' ][ $key ][ 'options' ] as $keyopt => $valopt ) {
2020-03-12 11:45:44 +00:00
if ( in_array ( $keyopt , $valArray )) {
$output [] = $valopt ;
2020-02-28 23:13:42 +00:00
}
2019-09-02 07:41:30 +00:00
}
2023-07-22 11:29:00 +00:00
$formatedarrayoption [ 'options_' . $key ] = implode ( ', ' , $output );
2021-02-23 21:03:23 +00:00
} elseif ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ] == 'date' ) {
2023-07-22 11:29:00 +00:00
if ( strlen ( $formatedarrayoption [ 'options_' . $key ]) > 0 ) {
$date = $formatedarrayoption [ 'options_' . $key ];
$formatedarrayoption [ 'options_' . $key ] = dol_print_date ( $date , 'day' ); // using company output language
$formatedarrayoption [ 'options_' . $key . '_locale' ] = dol_print_date ( $date , 'day' , 'tzserver' , $outputlangs ); // using output language format
$formatedarrayoption [ 'options_' . $key . '_rfc' ] = dol_print_date ( $date , 'dayrfc' ); // international format
2020-05-21 13:05:19 +00:00
} else {
2023-07-22 11:29:00 +00:00
$formatedarrayoption [ 'options_' . $key ] = '' ;
$formatedarrayoption [ 'options_' . $key . '_locale' ] = '' ;
$formatedarrayoption [ 'options_' . $key . '_rfc' ] = '' ;
2020-02-28 23:13:42 +00:00
}
2023-07-22 11:29:00 +00:00
$array_to_fill = array_merge ( $array_to_fill , array ( $array_key . '_options_' . $key . '_locale' => $formatedarrayoption [ 'options_' . $key . '_locale' ]));
$array_to_fill = array_merge ( $array_to_fill , array ( $array_key . '_options_' . $key . '_rfc' => $formatedarrayoption [ 'options_' . $key . '_rfc' ]));
2023-06-13 07:39:37 +00:00
} elseif ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ] == 'datetime' ) {
2023-07-22 11:29:00 +00:00
$datetime = $formatedarrayoption [ 'options_' . $key ];
2023-07-22 11:45:35 +00:00
$formatedarrayoption [ 'options_' . $key ] = ( $datetime != " 0000-00-00 00:00:00 " ? dol_print_date ( $datetime , 'dayhour' ) : '' ); // using company output language
$formatedarrayoption [ 'options_' . $key . '_locale' ] = ( $datetime != " 0000-00-00 00:00:00 " ? dol_print_date ( $datetime , 'dayhour' , 'tzserver' , $outputlangs ) : '' ); // using output language format
$formatedarrayoption [ 'options_' . $key . '_rfc' ] = ( $datetime != " 0000-00-00 00:00:00 " ? dol_print_date ( $datetime , 'dayhourrfc' ) : '' ); // international format
2023-07-22 11:29:00 +00:00
$array_to_fill = array_merge ( $array_to_fill , array ( $array_key . '_options_' . $key . '_locale' => $formatedarrayoption [ 'options_' . $key . '_locale' ]));
$array_to_fill = array_merge ( $array_to_fill , array ( $array_key . '_options_' . $key . '_rfc' => $formatedarrayoption [ 'options_' . $key . '_rfc' ]));
2021-02-23 21:03:23 +00:00
} elseif ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ] == 'link' ) {
2023-07-22 11:29:00 +00:00
$id = $formatedarrayoption [ 'options_' . $key ];
2021-02-23 21:03:23 +00:00
if ( $id != " " ) {
2020-02-28 23:13:42 +00:00
$param = $extrafields -> attributes [ $object -> table_element ][ 'param' ][ $key ];
2020-03-12 11:45:44 +00:00
$param_list = array_keys ( $param [ 'options' ]); // $param_list='ObjectName:classPath'
2020-02-28 23:13:42 +00:00
$InfoFieldList = explode ( " : " , $param_list [ 0 ]);
2020-03-12 11:45:44 +00:00
$classname = $InfoFieldList [ 0 ];
$classpath = $InfoFieldList [ 1 ];
2021-02-23 21:03:23 +00:00
if ( ! empty ( $classpath )) {
2020-02-28 23:13:42 +00:00
dol_include_once ( $InfoFieldList [ 1 ]);
2021-02-23 21:03:23 +00:00
if ( $classname && class_exists ( $classname )) {
2020-02-28 23:13:42 +00:00
$tmpobject = new $classname ( $this -> db );
2024-08-17 17:32:52 +00:00
'@phan-var-force CommonObject $tmpobject' ;
2020-02-28 23:13:42 +00:00
$tmpobject -> fetch ( $id );
// completely replace the id with the linked object name
2023-07-22 11:29:00 +00:00
$formatedarrayoption [ 'options_' . $key ] = $tmpobject -> name ;
2020-02-28 23:13:42 +00:00
}
2018-07-24 15:03:30 +00:00
}
}
}
2023-07-22 11:29:00 +00:00
if ( array_key_exists ( 'options_' . $key , $formatedarrayoption )) {
$array_to_fill = array_merge ( $array_to_fill , array ( $array_key . '_options_' . $key => $formatedarrayoption [ 'options_' . $key ]));
2022-07-24 11:44:47 +00:00
} else {
$array_to_fill = array_merge ( $array_to_fill , array ( $array_key . '_options_' . $key => '' ));
}
2020-02-28 23:13:42 +00:00
}
2013-03-07 02:24:22 +00:00
}
2013-03-23 17:04:46 +00:00
2013-03-07 02:24:22 +00:00
return $array_to_fill ;
}
2013-03-23 17:04:46 +00:00
2012-08-08 02:12:20 +00:00
/**
* Rect pdf
*
2024-03-19 18:08:06 +00:00
* @ param TCPDI | TCPDF $pdf Pdf object
* @ param float $x Abscissa of first point
* @ param float $y Ordinate of first point
* @ param float $l ? ?
* @ param float $h ? ?
2024-09-22 22:37:30 +00:00
* @ param int <- 1 , 1 > $hidetop 1 = Hide top bar of array and title , 0 = Hide nothing , - 1 = Hide only title
* @ param int < 0 , 1 > $hidebottom Hide bottom
2012-09-30 18:49:13 +00:00
* @ return void
2012-08-08 02:12:20 +00:00
*/
2020-10-07 13:01:28 +00:00
public function printRect ( $pdf , $x , $y , $l , $h , $hidetop = 0 , $hidebottom = 0 )
{
2021-02-23 21:03:23 +00:00
if ( empty ( $hidetop ) || $hidetop == - 1 ) {
$pdf -> line ( $x , $y , $x + $l , $y );
}
2020-10-07 13:01:28 +00:00
$pdf -> line ( $x + $l , $y , $x + $l , $y + $h );
2021-02-23 21:03:23 +00:00
if ( empty ( $hidebottom )) {
$pdf -> line ( $x + $l , $y + $h , $x , $y + $h );
}
2020-10-07 13:01:28 +00:00
$pdf -> line ( $x , $y + $h , $x , $y );
}
2024-10-04 07:13:44 +00:00
/**
* Print a rounded rectangle on the PDF
*
* @ param TCPDF $pdf Object PDF
* @ param float $x Abscissa of first point
* @ param float $y Ordinate of first point
* @ param float $w Width of the rectangle
* @ param float $h Height of the rectangle
* @ param float $r Corner radius ( can be an array for different radii per corner )
2025-11-20 00:47:46 +00:00
* @ param int <- 1 , 1 > $hidetop 1 = Hide top bar of array and title , 0 = Hide nothing , - 1 = Hide only title
2024-10-04 07:13:44 +00:00
* @ param int $hidebottom Hide bottom
* @ param string $style Draw style ( e . g . 'D' for draw , 'F' for fill , 'DF' for both )
* @ return void
*/
public function printRoundedRect ( $pdf , $x , $y , $w , $h , $r , $hidetop = 0 , $hidebottom = 0 , $style = 'D' )
{
// Top line
if ( empty ( $hidetop ) || $hidetop == - 1 ) {
$pdf -> RoundedRect ( $x , $y , $w , $h , $r , '1111' , $style );
} else {
// Draw rounded rectangle with hidden top side
$pdf -> RoundedRect ( $x , $y , $w , $h , $r , '0111' , $style );
}
if ( ! empty ( $hidebottom )) {
$pdf -> RoundedRect ( $x , $y , $w , $h , $r , '1101' , $style );
}
}
2020-10-07 13:01:28 +00:00
2024-10-08 20:44:36 +00:00
/**
* Get position in PDF after col display
2024-10-09 07:29:58 +00:00
* @ return false | array { page : int , y : float | int , col : string }
2024-10-08 20:44:36 +00:00
*/
public function getMaxAfterColsLinePositionsData ()
{
if ( empty ( $this -> afterColsLinePositions ) || ! is_array ( $this -> afterColsLinePositions )) {
return false ;
}
$colId = '' ;
$maxPage = $maxY = 0 ;
foreach ( $this -> afterColsLinePositions as $colKey => $value ) {
if ( $value [ 'page' ] > $maxPage ) {
$colId = $colKey ;
$maxPage = $value [ 'page' ];
$maxY = $value [ 'y' ]; // if page is higher we need to reset y to new max page y
} elseif ( $value [ 'page' ] == $maxPage ) {
$maxY = max ( $value [ 'y' ], $maxY );
$colId = $colKey ;
}
}
return [
'col' => $colId ,
'y' => $maxY ,
'page' => $maxPage
];
}
/**
* Used for reset afterColsLinePositions var in start of a new pdf draw line loop
* @ param float $y the new $y position usually get by TCPDF :: GetY ()
* @ param int $pageNumb the page number to reset at
2024-10-09 07:57:37 +00:00
* @ return void
2024-10-08 20:44:36 +00:00
*/
public function resetAfterColsLinePositionsData ( float $y , int $pageNumb )
{
$this -> afterColsLinePositions = [];
2024-10-09 08:05:53 +00:00
$this -> setAfterColsLinePositionsData ( 'startLine' , $y , $pageNumb );
2024-10-08 20:44:36 +00:00
}
/**
* Used for to set afterColsLinePositions var in a pdf draw line loop
* @ param string $colId the column id used as key in $this -> cols or an unique id code like startLine or separateLine ....
* @ param float $y the $y position usually get by TCPDF :: GetY () where print data ended
* @ param int $pageNumb the page number where print data ended
* @ return void
*/
public function setAfterColsLinePositionsData ( string $colId , float $y , int $pageNumb )
{
$this -> afterColsLinePositions [ $colId ] = [
'page' => $pageNumb ,
'y' => $y
];
}
2020-10-07 13:01:28 +00:00
/**
* uasort callback function to Sort columns fields
*
2024-09-22 22:37:30 +00:00
* @ param array { rank ? : int } $a PDF lines array fields configs
* @ param array { rank ? : int } $b PDF lines array fields configs
* @ return int <- 1 , 1 > Return compare result
2020-10-07 13:01:28 +00:00
*/
public function columnSort ( $a , $b )
{
2021-02-23 21:03:23 +00:00
if ( empty ( $a [ 'rank' ])) {
$a [ 'rank' ] = 0 ;
}
if ( empty ( $b [ 'rank' ])) {
$b [ 'rank' ] = 0 ;
}
2020-10-07 13:01:28 +00:00
if ( $a [ 'rank' ] == $b [ 'rank' ]) {
return 0 ;
}
return ( $a [ 'rank' ] > $b [ 'rank' ]) ? - 1 : 1 ;
}
/**
* Prepare Array Column Field
*
2024-09-22 22:37:30 +00:00
* @ param CommonObject $object common object
2020-10-07 13:01:28 +00:00
* @ param Translate $outputlangs langs
2024-09-22 22:37:30 +00:00
* @ param int < 0 , 1 > $hidedetails Do not show line details
* @ param int < 0 , 1 > $hidedesc Do not show desc
* @ param int < 0 , 1 > $hideref Do not show ref
2023-01-06 18:24:57 +00:00
* @ return void
2020-10-07 13:01:28 +00:00
*/
public function prepareArrayColumnField ( $object , $outputlangs , $hidedetails = 0 , $hidedesc = 0 , $hideref = 0 )
{
$this -> defineColumnField ( $object , $outputlangs , $hidedetails , $hidedesc , $hideref );
// Sorting
uasort ( $this -> cols , array ( $this , 'columnSort' ));
2024-01-13 18:48:20 +00:00
// Positioning
2020-10-07 13:01:28 +00:00
$curX = $this -> page_largeur - $this -> marge_droite ; // start from right
// Array width
$arrayWidth = $this -> page_largeur - $this -> marge_droite - $this -> marge_gauche ;
// Count flexible column
$totalDefinedColWidth = 0 ;
$countFlexCol = 0 ;
2021-02-23 21:03:23 +00:00
foreach ( $this -> cols as $colKey => & $colDef ) {
if ( ! $this -> getColumnStatus ( $colKey )) {
continue ; // continue if disabled
}
2020-10-07 13:01:28 +00:00
if ( ! empty ( $colDef [ 'scale' ])) {
// In case of column width is defined by percentage
$colDef [ 'width' ] = abs ( $arrayWidth * $colDef [ 'scale' ] / 100 );
}
if ( empty ( $colDef [ 'width' ])) {
$countFlexCol ++ ;
} else {
$totalDefinedColWidth += $colDef [ 'width' ];
}
}
2021-02-23 21:03:23 +00:00
foreach ( $this -> cols as $colKey => & $colDef ) {
2020-10-07 13:01:28 +00:00
// setting empty conf with default
if ( ! empty ( $colDef [ 'title' ])) {
$colDef [ 'title' ] = array_replace ( $this -> defaultTitlesFieldsStyle , $colDef [ 'title' ]);
} else {
$colDef [ 'title' ] = $this -> defaultTitlesFieldsStyle ;
}
// setting empty conf with default
if ( ! empty ( $colDef [ 'content' ])) {
$colDef [ 'content' ] = array_replace ( $this -> defaultContentsFieldsStyle , $colDef [ 'content' ]);
} else {
$colDef [ 'content' ] = $this -> defaultContentsFieldsStyle ;
}
2021-02-23 21:03:23 +00:00
if ( $this -> getColumnStatus ( $colKey )) {
2020-10-07 13:01:28 +00:00
// In case of flexible column
if ( empty ( $colDef [ 'width' ])) {
$colDef [ 'width' ] = abs (( $arrayWidth - $totalDefinedColWidth )) / $countFlexCol ;
}
// Set positions
$lastX = $curX ;
$curX = $lastX - $colDef [ 'width' ];
$colDef [ 'xStartPos' ] = $curX ;
$colDef [ 'xEndPos' ] = $lastX ;
}
}
}
/**
* get column content width from column key
*
* @ param string $colKey the column key
* @ return float width in mm
*/
public function getColumnContentWidth ( $colKey )
{
$colDef = $this -> cols [ $colKey ];
return $colDef [ 'width' ] - $colDef [ 'content' ][ 'padding' ][ 3 ] - $colDef [ 'content' ][ 'padding' ][ 1 ];
}
/**
* get column content X ( abscissa ) left position from column key
*
* @ param string $colKey the column key
* @ return float X position in mm
*/
public function getColumnContentXStart ( $colKey )
{
2023-09-30 09:37:53 +00:00
$colDef = ( isset ( $this -> cols [ $colKey ]) ? $this -> cols [ $colKey ] : null );
return ( is_array ( $colDef ) ? (( isset ( $colDef [ 'xStartPos' ]) ? $colDef [ 'xStartPos' ] : 0 ) + $colDef [ 'content' ][ 'padding' ][ 3 ]) : 0 );
2020-10-07 13:01:28 +00:00
}
/**
2023-01-08 18:28:38 +00:00
* get column position rank from column key
2020-10-07 13:01:28 +00:00
*
2023-01-08 18:28:38 +00:00
* @ param string $colKey the column key
* @ return int rank on success and - 1 on error
2020-10-07 13:01:28 +00:00
*/
public function getColumnRank ( $colKey )
{
2021-02-23 21:03:23 +00:00
if ( ! isset ( $this -> cols [ $colKey ][ 'rank' ])) {
return - 1 ;
}
2020-10-07 13:01:28 +00:00
return $this -> cols [ $colKey ][ 'rank' ];
}
/**
* get column position rank from column key
*
2023-01-08 18:28:38 +00:00
* @ param string $newColKey the new column key
2024-09-22 22:37:30 +00:00
* @ param array { rank ? : int } $defArray a single column definition array
2023-01-08 18:28:38 +00:00
* @ param string $targetCol target column used to place the new column beside
* @ param bool $insertAfterTarget insert before or after target column ?
* @ return int new rank on success and - 1 on error
2020-10-07 13:01:28 +00:00
*/
2023-12-21 12:43:19 +00:00
public function insertNewColumnDef ( $newColKey , $defArray , $targetCol = '' , $insertAfterTarget = false )
2020-10-07 13:01:28 +00:00
{
// prepare wanted rank
$rank = - 1 ;
// try to get rank from target column
if ( ! empty ( $targetCol )) {
$rank = $this -> getColumnRank ( $targetCol );
2021-02-23 21:03:23 +00:00
if ( $rank >= 0 && $insertAfterTarget ) {
$rank ++ ;
}
2020-10-07 13:01:28 +00:00
}
// get rank from new column definition
if ( $rank < 0 && ! empty ( $defArray [ 'rank' ])) {
$rank = $defArray [ 'rank' ];
}
// error: no rank
2021-02-23 21:03:23 +00:00
if ( $rank < 0 ) {
return - 1 ;
}
2020-10-07 13:01:28 +00:00
2021-02-23 21:03:23 +00:00
foreach ( $this -> cols as $colKey => & $colDef ) {
if ( $rank <= $colDef [ 'rank' ]) {
2024-08-07 00:53:45 +00:00
$colDef [ 'rank' ] += 1 ;
2020-10-07 13:01:28 +00:00
}
}
$defArray [ 'rank' ] = $rank ;
$this -> cols [ $newColKey ] = $defArray ; // array_replace is used to preserve keys
return $rank ;
}
/**
* print standard column content
*
2024-03-19 18:08:06 +00:00
* @ param TCPDI | TCPDF $pdf Pdf object
2024-01-13 18:48:20 +00:00
* @ param float $curY current Y position
2023-01-08 18:28:38 +00:00
* @ param string $colKey the column key
* @ param string $columnText column text
2023-12-06 14:46:39 +00:00
* @ return int Return integer < 0 if KO , >= if OK
2020-10-07 13:01:28 +00:00
*/
public function printStdColumnContent ( $pdf , & $curY , $colKey , $columnText = '' )
{
global $hookmanager ;
$parameters = array (
'curY' => & $curY ,
2026-03-29 20:29:38 +00:00
'columnText' => & $columnText ,
2020-10-07 13:01:28 +00:00
'colKey' => $colKey ,
'pdf' => & $pdf ,
);
$reshook = $hookmanager -> executeHooks ( 'printStdColumnContent' , $parameters , $this ); // Note that $action and $object may have been modified by hook
2026-03-29 20:29:38 +00:00
if ( $reshook > 0 && isset ( $hookmanager -> resArray [ 'columnText' ])) {
$columnText = $hookmanager -> resArray [ 'columnText' ];
}
2021-02-23 21:03:23 +00:00
if ( $reshook < 0 ) {
setEventMessages ( $hookmanager -> error , $hookmanager -> errors , 'errors' );
}
2026-03-29 20:29:38 +00:00
if ( ! $reshook || $reshook > 0 ) {
2021-02-23 21:03:23 +00:00
if ( empty ( $columnText )) {
2023-01-08 18:28:38 +00:00
return 0 ;
2021-02-23 21:03:23 +00:00
}
2024-01-13 18:48:20 +00:00
$pdf -> SetXY ( $this -> getColumnContentXStart ( $colKey ), $curY ); // Set current position
2020-10-07 13:01:28 +00:00
$colDef = $this -> cols [ $colKey ];
2024-01-13 18:48:20 +00:00
// save current cell padding
2020-02-24 13:18:49 +00:00
$curentCellPaddinds = $pdf -> getCellPaddings ();
2020-10-07 13:01:28 +00:00
// set cell padding with column content definition
2023-04-05 12:15:44 +00:00
$pdf -> setCellPaddings ( isset ( $colDef [ 'content' ][ 'padding' ][ 3 ]) ? $colDef [ 'content' ][ 'padding' ][ 3 ] : 0 , isset ( $colDef [ 'content' ][ 'padding' ][ 0 ]) ? $colDef [ 'content' ][ 'padding' ][ 0 ] : 0 , isset ( $colDef [ 'content' ][ 'padding' ][ 1 ]) ? $colDef [ 'content' ][ 'padding' ][ 1 ] : 0 , isset ( $colDef [ 'content' ][ 'padding' ][ 2 ]) ? $colDef [ 'content' ][ 'padding' ][ 2 ] : 0 );
2025-03-11 00:42:49 +00:00
$pdf -> writeHTMLCell ( $colDef [ 'width' ], 2 , isset ( $colDef [ 'xStartPos' ]) ? $colDef [ 'xStartPos' ] : 0 , $curY , $columnText , 0 , 1 , false , true , $colDef [ 'content' ][ 'align' ]);
2024-10-08 20:44:36 +00:00
$this -> setAfterColsLinePositionsData ( $colKey , $pdf -> GetY (), $pdf -> getPage ());
2020-02-24 19:47:19 +00:00
2020-10-07 13:01:28 +00:00
// restore cell padding
2020-02-24 16:44:46 +00:00
$pdf -> setCellPaddings ( $curentCellPaddinds [ 'L' ], $curentCellPaddinds [ 'T' ], $curentCellPaddinds [ 'R' ], $curentCellPaddinds [ 'B' ]);
2020-10-07 13:01:28 +00:00
}
2023-01-06 18:24:57 +00:00
2023-01-08 18:28:38 +00:00
return 0 ;
2020-10-07 13:01:28 +00:00
}
/**
* print description column content
*
2024-03-19 18:08:06 +00:00
* @ param TCPDI | TCPDF $pdf Pdf object
2024-01-13 18:48:20 +00:00
* @ param float $curY current Y position
2023-01-06 18:24:57 +00:00
* @ param string $colKey the column key
2024-09-22 22:37:30 +00:00
* @ param CommonObject $object CommonObject
2023-01-06 18:24:57 +00:00
* @ param int $i the $object -> lines array key
* @ param Translate $outputlangs Output language
2024-09-22 22:37:30 +00:00
* @ param int < 0 , 1 > $hideref hide ref
* @ param int < 0 , 1 > $hidedesc hide desc
* @ param int < 0 , 1 > $issupplierline if object needx supplier product
2023-01-06 18:24:57 +00:00
* @ return void
2020-10-07 13:01:28 +00:00
*/
public function printColDescContent ( $pdf , & $curY , $colKey , $object , $i , $outputlangs , $hideref = 0 , $hidedesc = 0 , $issupplierline = 0 )
{
add hook on printColDescContent (#35741)
* add hook on printColDescContent
Allow to add more informations on pdf description with hook management.
sample hook use :
public function printColDescContent($parameters, &$object, &$action)
{
$pdf = $parameters['pdf'];
if ($object->name == 'sponge mydiscount') {
//var_dump($parameters, $object, $action); exit;
$pdf->MultiCell(0, 3, "xxxxx", 0, 'L', 0, 1, '', '', true);
return 1;
}
}
* Add hook support to printColDescContent method
2025-10-26 13:43:40 +00:00
global $hookmanager ;
2020-10-07 13:01:28 +00:00
// load desc col params
$colDef = $this -> cols [ $colKey ];
2024-01-13 18:48:20 +00:00
// save current cell padding
2020-10-07 13:01:28 +00:00
$curentCellPaddinds = $pdf -> getCellPaddings ();
// set cell padding with column content definition
$pdf -> setCellPaddings ( $colDef [ 'content' ][ 'padding' ][ 3 ], $colDef [ 'content' ][ 'padding' ][ 0 ], $colDef [ 'content' ][ 'padding' ][ 1 ], $colDef [ 'content' ][ 'padding' ][ 2 ]);
// line description
2024-02-08 00:30:18 +00:00
pdf_writelinedesc ( $pdf , $object , $i , $outputlangs , $colDef [ 'width' ], 3 , $colDef [ 'xStartPos' ], $curY , $hideref , $hidedesc , $issupplierline , empty ( $colDef [ 'content' ][ 'align' ]) ? 'J' : $colDef [ 'content' ][ 'align' ]);
2020-10-07 13:01:28 +00:00
$posYAfterDescription = $pdf -> GetY () - $colDef [ 'content' ][ 'padding' ][ 0 ];
// restore cell padding
$pdf -> setCellPaddings ( $curentCellPaddinds [ 'L' ], $curentCellPaddinds [ 'T' ], $curentCellPaddinds [ 'R' ], $curentCellPaddinds [ 'B' ]);
// Display extrafield if needed
$params = array (
'display' => 'list' ,
'printableEnable' => array ( 3 ),
'printableEnableNotEmpty' => array ( 4 )
);
$extrafieldDesc = $this -> getExtrafieldsInHtml ( $object -> lines [ $i ], $outputlangs , $params );
if ( ! empty ( $extrafieldDesc )) {
$this -> printStdColumnContent ( $pdf , $posYAfterDescription , $colKey , $extrafieldDesc );
}
add hook on printColDescContent (#35741)
* add hook on printColDescContent
Allow to add more informations on pdf description with hook management.
sample hook use :
public function printColDescContent($parameters, &$object, &$action)
{
$pdf = $parameters['pdf'];
if ($object->name == 'sponge mydiscount') {
//var_dump($parameters, $object, $action); exit;
$pdf->MultiCell(0, 3, "xxxxx", 0, 'L', 0, 1, '', '', true);
return 1;
}
}
* Add hook support to printColDescContent method
2025-10-26 13:43:40 +00:00
$parameters = array (
'curY' => & $curY ,
'colKey' => $colKey ,
'object' => $object ,
'i' => $i ,
'outputlangs' => $outputlangs ,
'pdf' => & $pdf ,
);
$reshook = $hookmanager -> executeHooks ( 'printColDescContent' , $parameters , $this ); // Note that $action and $object may have been modified by hook
if ( $reshook < 0 ) {
setEventMessages ( $hookmanager -> error , $hookmanager -> errors , 'errors' );
}
2020-10-07 13:01:28 +00:00
}
/**
* get extrafield content for pdf writeHtmlCell compatibility
* usage for PDF line columns and object note block
*
2024-06-10 23:06:52 +00:00
* @ param CommonObject $object Common object
* @ param string $extrafieldKey The extrafield key
* @ param Translate $outputlangs The output langs ( if value is __ ( XXX ) __ we use it to translate it ) .
2020-10-07 13:01:28 +00:00
* @ return string
*/
2021-08-17 13:50:28 +00:00
public function getExtrafieldContent ( $object , $extrafieldKey , $outputlangs = null )
2020-10-07 13:01:28 +00:00
{
global $hookmanager ;
2021-02-23 21:03:23 +00:00
if ( empty ( $object -> table_element )) {
2023-01-06 18:24:57 +00:00
return '' ;
2021-02-23 21:03:23 +00:00
}
2020-10-07 13:01:28 +00:00
$extrafieldsKeyPrefix = " options_ " ;
// Cleanup extrafield key to remove prefix if present
$pos = strpos ( $extrafieldKey , $extrafieldsKeyPrefix );
if ( $pos === 0 ) {
$extrafieldKey = substr ( $extrafieldKey , strlen ( $extrafieldsKeyPrefix ));
}
$extrafieldOptionsKey = $extrafieldsKeyPrefix . $extrafieldKey ;
2023-01-28 09:32:07 +00:00
// Load extra fields if they haven't been loaded already.
2024-06-19 17:21:45 +00:00
if ( is_null ( $this -> extrafieldsCache )) {
2021-02-23 21:03:23 +00:00
$this -> extrafieldsCache = new ExtraFields ( $this -> db );
}
if ( empty ( $this -> extrafieldsCache -> attributes [ $object -> table_element ])) {
$this -> extrafieldsCache -> fetch_name_optionals_label ( $object -> table_element );
}
2020-10-07 13:01:28 +00:00
$extrafields = $this -> extrafieldsCache ;
2023-01-08 20:30:12 +00:00
$extrafieldOutputContent = '' ;
2023-12-04 11:04:36 +00:00
if ( isset ( $object -> array_options [ $extrafieldOptionsKey ])) {
2024-04-04 09:19:45 +00:00
$extrafieldOutputContent = $extrafields -> showOutputField ( $extrafieldKey , $object -> array_options [ $extrafieldOptionsKey ], '' , $object -> table_element , $outputlangs );
2023-12-04 11:04:36 +00:00
}
2020-10-07 13:01:28 +00:00
// TODO : allow showOutputField to be pdf public friendly, ex: in a link to object, clean getNomUrl to remove link and images... like a getName methode ...
if ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $extrafieldKey ] == 'link' ) {
// for lack of anything better we cleanup all html tags
$extrafieldOutputContent = dol_string_nohtmltag ( $extrafieldOutputContent );
}
2024-11-15 22:07:37 +00:00
// Display stars extrafield as simple string
if ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $extrafieldKey ] == 'stars' ) {
$extrafieldOutputContent = '' ;
for ( $i = 0 ; $i < $object -> array_options [ $extrafieldOptionsKey ]; $i ++ ) {
$extrafieldOutputContent .= ' *' ;
}
}
2020-10-07 13:01:28 +00:00
$parameters = array (
'object' => $object ,
'extrafields' => $extrafields ,
'extrafieldKey' => $extrafieldKey ,
2024-03-10 00:55:56 +00:00
'extrafieldOutputContent' => & $extrafieldOutputContent
2020-10-07 13:01:28 +00:00
);
$reshook = $hookmanager -> executeHooks ( 'getPDFExtrafieldContent' , $parameters , $this ); // Note that $action and $object may have been modified by hook
2021-02-23 21:03:23 +00:00
if ( $reshook < 0 ) {
setEventMessages ( $hookmanager -> error , $hookmanager -> errors , 'errors' );
}
if ( $reshook ) {
2020-10-07 13:01:28 +00:00
$extrafieldOutputContent = $hookmanager -> resPrint ;
}
return $extrafieldOutputContent ;
}
/**
2026-03-13 11:54:46 +00:00
* Display extrafields columns content on documents
2020-10-07 13:01:28 +00:00
*
2024-11-13 20:28:25 +00:00
* @ param CommonObject | CommonObjectLine $object line of common object
* @ param Translate $outputlangs Output language
* @ param array < string , mixed > $params array of additional parameters
* @ return string Html string
2020-10-07 13:01:28 +00:00
*/
public function getExtrafieldsInHtml ( $object , $outputlangs , $params = array ())
2020-02-24 19:50:07 +00:00
{
2020-10-07 13:01:28 +00:00
global $hookmanager ;
if ( empty ( $object -> table_element )) {
2023-07-12 10:57:17 +00:00
return " " ;
2020-10-07 13:01:28 +00:00
}
2024-01-13 18:48:20 +00:00
// Load extrafields if not already done
2024-06-19 17:21:45 +00:00
if ( is_null ( $this -> extrafieldsCache )) {
NEW add method confirmProduced in MOs API (#39324)
* FIX commande/stats: do not default "Created by" filter to current user (#39256)
The order statistics query is not filtered on the current user on first
page load, so the results shown are global. However the "Created by"
selector defaulted to the current user (select_dolusers auto-selects
$user->id when the passed value is empty), wrongly suggesting the
displayed figures were limited to that user.
Pass -1 instead of 0 when no user is selected so the combo keeps its
empty entry, matching the unfiltered query. The empty option posts -1,
which the query turns back into "no user filter", so the round-trip
stays consistent after a refresh.
* FIX Missing translation for "Weight"
* Fix/supplier doc keep project (#39306)
* FIX : situation invoice credit note wrong amount in progressive mode
When creating a credit note "with same lines" from a situation invoice,
the code always subtracts the previous situation invoice's line values
before inverting the sign, assuming lines are stored cumulative
(INVOICE_USE_SITUATION = 1, legacy mode).
In progressive mode (INVOICE_USE_SITUATION = 2), each situation invoice
line already stores its own delta amount and percent, so this extra
subtraction credits the wrong amount and percent (e.g. 60% / 1272
instead of the correct 20% / 424 on a real cycle).
Skip the subtraction in progressive mode so the credit note reuses the
source line's own delta values, as expected.
* FIX supplier order/proposal loses project after supplier selection
On the create form of a supplier order (fourn/commande/card.php) and a supplier
price request (supplier_proposal/card.php), the project select was filtered on
the supplier third party as soon as one was chosen: the `if ($socid > 0)` branch
took precedence over the PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS constant.
As a result, a supplier document created from a customer project lost its
preselected project when the page reloaded after picking the supplier (the
customer project is not linked to the supplier, so it was filtered out).
This aligns the behavior with the supplier invoice (fourn/facture/card.php),
which gives priority to PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS. The external
user restriction now targets $user->socid (the real external-user marker)
instead of $socid > 0, which also matched internal users after selecting a
supplier.
* Fix Standalone reception creation (#39299)
Fatal error: Uncaught Error: Call to a member function fetch_optionals() on null
* Fix missing include
* add method confirmProduced in MOs API
which was missing
---------
Co-authored-by: atm-corentin <165782689+atm-corentin@users.noreply.github.com>
Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com>
Co-authored-by: Alexandre SPANGARO <aspangaro.dolibarr@gmail.com>
Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com>
Co-authored-by: sonikf <93765174+sonikf@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-07-30 16:22:44 +00:00
include_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php' ;
2021-02-23 21:03:23 +00:00
$this -> extrafieldsCache = new ExtraFields ( $this -> db );
}
if ( empty ( $this -> extrafieldsCache -> attributes [ $object -> table_element ])) {
$this -> extrafieldsCache -> fetch_name_optionals_label ( $object -> table_element );
}
2020-10-07 13:01:28 +00:00
$extrafields = $this -> extrafieldsCache ;
$defaultParams = array (
'style' => '' ,
'display' => 'auto' , // auto, table, list
'printableEnable' => array ( 1 ),
'printableEnableNotEmpty' => array ( 2 ),
'table' => array (
'maxItemsInRow' => 2 ,
'cellspacing' => 0 ,
'cellpadding' => 0 ,
'border' => 0 ,
'labelcolwidth' => '25%' ,
'arrayOfLineBreakType' => array ( 'text' , 'html' )
),
'list' => array (
2021-04-19 19:30:25 +00:00
'separator' => '<br>'
2020-10-07 13:01:28 +00:00
),
'auto' => array (
'list' => 0 , // 0 for default
'table' => 4 // if there more than x extrafield to display
),
);
2024-08-07 00:53:45 +00:00
$params += $defaultParams ;
2020-10-07 13:01:28 +00:00
/**
2023-12-07 19:30:46 +00:00
* @ var ExtraFields $extrafields
2020-10-07 13:01:28 +00:00
*/
$html = '' ;
$fields = array ();
2020-11-16 10:37:28 +00:00
if ( ! empty ( $extrafields -> attributes [ $object -> table_element ][ 'label' ]) && is_array ( $extrafields -> attributes [ $object -> table_element ][ 'label' ])) {
2021-02-23 21:03:23 +00:00
foreach ( $extrafields -> attributes [ $object -> table_element ][ 'label' ] as $key => $label ) {
2020-10-07 13:01:28 +00:00
// Enable extrafield ?
$enabled = 0 ;
2026-03-12 13:40:36 +00:00
if ( ! empty ( $extrafields -> attributes [ $object -> table_element ][ 'enabled' ][ $key ])) {
$enabled = ( int ) dol_eval (( string ) $extrafields -> attributes [ $object -> table_element ][ 'enabled' ][ $key ], 1 , 1 , '2' );
}
2026-03-24 23:20:06 +00:00
if ( ! $enabled ) {
continue ;
}
// Reset enabled: only printable attribute determines PDF visibility
$enabled = 0 ;
2020-10-07 13:01:28 +00:00
$disableOnEmpty = 0 ;
2026-04-10 10:41:11 +00:00
$printable = 0 ;
2026-03-24 23:20:06 +00:00
if ( ! empty ( $extrafields -> attributes [ $object -> table_element ][ 'printable' ][ $key ])) {
2026-04-10 10:41:11 +00:00
$printable = ( int ) $extrafields -> attributes [ $object -> table_element ][ 'printable' ][ $key ];
2020-10-07 13:01:28 +00:00
if ( in_array ( $printable , $params [ 'printableEnable' ]) || in_array ( $printable , $params [ 'printableEnableNotEmpty' ])) {
$enabled = 1 ;
}
if ( in_array ( $printable , $params [ 'printableEnableNotEmpty' ])) {
$disableOnEmpty = 1 ;
}
}
2026-04-08 18:09:12 +00:00
if ( empty ( $enabled ) || empty ( $printable )) {
2020-10-07 13:01:28 +00:00
continue ;
}
2024-05-28 21:54:44 +00:00
// Load language if required
if ( ! empty ( $extrafields -> attributes [ $object -> table_element ][ 'langfile' ][ $key ])) {
$outputlangs -> load ( $extrafields -> attributes [ $object -> table_element ][ 'langfile' ][ $key ]);
}
2020-10-07 13:01:28 +00:00
$field = new stdClass ();
$field -> rank = intval ( $extrafields -> attributes [ $object -> table_element ][ 'pos' ][ $key ]);
2021-08-17 13:50:28 +00:00
$field -> content = $this -> getExtrafieldContent ( $object , $key , $outputlangs );
2024-07-25 12:29:12 +00:00
if ( isset ( $extrafields -> attributes [ $object -> table_element ][ 'langfile' ][ $key ])) {
$outputlangs -> load ( $extrafields -> attributes [ $object -> table_element ][ 'langfile' ][ $key ]);
}
2020-10-07 13:01:28 +00:00
$field -> label = $outputlangs -> transnoentities ( $label );
$field -> type = $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ];
2024-01-13 18:48:20 +00:00
// don't display if empty
2020-10-07 13:01:28 +00:00
if ( $disableOnEmpty && empty ( $field -> content )) {
continue ;
}
$fields [] = $field ;
}
}
2021-02-23 21:03:23 +00:00
if ( ! empty ( $fields )) {
2020-10-07 13:01:28 +00:00
// Sort extrafields by rank
2024-03-14 20:59:15 +00:00
uasort (
$fields ,
/**
* @ param stdClass $a
* @ param stdClass $b
* @ return int <- 1 , 1 >
*/
static function ( $a , $b ) {
return ( $a -> rank > $b -> rank ) ? 1 : - 1 ;
}
);
2020-02-23 14:24:59 +00:00
2020-10-07 13:01:28 +00:00
// define some HTML content with style
$html .= ! empty ( $params [ 'style' ]) ? '<style>' . $params [ 'style' ] . '</style>' : '' ;
// auto select display format
if ( $params [ 'display' ] == 'auto' ) {
$lastNnumbItems = 0 ;
foreach ( $params [ 'auto' ] as $display => $numbItems ) {
if ( $lastNnumbItems <= $numbItems && count ( $fields ) > $numbItems ) {
$lastNnumbItems = $numbItems ;
$params [ 'display' ] = $display ;
}
}
}
if ( $params [ 'display' ] == 'list' ) {
// Display in list format
$i = 0 ;
foreach ( $fields as $field ) {
$html .= ! empty ( $i ) ? $params [ 'list' ][ 'separator' ] : '' ;
$html .= '<strong>' . $field -> label . ' : </strong>' ;
$html .= $field -> content ;
$i ++ ;
}
} elseif ( $params [ 'display' ] == 'table' ) {
// Display in table format
$html .= '<table class="extrafield-table" cellspacing="' . $params [ 'table' ][ 'cellspacing' ] . '" cellpadding="' . $params [ 'table' ][ 'cellpadding' ] . '" border="' . $params [ 'table' ][ 'border' ] . '">' ;
$html .= " <tr> " ;
$itemsInRow = 0 ;
$maxItemsInRow = $params [ 'table' ][ 'maxItemsInRow' ];
foreach ( $fields as $field ) {
2021-04-19 19:30:25 +00:00
//$html.= !empty($html)?'<br>':'';
2020-10-07 13:01:28 +00:00
if ( $itemsInRow >= $maxItemsInRow ) {
// start a new line
$html .= " </tr><tr> " ;
$itemsInRow = 0 ;
}
// for some type we need line break
if ( in_array ( $field -> type , $params [ 'table' ][ 'arrayOfLineBreakType' ])) {
if ( $itemsInRow > 0 ) {
// close table row and empty cols
for ( $i = $itemsInRow ; $i <= $maxItemsInRow ; $i ++ ) {
2020-11-27 14:45:12 +00:00
$html .= " <td></td><td></td> " ;
2020-10-07 13:01:28 +00:00
}
$html .= " </tr> " ;
// start a new line
$html .= " <tr> " ;
}
$itemsInRow = $maxItemsInRow ;
$html .= '<td colspan="' . ( $maxItemsInRow * 2 - 1 ) . '">' ;
$html .= '<strong>' . $field -> label . ' :</strong> ' ;
$html .= $field -> content ;
$html .= " </td> " ;
} else {
$itemsInRow ++ ;
$html .= '<td width="' . $params [ 'table' ][ 'labelcolwidth' ] . '" class="extrafield-label">' ;
$html .= '<strong>' . $field -> label . ' :</strong>' ;
$html .= " </td> " ;
$html .= '<td class="extrafield-content">' ;
$html .= $field -> content ;
$html .= " </td> " ;
}
}
$html .= " </tr> " ;
$html .= '</table>' ;
}
}
return $html ;
}
/**
* get column status from column key
*
2023-04-30 01:10:20 +00:00
* @ param string $colKey the column key
* @ return boolean true if column on
2020-10-07 13:01:28 +00:00
*/
public function getColumnStatus ( $colKey )
{
if ( ! empty ( $this -> cols [ $colKey ][ 'status' ])) {
return true ;
2021-02-23 21:03:23 +00:00
} else {
return false ;
}
2020-10-07 13:01:28 +00:00
}
/**
* Print standard column content
*
2024-03-19 18:08:06 +00:00
* @ param TCPDI | TCPDF $pdf Pdf object
* @ param float $tab_top Tab top position
* @ param float $tab_height Default tab height
* @ param Translate $outputlangs Output language
2026-04-03 17:02:13 +00:00
* @ param int < 0 , 1 > $hidetop Hide top
2024-03-19 18:08:06 +00:00
* @ return float Height of col tab titles
2020-10-07 13:01:28 +00:00
*/
public function pdfTabTitles ( & $pdf , $tab_top , $tab_height , $outputlangs , $hidetop = 0 )
{
global $hookmanager , $conf ;
foreach ( $this -> cols as $colKey => $colDef ) {
$parameters = array (
'colKey' => $colKey ,
'pdf' => $pdf ,
'outputlangs' => $outputlangs ,
'tab_top' => $tab_top ,
'tab_height' => $tab_height ,
'hidetop' => $hidetop
);
$reshook = $hookmanager -> executeHooks ( 'pdfTabTitles' , $parameters , $this ); // Note that $object may have been modified by hook
if ( $reshook < 0 ) {
setEventMessages ( $hookmanager -> error , $hookmanager -> errors , 'errors' );
} elseif ( empty ( $reshook )) {
2021-02-23 21:03:23 +00:00
if ( ! $this -> getColumnStatus ( $colKey )) {
continue ;
}
2020-10-07 13:01:28 +00:00
// get title label
$colDef [ 'title' ][ 'label' ] = ! empty ( $colDef [ 'title' ][ 'label' ]) ? $colDef [ 'title' ][ 'label' ] : $outputlangs -> transnoentities ( $colDef [ 'title' ][ 'textkey' ]);
// Add column separator
2023-03-29 09:21:28 +00:00
if ( ! empty ( $colDef [ 'border-left' ]) && isset ( $colDef [ 'xStartPos' ])) {
2020-10-07 13:01:28 +00:00
$pdf -> line ( $colDef [ 'xStartPos' ], $tab_top , $colDef [ 'xStartPos' ], $tab_top + $tab_height );
}
if ( empty ( $hidetop )) {
2024-01-13 18:48:20 +00:00
// save current cell padding
2020-10-07 13:01:28 +00:00
$curentCellPaddinds = $pdf -> getCellPaddings ();
// Add space for lines (more if we need to show a second alternative language)
global $outputlangsbis ;
if ( is_object ( $outputlangsbis )) {
// set cell padding with column title definition
$pdf -> setCellPaddings ( $colDef [ 'title' ][ 'padding' ][ 3 ], $colDef [ 'title' ][ 'padding' ][ 0 ], $colDef [ 'title' ][ 'padding' ][ 1 ], 0.5 );
} else {
// set cell padding with column title definition
$pdf -> setCellPaddings ( $colDef [ 'title' ][ 'padding' ][ 3 ], $colDef [ 'title' ][ 'padding' ][ 0 ], $colDef [ 'title' ][ 'padding' ][ 1 ], $colDef [ 'title' ][ 'padding' ][ 2 ]);
}
2023-03-31 10:36:43 +00:00
if ( isset ( $colDef [ 'title' ][ 'align' ])) {
$align = $colDef [ 'title' ][ 'align' ];
} else {
$align = '' ;
}
2020-10-07 13:01:28 +00:00
$pdf -> SetXY ( $colDef [ 'xStartPos' ], $tab_top );
$textWidth = $colDef [ 'width' ];
2023-03-31 10:36:43 +00:00
$pdf -> MultiCell ( $textWidth , 2 , $colDef [ 'title' ][ 'label' ], '' , $align );
2020-10-07 13:01:28 +00:00
// Add variant of translation if $outputlangsbis is an object
if ( is_object ( $outputlangsbis ) && trim ( $colDef [ 'title' ][ 'label' ])) {
$pdf -> setCellPaddings ( $colDef [ 'title' ][ 'padding' ][ 3 ], 0 , $colDef [ 'title' ][ 'padding' ][ 1 ], $colDef [ 'title' ][ 'padding' ][ 2 ]);
$pdf -> SetXY ( $colDef [ 'xStartPos' ], $pdf -> GetY ());
$textbis = $outputlangsbis -> transnoentities ( $colDef [ 'title' ][ 'textkey' ]);
2023-03-31 10:36:43 +00:00
$pdf -> MultiCell ( $textWidth , 2 , $textbis , '' , $align );
2020-10-07 13:01:28 +00:00
}
$this -> tabTitleHeight = max ( $pdf -> GetY () - $tab_top , $this -> tabTitleHeight );
// restore cell padding
$pdf -> setCellPaddings ( $curentCellPaddinds [ 'L' ], $curentCellPaddinds [ 'T' ], $curentCellPaddinds [ 'R' ], $curentCellPaddinds [ 'B' ]);
}
}
}
return $this -> tabTitleHeight ;
}
/**
* Define Array Column Field for extrafields
*
2025-11-20 00:47:46 +00:00
* @ param CommonObject $object common object det
2020-10-07 13:01:28 +00:00
* @ param Translate $outputlangs langs
2025-11-20 00:47:46 +00:00
* @ param int < 0 , 1 > $hidedetails Do not show line details
2023-12-06 14:46:39 +00:00
* @ return int Return integer < 0 if KO , >= 0 if OK
2020-10-07 13:01:28 +00:00
*/
public function defineColumnExtrafield ( $object , $outputlangs , $hidedetails = 0 )
{
if ( ! empty ( $hidedetails )) {
2023-01-08 18:28:38 +00:00
return 0 ;
2020-10-07 13:01:28 +00:00
}
if ( empty ( $object -> table_element )) {
2023-01-08 18:28:38 +00:00
return 0 ;
2020-10-07 13:01:28 +00:00
}
2023-01-28 09:32:07 +00:00
// Load extra fields if they haven't been loaded already.
2024-06-19 17:21:45 +00:00
if ( is_null ( $this -> extrafieldsCache )) {
2021-02-23 21:03:23 +00:00
$this -> extrafieldsCache = new ExtraFields ( $this -> db );
}
if ( empty ( $this -> extrafieldsCache -> attributes [ $object -> table_element ])) {
$this -> extrafieldsCache -> fetch_name_optionals_label ( $object -> table_element );
}
2020-10-07 13:01:28 +00:00
$extrafields = $this -> extrafieldsCache ;
2023-01-28 09:36:34 +00:00
if ( ! empty ( $extrafields -> attributes [ $object -> table_element ]) && is_array ( $extrafields -> attributes [ $object -> table_element ]) && array_key_exists ( 'label' , $extrafields -> attributes [ $object -> table_element ]) && is_array ( $extrafields -> attributes [ $object -> table_element ][ 'label' ])) {
2021-02-23 21:03:23 +00:00
foreach ( $extrafields -> attributes [ $object -> table_element ][ 'label' ] as $key => $label ) {
2024-01-13 18:48:20 +00:00
// Don't display separator yet even is set to be displayed (not compatible yet)
2021-02-23 21:03:23 +00:00
if ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ] == 'separate' ) {
2020-10-07 13:01:28 +00:00
continue ;
}
// Enable extrafield ?
$enabled = 0 ;
if ( ! empty ( $extrafields -> attributes [ $object -> table_element ][ 'printable' ][ $key ])) {
$printable = intval ( $extrafields -> attributes [ $object -> table_element ][ 'printable' ][ $key ]);
if ( $printable === 1 || $printable === 2 ) {
$enabled = 1 ;
}
// Note : if $printable === 3 or 4 so, it's displayed after line description not in cols
}
2021-02-23 21:03:23 +00:00
if ( ! $enabled ) {
continue ;
2024-01-13 18:48:20 +00:00
} // don't waste resources if we don't need them...
2020-10-07 13:01:28 +00:00
// Load language if required
2021-02-23 21:03:23 +00:00
if ( ! empty ( $extrafields -> attributes [ $object -> table_element ][ 'langfile' ][ $key ])) {
$outputlangs -> load ( $extrafields -> attributes [ $object -> table_element ][ 'langfile' ][ $key ]);
}
2020-10-07 13:01:28 +00:00
// TODO : add more extrafield customisation capacities for PDF like width, rank...
// set column definition
$def = array (
'rank' => intval ( $extrafields -> attributes [ $object -> table_element ][ 'pos' ][ $key ]),
'width' => 25 , // in mm
2023-12-27 11:12:20 +00:00
'status' => ( bool ) $enabled ,
2020-10-07 13:01:28 +00:00
'title' => array (
'label' => $outputlangs -> transnoentities ( $label )
),
'content' => array (
'align' => 'C'
),
'border-left' => true , // add left line separator
);
$alignTypeRight = array ( 'double' , 'int' , 'price' );
if ( in_array ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ], $alignTypeRight )) {
$def [ 'content' ][ 'align' ] = 'R' ;
}
$alignTypeLeft = array ( 'text' , 'html' );
if ( in_array ( $extrafields -> attributes [ $object -> table_element ][ 'type' ][ $key ], $alignTypeLeft )) {
$def [ 'content' ][ 'align' ] = 'L' ;
}
// for extrafields we use rank of extrafield to place it on PDF
$this -> insertNewColumnDef ( " options_ " . $key , $def );
}
}
2023-01-06 18:24:57 +00:00
2023-01-08 18:28:38 +00:00
return 1 ;
2020-10-07 13:01:28 +00:00
}
2023-09-10 14:50:52 +00:00
/**
* Define Array Column Field into $this -> cols
* This method must be implemented by the module that generate the document with its own columns .
*
2025-11-20 00:47:46 +00:00
* @ param CommonObject $object Common object
2023-09-10 14:50:52 +00:00
* @ param Translate $outputlangs Langs
2025-11-20 00:47:46 +00:00
* @ param int < 0 , 1 > $hidedetails Do not show line details
* @ param int < 0 , 1 > $hidedesc Do not show desc
* @ param int < 0 , 1 > $hideref Do not show ref
2023-09-10 14:50:52 +00:00
* @ return void
*/
public function defineColumnField ( $object , $outputlangs , $hidedetails = 0 , $hidedesc = 0 , $hideref = 0 )
{
// Default field style for content
$this -> defaultContentsFieldsStyle = array (
'align' => 'R' , // R,C,L
'padding' => array ( 1 , 0.5 , 1 , 0.5 ), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
);
// Default field style for content
$this -> defaultTitlesFieldsStyle = array (
'align' => 'C' , // R,C,L
'padding' => array ( 0.5 , 0 , 0.5 , 0 ), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
);
// Example
/*
$rank = 0 ; // do not use negative rank
$this -> cols [ 'desc' ] = array (
'rank' => $rank ,
'width' => false , // only for desc
'status' => true ,
'title' => array (
2025-11-06 16:11:02 +00:00
'textkey' => 'Designation' , // use lang key is useful in some case with module
2023-09-10 14:50:52 +00:00
'align' => 'L' ,
// 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
// 'label' => ' ', // the final label
'padding' => array ( 0.5 , 0.5 , 0.5 , 0.5 ), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
),
'content' => array (
'align' => 'L' ,
'padding' => array ( 1 , 0.5 , 1 , 1.5 ), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
),
);
*/
}
2011-01-23 18:04:53 +00:00
}