Fiche Produit - Ajout Photo Produit

Re-bonjour,

Sur la modification du pdf_standard.module.php (génération de la fiche produit) j’essaie de rajouter la photo du produit.
Je bloque cependant sur la fonction « liste_photo » de product.class.pdf qui me retourne une erreur :

Le code est très court :

$id_product_photo=$object->rowid;
	$arephoto = false;
	if (! $arephoto)
	{
	$dir = DOL_DATA_ROOT.'/'.$objet->ref;
	      foreach ($id_product_photo->liste_photos($dir,1) as $key => $obj)
	      {
	      $filename=$obj['photo'];
	      $realpath = $dir.$filename;
	      $arephoto = true;
	      }
	}
						
	if ($realpath && $arephoto) $pathphoto=$realpath;

		// Define size of image if we need it
		$imglinesize=array();
		if (! empty($pathphoto)) $imglinesize=pdf_getSizeForImage($pathphoto);

		$posYAfterImage=42;

		// We start with Photo of product
					
		if (isset($imglinesize['width']) && isset($imglinesize['height']))
		{
		$pdf->Image($pathphoto, $tab_top, $tab_top, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300);	// Use 300 dpi

Bonjour :happy:
$object->liste_photos(…) non ?

Pareil,

Le problème je pense c’est que je n’ai rien qui ressort de la variable $id_product_photo qui fait appel au rowid du produit

liste_photos() est une fonction de classe de product
donc de $object et non pas de rowid de l’objet je pense.

1 « J'aime »

D’accord… Même si je n’ai pas tout saisi…

Mais pourtant il est bien appelé comme ca dans la génération PDF ‹ Azur › des propal

$objphoto = new Product($this->db);
$objphoto->fetch($object->lines[$i]->fk_product);
$dir = $conf->product->dir_output.'/'.$midir;
foreach ($objphoto->liste_photos($dir,1) as $key => $obj)

Du coup en utilisant ce code tu as encore une erreur?
moi j’aurai mis un truc genre

...
$objphoto = new Product($this->db);
$objphoto->fetch($object->id);
// ou $objphoto->fetch('', $object->ref);
$dir = $conf->product->dir_output.'/'.$midir;
foreach ($objphoto->liste_photos($dir,1) as $key => $obj)
....

Merci pour tes solutions.
En modifiant un peu le code, plus d’erreur mais l’image ne s’affiche toujours pas…

J’ai encore réduit le code :

//Photo
$objphoto = new Product($this->db);
$objphoto->fetch('', $object->ref);

$dir = $conf->produit->dir_output ."/" .dol_sanitizeFileName($objphoto);
foreach ($objphoto->liste_photos($dir,1) as $key => $obj)
{
	$filename=$obj['photo'];
	$realpath = $dir.$filename;
}

// Define size of image
$imglinesize=array();
if (! empty($realpath)) $imglinesize=pdf_getSizeForImage($realpath);

// We start with Photo of product
if (isset($imglinesize['width']) && isset($imglinesize['height']))
{
	$pdf->Image($realpath, $tab_top, $tab_top, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300);
	$posYAfterImage=$tab_top+$imglinesize['height'];
}

Cela fonctionne avec ce code :

//Contenu
					//Photo
					$objphoto = new Product($this->db);
					$objphoto->fetch($object->ref);
					
					$dir = $conf->produit->dir_output ."/" .dol_sanitizeFileName($object->ref)."/";
					foreach ($objphoto->liste_photos($dir,1) as $key => $obj)
						{
						$filename=$obj['photo'];
						$realpath = $dir.$filename;
						}

					// Define size of image if we need it
					$imglinesize=array();
					if (! empty($realpath)) $imglinesize=pdf_getSizeForImage($realpath);

					$tab_top=42;

					// We start with Photo of product
					
					if (isset($imglinesize['width']) && isset($imglinesize['height']))
					{
						$pdf->Image($realpath, 45, 50, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 800);	// Use 300 dpi
						// $pdf->Image does not increase value return by getY, so we save it manually
						$tab_top=47+$imglinesize['height'];
					}

Bonjour,

Pour InfraSPackPlus qui gère très bien les photos je commence par

include_once DOL_DOCUMENT_ROOT .'/core/lib/files.lib.php'; include_once DOL_DOCUMENT_ROOT .'/core/lib/images.lib.php';

Ensuite attention à l’option cachée !

PRODUCT_USE_OLD_PATH_FOR_PHOTO

Cordialement,
Sylvain Legrand.

Pourquoi, y’a une fonction appelée sur ces fichiers ?

Oui pour PRODUCT_USE_OLD_PATH_FOR_PHOTO
J’ai fait exprès de le retirer parce que cela n’a plus lieu d’être… < v4

Bonjour :happy:
@leboubou111
Peux-tu éditer le sujet de ton topic en y ajoutant au début [RESOLU] stp ?

Oui, mais je compte partager mon fichier modifié… Ca va surement servir à d’autre.
Il serai bien de l’intégrer dans la prochaine version de Dolibarr.

J’ai fait déjà quelques améliorations.

Il me reste à mettre les unités sur le poids, les dimensions, la surface et le volume.
Aussi j’aimerai ajouter une nouvelle page si la description est longue.

1 « J'aime »

Pour terminer mon fichier j’ai besoin d’un dernier coup de main.

Comment faire pour faire passer sur une nouvelle page si la hauteur du bloc dépasse de la page ?

Exemple avec ce code :

// Affiche le libellé
if ($object->label)
{
	$currentY = $pdf->GetY();
	$nexY+=2; // espace de 2mm
	$pdf->writeHTMLCell(...)
	$nexY = $pdf->GetY();
	$nexY+=5; // espace de 5mm
	$currentnewY = $pdf->GetY();
	$height_label=$currentnewY-$currentY;
}
else
{
	$height_label=0;
}

$pdf->AddPage();

Bon j’ai fini mon code…
Juste la fonction AddPage qui ne fonctionne pas… Je pense qu’il n’arrive pas à calculer

if ($nexY+$heightforfooter+$this->height_URL > $this->page_hauteur)

tout simplement parce que la fonction où est la variable $this->height_URL n’a toujours pas été appelée.

Mais pour savoir si l’encadré suivant tiendra sur la page j’ai besoin de connaitre sa hauteur en avance.

Je joins tous le code qui fait 750 lignes.
C’est la première fois que je code. Soyez indulgent svp.

<?php
/* Copyright (C) 2017 	Laurent Destailleur <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * or see http://www.gnu.org/
 */

/**
 *	\file       htdocs/core/modules/product/doc/pdf_standard.modules.php
 *	\ingroup    societe
 *	\brief      File of class to build PDF documents for products/services
 */

require_once DOL_DOCUMENT_ROOT.'/core/modules/product/modules_product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php' ;


/**
 *	Class to build documents using ODF templates generator
 */
class pdf_standard extends ModelePDFProduct
{
    /**
     * @var DoliDb Database handler
     */
    public $db;

	/**
     * @var string model name
     */
    public $name;

	/**
     * @var string model description (short text)
     */
    public $description;

	/**
     * @var string document type
     */
    public $type;

	/**
     * @var array() Minimum version of PHP required by module.
	 * e.g.: PHP ≥ 5.4 = array(5, 4)
     */
	public $phpmin = array(5, 4);

	/**
     * Dolibarr version of the loaded document
     * @public string
     */
	public $version = 'dolibarr';

    /**
     * @var int page_largeur
     */
    public $page_largeur;

    /**
     * @var int page_hauteur
     */
    public $page_hauteur;

    /**
     * @var array format
     */
    public $format;

	/**
     * @var int marge_gauche
     */
	public $marge_gauche;

	/**
     * @var int marge_droite
     */
	public $marge_droite;

	/**
     * @var int marge_haute
     */
	public $marge_haute;

	/**
     * @var int marge_basse
     */
	public $marge_basse;

    /**
	 * Issuer
	 * @var Societe
	 */
	public $emetteur;


	/**
	 *	Constructor
	 *
	 *  @param		DoliDB		$db      Database handler
	 */
	public function __construct($db)
	{
		global $conf,$langs,$mysoc;

		// Load traductions files requiredby by page
		$langs->loadLangs(array("main", "companies"));

		$this->db = $db;
		$this->name = "standard";
		$this->description = $langs->trans("DocumentModelStandardPDF");

		// Dimension page pour format A4
		$this->type = 'pdf';
		$formatarray=pdf_getFormat();
		$this->page_largeur = $formatarray['width'];
		$this->page_hauteur = $formatarray['height'];
		$this->format = array($this->page_largeur,$this->page_hauteur);
		$this->marge_gauche=isset($conf->global->MAIN_PDF_MARGIN_LEFT)?$conf->global->MAIN_PDF_MARGIN_LEFT:10;
		$this->marge_droite=isset($conf->global->MAIN_PDF_MARGIN_RIGHT)?$conf->global->MAIN_PDF_MARGIN_RIGHT:10;
		$this->marge_haute =isset($conf->global->MAIN_PDF_MARGIN_TOP)?$conf->global->MAIN_PDF_MARGIN_TOP:10;
		$this->marge_basse =isset($conf->global->MAIN_PDF_MARGIN_BOTTOM)?$conf->global->MAIN_PDF_MARGIN_BOTTOM:10;

		$this->option_logo = 1;                    // Affiche logo
		$this->option_codeproduitservice = 0;      // Affiche code produit-service
		$this->option_multilang = 1;               // Dispo en plusieurs langues
		$this->option_freetext = 0;				   // Support add of a personalised text

		// Recupere emetteur
		$this->emetteur=$mysoc;
		if (! $this->emetteur->country_code) $this->emetteur->country_code=substr($langs->defaultlang,-2);    // By default if not defined
	}


    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
	/**
	 *	Function to build a document on disk using the generic odt module.
	 *
	 *	@param		Product		$object				Object source to build document
	 *	@param		Translate	$outputlangs		Lang output object
	 * 	@param		string		$srctemplatepath	Full path of source filename for generator using a template file
	 *  @param		int			$hidedetails		Do not show line details
	 *  @param		int			$hidedesc			Do not show desc
	 *  @param		int			$hideref			Do not show ref
	 *	@return		int         					1 if OK, <=0 if KO
	 */
	function write_file($object,$outputlangs,$srctemplatepath,$hidedetails=0,$hidedesc=0,$hideref=0)
	{
        // phpcs:enable
		global $user,$langs,$conf,$mysoc,$db,$hookmanager, $imgsizeh;

		if (! is_object($outputlangs)) $outputlangs=$langs;
		// For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
		if (! empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output='ISO-8859-1';

		// Load traductions files requiredby by page
		$outputlangs->loadLangs(array("main", "dict", "companies", "bills", "products", "orders", "deliveries"));

		if ($conf->produit->dir_output)
		{
		    // Definition of $dir and $file
			if ($object->specimen)
			{
				$dir = $conf->produit->dir_output;
				$file = $dir . "/SPECIMEN.pdf";
			}
			else
			{
				$objectref = dol_sanitizeFileName($object->ref);
				$dir = $conf->produit->dir_output . "/" . $objectref;
				$file = $dir . "/" . $objectref . ".pdf";
			}

			$productFournisseur = new ProductFournisseur($this->db);
			$supplierprices = $productFournisseur->list_product_fournisseur_price($object->id);
			$object->supplierprices = $supplierprices;

			if (! file_exists($dir))
			{
				if (dol_mkdir($dir) < 0)
				{
					$this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
					return -1;
				}
			}

			if (file_exists($dir))
			{
				// Add pdfgeneration hook
				if (! is_object($hookmanager))
				{
					include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
					$hookmanager=new HookManager($this->db);
				}
				$hookmanager->initHooks(array('pdfgeneration'));
				$parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs);
				global $action;
				$reshook=$hookmanager->executeHooks('beforePDFCreation',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks

				// Create pdf instance
				$pdf=pdf_getInstance($this->format);
				$default_font_size = pdf_getPDFFontSize($outputlangs);	// Must be after pdf_getInstance
				$pdf->SetAutoPageBreak(1,0);

				$heightforinfotot = 40;	// Height reserved to output the info and total part
		        $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5);	// Height reserved to output the free text on last page
	            $heightforfooter = $this->marge_basse + 8;	// Height reserved to output the footer (value include bottom margin)
	            if ($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS >0) $heightforfooter+= 6;

                if (class_exists('TCPDF'))
                {
                    $pdf->setPrintHeader(false);
                    $pdf->setPrintFooter(false);
                }
                $pdf->SetFont(pdf_getPDFFont($outputlangs));
                // Set path to the background PDF File
                if (! empty($conf->global->MAIN_ADD_PDF_BACKGROUND))
                {
                    $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
                    $tplidx = $pdf->importPage(1);
                }

				$pdf->Open();
				$pagenb=0;
				$pdf->SetDrawColor(128,128,128);

				$pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
				$pdf->SetSubject($outputlangs->transnoentities("Product"));
				$pdf->SetCreator("Dolibarr ".DOL_VERSION);
				$pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
				if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);

				$pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);   // Left, Top, Right

				// New page
				$pdf->AddPage();
				if (! empty($tplidx)) $pdf->useTemplate($tplidx);
				$pagenb++;
				// entête de page
				$this->_pagehead($pdf, $object, $outputlangs);
				
				// Réserve de hauteur pour le pied de page
				$heightforfooter = $this->marge_basse + 8;	// Height reserved to output the footer (value include bottom margin)
				if ($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS >0) $heightforfooter+= 6;
				
				$pdf->SetFont('','', $default_font_size - 1);
				$pdf->MultiCell(0, 3, '');		// Set interline to 3
				$pdf->SetTextColor(0,0,0);


				// Contenu
				$nexY=40;
				
				if ($nexY+$heightforfooter+$this->height_photo > $this->page_hauteur)
				{
					// New page
					$pdf->AddPage();
					if (! empty($tplidx)) $pdf->useTemplate($tplidx);
					$pagenb++;
					if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
				}
				$this->_photo($pdf,$object,$outputlangs,$nexY);
				$nexY+=$this->height_photo;
				if ($nexY+$heightforfooter+$this->height_label > $this->page_hauteur)
				{
					// New page
					$pdf->AddPage();
					if (! empty($tplidx)) $pdf->useTemplate($tplidx);
					$pagenb++;
					if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
				}
				$this->_label($pdf,$object,$outputlangs,$nexY);
				$nexY=$pdf->GetY();
				if ($nexY+$heightforfooter+$this->height_URL > $this->page_hauteur)
				{
					// New page
					$pdf->AddPage();
					if (! empty($tplidx)) $pdf->useTemplate($tplidx);
					$pagenb++;
					if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
				}
				$this->_URL($pdf,$object,$outputlangs,$nexY+3);
				$nexY=$pdf->GetY();
				if ($nexY+$heightforfooter+$this->height_description > $this->page_hauteur)
				{
					// New page
					$pdf->AddPage();
					if (! empty($tplidx)) $pdf->useTemplate($tplidx);
					$pagenb++;
					if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
				}
				$this->_description($pdf,$object,$outputlangs,$nexY+5);
				$nexY=$pdf->GetY();
				if ($nexY+$heightforfooter+$this->height_infosup > $this->page_hauteur)
				{
					// New page
					$pdf->AddPage();
					if (! empty($tplidx)) $pdf->useTemplate($tplidx);
					$pagenb++;
					if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
				}
				$this->_infosup($pdf,$object,$outputlangs,$nexY+5);
				$nexY=$pdf->GetY();
				if ($nexY+$heightforfooter+$this->height_note > $this->page_hauteur)
				{
					// New page
					$pdf->AddPage();
					if (! empty($tplidx)) $pdf->useTemplate($tplidx);
					$pagenb++;
					if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
				}
				$this->_note($pdf,$object,$outputlangs,$nexY+5);

				// Pied de page
				$this->_pagefoot($pdf,$object,$outputlangs);
				if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();

				$pdf->Close();

				$pdf->Output($file,'F');

				// Add pdfgeneration hook
				$hookmanager->initHooks(array('pdfgeneration'));
				$parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs);
				global $action;
				$reshook=$hookmanager->executeHooks('afterPDFCreation',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks

				if (! empty($conf->global->MAIN_UMASK))
					@chmod($file, octdec($conf->global->MAIN_UMASK));

				$this->result = array('fullpath'=>$file);

				return 1;   // Pas d'erreur
			}
			else
			{
				$this->error=$langs->trans("ErrorCanNotCreateDir",$dir);
				return 0;
			}
		}
		else
		{
			$this->error=$langs->trans("ErrorConstantNotDefined","PRODUCT_OUTPUTDIR");
			return 0;
		}
	}


	/**
	 *  Show photo
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _photo(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size, $conf;

		// Photo
		if ($conf->global->MAIN_GENERATE_FICHE_PRODUCT_WITH_PICTURE == 1)
		{
			$objphoto = new Product($this->db);
			$objphoto->fetch($object->ref);
			
			$dir = $conf->produit->dir_output ."/" .dol_sanitizeFileName($object->ref)."/";
			foreach ($objphoto->liste_photos($dir,1) as $key => $obj)
				{
				$filename=$obj['photo'];
				$realpath = $dir.$filename;
				}
		
			if ($filename)
			{
				$imglimitsizew = $this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10;
				if (! empty ($conf->global->MAIN_GENERATE_FICHE_PRODUCT_MAX_SIZE_PICTURE))
				{
					$imglimitsizeh = $conf->global->MAIN_GENERATE_FICHE_PRODUCT_MAX_SIZE_PICTURE;
				}
				else
				{
					$imglimitsizeh = 110;
				}
				$imgrealsize=getimagesize($realpath);
				$imgsizew=$imgrealsize[0]/3.77953;
				$imgsizeh=$imgrealsize[1]/3.77953;
				if ($imgsizew>$imglimitsizew) $imgsizew=$imglimitsizew ;
				if ($imgsizeh>$imglimitsizeh) $imgsizeh=$imglimitsizeh ;
			
				// We start with Photo of product
				$pdf->Image($realpath, $this->marge_gauche, 44, 0, $imgsizeh, '', '', 'M', false, '', 'C') ;
				// $pdf->Image does not increase value return by getY, so we save it manually
			
				$nexY=52+$imgsizeh;
				$this->height_photo=$imgsizeh+12;
			}
		}
		else
		{
			$this->height_photo=0;
		}
	}


	/**
	 *  Show label
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _label(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size;

	    $default_font_size = pdf_getPDFFontSize($outputlangs);

		// Affiche le libellé
		if ($object->label)
		{
			$currentY = $pdf->GetY();
			$nexY+=2; // espace de 2mm
			$pdf->SetFont('','B', $default_font_size+7);
			$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-$this->marge_droite, 4, $this->marge_gauche, $nexY,
			dol_htmlentitiesbr($object->label), $border=0, $ln=1, $fill=0, $reseth=true, $align='C', $autopadding=false);
			$pdf->SetFont('', '', $default_font_size);
			$nexY = $pdf->GetY();
			$nexY+=5; // espace de 5mm
			$currentnewY = $pdf->GetY();
			$this->height_label=$currentnewY-$currentY;
		}
		else
		{
			$this->height_label=0;
		}
	}


	/**
	 *  Show URL
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _URL(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size;

		// Affiche le lien URL si défini
		if ($object->url) 
		{
			$currentY = $pdf->GetY();
			$nexY+=4; // espace de 4mm
			
			$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-10-$this->marge_droite-10, 4, $this->marge_gauche+10, $nexY, "Lien information produit : ", $border=0, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
			$nexY = $pdf->GetY();
			$pdf->SetXY($this->marge_gauche+10,$nexY);
			$pdf->SetFont('', '', $default_font_size-1);
			$pdf->Write(5, dol_htmlentitiesbr($object->url), dol_htmlentitiesbr($object->url), false, 'L', true);
			//$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-10-$this->marge_droite-10, 4, $this->marge_gauche+10, $nexY, dol_htmlentitiesbr($object->url), $border=0, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
			$pdf->SetFont('', '', $default_font_size);
			$nexY = $pdf->GetY();
			$nexY+=5; // espace de 5mm
			$currentnewY = $pdf->GetY();
			$this->height_URL=$currentnewY-$currentY;
		}
		else
		{
			$this->height_URL=0;
		}
	}


	/**
	 *  Show description
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _description(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size;

		// Affiche la Description
		if ($object->description)
		{	
			$currentY = $pdf->GetY();
			$nexY+=4; // espace de 4mm
			
			$pdf->SetFont('', 'B', $default_font_size);
			$pdf->SetFillColor(225, 225, 225);
			$pdf->SetXY($this->marge_gauche,$nexY+1);
			$pdf->RoundedRect($this->marge_gauche,$nexY, $this->page_largeur-$this->marge_droite-$this->marge_gauche, 6, 2, '1234', 'DF');
			$pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->marge_gauche, 5, "Description", 0, 'C', false);
			$nexY = $pdf->GetY();
			
			$nexY+=5; // espace de 5mm
			
			$pdf->SetFont('','', $default_font_size);
			$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-10-$this->marge_droite-10, 4, $this->marge_gauche+10, $nexY,
			dol_htmlentitiesbr($object->description), $border=0, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
			$nexY = $pdf->GetY();
			$nexY+=5; // espace de 5mm
			$currentnewY = $pdf->GetY();
			$this->height_description=$currentnewY-$currentY;
		}
		else
		{
			$this->height_description=0;
		}
	}


	/**
	 *  Show informations supplémentaires
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _infosup(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size, $langs;

		// Affichage des informations supplémentaires :
		if ($object->weight || $object->Length || $object->Width || $object->Height || $object->surface || $object->volume)
		{
			$currentY = $pdf->GetY();
			$nexY+=6; // espace de 6mm
			
			$pdf->SetFont('', 'B', $default_font_size);
			$pdf->SetFillColor(225, 225, 225);
			$pdf->SetXY($this->marge_gauche,$nexY+1);
			$pdf->RoundedRect($this->marge_gauche,$nexY, $this->page_largeur-$this->marge_droite-$this->marge_gauche, 6, 2, '1234', 'DF');
			$pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->marge_gauche, 5, "Informations Supplémentaires", 0, 'C', false);
			$pdf->SetFont('', '', $default_font_size);
			$nexY = $pdf->GetY(); 
			
			$nexY+=5; // espace de 5mm
			
			// Affiche le poids si défini
			if ($object->weight)
			{
				$pdf->writeHTMLCell(70, 4, $this->marge_gauche+10, $nexY,
				$langs->trans("Weight").' : ', $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10-70, 4, $this->marge_gauche+10+70, $nexY,
				dol_htmlentitiesbr($object->weight) .' ' .measuring_units_string($object->weight_units, $measuring_style='weight'), $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$nexY = $pdf->GetY();
			}
			// Affiche les dimentions si défini
			if ($object->length || $object->Width || $object->Height)
			{						
				$pdf->writeHTMLCell(70, 4, $this->marge_gauche+10, $nexY,
				$langs->trans("Length").' * '.$langs->trans("Width").' * '.$langs->trans("Height").' : ', $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10-70, 4, $this->marge_gauche+10+70, $nexY,
				($object->length != ''?$object->length:'?') .' ' .measuring_units_string($object->length_units, $measuring_style='size').' * '.($object->width != ''?$object->width:'?') .' ' .measuring_units_string($object->width_units, $measuring_style='size').' * '.($object->height != ''?$object->height:'?') .' ' .measuring_units_string($object->height_units, $measuring_style='size'), $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$nexY = $pdf->GetY();
			}
			// Affiche la surface si défini
			if ($object->surface)
			{
				$pdf->writeHTMLCell(70, 4, $this->marge_gauche+10, $nexY,
				$langs->trans("Area").' : ', $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10-70, 4, $this->marge_gauche+10+70, $nexY,
				dol_htmlentitiesbr($object->surface) .' ' .measuring_units_string($object->surface_units, $measuring_style='surface'), $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$nexY = $pdf->GetY();
			}
			// Affiche le volume si défini
			if ($object->volume)
			{
				$pdf->writeHTMLCell(70, 4, $this->marge_gauche+10, $nexY,
				$langs->trans("Volume").' : ', $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10-70, 4, $this->marge_gauche+10+70, $nexY,
				dol_htmlentitiesbr($object->volume) .' ' .measuring_units_string($object->volume_units, $measuring_style='volume'), $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$nexY = $pdf->GetY();
			}
			$nexY+=5; // espace de 5mm
			$currentnewY = $pdf->GetY();
			$this->height_infosup=$currentnewY-$currentY;
		}
		else
		{
			$this->height_infosup=0;
		}
	}


	/**
	 *  Show public note
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _note(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size;

		//Affichage des notes public
		// TODO There is no public note on product yet (Juste on GUI --> string on product table DB already exists)
		$notetoshow=empty($object->note_public)?'':$object->note_public;
		if ($notetoshow)
		{
			$currentY = $pdf->GetY();
			$nexY+=9; // espace de 6mm (le roundedrect commence à Y-3)

			$substitutionarray=pdf_getSubstitutionArray($outputlangs, null, $object);
			complete_substitutions_array($substitutionarray, $outputlangs, $object);
			$notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);

			$pdf->SetFont('','', $default_font_size - 1);
			$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-10-$this->marge_droite-10, 3, $this->marge_gauche+2, $nexY, dol_htmlentitiesbr($notetoshow), 0, 1);
			$currentnewY = $pdf->GetY();
			$height_rectnote=$currentnewY-$nexY;
			
			// Rect prend une longueur en 3eme param
			$pdf->SetDrawColor(192,192,192);
			$pdf->RoundedRect($this->marge_gauche, $nexY-3, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $height_note+6, 2, '1234');
			
			
			$nexY = $pdf->GetY();
			$nexY+=5; // espace de 5mm
			$currentnewY = $pdf->GetY();
			$this->height_note=$currentnewY-$currentY;					
		}
		else
		{
			$this->height_note=0;
		}
	}


	/**
	 *  Show top header of page.
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	string		$titlekey		Translation key to show as title of document
	 *  @return	void
	 */
	function _pagehead(&$pdf, $object, $outputlangs, $titlekey="")
	{
	    global $conf,$langs,$hookmanager;

	    // Load traductions files requiredby by page
		$outputlangs->loadLangs(array("main", "propal", "companies", "bills", "orders"));

	    $default_font_size = pdf_getPDFFontSize($outputlangs);

	    if ($object->type == 1) $titlekey='ServiceSheet';
	    else $titlekey='ProductSheet';

	    pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);

	    // Show Draft Watermark
	    if($object->statut==0 && (! empty($conf->global->COMMANDE_DRAFT_WATERMARK)) )
	    {
	        pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',$conf->global->COMMANDE_DRAFT_WATERMARK);
	    }

	    $pdf->SetTextColor(0,0,60);
	    $pdf->SetFont('','B', $default_font_size + 3);

	    $posy=$this->marge_haute;
	    $posx=$this->page_largeur-$this->marge_droite-100;
	    $pdf->SetXY($this->marge_gauche,$posy);

	    // Logo
	    $logo=$conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
	    if ($this->emetteur->logo)
	    {
	        if (is_readable($logo))
	        {
	            $height=pdf_getHeightForLogo($logo);
	            $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height);	// width=0 (auto)
	        }
	        else
	        {
	            $pdf->SetTextColor(200,0,0);
	            $pdf->SetFont('','B', $default_font_size -2);
	            $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound",$logo), 0, 'L');
	            $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
	        }
	    }
	    else
	    {
	        $text=$this->emetteur->name;
	        $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L');
	    }

	    $pdf->SetFont('','B', $default_font_size + 3);
	    $pdf->SetXY($posx,$posy);
	    $pdf->SetTextColor(0,0,60);
	    $title=$outputlangs->transnoentities($titlekey);
	    $pdf->MultiCell(100, 3, $title, '', 'R');

	    $pdf->SetFont('','B',$default_font_size);

	    $posy+=6;
	    $pdf->SetXY($posx,$posy);
	    $pdf->SetTextColor(0,0,60);
	    $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : " . $outputlangs->convToOutputCharset($object->ref), '', 'R');

	    // Show list of linked objects
	    $posy+=3;
	    $pdf->SetFont('','', $default_font_size - 1);
	    $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
	    $pdf->SetTextColor(0,0,0);

		$posyAfterPagehead=$pdf->GetY()+$height+$this->marge_haute;
	}

	/**
	 *   	Show footer of page. Need this->emetteur object
	 *
	 *   	@param	TCPDF		$pdf     			PDF
	 * 		@param	Object		$object				Object to show
	 *      @param	Translate	$outputlangs		Object lang for output
	 *      @param	int			$hidefreetext		1=Hide free text
	 *      @return	int								Return height of bottom margin including footer text
	 */
	function _pagefoot(&$pdf,$object,$outputlangs,$hidefreetext=0)
	{
	    global $conf;
	    $showdetails=$conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS;
	    return pdf_pagefoot($pdf,$outputlangs,'PRODUCT_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,$showdetails,$hidefreetext);
	}
}

