pdf.lib.php 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635
  1. <?php
  2. /* Copyright (C) 2006-2011 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  4. * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
  5. * Copyright (C) 2010-2012 Regis Houssin <regis.houssin@capnetworks.com>
  6. * Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
  7. * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
  8. * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. * or see http://www.gnu.org/
  23. */
  24. /**
  25. * \file htdocs/core/lib/pdf.lib.php
  26. * \brief Set of functions used for PDF generation
  27. * \ingroup core
  28. */
  29. /**
  30. * Return array with format properties of default PDF format
  31. *
  32. * @param Translate $outputlangs Output lang to use to autodetect output format if setup not done
  33. * @return array Array('width'=>w,'height'=>h,'unit'=>u);
  34. */
  35. function pdf_getFormat($outputlangs='')
  36. {
  37. global $conf,$db;
  38. // Default value if setup was not done and/or entry into c_paper_format not defined
  39. $width=210; $height=297; $unit='mm';
  40. if (empty($conf->global->MAIN_PDF_FORMAT))
  41. {
  42. include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  43. $pdfformat=dol_getDefaultFormat($outputlangs);
  44. }
  45. else $pdfformat=$conf->global->MAIN_PDF_FORMAT;
  46. $sql="SELECT code, label, width, height, unit FROM ".MAIN_DB_PREFIX."c_paper_format";
  47. $sql.=" WHERE code = '".$pdfformat."'";
  48. $resql=$db->query($sql);
  49. if ($resql)
  50. {
  51. $obj=$db->fetch_object($resql);
  52. if ($obj)
  53. {
  54. $width=(int) $obj->width;
  55. $height=(int) $obj->height;
  56. $unit=$obj->unit;
  57. }
  58. }
  59. //print "pdfformat=".$pdfformat." width=".$width." height=".$height." unit=".$unit;
  60. return array('width'=>$width,'height'=>$height,'unit'=>$unit);
  61. }
  62. /**
  63. * Return a PDF instance object. We create a FPDI instance that instantiate TCPDF.
  64. *
  65. * @param string $format Array(width,height). Keep empty to use default setup.
  66. * @param string $metric Unit of format ('mm')
  67. * @param string $pagetype 'P' or 'l'
  68. * @return TPDF PDF object
  69. */
  70. function pdf_getInstance($format='',$metric='mm',$pagetype='P')
  71. {
  72. global $conf;
  73. // Define constant for TCPDF
  74. if (! defined('K_TCPDF_EXTERNAL_CONFIG'))
  75. {
  76. define('K_TCPDF_EXTERNAL_CONFIG',1); // this avoid using tcpdf_config file
  77. define('K_PATH_CACHE', DOL_DATA_ROOT.'/admin/temp/');
  78. define('K_PATH_URL_CACHE', DOL_DATA_ROOT.'/admin/temp/');
  79. dol_mkdir(K_PATH_CACHE);
  80. define('K_BLANK_IMAGE', '_blank.png');
  81. define('PDF_PAGE_FORMAT', 'A4');
  82. define('PDF_PAGE_ORIENTATION', 'P');
  83. define('PDF_CREATOR', 'TCPDF');
  84. define('PDF_AUTHOR', 'TCPDF');
  85. define('PDF_HEADER_TITLE', 'TCPDF Example');
  86. define('PDF_HEADER_STRING', "by Dolibarr ERP CRM");
  87. define('PDF_UNIT', 'mm');
  88. define('PDF_MARGIN_HEADER', 5);
  89. define('PDF_MARGIN_FOOTER', 10);
  90. define('PDF_MARGIN_TOP', 27);
  91. define('PDF_MARGIN_BOTTOM', 25);
  92. define('PDF_MARGIN_LEFT', 15);
  93. define('PDF_MARGIN_RIGHT', 15);
  94. define('PDF_FONT_NAME_MAIN', 'helvetica');
  95. define('PDF_FONT_SIZE_MAIN', 10);
  96. define('PDF_FONT_NAME_DATA', 'helvetica');
  97. define('PDF_FONT_SIZE_DATA', 8);
  98. define('PDF_FONT_MONOSPACED', 'courier');
  99. define('PDF_IMAGE_SCALE_RATIO', 1.25);
  100. define('HEAD_MAGNIFICATION', 1.1);
  101. define('K_CELL_HEIGHT_RATIO', 1.25);
  102. define('K_TITLE_MAGNIFICATION', 1.3);
  103. define('K_SMALL_RATIO', 2/3);
  104. define('K_THAI_TOPCHARS', true);
  105. define('K_TCPDF_CALLS_IN_HTML', true);
  106. define('K_TCPDF_THROW_EXCEPTION_ERROR', false);
  107. }
  108. if (! empty($conf->global->MAIN_USE_FPDF) && ! empty($conf->global->MAIN_DISABLE_FPDI))
  109. return "Error MAIN_USE_FPDF and MAIN_DISABLE_FPDI can't be set together";
  110. // We use by default TCPDF else FPDF
  111. if (empty($conf->global->MAIN_USE_FPDF)) require_once TCPDF_PATH.'tcpdf.php';
  112. else require_once FPDF_PATH.'fpdf.php';
  113. // We need to instantiate fpdi object (instead of tcpdf) to use merging features. But we can disable it.
  114. if (empty($conf->global->MAIN_DISABLE_FPDI)) require_once FPDI_PATH.'fpdi.php';
  115. //$arrayformat=pdf_getFormat();
  116. //$format=array($arrayformat['width'],$arrayformat['height']);
  117. //$metric=$arrayformat['unit'];
  118. // Protection and encryption of pdf
  119. if (empty($conf->global->MAIN_USE_FPDF) && ! empty($conf->global->PDF_SECURITY_ENCRYPTION))
  120. {
  121. /* Permission supported by TCPDF
  122. - print : Print the document;
  123. - modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
  124. - copy : Copy or otherwise extract text and graphics from the document;
  125. - annot-forms : Add or modify text annotations, fill in interactive form fields, and, if 'modify' is also set, create or modify interactive form fields (including signature fields);
  126. - fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
  127. - extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
  128. - assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
  129. - print-high : Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this is not set, printing is limited to a low-level representation of the appearance, possibly of degraded quality.
  130. - owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
  131. */
  132. if (class_exists('FPDI')) $pdf = new FPDI($pagetype,$metric,$format);
  133. else $pdf = new TCPDF($pagetype,$metric,$format);
  134. // For TCPDF, we specify permission we want to block
  135. $pdfrights = array('modify','copy');
  136. $pdfuserpass = ''; // Password for the end user
  137. $pdfownerpass = NULL; // Password of the owner, created randomly if not defined
  138. $pdf->SetProtection($pdfrights,$pdfuserpass,$pdfownerpass);
  139. }
  140. else
  141. {
  142. if (class_exists('FPDI')) $pdf = new FPDI($pagetype,$metric,$format);
  143. else $pdf = new TCPDF($pagetype,$metric,$format);
  144. }
  145. // If we use FPDF class, we may need to add method writeHTMLCell
  146. if (! empty($conf->global->MAIN_USE_FPDF) && ! method_exists($pdf, 'writeHTMLCell'))
  147. {
  148. // Declare here a class to overwrite FPDI to add method writeHTMLCell
  149. /**
  150. * This class is an enhanced FPDI class that support method writeHTMLCell
  151. */
  152. class FPDI_DolExtended extends FPDI
  153. {
  154. /**
  155. * __call
  156. *
  157. * @param string $method Method
  158. * @param mixed $args Arguments
  159. * @return void
  160. */
  161. public function __call($method, $args)
  162. {
  163. if (isset($this->$method)) {
  164. $func = $this->$method;
  165. $func($args);
  166. }
  167. }
  168. /**
  169. * writeHTMLCell
  170. *
  171. * @param int $w Width
  172. * @param int $h Height
  173. * @param int $x X
  174. * @param int $y Y
  175. * @param string $html Html
  176. * @param int $border Border
  177. * @param int $ln Ln
  178. * @param boolean $fill Fill
  179. * @param boolean $reseth Reseth
  180. * @param string $align Align
  181. * @param boolean $autopadding Autopadding
  182. * @return void
  183. */
  184. public function writeHTMLCell($w, $h, $x, $y, $html = '', $border = 0, $ln = 0, $fill = false, $reseth = true, $align = '', $autopadding = true)
  185. {
  186. $this->SetXY($x,$y);
  187. $val=str_replace('<br>',"\n",$html);
  188. //$val=dol_string_nohtmltag($val,false,'ISO-8859-1');
  189. $val=dol_string_nohtmltag($val,false,'UTF-8');
  190. $this->MultiCell($w,$h,$val,$border,$align,$fill);
  191. }
  192. }
  193. $pdf2=new FPDI_DolExtended($pagetype,$metric,$format);
  194. unset($pdf);
  195. $pdf=$pdf2;
  196. }
  197. return $pdf;
  198. }
  199. /**
  200. * Return font name to use for PDF generation
  201. *
  202. * @param Translate $outputlangs Output langs object
  203. * @return string Name of font to use
  204. */
  205. function pdf_getPDFFont($outputlangs)
  206. {
  207. global $conf;
  208. if (! empty($conf->global->MAIN_PDF_FORCE_FONT)) return $conf->global->MAIN_PDF_FORCE_FONT;
  209. $font='Helvetica'; // By default, for FPDI, or ISO language on TCPDF
  210. if (class_exists('TCPDF')) // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower)
  211. {
  212. if ($outputlangs->trans('FONTFORPDF')!='FONTFORPDF')
  213. {
  214. $font=$outputlangs->trans('FONTFORPDF');
  215. }
  216. }
  217. return $font;
  218. }
  219. /**
  220. * Return font size to use for PDF generation
  221. *
  222. * @param Translate $outputlangs Output langs object
  223. * @return int Size of font to use
  224. */
  225. function pdf_getPDFFontSize($outputlangs)
  226. {
  227. $size=10; // By default, for FPDI or ISO language on TCPDF
  228. if (class_exists('TCPDF')) // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower)
  229. {
  230. if ($outputlangs->trans('FONTSIZEFORPDF')!='FONTSIZEFORPDF')
  231. {
  232. $size = (int) $outputlangs->trans('FONTSIZEFORPDF');
  233. }
  234. }
  235. return $size;
  236. }
  237. /**
  238. * Return height to use for Logo onto PDF
  239. *
  240. * @param string $logo Full path to logo file to use
  241. * @param bool $url Image with url (true or false)
  242. * @return number
  243. */
  244. function pdf_getHeightForLogo($logo, $url = false)
  245. {
  246. $height=22; $maxwidth=130;
  247. include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
  248. $tmp=dol_getImageSize($logo, $url);
  249. if ($tmp['height'])
  250. {
  251. $width=round($height*$tmp['width']/$tmp['height']);
  252. if ($width > $maxwidth) $height=$height*$maxwidth/$width;
  253. }
  254. //print $tmp['width'].' '.$tmp['height'].' '.$width; exit;
  255. return $height;
  256. }
  257. /**
  258. * Return a string with full address formated
  259. *
  260. * @param Translate $outputlangs Output langs object
  261. * @param Societe $sourcecompany Source company object
  262. * @param Societe $targetcompany Target company object
  263. * @param Contact $targetcontact Target contact object
  264. * @param int $usecontact Use contact instead of company
  265. * @param int $mode Address type
  266. * @param Societe $deliverycompany Delivery company object
  267. * @return string String with full address
  268. */
  269. function pdf_build_address($outputlangs,$sourcecompany,$targetcompany='',$targetcontact='',$usecontact=0,$mode='source',$deliverycompany='')
  270. {
  271. global $conf;
  272. $stringaddress = '';
  273. if ($mode == 'source' && ! is_object($sourcecompany)) return -1;
  274. if ($mode == 'target' && ! is_object($targetcompany)) return -1;
  275. if ($mode == 'delivery' && ! is_object($deliverycompany)) return -1;
  276. if (! empty($sourcecompany->state_id) && empty($sourcecompany->departement)) $sourcecompany->departement=getState($sourcecompany->state_id); //TODO: Deprecated
  277. if (! empty($sourcecompany->state_id) && empty($sourcecompany->state)) $sourcecompany->state=getState($sourcecompany->state_id);
  278. if (! empty($targetcompany->state_id) && empty($targetcompany->departement)) $targetcompany->departement=getState($targetcompany->state_id);
  279. if ($mode == 'source')
  280. {
  281. $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset(dol_format_address($sourcecompany))."\n";
  282. if (empty($conf->global->MAIN_PDF_DISABLESOURCEDETAILS))
  283. {
  284. // Phone
  285. if ($sourcecompany->phone) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Phone").": ".$outputlangs->convToOutputCharset($sourcecompany->phone);
  286. // Fax
  287. if ($sourcecompany->fax) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($sourcecompany->fax);
  288. // EMail
  289. if ($sourcecompany->email) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($sourcecompany->email);
  290. // Web
  291. if ($sourcecompany->url) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
  292. }
  293. }
  294. if ($mode == 'target')
  295. {
  296. if ($usecontact)
  297. {
  298. $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs,1));
  299. if (!empty($targetcontact->address)) {
  300. $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset(dol_format_address($targetcontact))."\n";
  301. }else {
  302. $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset(dol_format_address($targetcompany))."\n";
  303. }
  304. // Country
  305. if (!empty($targetcontact->country_code) && $targetcontact->country_code != $sourcecompany->country_code) {
  306. $stringaddress.=$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcontact->country_code))."\n";
  307. }
  308. else if (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
  309. $stringaddress.=$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code))."\n";
  310. }
  311. if (! empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS))
  312. {
  313. // Phone
  314. if ($targetcontact->phone_pro) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Phone").": ".$outputlangs->convToOutputCharset($targetcontact->phone_pro);
  315. // Fax
  316. if ($targetcontact->fax) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcontact->fax);
  317. // EMail
  318. if ($targetcontact->email) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcontact->email);
  319. // Web
  320. if ($targetcontact->url) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcontact->url);
  321. }
  322. }
  323. else
  324. {
  325. $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset(dol_format_address($targetcompany))."\n";
  326. // Country
  327. if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) $stringaddress.=$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code))."\n";
  328. if (! empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS))
  329. {
  330. // Phone
  331. if ($targetcompany->phone) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Phone").": ".$outputlangs->convToOutputCharset($targetcompany->phone);
  332. // Fax
  333. if ($targetcompany->fax) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcompany->fax);
  334. // EMail
  335. if ($targetcompany->email) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcompany->email);
  336. // Web
  337. if ($targetcompany->url) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcompany->url);
  338. }
  339. }
  340. // Intra VAT
  341. if (empty($conf->global->MAIN_TVAINTRA_NOT_IN_ADDRESS))
  342. {
  343. if ($targetcompany->tva_intra) $stringaddress.="\n".$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
  344. }
  345. // Professionnal Ids
  346. if (! empty($conf->global->MAIN_PROFID1_IN_ADDRESS) && ! empty($targetcompany->idprof1))
  347. {
  348. $tmp=$outputlangs->transcountrynoentities("ProfId1",$targetcompany->country_code);
  349. if (preg_match('/\((.+)\)/',$tmp,$reg)) $tmp=$reg[1];
  350. $stringaddress.="\n".$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
  351. }
  352. if (! empty($conf->global->MAIN_PROFID2_IN_ADDRESS) && ! empty($targetcompany->idprof2))
  353. {
  354. $tmp=$outputlangs->transcountrynoentities("ProfId2",$targetcompany->country_code);
  355. if (preg_match('/\((.+)\)/',$tmp,$reg)) $tmp=$reg[1];
  356. $stringaddress.="\n".$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
  357. }
  358. if (! empty($conf->global->MAIN_PROFID3_IN_ADDRESS) && ! empty($targetcompany->idprof3))
  359. {
  360. $tmp=$outputlangs->transcountrynoentities("ProfId3",$targetcompany->country_code);
  361. if (preg_match('/\((.+)\)/',$tmp,$reg)) $tmp=$reg[1];
  362. $stringaddress.="\n".$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
  363. }
  364. if (! empty($conf->global->MAIN_PROFID4_IN_ADDRESS) && ! empty($targetcompany->idprof4))
  365. {
  366. $tmp=$outputlangs->transcountrynoentities("ProfId4",$targetcompany->country_code);
  367. if (preg_match('/\((.+)\)/',$tmp,$reg)) $tmp=$reg[1];
  368. $stringaddress.="\n".$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
  369. }
  370. }
  371. if ($mode == 'delivery') // for a delivery address (address + phone/fax)
  372. {
  373. $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->convToOutputCharset(dol_format_address($deliverycompany))."\n";
  374. // Phone
  375. if ($deliverycompany->phone) $stringaddress .= ($stringaddress ? "\n" : '' ).$outputlangs->transnoentities("Phone").": ".$outputlangs->convToOutputCharset($deliverycompany->phone);
  376. // Fax
  377. if ($deliverycompany->fax) $stringaddress .= ($stringaddress ? ($deliverycompany->phone ? " - " : "\n") : '' ).$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($deliverycompany->fax);
  378. }
  379. return $stringaddress;
  380. }
  381. /**
  382. * Show header of page for PDF generation
  383. *
  384. * @param PDF &$pdf Object PDF
  385. * @param Translate $outputlangs Object lang for output
  386. * @param int $page_height Height of page
  387. * @return void
  388. */
  389. function pdf_pagehead(&$pdf,$outputlangs,$page_height)
  390. {
  391. global $conf;
  392. // Add a background image on document
  393. if (! empty($conf->global->MAIN_USE_BACKGROUND_ON_PDF))
  394. {
  395. $pdf->Image($conf->mycompany->dir_output.'/logos/'.$conf->global->MAIN_USE_BACKGROUND_ON_PDF, 0, 0, 0, $page_height);
  396. }
  397. }
  398. /**
  399. * Add a draft watermark on PDF files
  400. *
  401. * @param PDF &$pdf Object PDF
  402. * @param Translate $outputlangs Object lang
  403. * @param int $h Height of PDF
  404. * @param int $w Width of PDF
  405. * @param string $unit Unit of height (mm, pt, ...)
  406. * @param string $text Text to show
  407. * @return void
  408. */
  409. function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
  410. {
  411. // Print Draft Watermark
  412. if ($unit=='pt') $k=1;
  413. elseif ($unit=='mm') $k=72/25.4;
  414. elseif ($unit=='cm') $k=72/2.54;
  415. elseif ($unit=='in') $k=72;
  416. $savx=$pdf->getX(); $savy=$pdf->getY();
  417. $watermark_angle=atan($h/$w)/2;
  418. $watermark_x_pos=0;
  419. $watermark_y_pos=$h/3;
  420. $watermark_x=$w/2;
  421. $watermark_y=$h/3;
  422. $pdf->SetFont('','B',40);
  423. $pdf->SetTextColor(255,192,203);
  424. //rotate
  425. $pdf->_out(sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm',cos($watermark_angle),sin($watermark_angle),-sin($watermark_angle),cos($watermark_angle),$watermark_x*$k,($h-$watermark_y)*$k,-$watermark_x*$k,-($h-$watermark_y)*$k));
  426. //print watermark
  427. $pdf->SetXY($watermark_x_pos,$watermark_y_pos);
  428. $pdf->Cell($w-20,25,$outputlangs->convToOutputCharset($text),"",2,"C",0);
  429. //antirotate
  430. $pdf->_out('Q');
  431. $pdf->SetXY($savx,$savy);
  432. }
  433. /**
  434. * Show bank informations for PDF generation
  435. *
  436. * @param PDF &$pdf Object PDF
  437. * @param Translate $outputlangs Object lang
  438. * @param int $curx X
  439. * @param int $cury Y
  440. * @param Account $account Bank account object
  441. * @param int $onlynumber Output only number
  442. * @param int $default_font_size Default font size
  443. * @return float The Y PDF position
  444. */
  445. function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default_font_size=10)
  446. {
  447. global $mysoc, $conf;
  448. $diffsizetitle=(empty($conf->global->PDF_DIFFSIZE_TITLE)?3:$conf->global->PDF_DIFFSIZE_TITLE);
  449. $diffsizecontent=(empty($conf->global->PDF_DIFFSIZE_CONTENT)?4:$conf->global->PDF_DIFFSIZE_CONTENT);
  450. $pdf->SetXY($curx, $cury);
  451. if (empty($onlynumber))
  452. {
  453. $pdf->SetFont('','B',$default_font_size - $diffsizetitle);
  454. $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', 0);
  455. $cury+=4;
  456. }
  457. $outputlangs->load("banks");
  458. // Get format of bank account according to its country
  459. $usedetailedbban=$account->useDetailedBBAN();
  460. //$onlynumber=0; $usedetailedbban=0; // For tests
  461. if ($usedetailedbban)
  462. {
  463. $savcurx=$curx;
  464. if (empty($onlynumber))
  465. {
  466. $pdf->SetFont('','',$default_font_size - $diffsizecontent);
  467. $pdf->SetXY($curx, $cury);
  468. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': ' . $outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
  469. $cury+=3;
  470. }
  471. if (empty($onlynumber)) $pdf->line($curx+1, $cury+1, $curx+1, $cury+8);
  472. if ($usedetailedbban == 1)
  473. {
  474. $fieldstoshow=array('bank','desk','number','key');
  475. if ($conf->global->BANK_SHOW_ORDER_OPTION==1) $fieldstoshow=array('bank','desk','key','number');
  476. }
  477. else if ($usedetailedbban == 2)
  478. {
  479. $fieldstoshow=array('bank','number');
  480. }
  481. else dol_print_error('','Value returned by function useDetailedBBAN not managed');
  482. foreach ($fieldstoshow as $val)
  483. {
  484. if ($val == 'bank')
  485. {
  486. // Bank code
  487. $tmplength=18;
  488. $pdf->SetXY($curx, $cury+5);
  489. $pdf->SetFont('','',$default_font_size - 3);$pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($account->code_banque), 0, 'C', 0);
  490. $pdf->SetXY($curx, $cury+1);
  491. $curx+=$tmplength;
  492. $pdf->SetFont('','B',$default_font_size - 4);$pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities("BankCode"), 0, 'C', 0);
  493. if (empty($onlynumber)) $pdf->line($curx, $cury+1, $curx, $cury+8);
  494. }
  495. if ($val == 'desk')
  496. {
  497. // Desk
  498. $tmplength=18;
  499. $pdf->SetXY($curx, $cury+5);
  500. $pdf->SetFont('','',$default_font_size - 3);$pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($account->code_guichet), 0, 'C', 0);
  501. $pdf->SetXY($curx, $cury+1);
  502. $curx+=$tmplength;
  503. $pdf->SetFont('','B',$default_font_size - 4);$pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities("DeskCode"), 0, 'C', 0);
  504. if (empty($onlynumber)) $pdf->line($curx, $cury+1, $curx, $cury+8);
  505. }
  506. if ($val == 'number')
  507. {
  508. // Number
  509. $tmplength=24;
  510. $pdf->SetXY($curx, $cury+5);
  511. $pdf->SetFont('','',$default_font_size - 3);$pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($account->number), 0, 'C', 0);
  512. $pdf->SetXY($curx, $cury+1);
  513. $curx+=$tmplength;
  514. $pdf->SetFont('','B',$default_font_size - 4);$pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities("BankAccountNumber"), 0, 'C', 0);
  515. if (empty($onlynumber)) $pdf->line($curx, $cury+1, $curx, $cury+8);
  516. }
  517. if ($val == 'key')
  518. {
  519. // Key
  520. $tmplength=13;
  521. $pdf->SetXY($curx, $cury+5);
  522. $pdf->SetFont('','',$default_font_size - 3);$pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($account->cle_rib), 0, 'C', 0);
  523. $pdf->SetXY($curx, $cury+1);
  524. $curx+=$tmplength;
  525. $pdf->SetFont('','B',$default_font_size - 4);$pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities("BankAccountNumberKey"), 0, 'C', 0);
  526. if (empty($onlynumber)) $pdf->line($curx, $cury+1, $curx, $cury+8);
  527. }
  528. }
  529. $curx=$savcurx;
  530. $cury+=10;
  531. }
  532. else
  533. {
  534. $pdf->SetFont('','B',$default_font_size - $diffsizecontent);
  535. $pdf->SetXY($curx, $cury);
  536. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': ' . $outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
  537. $cury+=3;
  538. $pdf->SetFont('','B',$default_font_size - $diffsizecontent);
  539. $pdf->SetXY($curx, $cury);
  540. $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': ' . $outputlangs->convToOutputCharset($account->number), 0, 'L', 0);
  541. $cury+=3;
  542. if ($diffsizecontent <= 2) $cury+=1;
  543. }
  544. // Use correct name of bank id according to country
  545. $ibankey="IBANNumber";
  546. $bickey="BICNumber";
  547. if ($account->getCountryCode() == 'IN') $ibankey="IFSC";
  548. if ($account->getCountryCode() == 'IN') $bickey="SWIFT";
  549. $pdf->SetFont('','',$default_font_size - $diffsizecontent);
  550. if (empty($onlynumber) && ! empty($account->domiciliation))
  551. {
  552. $pdf->SetXY($curx, $cury);
  553. $val=$outputlangs->transnoentities("Residence").': ' . $outputlangs->convToOutputCharset($account->domiciliation);
  554. $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
  555. //$nboflines=dol_nboflines_bis($val,120);
  556. //$cury+=($nboflines*3)+2;
  557. $tmpy=$pdf->getStringHeight(100, $val);
  558. $cury+=$tmpy;
  559. }
  560. else if (! $usedetailedbban) $cury+=1;
  561. if (! empty($account->iban))
  562. {
  563. $pdf->SetXY($curx, $cury);
  564. $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': ' . $outputlangs->convToOutputCharset($account->iban), 0, 'L', 0);
  565. $cury+=3;
  566. }
  567. if (! empty($account->bic))
  568. {
  569. $pdf->SetXY($curx, $cury);
  570. $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': ' . $outputlangs->convToOutputCharset($account->bic), 0, 'L', 0);
  571. }
  572. return $pdf->getY();
  573. }
  574. /**
  575. * Show footer of page for PDF generation
  576. *
  577. * @param PDF &$pdf The PDF factory
  578. * @param Translate $outputlangs Object lang for output
  579. * @param string $paramfreetext Constant name of free text
  580. * @param Societe $fromcompany Object company
  581. * @param int $marge_basse Margin bottom we use for the autobreak
  582. * @param int $marge_gauche Margin left (no more used)
  583. * @param int $page_hauteur Page height (no more used)
  584. * @param Object $object Object shown in PDF
  585. * @param int $showdetails Show company details into footer. This param seems to not be used by standard version.
  586. * @param int $hidefreetext 1=Hide free text, 0=Show free text
  587. * @return int Return height of bottom margin including footer text
  588. */
  589. function pdf_pagefoot(&$pdf,$outputlangs,$paramfreetext,$fromcompany,$marge_basse,$marge_gauche,$page_hauteur,$object,$showdetails=0,$hidefreetext=0)
  590. {
  591. global $conf,$user;
  592. $outputlangs->load("dict");
  593. $line='';
  594. $dims=$pdf->getPageDimensions();
  595. // Line of free text
  596. if (empty($hidefreetext) && ! empty($conf->global->$paramfreetext))
  597. {
  598. // Make substitution
  599. $substitutionarray=array(
  600. '__FROM_NAME__' => $fromcompany->nom,
  601. '__FROM_EMAIL__' => $fromcompany->email,
  602. '__TOTAL_TTC__' => $object->total_ttc,
  603. '__TOTAL_HT__' => $object->total_ht,
  604. '__TOTAL_VAT__' => $object->total_vat
  605. );
  606. complete_substitutions_array($substitutionarray,$outputlangs,$object);
  607. $newfreetext=make_substitutions($conf->global->$paramfreetext,$substitutionarray);
  608. $line.=$outputlangs->convToOutputCharset($newfreetext);
  609. }
  610. // First line of company infos
  611. if ($showdetails)
  612. {
  613. $line1="";
  614. // Company name
  615. if ($fromcompany->name)
  616. {
  617. $line1.=($line1?" - ":"").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
  618. }
  619. // Address
  620. if ($fromcompany->address)
  621. {
  622. $line1.=($line1?" - ":"").$fromcompany->address;
  623. }
  624. // Zip code
  625. if ($fromcompany->zip)
  626. {
  627. $line1.=($line1?" - ":"").$fromcompany->zip;
  628. }
  629. // Town
  630. if ($fromcompany->town)
  631. {
  632. $line1.=($line1?" ":"").$fromcompany->town;
  633. }
  634. // Phone
  635. if ($fromcompany->phone)
  636. {
  637. $line1.=($line1?" - ":"").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
  638. }
  639. // Fax
  640. if ($fromcompany->fax)
  641. {
  642. $line1.=($line1?" - ":"").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
  643. }
  644. $line2="";
  645. // URL
  646. if ($fromcompany->url)
  647. {
  648. $line2.=($line2?" - ":"").$fromcompany->url;
  649. }
  650. // Email
  651. if ($fromcompany->email)
  652. {
  653. $line2.=($line2?" - ":"").$fromcompany->email;
  654. }
  655. }
  656. // Line 3 of company infos
  657. $line3="";
  658. // Juridical status
  659. if ($fromcompany->forme_juridique_code)
  660. {
  661. $line3.=($line3?" - ":"").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel($fromcompany->forme_juridique_code));
  662. }
  663. // Capital
  664. if ($fromcompany->capital)
  665. {
  666. $line3.=($line3?" - ":"").$outputlangs->transnoentities("CapitalOf",$fromcompany->capital)." ".$outputlangs->transnoentities("Currency".$conf->currency);
  667. }
  668. // Prof Id 1
  669. if ($fromcompany->idprof1 && ($fromcompany->country_code != 'FR' || ! $fromcompany->idprof2))
  670. {
  671. $field=$outputlangs->transcountrynoentities("ProfId1",$fromcompany->country_code);
  672. if (preg_match('/\((.*)\)/i',$field,$reg)) $field=$reg[1];
  673. $line3.=($line3?" - ":"").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
  674. }
  675. // Prof Id 2
  676. if ($fromcompany->idprof2)
  677. {
  678. $field=$outputlangs->transcountrynoentities("ProfId2",$fromcompany->country_code);
  679. if (preg_match('/\((.*)\)/i',$field,$reg)) $field=$reg[1];
  680. $line3.=($line3?" - ":"").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
  681. }
  682. // Line 4 of company infos
  683. $line4="";
  684. // Prof Id 3
  685. if ($fromcompany->idprof3)
  686. {
  687. $field=$outputlangs->transcountrynoentities("ProfId3",$fromcompany->country_code);
  688. if (preg_match('/\((.*)\)/i',$field,$reg)) $field=$reg[1];
  689. $line4.=($line4?" - ":"").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
  690. }
  691. // Prof Id 4
  692. if ($fromcompany->idprof4)
  693. {
  694. $field=$outputlangs->transcountrynoentities("ProfId4",$fromcompany->country_code);
  695. if (preg_match('/\((.*)\)/i',$field,$reg)) $field=$reg[1];
  696. $line4.=($line4?" - ":"").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
  697. }
  698. // IntraCommunautary VAT
  699. if ($fromcompany->tva_intra != '')
  700. {
  701. $line4.=($line4?" - ":"").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
  702. }
  703. $pdf->SetFont('','',7);
  704. $pdf->SetDrawColor(224,224,224);
  705. // The start of the bottom of this page footer is positioned according to # of lines
  706. $freetextheight=0;
  707. if ($line) // Free text
  708. {
  709. $width=20000; $align='L'; // By default, ask a manual break: We use a large value 20000, to not have automatic wrap. This make user understand, he need to add CR on its text.
  710. if (! empty($conf->global->MAIN_USE_AUTOWRAP_ON_FREETEXT)) {
  711. $width=200; $align='C';
  712. }
  713. $freetextheight=$pdf->getStringHeight($width,$line);
  714. }
  715. $marginwithfooter=$marge_basse + $freetextheight + (! empty($line1)?3:0) + (! empty($line2)?3:0) + (! empty($line3)?3:0) + (! empty($line4)?3:0);
  716. $posy=$marginwithfooter+0;
  717. if ($line) // Free text
  718. {
  719. $pdf->SetXY($dims['lm'],-$posy);
  720. $pdf->MultiCell($width, 3, $line, 0, $align, 0);
  721. $posy-=$freetextheight;
  722. }
  723. $pdf->SetY(-$posy);
  724. $pdf->line($dims['lm'], $dims['hk']-$posy, $dims['wk']-$dims['rm'], $dims['hk']-$posy);
  725. $posy--;
  726. if (! empty($line1))
  727. {
  728. $pdf->SetFont('','B',7);
  729. $pdf->SetXY($dims['lm'],-$posy);
  730. $pdf->MultiCell($dims['wk']-$dims['rm'], 2, $line1, 0, 'C', 0);
  731. $posy-=3;
  732. $pdf->SetFont('','',7);
  733. }
  734. if (! empty($line2))
  735. {
  736. $pdf->SetFont('','B',7);
  737. $pdf->SetXY($dims['lm'],-$posy);
  738. $pdf->MultiCell($dims['wk']-$dims['rm'], 2, $line2, 0, 'C', 0);
  739. $posy-=3;
  740. $pdf->SetFont('','',7);
  741. }
  742. if (! empty($line3))
  743. {
  744. $pdf->SetXY($dims['lm'],-$posy);
  745. $pdf->MultiCell($dims['wk']-$dims['rm'], 2, $line3, 0, 'C', 0);
  746. }
  747. if (! empty($line4))
  748. {
  749. $posy-=3;
  750. $pdf->SetXY($dims['lm'],-$posy);
  751. $pdf->MultiCell($dims['wk']-$dims['rm'], 2, $line4, 0, 'C', 0);
  752. }
  753. // Show page nb only on iso languages (so default Helvetica font)
  754. if (mb_strtolower(pdf_getPDFFont($outputlangs)) == 'helvetica')
  755. {
  756. $pdf->SetXY(-20,-$posy);
  757. //print 'xxx'.$pdf->PageNo().'-'.$pdf->getAliasNbPages().'-'.$pdf->getAliasNumPage();exit;
  758. if (empty($conf->global->MAIN_USE_FPDF)) $pdf->MultiCell(13, 2, $pdf->PageNo().'/'.$pdf->getAliasNbPages(), 0, 'R', 0);
  759. else $pdf->MultiCell(13, 2, $pdf->PageNo().'/{nb}', 0, 'R', 0);
  760. }
  761. return $marginwithfooter;
  762. }
  763. /**
  764. * Show linked objects for PDF generation
  765. *
  766. * @param PDF &$pdf Object PDF
  767. * @param object $object Object
  768. * @param Translate $outputlangs Object lang
  769. * @param int $posx X
  770. * @param int $posy Y
  771. * @param float $w Width of cells. If 0, they extend up to the right margin of the page.
  772. * @param float $h Cell minimum height. The cell extends automatically if needed.
  773. * @param int $align Align
  774. * @param string $default_font_size Font size
  775. * @return float The Y PDF position
  776. */
  777. function pdf_writeLinkedObjects(&$pdf,$object,$outputlangs,$posx,$posy,$w,$h,$align,$default_font_size)
  778. {
  779. $linkedobjects = pdf_getLinkedObjects($object,$outputlangs);
  780. if (! empty($linkedobjects))
  781. {
  782. foreach($linkedobjects as $linkedobject)
  783. {
  784. $posy+=3;
  785. $pdf->SetXY($posx,$posy);
  786. $pdf->SetFont('','', $default_font_size - 2);
  787. $pdf->MultiCell($w, $h, $linkedobject["ref_title"].' : '.$linkedobject["ref_value"], '', $align);
  788. if (! empty($linkedobject["date_title"]) && ! empty($linkedobject["date_value"]))
  789. {
  790. $posy+=3;
  791. $pdf->SetXY($posx,$posy);
  792. $pdf->MultiCell($w, $h, $linkedobject["date_title"].' : '.$linkedobject["date_value"], '', $align);
  793. }
  794. }
  795. }
  796. return $pdf->getY();
  797. }
  798. /**
  799. * Output line description into PDF
  800. *
  801. * @param PDF &$pdf PDF object
  802. * @param Object $object Object
  803. * @param int $i Current line number
  804. * @param Translate $outputlangs Object lang for output
  805. * @param int $w Width
  806. * @param int $h Height
  807. * @param int $posx Pos x
  808. * @param int $posy Pos y
  809. * @param int $hideref Hide reference
  810. * @param int $hidedesc Hide description
  811. * @param int $issupplierline Is it a line for a supplier object ?
  812. * @return void
  813. */
  814. function pdf_writelinedesc(&$pdf,$object,$i,$outputlangs,$w,$h,$posx,$posy,$hideref=0,$hidedesc=0,$issupplierline=0)
  815. {
  816. global $db, $conf, $langs, $hookmanager;
  817. $reshook=0;
  818. if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line) ) )
  819. {
  820. $special_code = $object->lines[$i]->special_code;
  821. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  822. $parameters = array('pdf'=>$pdf,'i'=>$i,'outputlangs'=>$outputlangs,'w'=>$w,'h'=>$h,'posx'=>$posx,'posy'=>$posy,'hideref'=>$hideref,'hidedesc'=>$hidedesc,'issupplierline'=>$issupplierline,'special_code'=>$special_code);
  823. $action='';
  824. $reshook=$hookmanager->executeHooks('pdf_writelinedesc',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  825. }
  826. if (empty($reshook))
  827. {
  828. $labelproductservice=pdf_getlinedesc($object,$i,$outputlangs,$hideref,$hidedesc,$issupplierline);
  829. // Description
  830. $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, 'J',true);
  831. return $labelproductservice;
  832. }
  833. }
  834. /**
  835. * Return line description translated in outputlangs and encoded into htmlentities and with <br>
  836. *
  837. * @param Object $object Object
  838. * @param int $i Current line number (0 = first line, 1 = second line, ...)
  839. * @param Translate $outputlangs Object langs for output
  840. * @param int $hideref Hide reference
  841. * @param int $hidedesc Hide description
  842. * @param int $issupplierline Is it a line for a supplier object ?
  843. * @return string String with line
  844. */
  845. function pdf_getlinedesc($object,$i,$outputlangs,$hideref=0,$hidedesc=0,$issupplierline=0)
  846. {
  847. global $db, $conf, $langs;
  848. $idprod=(! empty($object->lines[$i]->fk_product)?$object->lines[$i]->fk_product:false);
  849. $label=(! empty($object->lines[$i]->label)?$object->lines[$i]->label:(! empty($object->lines[$i]->product_label)?$object->lines[$i]->product_label:''));
  850. $desc=(! empty($object->lines[$i]->desc)?$object->lines[$i]->desc:(! empty($object->lines[$i]->description)?$object->lines[$i]->description:''));
  851. $ref_supplier=(! empty($object->lines[$i]->ref_supplier)?$object->lines[$i]->ref_supplier:(! empty($object->lines[$i]->ref_fourn)?$object->lines[$i]->ref_fourn:'')); // TODO Not yet saved for supplier invoices, only supplier orders
  852. $note=(! empty($object->lines[$i]->note)?$object->lines[$i]->note:'');
  853. $dbatch=(! empty($object->lines[$i]->detail_batch)?$object->lines[$i]->detail_batch:false);
  854. if ($issupplierline) $prodser = new ProductFournisseur($db);
  855. else $prodser = new Product($db);
  856. if ($idprod)
  857. {
  858. $prodser->fetch($idprod);
  859. // If a predefined product and multilang and on other lang, we renamed label with label translated
  860. if (! empty($conf->global->MAIN_MULTILANGS) && ($outputlangs->defaultlang != $langs->defaultlang))
  861. {
  862. if (! empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && $label == $prodser->label) $label=$prodser->multilangs[$outputlangs->defaultlang]["label"];
  863. //Manage HTML entities description test
  864. //Cause $prodser->description is store with htmlentities but $desc no
  865. $needdesctranslation=false;
  866. if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
  867. $needdesctranslation=(strpos(dol_html_entity_decode($desc,ENT_QUOTES | ENT_HTML401),dol_html_entity_decode($prodser->description,ENT_QUOTES | ENT_HTML401))!==false);
  868. } else {
  869. $needdesctranslation=($desc == $prodser->description);
  870. }
  871. if (! empty($prodser->multilangs[$outputlangs->defaultlang]["description"]) && ($needdesctranslation)) $desc=$prodser->multilangs[$outputlangs->defaultlang]["description"];
  872. if (! empty($prodser->multilangs[$outputlangs->defaultlang]["note"]) && $note == $prodser->note) $note=$prodser->multilangs[$outputlangs->defaultlang]["note"];
  873. }
  874. }
  875. // Description short of product line
  876. $libelleproduitservice=$label;
  877. // Description long of product line
  878. if (! empty($desc) && ($desc != $label))
  879. {
  880. if ($libelleproduitservice && empty($hidedesc))
  881. {
  882. $libelleproduitservice.='__N__';
  883. }
  884. if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except)
  885. {
  886. $discount=new DiscountAbsolute($db);
  887. $discount->fetch($object->lines[$i]->fk_remise_except);
  888. $libelleproduitservice=$outputlangs->transnoentitiesnoconv("DiscountFromCreditNote",$discount->ref_facture_source);
  889. }
  890. elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except)
  891. {
  892. $discount=new DiscountAbsolute($db);
  893. $discount->fetch($object->lines[$i]->fk_remise_except);
  894. $libelleproduitservice=$outputlangs->transnoentitiesnoconv("DiscountFromDeposit",$discount->ref_facture_source);
  895. // Add date of deposit
  896. if (! empty($conf->global->INVOICE_ADD_DEPOSIT_DATE)) echo ' ('.dol_print_date($discount->datec,'day','',$outputlangs).')';
  897. }
  898. else
  899. {
  900. if ($idprod)
  901. {
  902. if (empty($hidedesc)) $libelleproduitservice.=$desc;
  903. }
  904. else
  905. {
  906. $libelleproduitservice.=$desc;
  907. }
  908. }
  909. }
  910. // If line linked to a product
  911. if ($idprod)
  912. {
  913. // We add ref
  914. if ($prodser->ref)
  915. {
  916. $prefix_prodserv = "";
  917. $ref_prodserv = "";
  918. if (! empty($conf->global->PRODUCT_ADD_TYPE_IN_DOCUMENTS)) // In standard mode, we do not show this
  919. {
  920. if ($prodser->isservice())
  921. {
  922. $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
  923. }
  924. else
  925. {
  926. $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
  927. }
  928. }
  929. if (empty($hideref))
  930. {
  931. if ($issupplierline) $ref_prodserv = $prodser->ref.' ('.$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.')'; // Show local ref and supplier ref
  932. else $ref_prodserv = $prodser->ref; // Show local ref only
  933. $ref_prodserv .= " - ";
  934. }
  935. $libelleproduitservice=$prefix_prodserv.$ref_prodserv.$libelleproduitservice;
  936. }
  937. }
  938. // Add an additional description for the category products
  939. if (! empty($conf->global->CATEGORY_ADD_DESC_INTO_DOC) && $idprod && ! empty($conf->categorie->enabled))
  940. {
  941. include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
  942. $categstatic=new Categorie($db);
  943. // recovering the list of all the categories linked to product
  944. $tblcateg=$categstatic->containing($idprod,0);
  945. foreach ($tblcateg as $cate)
  946. {
  947. // Adding the descriptions if they are filled
  948. $desccateg=$cate->add_description;
  949. if ($desccateg)
  950. $libelleproduitservice.='__N__'.$desccateg;
  951. }
  952. }
  953. if (! empty($object->lines[$i]->date_start) || ! empty($object->lines[$i]->date_end))
  954. {
  955. $format='day';
  956. // Show duration if exists
  957. if ($object->lines[$i]->date_start && $object->lines[$i]->date_end)
  958. {
  959. $period='('.$outputlangs->transnoentitiesnoconv('DateFromTo',dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs),dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
  960. }
  961. if ($object->lines[$i]->date_start && ! $object->lines[$i]->date_end)
  962. {
  963. $period='('.$outputlangs->transnoentitiesnoconv('DateFrom',dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
  964. }
  965. if (! $object->lines[$i]->date_start && $object->lines[$i]->date_end)
  966. {
  967. $period='('.$outputlangs->transnoentitiesnoconv('DateUntil',dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
  968. }
  969. //print '>'.$outputlangs->charset_output.','.$period;
  970. $libelleproduitservice.="__N__".$period;
  971. //print $libelleproduitservice;
  972. }
  973. if ($dbatch)
  974. {
  975. $format='day';
  976. foreach ($dbatch as $detail)
  977. {
  978. $dte=array();
  979. if ($detail->eatby) $dte[]=$outputlangs->transnoentitiesnoconv('printEatby',dol_print_date($detail->eatby, $format, false, $outputlangs));
  980. if ($detail->sellby) $dte[]=$outputlangs->transnoentitiesnoconv('printSellby',dol_print_date($detail->sellby, $format, false, $outputlangs));
  981. if ($detail->batch) $dte[]=$outputlangs->transnoentitiesnoconv('printBatch',$detail->batch);
  982. $dte[]=$outputlangs->transnoentitiesnoconv('printQty',$detail->dluo_qty);
  983. $libelleproduitservice.= "__N__ ".implode($dte,"-");
  984. }
  985. }
  986. // Now we convert \n into br
  987. if (dol_textishtml($libelleproduitservice)) $libelleproduitservice=preg_replace('/__N__/','<br>',$libelleproduitservice);
  988. else $libelleproduitservice=preg_replace('/__N__/',"\n",$libelleproduitservice);
  989. $libelleproduitservice=dol_htmlentitiesbr($libelleproduitservice,1);
  990. return $libelleproduitservice;
  991. }
  992. /**
  993. * Return line num
  994. *
  995. * @param Object $object Object
  996. * @param int $i Current line number
  997. * @param Translate $outputlangs Object langs for output
  998. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  999. * @return void
  1000. */
  1001. function pdf_getlinenum($object,$i,$outputlangs,$hidedetails=0)
  1002. {
  1003. global $hookmanager;
  1004. if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
  1005. {
  1006. $special_code = $object->lines[$i]->special_code;
  1007. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1008. // TODO add hook function
  1009. }
  1010. else
  1011. {
  1012. return dol_htmlentitiesbr($object->lines[$i]->num);
  1013. }
  1014. }
  1015. /**
  1016. * Return line product ref
  1017. *
  1018. * @param Object $object Object
  1019. * @param int $i Current line number
  1020. * @param Translate $outputlangs Object langs for output
  1021. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1022. * @return void
  1023. */
  1024. function pdf_getlineref($object,$i,$outputlangs,$hidedetails=0)
  1025. {
  1026. global $hookmanager;
  1027. if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
  1028. {
  1029. $special_code = $object->lines[$i]->special_code;
  1030. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1031. // TODO add hook function
  1032. }
  1033. else
  1034. {
  1035. return dol_htmlentitiesbr($object->lines[$i]->product_ref);
  1036. }
  1037. }
  1038. /**
  1039. * Return line ref_supplier
  1040. *
  1041. * @param Object $object Object
  1042. * @param int $i Current line number
  1043. * @param Translate $outputlangs Object langs for output
  1044. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1045. * @return void
  1046. */
  1047. function pdf_getlineref_supplier($object,$i,$outputlangs,$hidedetails=0)
  1048. {
  1049. global $hookmanager;
  1050. if (is_object($hookmanager) && ( ($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
  1051. {
  1052. $special_code = $object->lines[$i]->special_code;
  1053. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1054. // TODO add hook function
  1055. }
  1056. else
  1057. {
  1058. return dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
  1059. }
  1060. }
  1061. /**
  1062. * Return line vat rate
  1063. *
  1064. * @param Object $object Object
  1065. * @param int $i Current line number
  1066. * @param Translate $outputlangs Object langs for output
  1067. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1068. * @return string
  1069. */
  1070. function pdf_getlinevatrate($object,$i,$outputlangs,$hidedetails=0)
  1071. {
  1072. global $hookmanager;
  1073. if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
  1074. {
  1075. $special_code = $object->lines[$i]->special_code;
  1076. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1077. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1078. $action='';
  1079. return $hookmanager->executeHooks('pdf_getlinevatrate',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1080. }
  1081. else
  1082. {
  1083. if (empty($hidedetails) || $hidedetails > 1) return vatrate($object->lines[$i]->tva_tx,1,$object->lines[$i]->info_bits,1);
  1084. }
  1085. }
  1086. /**
  1087. * Return line unit price excluding tax
  1088. *
  1089. * @param Object $object Object
  1090. * @param int $i Current line number
  1091. * @param Translate $outputlangs Object langs for output
  1092. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1093. * @return string
  1094. */
  1095. function pdf_getlineupexcltax($object,$i,$outputlangs,$hidedetails=0)
  1096. {
  1097. global $conf, $hookmanager;
  1098. $sign=1;
  1099. if (isset($object->type) && $object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1;
  1100. if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
  1101. {
  1102. $special_code = $object->lines[$i]->special_code;
  1103. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1104. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1105. $action='';
  1106. return $hookmanager->executeHooks('pdf_getlineupexcltax',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1107. }
  1108. else
  1109. {
  1110. if (empty($hidedetails) || $hidedetails > 1) return price($sign * $object->lines[$i]->subprice, 0, $outputlangs);
  1111. }
  1112. }
  1113. /**
  1114. * Return line unit price including tax
  1115. *
  1116. * @param Object $object Object
  1117. * @param int $i Current line number
  1118. * @param Tranlate $outputlangs Object langs for output
  1119. * @param int $hidedetails Hide value (0 = no, 1 = yes, 2 = just special lines)
  1120. * @return void
  1121. */
  1122. function pdf_getlineupwithtax($object,$i,$outputlangs,$hidedetails=0)
  1123. {
  1124. global $hookmanager;
  1125. if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
  1126. {
  1127. $special_code = $object->lines[$i]->special_code;
  1128. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1129. foreach($object->hooks as $modules)
  1130. {
  1131. if (method_exists($modules[$special_code],'pdf_getlineupwithtax')) return $modules[$special_code]->pdf_getlineupwithtax($object,$i,$outputlangs,$hidedetails);
  1132. }
  1133. }
  1134. else
  1135. {
  1136. if (empty($hidedetails) || $hidedetails > 1) return price(($object->lines[$i]->subprice) + ($object->lines[$i]->subprice)*($object->lines[$i]->tva_tx)/100, 0, $outputlangs);
  1137. }
  1138. }
  1139. /**
  1140. * Return line quantity
  1141. *
  1142. * @param Object $object Object
  1143. * @param int $i Current line number
  1144. * @param Translate $outputlangs Object langs for output
  1145. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1146. * @return string
  1147. */
  1148. function pdf_getlineqty($object,$i,$outputlangs,$hidedetails=0)
  1149. {
  1150. global $hookmanager;
  1151. if ($object->lines[$i]->special_code != 3)
  1152. {
  1153. if (is_object($hookmanager) && (( $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
  1154. {
  1155. $special_code = $object->lines[$i]->special_code;
  1156. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1157. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1158. $action='';
  1159. return $hookmanager->executeHooks('pdf_getlineqty',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1160. }
  1161. else
  1162. {
  1163. if (empty($hidedetails) || $hidedetails > 1) return $object->lines[$i]->qty;
  1164. }
  1165. }
  1166. }
  1167. /**
  1168. * Return line quantity asked
  1169. *
  1170. * @param Object $object Object
  1171. * @param int $i Current line number
  1172. * @param Translate $outputlangs Object langs for output
  1173. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1174. * @return string
  1175. */
  1176. function pdf_getlineqty_asked($object,$i,$outputlangs,$hidedetails=0)
  1177. {
  1178. global $hookmanager;
  1179. if ($object->lines[$i]->special_code != 3)
  1180. {
  1181. if (is_object($hookmanager) && (( $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
  1182. {
  1183. $special_code = $object->lines[$i]->special_code;
  1184. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1185. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1186. $action='';
  1187. return $hookmanager->executeHooks('pdf_getlineqty_asked',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1188. }
  1189. else
  1190. {
  1191. if (empty($hidedetails) || $hidedetails > 1) return $object->lines[$i]->qty_asked;
  1192. }
  1193. }
  1194. }
  1195. /**
  1196. * Return line quantity shipped
  1197. *
  1198. * @param Object $object Object
  1199. * @param int $i Current line number
  1200. * @param Translate $outputlangs Object langs for output
  1201. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1202. * @return string
  1203. */
  1204. function pdf_getlineqty_shipped($object,$i,$outputlangs,$hidedetails=0)
  1205. {
  1206. global $hookmanager;
  1207. if ($object->lines[$i]->special_code != 3)
  1208. {
  1209. if (is_object($hookmanager) && (( $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
  1210. {
  1211. $special_code = $object->lines[$i]->special_code;
  1212. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1213. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1214. $action='';
  1215. return $hookmanager->executeHooks('pdf_getlineqty_shipped',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1216. }
  1217. else
  1218. {
  1219. if (empty($hidedetails) || $hidedetails > 1) return $object->lines[$i]->qty_shipped;
  1220. }
  1221. }
  1222. }
  1223. /**
  1224. * Return line keep to ship quantity
  1225. *
  1226. * @param Object $object Object
  1227. * @param int $i Current line number
  1228. * @param Translate $outputlangs Object langs for output
  1229. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1230. * @return void
  1231. */
  1232. function pdf_getlineqty_keeptoship($object,$i,$outputlangs,$hidedetails=0)
  1233. {
  1234. global $hookmanager;
  1235. if ($object->lines[$i]->special_code != 3)
  1236. {
  1237. if (is_object($hookmanager) && (( $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
  1238. {
  1239. $special_code = $object->lines[$i]->special_code;
  1240. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1241. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1242. $action='';
  1243. return $hookmanager->executeHooks('pdf_getlineqty_keeptoship',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1244. }
  1245. else
  1246. {
  1247. if (empty($hidedetails) || $hidedetails > 1) return ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
  1248. }
  1249. }
  1250. }
  1251. /**
  1252. * Return line remise percent
  1253. *
  1254. * @param Object $object Object
  1255. * @param int $i Current line number
  1256. * @param Translate $outputlangs Object langs for output
  1257. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1258. * @return string
  1259. */
  1260. function pdf_getlineremisepercent($object,$i,$outputlangs,$hidedetails=0)
  1261. {
  1262. global $hookmanager;
  1263. include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  1264. if ($object->lines[$i]->special_code != 3)
  1265. {
  1266. if (is_object($hookmanager) && ( ($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code) ) || ! empty($object->lines[$i]->fk_parent_line) ) )
  1267. {
  1268. $special_code = $object->lines[$i]->special_code;
  1269. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1270. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1271. $action='';
  1272. return $hookmanager->executeHooks('pdf_getlineremisepercent',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1273. }
  1274. else
  1275. {
  1276. if (empty($hidedetails) || $hidedetails > 1) return dol_print_reduction($object->lines[$i]->remise_percent,$outputlangs);
  1277. }
  1278. }
  1279. }
  1280. /**
  1281. * Return line total excluding tax
  1282. *
  1283. * @param Object $object Object
  1284. * @param int $i Current line number
  1285. * @param Translate $outputlangs Object langs for output
  1286. * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines)
  1287. * @return string Return total of line excl tax
  1288. */
  1289. function pdf_getlinetotalexcltax($object,$i,$outputlangs,$hidedetails=0)
  1290. {
  1291. global $conf, $hookmanager;
  1292. $sign=1;
  1293. if (isset($object->type) && $object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1;
  1294. if ($object->lines[$i]->special_code == 3)
  1295. {
  1296. return $outputlangs->transnoentities("Option");
  1297. }
  1298. else
  1299. {
  1300. if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
  1301. {
  1302. $special_code = $object->lines[$i]->special_code;
  1303. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1304. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1305. $action='';
  1306. return $hookmanager->executeHooks('pdf_getlinetotalexcltax',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1307. }
  1308. else
  1309. {
  1310. if (empty($hidedetails) || $hidedetails > 1) return price($sign * $object->lines[$i]->total_ht, 0, $outputlangs);
  1311. }
  1312. }
  1313. return '';
  1314. }
  1315. /**
  1316. * Return line total including tax
  1317. *
  1318. * @param Object $object Object
  1319. * @param int $i Current line number
  1320. * @param Translate $outputlangs Object langs for output
  1321. * @param int $hidedetails Hide value (0 = no, 1 = yes, 2 = just special lines)
  1322. * @return string Return total of line incl tax
  1323. */
  1324. function pdf_getlinetotalwithtax($object,$i,$outputlangs,$hidedetails=0)
  1325. {
  1326. global $hookmanager;
  1327. if ($object->lines[$i]->special_code == 3)
  1328. {
  1329. return $outputlangs->transnoentities("Option");
  1330. }
  1331. else
  1332. {
  1333. if (is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
  1334. {
  1335. $special_code = $object->lines[$i]->special_code;
  1336. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1337. $parameters = array('i'=>$i,'outputlangs'=>$outputlangs,'hidedetails'=>$hidedetails,'special_code'=>$special_code);
  1338. $action='';
  1339. return $hookmanager->executeHooks('pdf_getlinetotalwithtax',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1340. }
  1341. else
  1342. {
  1343. if (empty($hidedetails) || $hidedetails > 1) return price(($object->lines[$i]->total_ht) + ($object->lines[$i]->total_ht)*($object->lines[$i]->tva_tx)/100, 0, $outputlangs);
  1344. }
  1345. }
  1346. return '';
  1347. }
  1348. /**
  1349. * Return total quantity of products and/or services
  1350. *
  1351. * @param Object $object Object
  1352. * @param string $type Type
  1353. * @param Translate $outputlangs Object langs for output
  1354. * @return void
  1355. */
  1356. function pdf_getTotalQty($object,$type,$outputlangs)
  1357. {
  1358. global $hookmanager;
  1359. $total=0;
  1360. $nblignes=count($object->lines);
  1361. // Loop on each lines
  1362. for ($i = 0 ; $i < $nblignes ; $i++)
  1363. {
  1364. if ($object->lines[$i]->special_code != 3)
  1365. {
  1366. if ($type=='all')
  1367. {
  1368. $total += $object->lines[$i]->qty;
  1369. }
  1370. else if ($type==9 && is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && ! empty($object->lines[$i]->special_code)) || ! empty($object->lines[$i]->fk_parent_line)))
  1371. {
  1372. $special_code = $object->lines[$i]->special_code;
  1373. if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
  1374. // TODO add hook function
  1375. }
  1376. else if ($type==0 && $object->lines[$i]->product_type == 0)
  1377. {
  1378. $total += $object->lines[$i]->qty;
  1379. }
  1380. else if ($type==1 && $object->lines[$i]->product_type == 1)
  1381. {
  1382. $total += $object->lines[$i]->qty;
  1383. }
  1384. }
  1385. }
  1386. return $total;
  1387. }
  1388. /**
  1389. * Return linked objects
  1390. *
  1391. * @param object $object Object
  1392. * @param Translate $outputlangs Object lang for output
  1393. * @return array Linked objects
  1394. */
  1395. function pdf_getLinkedObjects($object,$outputlangs)
  1396. {
  1397. global $hookmanager;
  1398. $linkedobjects=array();
  1399. $object->fetchObjectLinked();
  1400. foreach($object->linkedObjects as $objecttype => $objects)
  1401. {
  1402. if ($objecttype == 'propal')
  1403. {
  1404. $outputlangs->load('propal');
  1405. $num=count($objects);
  1406. for ($i=0;$i<$num;$i++)
  1407. {
  1408. $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
  1409. $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($objects[$i]->ref);
  1410. $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
  1411. $linkedobjects[$objecttype]['date_value'] = dol_print_date($objects[$i]->date,'day','',$outputlangs);
  1412. }
  1413. }
  1414. else if ($objecttype == 'commande')
  1415. {
  1416. $outputlangs->load('orders');
  1417. $num=count($objects);
  1418. for ($i=0;$i<$num;$i++)
  1419. {
  1420. $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
  1421. $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($objects[$i]->ref) . ($objects[$i]->ref_client ? ' ('.$objects[$i]->ref_client.')' : '');
  1422. $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
  1423. $linkedobjects[$objecttype]['date_value'] = dol_print_date($objects[$i]->date,'day','',$outputlangs);
  1424. }
  1425. }
  1426. else if ($objecttype == 'contrat')
  1427. {
  1428. $outputlangs->load('contracts');
  1429. $num=count($objects);
  1430. for ($i=0;$i<$num;$i++)
  1431. {
  1432. $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
  1433. $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($objects[$i]->ref);
  1434. $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
  1435. $linkedobjects[$objecttype]['date_value'] = dol_print_date($objects[$i]->date_contrat,'day','',$outputlangs);
  1436. }
  1437. }
  1438. }
  1439. // For add external linked objects
  1440. if (is_object($hookmanager))
  1441. {
  1442. $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs'=>$outputlangs);
  1443. $action='';
  1444. $hookmanager->executeHooks('pdf_getLinkedObjects',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  1445. if (! empty($hookmanager->resArray)) $linkedobjects = $hookmanager->resArray;
  1446. }
  1447. return $linkedobjects;
  1448. }
  1449. /**
  1450. * Return dimensions to use for images onto PDF checking that width and height are not higher than
  1451. * maximum (16x32 by default).
  1452. *
  1453. * @param string $realpath Full path to photo file to use
  1454. * @return array Height and width to use to output image (in pdf user unit, so mm)
  1455. */
  1456. function pdf_getSizeForImage($realpath)
  1457. {
  1458. global $conf;
  1459. $maxwidth=(empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH)?20:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH);
  1460. $maxheight=(empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT)?32:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT);
  1461. include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
  1462. $tmp=dol_getImageSize($realpath);
  1463. if ($tmp['height'])
  1464. {
  1465. $width=(int) round($maxheight*$tmp['width']/$tmp['height']); // I try to use maxheight
  1466. if ($width > $maxwidth) // Pb with maxheight, so i use maxwidth
  1467. {
  1468. $width=$maxwidth;
  1469. $height=(int) round($maxwidth*$tmp['height']/$tmp['width']);
  1470. }
  1471. else // No pb with maxheight
  1472. {
  1473. $height=$maxheight;
  1474. }
  1475. }
  1476. return array('width'=>$width,'height'=>$height);
  1477. }