diff --git a/SECURITY.md b/SECURITY.md index 0cc37b96ce6..4d335d63737 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -104,3 +104,6 @@ Scope is the web application (backoffice) and the APIs. * SSL/TLS best practices * Invalid or missing SPF (Sender Policy Framework) records (Incomplete or missing SPF/DKIM/DMARC) * Physical or social engineering attempts or issues that require physical access to a victim’s computer/device +* Ability to include javascript into a page of the website using the website page editor are not qualified (this is the expected behaviour) +* Ability to execute PHP code on the server using the website using the website page editor by a user that own the super permission "add php code into pages" are not qualified (this is the expected behaviour). + diff --git a/htdocs/accountancy/admin/accountmodel.php b/htdocs/accountancy/admin/accountmodel.php index dbe02a3ff02..e14477b9158 100644 --- a/htdocs/accountancy/admin/accountmodel.php +++ b/htdocs/accountancy/admin/accountmodel.php @@ -191,10 +191,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { // Si verif ok et action add, on ajoute la ligne if ($ok && GETPOST('actionadd', 'alpha')) { + $newid = 0; if ($tabrowid[$id]) { // Get free id for insert - $newid = 0; - $sql = "SELECT MAX(".$db->sanitize($tabrowid[$id]).") newid FROM ".$db->sanitize($tabname[$id]); + $sql = "SELECT MAX(".$db->sanitize($tabrowid[$id]).") as newid FROM ".$db->sanitize($tabname[$id]); $result = $db->query($sql); if ($result) { $obj = $db->fetch_object($result); diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index bbf41060a4c..7ac6bc27cea 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -484,7 +484,7 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); $error++; break; - } elseif (isset($object->date_validation) || $object->date_validation != '') { + } elseif (isset($object->date_validation) && $object->date_validation != '') { setEventMessages($langs->trans("ValidatedRecordWhereFound"), null, 'errors'); $error++; break; diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 40b7599040c..bb549a3bc6d 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -447,7 +447,7 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); $error++; break; - } elseif (isset($object->date_validation) || $object->date_validation != '') { + } elseif (isset($object->date_validation) && $object->date_validation != '') { setEventMessages($langs->trans("ValidatedRecordWhereFound"), null, 'errors'); $error++; break; diff --git a/htdocs/adherents/ldap.php b/htdocs/adherents/ldap.php index edfa8adbb2f..f94cc476321 100644 --- a/htdocs/adherents/ldap.php +++ b/htdocs/adherents/ldap.php @@ -120,12 +120,13 @@ print '
'; print ''; // Login -print ''; +print ''; // If there is a link to the unencrypted password, we show the value in database here so we can compare because it is shown nowhere else +// This is for very old situation. Password are now encrypted and $object->pass is empty. if (getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD')) { print ''; - print ''; + print ''; print "\n"; } diff --git a/htdocs/admin/invoice.php b/htdocs/admin/invoice.php index a2f0282ba9f..fa0e810f33b 100644 --- a/htdocs/admin/invoice.php +++ b/htdocs/admin/invoice.php @@ -617,13 +617,14 @@ if (getDolGlobalString('INVOICE_USE_DEFAULT_DOCUMENT')) { // Hidden conf print ''; print ''; print ''; + print ''; print '
'; print '
'.$langs->trans("Login").' / '.$langs->trans("Id").''.$object->login.' 
'.$langs->trans("Login").' / '.$langs->trans("Id").''.dol_escape_htmltag($object->login).' 
'.$langs->trans("LDAPFieldPasswordNotCrypted").''.$object->pass.''.dol_escape_htmltag($object->pass).'
'; print ''; print ''; print ''; - print ''; + print ''; print "\n"; $listtype = array( @@ -659,6 +660,7 @@ print load_fiche_titre($langs->trans("SuggestedPaymentModesIfNotDefinedInInvoice print ''; print ''; +print ''; print '
'; print '
'.$langs->trans("Type").''.$langs->trans("Name").'
'; @@ -667,17 +669,16 @@ print ''; print ''; -print ''; +print ''; print "\n"; print ''; print ""; print ""; print "
'; print ''; print $langs->trans("PaymentMode").'
".$langs->trans("SuggestPaymentByRIBOnAccount").""; if (isModEnabled('bank')) { - $sql = "SELECT rowid, label"; + $sql = "SELECT rowid, label, clos"; $sql .= " FROM ".MAIN_DB_PREFIX."bank_account"; - $sql .= " WHERE clos = 0"; - $sql .= " AND courant = 1"; + $sql .= " WHERE courant = 1"; $sql .= " AND entity IN (".getEntity('bank_account').")"; $resql = $db->query($sql); if ($resql) { @@ -687,15 +688,19 @@ if (isModEnabled('bank')) { print '"; + print ajax_combobox("rib"); } else { print ''.$langs->trans("NoActiveBankAccountDefined").''; } @@ -735,6 +740,8 @@ if ($resql) { } } print ""; +print ajax_combobox("chq", array(), 0, 0, 'resolve', -2); + print "
"; print ''; @@ -757,12 +764,13 @@ print "\n"; print ''; print ''; print ''; +print ''; print ''; print $langs->trans("ForceInvoiceDate"); print ''; print $form->selectyesno("forcedate", getDolGlobalInt('FAC_FORCE_DATE_VALIDATION', 0), 1); print ''; -print ''; +print ''; print "\n"; print ''; @@ -777,6 +785,7 @@ $htmltext .= ''; print '
'; print ''; print ''; +print ''; print ''; print $form->textwithpicto($langs->trans("FreeLegalTextOnInvoices"), $langs->trans("AddCRIfTooLong").'