Pour que le code fonctionne il faut rajouter deux options

MAIN_GENERATE_FICHE_PRODUCT_WITH_PICTURE -> 1 = Génération Fiche Produit - Ajoute l’image du produit
MAIN_GENERATE_FICHE_PRODUCT_MAX_SIZE_PICTURE -> Valeur = Génération Fiche Produit - Taille limite de l’image du produit en mm (110 par défaut)

Je pense avoir trouvé en utilisant la fonction pdfGetHeightForHtmlContent et/ou getStringHeight
Ca va être long à intégrer…

Code terminé :

Voici la nouvelle page Fiche Produit

Modifications apportées :

[ul]
[li]Plusieurs améliorations esthétiques[/li]
[li] Ajout cadre « Description’, 'Informations Supplémentaires » et « Notes »[/li]
[li] Encadrement des informations supplémentaires (poids, taille, etc…)[/li]
[li] Modification taille carractère[/li]
[li]Ajout de la première photo (identique au modèle « Azur ») au début de la fiche (et centré)[/li]
[li] Si renseigné MAIN_GENERATE_FICHE_PRODUCT_WITH_PICTURE dans Configuration->Divers[/li]
[li] On peut définir la hauteur maximum de l’image MAIN_GENERATE_FICHE_PRODUCT_MAX_HEIGHT_SIZE_PICTURE en mm (par défaut : 110mm)[/li]
[li] La largeur s’effectue automatiquement[/li]
[li]Ajout du lien URL si renseigné[/li]
[li]Ajout des unités (Kg, cm, m², etc…)[/li]
[li]Ajout des notes publiques (quand sera dispo sur prochaine version)[/li]
[li]Les informations ne s’affichent que si renseignées sur la fiche produit[/li]
[li]Saut de page automatique en fonction de la hauteur de l’élément à afficher[/li]

