From 3477cb544a38a4e52e276ee5392907325fb678f9 Mon Sep 17 00:00:00 2001 From: Thomas905 Date: Wed, 6 Dec 2023 15:38:23 +0100 Subject: [PATCH 01/60] general donation payment page --- htdocs/core/menus/standard/eldy.lib.php | 1 + htdocs/don/paiement/list.php | 468 ++++++++++++++++++++++++ htdocs/langs/fr_FR/donations.lang | 1 + 3 files changed, 470 insertions(+) create mode 100644 htdocs/don/paiement/list.php diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 7899d12259b43..a17c23f06acaa 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1548,6 +1548,7 @@ function get_left_menu_billing($mainmenu, &$newmenu, $usemenuhider = 1, $leftmen if ($usemenuhider || empty($leftmenu) || $leftmenu == "donations") { $newmenu->add("/don/card.php?leftmenu=donations&action=create", $langs->trans("NewDonation"), 1, $user->hasRight('don', 'creer')); $newmenu->add("/don/list.php?leftmenu=donations", $langs->trans("List"), 1, $user->hasRight('don', 'lire')); + $newmenu->add("/don/paiement/list.php", $langs->trans("Payments"), 1, $user->hasRight('don', 'lire')); } // if ($leftmenu=="donations") $newmenu->add("/don/stats/index.php",$langs->trans("Statistics"), 1, $user->hasRight('don', 'lire')); } diff --git a/htdocs/don/paiement/list.php b/htdocs/don/paiement/list.php new file mode 100644 index 0000000000000..4868fb61041f1 --- /dev/null +++ b/htdocs/don/paiement/list.php @@ -0,0 +1,468 @@ + + * Copyright (C) 2004-2018 Laurent Destailleur + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2013 Cédric Salvador + * Copyright (C) 2019 Thibault FOUCART + * + * 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 . + */ + +/** + * \file htdocs/don/list.php + * \ingroup donations + * \brief List of donations + */ + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; +require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array('companies', 'donations')); + +$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'create'/'add', 'edit'/'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'sclist'; + +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +$type = GETPOST('type', 'aZ'); +$mode = GETPOST('mode', 'alpha'); +if (empty($page) || $page == -1) { + $page = 0; +} // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortorder) { + $sortorder = "DESC"; +} +if (!$sortfield) { + $sortfield = "d.datedon"; +} + +$search_status = (GETPOST("search_status", 'intcomma') != '') ? GETPOST("search_status", 'intcomma') : "-4"; +$search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); +$search_ref = GETPOST('search_ref', 'alpha'); +$search_thirdparty = GETPOST('search_thirdparty', 'alpha'); +$search_payment = GETPOST('search_payment', 'alpha'); +$search_amount = GETPOST('search_amount', 'alpha'); +$search_bank_account = GETPOST('search_bank_account', 'int'); +$optioncss = GETPOST('optioncss', 'alpha'); +$moreforfilter = GETPOST('moreforfilter', 'alpha'); + +if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // Both test are required to be compatible with all browsers + $search_all = ""; + $search_ref = ""; + $search_company = ""; + $search_thirdparty = ""; + $search_name = ""; + $search_payment = ""; + $search_amount = ""; + $search_status = ''; +} + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('donationlist')); + + +// List of fields to search into when doing a "search in all" +$fieldstosearchall = array( + 'p.ref'=>"RefPayment", + 'p.num_payment'=>"Numero", + 'pd.amount'=>"Amount", +); + +// Security check +$result = restrictedArea($user, 'don'); + +$permissiontoread = $user->hasRight('don', 'read'); +$permissiontoadd = $user->hasRight('don', 'write'); +$permissiontodelete = $user->hasRight('don', 'delete'); + +/* + * Actions + */ + + +if (GETPOST('cancel', 'alpha')) { + $action = 'list'; + $massaction = ''; +} +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { + $massaction = ''; +} + +/* + * View + */ + +$form = new Form($db); +$donationstatic = new Don($db); +$companystatic = new Societe($db); +$bankline = new AccountLine($db); +$accountstatic = new Account($db); + +$title = $langs->trans("Donations"); +$help_url = 'EN:Module_Donations|FR:Module_Dons|ES:Módulo_Donaciones|DE:Modul_Spenden'; + + +// Build and execute select +// -------------------------------------------------------------------- +$sql = "SELECT pd.rowid as payment_id, pd.amount, pd.datep, pd.fk_typepayment, pd.num_payment, pd.amount, pd.fk_bank, "; +$sql .= ' s.rowid as soc_id, s.nom, '; +$sql .= ' d.societe, '; +$sql .= ' c.code as paiement_code, '; +$sql .= ' d.rowid, ba.rowid as bid, ba.ref as bref, ba.label as blabel, ba.number, ba.account_number as account_number, ba.iban_prefix, ba.bic, ba.currency_code, ba.fk_accountancy_journal as accountancy_journal '; + +$sqlfields = $sql; // $sql fields to remove for count total + +$sql .= " FROM ".MAIN_DB_PREFIX."payment_donation as pd"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."don as d ON (d.rowid = pd.fk_donation)"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank as b ON (b.rowid = pd.fk_bank)"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank_account as ba ON (ba.rowid = b.fk_account)"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON (s.rowid = d.fk_soc)"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as c ON (c.id = pd.fk_typepayment)"; + +if ($search_status != '' && $search_status != '-4') { + $sql .= " AND d.fk_statut IN (".$db->sanitize($search_status).")"; +} +if (trim($search_ref) != '') { + $sql .= natural_search('pd.ref', $search_ref); +} +if (trim($search_all) != '') { + $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +} +if (trim($search_company) != '') { + $sql .= natural_search('d.societe', $search_company); +} +if ($search_bank_account > 0) { + $sql .= ' AND b.fk_account = '.((int) $search_bank_account); +} +if (trim($search_payment) != '') { + $sql .= natural_search("pd.rowid", $search_payment); +} +if ($search_amount) { + $sql .= natural_search('d.amount', $search_amount, 1); +} + + +// Count total nb of records +$nbtotalofrecords = ''; +if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); + $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); + if ($resql) { + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + } else { + dol_print_error($db); + } + + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0 + $page = 0; + $offset = 0; + } + $db->free($resql); +} + +// Complete request and execute it with limit +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); +} + +$resql = $db->query($sql); + +if (!$resql) { + dol_print_error($db); + exit; +} + + + +$num = $db->num_rows($resql); + +// Direct jump if only one record found +if ($num == 1 && !getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) { + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.$id); + exit; +} + + +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist'); // Can use also classforhorizontalscrolloftabs instead of bodyforlist for no horizontal scroll + +// Example : Adding jquery code +// print ''; + +$arrayofselected = is_array($toselect) ? $toselect : array(); + +$param = ''; +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); +} +if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.((int) $limit); +} +if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); +} +if ($search_ref) { + $param .= '&search_ref='.urlencode($search_ref); +} +if ($search_company) { + $param .= '&search_company='.urlencode($search_company); +} +if ($search_payment) { + $param .= '&search_payment='.urlencode($search_payment); +} +if ($search_amount) { + $param .= '&search_amount='.urlencode($search_amount); +} + +// List of mass actions available +$arrayofmassactions = array( + //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"), + //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), + //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), + //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), +); +if (!empty($permissiontodelete)) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +} +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { + $arrayofmassactions = array(); +} +$massactionbutton = $form->selectMassAction('', $arrayofmassactions); + + +print '
'."\n"; +if ($optioncss != '') { + print ''; +} +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print_barre_liste($langs->trans("DonationsReglement"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'object_donation', 0, $newcardbutton, '', $limit, 0, 0, 1); + +if ($search_all) { + $setupstring = ''; + foreach ($fieldstosearchall as $key => $val) { + $fieldstosearchall[$key] = $langs->trans($val); + $setupstring .= $key."=".$val.";"; + } + print ''."\n"; + print '
'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
'; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields +$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
'; +print ''."\n"; + +// Fields title search +// -------------------------------------------------------------------- +print ''; +// Action column +if (getDolGlobalInt('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; +} + +print ''; + + +print ''; + +print ''; + +print ''; + +print ''; + +print ''; + +print ''; + +print ''; + + +$totalarray = array(); +$totalarray['nbfield'] = 0; + +// Fields title label +// -------------------------------------------------------------------- +print ''; +// Action column +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print_liste_field_titre(''); + $totalarray['nbfield']++; +} + +print_liste_field_titre("RefPayment", $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder); +$totalarray['nbfield']++; +print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "d.datedon", "", $param, '', $sortfield, $sortorder, ); +$totalarray['nbfield']++; +print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "d.fk_soc", "", $param, "", $sortfield, $sortorder,); +$totalarray['nbfield']++; +print_liste_field_titre("Type", $_SERVER["PHP_SELF"], "d.amount", "", $param, '', $sortfield, $sortorder); +$totalarray['nbfield']++; +print_liste_field_titre("Numero", $_SERVER["PHP_SELF"], "p.num_paiement", '', $param, '', $sortfield, $sortorder, '', "ChequeOrTransferNumber"); +$totalarray['nbfield']++; +print_liste_field_titre("BankTransactionLine", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder); +$totalarray['nbfield']++; +print_liste_field_titre("Account", $_SERVER["PHP_SELF"], "d.fk_statut", "", $param, '', $sortfield, $sortorder); +$totalarray['nbfield']++; +print_liste_field_titre("Amount", $_SERVER["PHP_SELF"], "d.fk_statut", "", $param, '', $sortfield, $sortorder); +$totalarray['nbfield']++; + +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print_liste_field_titre(''); + $totalarray['nbfield']++; +} +print ''."\n"; + +$i = 0; +$savnbfield = $totalarray['nbfield']; +$totalarray = array(); +$totalarray['nbfield'] = 0; +$imaxinloop = ($limit ? min($num, $limit) : $num); +while ($i < $imaxinloop) { + + $obj = $db->fetch_object($resql); + + $companystatic->id = $obj->soc_id; + $companystatic->name = $obj->nom; + + $company = new Societe($db); + $result = $company->fetch($obj->socid); + + print ''; + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } + + print ''; + + $dateformatforpayment = 'dayhour'; + print ''; + + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + + print ''; + + print ''; + + print ''; + + + print ''; + + $i++; +} + +print "
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; +print ''; +print ''; +print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); +print ''; +print '
'; +print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); +print '
'; +print '
'; +print ''; +print ''; +$form->select_types_paiements($search_payment_type, 'search_payment_type', '', 2, 1, 1); +print ''; +print ''; +print ''; +$form->select_comptes($search_bank_account, 'search_bank_account', 0, '', 1); +print ''; +print ''; +print '
'.img_object($langs->trans("Payment"), "payment").' '.$obj->payment_id.''.dol_print_date($db->jdate($obj->datep), $dateformatforpayment, 'tzuser').''; + if ($obj->soc_id > 0) { + print $companystatic->getNomUrl(1, '', 24); + } else { + print $donationstatic->societe = $obj->societe; + } + print ''.$langs->trans("PaymentTypeShort".$obj->paiement_code).''.$obj->num_payment.''; + if ($obj->fk_bank > 0) { + $test = $bankline->fetch($obj->fk_bank); + print $bankline->getNomUrl(1, 0); + } + print ''; + if ($obj->bid > 0) { + $accountstatic->id = $obj->bid; + $accountstatic->ref = $obj->bref; + $accountstatic->label = $obj->blabel; + $accountstatic->number = $obj->number; + $accountstatic->account_number = $obj->account_number; + + $accountingjournal = new AccountingJournal($db); + $accountingjournal->fetch($obj->accountancy_journal); + $accountstatic->accountancy_journal = $accountingjournal->code; + + print $accountstatic->getNomUrl(1); + } + + print ''.price($obj->amount).'
"; +print '
'; +print "
\n"; +$db->free($resql); + +llxFooter(); +$db->close(); diff --git a/htdocs/langs/fr_FR/donations.lang b/htdocs/langs/fr_FR/donations.lang index b0a000d9af4d6..610c07349f3c7 100644 --- a/htdocs/langs/fr_FR/donations.lang +++ b/htdocs/langs/fr_FR/donations.lang @@ -33,3 +33,4 @@ DONATION_ART978=Afficher article 978 du CGI si vous êtes concernés DonationPayment=Paiement du don DonationValidated=Don %s validé DonationUseThirdparties=Utiliser un tiers existant comme coordonnées des donateurs +DonationsReglement= Règlements reçus pour les dons From 30681c5e24f8885a9a4af202304ba33445d93e8a Mon Sep 17 00:00:00 2001 From: Thomas905 Date: Thu, 7 Dec 2023 08:51:16 +0100 Subject: [PATCH 02/60] working table donation list --- htdocs/don/paiement/list.php | 567 +++++++++++++++++++++++------------ 1 file changed, 374 insertions(+), 193 deletions(-) diff --git a/htdocs/don/paiement/list.php b/htdocs/don/paiement/list.php index 4868fb61041f1..db7e303b22eeb 100644 --- a/htdocs/don/paiement/list.php +++ b/htdocs/don/paiement/list.php @@ -39,6 +39,25 @@ $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'sclist'; +$paiementid = GETPOST('paiementid', 'int'); + +$search_ref = GETPOST("search_ref", "alpha"); +$search_date_startday = GETPOST('search_date_startday', 'int'); +$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); +$search_date_startyear = GETPOST('search_date_startyear', 'int'); +$search_date_endday = GETPOST('search_date_endday', 'int'); +$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); +$search_date_endyear = GETPOST('search_date_endyear', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); +$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); +$search_company = GETPOST("search_company", 'alpha'); +$search_paymenttype = GETPOST("search_paymenttype"); +$search_account = GETPOST("search_account", "int"); +$search_payment_num = GETPOST('search_payment_num', 'alpha'); +$search_amount = GETPOST("search_amount", 'alpha'); +$search_status = GETPOST('search_status', 'intcomma'); +$search_sale = GETPOST('search_sale', 'int'); + $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); @@ -55,41 +74,39 @@ $sortorder = "DESC"; } if (!$sortfield) { - $sortfield = "d.datedon"; + $sortfield = "pd.rowid"; } -$search_status = (GETPOST("search_status", 'intcomma') != '') ? GETPOST("search_status", 'intcomma') : "-4"; -$search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); -$search_ref = GETPOST('search_ref', 'alpha'); -$search_thirdparty = GETPOST('search_thirdparty', 'alpha'); -$search_payment = GETPOST('search_payment', 'alpha'); -$search_amount = GETPOST('search_amount', 'alpha'); -$search_bank_account = GETPOST('search_bank_account', 'int'); -$optioncss = GETPOST('optioncss', 'alpha'); -$moreforfilter = GETPOST('moreforfilter', 'alpha'); - -if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // Both test are required to be compatible with all browsers - $search_all = ""; - $search_ref = ""; - $search_company = ""; - $search_thirdparty = ""; - $search_name = ""; - $search_payment = ""; - $search_amount = ""; - $search_status = ''; -} - -// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context -$hookmanager->initHooks(array('donationlist')); +$search_all = trim(GETPOSTISSET("search_all") ? GETPOST("search_all", 'alpha') : GETPOST('sall')); // List of fields to search into when doing a "search in all" $fieldstosearchall = array( - 'p.ref'=>"RefPayment", - 'p.num_payment'=>"Numero", + 'pd.rowid'=>"RefPayment", + 's.nom'=>"ThirdParty", + 'pd.num_paiement'=>"Numero", 'pd.amount'=>"Amount", ); +$arrayfields = array( + 'pd.rowid' => array('label'=>"RefPayment", 'checked'=>1, 'position'=>10), + 'pd.datep' => array('label'=>"Date", 'checked'=>1, 'position'=>20), + 's.nom' => array('label'=>"ThirdParty", 'checked'=>1, 'position'=>30), + 'c.code' => array('label'=>"Type", 'checked'=>1, 'position'=>40), + 'pd.num_paiement' => array('label'=>"Numero", 'checked'=>1, 'position'=>50, 'tooltip'=>"ChequeOrTransferNumber"), + 'transaction' => array('label'=>"BankTransactionLine", 'checked'=>1, 'position'=>60, 'enabled'=>(isModEnabled("banque"))), + 'ba.label' => array('label'=>"Account", 'checked'=>1, 'position'=>70, 'enabled'=>(isModEnabled("banque"))), + 'pd.amount' => array('label'=>"Amount", 'checked'=>1, 'position'=>80), +); +$arrayfields = dol_sort_array($arrayfields, 'position'); + +$optioncss = GETPOST('optioncss', 'alpha'); +$moreforfilter = GETPOST('moreforfilter', 'alpha'); + + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('donationlist')); + // Security check $result = restrictedArea($user, 'don'); @@ -101,15 +118,38 @@ * Actions */ - -if (GETPOST('cancel', 'alpha')) { - $action = 'list'; - $massaction = ''; -} -if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { - $massaction = ''; +$parameters = array('socid'=>$paiementid); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // All tests are required to be compatible with all browsers + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { + $search_ref = ''; + $search_date_startday = ''; + $search_date_startmonth = ''; + $search_date_startyear = ''; + $search_date_endday = ''; + $search_date_endmonth = ''; + $search_date_endyear = ''; + $search_date_start = ''; + $search_date_end = ''; + $search_account = ''; + $search_amount = ''; + $search_paymenttype = ''; + $search_payment_num = ''; + $search_company = ''; + $option = ''; + $toselect = array(); + $search_array_options = array(); + } } + /* * View */ @@ -132,6 +172,11 @@ $sql .= ' c.code as paiement_code, '; $sql .= ' d.rowid, ba.rowid as bid, ba.ref as bref, ba.label as blabel, ba.number, ba.account_number as account_number, ba.iban_prefix, ba.bic, ba.currency_code, ba.fk_accountancy_journal as accountancy_journal '; +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + $sqlfields = $sql; // $sql fields to remove for count total $sql .= " FROM ".MAIN_DB_PREFIX."payment_donation as pd"; @@ -140,29 +185,41 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank_account as ba ON (ba.rowid = b.fk_account)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON (s.rowid = d.fk_soc)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as c ON (c.id = pd.fk_typepayment)"; +$sql .= " WHERE d.entity IN (".getEntity('donation').")"; -if ($search_status != '' && $search_status != '-4') { - $sql .= " AND d.fk_statut IN (".$db->sanitize($search_status).")"; +if ($search_ref) { + $sql .= natural_search('pd.rowid', $search_ref); } -if (trim($search_ref) != '') { - $sql .= natural_search('pd.ref', $search_ref); +if ($search_date_start) { + $sql .= " AND pd.datep >= '" . $db->idate($search_date_start) . "'"; } -if (trim($search_all) != '') { - $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +if ($search_date_end) { + $sql .= " AND pd.datep <= '" . $db->idate($search_date_end) . "'"; } -if (trim($search_company) != '') { - $sql .= natural_search('d.societe', $search_company); +if ($search_account > 0) { + $sql .= " AND b.fk_account=".((int) $search_account); } -if ($search_bank_account > 0) { - $sql .= ' AND b.fk_account = '.((int) $search_bank_account); +if ($search_paymenttype != '') { + $sql .= " AND c.code='".$db->escape($search_paymenttype)."'"; } -if (trim($search_payment) != '') { - $sql .= natural_search("pd.rowid", $search_payment); +if ($search_payment_num != '') { + $sql .= natural_search('pd.num_payment', $search_payment_num); } if ($search_amount) { - $sql .= natural_search('d.amount', $search_amount, 1); + $sql .= natural_search('pd.amount', $search_amount, 1); +} +if ($search_company) { + $sql .= natural_search('s.nom', $search_company); +} + +if ($search_all) { + $sql .= natural_search(array_keys($fieldstosearchall), $search_all); } +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; // Count total nb of records $nbtotalofrecords = ''; @@ -185,6 +242,8 @@ $db->free($resql); } +$sql .= $db->order($sortfield, $sortorder); + // Complete request and execute it with limit if ($limit) { $sql .= $db->plimit($limit + 1, $offset); @@ -197,116 +256,91 @@ exit; } - - $num = $db->num_rows($resql); -// Direct jump if only one record found -if ($num == 1 && !getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) { - $obj = $db->fetch_object($resql); - $id = $obj->rowid; - header("Location: ".dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.$id); - exit; -} - - // Output page // -------------------------------------------------------------------- llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist'); // Can use also classforhorizontalscrolloftabs instead of bodyforlist for no horizontal scroll -// Example : Adding jquery code -// print ''; - -$arrayofselected = is_array($toselect) ? $toselect : array(); - $param = ''; -if (!empty($mode)) { - $param .= '&mode='.urlencode($mode); -} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.((int) $limit); } -if ($optioncss != '') { - $param .= '&optioncss='.urlencode($optioncss); -} + if ($search_ref) { $param .= '&search_ref='.urlencode($search_ref); } +if ($search_date_startday) { + $param .= '&search_date_startday='.urlencode($search_date_startday); +} +if ($search_date_startmonth) { + $param .= '&search_date_startmonth='.urlencode($search_date_startmonth); +} +if ($search_date_startyear) { + $param .= '&search_date_startyear='.urlencode($search_date_startyear); +} +if ($search_date_endday) { + $param .= '&search_date_endday='.urlencode($search_date_endday); +} +if ($search_date_endmonth) { + $param .= '&search_date_endmonth='.urlencode($search_date_endmonth); +} +if ($search_date_endyear) { + $param .= '&search_date_endyear='.urlencode($search_date_endyear); +} if ($search_company) { $param .= '&search_company='.urlencode($search_company); } -if ($search_payment) { - $param .= '&search_payment='.urlencode($search_payment); -} -if ($search_amount) { +if ($search_amount != '') { $param .= '&search_amount='.urlencode($search_amount); } - -// List of mass actions available -$arrayofmassactions = array( - //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"), - //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), - //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), - //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), -); -if (!empty($permissiontodelete)) { - $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +if ($search_paymenttype) { + $param .= '&search_paymenttype='.urlencode($search_paymenttype); } -if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { - $arrayofmassactions = array(); +if ($search_account) { + $param .= '&search_account='.urlencode($search_account); +} +if ($search_payment_num) { + $param .= '&search_payment_num='.urlencode($search_payment_num); +} +if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); } -$massactionbutton = $form->selectMassAction('', $arrayofmassactions); - -print '
'."\n"; +print ''; if ($optioncss != '') { print ''; } print ''; -print ''; print ''; +print ''; print ''; print ''; -print ''; print ''; -print ''; -print ''; -print ''; -print_barre_liste($langs->trans("DonationsReglement"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'object_donation', 0, $newcardbutton, '', $limit, 0, 0, 1); +print_barre_liste($langs->trans("ReceivedCustomersPayments"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'bill', 0, '', '', $limit, 0, 0, 1); if ($search_all) { - $setupstring = ''; foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); - $setupstring .= $key."=".$val.";"; } - print ''."\n"; print '
'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
'; } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields -$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields +$massactionbutton = ''; +if ($massactionbutton) { + $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); +} +$moreforfilter = ''; print '
'; -print ''."\n"; +print '
'; // Fields title search // -------------------------------------------------------------------- @@ -319,42 +353,85 @@ print ''; } -print ''; +if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER_IN_LIST')) { + print ''; +} + + +if (!empty($arrayfields['pd.rowid']['checked'])) { + print ''; +} + +// Filter: Date +if (!empty($arrayfields['pd.datep']['checked'])) { + print ''; +} +// Filter: Thirdparty +if (!empty($arrayfields['s.nom']['checked'])) { + print ''; +} -print ''; +// Filter: Payment type +if (!empty($arrayfields['c.code']['checked'])) { + print ''; +} -print ''; +// Filter: Bank transaction number +if (!empty($arrayfields['transaction']['checked'])) { + print ''; +} -print ''; +// Filter: Cheque number (fund transfer) +if (!empty($arrayfields['pd.num_paiement']['checked'])) { + print ''; +} -print ''; +// Filter: Bank account +if (!empty($arrayfields['ba.label']['checked'])) { + print ''; +} -print ''; +// Filter: Amount +if (!empty($arrayfields['pd.amount']['checked'])) { + print ''; +} -print ''; +// Fields from hook +$parameters = array('arrayfields'=>$arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; -print ''; +// Action column +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; +} +print ''."\n"; $totalarray = array(); $totalarray['nbfield'] = 0; @@ -364,33 +441,72 @@ print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print_liste_field_titre(''); + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + $totalarray['nbfield']++; +} +if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER_IN_LIST')) { + print_liste_field_titre('#', $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['pd.rowid']['checked'])) { + print_liste_field_titre($arrayfields['pd.rowid']['label'], $_SERVER["PHP_SELF"], "pd.rowid", '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['pd.datep']['checked'])) { + print_liste_field_titre($arrayfields['pd.datep']['label'], $_SERVER["PHP_SELF"], "pd.datep", '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['s.nom']['checked'])) { + print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['c.code']['checked'])) { + print_liste_field_titre($arrayfields['c.code']['label'], $_SERVER["PHP_SELF"], "c.code", '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['pd.num_paiement']['checked'])) { + print_liste_field_titre($arrayfields['pd.num_paiement']['label'], $_SERVER["PHP_SELF"], "pd.num_payment", '', $param, '', $sortfield, $sortorder, '', $arrayfields['p.num_paiement']['tooltip']); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['transaction']['checked'])) { + print_liste_field_titre($arrayfields['transaction']['label'], $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['ba.label']['checked'])) { + print_liste_field_titre($arrayfields['ba.label']['label'], $_SERVER["PHP_SELF"], "ba.label", '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; +} +if (!empty($arrayfields['pd.amount']['checked'])) { + print_liste_field_titre($arrayfields['pd.amount']['label'], $_SERVER["PHP_SELF"], "pd.amount", '', $param, '', $sortfield, $sortorder); $totalarray['nbfield']++; } -print_liste_field_titre("RefPayment", $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder); -$totalarray['nbfield']++; -print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "d.datedon", "", $param, '', $sortfield, $sortorder, ); -$totalarray['nbfield']++; -print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "d.fk_soc", "", $param, "", $sortfield, $sortorder,); -$totalarray['nbfield']++; -print_liste_field_titre("Type", $_SERVER["PHP_SELF"], "d.amount", "", $param, '', $sortfield, $sortorder); -$totalarray['nbfield']++; -print_liste_field_titre("Numero", $_SERVER["PHP_SELF"], "p.num_paiement", '', $param, '', $sortfield, $sortorder, '', "ChequeOrTransferNumber"); -$totalarray['nbfield']++; -print_liste_field_titre("BankTransactionLine", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder); -$totalarray['nbfield']++; -print_liste_field_titre("Account", $_SERVER["PHP_SELF"], "d.fk_statut", "", $param, '', $sortfield, $sortorder); -$totalarray['nbfield']++; -print_liste_field_titre("Amount", $_SERVER["PHP_SELF"], "d.fk_statut", "", $param, '', $sortfield, $sortorder); -$totalarray['nbfield']++; - +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print_liste_field_titre(''); + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); $totalarray['nbfield']++; } print ''."\n"; + +// Detect if we need a fetch on each output line +$needToFetchEachLine = 0; +if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { + foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) { + if (!is_null($val) && preg_match('/\$object/', $val)) { + $needToFetchEachLine++; // There is at least one compute field that use $object + } + } +} + +// Loop on record +// -------------------------------------------------------------------- $i = 0; $savnbfield = $totalarray['nbfield']; $totalarray = array(); @@ -408,61 +524,126 @@ print ''; if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - print ''; + // Ref + if (!empty($arrayfields['pd.rowid']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } - $dateformatforpayment = 'dayhour'; - print ''; + // Date + if (!empty($arrayfields['pd.datep']['checked'])) { + $dateformatforpayment = 'dayhour'; + print ''; - print ''; - if (!$i) { - $totalarray['nbfield']++; } - print ''; + // Thirdparty + if (!empty($arrayfields['s.nom']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } - print ''; - print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - print ''; - - print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } - $accountingjournal = new AccountingJournal($db); - $accountingjournal->fetch($obj->accountancy_journal); - $accountstatic->accountancy_journal = $accountingjournal->code; + // Bank transaction + if (!empty($arrayfields['transaction']['checked'])) { + print ''; + } - print $accountstatic->getNomUrl(1); + // Bank account + if (!empty($arrayfields['ba.label']['checked'])) { + print ''; + // Amount + if (!empty($arrayfields['pd.amount']['checked'])) { + print ''; + } $i++; } -print "
'; -print ''; -print ''; + print ''; + print ''; + print ''; + print '
'; + print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; + print '
'; + print ''; + print ''; -print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); -print ''; -print '
'; -print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); -print '
'; -print '
'; + print $form->select_types_paiements($search_paymenttype, 'search_paymenttype', '', 2, 1, 1, 0, 1, 'maxwidth100', 1); + print ''; -print ''; -print ''; + print ''; + print ''; -$form->select_types_paiements($search_payment_type, 'search_payment_type', '', 2, 1, 1); -print ''; + print ''; -print ''; -print ''; + $form->select_comptes($search_account, 'search_account', 0, '', 1); + print ''; + print ''; + print ''; -$form->select_comptes($search_bank_account, 'search_bank_account', 0, '', 1); -print ''; -print ''; -print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->id_paiement, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''.img_object($langs->trans("Payment"), "payment").' '.$obj->payment_id.'' . img_object($langs->trans("Payment"), "payment") . ' ' . $obj->payment_id . ''.dol_print_date($db->jdate($obj->datep), $dateformatforpayment, 'tzuser').''.dol_print_date($db->jdate($obj->datep), $dateformatforpayment, 'tzuser').''; - if ($obj->soc_id > 0) { - print $companystatic->getNomUrl(1, '', 24); - } else { - print $donationstatic->societe = $obj->societe; - } - print ''.$langs->trans("PaymentTypeShort".$obj->paiement_code).''; + if ($obj->soc_id > 0) { + print $companystatic->getNomUrl(1, '', 24); + } else { + print $donationstatic->societe = $obj->societe; + } + print ''.$obj->num_payment.''; - if ($obj->fk_bank > 0) { - $test = $bankline->fetch($obj->fk_bank); - print $bankline->getNomUrl(1, 0); + // Payment type + if (!empty($arrayfields['c.code']['checked'])) { + print ''.$langs->trans("PaymentTypeShort".$obj->paiement_code).''; - if ($obj->bid > 0) { - $accountstatic->id = $obj->bid; - $accountstatic->ref = $obj->bref; - $accountstatic->label = $obj->blabel; - $accountstatic->number = $obj->number; - $accountstatic->account_number = $obj->account_number; + // Filter: Cheque number (fund transfer) + if (!empty($arrayfields['pd.num_paiement']['checked'])) { + print ''.$obj->num_payment.''; + if ($obj->fk_bank > 0) { + $test = $bankline->fetch($obj->fk_bank); + print $bankline->getNomUrl(1, 0); + } + print ''; + if ($obj->bid > 0) { + $accountstatic->id = $obj->bid; + $accountstatic->ref = $obj->bref; + $accountstatic->label = $obj->blabel; + $accountstatic->number = $obj->number; + $accountstatic->account_number = $obj->account_number; + + $accountingjournal = new AccountingJournal($db); + $accountingjournal->fetch($obj->accountancy_journal); + $accountstatic->accountancy_journal = $accountingjournal->code; + + print $accountstatic->getNomUrl(1); + } } - print ''.price($obj->amount).'' . price($obj->amount) . '
"; -print '
'; -print "
\n"; +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''.$langs->trans("NoRecordFound").''; +} + $db->free($resql); +$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print ''."\n"; +print ''."\n"; + +print ''."\n"; + llxFooter(); $db->close(); From bcc46412cb4bf9f0c68e3bef985019138ca755d8 Mon Sep 17 00:00:00 2001 From: Thomas905 Date: Thu, 7 Dec 2023 08:56:29 +0100 Subject: [PATCH 03/60] change --- htdocs/don/paiement/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/don/paiement/list.php b/htdocs/don/paiement/list.php index db7e303b22eeb..4e06f34be7398 100644 --- a/htdocs/don/paiement/list.php +++ b/htdocs/don/paiement/list.php @@ -322,7 +322,7 @@ print ''; print ''; -print_barre_liste($langs->trans("ReceivedCustomersPayments"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'bill', 0, '', '', $limit, 0, 0, 1); +print_barre_liste($langs->trans("DonationsReglement"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'bill', 0, '', '', $limit, 0, 0, 1); if ($search_all) { foreach ($fieldstosearchall as $key => $val) { From b1216340eb2545dd47b1ac1d15c9acb975edba0e Mon Sep 17 00:00:00 2001 From: Thomas905 Date: Thu, 7 Dec 2023 09:07:31 +0100 Subject: [PATCH 04/60] add total line --- htdocs/don/paiement/list.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/htdocs/don/paiement/list.php b/htdocs/don/paiement/list.php index 4e06f34be7398..478136a94fc3c 100644 --- a/htdocs/don/paiement/list.php +++ b/htdocs/don/paiement/list.php @@ -550,7 +550,9 @@ if (!empty($arrayfields['pd.datep']['checked'])) { $dateformatforpayment = 'dayhour'; print ''.dol_print_date($db->jdate($obj->datep), $dateformatforpayment, 'tzuser').''; - + if (!$i) { + $totalarray['nbfield']++; + } } // Thirdparty @@ -592,6 +594,9 @@ print $bankline->getNomUrl(1, 0); } print ''; + if (!$i) { + $totalarray['nbfield']++; + } } // Bank account @@ -610,11 +615,23 @@ print $accountstatic->getNomUrl(1); } + if (!$i) { + $totalarray['nbfield']++; + } } // Amount if (!empty($arrayfields['pd.amount']['checked'])) { print '' . price($obj->amount) . ''; + if (!$i) { + $totalarray['nbfield']++; + $totalarray['pos'][$totalarray['nbfield']] = 'amount'; + } + if (empty($totalarray['val']['amount'])) { + $totalarray['val']['amount'] = $obj->amount; + } else { + $totalarray['val']['amount'] += $obj->amount; + } } $i++; From 7298af5f06fe7e152b1e56817ae922d3c403d964 Mon Sep 17 00:00:00 2001 From: Thomas905 Date: Thu, 7 Dec 2023 09:13:57 +0100 Subject: [PATCH 05/60] indent --- htdocs/don/paiement/list.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/htdocs/don/paiement/list.php b/htdocs/don/paiement/list.php index 478136a94fc3c..4f9b91530a20d 100644 --- a/htdocs/don/paiement/list.php +++ b/htdocs/don/paiement/list.php @@ -79,7 +79,6 @@ $search_all = trim(GETPOSTISSET("search_all") ? GETPOST("search_all", 'alpha') : GETPOST('sall')); - // List of fields to search into when doing a "search in all" $fieldstosearchall = array( 'pd.rowid'=>"RefPayment", @@ -103,7 +102,6 @@ $optioncss = GETPOST('optioncss', 'alpha'); $moreforfilter = GETPOST('moreforfilter', 'alpha'); - // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('donationlist')); @@ -149,7 +147,6 @@ } } - /* * View */ @@ -163,7 +160,6 @@ $title = $langs->trans("Donations"); $help_url = 'EN:Module_Donations|FR:Module_Dons|ES:Módulo_Donaciones|DE:Modul_Spenden'; - // Build and execute select // -------------------------------------------------------------------- $sql = "SELECT pd.rowid as payment_id, pd.amount, pd.datep, pd.fk_typepayment, pd.num_payment, pd.amount, pd.fk_bank, "; @@ -211,7 +207,6 @@ if ($search_company) { $sql .= natural_search('s.nom', $search_company); } - if ($search_all) { $sql .= natural_search(array_keys($fieldstosearchall), $search_all); } @@ -270,7 +265,6 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.((int) $limit); } - if ($search_ref) { $param .= '&search_ref='.urlencode($search_ref); } @@ -358,7 +352,6 @@ print ''; } - if (!empty($arrayfields['pd.rowid']['checked'])) { print ''; print ''; @@ -494,7 +487,6 @@ } print ''."\n"; - // Detect if we need a fetch on each output line $needToFetchEachLine = 0; if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { @@ -513,7 +505,6 @@ $totalarray['nbfield'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); while ($i < $imaxinloop) { - $obj = $db->fetch_object($resql); $companystatic->id = $obj->soc_id; @@ -569,7 +560,6 @@ } } - // Payment type if (!empty($arrayfields['c.code']['checked'])) { print ''.$langs->trans("PaymentTypeShort".$obj->paiement_code).''; From cc70f0defa0c0e7aa2ead0afa9562a7d00961203 Mon Sep 17 00:00:00 2001 From: Thomas905 Date: Thu, 7 Dec 2023 09:44:27 +0100 Subject: [PATCH 06/60] fix menu left --- htdocs/core/menus/standard/eldy.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index a17c23f06acaa..d1fb4605a9fa6 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1548,7 +1548,7 @@ function get_left_menu_billing($mainmenu, &$newmenu, $usemenuhider = 1, $leftmen if ($usemenuhider || empty($leftmenu) || $leftmenu == "donations") { $newmenu->add("/don/card.php?leftmenu=donations&action=create", $langs->trans("NewDonation"), 1, $user->hasRight('don', 'creer')); $newmenu->add("/don/list.php?leftmenu=donations", $langs->trans("List"), 1, $user->hasRight('don', 'lire')); - $newmenu->add("/don/paiement/list.php", $langs->trans("Payments"), 1, $user->hasRight('don', 'lire')); + $newmenu->add("/don/paiement/list.php?leftmenu=donations", $langs->trans("Payments"), 1, $user->hasRight('don', 'lire')); } // if ($leftmenu=="donations") $newmenu->add("/don/stats/index.php",$langs->trans("Statistics"), 1, $user->hasRight('don', 'lire')); } From 4d7a256d0d828b24ce52f4b71cb0b3d0ea6c3732 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 10 Dec 2023 07:26:02 +0100 Subject: [PATCH 07/60] NEW Supplier Invoice - List - Selector with choice on ECC country --- htdocs/fourn/facture/list.php | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index a65fca4d55c3b..eb2e8a59db352 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -12,7 +12,7 @@ * Copyright (C) 2017 Josep Lluís Amador * Copyright (C) 2018-2022 Charlene Benke * Copyright (C) 2018-2020 Frédéric France - * Copyright (C) 2019-2021 Alexandre Spangaro + * Copyright (C) 2019-2023 Alexandre Spangaro * Copyright (C) 2023 Nick Fragoulis * * This program is free software; you can redistribute it and/or modify @@ -88,7 +88,7 @@ $search_town = GETPOST('search_town', 'alpha'); $search_zip = GETPOST('search_zip', 'alpha'); $search_state = GETPOST("search_state"); -$search_country = GETPOST("search_country", 'int'); +$search_country = GETPOST("search_country", 'alpha'); $search_type_thirdparty = GETPOST("search_type_thirdparty", 'int'); $search_user = GETPOST('search_user', 'int'); $search_sale = GETPOST('search_sale', 'int'); @@ -530,8 +530,26 @@ if ($search_state) { $sql .= natural_search("state.nom", $search_state); } -if ($search_country) { - $sql .= " AND s.fk_pays IN (".$db->sanitize($search_country).')'; +if (strlen(trim($search_country))) { + $arrayofcode = getCountriesInEEC(); + $country_code_in_EEC = $country_code_in_EEC_without_me = ''; + foreach ($arrayofcode as $key => $value) { + $country_code_in_EEC .= ($country_code_in_EEC ? "," : "")."'".$value."'"; + if ($value != $mysoc->country_code) { + $country_code_in_EEC_without_me .= ($country_code_in_EEC_without_me ? "," : "")."'".$value."'"; + } + } + if ($search_country == 'special_allnotme') { + $sql .= " AND country.code <> '".$db->escape($mysoc->country_code)."'"; + } elseif ($search_country == 'special_eec') { + $sql .= " AND country.code IN (".$db->sanitize($country_code_in_EEC, 1).")"; + } elseif ($search_country == 'special_eecnotme') { + $sql .= " AND country.code IN (".$db->sanitize($country_code_in_EEC_without_me, 1).")"; + } elseif ($search_country == 'special_noteec') { + $sql .= " AND country.code NOT IN (".$db->sanitize($country_code_in_EEC, 1).")"; + } else { + $sql .= natural_search("country.code", $search_country); + } } if ($search_type_thirdparty != '' && $search_type_thirdparty >= 0) { $sql .= " AND s.fk_typent IN (".$db->sanitize($search_type_thirdparty).')'; @@ -1138,7 +1156,7 @@ // Country if (!empty($arrayfields['country.code_iso']['checked'])) { print ''; - print $form->select_country($search_country, 'search_country', '', 0, 'minwidth100imp maxwidth100'); + print $form->select_country($search_country, 'search_country', '', 0, 'minwidth150imp maxwidth150', 'code2', 1, 0, 1, null, 1); print ''; } // Company type From 3aedcd46a2cb97dd09fe34f0264950470e06e5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charl=C3=A8ne=20Benke?= <1179011+defrance@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:00:22 +0100 Subject: [PATCH 08/60] add some bank info on odt --- htdocs/core/class/commondocgenerator.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index e211cd631d04f..074280e584c64 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -616,6 +616,9 @@ public function get_substitutionarray_object($object, $outputlangs, $array_key = $resarray[$array_key.'_bank_label'] = (empty($bank_account) ? '' : $bank_account->label); $resarray[$array_key.'_bank_number'] = (empty($bank_account) ? '' : $bank_account->number); $resarray[$array_key.'_bank_proprio'] =(empty($bank_account) ? '' : $bank_account->proprio); + $resarray[$array_key.'_bank_address'] =(empty($bank_account) ? '' : $bank_account->address); + $resarray[$array_key.'_bank_state'] =(empty($bank_account) ? '' : $bank_account->state); + $resarray[$array_key.'_bank_country'] =(empty($bank_account) ? '' : $bank_account->country); } if (method_exists($object, 'getTotalDiscount') && in_array(get_class($object), array('Propal', 'Proposal', 'Commande', 'Facture', 'SupplierProposal', 'CommandeFournisseur', 'FactureFournisseur'))) { From f351633c3a24b72191ed9872ebe49ce724abf23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charl=C3=A8ne=20Benke?= <1179011+defrance@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:53:04 +0100 Subject: [PATCH 09/60] fix warning error on empty extrafields --- htdocs/core/class/commondocgenerator.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 074280e584c64..9de3ef4fa4ebb 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -947,7 +947,7 @@ public function fill_substitutionarray_with_extrafields($object, $array_to_fill, // phpcs:enable global $conf; - if (is_array($extrafields->attributes[$object->table_element]['label'])) { + if ($extrafields->attributes[$object->table_element]['count'] > 0){ foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $label) { $formatedarrayoption = $object->array_options; From c4b4ada8be0e967bb6404aa3101283b5e707a4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charl=C3=A8ne=20Benke?= <1179011+defrance@users.noreply.github.com> Date: Mon, 11 Dec 2023 12:07:33 +0100 Subject: [PATCH 10/60] Update commondocgenerator.class.php --- htdocs/core/class/commondocgenerator.class.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 9de3ef4fa4ebb..9a67aa355428b 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -811,10 +811,11 @@ public function get_substitutionarray_lines($line, $outputlangs, $linenumber = 0 } else { // Set unused placeholders as blank $extrafields->fetch_name_optionals_label("product"); - $extralabels = $extrafields->attributes["product"]['label']; - - foreach ($extralabels as $key => $label) { - $resarray['line_product_options_'.$key] = ''; + if ($extrafields->attributes["product"]['count'] > 0) { + $extralabels = $extrafields->attributes["product"]['label']; + foreach ($extralabels as $key => $label) { + $resarray['line_product_options_'.$key] = ''; + } } } @@ -947,7 +948,7 @@ public function fill_substitutionarray_with_extrafields($object, $array_to_fill, // phpcs:enable global $conf; - if ($extrafields->attributes[$object->table_element]['count'] > 0){ + if ($extrafields->attributes[$object->table_element]['count'] > 0) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $label) { $formatedarrayoption = $object->array_options; From b31c1e77fd1208b87329215c2d7fd3cbf22173a1 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 11 Dec 2023 17:52:46 +0100 Subject: [PATCH 11/60] New functionality for ovewrite modification in template --- htdocs/website/class/website.class.php | 75 +++++++++++++++++++++++++- htdocs/website/index.php | 10 ++++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index f5a4ec292bd88..edc5d9e9c95b1 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -140,6 +140,10 @@ class Website extends CommonObject */ public $lines; + /** + * @var string name of template + */ + public $name_template; const STATUS_DRAFT = 0; const STATUS_VALIDATED = 1; @@ -331,7 +335,8 @@ public function fetch($id, $ref = null) $sql .= " t.fk_user_creat,"; $sql .= " t.fk_user_modif,"; $sql .= " t.date_creation,"; - $sql .= " t.tms as date_modification"; + $sql .= " t.tms as date_modification,"; + $sql .= " t.name_template"; $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; $sql .= " WHERE t.entity IN (".getEntity('website').")"; if (!empty($ref)) { @@ -362,6 +367,7 @@ public function fetch($id, $ref = null) $this->fk_user_modif = $obj->fk_user_modif; $this->date_creation = $this->db->jdate($obj->date_creation); $this->date_modification = $this->db->jdate($obj->date_modification); + $this->name_template = $obj->name_template; } $this->db->free($resql); @@ -955,7 +961,6 @@ public function exportWebSite() } $destdir = $conf->website->dir_temp.'/'.$website->ref; - dol_syslog("Clear temp dir ".$destdir); $count = 0; $countreallydeleted = 0; @@ -1605,4 +1610,70 @@ public function componentSelectLang($languagecodes, $weblangs, $morecss = '', $h return $out; } + + /** + * Overite template by copy and past all files + * @return int 1 if OK, -1 if KO + */ + public function overwriteTemplate() + { + global $conf; + + $website = $this; + if (empty($website->id) || empty($website->ref)) { + setEventMessages("Website id or ref is not defined", null, 'errors'); + return false; + } + + $pathToInstallDir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.urlencode($website->name_template); + + //check if can write in + if (!is_writable($pathToInstallDir)) { + if (is_readable($pathToInstallDir)) { + $files = scandir($pathToInstallDir); + $x =''; + foreach ($files as $file) { + $x .= $file . "\n"; + } + } else { + setEventMessages("Install dir ".$pathToInstallDir." is not readable", null, 'errors'); + return false; + } + } + + $srcdir = $conf->website->dir_output.'/'.$website->ref; + $destdir = $conf->install->dir_templates; + + dol_syslog("Copy templates from ".$srcdir." into ".$destdir); + $result = dolCopyDir($srcdir, $destdir, 0, 1); + + if ($result < 0) { + setEventMessages("Failed to copy templates", null, 'errors'); + var_dump(2); + } + + setEventMessages("Templates successfully overwritten", null, 'messages'); + return true; + } + + /** + * update name_template in table after import template + * @param string $name_template name of template + * @return int 1 if OK, -1 if KO + */ + public function setTemplateName($name_template) + { + $sql = "UPDATE ".$this->db->prefix()."website SET"; + $sql .= " name_template = '".$this->db->escape($name_template)."'"; + $sql .= " WHERE rowid = ".(int) $this->id; + $result = $this->db->query($sql); + //print_r($sql);exit; + if ($result) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } } diff --git a/htdocs/website/index.php b/htdocs/website/index.php index aa7ea1f78e7be..5a65a52f4c5ca 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2417,6 +2417,11 @@ } } +// Overite site +if ($action == 'overwitesite' && $user->hasRight('website', 'export')) { + $fileofzip = $object->overwriteTemplate(); + var_dump($fileofzip); +} // Regenerate site if ($action == 'regeneratesite' && $usercanedit) { // Check symlink to medias and restore it if ko. Recreate also dir of website if not found. @@ -2517,6 +2522,9 @@ } if (!$error && GETPOSTISSET('templateuserfile')) { + $templatewithoutzip = preg_replace('/\.zip$/i', '', GETPOST('templateuserfile')); + $object->setTemplateName($templatewithoutzip); + $result = $object->importWebSite($fileofzip); if ($result < 0) { @@ -3054,6 +3062,8 @@ print ''; } + // overite template + print 'ref).'" class="button bordertransp"> '.dol_escape_htmltag($langs->trans("Overwrite")).''; } else { print ''; } From 20a912ff707e52a6707990754297692a6e7822a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Fali=C3=A8re?= Date: Wed, 13 Dec 2023 16:04:27 +0100 Subject: [PATCH 12/60] ADD ticket subject on emails --- htdocs/core/class/html.formticket.class.php | 2 +- htdocs/ticket/class/ticket.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index fe0f6c71e1f69..506e78fa925a4 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -1498,7 +1498,7 @@ public function showMessageForm($width = '40%') } print ''.$langs->trans('Subject').''; if (empty($topic)) { - print 'ref.'] '.$langs->trans('TicketNewMessage').'" />'; + print 'ref. ': ' . $ticketstat->subject . '] ' .$langs->trans('TicketNewMessage') . '" />'; } else { print 'ref.'] '.$topic.'" />'; } diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 198d8f7ce3c3f..8f4f3cb0992f7 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2648,7 +2648,7 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) if (!empty($sendto)) { $appli = getDolGlobalString('MAIN_APPLICATION_TITLE', $mysoc->name); - $subject = '['.$appli.'- ticket #'.$object->track_id.'] '.$langs->trans('TicketNewMessage'); + $subject = '['.$appli.'- ticket #'.$object->track_id.': ' . $this->subject . '] '.$langs->trans('TicketNewMessage'); // Message send $message = $langs->trans('TicketMessageMailIntroText'); From aaba4b823bb46424cccd43fb2a9f68022eb0d3e6 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 15 Dec 2023 18:17:51 +0100 Subject: [PATCH 13/60] add function for copy file when detected changes --- htdocs/website/class/website.class.php | 163 +++++++++++++++++++++---- htdocs/website/index.php | 4 +- 2 files changed, 141 insertions(+), 26 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index edc5d9e9c95b1..a4a839acaded0 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1182,7 +1182,6 @@ public function importWebSite($pathtofile) $error = 0; $pathtofile = dol_sanitizePathName($pathtofile); - $object = $this; if (empty($object->ref)) { $this->error = 'Function importWebSite called on object not loaded (object->ref is empty)'; @@ -1625,35 +1624,83 @@ public function overwriteTemplate() return false; } - $pathToInstallDir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.urlencode($website->name_template); + if (!is_writable($conf->website->dir_output)) { + setEventMessages("Temporary dir ".$conf->website->dir_output." is not writable", null, 'errors'); + return ''; + } + + $sourcedir = $conf->website->dir_output."/".$website->ref; - //check if can write in - if (!is_writable($pathToInstallDir)) { - if (is_readable($pathToInstallDir)) { - $files = scandir($pathToInstallDir); - $x =''; - foreach ($files as $file) { - $x .= $file . "\n"; + $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; + + // Copier le fichier zip dans le dossier de destination + + if (is_dir($destdir) && is_dir($sourcedir)) { + $arraydestdir = dol_dir_list($destdir, "all", 0, '', '', 'name', SORT_ASC); + $arraysourcedir = dol_dir_list($sourcedir, "all", 1, '', '', 'name', SORT_ASC); + } + $destinationFileNames = array_column($arraydestdir, 'name'); + // var_dump($arraysourcedir);exit; + foreach ($arraysourcedir as $sourceFile) { + if ($this->extractNumberFromFilename($sourceFile['fullname']) > 1) { + if (!preg_match('/\.old$/', $sourceFile['name'])) { + $arraySource[] = $sourceFile['fullname']; } - } else { - setEventMessages("Install dir ".$pathToInstallDir." is not readable", null, 'errors'); - return false; } } + // for extract pages in destination folder + foreach ($arraydestdir as $destFile) { + if ($destFile['name'] == 'containers') { + $containersDir = dol_dir_list($destFile['fullname']); - $srcdir = $conf->website->dir_output.'/'.$website->ref; - $destdir = $conf->install->dir_templates; + foreach ($containersDir as $file) { + $extractPageFromDestDir = $this->extractNumberFromFilename($file['fullname']); + if ($extractPageFromDestDir > 1) { + $arrayDest[] = $file['fullname']; + } + } + } + } - dol_syslog("Copy templates from ".$srcdir." into ".$destdir); - $result = dolCopyDir($srcdir, $destdir, 0, 1); + $minCount = min(count($arraySource), count($arrayDest)); + for ($i = 0; $i < $minCount; $i++) { + $sourceFilePath = $arraySource[$i]; + $destFilePath = $arrayDest[$i]; - if ($result < 0) { - setEventMessages("Failed to copy templates", null, 'errors'); - var_dump(2); + $sourceContent = file_get_contents($sourceFilePath); + if ($sourceContent === false) { + echo "Erreur lors de la lecture du fichier source: " . basename($sourceFilePath) . "\n"; + } else { + $destContent = file_get_contents($destFilePath); + if ($destContent === false) { + echo "Erreur lors de la lecture du fichier de destination: " . basename($destFilePath) . "\n"; + } else { + if ($sourceContent !== $destContent) { + $numPage = $this->extractNumberFromFilename($sourceFilePath); + + $differences = $this->showDifferences($sourceContent, $destContent, $numPage); + + //var_dump($differences); + //var_dump($arrayreplacement); + // Les contenus sont différents, effectuer la copie + + if (file_put_contents($destFilePath, $sourceContent) === false) { + echo "Échec de la copie du fichier: " . basename($sourceFilePath) . "\n"; + } else { + if (count($differences) > 0) { + $result = dolReplaceInFile($destFilePath, $differences); + if ($result > 0) { + echo 'rename with correct number page'; + } + echo "Fichier copié avec succès: " . basename($sourceFilePath) . "\n"; + } + } + } else { + echo "Aucune modification détectée, copie non nécessaire pour: " . basename($sourceFilePath) . "\n"; + } + } + } } - - setEventMessages("Templates successfully overwritten", null, 'messages'); - return true; } /** @@ -1667,7 +1714,7 @@ public function setTemplateName($name_template) $sql .= " name_template = '".$this->db->escape($name_template)."'"; $sql .= " WHERE rowid = ".(int) $this->id; $result = $this->db->query($sql); - //print_r($sql);exit; + if ($result) { $this->db->commit(); return 1; @@ -1676,4 +1723,74 @@ public function setTemplateName($name_template) return -1; } } + + /** + * extract num of page + * @param string $filename name of file + * @return int 1 if OK, -1 if KO + */ + protected function extractNumberFromFilename($filename) + { + $matches = []; + if (preg_match('/page(\d+)\.tpl\.php/', $filename, $matches)) { + return (int) $matches[1]; + } + return -1; + } + + /** + * remove espace in string + * @param string $str string + * @return string + */ + protected function normalizeString($str) + { + + $str = str_replace("\r\n", "\n", $str); + $str = str_replace("\r", "\n", $str); + + $lines = explode("\n", $str); + $lines = array_map('trim', $lines); + + return implode("\n", $lines); + } + + /** + * show difference between to string + * @param string $str1 first string + * @param string $str2 seconde string + * @param string $exceptNumPge num of page file + * @return array|int -1 if KO, array if OK + */ + protected function showDifferences($str1, $str2, $exceptNumPge = '0') + { + $diff = []; + $str1 = $this->normalizeString($str1); + $str2 = $this->normalizeString($str2); + + $lines1 = explode("\n", $str1); + $lines2 = explode("\n", $str2); + + foreach ($lines1 as $lineNum => $lineContent) { + if (isset($lines2[$lineNum])) { + if ($lineContent !== $lines2[$lineNum]) { + $diff[$lines2[$lineNum]] = $lineContent; + } + } else { + $diff['new'] = "line " . ($lineNum + 1) . ": " . $lineContent; + } + } + foreach ($lines2 as $lineNum => $lineContent) { + if (!isset($lines1[$lineNum])) { + $diff[] = "Supplémentaire dans la destination à la ligne " . ($lineNum + 1) . ": " . $lineContent; + } + } + // search if except exist in array + foreach ($diff as $key => $line) { + if (str_contains($line, $exceptNumPge)) { + $lineNochange[$line] = $key; + } + } + return $lineNochange; + } } diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 5a65a52f4c5ca..0fb360f0755cb 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2399,12 +2399,11 @@ } // Export site -if ($action == 'exportsite' && $user->hasRight('website', 'export')) { +if ($action == 'exportsite') { $fileofzip = $object->exportWebSite(); if ($fileofzip) { $file_name = basename($fileofzip); - header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=".$file_name); header("Content-Length: ".filesize($fileofzip)); @@ -2420,7 +2419,6 @@ // Overite site if ($action == 'overwitesite' && $user->hasRight('website', 'export')) { $fileofzip = $object->overwriteTemplate(); - var_dump($fileofzip); } // Regenerate site if ($action == 'regeneratesite' && $usercanedit) { From 88a72050fe6c6e8ff9f7c7858670bcf47eb50d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Fali=C3=A8re?= Date: Mon, 18 Dec 2023 09:45:09 +0100 Subject: [PATCH 14/60] Modify subject structure --- htdocs/core/class/html.formticket.class.php | 2 +- htdocs/ticket/class/ticket.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index d606faea719a8..6a3435e5d4e81 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -1498,7 +1498,7 @@ public function showMessageForm($width = '40%') } print ''.$langs->trans('Subject').''; if (empty($topic)) { - print 'ref. ': ' . $ticketstat->subject . '] ' .$langs->trans('TicketNewMessage') . '" />'; + print 'ref.'] '. $ticketstat->subject .'" />'; } else { print 'ref.'] '.$topic.'" />'; } diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 8f4f3cb0992f7..ff93d78ed7992 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2648,7 +2648,7 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) if (!empty($sendto)) { $appli = getDolGlobalString('MAIN_APPLICATION_TITLE', $mysoc->name); - $subject = '['.$appli.'- ticket #'.$object->track_id.': ' . $this->subject . '] '.$langs->trans('TicketNewMessage'); + $subject = '['.$appli.'- ticket #'.$object->track_id.'] '.$this->subject; // Message send $message = $langs->trans('TicketMessageMailIntroText'); From 0e564736203595b6ab3e18a37504b4617c01506a Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 18 Dec 2023 18:13:50 +0100 Subject: [PATCH 15/60] update function for overwrite folder --- htdocs/website/class/website.class.php | 155 +++---------------------- 1 file changed, 19 insertions(+), 136 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index a4a839acaded0..a8ac86c75d47f 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1623,83 +1623,36 @@ public function overwriteTemplate() setEventMessages("Website id or ref is not defined", null, 'errors'); return false; } - - if (!is_writable($conf->website->dir_output)) { - setEventMessages("Temporary dir ".$conf->website->dir_output." is not writable", null, 'errors'); + if (!is_writable($conf->website->dir_temp)) { + setEventMessages("Temporary dir ".$conf->website->dir_temp." is not writable", null, 'errors'); return ''; } - $sourcedir = $conf->website->dir_output."/".$website->ref; - $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; - // Copier le fichier zip dans le dossier de destination - - if (is_dir($destdir) && is_dir($sourcedir)) { - $arraydestdir = dol_dir_list($destdir, "all", 0, '', '', 'name', SORT_ASC); - $arraysourcedir = dol_dir_list($sourcedir, "all", 1, '', '', 'name', SORT_ASC); - } - $destinationFileNames = array_column($arraydestdir, 'name'); - // var_dump($arraysourcedir);exit; - foreach ($arraysourcedir as $sourceFile) { - if ($this->extractNumberFromFilename($sourceFile['fullname']) > 1) { - if (!preg_match('/\.old$/', $sourceFile['name'])) { - $arraySource[] = $sourceFile['fullname']; - } - } + $filename = $this->exportWebSite(); + if (!is_writable($destdir)) { + setEventMessages("Error to write in folder".$destdir, null, 'errors'); + return ''; } - // for extract pages in destination folder - foreach ($arraydestdir as $destFile) { - if ($destFile['name'] == 'containers') { - $containersDir = dol_dir_list($destFile['fullname']); + $destfile = $destdir.'/'.basename($filename); - foreach ($containersDir as $file) { - $extractPageFromDestDir = $this->extractNumberFromFilename($file['fullname']); - if ($extractPageFromDestDir > 1) { - $arrayDest[] = $file['fullname']; - } - } + // Copier le fichier zip dans le dossier de destination + if (file_exists($filename)) { + if (!copy($filename, $destfile)) { + setEventMessages("Failed to copy zip file to destination directory", null, 'errors'); + return ''; } } - $minCount = min(count($arraySource), count($arrayDest)); - for ($i = 0; $i < $minCount; $i++) { - $sourceFilePath = $arraySource[$i]; - $destFilePath = $arrayDest[$i]; + $result = dol_uncompress($destfile, $destdir.'/'); - $sourceContent = file_get_contents($sourceFilePath); - if ($sourceContent === false) { - echo "Erreur lors de la lecture du fichier source: " . basename($sourceFilePath) . "\n"; - } else { - $destContent = file_get_contents($destFilePath); - if ($destContent === false) { - echo "Erreur lors de la lecture du fichier de destination: " . basename($destFilePath) . "\n"; - } else { - if ($sourceContent !== $destContent) { - $numPage = $this->extractNumberFromFilename($sourceFilePath); - - $differences = $this->showDifferences($sourceContent, $destContent, $numPage); - - //var_dump($differences); - //var_dump($arrayreplacement); - // Les contenus sont différents, effectuer la copie - - if (file_put_contents($destFilePath, $sourceContent) === false) { - echo "Échec de la copie du fichier: " . basename($sourceFilePath) . "\n"; - } else { - if (count($differences) > 0) { - $result = dolReplaceInFile($destFilePath, $differences); - if ($result > 0) { - echo 'rename with correct number page'; - } - echo "Fichier copié avec succès: " . basename($sourceFilePath) . "\n"; - } - } - } else { - echo "Aucune modification détectée, copie non nécessaire pour: " . basename($sourceFilePath) . "\n"; - } - } - } + if (!empty($result['error'])) { + setEventMessages('Failed to unzip file '.$destfile.'.', null, 'errors'); + return -1; + } else { + dol_delete_file($destfile); + return 1; } } @@ -1723,74 +1676,4 @@ public function setTemplateName($name_template) return -1; } } - - /** - * extract num of page - * @param string $filename name of file - * @return int 1 if OK, -1 if KO - */ - protected function extractNumberFromFilename($filename) - { - $matches = []; - if (preg_match('/page(\d+)\.tpl\.php/', $filename, $matches)) { - return (int) $matches[1]; - } - return -1; - } - - /** - * remove espace in string - * @param string $str string - * @return string - */ - protected function normalizeString($str) - { - - $str = str_replace("\r\n", "\n", $str); - $str = str_replace("\r", "\n", $str); - - $lines = explode("\n", $str); - $lines = array_map('trim', $lines); - - return implode("\n", $lines); - } - - /** - * show difference between to string - * @param string $str1 first string - * @param string $str2 seconde string - * @param string $exceptNumPge num of page file - * @return array|int -1 if KO, array if OK - */ - protected function showDifferences($str1, $str2, $exceptNumPge = '0') - { - $diff = []; - $str1 = $this->normalizeString($str1); - $str2 = $this->normalizeString($str2); - - $lines1 = explode("\n", $str1); - $lines2 = explode("\n", $str2); - - foreach ($lines1 as $lineNum => $lineContent) { - if (isset($lines2[$lineNum])) { - if ($lineContent !== $lines2[$lineNum]) { - $diff[$lines2[$lineNum]] = $lineContent; - } - } else { - $diff['new'] = "line " . ($lineNum + 1) . ": " . $lineContent; - } - } - foreach ($lines2 as $lineNum => $lineContent) { - if (!isset($lines1[$lineNum])) { - $diff[] = "Supplémentaire dans la destination à la ligne " . ($lineNum + 1) . ": " . $lineContent; - } - } - // search if except exist in array - foreach ($diff as $key => $line) { - if (str_contains($line, $exceptNumPge)) { - $lineNochange[$line] = $key; - } - } - return $lineNochange; - } } From 8c8404f32ffca72418f21f4ba0d44dcc71f86158 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 22 Dec 2023 17:47:19 +0100 Subject: [PATCH 16/60] update function --- htdocs/website/class/website.class.php | 305 +++++++++++++++++++++++-- 1 file changed, 285 insertions(+), 20 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index a8ac86c75d47f..e872e00ee1e4e 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1317,7 +1317,7 @@ public function importWebSite($pathtofile) // Regenerate index 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); - + $this->initFilesStatus($pathofwebsite); if ($error) { $this->db->rollback(); return -1; @@ -1612,7 +1612,7 @@ public function componentSelectLang($languagecodes, $weblangs, $morecss = '', $h /** * Overite template by copy and past all files - * @return int 1 if OK, -1 if KO + * @return void */ public function overwriteTemplate() { @@ -1628,32 +1628,103 @@ public function overwriteTemplate() return ''; } - $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; + $sourcedir = $conf->website->dir_output."/".$website->ref; - $filename = $this->exportWebSite(); - if (!is_writable($destdir)) { - setEventMessages("Error to write in folder".$destdir, null, 'errors'); - return ''; - } - $destfile = $destdir.'/'.basename($filename); + $fichierEtat = $sourcedir . '/etat_fichiers.txt'; + + $etatPrecedent = $this->checkPreviousState($fichierEtat); - // Copier le fichier zip dans le dossier de destination - if (file_exists($filename)) { - if (!copy($filename, $destfile)) { - setEventMessages("Failed to copy zip file to destination directory", null, 'errors'); - return ''; + $arraySourcedir = dol_dir_list($sourcedir); + + $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; } - $result = dol_uncompress($destfile, $destdir.'/'); + // listed modified files - if (!empty($result['error'])) { - setEventMessages('Failed to unzip file '.$destfile.'.', null, 'errors'); - return -1; + $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; + $arraydestdir = dol_dir_list($destdir, "all", 1); + $differences = []; + + if (count($modifications) >1) { + foreach ($modifications as $fichierModifie) { + $nomFichierModifie = $fichierModifie['name']; + if ($nomFichierModifie == basename($fichierEtat)) { + continue; + } + + // Find the corresponding file in the destination folder + foreach ($arraydestdir as $destFile) { + if ($destFile['name'] == $nomFichierModifie) { + $sourceContent = file_get_contents($fichierModifie['fullname']); + $destContent = file_get_contents($destFile['fullname']); + + if ($sourceContent !== $destContent) { + $numPage = $this->extractNumberFromFilename($fichierModifie['fullname']); + $differences[$nomFichierModifie] = $this->showDifferences($destContent, $sourceContent, $numPage); + + if (count($differences[$nomFichierModifie]) > 0) { + $result = $this->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); + if ($result !== false) { + setEventMessages("file ".$nomFichierModifie." was modified", null, 'warnings'); + } else { + setEventMessages("file ".$nomFichierModifie." was not modified", null, 'errors'); + } + } + } + } else { + // TO DO when file has not same name + // $succes = 0; + // $differences[$nomFichierModifie] = $this->compareFichierModifie($sourcedir, $destdir, $fichierModifie); + + // if (count($differences[$nomFichierModifie]) > 0) { + // $result = $this->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); + // if ($result !== false) { + // $succes++; + // } else { + // setEventMessages("file ".$nomFichierModifie." was not modified", null, 'errors'); + // } + // } + } + } + // if ($succes) { + // setEventMessages("file ".$nomFichierModifie." was modified", null, 'warnings'); + // } + } } else { - dol_delete_file($destfile); - return 1; + setEventMessages("No files was modified", null, 'warnings'); } + + // save state file + $this->saveState($etatPrecedent, $fichierEtat); + + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); + exit(); + } + + /** + * extract num of page + * @param string $filename name of file + * @return int 1 if OK, -1 if KO + */ + protected function extractNumberFromFilename($filename) + { + $matches = []; + if (preg_match('/page(\d+)\.tpl\.php/', $filename, $matches)) { + return (int) $matches[1]; + } + return -1; } /** @@ -1676,4 +1747,198 @@ public function setTemplateName($name_template) return -1; } } + + /** + * check previous state for file + * @param string $pathname path of file + * @return array|mixed + */ + public function checkPreviousState($pathname) + { + if (!file_exists($pathname)) { + if (touch($pathname)) { + dolChmod($pathname, '0664'); + } + return []; + } + return unserialize(file_get_contents($pathname)); + } + + + /** + * Save state for File + * @param mixed $etat state + * @param mixed $pathname path of file + * @return int|false + */ + public function saveState($etat, $pathname) + { + 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 . '/etat_fichiers.txt'; + + $etatPrecedent = $this->checkPreviousState($fichierEtat); + + // for first save state when ceate 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); + } + } + + // public function compareFichierModifie($dossierSource, $dossierDestination, $fichierModifie) + // { + + // // Initialiser les tableaux pour les fichiers filtrés + // $fichiersSource = []; + // $fichiersDestination = []; + + // // Parcourir et filtrer les fichiers source + // foreach (dol_dir_list($dossierSource, "files") as $file) { + // if (preg_match('/^page\d+/', $file['name']) && !str_contains($file['name'], '.old')) { + // $fichiersSource[] = $file; + // } + // } + + // // Parcourir et filtrer les fichiers destination + // foreach (dol_dir_list($dossierDestination, "all", 1) as $file) { + // if (preg_match('/^page\d+/', $file['name']) && !str_contains($file['name'], '.old')) { + // $fichiersDestination[] = $file; + // } + // } + + // // Trouver l'index du fichier modifié dans la liste triée + // $indexModifie = -1; + // foreach ($fichiersSource as $index => $file) { + // if ($file['name'] == basename($fichierModifie['fullname'])) { + // $indexModifie = $index; + // break; + // } + // } + + // if ($indexModifie != -1 && isset($fichiersDestination[$indexModifie])) { + // // Comparer le fichier modifié avec le fichier correspondant dans le dossier de destination + // $sameFichier= $fichiersDestination[$indexModifie]['fullname']; + // $sourceContent = file_get_contents($fichierModifie['fullname']); + // $destContent = file_get_contents($sameFichier); + // $differences = $this->showDifferences($destContent, $sourceContent); + // return $differences; + // } + // return array(); + // } + + /** + * remove espace in string + * @param string $str string + * @return string + */ + protected function normalizeString($str) + { + + $str = str_replace("\r\n", "\n", $str); + $str = str_replace("\r", "\n", $str); + + $lines = explode("\n", $str); + $lines = array_map('trim', $lines); + + return implode("\n", $lines); + } + + /** + * show difference between to string + * @param string $str1 first string + * @param string $str2 seconde string + * @param string $exceptNumPge num of page file + * @return array|int -1 if KO, array if OK + */ + protected function showDifferences($str1, $str2, $exceptNumPge = '0') + { + $diff = []; + $str1 = $this->normalizeString($str1); + $str2 = $this->normalizeString($str2); + + $lines1 = explode("\n", $str1); + $lines2 = explode("\n", $str2); + + $maxLines = max(count($lines1), count($lines2)); + + for ($lineNum = 0; $lineNum < $maxLines; $lineNum++) { + $lineContent1 = $lines1[$lineNum] ?? ''; + $lineContent2 = $lines2[$lineNum] ?? ''; + + if (str_contains($lineContent1, $exceptNumPge) || str_contains($lineContent2, $exceptNumPge)) { + continue; + } + + if ($lineContent1 !== $lineContent2) { + if (isset($lines1[$lineNum]) && !isset($lines2[$lineNum])) { + // Ligne deleted de la source + $diff["Supprimée à la ligne " . ($lineNum + 1)] = $lineContent1; + } elseif (!isset($lines1[$lineNum]) && isset($lines2[$lineNum])) { + // Nouvelle ligne added dans la destination + $diff["Ajoutée à la ligne " . ($lineNum + 1)] = $lineContent2; + } else { + // Différence found it + $diff["Modifiée à la ligne " . ($lineNum + 1)] = $lineContent2; + } + } + } + + return $diff; + } + + /** + * Replace ligne by ligne in file using num of ligne + * @param string $desfFile path of file dest + * @param array $differences array of differences between files + * @return false|int false if we cant replace + */ + public function replaceLignEUsingNum($desfFile, $differences) + { + // if (file_exists($desfFile)) { + // dolChmod($desfFile,'766'); + // } + $contentDest = file($desfFile, FILE_IGNORE_NEW_LINES); + + foreach ($differences as $key => $ligneSource) { + if (preg_match('/(Ajoutée|Modifiée) à la ligne (\d+)/', $key, $matches)) { + $typeModification = $matches[1]; + $numLigne = (int) $matches[2] - 1; + + if ($typeModification === 'Ajoutée') { + array_splice($contentDest, $numLigne, 0, $ligneSource); + } elseif ($typeModification === 'Modifiée') { + $contentDest[$numLigne] = $ligneSource; + } + } elseif (preg_match('/Supprimée à la ligne (\d+)/', $key, $matches)) { + $numLigne = (int) $matches[1] - 1; + unset($contentDest[$numLigne]); + } + } + //Reindex the table keys + + $contentDest = array_values($contentDest); + $stringreplacement = implode("\n", $contentDest); + + file_put_contents($desfFile, $stringreplacement); + } } From 91d09cc0b299d1df658500a8248d6f7164a14fee Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 26 Dec 2023 18:56:32 +0100 Subject: [PATCH 17/60] recupere lines dont want to change --- htdocs/website/class/website.class.php | 184 ++++++++++++++----------- 1 file changed, 107 insertions(+), 77 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index e872e00ee1e4e..a9eb5d56f59ee 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1677,40 +1677,43 @@ public function overwriteTemplate() if (count($differences[$nomFichierModifie]) > 0) { $result = $this->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { - setEventMessages("file ".$nomFichierModifie." was modified", null, 'warnings'); + // save state file + $this->saveState($etatPrecedent, $fichierEtat); + setEventMessages("file ".$nomFichierModifie." was modified in template ".$website->name_template."", null, 'warnings'); + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); + exit(); } else { setEventMessages("file ".$nomFichierModifie." was not modified", null, 'errors'); } } } - } else { + } elseif (preg_match('/page(\d+)\.tpl\.php/', $nomFichierModifie)) { // TO DO when file has not same name - // $succes = 0; - // $differences[$nomFichierModifie] = $this->compareFichierModifie($sourcedir, $destdir, $fichierModifie); - - // if (count($differences[$nomFichierModifie]) > 0) { - // $result = $this->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); - // if ($result !== false) { - // $succes++; - // } else { - // setEventMessages("file ".$nomFichierModifie." was not modified", null, 'errors'); - // } - // } + $succes = 0; + $differences[$nomFichierModifie] = $this->compareFichierModifie($sourcedir, $destdir, $fichierModifie); + if (count($differences[$nomFichierModifie]) > 0) { + $result = $this->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); + if ($result !== false) { + $succes++; + } else { + setEventMessages("file ".$nomFichierModifie." was not modified", null, 'errors'); + } + } } } - // if ($succes) { - // setEventMessages("file ".$nomFichierModifie." was modified", null, 'warnings'); - // } + if ($succes) { + // save state file + $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 files was modified", null, 'warnings'); + setEventMessages("No file has been modified", null, 'warnings'); + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); + exit(); } - - // save state file - $this->saveState($etatPrecedent, $fichierEtat); - - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); - exit(); } /** @@ -1805,53 +1808,65 @@ public function initFilesStatus($sourcedir) } } - // public function compareFichierModifie($dossierSource, $dossierDestination, $fichierModifie) - // { - - // // Initialiser les tableaux pour les fichiers filtrés - // $fichiersSource = []; - // $fichiersDestination = []; - - // // Parcourir et filtrer les fichiers source - // foreach (dol_dir_list($dossierSource, "files") as $file) { - // if (preg_match('/^page\d+/', $file['name']) && !str_contains($file['name'], '.old')) { - // $fichiersSource[] = $file; - // } - // } - - // // Parcourir et filtrer les fichiers destination - // foreach (dol_dir_list($dossierDestination, "all", 1) as $file) { - // if (preg_match('/^page\d+/', $file['name']) && !str_contains($file['name'], '.old')) { - // $fichiersDestination[] = $file; - // } - // } - - // // Trouver l'index du fichier modifié dans la liste triée - // $indexModifie = -1; - // foreach ($fichiersSource as $index => $file) { - // if ($file['name'] == basename($fichierModifie['fullname'])) { - // $indexModifie = $index; - // break; - // } - // } - - // if ($indexModifie != -1 && isset($fichiersDestination[$indexModifie])) { - // // Comparer le fichier modifié avec le fichier correspondant dans le dossier de destination - // $sameFichier= $fichiersDestination[$indexModifie]['fullname']; - // $sourceContent = file_get_contents($fichierModifie['fullname']); - // $destContent = file_get_contents($sameFichier); - // $differences = $this->showDifferences($destContent, $sourceContent); - // return $differences; - // } - // return array(); - // } + /** + * Compare two files has not same name but same content + * @param string $dossierSource filepath of folder source + * @param string $dossierDestination filepath of folder dest + * @param mixed $fichierModifie files modified + * @return array empty if KO, array if OK + */ + public function compareFichierModifie($dossierSource, $dossierDestination, $fichierModifie) + { + + $fichiersSource = []; + $fichiersDestination = []; + + // filter files source + foreach (dol_dir_list($dossierSource, "files") as $file) { + if (preg_match('/^page\d+/', $file['name']) && !str_contains($file['name'], '.old')) { + $fichiersSource[] = $file; + } + } + + // filter files destination + foreach (dol_dir_list($dossierDestination, "all", 1) as $file) { + if (preg_match('/^page\d+/', $file['name']) && !str_contains($file['name'], '.old')) { + $fichiersDestination[] = $file; + } + } + + // find index source and search it in folder destination + $numOfPageSource = 0; + $indexModifie = -1; + foreach ($fichiersSource as $index => $file) { + if ($file['name'] == basename($fichierModifie['fullname'])) { + $numOfPageSource = $this->extractNumberFromFilename($file['name']); + $indexModifie = $index; + break; + } + } + + if ($indexModifie != -1 && isset($fichiersDestination[$indexModifie])) { + $sameFichier= $fichiersDestination[$indexModifie]['fullname']; + $sourceContent = file_get_contents($fichierModifie['fullname']); + $destContent = file_get_contents($sameFichier); + + $numOfPageDest = $this->extractNumberFromFilename($sameFichier); + + $differences = $this->showDifferences($destContent, $sourceContent, array($numOfPageDest,$numOfPageSource)); + $differences['file_destination'] = $fichiersDestination[$indexModifie]; + + return $differences; + } + return array(); + } /** * remove espace in string * @param string $str string * @return string */ - protected function normalizeString($str) + private function normalizeString($str) { $str = str_replace("\r\n", "\n", $str); @@ -1867,26 +1882,30 @@ protected function normalizeString($str) * show difference between to string * @param string $str1 first string * @param string $str2 seconde string - * @param string $exceptNumPge num of page file + * @param array $exceptNumPge num of page files we dont want to change * @return array|int -1 if KO, array if OK */ - protected function showDifferences($str1, $str2, $exceptNumPge = '0') + protected function showDifferences($str1, $str2, $exceptNumPge = array()) { - $diff = []; + $diff = array(); $str1 = $this->normalizeString($str1); $str2 = $this->normalizeString($str2); $lines1 = explode("\n", $str1); $lines2 = explode("\n", $str2); + $linesShouldnChange = array(); + $linesShouldnNotChange = array(); $maxLines = max(count($lines1), count($lines2)); - for ($lineNum = 0; $lineNum < $maxLines; $lineNum++) { $lineContent1 = $lines1[$lineNum] ?? ''; $lineContent2 = $lines2[$lineNum] ?? ''; - if (str_contains($lineContent1, $exceptNumPge) || str_contains($lineContent2, $exceptNumPge)) { - continue; + if (str_contains($lineContent1, $exceptNumPge[0])) { + $linesShouldnChange[] = $lineContent1; + } + if (str_contains($lineContent2, $exceptNumPge[1])) { + $linesShouldnNotChange[] = $lineContent2; } if ($lineContent1 !== $lineContent2) { @@ -1902,6 +1921,13 @@ protected function showDifferences($str1, $str2, $exceptNumPge = '0') } } } + $pairesRemplacement = array(); + foreach ($linesShouldnNotChange as $numLigne => $ligneRemplacement) { + if (isset($linesShouldnChange[$numLigne])) { + $pairesRemplacement[$ligneRemplacement] = $linesShouldnChange[$numLigne]; + } + } + $diff['lignes_dont_change'] = $pairesRemplacement; return $diff; } @@ -1912,12 +1938,13 @@ protected function showDifferences($str1, $str2, $exceptNumPge = '0') * @param array $differences array of differences between files * @return false|int false if we cant replace */ - public function replaceLignEUsingNum($desfFile, $differences) + protected function replaceLignEUsingNum($desfFile, $differences) { - // if (file_exists($desfFile)) { - // dolChmod($desfFile,'766'); - // } - $contentDest = file($desfFile, FILE_IGNORE_NEW_LINES); + if (file_exists($desfFile)) { + dolChmod($desfFile, '0664'); + unset($differences['file_destination']); + } + $contentDest = file($desfFile); foreach ($differences as $key => $ligneSource) { if (preg_match('/(Ajoutée|Modifiée) à la ligne (\d+)/', $key, $matches)) { @@ -1935,10 +1962,13 @@ public function replaceLignEUsingNum($desfFile, $differences) } } //Reindex the table keys - $contentDest = array_values($contentDest); $stringreplacement = implode("\n", $contentDest); - file_put_contents($desfFile, $stringreplacement); + foreach ($differences['lignes_dont_change'] as $linechanged => $line) { + if (in_array($linechanged, $contentDest)) { + dolReplaceInFile($desfFile, array($linechanged => $line)); + } + } } } From 52cb80879fd67c38fea766a7028b68bd56791934 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Wed, 27 Dec 2023 19:24:29 +0100 Subject: [PATCH 18/60] verify permission for files --- htdocs/website/class/website.class.php | 73 ++++++++++++++++---------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index a9eb5d56f59ee..2bdff5673c945 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1656,14 +1656,13 @@ public function overwriteTemplate() $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; $arraydestdir = dol_dir_list($destdir, "all", 1); $differences = []; - if (count($modifications) >1) { foreach ($modifications as $fichierModifie) { $nomFichierModifie = $fichierModifie['name']; if ($nomFichierModifie == basename($fichierEtat)) { continue; } - + $succes = 0; // Find the corresponding file in the destination folder foreach ($arraydestdir as $destFile) { if ($destFile['name'] == $nomFichierModifie) { @@ -1671,49 +1670,52 @@ public function overwriteTemplate() $destContent = file_get_contents($destFile['fullname']); if ($sourceContent !== $destContent) { - $numPage = $this->extractNumberFromFilename($fichierModifie['fullname']); - $differences[$nomFichierModifie] = $this->showDifferences($destContent, $sourceContent, $numPage); - + $differences[$nomFichierModifie] = $this->showDifferences($destContent, $sourceContent); if (count($differences[$nomFichierModifie]) > 0) { $result = $this->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { - // save state file - $this->saveState($etatPrecedent, $fichierEtat); + if ($result == -2) { + setEventMessages("No permissions to write in file ".$nomFichierModifie." from template ".$website->name_template."", null, 'errors'); + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); + exit(); + } setEventMessages("file ".$nomFichierModifie." was modified in template ".$website->name_template."", null, 'warnings'); - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); - exit(); } else { setEventMessages("file ".$nomFichierModifie." was not modified", null, 'errors'); } } } - } elseif (preg_match('/page(\d+)\.tpl\.php/', $nomFichierModifie)) { - // TO DO when file has not same name - $succes = 0; + } + if (preg_match('/page(\d+)\.tpl\.php/', $nomFichierModifie)) { $differences[$nomFichierModifie] = $this->compareFichierModifie($sourcedir, $destdir, $fichierModifie); if (count($differences[$nomFichierModifie]) > 0) { $result = $this->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { + if ($result == -2) { + setEventMessages("No permissions to write in file ".$nomFichierModifie." from template ".$website->name_template."", null, 'errors'); + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); + exit(); + } $succes++; - } else { - setEventMessages("file ".$nomFichierModifie." was not modified", null, 'errors'); } } } } - if ($succes) { - // save state file - $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(); - } + } + if ($succes>0) { + // save state file + $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, 'warnings'); - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); - exit(); + setEventMessages("No file has been modified", null, 'errors'); } + // save state file + $this->saveState($etatPrecedent, $fichierEtat); + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); + exit(); } /** @@ -1901,10 +1903,10 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) $lineContent1 = $lines1[$lineNum] ?? ''; $lineContent2 = $lines2[$lineNum] ?? ''; - if (str_contains($lineContent1, $exceptNumPge[0])) { + if (strpos($lineContent1, $exceptNumPge[0])) { $linesShouldnChange[] = $lineContent1; } - if (str_contains($lineContent2, $exceptNumPge[1])) { + if (strpos($lineContent2, $exceptNumPge[1])) { $linesShouldnNotChange[] = $lineContent2; } @@ -1940,12 +1942,25 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) */ protected function replaceLignEUsingNum($desfFile, $differences) { + $userId = fileowner($desfFile); + if ($userId !== false) { + // Obtain user information from the ID + if (function_exists('posix_getpwuid')&& function_exists('posix_getpwuid')) { + $uid = posix_geteuid(); + $userInfoM = posix_getpwuid($uid); + + $userInfo = posix_getpwuid($userId); + if ($userInfo['uid'] !== $userInfoM['uid']) { + return -2; + } + } + } if (file_exists($desfFile)) { dolChmod($desfFile, '0664'); - unset($differences['file_destination']); } - $contentDest = file($desfFile); - + unset($differences['file_destination']); + $contentDest = file($desfFile, FILE_IGNORE_NEW_LINES); + //var_dump($desfFile);exit; foreach ($differences as $key => $ligneSource) { if (preg_match('/(Ajoutée|Modifiée) à la ligne (\d+)/', $key, $matches)) { $typeModification = $matches[1]; From c08edf237dbcf4958b26df5754101af79c6b90eb Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 29 Dec 2023 18:35:24 +0100 Subject: [PATCH 19/60] extract num of page and found the correct page in destination --- htdocs/website/class/website.class.php | 61 +++++++++++++++++++------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 2bdff5673c945..68d8dff6e8f6f 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1656,6 +1656,7 @@ public function overwriteTemplate() $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; $arraydestdir = dol_dir_list($destdir, "all", 1); $differences = []; + var_dump($modifications); if (count($modifications) >1) { foreach ($modifications as $fichierModifie) { $nomFichierModifie = $fichierModifie['name']; @@ -1689,10 +1690,11 @@ public function overwriteTemplate() if (preg_match('/page(\d+)\.tpl\.php/', $nomFichierModifie)) { $differences[$nomFichierModifie] = $this->compareFichierModifie($sourcedir, $destdir, $fichierModifie); if (count($differences[$nomFichierModifie]) > 0) { + //var_dump($differences[$nomFichierModifie]); $result = $this->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { - setEventMessages("No permissions to write in file ".$nomFichierModifie." from template ".$website->name_template."", null, 'errors'); + setEventMessages("No permissions to write in file ".$differences[$nomFichierModifie]['file_destination']['name']." from template ".$website->name_template."", null, 'errors'); header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); exit(); } @@ -1823,10 +1825,15 @@ public function compareFichierModifie($dossierSource, $dossierDestination, $fich $fichiersSource = []; $fichiersDestination = []; + $fichierWithNoPage = []; + $fichierWithNoPageInDest = []; + // filter files source foreach (dol_dir_list($dossierSource, "files") as $file) { if (preg_match('/^page\d+/', $file['name']) && !str_contains($file['name'], '.old')) { $fichiersSource[] = $file; + } else { + $fichierWithNoPage[] = $file; } } @@ -1834,30 +1841,56 @@ public function compareFichierModifie($dossierSource, $dossierDestination, $fich foreach (dol_dir_list($dossierDestination, "all", 1) as $file) { if (preg_match('/^page\d+/', $file['name']) && !str_contains($file['name'], '.old')) { $fichiersDestination[] = $file; + } else { + $fichierWithNoPageInDest[] = $file; } } // find index source and search it in folder destination $numOfPageSource = 0; - $indexModifie = -1; foreach ($fichiersSource as $index => $file) { if ($file['name'] == basename($fichierModifie['fullname'])) { $numOfPageSource = $this->extractNumberFromFilename($file['name']); - $indexModifie = $index; break; } } - if ($indexModifie != -1 && isset($fichiersDestination[$indexModifie])) { - $sameFichier= $fichiersDestination[$indexModifie]['fullname']; - $sourceContent = file_get_contents($fichierModifie['fullname']); - $destContent = file_get_contents($sameFichier); + //search numPage where was declared + $fileFounded = array(); + foreach ($fichierWithNoPage as $filesource) { + $fileContent = file_get_contents($filesource['fullname']); + if (strpos($fileContent, "require './page".$numOfPageSource.".tpl.php'") !== false) { + $fileFounded = $filesource; + break; + } + } + // find file with same name and extract num page in destination folder + $numPageFounded = ''; + foreach ($fichierWithNoPageInDest as $filedest) { + if ($filedest['name'] === $fileFounded['name']) { + $fileContent = file_get_contents($filedest['fullname']); + if (preg_match("/page\d+\.tpl\.php/", $fileContent, $matches)) { + $numPageFounded = $matches[0]; + break; + } + } + } + //search file with the number of page founded + $fileNeeded = array(); + foreach ($fichiersDestination as $index => $file) { + if ($file['name'] == $numPageFounded) { + $fileNeeded = $file; + break; + } + } - $numOfPageDest = $this->extractNumberFromFilename($sameFichier); + if (isset($fileNeeded)) { + $sourceContent = file_get_contents($fichierModifie['fullname']); + $destContent = file_get_contents($fileNeeded['fullname']); + $numOfPageDest = $this->extractNumberFromFilename($fileNeeded['name']); $differences = $this->showDifferences($destContent, $sourceContent, array($numOfPageDest,$numOfPageSource)); - $differences['file_destination'] = $fichiersDestination[$indexModifie]; - + $differences['file_destination'] = $fileNeeded; return $differences; } return array(); @@ -1870,14 +1903,9 @@ public function compareFichierModifie($dossierSource, $dossierDestination, $fich */ private function normalizeString($str) { - $str = str_replace("\r\n", "\n", $str); $str = str_replace("\r", "\n", $str); - - $lines = explode("\n", $str); - $lines = array_map('trim', $lines); - - return implode("\n", $lines); + return $str; } /** @@ -1960,7 +1988,6 @@ protected function replaceLignEUsingNum($desfFile, $differences) } unset($differences['file_destination']); $contentDest = file($desfFile, FILE_IGNORE_NEW_LINES); - //var_dump($desfFile);exit; foreach ($differences as $key => $ligneSource) { if (preg_match('/(Ajoutée|Modifiée) à la ligne (\d+)/', $key, $matches)) { $typeModification = $matches[1]; From a5a4d6d0aff6fdb40c40fb9ccc6cf50dbd146038 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 29 Dec 2023 18:37:06 +0100 Subject: [PATCH 20/60] remove var_dump --- htdocs/website/class/website.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 68d8dff6e8f6f..8cd5bd412eee1 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1656,7 +1656,7 @@ public function overwriteTemplate() $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; $arraydestdir = dol_dir_list($destdir, "all", 1); $differences = []; - var_dump($modifications); + if (count($modifications) >1) { foreach ($modifications as $fichierModifie) { $nomFichierModifie = $fichierModifie['name']; @@ -1690,7 +1690,6 @@ public function overwriteTemplate() if (preg_match('/page(\d+)\.tpl\.php/', $nomFichierModifie)) { $differences[$nomFichierModifie] = $this->compareFichierModifie($sourcedir, $destdir, $fichierModifie); if (count($differences[$nomFichierModifie]) > 0) { - //var_dump($differences[$nomFichierModifie]); $result = $this->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { From a60bc67c515a9c758467afaeb4b21dd99e9a0e30 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 2 Jan 2024 17:51:18 +0100 Subject: [PATCH 21/60] correct path image --- htdocs/website/class/website.class.php | 38 ++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 8cd5bd412eee1..2ef78d4a6e767 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1656,7 +1656,7 @@ public function overwriteTemplate() $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; $arraydestdir = dol_dir_list($destdir, "all", 1); $differences = []; - + //var_dump($modifications);exit; if (count($modifications) >1) { foreach ($modifications as $fichierModifie) { $nomFichierModifie = $fichierModifie['name']; @@ -1925,18 +1925,30 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) $linesShouldnChange = array(); $linesShouldnNotChange = array(); + $linefound = array(); + $countNumPage = count($exceptNumPge); + + for ($i = 0;$i< $countNumPage; $i++) { + $linefound[$i]['meta'] = '/content="' . preg_quote($exceptNumPge[$i], '/') . '" \/>/'; + $linefound[$i]['output'] = '/dolWebsiteOutput\(\$tmp, "html", ' . preg_quote($exceptNumPge[$i], '/') . '\);/'; + } + $maxLines = max(count($lines1), count($lines2)); for ($lineNum = 0; $lineNum < $maxLines; $lineNum++) { $lineContent1 = $lines1[$lineNum] ?? ''; $lineContent2 = $lines2[$lineNum] ?? ''; - - if (strpos($lineContent1, $exceptNumPge[0])) { + if (preg_match($linefound[0]['output'], $lineContent1)) { $linesShouldnChange[] = $lineContent1; } - if (strpos($lineContent2, $exceptNumPge[1])) { + if (preg_match($linefound[1]['output'], $lineContent2)) { + $linesShouldnNotChange[] = $lineContent2; + } + if (preg_match($linefound[0]['meta'], $lineContent1)) { + $linesShouldnChange[] = $lineContent1; + } + if (preg_match($linefound[1]['meta'], $lineContent2)) { $linesShouldnNotChange[] = $lineContent2; } - if ($lineContent1 !== $lineContent2) { if (isset($lines1[$lineNum]) && !isset($lines2[$lineNum])) { // Ligne deleted de la source @@ -1950,6 +1962,8 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) } } } + + $pairesRemplacement = array(); foreach ($linesShouldnNotChange as $numLigne => $ligneRemplacement) { if (isset($linesShouldnChange[$numLigne])) { @@ -1958,6 +1972,20 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) } $diff['lignes_dont_change'] = $pairesRemplacement; + // search path of image and replace it with the correcte path + $pattern = '/medias\/image\/'.$this->ref.'\/([^\'"\s]+)/'; + + foreach ($diff as $key => $value) { + // Assurez-vous que la valeur est une chaîne + if (is_string($value)) { + if (preg_match($pattern, $value)) { + //var_dump( "Trouvé dans".$this->name_template." / ". $key." : ".$value."\n"); + $newValue = preg_replace($pattern, 'medias/image/'.$this->name_template.'/$1', $value); + + $diff[$key] = $newValue; + } + } + } return $diff; } From 64a854bb1d4cb7fbb183c2700be2ca25831ffa34 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 5 Jan 2024 19:26:22 +0100 Subject: [PATCH 22/60] fix problem when create new page --- htdocs/website/class/website.class.php | 164 ++++++++++++++++++------- 1 file changed, 119 insertions(+), 45 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 2ef78d4a6e767..7b02d600cb2cb 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1656,50 +1656,114 @@ public function overwriteTemplate() $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; $arraydestdir = dol_dir_list($destdir, "all", 1); $differences = []; - //var_dump($modifications);exit; - if (count($modifications) >1) { + $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; } $succes = 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'); + } + $fileFounded = ''; + foreach ($arraySourcedir as $file) { + if ($file['name'] == $nomFichierModifie) { + $fileContent = file_get_contents($file['fullname']); + if (preg_match("/page\d+\.tpl\.php/", $fileContent, $matches)) { + $fileFounded = $matches[0]; + break; + } + } + } + foreach ($arraySourcedir as $file) { + if($file['name'] == $fileFounded) { + 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->replaceLignEUsingNum($destdir.'/containers/'."page" . $nextpage . ".tpl.php", $diff); + if ($replace !== false) { + setEventMessages("Copy file page".$nextpage.".tpl.php in template ".$this->name_template." with succes", 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(); + } + } + + + } // Find the corresponding file in the destination folder - 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 (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->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); + if ($result !== false) { + if ($result == -2) { + setEventMessages("No permissions to write in file ".$nomFichierModifie." from template ".$website->name_template."", null, 'errors'); + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); + exit(); + } + setEventMessages("file ".$nomFichierModifie." was modified in template ".$website->name_template."", null, 'warnings'); + } else { + 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->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); + $result = $this->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { - setEventMessages("No permissions to write in file ".$nomFichierModifie." from template ".$website->name_template."", null, 'errors'); + setEventMessages("No permissions to write in file ".$differences[$nomFichierModifie]['file_destination']['name']." from template ".$website->name_template."", null, 'errors'); header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); exit(); } - setEventMessages("file ".$nomFichierModifie." was modified in template ".$website->name_template."", null, 'warnings'); - } else { - 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->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); - if ($result !== false) { - if ($result == -2) { - setEventMessages("No permissions to write in file ".$differences[$nomFichierModifie]['file_destination']['name']." from template ".$website->name_template."", null, 'errors'); - header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); - exit(); + $succes++; } - $succes++; } } + + } } } @@ -1885,11 +1949,13 @@ public function compareFichierModifie($dossierSource, $dossierDestination, $fich if (isset($fileNeeded)) { $sourceContent = file_get_contents($fichierModifie['fullname']); - $destContent = file_get_contents($fileNeeded['fullname']); - - $numOfPageDest = $this->extractNumberFromFilename($fileNeeded['name']); - $differences = $this->showDifferences($destContent, $sourceContent, array($numOfPageDest,$numOfPageSource)); - $differences['file_destination'] = $fileNeeded; + if (file_exists($fileNeeded['fullname'])) { + $destContent = file_get_contents($fileNeeded['fullname']); + + $numOfPageDest = $this->extractNumberFromFilename($fileNeeded['name']); + $differences = $this->showDifferences($destContent, $sourceContent, array($numOfPageDest,$numOfPageSource)); + $differences['file_destination'] = $fileNeeded; + } return $differences; } return array(); @@ -1940,12 +2006,12 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) if (preg_match($linefound[0]['output'], $lineContent1)) { $linesShouldnChange[] = $lineContent1; } - if (preg_match($linefound[1]['output'], $lineContent2)) { - $linesShouldnNotChange[] = $lineContent2; - } if (preg_match($linefound[0]['meta'], $lineContent1)) { $linesShouldnChange[] = $lineContent1; } + if (preg_match($linefound[1]['output'], $lineContent2)) { + $linesShouldnNotChange[] = $lineContent2; + } if (preg_match($linefound[1]['meta'], $lineContent2)) { $linesShouldnNotChange[] = $lineContent2; } @@ -1964,14 +2030,24 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) } - $pairesRemplacement = array(); - foreach ($linesShouldnNotChange as $numLigne => $ligneRemplacement) { - if (isset($linesShouldnChange[$numLigne])) { - $pairesRemplacement[$ligneRemplacement] = $linesShouldnChange[$numLigne]; - } + if (empty($linesShouldnChange)) { + $linesShouldnChange[0] = ''; + $linesShouldnChange[1] = '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "html", '.$exceptNumPge[0].');'; } - $diff['lignes_dont_change'] = $pairesRemplacement; + $pairesRemplacement = array(); + if (!empty($linesShouldnNotChange)) { + $i =0; + foreach ($linesShouldnNotChange as $numLigne => $ligneRemplacement) { + if (isset($linesShouldnChange[$numLigne])) { + $pairesRemplacement[$ligneRemplacement] = $linesShouldnChange[$numLigne]; + }else { + $pairesRemplacement[$ligneRemplacement] = $linesShouldnChange[$i]; + } + $i++; + } + $diff['lignes_dont_change'] = $pairesRemplacement; + } // search path of image and replace it with the correcte path $pattern = '/medias\/image\/'.$this->ref.'\/([^\'"\s]+)/'; @@ -1979,9 +2055,7 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) // Assurez-vous que la valeur est une chaîne if (is_string($value)) { if (preg_match($pattern, $value)) { - //var_dump( "Trouvé dans".$this->name_template." / ". $key." : ".$value."\n"); - $newValue = preg_replace($pattern, 'medias/image/'.$this->name_template.'/$1', $value); - + $newValue = preg_replace($pattern, 'medias/image/'.$this->name_template.'/$1', $value); $diff[$key] = $newValue; } } From 5f4e5844253cbe3b588137e52ae3bbe6823b30e5 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 5 Jan 2024 19:26:27 +0100 Subject: [PATCH 23/60] fix problem when create new page --- htdocs/website/class/website.class.php | 40 +++++++++++--------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 7b02d600cb2cb..1825d66322adc 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1666,13 +1666,13 @@ public function overwriteTemplate() continue; } $succes = 0; - - //check if it is a new file + + //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'); + $cp = dol_copy($fichierModifie['fullname'], $destdir.'/containers/'.$nomFichierModifie, '0664'); if ($cp > 0) { - if (file_exists($destdir.'/containers/'.$nomFichierModifie)){ + if (file_exists($destdir.'/containers/'.$nomFichierModifie)) { $tabnumpage = array(); foreach ($arraydestdir as $fileDest) { if ($this->extractNumberFromFilename($fileDest['name']) !== -1) { @@ -1684,7 +1684,7 @@ public function overwriteTemplate() $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")) { + 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'); } $fileFounded = ''; @@ -1698,22 +1698,20 @@ public function overwriteTemplate() } } foreach ($arraySourcedir as $file) { - if($file['name'] == $fileFounded) { - if (!is_writable($file['fullname'])){ - dolChmod($file['fullname'],'0664'); + if ($file['name'] == $fileFounded) { + 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']))); + $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->replaceLignEUsingNum($destdir.'/containers/'."page" . $nextpage . ".tpl.php", $diff); if ($replace !== false) { - setEventMessages("Copy file page".$nextpage.".tpl.php in template ".$this->name_template." with succes", null,'warnings'); + setEventMessages("Copy file page".$nextpage.".tpl.php in template ".$this->name_template." with succes", null, 'warnings'); } } - } } } - } $this->saveState($etatPrecedent, $fichierEtat); setEventMessages("file ".$nomFichierModifie." was created in template ".$website->name_template."", null, 'warnings'); @@ -1721,16 +1719,14 @@ public function overwriteTemplate() exit(); } } - - } // Find the corresponding file in the destination folder - if (in_array($nomFichierModifie, $namesSource)){ + if (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) { @@ -1762,8 +1758,6 @@ public function overwriteTemplate() } } } - - } } } @@ -1951,11 +1945,11 @@ public function compareFichierModifie($dossierSource, $dossierDestination, $fich $sourceContent = file_get_contents($fichierModifie['fullname']); if (file_exists($fileNeeded['fullname'])) { $destContent = file_get_contents($fileNeeded['fullname']); - + $numOfPageDest = $this->extractNumberFromFilename($fileNeeded['name']); $differences = $this->showDifferences($destContent, $sourceContent, array($numOfPageDest,$numOfPageSource)); $differences['file_destination'] = $fileNeeded; - } + } return $differences; } return array(); @@ -2041,13 +2035,13 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) foreach ($linesShouldnNotChange as $numLigne => $ligneRemplacement) { if (isset($linesShouldnChange[$numLigne])) { $pairesRemplacement[$ligneRemplacement] = $linesShouldnChange[$numLigne]; - }else { + } else { $pairesRemplacement[$ligneRemplacement] = $linesShouldnChange[$i]; } $i++; } $diff['lignes_dont_change'] = $pairesRemplacement; - } + } // search path of image and replace it with the correcte path $pattern = '/medias\/image\/'.$this->ref.'\/([^\'"\s]+)/'; @@ -2055,7 +2049,7 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) // Assurez-vous que la valeur est une chaîne if (is_string($value)) { if (preg_match($pattern, $value)) { - $newValue = preg_replace($pattern, 'medias/image/'.$this->name_template.'/$1', $value); + $newValue = preg_replace($pattern, 'medias/image/'.$this->name_template.'/$1', $value); $diff[$key] = $newValue; } } From bfae93b3b34afac43723fba00254aec6232bd4cf Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Sat, 6 Jan 2024 19:48:11 +0100 Subject: [PATCH 24/60] fix rights for exportwebsite --- htdocs/website/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 1e33b30f47020..fa3c34860bbe4 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2399,7 +2399,7 @@ } // Export site -if ($action == 'exportsite') { +if ($action == 'exportsite' && $user->hasRight('website', 'export')) { $fileofzip = $object->exportWebSite(); if ($fileofzip) { From bb2f13aed4e56b872e02cc8cb9cb31e23a843cdc Mon Sep 17 00:00:00 2001 From: Quentin VIAL-GOUTEYRON Date: Thu, 25 Jan 2024 14:40:11 +0100 Subject: [PATCH 25/60] FIX : crabe PDF is generating in conf->entity instead of object->entity --- htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index af927f6d188b1..8f4dbd66606c3 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -304,11 +304,11 @@ public function write_file($object, $outputlangs, $srctemplatepath = '', $hidede // Definition of $dir and $file if ($object->specimen) { - $dir = empty($conf->facture->multidir_output[$conf->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$conf->entity]; + $dir = empty($conf->facture->multidir_output[$object->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$object->entity]; $file = $dir."/SPECIMEN.pdf"; } else { $objectref = dol_sanitizeFileName($object->ref); - $dir = (empty($conf->facture->multidir_output[$conf->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$conf->entity])."/".$objectref; + $dir = (empty($conf->facture->multidir_output[$object->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$object->entity])."/".$objectref; $file = $dir."/".$objectref.".pdf"; } if (!file_exists($dir)) { From 8dce4e711409be5d449ec2c0179b2a8e5645bee8 Mon Sep 17 00:00:00 2001 From: Alban Durrheimer Date: Fri, 26 Jan 2024 10:00:51 +0100 Subject: [PATCH 26/60] Fix port in Docker MailDev --- build/docker/Dockerfile | 2 +- build/docker/docker-compose.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/docker/Dockerfile b/build/docker/Dockerfile index 69f4d27b26fb7..5cd4c60673b95 100644 --- a/build/docker/Dockerfile +++ b/build/docker/Dockerfile @@ -50,7 +50,7 @@ RUN echo 'xdebug.idekey="netbeans-xdebug"' >> ${PHP_INI_DIR}/php.ini # set up sendmail config, to use maildev RUN echo "account default" > /etc/msmtprc RUN echo "auth off" >> /etc/msmtprc -RUN echo "port 25" >> /etc/msmtprc +RUN echo "port 1025" >> /etc/msmtprc RUN echo "host mail" >> /etc/msmtprc RUN echo "from local@localdomain.com" >> /etc/msmtprc RUN echo "domain localhost.localdomain" >> /etc/msmtprc diff --git a/build/docker/docker-compose.yml b/build/docker/docker-compose.yml index ddcdc58560a3a..cc2988a67d19e 100644 --- a/build/docker/docker-compose.yml +++ b/build/docker/docker-compose.yml @@ -55,8 +55,8 @@ services: mail: image: maildev/maildev ports: - - "8081:80" - - "25:25" + - "8081:1080" + - "25:1025" networks: - internal-pod - external-pod From 5a412c66f77430f3579af4a6d8b2dd1d1eb2f3bc Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 26 Jan 2024 10:58:23 +0100 Subject: [PATCH 27/60] fix broken feature in 19 for product on task time --- htdocs/projet/tasks/time.php | 63 +++++++++++++++++------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 8a4c7f1c97663..37f74e0f6037d 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -158,36 +158,6 @@ $massaction = ''; } -// Definition of fields for list -$arrayfields = array(); -$arrayfields['t.element_date'] = array('label'=>$langs->trans("Date"), 'checked'=>1); -$arrayfields['p.fk_soc'] = array('label'=>$langs->trans("ThirdParty"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1','checked'=>1); -$arrayfields['s.name_alias'] = array('label'=>$langs->trans("AliasNameShort"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1'); -if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task - if (! empty($allprojectforuser)) { - $arrayfields['p.project_ref'] = ['label' => $langs->trans('RefProject'), 'checked' => 1]; - $arrayfields['p.project_label'] = ['label' => $langs->trans('ProjectLabel'), 'checked' => 1]; - } - $arrayfields['t.element_ref'] = array('label'=>$langs->trans("RefTask"), 'checked'=>1); - $arrayfields['t.element_label'] = array('label'=>$langs->trans("LabelTask"), 'checked'=>1); -} -$arrayfields['author'] = array('label' => $langs->trans("By"), 'checked' => 1); -$arrayfields['t.note'] = array('label' => $langs->trans("Note"), 'checked' => 1); -if (!getDolGlobalInt('PROJECT_HIDE_TASKS') && getDolGlobalInt('PROJECT_BILL_TIME_SPENT') && !$projectstatic->usage_bill_time ) { - $projectstatic->usage_bill_time=1; -} -if (isModEnabled('service') && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) { - $arrayfields['t.fk_product'] = array('label' => $langs->trans("Product"), 'checked' => 1); -} -$arrayfields['t.element_duration'] = array('label'=>$langs->trans("Duration"), 'checked'=>1); -$arrayfields['value'] = array('label'=>$langs->trans("Value"), 'checked'=>1, 'enabled'=>isModEnabled("salaries")); -$arrayfields['valuebilled'] = array('label'=>$langs->trans("Billed"), 'checked'=>1, 'enabled'=>(((getDolGlobalInt('PROJECT_HIDE_TASKS') || !getDolGlobalInt('PROJECT_BILL_TIME_SPENT')) ? 0 : 1) && $projectstatic->usage_bill_time)); -// Extra fields -include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_array_fields.tpl.php'; - -$arrayfields = dol_sort_array($arrayfields, 'position'); - - $parameters = array('socid' => $socid, 'projectid' => $projectid); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { @@ -1296,7 +1266,31 @@ // Print form confirm print $formconfirm; + // Definition of fields for list + $arrayfields = array(); + $arrayfields['t.element_date'] = array('label'=>$langs->trans("Date"), 'checked'=>1); + $arrayfields['p.fk_soc'] = array('label'=>$langs->trans("ThirdParty"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1','checked'=>1); + $arrayfields['s.name_alias'] = array('label'=>$langs->trans("AliasNameShort"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1'); + if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task + if (! empty($allprojectforuser)) { + $arrayfields['p.project_ref'] = ['label' => $langs->trans('RefProject'), 'checked' => 1]; + $arrayfields['p.project_label'] = ['label' => $langs->trans('ProjectLabel'), 'checked' => 1]; + } + $arrayfields['t.element_ref'] = array('label'=>$langs->trans("RefTask"), 'checked'=>1); + $arrayfields['t.element_label'] = array('label'=>$langs->trans("LabelTask"), 'checked'=>1); + } + $arrayfields['author'] = array('label' => $langs->trans("By"), 'checked' => 1); + $arrayfields['t.note'] = array('label' => $langs->trans("Note"), 'checked' => 1); + if (isModEnabled('service') && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) { + $arrayfields['t.fk_product'] = array('label' => $langs->trans("Product"), 'checked' => 1); + } + $arrayfields['t.element_duration'] = array('label'=>$langs->trans("Duration"), 'checked'=>1); + $arrayfields['value'] = array('label'=>$langs->trans("Value"), 'checked'=>1, 'enabled'=>isModEnabled("salaries")); + $arrayfields['valuebilled'] = array('label'=>$langs->trans("Billed"), 'checked'=>1, 'enabled'=>(((getDolGlobalInt('PROJECT_HIDE_TASKS') || !getDolGlobalInt('PROJECT_BILL_TIME_SPENT')) ? 0 : 1) && $projectstatic->usage_bill_time)); + // Extra fields + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_array_fields.tpl.php'; + $arrayfields = dol_sort_array($arrayfields, 'position'); $param = ''; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { @@ -1840,8 +1834,8 @@ function setDetailVisibility() { if (isModEnabled("service") && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) { print ''; - print img_picto('', 'product'); - print $form->select_produits('', 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth150', 0, '', null, 1); + print img_picto('', 'service'); + print $form->select_produits((GETPOSTISSET('fk_product')?GETPOST("fk_product", 'int'):''), 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth150', 0, '', null, 1); print ''; } } @@ -2345,9 +2339,10 @@ function setDetailVisibility() { // Product if (!empty($arrayfields['t.fk_product']['checked'])) { - print ''; + print ''; if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) { - $form->select_produits($task_time->fk_product, 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); + print img_picto('', 'service'); + print $form->select_produits($task_time->fk_product, 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500', 0, '', null, 1); } elseif (!empty($task_time->fk_product)) { $product = new Product($db); $resultFetch = $product->fetch($task_time->fk_product); From 78c06fbd074372c0e1890bb0ce34397d7ea5909e Mon Sep 17 00:00:00 2001 From: William Mead Date: Fri, 26 Jan 2024 11:08:50 +0100 Subject: [PATCH 28/60] Fixed empty parent company list column --- htdocs/societe/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 9e00065606f81..8e4b086b93d84 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -1694,7 +1694,7 @@ $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur; $companystatic->fk_prospectlevel = $obj->fk_prospectlevel; - $companystatic->fk_parent = $obj->fk_parent; + $companystatic->parent = $obj->fk_parent; $companystatic->entity = $obj->entity; } From 69289f5005072c4b1bb439beb6831ef1f5c71ed0 Mon Sep 17 00:00:00 2001 From: Hystepik Date: Fri, 26 Jan 2024 15:41:13 +0100 Subject: [PATCH 29/60] New hook to allow module show onlinepaymenturl --- htdocs/adherents/card.php | 8 ++++++++ htdocs/adherents/subscription.php | 8 ++++++++ htdocs/commande/card.php | 9 +++++++++ htdocs/compta/facture/card.php | 8 ++++++++ htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 9 ++++++++- htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 9 ++++++++- htdocs/don/card.php | 8 ++++++++ 7 files changed, 57 insertions(+), 2 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 1af279d33d466..7f41b76e564b9 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -2069,6 +2069,14 @@ function initfieldrequired() { // Show online payment link $useonlinepayment = (isModEnabled('paypal') || isModEnabled('stripe') || isModEnabled('paybox')); + $parameters = array(); + $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } else { + $useonlinepayment = $reshook; + } + if ($useonlinepayment) { print '
'; if (empty($amount)) { // Take the maximum amount among what the member is supposed to pay / has paid in the past diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 7c6647835d82f..3d479cd23c666 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -825,6 +825,14 @@ // Shon online payment link $useonlinepayment = (isModEnabled('paypal') || isModEnabled('stripe') || isModEnabled('paybox')); + $parameters = array(); + $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + if (isset($hookmanager->resArray['showonlinepaymenturl'])) { + $useonlinepayment = $hookmanager->resArray['showonlinepaymenturl']; + } + } + if ($useonlinepayment) { print '
'; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index fc72d6a7f8a5b..cae96460a93bc 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -3090,6 +3090,15 @@ // Show online payment link $useonlinepayment = (isModEnabled('paypal') || isModEnabled('stripe') || isModEnabled('paybox')); + + $parameters = array(); + $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + if (isset($hookmanager->resArray['showonlinepaymenturl'])) { + $useonlinepayment = $hookmanager->resArray['showonlinepaymenturl']; + } + } + if (getDolGlobalString('ORDER_HIDE_ONLINE_PAYMENT_ON_ORDER')) { $useonlinepayment = 0; } diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 64d2f2637aefc..55f4876fee286 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -5993,6 +5993,14 @@ function js_recalculate_revenuestamp(){ // Show online payment link $useonlinepayment = (isModEnabled('paypal') || isModEnabled('stripe') || isModEnabled('paybox')); + $parameters = array(); + $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + if (isset($hookmanager->resArray['showonlinepaymenturl'])) { + $useonlinepayment = $hookmanager->resArray['showonlinepaymenturl']; + } + } + if ($object->status != Facture::STATUS_DRAFT && $useonlinepayment) { print '
'."\n"; require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 6c58f02900ac9..13df1c7b90c46 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1111,7 +1111,7 @@ protected function _tableau_versements_header($pdf, $object, $outputlangs, $defa protected function _tableau_info(&$pdf, $object, $posy, $outputlangs, $outputlangsbis) { // phpcs:enable - global $conf, $mysoc; + global $conf, $mysoc, $hookmanager; $default_font_size = pdf_getPDFFontSize($outputlangs); @@ -1238,6 +1238,13 @@ protected function _tableau_info(&$pdf, $object, $posy, $outputlangs, $outputlan if (isModEnabled('paybox')) { $useonlinepayment++; } + $parameters = array(); + $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + if (isset($hookmanager->resArray['showonlinepaymenturl'])) { + $useonlinepayment += $hookmanager->resArray['showonlinepaymenturl']; + } + } } if ($object->statut != Facture::STATUS_DRAFT && $useonlinepayment) { diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 1d6b8104d873a..1a3db19bab3ce 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1204,7 +1204,7 @@ public function drawPaymentsTable(&$pdf, $object, $posy, $outputlangs) */ protected function drawInfoTable(&$pdf, $object, $posy, $outputlangs, $outputlangsbis) { - global $conf, $mysoc; + global $conf, $mysoc, $hookmanager; $default_font_size = pdf_getPDFFontSize($outputlangs); @@ -1333,6 +1333,13 @@ protected function drawInfoTable(&$pdf, $object, $posy, $outputlangs, $outputlan if (isModEnabled('paybox')) { $useonlinepayment++; } + $parameters = array(); + $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + if (isset($hookmanager->resArray['showonlinepaymenturl'])) { + $useonlinepayment += $hookmanager->resArray['showonlinepaymenturl']; + } + } } diff --git a/htdocs/don/card.php b/htdocs/don/card.php index 44e5b207156fd..a9ffd884b5e1c 100644 --- a/htdocs/don/card.php +++ b/htdocs/don/card.php @@ -974,6 +974,14 @@ // Show online payment link $useonlinepayment = (isModEnabled('paypal') || isModEnabled('stripe') || isModEnabled('paybox')); + $parameters = array(); + $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + if (isset($hookmanager->resArray['showonlinepaymenturl'])) { + $useonlinepayment += $hookmanager->resArray['showonlinepaymenturl']; + } + } + if ($useonlinepayment) { //$object->statut != Facture::STATUS_DRAFT && print '
'."\n"; require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; From 47c98623f4a986923f93c1f00f781abcc3195e66 Mon Sep 17 00:00:00 2001 From: Hystepik Date: Fri, 26 Jan 2024 15:58:22 +0100 Subject: [PATCH 30/60] fix php errors --- htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 1 + htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 1 + 2 files changed, 2 insertions(+) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 13df1c7b90c46..6ac14a9648960 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1239,6 +1239,7 @@ protected function _tableau_info(&$pdf, $object, $posy, $outputlangs, $outputlan $useonlinepayment++; } $parameters = array(); + $action = ''; $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook > 0) { if (isset($hookmanager->resArray['showonlinepaymenturl'])) { diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 1a3db19bab3ce..7f54da1fd99a2 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1334,6 +1334,7 @@ protected function drawInfoTable(&$pdf, $object, $posy, $outputlangs, $outputlan $useonlinepayment++; } $parameters = array(); + $action = ''; $reshook = $hookmanager->executeHooks('doShowOnlinePaymentUrl', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook > 0) { if (isset($hookmanager->resArray['showonlinepaymenturl'])) { From 9c638968ff993a1c96ab07ed36cf8d7ac5da35ea Mon Sep 17 00:00:00 2001 From: tnegre Date: Fri, 26 Jan 2024 16:00:17 +0100 Subject: [PATCH 31/60] Takepos : display errors on payment error --- htdocs/takepos/invoice.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index 4130ac5c3cbc7..db223e58f9ce9 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -305,7 +305,11 @@ function fail($message) if ($pay != "delayed") { $payment->create($user); - $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', ''); + $res = $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', ''); + if ($res < 0) { + $error++; + dol_htmloutput_errors($langs->trans('ErrorNoPaymentDefined'), $payment->errors, 1); + } $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded } } From 673b1727e2c241054bacc0e435fde2d98127c080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sat, 27 Jan 2024 10:38:23 +0100 Subject: [PATCH 32/60] fix getMultidirOutput can't find multidir_output for mycompany --- htdocs/core/class/conf.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 92afb54af522c..e8dd4158b600e 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -534,6 +534,9 @@ public function setValues($db) } // For mycompany storage + $this->mycompany->multidir_output = array($this->entity => $rootfordata."/mycompany"); + $this->mycompany->multidir_temp = array($this->entity => $rootfortemp."/mycompany/temp"); + // For backward compatibility $this->mycompany->dir_output = $rootfordata."/mycompany"; $this->mycompany->dir_temp = $rootfortemp."/mycompany/temp"; From fdfbe63e8f9b4e27b95c6b6bdb87fe3b3d31bbf2 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sat, 27 Jan 2024 13:44:43 +0100 Subject: [PATCH 33/60] qual: Update profid.lib.php - Update isValidTinForES() documentation --- htdocs/core/lib/profid.lib.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/profid.lib.php b/htdocs/core/lib/profid.lib.php index de4f5c70403b6..f1f5d805a0fd3 100644 --- a/htdocs/core/lib/profid.lib.php +++ b/htdocs/core/lib/profid.lib.php @@ -165,12 +165,12 @@ function isValidTinForBE($str) /** * Check the syntax validity of a Spanish (ES) Tax Identification Number (TIN), where: - * - NIF = Número de Identificación Fiscal - * - CIF = Código de Identificación Fiscal + * - NIF = Número de Identificación Fiscal (used for residents only before 2008. Used for both residents and companies since 2008.) + * - CIF = Código de Identificación Fiscal (used for companies only before 2008. Replaced by NIF since 2008.) * - NIE = Número de Identidad de Extranjero * * @param string $str TIN to check - * @return int 1 if NIF ok, 2 if CIF ok, 3 if NIE ok, -1 if NIF bad, -2 if CIF bad, -3 if NIE bad, 0 if unexpected bad + * @return int 1 if NIF ok, 2 if CIF ok, 3 if NIE ok, -1 if NIF bad, -2 if CIF bad, -3 if NIE bad, -4 if unexpected bad * @since Dolibarr V20 */ function isValidTinForES($str) From 0511ec529a29851f71792344ee41bb23978a5023 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sat, 27 Jan 2024 14:02:22 +0100 Subject: [PATCH 34/60] qual: phpstan for htdocs/hrm/job_card.php htdocs/hrm/job_card.php 169 Property CommonObject::$id (int) does not accept null. htdocs/hrm/job_card.php 169 Property Job::$ref (string) does not accept null. --- htdocs/hrm/job_card.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/hrm/job_card.php b/htdocs/hrm/job_card.php index e0cfb3636bf9e..3ca13ca1b7738 100644 --- a/htdocs/hrm/job_card.php +++ b/htdocs/hrm/job_card.php @@ -166,7 +166,8 @@ $object->fetch($id); $skillRequire = $object->getSkillRankForJob($originalId); if ($object->id > 0) { - $object->id = $object->ref = null; + $object->id = 0; + $object->ref = ''; if (GETPOST('clone_label', 'alphanohtml')) { $object->label = GETPOST('clone_label', 'alphanohtml'); From 1d0a6411bc67314d0a2ffca1a5a544c61df43460 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sat, 27 Jan 2024 14:09:04 +0100 Subject: [PATCH 35/60] qual: add phpunit tests for profid.lib.php --- test/phpunit/AllTests.php | 2 + test/phpunit/ProfidLibTest.php | 283 +++++++++++++++++++++++++++++++++ 2 files changed, 285 insertions(+) create mode 100644 test/phpunit/ProfidLibTest.php diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index 5a5c2f48b0248..965ea8a2ce7b4 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -99,6 +99,8 @@ public static function suite() $suite->addTestSuite('FunctionsLibTest'); require_once dirname(__FILE__).'/Functions2LibTest.php'; $suite->addTestSuite('Functions2LibTest'); + require_once dirname(__FILE__).'/ProfidLibTest.php.php'; + $suite->addTestSuite('ProfidLibTest'); require_once dirname(__FILE__).'/XCalLibTest.php'; $suite->addTestSuite('XCalLibTest'); diff --git a/test/phpunit/ProfidLibTest.php b/test/phpunit/ProfidLibTest.php new file mode 100644 index 0000000000000..c0735e7c71bd3 --- /dev/null +++ b/test/phpunit/ProfidLibTest.php @@ -0,0 +1,283 @@ + + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file test/phpunit/ProfidLibTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +global $conf,$user,$langs,$db,$mysoc; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/core/lib/profid.lib.php'; + +if (! defined('NOREQUIREUSER')) { + define('NOREQUIREUSER', '1'); +} +if (! defined('NOREQUIREDB')) { + define('NOREQUIREDB', '1'); +} +if (! defined('NOREQUIRESOC')) { + define('NOREQUIRESOC', '1'); +} +if (! defined('NOREQUIRETRAN')) { + define('NOREQUIRETRAN', '1'); +} +if (! defined('NOCSRFCHECK')) { + define('NOCSRFCHECK', '1'); +} +if (! defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', '1'); +} +if (! defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); // If there is no menu to show +} +if (! defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +} +if (! defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} +if (! defined("NOLOGIN")) { + define("NOLOGIN", '1'); // If this page is public (can be called outside logged session) +} + + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class ProfidLibTest extends PHPUnit\Framework\TestCase +{ + protected $savconf; + protected $savuser; + protected $savlangs; + protected $savdb; + + /** + * Constructor + * We save global variables into local variables + * + * @param string $name Name + * @return CoreTest + */ + public function __construct($name = '') + { + parent::__construct($name); + + //$this->sharedFixture + global $conf,$user,$langs,$db; + $this->savconf=$conf; + $this->savuser=$user; + $this->savlangs=$langs; + $this->savdb=$db; + + print __METHOD__." db->type=".$db->type." user->id=".$user->id; + //print " - db ".$db->db; + print "\n"; + } + + /** + * setUpBeforeClass + * + * @return void + */ + public static function setUpBeforeClass(): void + { + global $conf,$user,$langs,$db; + //$db->begin(); // This is to have all actions inside a transaction even if test launched without suite. + + print __METHOD__."\n"; + } + + /** + * tearDownAfterClass + * + * @return void + */ + public static function tearDownAfterClass(): void + { + global $conf,$user,$langs,$db; + //$db->rollback(); + + print __METHOD__."\n"; + } + + /** + * Init phpunit tests. Restore variables before each test. + * + * @return void + */ + protected function setUp(): void + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + //$db=$this->savdb; + + print __METHOD__."\n"; + } + + /** + * End phpunit tests + * + * @return void + */ + protected function tearDown(): void + { + print __METHOD__."\n"; + } + + + + /** + * testIsValidLuhn + * + * @return void + */ + public function testIsValidLuhn() + { + // Tests OK + $this->assertTrue(isValidLuhn(972487086)); // int + $this->assertTrue(isValidLuhn("972487086")); // string + // Tests KO + $this->assertFalse(isValidLuhn(123456789)); // int + $this->assertFalse(isValidLuhn("123456789")); // string + } + + + + /** + * testIsValidSiren + * + * @return void + */ + public function testIsValidSiren() + { + // Tests OK + $this->assertTrue(isValidSiren("732829320")); + $this->assertTrue(isValidSiren(" 732 829 320 ")); // formatted with spaces + // Tests NOK + $this->assertFalse(isValidSiren("123456ABC")); // not numeric + $this->assertFalse(isValidSiren("43336767")); // Luhn test OK but length != 9 + $this->assertFalse(isValidSiren("123456789")); // 9 digits but Luhn test KO + } + + + + /** + * testIsValidSiret + * + * @return void + */ + public function testIsValidSiret() + { + // Tests OK + $this->assertTrue(isValidSiret("73282932000074")); + $this->assertTrue(isValidSiret(" 732 829 320 00074 ")); // formatted with spaces + $this->assertTrue(isValidSiret("35600000049837")); // Specific cases of "La Poste" companies + // Tests NOK + $this->assertFalse(isValidSiret("123456ABC12345")); // not numeric + $this->assertFalse(isValidSiret("3624679471379")); // Luhn test OK but length != 14 + $this->assertFalse(isValidSiret("12345678912345")); // 14 digits but Luhn test KO + } + + + + /** + * testIsValidTinForPT + * + * @return void + */ + public function testIsValidTinForPT() + { + // Tests OK + $this->assertTrue(isValidTinForPT("123456789")); + $this->assertTrue(isValidTinForPT(" 123 456 789 ")); // formatted with spaces + // Tests NOK + $this->assertFalse(isValidTinForPT("123456ABC")); // not numeric + $this->assertFalse(isValidTinForPT("12345678")); // length != 9 + } + + + + /** + * testIsValidTinForDZ + * + * @return void + */ + public function testIsValidTinForDZ() + { + // Tests OK + $this->assertTrue(isValidTinForDZ("123456789123456")); + $this->assertTrue(isValidTinForDZ(" 12345 67891 23456 ")); // formatted with spaces + // Tests NOK + $this->assertFalse(isValidTinForDZ("123456789123ABC")); // not numeric + $this->assertFalse(isValidTinForDZ("123456789123")); // length != 15 + } + + + + /** + * testIsValidTinForBE + * + * @return void + */ + public function testIsValidTinForBE() + { + // Tests OK + $this->assertTrue(isValidTinForBE("0123.123.123")); + $this->assertTrue(isValidTinForBE("1234.123.123")); + // Tests NOK + //$this->assertFalse(isValidTinForBE("2345.123.123")); // First digit shall be 0 or 1 + $this->assertFalse(isValidTinForBE("1234 123 123")); // formatted with spaces instead of dots + $this->assertFalse(isValidTinForBE("1234123123")); // without dots formatting + $this->assertFalse(isValidTinForBE("ABCD.123.123")); // not digits only + } + + // TODO + /** + * testIsValidTinForES + * + * @return void + */ + /* + public function testIsValidTinForES() + { + // Tests for NIF + $this->assertEquals(1, isValidTinForES("")); // valid NIF + $this->assertEquals(-1, isValidTinForES("")); // valid regex, but invalid control key + // Tests for CIF + $this->assertEquals(2, isValidTinForES("")); // valid CIF + $this->assertEquals(-2, isValidTinForES("")); // valid regex, but invalid control key + // Tests for NIE + $this->assertEquals(3, isValidTinForES("")); // valid NIE + $this->assertEquals(-3, isValidTinForES("")); // valid regex, but invalid control key + // Tests for unknown error + $this->assertEquals(-4, isValidTinForES("")); // invalid regex for both NIF, CIF and NIE + } + */ +} From 49461846484497422846a229820154ea7c4d0ff3 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sat, 27 Jan 2024 14:15:16 +0100 Subject: [PATCH 36/60] phpcs --- test/phpunit/ProfidLibTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/phpunit/ProfidLibTest.php b/test/phpunit/ProfidLibTest.php index c0735e7c71bd3..fdaacbb13ebf3 100644 --- a/test/phpunit/ProfidLibTest.php +++ b/test/phpunit/ProfidLibTest.php @@ -269,13 +269,13 @@ public function testIsValidTinForES() { // Tests for NIF $this->assertEquals(1, isValidTinForES("")); // valid NIF - $this->assertEquals(-1, isValidTinForES("")); // valid regex, but invalid control key + $this->assertEquals(-1, isValidTinForES("")); // valid regex, but invalid control key // Tests for CIF $this->assertEquals(2, isValidTinForES("")); // valid CIF - $this->assertEquals(-2, isValidTinForES("")); // valid regex, but invalid control key + $this->assertEquals(-2, isValidTinForES("")); // valid regex, but invalid control key // Tests for NIE $this->assertEquals(3, isValidTinForES("")); // valid NIE - $this->assertEquals(-3, isValidTinForES("")); // valid regex, but invalid control key + $this->assertEquals(-3, isValidTinForES("")); // valid regex, but invalid control key // Tests for unknown error $this->assertEquals(-4, isValidTinForES("")); // invalid regex for both NIF, CIF and NIE } From 24f85fc1e0f14c682267b3867dd82979fb9cc9e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sat, 27 Jan 2024 18:56:15 +0100 Subject: [PATCH 37/60] add idprofxx missing in societe class --- htdocs/societe/class/societe.class.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index cf7d9aa55b931..15e88771d2488 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -469,6 +469,30 @@ class Societe extends CommonObject */ public $idprof6; + /** + * Professional ID 7 + * @var string + */ + public $idprof7; + + /** + * Professional ID 8 + * @var string + */ + public $idprof8; + + /** + * Professional ID 9 + * @var string + */ + public $idprof9; + + /** + * Professional ID 10 + * @var string + */ + public $idprof10; + /** * Social object of the company * @var string From e6d9dda7290e6956ab21f1bbedd054f749a55f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sat, 27 Jan 2024 20:22:51 +0100 Subject: [PATCH 38/60] Update setup.php --- htdocs/ai/admin/setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/ai/admin/setup.php b/htdocs/ai/admin/setup.php index af410762a8840..33d4954ea2d01 100644 --- a/htdocs/ai/admin/setup.php +++ b/htdocs/ai/admin/setup.php @@ -61,7 +61,7 @@ $arrayofia = array('chatgpt'); -foreach($arrayofia as $ia) { +foreach ($arrayofia as $ia) { // Setup conf AI_PUBLIC_INTERFACE_TOPIC $item = $formSetup->newItem('AI_KEY_API_'.strtoupper($ia)); $item->defaultFieldValue = ''; From 3f327252e1a4332d5248abd43f291ba0dd4a4c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sat, 27 Jan 2024 20:24:05 +0100 Subject: [PATCH 39/60] Update README.md --- htdocs/webportal/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/webportal/README.md b/htdocs/webportal/README.md index 0dddedea0eb89..d9bf8faf0611f 100644 --- a/htdocs/webportal/README.md +++ b/htdocs/webportal/README.md @@ -3,7 +3,7 @@ Module Web Portal This is a module to provide a ready to use Web Portal for your customers, suppliers, partners or members of the mebership module. -Accounts (login and pass) to acces this portal can be created for any thirdparty (from the tab "Web site accounts"). +Accounts (login and pass) to access this portal can be created for any thirdparty (from the tab "Web site accounts"). It is better to have a standalone web server with its own virtual host and domain name to use this module, so using the web portal does not reaveal the domain and url of your backoffice installation. @@ -15,7 +15,7 @@ If the Thirdparty module is enabled: * Read/modify Name, phone, email, addresses of thirdparty If the Patnership module is enabled: -* Read properties (status, stard date, end date) of its partnership. +* Read properties (status, start date, end date) of its partnership. If the Proposal module is enabled: * Read its orders @@ -42,4 +42,4 @@ Documentation [Module Web Portal](https://wiki.dolibarr.org/index.php/Module_Web_Portal) - \ No newline at end of file + From e0b35d2f6bff50d802739cdc9b400fb448ca57ec Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sat, 27 Jan 2024 23:24:01 +0100 Subject: [PATCH 40/60] typo --- test/phpunit/AllTests.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index 965ea8a2ce7b4..7dd60f8431e54 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -99,7 +99,7 @@ public static function suite() $suite->addTestSuite('FunctionsLibTest'); require_once dirname(__FILE__).'/Functions2LibTest.php'; $suite->addTestSuite('Functions2LibTest'); - require_once dirname(__FILE__).'/ProfidLibTest.php.php'; + require_once dirname(__FILE__).'/ProfidLibTest.php'; $suite->addTestSuite('ProfidLibTest'); require_once dirname(__FILE__).'/XCalLibTest.php'; $suite->addTestSuite('XCalLibTest'); From e66d9dd22f5cd04cdfb9347aa063c854795a9cfc Mon Sep 17 00:00:00 2001 From: vmaury Date: Sun, 28 Jan 2024 09:32:53 +0100 Subject: [PATCH 41/60] Fix : random bug when attaching file to email : no file attached --- htdocs/core/class/CMailFile.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index a7eed92b727c7..d52e5139da72a 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -1644,9 +1644,9 @@ private function write_files($filename_list, $mimetype_list, $mimefilename_list, $filename_list_size = count($filename_list); for ($i = 0; $i < $filename_list_size; $i++) { if ($filename_list[$i]) { - dol_syslog("CMailFile::write_files: i=$i"); + dol_syslog("CMailFile::write_files: i=$i ".$filename_list[$i]); $encoded = $this->_encode_file($filename_list[$i]); - if ($encoded >= 0) { + if ($encoded !== -1) { if ($mimefilename_list[$i]) { $filename_list[$i] = $mimefilename_list[$i]; } From 05422868dc10dec88675257086065607076b763e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 28 Jan 2024 14:52:35 +0100 Subject: [PATCH 42/60] Fix codespell --- ChangeLog | 7 ------- htdocs/webportal/README.md | 8 +++----- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9b9664a1cf622..b19c131511eaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -187,15 +187,8 @@ NEW: updating for display Help title when try to delete Don (issue #25314) NEW: Upgrade in module builder in menu section NEW: use account address in sepa mandate (#23642) NEW: VAT rate - Add entity -<<<<<<< HEAD -NEW: webportal site account NEW: When an user unset the batch management of products, transformation of each batch stock movement in global stock movement - -FIX: #25828 wrong odt style naming -======= -NEW: When an user unset the batch management of products, transformation of each batch stock mouvement in global stock mouvement NEW: PDF Generation for each Human Resource Evaluations. ->>>>>>> branch '19.0' of git@github.com:Dolibarr/dolibarr.git SEC: #25512 applicative anti bruteforce - security on too many login attempts (#25520) SEC: Add action confirm_... as sensitive to need a CSRF token diff --git a/htdocs/webportal/README.md b/htdocs/webportal/README.md index 0dddedea0eb89..3d7e82ccbc2d8 100644 --- a/htdocs/webportal/README.md +++ b/htdocs/webportal/README.md @@ -3,7 +3,7 @@ Module Web Portal This is a module to provide a ready to use Web Portal for your customers, suppliers, partners or members of the mebership module. -Accounts (login and pass) to acces this portal can be created for any thirdparty (from the tab "Web site accounts"). +Accounts (login and pass) to access this portal can be created for any thirdparty (from the tab "Web site accounts"). It is better to have a standalone web server with its own virtual host and domain name to use this module, so using the web portal does not reaveal the domain and url of your backoffice installation. @@ -15,8 +15,8 @@ If the Thirdparty module is enabled: * Read/modify Name, phone, email, addresses of thirdparty If the Patnership module is enabled: -* Read properties (status, stard date, end date) of its partnership. - +* Read properties (status, start date, end date) of its partnership. + If the Proposal module is enabled: * Read its orders @@ -41,5 +41,3 @@ Documentation ------------- [Module Web Portal](https://wiki.dolibarr.org/index.php/Module_Web_Portal) - - \ No newline at end of file From e3c606b9eb75e7348b8bffe04a5ebcadc058df39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Sun, 28 Jan 2024 15:32:34 +0100 Subject: [PATCH 43/60] fix precommit --- htdocs/website/class/website.class.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 642447afc2335..3d5ad0b9ba665 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1662,7 +1662,7 @@ public function overwriteTemplate() if ($nomFichierModifie == basename($fichierEtat)) { continue; } - $succes = 0; + $success = 0; //check if it is a new file if ((!preg_match('/^page\d+\.tpl\.php$/', $nomFichierModifie)) && (!in_array($nomFichierModifie, $names))) { @@ -1701,9 +1701,9 @@ public function overwriteTemplate() } $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->replaceLignEUsingNum($destdir.'/containers/'."page" . $nextpage . ".tpl.php", $diff); + $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 succes", null, 'warnings'); + setEventMessages("Copy file page".$nextpage.".tpl.php in template ".$this->name_template." with success", null, 'warnings'); } } } @@ -1727,7 +1727,7 @@ public function overwriteTemplate() if ($sourceContent !== $destContent) { $differences[$nomFichierModifie] = $this->showDifferences($destContent, $sourceContent); if (count($differences[$nomFichierModifie]) > 0) { - $result = $this->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); + $result = $this->replaceLineUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { setEventMessages("No permissions to write in file ".$nomFichierModifie." from template ".$website->name_template."", null, 'errors'); @@ -1744,21 +1744,21 @@ public function overwriteTemplate() if (preg_match('/page(\d+)\.tpl\.php/', $nomFichierModifie)) { $differences[$nomFichierModifie] = $this->compareFichierModifie($sourcedir, $destdir, $fichierModifie); if (count($differences[$nomFichierModifie]) > 0) { - $result = $this->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); + $result = $this->replaceLineUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { setEventMessages("No permissions to write in file ".$differences[$nomFichierModifie]['file_destination']['name']." from template ".$website->name_template."", null, 'errors'); header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); exit(); } - $succes++; + $success++; } } } } } } - if ($succes>0) { + if ($success>0) { // save state file $this->saveState($etatPrecedent, $fichierEtat); setEventMessages("file ".$differences[$nomFichierModifie]['file_destination']['name']." was modified in template ".$website->name_template."", null, 'warnings'); @@ -1848,7 +1848,7 @@ public function initFilesStatus($sourcedir) $etatPrecedent = $this->checkPreviousState($fichierEtat); - // for first save state when ceate file + // for first save state when create file if (empty($etatPrecedent)) { $arraySourcedir = dol_dir_list($sourcedir, "files"); $etatFichiers = []; @@ -1968,7 +1968,7 @@ private function normalizeString($str) * show difference between to string * @param string $str1 first string * @param string $str2 seconde string - * @param array $exceptNumPge num of page files we dont want to change + * @param array $exceptNumPge num of page files we don't want to change * @return array|int -1 if KO, array if OK */ protected function showDifferences($str1, $str2, $exceptNumPge = array()) @@ -2055,12 +2055,12 @@ protected function showDifferences($str1, $str2, $exceptNumPge = array()) } /** - * Replace ligne by ligne in file using num of ligne + * Replace line by line in file using num of line * @param string $desfFile path of file dest * @param array $differences array of differences between files - * @return false|int false if we cant replace + * @return false|int false if we can't replace */ - protected function replaceLignEUsingNum($desfFile, $differences) + protected function replaceLineUsingNum($desfFile, $differences) { $userId = fileowner($desfFile); if ($userId !== false) { @@ -2095,7 +2095,7 @@ protected function replaceLignEUsingNum($desfFile, $differences) unset($contentDest[$numLigne]); } } - //Reindex the table keys + // Reindex the table keys $contentDest = array_values($contentDest); $stringreplacement = implode("\n", $contentDest); file_put_contents($desfFile, $stringreplacement); From 14b14a3b0f10d56e8dd0c37c41c853d9feb2d501 Mon Sep 17 00:00:00 2001 From: MDW Date: Sun, 28 Jan 2024 15:38:23 +0100 Subject: [PATCH 44/60] Add --files to pre-commit call for selected files --- .github/workflows/pre-commit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index e96c5ef4ba049..a34b2d0ad7e4f 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -69,7 +69,7 @@ jobs: ALL_CHANGED_FILES: ${{ steps.changed-php.outputs.all_changed_files }} run: | set -o pipefail - pre-commit run php-cs ${ALL_CHANGED_FILES} | tee -a ${RAW_LOG} + pre-commit run php-cs --files ${ALL_CHANGED_FILES} | tee -a ${RAW_LOG} # If error, we convert log in the checkstyle format - name: Convert Raw Log to CheckStyle format From 4c077ebc4ee5a025da91f154e1579885b5f195f8 Mon Sep 17 00:00:00 2001 From: MDW Date: Sun, 28 Jan 2024 15:51:14 +0100 Subject: [PATCH 45/60] Fix: pre-commit - install required phpcs # Fix: pre-commit - install required phpcs --- .github/workflows/pre-commit.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index a34b2d0ad7e4f..c685645c504c4 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -63,6 +63,14 @@ jobs: # files: | # **.php + - name: Setup PHPCS + uses: shivammathur/setup-php@v2 + if: steps.changed-php.outputs.any_changed == 'true' + with: + php-version: 8.1 + coverage: none # disable xdebug, pcov + tools: phpcs + - name: Run some pre-commit hooks on selected changed files only if: steps.changed-php.outputs.any_changed == 'true' env: From 92cf4f2fd1ae52ea63376b237761a80cea1464d9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 28 Jan 2024 16:36:01 +0100 Subject: [PATCH 46/60] Mutualize code --- htdocs/admin/ticket_public.php | 6 +++--- htdocs/core/modules/modWebPortal.class.php | 2 ++ htdocs/langs/en_US/admin.lang | 2 ++ htdocs/langs/en_US/ticket.lang | 2 -- htdocs/langs/en_US/website.lang | 2 -- htdocs/langs/fr_FR/admin.lang | 1 + htdocs/langs/fr_FR/ticket.lang | 1 - htdocs/webportal/admin/configcss.php | 2 +- htdocs/webportal/admin/setup.php | 8 ++++---- htdocs/webportal/admin/setup_theme.php | 2 +- htdocs/website/index.php | 14 +++++++++----- 11 files changed, 23 insertions(+), 19 deletions(-) diff --git a/htdocs/admin/ticket_public.php b/htdocs/admin/ticket_public.php index e083c87d205e3..e58b0599b7601 100644 --- a/htdocs/admin/ticket_public.php +++ b/htdocs/admin/ticket_public.php @@ -476,12 +476,12 @@ // Url public interface $url_interface = getDolGlobalString("TICKET_URL_PUBLIC_INTERFACE"); - print ''.$langs->trans("TicketUrlPublicInterfaceLabelAdmin").''; + print ''.$langs->trans("UrlPublicInterfaceLabelAdmin").''; print ''; - print ''; + print ''; print ''; print ''; - print $form->textwithpicto('', $langs->trans("TicketUrlPublicInterfaceHelpAdmin"), 1, 'help'); + print $form->textwithpicto('', $langs->trans("UrlPublicInterfaceHelpAdmin"), 1, 'help'); print ''; print ''; diff --git a/htdocs/core/modules/modWebPortal.class.php b/htdocs/core/modules/modWebPortal.class.php index 6bd2885f31a45..99f31d1907fe4 100644 --- a/htdocs/core/modules/modWebPortal.class.php +++ b/htdocs/core/modules/modWebPortal.class.php @@ -280,6 +280,7 @@ public function __construct($db) $this->menu = array(); $r = 0; // Add here entries to declare new menus + /* $this->menu[$r++] = array( 'fk_menu' => '', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 'type' => 'top', // This is a Top menu entry @@ -295,6 +296,7 @@ public function __construct($db) 'target' => '', 'user' => 2, // 0=Menu for internal users, 1=external users, 2=both ); + */ /*$this->menu[$r++]=array( 'fk_menu'=>'fk_mainmenu=webportal', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 'type'=>'left', // This is a Left menu entry diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index fac5f950a3096..1a8c9492605be 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2437,3 +2437,5 @@ ParametersForTestEnvironment=Parameters for test environment TryToKeepOnly=Try to keep only %s RecommendedForProduction=Recommended for Production RecommendedForDebug=Recommended for Debug +UrlPublicInterfaceLabelAdmin=Alternative URL for public interface +UrlPublicInterfaceHelpAdmin=It is possible to define an alias to the web server and thus make available the public interface with another URL (the virtual host server must act as a proxy on the standard URL) diff --git a/htdocs/langs/en_US/ticket.lang b/htdocs/langs/en_US/ticket.lang index 460e73e1cf107..e1493e9c14b4d 100644 --- a/htdocs/langs/en_US/ticket.lang +++ b/htdocs/langs/en_US/ticket.lang @@ -107,8 +107,6 @@ TicketsShowProgressionHelp=Enable this option to hide the progress of the ticket TicketCreateThirdPartyWithContactIfNotExist=Ask name and company name for unknown emails. TicketCreateThirdPartyWithContactIfNotExistHelp=Check if a third party or a contact exists for the email entered. If not, ask a name and a company name to create a third party with contact. PublicInterface=Public interface -TicketUrlPublicInterfaceLabelAdmin=Alternative URL for public interface -TicketUrlPublicInterfaceHelpAdmin=It is possible to define an alias to the web server and thus make available the public interface with another URL (the server must act as a proxy on this new URL) TicketPublicInterfaceTextHomeLabelAdmin=Welcome text of the public interface TicketPublicInterfaceTextHome=You can create a support ticket or view existing from its identifier tracking ticket. TicketPublicInterfaceTextHomeHelpAdmin=The text defined here will appear on the home page of the public interface. diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 1b076f689b474..6d457dfb33bb2 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -174,8 +174,6 @@ WebPortalSetup = WebPortal setup WebPortalCSS=Web portal CSS Settings = Settings WebPortalSetupPage = WebPortal setup page -WEBPORTAL_ROOT_URL = Alternative virtual host URL -WebPortalRootUrlHelp = Public access url (http or https) if you have a virtual host or keep empty WEBPORTAL_TITLE = Brand name on header of public page UserAccountForWebPortalAreInThirdPartyTabHelp = Users accounts for WebPortal can be set on each third party card in Website accounts tab WebPortalAccessHidden = Hidden diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index b9876492cddb2..9864434ff1428 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -2440,3 +2440,4 @@ ParametersForTestEnvironment=Paramètres pour l'environnement de test TryToKeepOnly=Essayez de ne conserver que %s RecommendedForProduction=Recommandé pour la production RecommendedForDebug=Recommandé pour le débogage +UrlPublicInterfaceHelpAdmin=Il est possible de définir un alias vers le serveur et de rendre ainsi l'interface publique accessible avec une autre URL (le serveur doit agir comme un proxy sur cette nouvelle URL) diff --git a/htdocs/langs/fr_FR/ticket.lang b/htdocs/langs/fr_FR/ticket.lang index e8c90035e072c..d910042f8cafe 100644 --- a/htdocs/langs/fr_FR/ticket.lang +++ b/htdocs/langs/fr_FR/ticket.lang @@ -108,7 +108,6 @@ TicketCreateThirdPartyWithContactIfNotExist=Demandez le nom et le nom de l'entre TicketCreateThirdPartyWithContactIfNotExistHelp=Vérifiez s'il existe un tiers ou un contact pour l'e-mail saisi. Sinon, demandez un nom et un nom société pour créer un tiers avec contact. PublicInterface=Interface publique TicketUrlPublicInterfaceLabelAdmin=URL alternative pour l'interface publique -TicketUrlPublicInterfaceHelpAdmin=Il est possible de définir un alias vers le serveur et de rendre ainsi l'interface publique accessible avec une autre URL (le serveur doit agir comme un proxy sur cette nouvelle URL) TicketPublicInterfaceTextHomeLabelAdmin=Texte de bienvenue dans l'interface publique TicketPublicInterfaceTextHome=Vous pouvez créer un ticket ou consulter à partir d'un ID de ticket existant. TicketPublicInterfaceTextHomeHelpAdmin=Le texte défini ici apparaîtra sur la page d'accueil de l'interface publique. diff --git a/htdocs/webportal/admin/configcss.php b/htdocs/webportal/admin/configcss.php index 56842f4cf7436..8f68e8e81c897 100644 --- a/htdocs/webportal/admin/configcss.php +++ b/htdocs/webportal/admin/configcss.php @@ -29,7 +29,7 @@ require_once DOL_DOCUMENT_ROOT . "/webportal/lib/webportal.lib.php"; // Translations -$langs->loadLangs(array("admin", "hrm", "other")); +$langs->loadLangs(array("admin", "hrm", "other", "website")); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('webportalsetup', 'globalsetup')); diff --git a/htdocs/webportal/admin/setup.php b/htdocs/webportal/admin/setup.php index 334a97336cd4e..78e183d2a954e 100644 --- a/htdocs/webportal/admin/setup.php +++ b/htdocs/webportal/admin/setup.php @@ -57,15 +57,15 @@ if (!class_exists('FormSetup')) { require_once DOL_DOCUMENT_ROOT . '/core/class/html.formsetup.class.php'; } - $formSetup = new FormSetup($db); // root url $item = $formSetup->newItem('WEBPORTAL_ROOT_URL')->setAsString(); +$item->nameText = $langs->transnoentities('UrlPublicInterfaceLabelAdmin'); $item->fieldAttr = array('placeholder' => 'https://'); -$item->helpText = $langs->transnoentities('WebPortalRootUrlHelp'); +$item->helpText = $langs->transnoentities('UrlPublicInterfaceHelpAdmin'); require_once __DIR__ . '/../class/context.class.php'; -$context = Context::getInstance(); +//$context = Context::getInstance(); //$item->fieldOutputOverride = ''.img_picto('', 'globe', 'class="pictofixedwidth"').Context::getRootConfigUrl().''; @@ -270,7 +270,7 @@ // Setup page goes here print info_admin($langs->trans("UserAccountForWebPortalAreInThirdPartyTabHelp")); -print '
'; +print '

'; if ($action == 'edit') { print $formSetup->generateOutput(true); diff --git a/htdocs/webportal/admin/setup_theme.php b/htdocs/webportal/admin/setup_theme.php index 1e751389feade..9900f89d20159 100644 --- a/htdocs/webportal/admin/setup_theme.php +++ b/htdocs/webportal/admin/setup_theme.php @@ -28,7 +28,7 @@ require_once DOL_DOCUMENT_ROOT . "/webportal/lib/webportal.lib.php"; // Translations -$langs->loadLangs(array("admin", "webportal")); +$langs->loadLangs(array("admin", "webportal", "website")); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('webportalthemesetup', 'globalsetup')); diff --git a/htdocs/website/index.php b/htdocs/website/index.php index cd9859e447fcc..7e0e6183b72b2 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2417,9 +2417,11 @@ } } -// Overite site -if ($action == 'overwitesite' && $user->hasRight('website', 'export')) { - $fileofzip = $object->overwriteTemplate(); +// Overwrite site +if ($action == 'overwritesite' && $user->hasRight('website', 'export')) { + if (getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE')) { + $fileofzip = $object->overwriteTemplate(); + } } // Regenerate site if ($action == 'regeneratesite' && $usercanedit) { @@ -3065,8 +3067,10 @@ print ''; } - // overite template - print 'ref).'" class="button bordertransp"> '.dol_escape_htmltag($langs->trans("Overwrite")).''; + if (getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE')) { + // overite template + print 'ref).'" class="button bordertransp"> '.dol_escape_htmltag($langs->trans("Overwrite")).''; + } } else { print ''; } From 64233c312e1c317ebe4b9b639cebadc524216c91 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 28 Jan 2024 17:05:15 +0100 Subject: [PATCH 47/60] Debug v20 --- htdocs/website/class/website.class.php | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 642447afc2335..7b6f2a00f3f06 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1608,8 +1608,9 @@ public function componentSelectLang($languagecodes, $weblangs, $morecss = '', $h } /** - * Overite template by copy and past all files - * @return void + * Overite template by copying all files + * + * @return int <0 if KO, >0 if OK */ public function overwriteTemplate() { @@ -1618,11 +1619,15 @@ public function overwriteTemplate() $website = $this; if (empty($website->id) || empty($website->ref)) { setEventMessages("Website id or ref is not defined", null, 'errors'); - return false; + return -1; + } + if (empty($website->name_template)) { + setEventMessages("To export the website template into the GIT sources directory, the name of the directory/template must be know. For this website, the variable 'name_template' is unknown, so export in GIT sources is not possible.", null, 'errors'); + return -1; } if (!is_writable($conf->website->dir_temp)) { setEventMessages("Temporary dir ".$conf->website->dir_temp." is not writable", null, 'errors'); - return ''; + return -1; } $sourcedir = $conf->website->dir_output."/".$website->ref; @@ -1717,6 +1722,7 @@ public function overwriteTemplate() } } } + // Find the corresponding file in the destination folder if (in_array($nomFichierModifie, $namesSource)) { foreach ($arraydestdir as $destFile) { @@ -1730,7 +1736,7 @@ public function overwriteTemplate() $result = $this->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { - setEventMessages("No permissions to write in file ".$nomFichierModifie." from template ".$website->name_template."", null, 'errors'); + setEventMessages("No permissions to write in file ".$nomFichierModifie." from the template ".$website->name_template."", null, 'errors'); header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); exit(); } @@ -1747,7 +1753,7 @@ public function overwriteTemplate() $result = $this->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { - setEventMessages("No permissions to write in file ".$differences[$nomFichierModifie]['file_destination']['name']." from template ".$website->name_template."", null, 'errors'); + setEventMessages("No permissions to write in file ".$differences[$nomFichierModifie]['file_destination']['name']." from the template ".$website->name_template."", null, 'errors'); header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); exit(); } @@ -1768,8 +1774,10 @@ public function overwriteTemplate() } else { setEventMessages("No file has been modified", null, 'errors'); } + // save state file $this->saveState($etatPrecedent, $fichierEtat); + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$website->ref); exit(); } From ec3687528efb97e0e5cc1ae1832e77afafe3eaa5 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sun, 28 Jan 2024 17:11:12 +0100 Subject: [PATCH 48/60] qual: Update ProfidLibTest.php - uncomment line testing that BE TIN shall start by 0 or 1 Since PR#27829 has been merged, we can now uncomment the line testing that a the Belgium Tax Identification Number shall start by 0 or 1. --- test/phpunit/ProfidLibTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/phpunit/ProfidLibTest.php b/test/phpunit/ProfidLibTest.php index fdaacbb13ebf3..a0995e9d246aa 100644 --- a/test/phpunit/ProfidLibTest.php +++ b/test/phpunit/ProfidLibTest.php @@ -252,7 +252,7 @@ public function testIsValidTinForBE() $this->assertTrue(isValidTinForBE("0123.123.123")); $this->assertTrue(isValidTinForBE("1234.123.123")); // Tests NOK - //$this->assertFalse(isValidTinForBE("2345.123.123")); // First digit shall be 0 or 1 + $this->assertFalse(isValidTinForBE("2345.123.123")); // First digit shall be 0 or 1 $this->assertFalse(isValidTinForBE("1234 123 123")); // formatted with spaces instead of dots $this->assertFalse(isValidTinForBE("1234123123")); // without dots formatting $this->assertFalse(isValidTinForBE("ABCD.123.123")); // not digits only From f03f5b6be4f26154be9813cd2d4a85d1fdbb488f Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sun, 28 Jan 2024 17:35:17 +0100 Subject: [PATCH 49/60] qual: phpstan for htdocs/fourn/class/fournisseur.commande.class.php htdocs/fourn/class/fournisseur.commande.class.php 1146 Method CommandeFournisseur::getNextNumRef() should return string but returns int. htdocs/fourn/class/fournisseur.commande.class.php 1150 Method CommandeFournisseur::getNextNumRef() should return string but returns int. htdocs/fourn/class/fournisseur.commande.class.php 1867 Property CommandeFournisseur::$date_creation (int) does not accept string. htdocs/fourn/class/fournisseur.commande.class.php 1869 Property CommandeFournisseur::$ref_supplier (string) does not accept null. htdocs/fourn/class/fournisseur.commande.class.php 1870 Property CommandeFournisseur::$user_approve_id (int) does not accept string. htdocs/fourn/class/fournisseur.commande.class.php 1871 Property CommandeFournisseur::$user_approve_id2 (int) does not accept string. htdocs/fourn/class/fournisseur.commande.class.php 1872 Property CommandeFournisseur::$date_approve (int) does not accept string. htdocs/fourn/class/fournisseur.commande.class.php 1873 Property CommandeFournisseur::$date_approve2 (int) does not accept string. htdocs/fourn/class/fournisseur.commande.class.php 3020 Property CommonOrderLine::$remise_percent (float) does not accept string. htdocs/fourn/class/fournisseur.commande.class.php 3048 Property CommonOrderLine::$remise_percent (float) does not accept string. --- .../class/fournisseur.commande.class.php | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index d72a1454db746..ab6cb325a490c 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1104,11 +1104,11 @@ public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $save_la /** - * Returns the following order reference not used depending on the numbering model activated - * defined within COMMANDE_SUPPLIER_ADDON_NUMBER + * Returns the next order reference not used, based on the + * numbering model defined within COMMANDE_SUPPLIER_ADDON_NUMBER * * @param Societe $soc company object - * @return string free reference for the invoice + * @return string|int free reference for the invoice */ public function getNextNumRef($soc) { @@ -1864,13 +1864,13 @@ public function createFromClone(User $user, $socid = 0, $notrigger = 0) // Clear fields $this->user_author_id = $user->id; $this->user_validation_id = 0; - $this->date_creation = ''; - $this->date_validation = ''; - $this->ref_supplier = null; - $this->user_approve_id = ''; - $this->user_approve_id2 = ''; - $this->date_approve = ''; - $this->date_approve2 = ''; + $this->date_creation = 0; + $this->date_validation = 0; + $this->ref_supplier = ''; + $this->user_approve_id = 0; + $this->user_approve_id2 = 0; + $this->date_approve = 0; + $this->date_approve2 = 0; // Create clone $this->context['createfromclone'] = 'createfromclone'; @@ -2923,7 +2923,7 @@ public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $t $remise_percent = 0; } - $remise_percent = price2num($remise_percent); + $remise_percent = (float) price2num($remise_percent); $qty = price2num($qty); if (!$qty) { $qty = 1; From 6f18b66bfac64d68243315a19c3c9866e133b8bc Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sun, 28 Jan 2024 17:38:46 +0100 Subject: [PATCH 50/60] doc --- htdocs/fourn/class/fournisseur.commande.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index ab6cb325a490c..4f4a06dc51252 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1108,7 +1108,7 @@ public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $save_la * numbering model defined within COMMANDE_SUPPLIER_ADDON_NUMBER * * @param Societe $soc company object - * @return string|int free reference for the invoice + * @return string|int free reference for the invoice. '', -1 or -2 if error. */ public function getNextNumRef($soc) { From 83154b2809b73cbb6346d904f80b18e7585bdbfb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 28 Jan 2024 17:41:47 +0100 Subject: [PATCH 51/60] Better messages --- htdocs/website/class/website.class.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 7b6f2a00f3f06..45c047b94bd7e 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1632,12 +1632,15 @@ public function overwriteTemplate() $sourcedir = $conf->website->dir_output."/".$website->ref; - $fichierEtat = $sourcedir . '/etat_fichiers.txt'; + $fichierEtat = $sourcedir . '/filelist-lastwrite-doctemplates.txt'; + // Get array with hash of files $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') { @@ -1650,12 +1653,12 @@ public function overwriteTemplate() $modifications[] = $file; } - $etatPrecedent[$file['name']] = $hashActuel; + $etatPrecedent[$file['name']] = $hashActuel; // we store he new hash to record it later on disk. } - // listed modified files - - $destdir = DOL_DOCUMENT_ROOT . '/install/doctemplates/websites/'.$website->name_template; + // Replace modified files into the doctemplates directory. + $destdirrel = 'install/doctemplates/websites/'.$website->name_template; + $destdir = DOL_DOCUMENT_ROOT.'/'.$destdirrel; $arraydestdir = dol_dir_list($destdir, "all", 1); $differences = []; $names = array_column($arraydestdir, 'name'); @@ -1736,7 +1739,7 @@ public function overwriteTemplate() $result = $this->replaceLignEUsingNum($destFile['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { - setEventMessages("No permissions to write in file ".$nomFichierModifie." from the template ".$website->name_template."", null, 'errors'); + 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(); } @@ -1753,7 +1756,7 @@ public function overwriteTemplate() $result = $this->replaceLignEUsingNum($differences[$nomFichierModifie]['file_destination']['fullname'], $differences[$nomFichierModifie]); if ($result !== false) { if ($result == -2) { - setEventMessages("No permissions to write in file ".$differences[$nomFichierModifie]['file_destination']['name']." from the template ".$website->name_template."", null, 'errors'); + 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(); } @@ -1765,7 +1768,7 @@ public function overwriteTemplate() } } if ($succes>0) { - // save state file + // 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); @@ -1852,7 +1855,7 @@ public function saveState($etat, $pathname) */ public function initFilesStatus($sourcedir) { - $fichierEtat = $sourcedir . '/etat_fichiers.txt'; + $fichierEtat = $sourcedir . '/filelist-lastwrite-doctemplates.txt'; $etatPrecedent = $this->checkPreviousState($fichierEtat); From 38f897609d24bfb2214c6fa5c20478b896c3b227 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 28 Jan 2024 17:47:50 +0100 Subject: [PATCH 52/60] Trans --- htdocs/langs/en_US/website.lang | 1 + htdocs/website/index.php | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 6d457dfb33bb2..d97f4ff23ac6f 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -232,3 +232,4 @@ WebPortalErrorFetchLoggedUser = Error when loading user (Id : %s) WebPortalErrorFetchLoggedThirdParty = Error when loading third-party (Id : %s) WebPortalErrorFetchLoggedMember = Error when loading member (Id : %s) WebPortalErrorFetchLoggedPartnership = Error when loading partnership (Third-party Id : %s, Member Id : %s) +ExportIntoGIT=Export into sources \ No newline at end of file diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 7e0e6183b72b2..872431c1bb9b0 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -3022,6 +3022,11 @@ // Export web site print ''; + if (getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE')) { + // Overwrite template in sources + print 'ref).'" class="button bordertransp">'.dol_escape_htmltag($langs->trans("ExportIntoGIT")).''; + } + // Clone web site print ''; @@ -3067,10 +3072,6 @@ print ''; } - if (getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE')) { - // overite template - print 'ref).'" class="button bordertransp"> '.dol_escape_htmltag($langs->trans("Overwrite")).''; - } } else { print ''; } From 044395bda6f7a267f906eeee737fa984c50fbb11 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Sun, 28 Jan 2024 17:53:16 +0100 Subject: [PATCH 53/60] qual: phpstan for htdocs/product/class/product.class.php htdocs/product/class/product.class.php 2449 Property Product::$price (float) does not accept string. htdocs/product/class/product.class.php 2450 Property Product::$price_ttc (float) does not accept string. htdocs/product/class/product.class.php 2909 Property Product::$price_ttc (float) does not accept string. htdocs/product/class/product.class.php 5077 Method Product::isVariant() should return int but returns false. htdocs/product/class/product.class.php 5079 Method Product::isVariant() should return int but returns true. htdocs/product/class/product.class.php 5085 Method Product::isVariant() should return int but returns false. htdocs/product/class/product.class.php 5608 Method Product::getLibFinished() should return string but returns int. --- htdocs/product/class/product.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 3e0d45f75f40d..1858ed5f98598 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2358,7 +2358,7 @@ public function updatePrice($newprice, $newpricebase, $user, $newvat = '', $newm $price_min_ttc = 0; } } else { - $price = price2num($newprice, 'MU'); + $price = (float) price2num($newprice, 'MU'); $price_ttc = ($newnpr != 1) ? (float) price2num($newprice) * (1 + ($newvat / 100)) : $price; $price_ttc = price2num($price_ttc, 'MU'); @@ -2905,8 +2905,8 @@ public function fetch($id = 0, $ref = '', $ref_ext = '', $barcode = '', $ignore_ if ($price_result >= 0) { $this->price = $price_result; // Calculate the VAT - $this->price_ttc = price2num($this->price) * (1 + ($this->tva_tx / 100)); - $this->price_ttc = price2num($this->price_ttc, 'MU'); + $this->price_ttc = (float) price2num($this->price) * (1 + ($this->tva_tx / 100)); + $this->price_ttc = (float) price2num($this->price_ttc, 'MU'); } } @@ -5062,7 +5062,7 @@ public function hasVariants() /** * Return if loaded product is a variant * - * @return int + * @return bool|int Return true if the product is a variant, false if not, -1 if error */ public function isVariant() { @@ -5587,7 +5587,7 @@ public function LibStatut($status, $mode = 0, $type = 0) /** * Retour label of nature of product * - * @return string Label + * @return string|int Return label or ''. -1 if error */ public function getLibFinished() { From 7baa02bda5c14d94231e551fe4ff76a14be6ca38 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 28 Jan 2024 18:22:21 +0100 Subject: [PATCH 54/60] Debug export website --- htdocs/core/lib/files.lib.php | 8 +++----- htdocs/website/class/website.class.php | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index c842276835df0..f5d930f26b6f9 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2194,9 +2194,8 @@ function dol_convert_file($fileinput, $ext = 'png', $fileoutput = '', $page = '' */ function dol_compress_file($inputfile, $outputfile, $mode = "gz", &$errorstring = null) { - global $conf; - $foundhandler = 0; + //var_dump(basename($inputfile)); exit; try { dol_syslog("dol_compress_file mode=".$mode." inputfile=".$inputfile." outputfile=".$outputfile); @@ -2265,6 +2264,7 @@ function dol_compress_file($inputfile, $outputfile, $mode = "gz", &$errorstring include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php'; $archive = new PclZip($outputfile); + $result = $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile)); if ($result === 0) { @@ -2439,7 +2439,7 @@ function dol_uncompress($inputfile, $outputdir) * @param string $inputdir Source dir name * @param string $outputfile Target file name (output directory must exists and be writable) * @param string $mode 'zip' - * @param string $excludefiles A regex pattern. For example: '/\.log$|\/temp\//' + * @param string $excludefiles A regex pattern to exclude files. For example: '/\.log$|\/temp\//' * @param string $rootdirinzip Add a root dir level in zip file * @param string $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666' * @return int Return integer <0 if KO, >0 if OK @@ -2447,8 +2447,6 @@ function dol_uncompress($inputfile, $outputdir) */ function dol_compress_dir($inputdir, $outputfile, $mode = "zip", $excludefiles = '', $rootdirinzip = '', $newmask = 0) { - global $conf; - $foundhandler = 0; dol_syslog("Try to zip dir ".$inputdir." into ".$outputfile." mode=".$mode); diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 45c047b94bd7e..c6821322778d6 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1154,7 +1154,8 @@ public function exportWebSite() $filename = $conf->website->dir_temp.'/'.$website->ref.'/website_'.$website->ref.'-'.dol_print_date(dol_now(), 'dayhourlog').'-V'.((float) DOL_VERSION).'.zip'; dol_delete_file($fileglob, 0); - $result = dol_compress_file($filedir, $filename, 'zip'); + + $result = dol_compress_dir($filedir, $filename, 'zip'); if ($result > 0) { return $filename; From 61b1aee956f1d6c7fd54909f64e797e1c2d49ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sun, 28 Jan 2024 18:26:30 +0100 Subject: [PATCH 55/60] Update website.class.php --- htdocs/website/class/website.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 96919e1015912..a0f7cec7e0d50 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1610,7 +1610,7 @@ public function componentSelectLang($languagecodes, $weblangs, $morecss = '', $h /** * Overite template by copying all files * - * @return int <0 if KO, >0 if OK + * @return int Return integer <0 if KO, >0 if OK */ public function overwriteTemplate() { From ddb134c43ed06b729f5c1d9248dfea3395dcaba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sun, 28 Jan 2024 18:44:17 +0100 Subject: [PATCH 56/60] Update pre-commit.yml --- .github/workflows/pre-commit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index e96c5ef4ba049..a34b2d0ad7e4f 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -69,7 +69,7 @@ jobs: ALL_CHANGED_FILES: ${{ steps.changed-php.outputs.all_changed_files }} run: | set -o pipefail - pre-commit run php-cs ${ALL_CHANGED_FILES} | tee -a ${RAW_LOG} + pre-commit run php-cs --files ${ALL_CHANGED_FILES} | tee -a ${RAW_LOG} # If error, we convert log in the checkstyle format - name: Convert Raw Log to CheckStyle format From d688f12c07a6b4208a6a80acb457e06ac5999e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sun, 28 Jan 2024 21:53:26 +0100 Subject: [PATCH 57/60] Update functions.lib.php --- htdocs/core/lib/functions.lib.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index cff1b5b85aabe..352c0ea1012e0 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8175,6 +8175,10 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, '__MYCOMPANY_PROFID4__' => $mysoc->idprof4, '__MYCOMPANY_PROFID5__' => $mysoc->idprof5, '__MYCOMPANY_PROFID6__' => $mysoc->idprof6, + '__MYCOMPANY_PROFID7__' => $mysoc->idprof7, + '__MYCOMPANY_PROFID8__' => $mysoc->idprof8, + '__MYCOMPANY_PROFID9__' => $mysoc->idprof9, + '__MYCOMPANY_PROFID10__' => $mysoc->idprof10, '__MYCOMPANY_CAPITAL__' => $mysoc->capital, '__MYCOMPANY_FULLADDRESS__' => (method_exists($mysoc, 'getFullAddress') ? $mysoc->getFullAddress(1, ', ') : ''), // $mysoc may be stdClass '__MYCOMPANY_ADDRESS__' => $mysoc->address, @@ -8217,6 +8221,10 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__THIRDPARTY_IDPROF4__'] = '__THIRDPARTY_IDPROF4__'; $substitutionarray['__THIRDPARTY_IDPROF5__'] = '__THIRDPARTY_IDPROF5__'; $substitutionarray['__THIRDPARTY_IDPROF6__'] = '__THIRDPARTY_IDPROF6__'; + $substitutionarray['__MYCOMPANY_PROFID7__'] => '__MYCOMPANY_PROFID7__', + $substitutionarray['__MYCOMPANY_PROFID8__'] => '__MYCOMPANY_PROFID8__', + $substitutionarray['__MYCOMPANY_PROFID9__'] => '__MYCOMPANY_PROFID9__', + $substitutionarray['__MYCOMPANY_PROFID10__'] => '__MYCOMPANY_PROFID10__', $substitutionarray['__THIRDPARTY_TVAINTRA__'] = '__THIRDPARTY_TVAINTRA__'; $substitutionarray['__THIRDPARTY_NOTE_PUBLIC__'] = '__THIRDPARTY_NOTE_PUBLIC__'; $substitutionarray['__THIRDPARTY_NOTE_PRIVATE__'] = '__THIRDPARTY_NOTE_PRIVATE__'; From 3a6cdf6411cad14ac48d6d43ad13d628d562ea24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sun, 28 Jan 2024 23:19:56 +0100 Subject: [PATCH 58/60] Update functions.lib.php --- htdocs/core/lib/functions.lib.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 352c0ea1012e0..3d12972e66254 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8221,10 +8221,10 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__THIRDPARTY_IDPROF4__'] = '__THIRDPARTY_IDPROF4__'; $substitutionarray['__THIRDPARTY_IDPROF5__'] = '__THIRDPARTY_IDPROF5__'; $substitutionarray['__THIRDPARTY_IDPROF6__'] = '__THIRDPARTY_IDPROF6__'; - $substitutionarray['__MYCOMPANY_PROFID7__'] => '__MYCOMPANY_PROFID7__', - $substitutionarray['__MYCOMPANY_PROFID8__'] => '__MYCOMPANY_PROFID8__', - $substitutionarray['__MYCOMPANY_PROFID9__'] => '__MYCOMPANY_PROFID9__', - $substitutionarray['__MYCOMPANY_PROFID10__'] => '__MYCOMPANY_PROFID10__', + $substitutionarray['__MYCOMPANY_PROFID7__'] => '__MYCOMPANY_PROFID7__'; + $substitutionarray['__MYCOMPANY_PROFID8__'] => '__MYCOMPANY_PROFID8__'; + $substitutionarray['__MYCOMPANY_PROFID9__'] => '__MYCOMPANY_PROFID9__'; + $substitutionarray['__MYCOMPANY_PROFID10__'] => '__MYCOMPANY_PROFID10__'; $substitutionarray['__THIRDPARTY_TVAINTRA__'] = '__THIRDPARTY_TVAINTRA__'; $substitutionarray['__THIRDPARTY_NOTE_PUBLIC__'] = '__THIRDPARTY_NOTE_PUBLIC__'; $substitutionarray['__THIRDPARTY_NOTE_PRIVATE__'] = '__THIRDPARTY_NOTE_PRIVATE__'; From 7f4ca5380563d3b18563c3abdf9ffaecfb484b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sun, 28 Jan 2024 23:39:52 +0100 Subject: [PATCH 59/60] Update functions.lib.php --- htdocs/core/lib/functions.lib.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 3d12972e66254..37c95a9574eb2 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8221,10 +8221,10 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__THIRDPARTY_IDPROF4__'] = '__THIRDPARTY_IDPROF4__'; $substitutionarray['__THIRDPARTY_IDPROF5__'] = '__THIRDPARTY_IDPROF5__'; $substitutionarray['__THIRDPARTY_IDPROF6__'] = '__THIRDPARTY_IDPROF6__'; - $substitutionarray['__MYCOMPANY_PROFID7__'] => '__MYCOMPANY_PROFID7__'; - $substitutionarray['__MYCOMPANY_PROFID8__'] => '__MYCOMPANY_PROFID8__'; - $substitutionarray['__MYCOMPANY_PROFID9__'] => '__MYCOMPANY_PROFID9__'; - $substitutionarray['__MYCOMPANY_PROFID10__'] => '__MYCOMPANY_PROFID10__'; + $substitutionarray['__MYCOMPANY_PROFID7__'] = '__MYCOMPANY_PROFID7__'; + $substitutionarray['__MYCOMPANY_PROFID8__'] = '__MYCOMPANY_PROFID8__'; + $substitutionarray['__MYCOMPANY_PROFID9__'] = '__MYCOMPANY_PROFID9__'; + $substitutionarray['__MYCOMPANY_PROFID10__'] = '__MYCOMPANY_PROFID10__'; $substitutionarray['__THIRDPARTY_TVAINTRA__'] = '__THIRDPARTY_TVAINTRA__'; $substitutionarray['__THIRDPARTY_NOTE_PUBLIC__'] = '__THIRDPARTY_NOTE_PUBLIC__'; $substitutionarray['__THIRDPARTY_NOTE_PRIVATE__'] = '__THIRDPARTY_NOTE_PRIVATE__'; From ee810d65dae3ddfd3bb67115e3abc83b9d4683a5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Jan 2024 01:52:43 +0100 Subject: [PATCH 60/60] Close #27842 --- htdocs/product/price.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 122001ce2f6d8..4df1f623fb555 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -2191,7 +2191,7 @@ function on_change() { print ''; - print "".$staticsoc->getNomUrl(1).""; + print ''.$staticsoc->getNomUrl(1).""; print ''.$line->ref_customer.''; print "".dol_print_date($line->datec, "dayhour", 'tzuserrel').""; print ''.$langs->trans($line->price_base_type).""; @@ -2307,10 +2307,10 @@ function on_change() { $pu = $object->price_ttc; } - // Local tax was not saved into table llx_product on old version. So we will use value linked to VAT code. + // Local tax was not saved into table llx_product on old versions. So we will use the value linked to the VAT code. $localtaxarray = getLocalTaxesFromRate($object->tva_tx.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), 0, $mysoc, $mysoc); // Define part of HT, VAT, TTC - $resultarray = calcul_price_total(1, $pu, 0, $object->tva_tx, 1, 1, 0, $object->price_base_type, $object->recuperableonly, $object->type, $mysoc, $localtaxarray); + $resultarray = calcul_price_total(1, $pu, 0, $object->tva_tx, 1, 1, 0, $object->price_base_type, 0, $object->type, $mysoc, $localtaxarray); // Calcul du total ht sans remise $total_ht = $resultarray[0]; $total_vat = $resultarray[1]; @@ -2398,7 +2398,7 @@ function on_change() { print ''; - print "".$staticsoc->getNomUrl(1).""; + print ''.$staticsoc->getNomUrl(1).""; print ''.dol_escape_htmltag($line->ref_customer).''; print "".dol_print_date($line->datec, "dayhour", 'tzuserrel').""; print ''.$langs->trans($line->price_base_type)."";