'.$htmltext, 1, 'help', '', 0, 2, 'freetexttooltip').'
'; $variablename = 'INVOICE_FREE_TEXT'; @@ -788,7 +797,7 @@ if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { print $doleditor->Create(); } print ''; -print ''; +print ''; print "\n"; print '
'; @@ -796,12 +805,13 @@ print ''; print '
'; print ''; print ''; +print ''; print ''; print $form->textwithpicto($langs->trans("WatermarkOnDraftBill"), $htmltext, 1, 'help', '', 0, 2, 'watermarktooltip').'
'; print ''; print ''; print ''; -print ''; +print ''; print "\n"; print '
'; diff --git a/htdocs/ai/admin/custom_prompt.php b/htdocs/ai/admin/custom_prompt.php index 699479bbb9e..7790c822249 100644 --- a/htdocs/ai/admin/custom_prompt.php +++ b/htdocs/ai/admin/custom_prompt.php @@ -165,9 +165,6 @@ if ($action == 'confirm_deleteproperty' && GETPOST('confirm') == 'yes') { } } } -if ($action == 'confirm_deleteproperty') { - var_dump(GETPOST('confirm'));exit; -} /* @@ -344,7 +341,7 @@ if ($action == 'edit' || $action == 'create') { $('#postPromptInput').val(''); } }); - + $('.showInputBtn').click(function() { event.preventDefault(); var index = $(this).data('index'); @@ -357,7 +354,7 @@ if ($action == 'edit' || $action == 'create') { $(this).html($(this).data('icon-cancel')); $(this).data('state', 'cancel'); - } else { + } else { $('#prePromptInput_'+index).attr('disabled', 'disabled'); $('#postPromptInput_'+index).attr('disabled', 'disabled'); @@ -367,8 +364,8 @@ if ($action == 'edit' || $action == 'create') { } }); }); - - + + "; print $out; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index e62067bd89a..6d3048b8e65 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -2903,19 +2903,23 @@ if ($action == 'create') { print '' . $langs->transcountry("AmountLT1", $mysoc->country_code) . ''; print '' . price($object->total_localtax1, 0, $langs, 1, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($object->total_localtax1, 0, $langs, 1, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT'); + + print '' . price($object->multicurrency_total_localtax1, 0, $langs, 1, -1, -1, $object->multicurrency_code) . ''; } print ''; + } - if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) { - print ''; - print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; - print '' . price($object->total_localtax2, 0, $langs, 1, -1, -1, $conf->currency) . ''; - if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($object->total_localtax2, 0, $langs, 1, -1, -1, $object->multicurrency_code) . ''; - } - print ''; + if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) { + print ''; + print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; + print '' . price($object->total_localtax2, 0, $langs, 1, -1, -1, $conf->currency) . ''; + if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { + $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT'); + + print '' . price($object->multicurrency_total_localtax2, 0, $langs, 1, -1, -1, $object->multicurrency_code) . ''; } + print ''; } print ''; diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 51cb5484af0..00311e60480 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -281,18 +281,6 @@ class Propal extends CommonObject public $labelStatus = array(); public $labelStatusShort = array(); - // Multicurrency - /** - * @var int ID - */ - public $fk_multicurrency; - - public $multicurrency_code; - public $multicurrency_tx; - public $multicurrency_total_ht; - public $multicurrency_total_tva; - public $multicurrency_total_ttc; - /** * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 1f13f844c5c..f918d886795 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2804,20 +2804,24 @@ if ($action == 'create' && $usercancreate) { print '' . $langs->transcountry("AmountLT1", $mysoc->country_code) . ''; print '' . price($object->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($object->total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT'); + + print '' . price($object->multicurrency_total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . ''; } print ''; + } - // Amount Local Taxes - if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) { - print ''; - print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; - print '' . price($object->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency) . ''; - if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($object->total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . ''; - } - print ''; + // Amount Local Taxes + if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) { + print ''; + print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; + print '' . price($object->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency) . ''; + if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { + $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT'); + + print '' . price($object->multicurrency_total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . ''; } + print ''; } print ''; diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index b7d2e37c24d..75b60a33839 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -253,20 +253,6 @@ class Commande extends CommonOrder */ public $lines = array(); - // Multicurrency - /** - * @var int Currency ID - */ - public $fk_multicurrency; - - /** - * @var string multicurrency code - */ - public $multicurrency_code; - public $multicurrency_tx; - public $multicurrency_total_ht; - public $multicurrency_total_tva; - public $multicurrency_total_ttc; //! key of module source when order generated from a dedicated module ('cashdesk', 'takepos', ...) public $module_source; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 30b7d6e655a..7296c3dd820 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -5014,21 +5014,24 @@ if ($action == 'create') { print '' . $langs->transcountry("AmountLT1", $mysoc->country_code) . ''; print '' . price($sign * $object->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($sign * $object->total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT'); + + print '' . price($sign * $object->multicurrency_total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . ''; } print ''; - - if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { - print ''; - print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; - print '' . price($sign * $object->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency) . ''; - if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($sign * $object->total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . ''; - } - print ''; - } } + if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { + print ''; + print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; + print '' . price($sign * $object->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency) . ''; + if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { + $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT'); + + print '' . price($sign * $object->multicurrency_total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . ''; + } + print ''; + } // Add the revenue stamp if ($selleruserevenustamp) { diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 8aee3548b16..d1d37f33589 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -194,6 +194,7 @@ class Facture extends CommonInvoice public $date_pointoftax; + /** * @var int Situation cycle reference number */ diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 19ae71b14e2..6d3d2c65557 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -504,6 +504,16 @@ abstract class CommonObject */ public $multicurrency_total_ttc; + /** + * @var float Multicurrency total localta1 + */ + public $multicurrency_total_localtax1; // not in database + + /** + * @var float Multicurrency total localtax2 + */ + public $multicurrency_total_localtax2; // not in database + /** * @var string * @see SetDocModel() diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 960d9ee7eec..5b18aee94af 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -857,14 +857,14 @@ function dol_copy($srcfile, $destfile, $newmask = '0', $overwriteifexists = 1, $ /** * Copy a dir to another dir. This include recursive subdirectories. * - * @param string $srcfile Source file (a directory) - * @param string $destfile Destination file (a directory) - * @param string $newmask Mask for new file ('0' by default means getDolGlobalString('MAIN_UMASK')). Example: '0666' - * @param int $overwriteifexists Overwrite file if exists (1 by default) + * @param string $srcfile Source file (a directory) + * @param string $destfile Destination file (a directory) + * @param string $newmask Mask for new file ('0' by default means getDolGlobalString('MAIN_UMASK')). Example: '0666' + * @param int $overwriteifexists Overwrite file if exists (1 by default) * @param array $arrayreplacement Array to use to replace filenames with another one during the copy (works only on file names, not on directory names). - * @param int $excludesubdir 0=Do not exclude subdirectories, 1=Exclude subdirectories, 2=Exclude subdirectories if name is not a 2 chars (used for country codes subdirectories). - * @param string[] $excludefileext Exclude some file extensions - * @return int Return integer <0 if error, 0 if nothing done (all files already exists and overwriteifexists=0), >0 if OK + * @param int $excludesubdir 0=Do not exclude subdirectories, 1=Exclude subdirectories, 2=Exclude subdirectories if name is not a 2 chars (used for country codes subdirectories). + * @param string[] $excludefileext Exclude some file extensions + * @return int Return integer <0 if error, 0 if nothing done (all files already exists and overwriteifexists=0), >0 if OK * @see dol_copy() */ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement = null, $excludesubdir = 0, $excludefileext = null) @@ -878,6 +878,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep } $destexists = dol_is_dir($destfile); + //if (! $overwriteifexists && $destexists) return 0; // The overwriteifexists is for files only, so propagated to dol_copy only. if (!$destexists) { @@ -888,7 +889,13 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep $dirmaskdec = octdec(getDolGlobalString('MAIN_UMASK')); } $dirmaskdec |= octdec('0200'); // Set w bit required to be able to create content for recursive subdirs files - dol_mkdir($destfile, '', decoct($dirmaskdec)); + + $result = dol_mkdir($destfile, '', decoct($dirmaskdec)); + + if (!dol_is_dir($destfile)) { + // The output directory does not exists and we failed to create it. So we stop here. + return -1; + } } $ossrcfile = dol_osencode($srcfile); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 2f794579b7b..40afe9b9dc8 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4618,7 +4618,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = 0, $srco if (empty($srconly) && in_array($pictowithouttext, array( '1downarrow', '1uparrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected', 'accountancy', 'accounting_account', 'account', 'accountline', 'action', 'add', 'address', 'ai', 'angle-double-down', 'angle-double-up', 'asset', - 'bank_account', 'barcode', 'bank', 'bell', 'bill', 'billa', 'billr', 'billd', 'birthday-cake', 'bookmark', 'bom', 'briefcase-medical', 'bug', 'building', + 'bank_account', 'barcode', 'bank', 'bell', 'bill', 'billa', 'billr', 'billd', 'birthday-cake', 'bom', 'bookcal', 'bookmark', 'briefcase-medical', 'bug', 'building', 'card', 'calendarlist', 'calendar', 'calendarmonth', 'calendarweek', 'calendarday', 'calendarperuser', 'calendarpertype', 'cash-register', 'category', 'chart', 'check', 'clock', 'clone', 'close_title', 'code', 'cog', 'collab', 'company', 'contact', 'country', 'contract', 'conversation', 'cron', 'cross', 'cubes', 'check-circle', 'check-square', 'currency', 'multicurrency', @@ -4666,6 +4666,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = 0, $srco 'asset' => 'money-check-alt', 'autofill' => 'fill', 'bank_account' => 'university', 'bill' => 'file-invoice-dollar', 'billa' => 'file-excel', 'billr' => 'file-invoice-dollar', 'billd' => 'file-medical', + 'bookcal' => 'calendar-check', 'supplier_invoice' => 'file-invoice-dollar', 'supplier_invoicea' => 'file-excel', 'supplier_invoicer' => 'file-invoice-dollar', 'supplier_invoiced' => 'file-medical', 'bom' => 'shapes', 'card' => 'address-card', 'chart' => 'chart-line', 'company' => 'building', 'contact' => 'address-book', 'contract' => 'suitcase', 'collab' => 'people-arrows', 'conversation' => 'comments', 'country' => 'globe-americas', 'cron' => 'business-time', 'cross' => 'times', @@ -4764,6 +4765,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = 0, $srco 'action' => 'infobox-action', 'account' => 'infobox-bank_account', 'accounting_account' => 'infobox-bank_account', 'accountline' => 'infobox-bank_account', 'accountancy' => 'infobox-bank_account', 'asset' => 'infobox-bank_account', 'bank_account' => 'infobox-bank_account', 'bill' => 'infobox-commande', 'billa' => 'infobox-commande', 'billr' => 'infobox-commande', 'billd' => 'infobox-commande', + 'bookcal' => 'infobox-action', 'margin' => 'infobox-bank_account', 'conferenceorbooth' => 'infobox-project', 'cash-register' => 'infobox-bank_account', 'contract' => 'infobox-contrat', 'check' => 'font-status4', 'collab' => 'infobox-action', 'conversation' => 'infobox-contrat', 'donation' => 'infobox-commande', 'dolly' => 'infobox-commande', 'dollyrevert' => 'flip infobox-order_supplier', @@ -7424,7 +7426,7 @@ function dol_mkdir($dir, $dataroot = '', $newmask = '') } $dirmaskdec |= octdec('0111'); // Set x bit required for directories if (!@mkdir($ccdir_osencoded, $dirmaskdec)) { - // Si le is_dir a renvoye une fausse info, alors on passe ici. + // If the is_dir has returned a false information, we arrive here dol_syslog("functions.lib::dol_mkdir: Fails to create directory '".$ccdir."' or directory already exists.", LOG_WARNING); $nberr++; } else { @@ -8322,7 +8324,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, '__USER_SIGNATURE__' => (string) (($usersignature && !getDolGlobalString('MAIN_MAIL_DO_NOT_USE_SIGN')) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($usersignature), 30) : $usersignature) : '') )); - if (is_object($user)) { + if (is_object($user) && ($user instanceof User)) { $substitutionarray = array_merge($substitutionarray, array( '__USER_ID__' => (string) $user->id, '__USER_LOGIN__' => (string) $user->login, diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index 68e8b982cce..bb1ce99fa52 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -839,7 +839,8 @@ function deletePropsAndPermsFromDoc($file, $objectname) /** - * Search a string and return all lines needed from file + * Search a string and return all lines needed from file. Does not include line $start nor $end + * * @param string $file file for searching * @param string $start start line if exist * @param string $end end line if exist @@ -953,106 +954,136 @@ function writePermsInAsciiDoc($file, $destfile) /** * Add Object in ModuleApi File - * @param string $file path of file - * @param array $objects array of objects in the module - * @param string $modulename name of module - * @return int 1 if OK, -1 if KO + * + * @param string $srcfile Source file to use as example + * @param string $file Path of modified file + * @param array $objects Array of objects in the module + * @param string $modulename Name of module + * @return int Return 1 if OK, -1 if KO */ -function addObjectsToApiFile($file, $objects, $modulename) +function addObjectsToApiFile($srcfile, $file, $objects, $modulename) { + global $langs, $user; + if (!file_exists($file)) { return -1; } - $content = file($file); - $includeClass = "dol_include_once('/mymodule/class/myobject.class.php');"; - $props = "public \$myobject;"; - $varcomented = "@var MyObject \$myobject {@type MyObject}"; - $constructObj = "\$this->myobject = new MyObject(\$this->db);"; + + $now = dol_now(); + $content = file($file); // $content is an array + + $includeClass = "dol_include_once\(\'\/\w+\/class\/\w+\.class\.php\'\);"; + $props = 'public\s+\$\w+;'; + $varcommented = '@var\s+\w+\s+\$\w+\s+{@type\s+\w+}'; + $constructObj = '\$this->\w+\s+=\s+new\s+\w+\(\$this->db\);'; // add properties and declare them in constructor foreach ($content as $lineNumber => &$lineContent) { - if (strpos($lineContent, $varcomented) !== false) { + if (preg_match('/'.$varcommented.'/', $lineContent)) { $lineContent = ''; - foreach ($objects as $object) { - $lineContent .= "\t * @var ".$object." \$".strtolower($object)." {@type ".$object."}". PHP_EOL; + foreach ($objects as $objectname) { + $lineContent .= "\t * @var ".$objectname." \$".strtolower($objectname)." {@type ".$objectname."}". PHP_EOL; } //var_dump($lineContent);exit; - } - if (strpos($lineContent, $props) !== false) { + } elseif (preg_match('/'.$props.'/', $lineContent)) { $lineContent = ''; - foreach ($objects as $object) { - $lineContent .= "\tpublic \$".strtolower($object).";". PHP_EOL; + foreach ($objects as $objectname) { + $lineContent .= "\tpublic \$".strtolower($objectname).";". PHP_EOL; } - } - if (strpos($lineContent, $constructObj) !== false) { + } elseif (preg_match('/'.$constructObj.'/', $lineContent)) { $lineContent = ''; - foreach ($objects as $object) { - $lineContent .= "\t\t\$this->".strtolower($object)." = new ".$object."(\$this->db);". PHP_EOL; + foreach ($objects as $objectname) { + $lineContent .= "\t\t\$this->".strtolower($objectname)." = new ".$objectname."(\$this->db);". PHP_EOL; } - } - if (strpos($lineContent, $includeClass) !== false) { + } elseif (preg_match('/'.$includeClass.'/', $lineContent)) { $lineContent = ''; - foreach ($objects as $object) { - $lineContent .= "dol_include_once('/".strtolower($modulename)."/class/".strtolower($object).".class.php');". PHP_EOL; + foreach ($objects as $objectname) { + $lineContent .= "dol_include_once('/".strtolower($modulename)."/class/".strtolower($objectname).".class.php');". PHP_EOL; } } } + $allContent = implode("", $content); file_put_contents($file, $allContent); - //add methods for each object - $allContent = getFromFile($file, '/*begin methods CRUD*/', '/*end methods CRUD*/'); - foreach ($objects as $object) { - $contentReplaced = str_replace(["myobject","MyObject"], [strtolower($object),$object], $allContent); - dolReplaceInFile($file, array('/*end methods CRUD*/' => '/*CRUD FOR '.strtoupper($object).'*/'."\n".$contentReplaced."\n\t".'/*END CRUD FOR '.strtoupper($object).'*/'."\n\t".'/*end methods CRUD*/')); + // Add methods for each object + $allContent = getFromFile($srcfile, '/* BEGIN MODULEBUILDER API MYOBJECT */', '/* END MODULEBUILDER API MYOBJECT */'); + foreach ($objects as $objectname) { + $arrayreplacement = array( + 'mymodule' => strtolower($modulename), + 'MyModule' => $modulename, + 'MYMODULE' => strtoupper($modulename), + 'My module' => $modulename, + 'my module' => $modulename, + 'Mon module' => $modulename, + 'mon module' => $modulename, + 'htdocs/modulebuilder/template' => strtolower($modulename), + 'myobject' => strtolower($objectname), + 'MyObject' => $objectname, + 'MYOBJECT' => strtoupper($objectname), + '---Put here your own copyright and developer email---' => dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '') + ); + $contentReplaced = make_substitutions($allContent, $arrayreplacement, null); + //$contentReplaced = str_replace(["myobject","MyObject"], [strtolower($object),$object], $allContent); + + dolReplaceInFile($file, array( + '/* BEGIN MODULEBUILDER API MYOBJECT */' => '/* BEGIN MODULEBUILDER API '.strtoupper($objectname).' */'.$contentReplaced."\t".'/* END MODULEBUILDER API '.strtoupper($objectname).' */'."\n\n\n\t".'/* BEGIN MODULEBUILDER API MYOBJECT */' + )); } - dolReplaceInFile($file, array($allContent => '','MyModule' => ucfirst($modulename))); + + // Remove the block $allContent found in src file + // TODO Replace with a replacement of all text including into /* BEGIN MODULEBUILDER API MYOBJECT */ and /* END MODULEBUILDER API MYOBJECT */ + dolReplaceInFile($file, array($allContent => '')); + return 1; } /** - * Remove Object variables and methods from API_Module File - * @param string $file file api module - * @param string $objectname name of object want to remove - * @param string $modulename name of module - * @return int 1 if OK, -1 if KO + * Remove Object variables and methods from API_Module File + * + * @param string $file File api module + * @param array $objects Array of objects in the module + * @param string $objectname Name of object want to remove + * @return int 1 if OK, -1 if KO */ -function removeObjectFromApiFile($file, $objectname, $modulename) +function removeObjectFromApiFile($file, $objects, $objectname) { - $begin = '/*CRUD FOR '.strtoupper($objectname).'*/'; - $end = '/*END CRUD FOR '.strtoupper($objectname).'*/'; - $includeClass = "dol_include_once('/".strtolower($modulename)."/class/".strtolower($objectname).".class.php');"; - $varcomentedDel = "\t * @var ".$objectname." \$".strtolower($objectname)." {@type ".$objectname."}"; - $propsDel = "\tpublic \$".strtolower($objectname).";"; - $constructObjDel = "\t\t\$this->".strtolower($objectname)." = new ".$objectname."(\$this->db);"; - if (!file_exists($file)) { return -1; } - $content = file($file); - // for delete property and the initialization from the construct + + $content = file($file); // $content is an array + + $includeClass = "dol_include_once\(\'\/\w+\/class\/".strtolower($objectname)."\.class\.php\'\);"; + $props = 'public\s+\$'.strtolower($objectname); + $varcommented = '@var\s+\w+\s+\$'.strtolower($objectname).'\s+{@type\s+\w+}'; + $constructObj = '\$this->'.strtolower($objectname).'\s+=\s+new\s+\w+\(\$this->db\);'; + + // add properties and declare them in constructor foreach ($content as $lineNumber => &$lineContent) { - if (strpos($lineContent, $includeClass) !== false) { + if (preg_match('/'.$varcommented.'/i', $lineContent)) { $lineContent = ''; - } - if (strpos($lineContent, $varcomentedDel) !== false) { + } elseif (preg_match('/'.$props.'/i', $lineContent)) { $lineContent = ''; - } - if (strpos($lineContent, $propsDel) !== false) { + } elseif (preg_match('/'.$constructObj.'/i', $lineContent)) { $lineContent = ''; - } - if (strpos($lineContent, $constructObjDel) !== false) { + } elseif (preg_match('/'.$includeClass.'/i', $lineContent)) { $lineContent = ''; } } + $allContent = implode("", $content); file_put_contents($file, $allContent); + // for delete methods of object + $begin = '/* BEGIN MODULEBUILDER API '.strtoupper($objectname).' */'; + $end = '/* END MODULEBUILDER API '.strtoupper($objectname).' */'; $allContent = getFromFile($file, $begin, $end); $check = dolReplaceInFile($file, array($allContent => '')); if ($check) { dolReplaceInFile($file, array($begin => '', $end => '')); } + return 1; } diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 15fbe56aa32..04081ba6a02 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -453,7 +453,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $err += $this->insert_tabs(); } - // Insert activation of module's parts + // Insert activation of module's parts. Copy website templates into doctemplates. if (!$err) { $err += $this->insert_module_parts(); } @@ -2310,6 +2310,15 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $this->errors[] = ($errormsg ? $errormsg : $langs->trans('ErrorFailToCreateZip', $dest)); } } + + // Copy also the preview website_xxx.jpg file + $docs = dol_dir_list($srcroot, 'files', 0, 'website_.*\.jpg$'); + foreach ($docs as $cursorfile) { + $src = $srcroot.'/'.$cursorfile['name']; + $dest = DOL_DATA_ROOT.'/doctemplates/websites/'.$cursorfile['name']; + + dol_copy($src, $dest); + } } $entity = $conf->entity; // Reset the current entity diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index 22fb04d708e..fafec559fad 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -947,8 +947,10 @@ class pdf_einstein extends ModelePDFCommandes $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -977,8 +979,10 @@ class pdf_einstein extends ModelePDFCommandes $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1038,8 +1042,11 @@ class pdf_einstein extends ModelePDFCommandes $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1071,8 +1078,10 @@ class pdf_einstein extends ModelePDFCommandes $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php index ca7209733f5..4b9e85e2589 100644 --- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php @@ -1149,8 +1149,10 @@ class pdf_eratosthene extends ModelePDFCommandes $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1179,8 +1181,10 @@ class pdf_eratosthene extends ModelePDFCommandes $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1240,8 +1244,11 @@ class pdf_eratosthene extends ModelePDFCommandes $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1273,8 +1280,10 @@ class pdf_eratosthene extends ModelePDFCommandes $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index f2f05ed7f84..4be06d41f7d 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1397,8 +1397,6 @@ class pdf_crabe extends ModelePDFFactures if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) { // Nothing to do } else { - // FIXME amount of vat not supported with multicurrency - //Local tax 1 before VAT //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') //{ @@ -1425,8 +1423,10 @@ class pdf_crabe extends ModelePDFFactures $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1456,8 +1456,10 @@ class pdf_crabe extends ModelePDFFactures $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1517,8 +1519,11 @@ class pdf_crabe extends ModelePDFFactures $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1547,8 +1552,10 @@ class pdf_crabe extends ModelePDFFactures $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } //} diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index a95a53f4084..baf4e960678 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1658,8 +1658,6 @@ class pdf_sponge extends ModelePDFFactures if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL') && $tvaisnull) { // Nothing to do } else { - // FIXME amount of vat not supported with multicurrency - //Local tax 1 before VAT //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') //{ @@ -1686,8 +1684,10 @@ class pdf_sponge extends ModelePDFFactures $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1717,8 +1717,10 @@ class pdf_sponge extends ModelePDFFactures $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1802,8 +1804,11 @@ class pdf_sponge extends ModelePDFFactures $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1835,8 +1840,10 @@ class pdf_sponge extends ModelePDFFactures $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } diff --git a/htdocs/core/modules/modAi.class.php b/htdocs/core/modules/modAi.class.php index 3194a93ed5a..3c47eb376d3 100644 --- a/htdocs/core/modules/modAi.class.php +++ b/htdocs/core/modules/modAi.class.php @@ -69,7 +69,7 @@ class modAi extends DolibarrModules $this->descriptionlong = "AiDescriptionLong"; // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' - $this->version = 'development'; + $this->version = 'experimental'; // Key used in llx_const table to save module status enabled/disabled (where BOOKCAL is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); @@ -78,7 +78,7 @@ class modAi extends DolibarrModules // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' - $this->picto = 'fa-microchip'; + $this->picto = 'fa-magic'; // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) $this->module_parts = array( diff --git a/htdocs/core/modules/modBookCal.class.php b/htdocs/core/modules/modBookCal.class.php index a778ac8ffc7..0b2ce6c2c77 100644 --- a/htdocs/core/modules/modBookCal.class.php +++ b/htdocs/core/modules/modBookCal.class.php @@ -78,7 +78,7 @@ class modBookCal extends DolibarrModules // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' - $this->picto = 'fa-calendar-check'; + $this->picto = 'bookcal'; // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) $this->module_parts = array( diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 1bdaa836188..dae580d2d47 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -1132,8 +1132,10 @@ class pdf_azur extends ModelePDFPropales $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1150,8 +1152,6 @@ class pdf_azur extends ModelePDFPropales if ($tvakey != 0) { // On affiche pas taux 0 //$this->atleastoneratenotnull++; - - $index++; $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); @@ -1164,8 +1164,10 @@ class pdf_azur extends ModelePDFPropales $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1224,8 +1226,11 @@ class pdf_azur extends ModelePDFPropales $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1256,8 +1261,10 @@ class pdf_azur extends ModelePDFPropales $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index 47f76988e44..d661b0ce260 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -1232,8 +1232,10 @@ class pdf_cyan extends ModelePDFPropales $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1250,8 +1252,6 @@ class pdf_cyan extends ModelePDFPropales if ($tvakey != 0) { // On affiche pas taux 0 //$this->atleastoneratenotnull++; - - $index++; $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); @@ -1265,8 +1265,10 @@ class pdf_cyan extends ModelePDFPropales $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1320,8 +1322,11 @@ class pdf_cyan extends ModelePDFPropales $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1353,8 +1358,10 @@ class pdf_cyan extends ModelePDFPropales $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index c59c4271710..9ff542d9799 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -165,7 +165,7 @@ BadValueForType=Bad value for type %s DefinePropertiesFromExistingTable=Define the fields/properties from an existing table DefinePropertiesFromExistingTableDesc=If a table in the database (for the object to create) already exists, you can use it to define the properties of the object. DefinePropertiesFromExistingTableDesc2=Keep empty if the table does not exist yet. The code generator will use different kinds of fields to build an example of table that you can edit later. -GeneratePermissions=I want to manage permissions on this object +GeneratePermissions=I want to manage permissions on this object GeneratePermissionsHelp=If you check this, some code will be added to manage permissions to read, write and delete record of the objects PermissionDeletedSuccesfuly=Permission has been successfully removed PermissionUpdatedSuccesfuly=Permission has been successfully updated @@ -173,6 +173,7 @@ PermissionAddedSuccesfuly=Permission has been successfully added MenuDeletedSuccessfuly=Menu has been successfully deleted MenuAddedSuccessfuly=Menu has been successfully added MenuUpdatedSuccessfuly=Menu has been successfully updated +AddAPIsForThisObject=Add APIs for this object ApiObjectDeleted=API for object %s has been successfully deleted CRUDRead=Read CRUDCreateWrite=Create or Update @@ -181,8 +182,8 @@ DictionariesCreated=Dictionary %s created successfully DictionaryDeleted=Dictionary %s removed successfully PropertyModuleUpdated=Property %s has been update successfully InfoForApiFile=* When you generate file for the first time then all methods will be created for each object.
* When you click in remove you just remove all methods for the selected object. -SetupFile=Page for module setup +SetupFile=Page for module setup EmailingSelectors=Emails selectors EmailingSelectorDesc=You can generate and edit here the class files to provide new email target selectors for the mass emailing module EmailingSelectorFile=Emails selector file -NoEmailingSelector=No emails selector file \ No newline at end of file +NoEmailingSelector=No emails selector file diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 1e78c341f06..e0acefa2b0e 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -467,13 +467,13 @@ if ($dirins && in_array($action, array('initapi', 'initphpunit', 'initpagecontac '---Put here your own copyright and developer email---' => dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '') ); - if (count($objects) > 1) { - addObjectsToApiFile($destfile, $objects, $modulename); + if ($action == 'initapi') { + if (count($objects) >= 1) { + addObjectsToApiFile($srcfile, $destfile, $objects, $modulename); + } } else { // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); - // @phan-suppress-next-line PhanPluginSuspiciousParamPosition - dolReplaceInFile($destfile, array('/*begin methods CRUD*/' => '/*begin methods CRUD*/'."\n\t".'/*CRUD FOR '.strtoupper($objectname).'*/', '/*end methods CRUD*/' => '/*END CRUD FOR '.strtoupper($objectname).'*/'."\n\t".'/*end methods CRUD*/')); } if ($varnametoupdate) { @@ -952,20 +952,31 @@ if ($dirins && $action == 'confirm_removefile' && !empty($module)) { $filetodelete = $dirins.'/'.$relativefilename; $dirtodelete = $dirins.'/'.$dirnametodelete; - //check when we want delete api_file + // Get list of existing objects + $objects = dolGetListOfObjectClasses($destdir); + + $keyofobjecttodelete = array_search($objectname, $objects); + if ($keyofobjecttodelete !== false) { + unset($objects[$keyofobjecttodelete]); + } + + // Delete or modify the file if (strpos($relativefilename, 'api') !== false) { $file_api = $destdir.'/class/api_'.strtolower($module).'.class.php'; - $removeFile = removeObjectFromApiFile($file_api, $objectname, $module); - $var = getFromFile($file_api, '/*begin methods CRUD*/', '/*end methods CRUD*/'); - if (str_word_count($var) == 0) { + + $removeFile = removeObjectFromApiFile($file_api, $objects, $objectname); + + if (count($objects) == 0) { $result = dol_delete_file($filetodelete); } + if ($removeFile) { setEventMessages($langs->trans("ApiObjectDeleted"), null); } } else { $result = dol_delete_file($filetodelete); } + if (!$result) { setEventMessages($langs->trans("ErrorFailToDeleteFile", basename($filetodelete)), null, 'errors'); } else { @@ -4209,7 +4220,7 @@ if ($module == 'initmodule') { print ''.$langs->trans("ApiExplorer").''; } } else { - print ''.img_picto('AddAPIsForThisObject', 'generate', 'class="paddingleft"').''; + print ''.img_picto($langs->trans('AddAPIsForThisObject'), 'generate', 'class="paddingleft"').''; } } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; diff --git a/htdocs/modulebuilder/template/admin/about.php b/htdocs/modulebuilder/template/admin/about.php index 7ec1d1f30f3..ecacf04f4c1 100644 --- a/htdocs/modulebuilder/template/admin/about.php +++ b/htdocs/modulebuilder/template/admin/about.php @@ -83,7 +83,7 @@ $backtopage = GETPOST('backtopage', 'alpha'); $form = new Form($db); $help_url = ''; -$title = "MyModuleAbout"; +$title = "MyModuleSetup"; llxHeader('', $langs->trans($title), $help_url, '', 0, 0, '', '', '', 'mod-mymodule page-admin_about'); diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index c124d0b7220..9cbcc07479d 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -12,7 +12,7 @@ * Copyright (C) 2014 Henry Florian * Copyright (C) 2014-2016 Philippe Grand * Copyright (C) 2014 Ion agorria - * Copyright (C) 2016-2018 Ferran Marcet + * Copyright (C) 2016-2024 Ferran Marcet * Copyright (C) 2017 Gustavo Novaro * Copyright (C) 2019-2024 Frédéric France * Copyright (C) 2023 Benjamin Falière @@ -1362,8 +1362,8 @@ class Product extends CommonObject if (!$this->hasbatch() && $this->oldcopy->hasbatch()) { // Selection of all product stock movements that contains batchs - $sql = 'SELECT pb.qty, pb.fk_entrepot, pb.batch FROM '.MAIN_DB_PREFIX.'product_batch as pb'; - $sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'product_stock as ps ON (ps.rowid = batch.fk_product_stock)'; + $sql = 'SELECT pb.qty, ps.fk_entrepot, pb.batch FROM '.MAIN_DB_PREFIX.'product_batch as pb'; + $sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'product_stock as ps ON (ps.rowid = pb.fk_product_stock)'; $sql .= ' WHERE ps.fk_product = '.(int) $this->id; $resql = $this->db->query($sql); diff --git a/htdocs/product/class/productbatch.class.php b/htdocs/product/class/productbatch.class.php index 2da779311c4..7322dcdb0dd 100644 --- a/htdocs/product/class/productbatch.class.php +++ b/htdocs/product/class/productbatch.class.php @@ -1,7 +1,8 @@ * Copyright (C) 2013-2014 Cedric GROSS - * Copyright (C) 2024 Frédéric France + * Copyright (C) 2024 Frédéric France + * Copyright (C) 2024 Ferran Marcet * * 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 @@ -522,7 +523,7 @@ class Productbatch extends CommonObject $tmp->import_key = $obj->import_key; if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) { - $tmp->context['stock_date_entry'] = $obj->date_entree; + $tmp->context['stock_entry_date'] = $dbs->jdate($obj->date_entree); } if ($fk_product > 0) { diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 47d572654be..2dbc2227f9d 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1075,15 +1075,16 @@ class Website extends CommonObject $i++; } + $line = '-- File generated by Dolibarr '.DOL_VERSION.' --;'."\n"; + $line .= "\n"; + fwrite($fp, $line); + foreach ($listofpages as $pageid => $objectpageold) { $oldpageid = $objectpageold->id; $allaliases = $objectpageold->pageurl; $allaliases .= ($objectpageold->aliasalt ? ','.$objectpageold->aliasalt : ''); - $line = '-- File generated by Dolibarr '.DOL_VERSION.' -- '.dol_print_date(dol_now('gmt'), 'standard', 'gmt').' UTC --;'."\n"; - $line .= "\n"; - if (!getDolGlobalInt('WEBSITE_EXPORT_KEEP_FILES_OF_PAGES')) { // We don't need to keep the PHP files of pages and aliases (they are regenerated at import) so we remove them. You can ask to keep them in the export // Delete the pageX.tpl.php page dol_delete_file($conf->website->dir_temp.'/'.$website->ref.'/containers/page'.$objectpageold->id.'.tpl.php', 0, 0, 0, null, false, 0); @@ -1098,13 +1099,12 @@ class Website extends CommonObject } // This comment syntax is important, it is parsed by import to get information on page ID and all aliases to regenerate - $line .= '-- Page ID '.$objectpageold->newid.'__+MAX_llx_website_page__ - Aliases '.$allaliases.' --;'; // newid start at 1, 2... + $line = '-- Page ID '.$objectpageold->newid.'__+MAX_llx_website_page__ - Aliases '.$allaliases.' --;'; // newid start at 1, 2... $line .= "\n"; fwrite($fp, $line); // Warning: We must keep llx_ here. It is a generic SQL. $line = 'INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames)'; - $line .= " VALUES("; $line .= $objectpageold->newid."__+MAX_llx_website_page__, "; $line .= ($objectpageold->newfk_page ? $this->db->escape($objectpageold->newfk_page)."__+MAX_llx_website_page__" : "null").", "; @@ -1170,7 +1170,7 @@ class Website extends CommonObject fwrite($fp, $line); } - $line .= "\n"; + fwrite($fp, "\n"); } $line = "\n-- For Dolibarr v14+ --;\n"; @@ -1180,6 +1180,7 @@ class Website extends CommonObject fwrite($fp, $line); fclose($fp); + dolChmod($filesql); // Build zip file @@ -1244,7 +1245,8 @@ class Website extends CommonObject $arrayreplacement['__LOGO_MINI_KEY__'] = $this->db->escape($mysoc->logo_mini); $arrayreplacement['__LOGO_KEY__'] = $this->db->escape($mysoc->logo); - // Copy containers + + // Copy containers directory dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/containers', $conf->website->dir_output.'/'.$object->ref, 0, 1); // Overwrite if exists // Make replacement into css and htmlheader file @@ -1262,8 +1264,17 @@ class Website extends CommonObject $error++; } - dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/medias/image/websitekey', $conf->website->dir_output.'/'.$object->ref.'/medias/image/'.$object->ref, 0, 1); // Medias can be shared, do not overwrite if exists - dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/medias/js/websitekey', $conf->website->dir_output.'/'.$object->ref.'/medias/js/'.$object->ref, 0, 1); // Medias can be shared, do not overwrite if exists + $result = dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/medias/image/websitekey', $conf->website->dir_output.'/'.$object->ref.'/medias/image/'.$object->ref, 0, 1); + if ($result < 0) { + $this->errors[] = 'Failed to copy files into '.$conf->website->dir_output.'/'.$object->ref.'/medias/image/'.$object->ref.'.'; + return -5; + } + + $result = dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/medias/js/websitekey', $conf->website->dir_output.'/'.$object->ref.'/medias/js/'.$object->ref, 0, 1); + if ($result < 0) { + $this->errors[] = 'Failed to copy files into '.$conf->website->dir_output.'/'.$object->ref.'/medias/js/'.$object->ref.'.'; + return -5; + } $sqlfile = $conf->website->dir_temp."/".$object->ref.'/website_pages.sql'; @@ -1288,7 +1299,7 @@ class Website extends CommonObject $objectpagestatic = new WebsitePage($this->db); - // Make replacement of IDs + // Regenerate the php files for pages $fp = fopen($sqlfile, "r"); if ($fp) { while (!feof($fp)) { @@ -1296,18 +1307,30 @@ class Website extends CommonObject // Warning fgets with second parameter that is null or 0 hang. $buf = fgets($fp, 65000); + $newid = 0; + + // Scan the line if (preg_match('/^-- Page ID (\d+)\s[^\s]+\s(\d+).*Aliases\s(.*)\s--;/i', $buf, $reg)) { + // Example of line: "-- Page ID 179 -> 1__+MAX_llx_website_page__ - Aliases about-us --;" $oldid = $reg[1]; $newid = ($reg[2] + $maxrowid); $aliasesarray = explode(',', $reg[3]); - dol_syslog("Found ID ".$oldid." to replace with ID ".$newid." and shortcut aliases to create: ".$reg[3]); + dol_syslog("In sql source file, we have the page ID ".$oldid." to replace with the new ID ".$newid.", and we must create the shortcut aliases: ".$reg[3]); - dol_move($conf->website->dir_output.'/'.$object->ref.'/page'.$oldid.'.tpl.php', $conf->website->dir_output.'/'.$object->ref.'/page'.$newid.'.tpl.php', 0, 1, 0, 0); + //dol_move($conf->website->dir_output.'/'.$object->ref.'/page'.$oldid.'.tpl.php', $conf->website->dir_output.'/'.$object->ref.'/page'.$newid.'.tpl.php', 0, 1, 0, 0); + } elseif (preg_match('/^-- Page ID (\d+).*Aliases\s(.*)\s--;/i', $buf, $reg)) { + // Example of line: "-- Page ID 1__+MAX_llx_website_page__ - Aliases about-us --;" + $newid = ($reg[1] + $maxrowid); + $aliasesarray = explode(',', $reg[2]); + dol_syslog("In sql source file, we have the page with the new ID ".$newid.", and we must create the shortcut aliases: ".$reg[3]); + } + + if ($newid) { $objectpagestatic->fetch($newid); - // The move is not enough, so we regenerate pageX.tpl.php + // We regenerate the pageX.tpl.php $filetpl = $conf->website->dir_output.'/'.$object->ref.'/page'.$newid.'.tpl.php'; $result = dolSavePageContent($filetpl, $object, $objectpagestatic); if (!$result) { @@ -1346,7 +1369,7 @@ class Website extends CommonObject } } - // Regenerate index page to point to the new index page + // Regenerate the index.php page to point to the new index page $pathofwebsite = $conf->website->dir_output.'/'.$object->ref; dolSaveIndexPage($pathofwebsite, $pathofwebsite.'/index.php', $pathofwebsite.'/page'.$object->fk_default_home.'.tpl.php', $pathofwebsite.'/wrapper.php', $object); @@ -1684,173 +1707,20 @@ class Website extends CommonObject // Export on target sources $resultarray = dol_uncompress($pathtotmpzip, $destdir); + // Remove the file README and LICENSE from the $destdir (already into the containers directory) + dol_delete_file($destdir.'/README.md'); + dol_delete_file($destdir.'/LICENSE'); + + // Remove non required files (will be re-generated during the import) + dol_delete_file($destdir.'/containers/index.php'); + dol_delete_file($destdir.'/containers/master.inc.php'); + if (!empty($resultarray)) { setEventMessages("Error, failed to unzip the export into target dir", null, 'errors'); } else { setEventMessages("Website content written into ".$destdirrel, null, 'mesgs'); } - /* - $sourcedir = $conf->website->dir_output."/".$website->ref; - - // Get array with hash of files (for the last sync) - $fichierEtat = $sourcedir . '/filelist-'.dol_sanitizeFileName($destdir).'.txt'; - $etatPrecedent = $this->checkPreviousState($fichierEtat); - - // Get list of all source files of the website - $arraySourcedir = dol_dir_list($sourcedir); - - // Get list of modified files - $modifications = []; - foreach ($arraySourcedir as $file) { - if (substr($file['name'], -4) === '.old') { - continue; - } - $hashActuel = hash_file('md5', $file['fullname']); - - // Check whether the file is new or has been modified - if (!isset($etatPrecedent[$file['name']]) || $etatPrecedent[$file['name']] !== $hashActuel) { - $modifications[] = $file; - } - - $etatPrecedent[$file['name']] = $hashActuel; // we store he new hash to record it later on disk. - } - - $arraydestdir = dol_dir_list($destdir, "all", 1); - $differences = []; - $names = array_column($arraydestdir, 'name'); - $namesSource = array_column($arraySourcedir, 'name'); - - if (count($modifications) > 1) { - foreach ($modifications as $fichierModifie) { - $nomFichierModifie = $fichierModifie['name']; - if ($nomFichierModifie == basename($fichierEtat)) { - continue; - } - $success = 0; - - //check if it is a new file - if ((!preg_match('/^page\d+\.tpl\.php$/', $nomFichierModifie)) && (!in_array($nomFichierModifie, $names))) { - if (file_exists($fichierModifie['fullname']) && dol_is_dir($destdir.'/containers')) { - $cp = dol_copy($fichierModifie['fullname'], $destdir.'/containers/'.$nomFichierModifie, '0664'); - if ($cp > 0) { - if (file_exists($destdir.'/containers/'.$nomFichierModifie)) { - $tabnumpage = array(); - foreach ($arraydestdir as $fileDest) { - if ($this->extractNumberFromFilename($fileDest['name']) !== -1) { - $tabnumpage[] = $this->extractNumberFromFilename($fileDest['name']); - } - } - $getContentSource = file_get_contents($destdir.'/containers/'.$nomFichierModifie); - $nextpage = max($tabnumpage) + 1; - $chaineModifiee = preg_replace('/page\d+\.tpl\.php/', 'page' . $nextpage . '.tpl.php', $getContentSource); - $write = file_put_contents($destdir.'/containers/'.$nomFichierModifie, $chaineModifiee); - if ($write !== false) { - if (!touch($destdir.'/containers/'."page" . $nextpage . ".tpl.php")) { - setEventMessages("Please check permission to create page" . $nextpage . ".tpl.php in template ".$website->name_template."", null, 'errors'); - } - $filesFound = ''; - foreach ($arraySourcedir as $file) { - if ($file['name'] == $nomFichierModifie) { - $fileContent = file_get_contents($file['fullname']); - $matches = array(); - if (preg_match("/page\d+\.tpl\.php/", $fileContent, $matches)) { - $filesFound = $matches[0]; - break; - } - } - } - foreach ($arraySourcedir as $file) { - if ($file['name'] == $filesFound) { - if (!is_writable($file['fullname'])) { - dolChmod($file['fullname'], '0664'); - } - $diff = $this->showDifferences(file_get_contents($destdir.'/containers/'."page" . $nextpage . ".tpl.php"), file_get_contents($file['fullname']), array($nextpage,$this->extractNumberFromFilename($file['name']))); - if ($diff != -1) { - $replace = $this->replaceLineUsingNum($destdir.'/containers/'."page" . $nextpage . ".tpl.php", $diff); - if ($replace !== false) { - setEventMessages("Copy file page".$nextpage.".tpl.php in template ".$this->name_template." with success", null, 'warnings'); - } - } - } - } - } - } - - $this->saveState($etatPrecedent, $fichierEtat); - setEventMessages("file ".$nomFichierModifie." was created in template ".$website->name_template."", null, 'warnings'); - - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); - exit(); - } - } else { - setEventMessages("Error, target dir containers not found", null, 'errors'); - $error = 1; - break; - } - } - - // Find the corresponding file in the destination folder - if (!$error && in_array($nomFichierModifie, $namesSource)) { - foreach ($arraydestdir as $destFile) { - if ($destFile['name'] == $nomFichierModifie) { - $sourceContent = file_get_contents($fichierModifie['fullname']); - $destContent = file_get_contents($destFile['fullname']); - - if ($sourceContent !== $destContent) { - $differences[$nomFichierModifie] = $this->showDifferences($destContent, $sourceContent); - if (count($differences[$nomFichierModifie]) > 0) { - $result = $this->replaceLineUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); - if ($result >= 0) { - setEventMessages("file ".$nomFichierModifie." was modified in template ".$website->name_template."", null, 'warnings'); - } else { - if ($result == -2) { - setEventMessages("No permissions to write into file ".$destdirrel.'/'.$nomFichierModifie." from the current website ".$website->name_template."", null, 'errors'); - - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); - exit(); - } - setEventMessages("file ".$nomFichierModifie." was not modified", null, 'errors'); - } - } - } - } - - if (preg_match('/page(\d+)\.tpl\.php/', $nomFichierModifie)) { - $differences[$nomFichierModifie] = $this->compareFichierModifie($sourcedir, $destdir, $fichierModifie); - if (count($differences[$nomFichierModifie]) > 0) { - $result = $this->replaceLineUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); - if ($result !== false) { - if ($result == -2) { - setEventMessages("No permissions to write into file ".$destdirrel.'/'.$differences[$nomFichierModifie]['file_destination']['name']." from the current website ".$website->name_template."", null, 'errors'); - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); - exit(); - } - $success++; - } - } - } - } - } - } - if ($success > 0) { - // Save the state file filelist.txt - $this->saveState($etatPrecedent, $fichierEtat); - setEventMessages("file ".$differences[$nomFichierModifie]['file_destination']['name']." was modified in template ".$website->name_template."", null, 'warnings'); - - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); - exit(); - } - } else { - setEventMessages("No file has been modified", null, 'errors'); - } - - // save state file - if (!$error) { - $this->saveState($etatPrecedent, $fichierEtat); - } - */ - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); exit(); } @@ -1918,38 +1788,6 @@ class Website extends CommonObject return file_put_contents($pathname, serialize($etat)); } - /** - * create file for save state of all files in folder - * - * @param string $sourcedir path of folder - * @return void - */ - /* - public function initFilesStatus($sourcedir) - { - $fichierEtat = $sourcedir . '/filelist-lastwrite-doctemplates.txt'; - - $etatPrecedent = $this->checkPreviousState($fichierEtat); - - // for first save state when create file - if (empty($etatPrecedent)) { - $arraySourcedir = dol_dir_list($sourcedir, "files"); - $etatFichiers = []; - - foreach ($arraySourcedir as $file) { - // Ignore .old files and the status file itself - if (substr($file['name'], -4) === '.old' || $file['name'] === basename($fichierEtat)) { - continue; - } - - $hashActuel = hash_file('md5', $file['fullname']); - $etatFichiers[$file['name']] = $hashActuel; - } - $this->saveState($etatFichiers, $fichierEtat); - } - } - */ - /** * Compare two files has not same name but same content * @param string $dossierSource filepath of folder source diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 566a1c2feb9..37430439427 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1155,7 +1155,17 @@ if ($action == 'addcontainer' && $usercanedit) { $substitutionarray = array(); $substitutionarray['__WEBSITE_CREATE_BY__'] = $user->getFullName($langs); - // Define id of page the new page is translation of + // Define id of the page the new page is translation of + /* + if ($objectpage->lang == $object->lang) { + // If + $pageidfortranslation = (GETPOSTINT('pageidfortranslation') > 0 ? GETPOSTINT('pageidfortranslation') : 0); + if ($pageidfortranslation > 0) { + // We must update the page $pageidfortranslation to set fk_page = $object->id. + // But what if page $pageidfortranslation is already linked to another ? + } + } else { + */ $pageidfortranslation = (GETPOSTINT('pageidfortranslation') > 0 ? GETPOSTINT('pageidfortranslation') : 0); if ($pageidfortranslation > 0) { // Check if the page we are translation of is already a translation of a source page. if yes, we will use source id instead @@ -1166,6 +1176,7 @@ if ($action == 'addcontainer' && $usercanedit) { } } $objectpage->fk_page = $pageidfortranslation; + //} $sample = GETPOST('sample', 'alpha'); if (empty($sample)) { @@ -2406,6 +2417,22 @@ if ($usercanedit && (($action == 'updatesource' || $action == 'updatecontent' || } } +if ($action == 'deletelang' && $usercanedit) { + $sql = "UPDATE ".MAIN_DB_PREFIX."website_page SET fk_page = NULL"; + $sql .= " WHERE rowid = ".GETPOSTINT('deletelangforid'); + //$sql .= " AND fk_page = ".((int) $objectpage->id); + + $resql = $db->query($sql); + if (!$resql) { + setEventMessages($db->lasterror(), null, 'errors'); + } else { + $objectpage->fk_page = null; + } + + $action = 'editmeta'; +} + + // Export site if ($action == 'exportsite' && $user->hasRight('website', 'export')) { $fileofzip = $object->exportWebSite(); @@ -4360,7 +4387,9 @@ if ($action == 'editmeta' || $action == 'createcontainer') { // Edit properties if ($i > 0) { $tmpstring .= '
'; } - $tmpstring .= $tmppage->getNomUrl(1).' ('.$tmppage->lang.')'; + $tmpstring .= $tmppage->getNomUrl(1).' '.picto_from_langcode($tmppage->lang).' '.$tmppage->lang; + // Button unlink + $tmpstring .= ' id).'">'.img_picto($langs->trans("Remove"), 'unlink').''; $translatedby++; $i++; } @@ -4376,17 +4405,27 @@ if ($action == 'editmeta' || $action == 'createcontainer') { // Edit properties dol_print_error($db); } } - if (empty($translatedby) && ($action == 'editmeta' || $action == 'createcontainer' || $objectpage->fk_page > 0)) { + if ((empty($translatedby) || ($objectpage->lang != $object->lang)) && ($action == 'editmeta' || $action == 'createcontainer' || $objectpage->fk_page > 0)) { $sourcepage = new WebsitePage($db); - $result = $sourcepage->fetch($objectpage->fk_page); - if ($result == 0) { - // not found, we can reset value to clean database - } elseif ($result > 0) { + $result = 1; + if ($objectpage->fk_page > 0) { + $result = $sourcepage->fetch($objectpage->fk_page); + if ($result == 0) { + // not found, we can reset value to clean database + // TODO + } + } + if ($result >= 0) { + if ($translatedby) { + print '
'; + } $translationof = $objectpage->fk_page; print ''.$langs->trans('ThisPageIsTranslationOf').' '; - print $formwebsite->selectContainer($website, 'pageidfortranslation', ($translationof ? $translationof : -1), 1, $action, 'minwidth300', array($objectpage->id)); + print $sourcepage->getNomUrl(2).' '.$formwebsite->selectContainer($website, 'pageidfortranslation', ($translationof ? $translationof : -1), 1, $action, 'minwidth300', array($objectpage->id)); if ($translationof > 0 && $sourcepage->lang) { - print $sourcepage->getNomUrl(2).' ('.$sourcepage->lang.')'; + print picto_from_langcode($sourcepage->lang).' '.$sourcepage->lang; + // Button unlink + print ' id).'">'.img_picto($langs->trans("Remove"), 'unlink').''; } } }