J’en ai profité pour supprimer tout le code qui ne servait à rien.

Fonctionne sur la version Dolibarr 9.0.1.
Pas testé sur les versions antérieurs mais devrait fonctionner.

<?php
/* Copyright (C) 2017 	Laurent Destailleur <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * or see http://www.gnu.org/
 */

/**
 *	\file       htdocs/core/modules/product/doc/pdf_standard.modules.php
 *	\ingroup    societe
 *	\brief      File of class to build PDF documents for products/services
 */

require_once DOL_DOCUMENT_ROOT.'/core/modules/product/modules_product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php' ;


/**
 *	Class to build documents using ODF templates generator
 */
class pdf_standard extends ModelePDFProduct
{
    /**
     * @var DoliDb Database handler
     */
    public $db;

	/**
     * @var string model name
     */
    public $name;

	/**
     * @var string model description (short text)
     */
    public $description;

	/**
     * @var string document type
     */
    public $type;

	/**
     * @var array() Minimum version of PHP required by module.
	 * e.g.: PHP ≥ 5.4 = array(5, 4)
     */
	public $phpmin = array(5, 4);

	/**
     * Dolibarr version of the loaded document
     * @public string
     */
	public $version = 'dolibarr';

    /**
     * @var int page_largeur
     */
    public $page_largeur;

    /**
     * @var int page_hauteur
     */
    public $page_hauteur;

    /**
     * @var array format
     */
    public $format;

	/**
     * @var int marge_gauche
     */
	public $marge_gauche;

	/**
     * @var int marge_droite
     */
	public $marge_droite;

	/**
     * @var int marge_haute
     */
	public $marge_haute;

	/**
     * @var int marge_basse
     */
	public $marge_basse;

    /**
	 * Issuer
	 * @var Societe
	 */
	public $emetteur;


	/**
	 *	Constructor
	 *
	 *  @param		DoliDB		$db      Database handler
	 */
	public function __construct($db)
	{
		global $conf,$langs,$mysoc;

		// Load traductions files requiredby by page
		$langs->loadLangs(array("main", "companies"));

		$this->db = $db;
		$this->name = "standard";
		$this->description = $langs->trans("DocumentModelStandardPDF");

		// Dimension page pour format A4
		$this->type = 'pdf';
		$formatarray=pdf_getFormat();
		$this->page_largeur = $formatarray['width'];
		$this->page_hauteur = $formatarray['height'];
		$this->format = array($this->page_largeur,$this->page_hauteur);
		$this->marge_gauche=isset($conf->global->MAIN_PDF_MARGIN_LEFT)?$conf->global->MAIN_PDF_MARGIN_LEFT:10;
		$this->marge_droite=isset($conf->global->MAIN_PDF_MARGIN_RIGHT)?$conf->global->MAIN_PDF_MARGIN_RIGHT:10;
		$this->marge_haute =isset($conf->global->MAIN_PDF_MARGIN_TOP)?$conf->global->MAIN_PDF_MARGIN_TOP:10;
		$this->marge_basse =isset($conf->global->MAIN_PDF_MARGIN_BOTTOM)?$conf->global->MAIN_PDF_MARGIN_BOTTOM:10;

		$this->option_logo = 1;                    // Affiche logo
		$this->option_codeproduitservice = 0;      // Affiche code produit-service
		$this->option_multilang = 1;               // Dispo en plusieurs langues
		$this->option_freetext = 0;				   // Support add of a personalised text

		// Recupere emetteur
		$this->emetteur=$mysoc;
		if (! $this->emetteur->country_code) $this->emetteur->country_code=substr($langs->defaultlang,-2);    // By default if not defined
	}


    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
	/**
	 *	Function to build a document on disk using the generic odt module.
	 *
	 *	@param		Product		$object				Object source to build document
	 *	@param		Translate	$outputlangs		Lang output object
	 * 	@param		string		$srctemplatepath	Full path of source filename for generator using a template file
	 *  @param		int			$hidedetails		Do not show line details
	 *  @param		int			$hidedesc			Do not show desc
	 *  @param		int			$hideref			Do not show ref
	 *	@return		int         					1 if OK, <=0 if KO
	 */
	function write_file($object,$outputlangs,$srctemplatepath,$hidedetails=0,$hidedesc=0,$hideref=0)
	{
        // phpcs:enable
		global $user,$langs,$conf,$mysoc,$db,$hookmanager, $imgsizeh;

		if (! is_object($outputlangs)) $outputlangs=$langs;
		// For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
		if (! empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output='ISO-8859-1';

		// Load traductions files requiredby by page
		$outputlangs->loadLangs(array("main", "dict", "companies", "bills", "products", "orders", "deliveries"));

		if ($conf->produit->dir_output)
		{
		    // Definition of $dir and $file
			if ($object->specimen)
			{
				$dir = $conf->produit->dir_output;
				$file = $dir . "/SPECIMEN.pdf";
			}
			else
			{
				$objectref = dol_sanitizeFileName($object->ref);
				$dir = $conf->produit->dir_output . "/" . $objectref;
				$file = $dir . "/" . $objectref . ".pdf";
			}

			$productFournisseur = new ProductFournisseur($this->db);
			$supplierprices = $productFournisseur->list_product_fournisseur_price($object->id);
			$object->supplierprices = $supplierprices;

			if (! file_exists($dir))
			{
				if (dol_mkdir($dir) < 0)
				{
					$this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
					return -1;
				}
			}

			if (file_exists($dir))
			{
				// Add pdfgeneration hook
				if (! is_object($hookmanager))
				{
					include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
					$hookmanager=new HookManager($this->db);
				}
				$hookmanager->initHooks(array('pdfgeneration'));
				$parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs);
				global $action;
				$reshook=$hookmanager->executeHooks('beforePDFCreation',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks

				// Create pdf instance
				$pdf=pdf_getInstance($this->format);
				$default_font_size = pdf_getPDFFontSize($outputlangs);	// Must be after pdf_getInstance
				$pdf->SetAutoPageBreak(1,0);

				$heightforinfotot = 40;	// Height reserved to output the info and total part
		        $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5);	// Height reserved to output the free text on last page
	            $heightforfooter = $this->marge_basse + 8;	// Height reserved to output the footer (value include bottom margin)
	            if ($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS >0) $heightforfooter+= 6;

                if (class_exists('TCPDF'))
                {
                    $pdf->setPrintHeader(false);
                    $pdf->setPrintFooter(false);
                }
                $pdf->SetFont(pdf_getPDFFont($outputlangs));
                // Set path to the background PDF File
                if (! empty($conf->global->MAIN_ADD_PDF_BACKGROUND))
                {
                    $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
                    $tplidx = $pdf->importPage(1);
                }

				$pdf->Open();
				$pagenb=0;
				$pdf->SetDrawColor(128,128,128);

				$pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
				$pdf->SetSubject($outputlangs->transnoentities("Product"));
				$pdf->SetCreator("Dolibarr ".DOL_VERSION);
				$pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
				if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);

				$pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);   // Left, Top, Right

				// New page
				$pdf->AddPage();
				if (! empty($tplidx)) $pdf->useTemplate($tplidx);
				$pagenb++;
				// entête de page
				$this->_pagehead($pdf, $object, $outputlangs);
				
				// Réserve de hauteur pour le pied de page
				$heightforfooter = $this->marge_basse + 8;	// Height reserved to output the footer (value include bottom margin)
				if ($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS >0) $heightforfooter+= 6;
				
				$pdf->SetFont('','', $default_font_size - 1);
				$pdf->MultiCell(0, 3, '');		// Set interline to 3
				$pdf->SetTextColor(0,0,0);


				// Contenu
				$nexY=40;
				
				// Affiche la photo si présente et si les options sont présentes dans $conf->global->MAIN_GENERATE_FICHE_PRODUCT_WITH_PICTURE
				if ($conf->global->MAIN_GENERATE_FICHE_PRODUCT_WITH_PICTURE ==1)
				{	
					$this->_photo($pdf,$object,$outputlangs,$nexY);
				}
				else
				{
					$this->height_photo=0;
				}
				
				$nexY+=$this->height_photo;

				// Affiche Libellé si présent
				if ($object->label)
				{	
					if ($nexY+$heightforfooter+$this->pdfPersoGetHeightForHtmlContent($pdf,dol_htmlentitiesbr($object->label), 1, 'UTF-8', 0)+15 > $this->page_hauteur)
					{
						// Nouvelle page si dépasse
						// Pied de page
						$this->_pagefoot($pdf,$object,$outputlangs);
						if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();
						$pdf->AddPage();
						if (! empty($tplidx)) $pdf->useTemplate($tplidx);
						$pagenb++;
						if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
						$nexY=32;
					}
					$this->_label($pdf,$object,$outputlangs,$nexY+5);
					$nexY=$pdf->GetY();
				}

				// Affiche URL si présente
				if ($object->url)
				{
					if ($nexY+$heightforfooter+$this->pdfPersoGetHeightForHtmlContent($pdf, "Lien information produit : ", 1, 'UTF-8', 0)+$this->pdfPersoGetHeightForHtmlContent($pdf,dol_htmlentitiesbr($object->url))+5 > $this->page_hauteur)
					{
						// Nouvelle page si dépasse
						// Pied de page
						$this->_pagefoot($pdf,$object,$outputlangs);
						if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();
						$pdf->AddPage();
						if (! empty($tplidx)) $pdf->useTemplate($tplidx);
						$pagenb++;
						if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
						$nexY=32;
					}
					$this->_URL($pdf,$object,$outputlangs,$nexY+10);
					$nexY=$pdf->GetY();
				}
				
				// Affiche description si présente
				if ($object->description)
				{	
					if ($nexY+$heightforfooter+$this->pdfPersoGetHeightForHtmlContent($pdf,dol_htmlentitiesbr($object->description), 1, 'UTF-8', 0)+25 > $this->page_hauteur)
					{
						// Nouvelle page si dépasse
						// Pied de page
						$this->_pagefoot($pdf,$object,$outputlangs);
						if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();
						$pdf->AddPage();
						if (! empty($tplidx)) $pdf->useTemplate($tplidx);
						$pagenb++;
						if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
						$nexY=32;
					}
					$this->_description($pdf,$object,$outputlangs,$nexY+10);
					$nexY=$pdf->GetY();
				}
				
				// Affiche Informations Supplémentaires si présentes
				if ($object->weight || $object->Length || $object->Width || $object->Height || $object->surface || $object->volume)
				{
					if ($nexY+$heightforfooter+($this->pdfPersoGetHeightForHtmlContent($pdf,$langs->trans("Weight"), 1, 'UTF-8', 0)*4)+25 > $this->page_hauteur)
					{
						// Nouvelle page si dépasse
						// Pied de page
						$this->_pagefoot($pdf,$object,$outputlangs);
						if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();
						$pdf->AddPage();
						if (! empty($tplidx)) $pdf->useTemplate($tplidx);
						$pagenb++;
						if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
						$nexY=32;
					}
					$this->_infosup($pdf,$object,$outputlangs,$nexY+10);
					$nexY=$pdf->GetY();
				}
				
				// Affiche Notes Publiques si présentes
				if ($object->note_public)
				{	
					if ($nexY+$heightforfooter+$this->pdfPersoGetHeightForHtmlContent($pdf,dol_htmlentitiesbr($object->note_public), 1, 'UTF-8', 0)+25 > $this->page_hauteur)
					{
						// Nouvelle page si dépasse
						// Pied de page
						$this->_pagefoot($pdf,$object,$outputlangs);
						if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();
						$pdf->AddPage();
						if (! empty($tplidx)) $pdf->useTemplate($tplidx);
						$pagenb++;
						if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, $outputlangs);
						$nexY=32;
					}
					$this->_note($pdf,$object,$outputlangs,$nexY+10);
				}
				// Pied de page
				$this->_pagefoot($pdf,$object,$outputlangs);
				if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages();

				$pdf->Close();

				$pdf->Output($file,'F');

				// Add pdfgeneration hook
				$hookmanager->initHooks(array('pdfgeneration'));
				$parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs);
				global $action;
				$reshook=$hookmanager->executeHooks('afterPDFCreation',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks

				if (! empty($conf->global->MAIN_UMASK))
					@chmod($file, octdec($conf->global->MAIN_UMASK));

				$this->result = array('fullpath'=>$file);

				return 1;   // Pas d'erreur
			}
			else
			{
				$this->error=$langs->trans("ErrorCanNotCreateDir",$dir);
				return 0;
			}
		}
		else
		{
			$this->error=$langs->trans("ErrorConstantNotDefined","PRODUCT_OUTPUTDIR");
			return 0;
		}
	}


	/**
	 *  Show photo
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _photo(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size, $conf;

		// Photo
		$objphoto = new Product($this->db);
		$objphoto->fetch($object->ref);
		
		$dir = $conf->produit->dir_output ."/" .dol_sanitizeFileName($object->ref)."/";
		foreach ($objphoto->liste_photos($dir,1) as $key => $obj)
			{
			$filename=$obj['photo'];
			$realpath = $dir.$filename;
			}
	
		if ($filename)
		{
			$imglimitsizew = $this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10;
			if (! empty ($conf->global->MAIN_GENERATE_FICHE_PRODUCT_MAX_HEIGHT_SIZE_PICTURE))
			{
				$imglimitsizeh = $conf->global->MAIN_GENERATE_FICHE_PRODUCT_MAX_HEIGHT_SIZE_PICTURE;
			}
			else
			{
				$imglimitsizeh = 110;
			}
			$imgrealsize=getimagesize($realpath);
			$imgsizew=$imgrealsize[0]/3.77953;
			$imgsizeh=$imgrealsize[1]/3.77953;
			if ($imgsizew>$imglimitsizew) $imgsizew=$imglimitsizew ;
			if ($imgsizeh>$imglimitsizeh) $imgsizeh=$imglimitsizeh ;
		
			// We start with Photo of product
			$pdf->Image($realpath, $this->marge_gauche, $nexY, 0, $imgsizeh, '', '', 'M', false, '', 'C') ;
			// $pdf->Image does not increase value return by getY, so we save it manually
		
			$this->height_photo=$imgsizeh+5;
		}
	}


	/**
	 *  Show label
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _label(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size;

	    $default_font_size = pdf_getPDFFontSize($outputlangs);

		// Affiche le libellé
		if ($object->label)
		{
			$pdf->SetFont('','B', $default_font_size+7);
			$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-$this->marge_droite, 4, $this->marge_gauche, $nexY,
			dol_htmlentitiesbr($object->label), $border=0, $ln=1, $fill=0, $reseth=true, $align='C', $autopadding=false);
			$pdf->SetFont('', '', $default_font_size);
		}
	}


	/**
	 *  Show URL
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _URL(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size;

		// Affiche le lien URL si défini
		if ($object->url) 
		{
			$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-10-$this->marge_droite-10, 4, $this->marge_gauche+10, $nexY, "Lien information produit : ", $border=0, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
			$nexY = $pdf->GetY();
			$pdf->SetXY($this->marge_gauche+10,$nexY);
			$pdf->SetFont('', '', $default_font_size-1);
			$pdf->Write(5, dol_htmlentitiesbr($object->url), dol_htmlentitiesbr($object->url), false, 'L', true);
			//$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-10-$this->marge_droite-10, 4, $this->marge_gauche+10, $nexY, dol_htmlentitiesbr($object->url), $border=0, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
			$pdf->SetFont('', '', $default_font_size);
		}
	}


	/**
	 *  Show description
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _description(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size;

		// Affiche la Description
		if ($object->description)
		{	
			$pdf->SetFont('', 'B', $default_font_size+2);
			$pdf->SetFillColor(225, 225, 225);
			$pdf->SetXY($this->marge_gauche,$nexY+1);
			$pdf->RoundedRect($this->marge_gauche,$nexY, $this->page_largeur-$this->marge_droite-$this->marge_gauche, 7, 2, '1234', 'DF');
			$pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->marge_gauche, 5, "Description", 0, 'C', false);
			$nexY = $pdf->GetY()+5; // espace de 5mm
			
			$pdf->SetFont('','', $default_font_size);
			$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-10-$this->marge_droite-10, 4, $this->marge_gauche+10, $nexY,
			dol_htmlentitiesbr($object->description), $border=0, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
		}
	}


	/**
	 *  Show informations supplémentaires
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _infosup(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size, $langs;

		// Affichage des informations supplémentaires :
		if ($object->weight || $object->Length || $object->Width || $object->Height || $object->surface || $object->volume)
		{
			$pdf->SetFont('', 'B', $default_font_size);
			$pdf->SetFillColor(225, 225, 225);
			$pdf->SetXY($this->marge_gauche,$nexY+1);
			$pdf->RoundedRect($this->marge_gauche,$nexY, $this->page_largeur-$this->marge_droite-$this->marge_gauche, 6, 2, '1234', 'DF');
			$pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->marge_gauche, 5, "Informations Supplémentaires", 0, 'C', false);
			$pdf->SetFont('', '', $default_font_size);
			$nexY = $pdf->GetY()+5;  // espace de 5mm
			
			// Affiche le poids si défini
			if ($object->weight)
			{
				$pdf->writeHTMLCell(70, 4, $this->marge_gauche+10, $nexY,
				$langs->trans("Weight").' : ', $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10-70, 4, $this->marge_gauche+10+70, $nexY,
				dol_htmlentitiesbr($object->weight) .' ' .measuring_units_string($object->weight_units, $measuring_style='weight'), $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$nexY = $pdf->GetY();
			}
			// Affiche les dimentions si défini
			if ($object->length || $object->Width || $object->Height)
			{						
				$pdf->writeHTMLCell(70, 4, $this->marge_gauche+10, $nexY,
				$langs->trans("Length").' * '.$langs->trans("Width").' * '.$langs->trans("Height").' : ', $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10-70, 4, $this->marge_gauche+10+70, $nexY,
				($object->length != ''?$object->length:'?') .' ' .measuring_units_string($object->length_units, $measuring_style='size').' * '.($object->width != ''?$object->width:'?') .' ' .measuring_units_string($object->width_units, $measuring_style='size').' * '.($object->height != ''?$object->height:'?') .' ' .measuring_units_string($object->height_units, $measuring_style='size'), $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$nexY = $pdf->GetY();
			}
			// Affiche la surface si défini
			if ($object->surface)
			{
				$pdf->writeHTMLCell(70, 4, $this->marge_gauche+10, $nexY,
				$langs->trans("Area").' : ', $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10-70, 4, $this->marge_gauche+10+70, $nexY,
				dol_htmlentitiesbr($object->surface) .' ' .measuring_units_string($object->surface_units, $measuring_style='surface'), $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$nexY = $pdf->GetY();
			}
			// Affiche le volume si défini
			if ($object->volume)
			{
				$pdf->writeHTMLCell(70, 4, $this->marge_gauche+10, $nexY,
				$langs->trans("Volume").' : ', $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10-70, 4, $this->marge_gauche+10+70, $nexY,
				dol_htmlentitiesbr($object->volume) .' ' .measuring_units_string($object->volume_units, $measuring_style='volume'), $border=1, $ln=1, $fill=0, $reseth=true, $align='L', $autopadding=false);
				$nexY = $pdf->GetY();
			}
		}
	}


	/**
	 *  Show public note
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	int			$nexY			Position Y to start
	 *  @return	void
	 */
	function _note(&$pdf, $object, $outputlangs, $nexY)
	{
	    global $default_font_size;

		// Affichage des notes public
		// There is no public note on product yet (Juste on GUI --> string on product table DB already exists)
		if ($object->note_public)
		{
			$pdf->SetFont('', 'B', $default_font_size);
			$pdf->SetFillColor(225, 225, 225);
			$pdf->SetXY($this->marge_gauche,$nexY+1);
			$pdf->RoundedRect($this->marge_gauche, $nexY-3, $this->page_largeur-$this->marge_gauche-$this->marge_droite, 6, 2, '1234', 'DF');
			$pdf->MultiCell($this->page_largeur-$this->marge_gauche-$this->marge_droite,5,"Notes", 0, 'C', false);
			$pdf->SetFont('', '', $default_font_size);
			$nexY = $pdf->GetY()+5;  // espace de 5mm
			
			$pdf->SetFont('','', $default_font_size - 1);
			$pdf->writeHTMLCell($this->page_largeur-$this->marge_gauche-10-$this->marge_droite-10, 4, $this->marge_gauche+2, $nexY, dol_htmlentitiesbr($object->note_public), 0, 1);
		}
	}


	/**
	 *  Show top header of page.
	 *
	 *  @param	TCPDF		$pdf     		Object PDF
	 *  @param  Object		$object     	Object to show
	 *  @param  Translate	$outputlangs	Object lang for output
	 *  @param	string		$titlekey		Translation key to show as title of document
	 *  @return	void
	 */
	function _pagehead(&$pdf, $object, $outputlangs, $titlekey="")
	{
	    global $conf,$langs,$hookmanager;

	    // Load traductions files requiredby by page
		$outputlangs->loadLangs(array("main", "propal", "companies", "bills", "orders"));

	    $default_font_size = pdf_getPDFFontSize($outputlangs);

	    if ($object->type == 1) $titlekey='ServiceSheet';
	    else $titlekey='ProductSheet';

	    pdf_pagehead($pdf,$outputlangs,$this->page_hauteur);

	    // Show Draft Watermark
	    if($object->statut==0 && (! empty($conf->global->COMMANDE_DRAFT_WATERMARK)) )
	    {
	        pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',$conf->global->COMMANDE_DRAFT_WATERMARK);
	    }

	    $pdf->SetTextColor(0,0,60);
	    $pdf->SetFont('','B', $default_font_size + 3);

	    $posy=$this->marge_haute;
	    $posx=$this->page_largeur-$this->marge_droite-100;
	    $pdf->SetXY($this->marge_gauche,$posy);

	    // Logo
	    $logo=$conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
	    if ($this->emetteur->logo)
	    {
	        if (is_readable($logo))
	        {
	            $height=pdf_getHeightForLogo($logo);
	            $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height);	// width=0 (auto)
	        }
	        else
	        {
	            $pdf->SetTextColor(200,0,0);
	            $pdf->SetFont('','B', $default_font_size -2);
	            $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound",$logo), 0, 'L');
	            $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
	        }
	    }
	    else
	    {
	        $text=$this->emetteur->name;
	        $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L');
	    }

	    $pdf->SetFont('','B', $default_font_size + 4);
	    $pdf->SetXY($posx,$posy);
	    $pdf->SetTextColor(0,0,60);
	    $title=$outputlangs->transnoentities($titlekey);
	    $pdf->MultiCell(100, 4, $title, '', 'R');

	    $pdf->SetFont('','B',$default_font_size);

	    $posy+=7;
	    $pdf->SetXY($posx,$posy);
	    $pdf->SetTextColor(0,0,60);
	    $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : " . $outputlangs->convToOutputCharset($object->ref), '', 'R');

	    // Show list of linked objects
	    $posy+=7;
	    $pdf->SetFont('','', $default_font_size - 1);
	    $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
	    $pdf->SetTextColor(0,0,0);
	}

	/**
	 *   	Show footer of page. Need this->emetteur object
	 *
	 *   	@param	TCPDF		$pdf     			PDF
	 * 		@param	Object		$object				Object to show
	 *      @param	Translate	$outputlangs		Object lang for output
	 *      @param	int			$hidefreetext		1=Hide free text
	 *      @return	int								Return height of bottom margin including footer text
	 */
	function _pagefoot(&$pdf,$object,$outputlangs,$hidefreetext=0)
	{
	    global $conf;
	    $showdetails=$conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS;
	    return pdf_pagefoot($pdf,$outputlangs,'PRODUCT_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,$showdetails,$hidefreetext);
	}
	
	
	/**
 * Function to try to calculate height of a HTML Content
 *
 * @param 	TCPDF     $pdf				PDF initialized object
 * @param 	string    $htmlcontent		HTML Contect
 * @return 	int							Height
 * @see getStringHeight
 */
	function pdfPersoGetHeightForHtmlContent(&$pdf, $htmlcontent)
	{
		// store current object
		$pdf->startTransaction();
		// store starting values
		$start_y = $pdf->GetY();
		//var_dump($start_y);
		$start_page = $pdf->getPage();
		// call printing functions with content
		$pdf->writeHTMLCell($this->page_largeur-$this->marge_droite-10-$this->marge_gauche-10, 0, $this->marge_gauche+10, $start_y, $htmlcontent, 0, 1, false, true, 'J',true);
		// get the new Y
		$end_y = $pdf->GetY();
		$end_page = $pdf->getPage();
		// calculate height
		$height = 0;
		if ($end_page == $start_page) {
			$height = $end_y - $start_y;
		}
		else
		{
			for ($page=$start_page; $page <= $end_page; ++$page) {
				$pdf->setPage($page);
				$tmpm=$pdf->getMargins();
				$tMargin = $tmpm['top'];
				if ($page == $start_page) {
					// first page
					$height = $pdf->getPageHeight() - $start_y - $pdf->getBreakMargin();
				} elseif ($page == $end_page) {
					// last page
					$height = $end_y - $tMargin;
				} else {
					$height = $pdf->getPageHeight() - $tMargin - $pdf->getBreakMargin();
				}
			}
		}
		// restore previous object
		$pdf = $pdf->rollbackTransaction();

		return $height;
	}
}
3 « J'aime »

Bonjour :happy:
Si tu veux que ton code soit intégré, amélioré etc propose le sur github :

1 « J'aime »

J’approuve le passage de la PR sur le github… Surtout que c’est utile et on pourra t’aider à corriger tout ce qui est poids et mesures qui va changer dans la v10 à ec un nouveau code et gestion unite/ conversion

C’est fait : https://github.com/Dolibarr/dolibarr/issues/11039

Par contre je n’ai pas réussi à faire de PR, du coup j’ai fait une Issue.

J’ai corrigé le code pour qu’il soit multilingue avant de poster.