diff --git a/ChangeLog b/ChangeLog index 0fe697ccb6c..06c6898993d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,216 +24,194 @@ For users: --------------- NEW: Minimal PHP version is now PHP 7.0 instead of PHP 5.6 -NEW: #19680 Add option PRODUCT_ALLOW_EXTERNAL_DOWNLOAD to automatically have uploaded files shared publicly by a link +NEW: #21780 Add pid field to Cronjob class and store PID on job execution NEW: #20650 can move the checkbox column on left (experimental option MAIN_CHECKBOX_LEFT_COLUMN) NEW: #21000 Added columns 'alias_name' on project, supplier invoice, supplier order, supplier proposals and task list -NEW: #21780 Add pid field to Cronjob class and store PID on job execution NEW: #21395 Added option for dark theme mode in display - color and theme NEW: #21397 added option to auto define barcode numbers for third-parties in barcode module setup -NEW: #21399 add image for event_array +NEW: #21399 NEW: #21442 Enhancement of module builder init NEW: #21654 add bank account number used on invoices for debit -NEW: #22048 added notes to productlot module +NEW: #22048 Added notes to productlot module NEW: #22298 Bank - Add salaries & vat in the tab of planned entries of a bank account -NEW: #22328 OAuth admin -NEW: #22424 online signature for contracts +NEW: #22328 +NEW: #22424 NEW: #22500 member module set up made easier NEW: #22527 projects and thirdparties can be viewed as conversation ("Message" view), like events/agenda. NEW: #22546 can now set user supervisors using mass action in htdocs/user NEW: #22594 can chose if VAT ID is unique or not for third parties NEW: #22622 all partnerships displayed on tab partnership of a thirdparty and member NEW: #22676 massaction for updating product prices -NEW: #22735 massaction to affect users on projects -NEW: #25594 can chose if VAT ID is unique or not for third parties +NEW: #22735 Massaction to assign users on projects NEW: #4482 adding js to hide/show advanced option on the export data page - +NEW: Accountancy - Add a graphic option to enable lettering function - FPC21 +NEW: Accountancy - Add a way to clean some words when you generate thirdparty accounting account +NEW: Accountancy - Added an option during export to export or not the lettering FPC21 +NEW: Accountancy - Manage supplier deposit with specific account +NEW: Accountancy - Model Digitaria - Add a way to clean some words when you generate thirdparty accounting account FPC22 +NEW: Add a button "Test collect" in email collector NEW: Add a constant to disallow modification of the product reference. +NEW: Add a method doAutoRenewContracts that can be used as a cron task. +NEW: Add " as enclosure by default for CSV export. Keep removing CR/LF. NEW: add attached file in presend email form of thirdparty card NEW: Add a way to enter LICENSE file content in property of website +NEW: Add badge in admin extrafields setup +NEW: add constant PROPAL_BYPASS_VALIDATED_STATUS +NEW: Add date event (!= date project) and location on event organization NEW: Add employment anniversary in birthday box +NEW: Add extrafield type "IP" to store IP addresses +NEW: Add fail2ban rules examples to limit access to /public pages +NEW: Add filter "Product subject to lot/Serial" in stock per lot/serial NEW: Add hidden option MAIN_EMAIL_SUPPORT_ACK to restore Email ack checkbox (feature abandonned by mailers) +NEW: Add IMAP port setting on email collector module +NEW: Adding JAPAN Chart-of-Account and regions/departments +NEW: Adding NIF verification for Algeria NEW: Add link to create an element from the category page +NEW: add margin infos to takepos invoice lines NEW: Add max size send for "backup and link to mail" option NEW: Add method httponly_accessforbidden() NEW: Add more advices into the Setup security page -NEW: Add new global variable for keeping the previous signature information on proposale (case of reopen a proposale) +NEW: Add new global variable for keeping the previous signature information on proposal (case of reopening a proposal) +NEW: Add objectLink on shipment NEW: Add option --force on CLI cron_run_jobs.php NEW: Add option "Show price on the generated documents for receptions" +NEW: Add performance index (name for company and contact) and llx_bank_url(url_id) +NEW: Add picto property on sub-module for password generation +NEW: add redirect on action confirm addconsumedline and addproduceline +NEW: Add a new advanced permission "read price" +NEW: Add substitution key __SENDEREMAIL_SIGNATURE__ +NEW: Add the referrer-policy to "same-origin" by default on all public pages. +NEW: Add the SMTP header References on ticket email created by email +NEW: Add the thirdparty column to the time list (projet/tasks/time.php) +NEW: Add trigger to record the event of sending an email from a project #20912 +NEW: Allow download link option in module configuration (propal,invoice,supplier proposal, order) +NEW: Bulk action to remove a category in list/search website pages +NEW: Can copy/paste images into emails sent. +NEW: Can edit label of an emailing even once sent +NEW: Can edit property css, cssview, csslist on extrafields +NEW: Can enter the unit price including the vat when adding new product lines on invoices, orders, proposals, ... +NEW: Can invoice task time per different services +NEW: Can join several files by default on email form +NEW: Can send an email on scheduled job error +NEW: Can set a commercial discount by entering amount including VAT +NEW: Can set a monthly frequency (or multiple) in cron tasks. +NEW: Can set start and end dates and comment on button "Activate all services" +NEW: Can sort on preselected best supplier price +NEW: Can use products categories to make inventory +NEW: Change filter type on tickets list into a multiselect combo +NEW: conf TIMESPENT_ALWAYS_UPDATE_THM, when it's on we always check current thm of user to update it in task time line +NEW: constant PROPAL_NEW_AS_SIGNED +NEW: show date delivery planned on orders linked to company and product +NEW: Default doc template of contracts is not mandatory +NEW: Default values in extrafields are no more limited to 255 char. +NEW: display currency in takepos menu +NEW: Enable online signature for interventions +NEW: extrafield price with currency +NEW: filter on reception dates (from / to) in cheque paiement card +NEW: Members: default_lang for members +NEW: Members: Table of membership types +NEW: Members: add free membership amounts at the membership type level +NEW: TakePOS: Header Scroll in TakePOS +NEW: TakePOS: add price to product box in TakePOS +NEW: TakePOS: add setup parameters, can setup terminal name +NEW: TakePOS: support of Stripe Terminal with TakePOS +NEW: TakePOS: Receipt preview in TakePOS setup +NEW: TakePOS: different product list on smartphone +NEW: Website: can delete a whole website if disabled +NEW: Website: can remove a website template +NEW: Website: can set header "Strict-Transport-Security" in web sites. +NEW: Website: can switch status of website and page from the website toolbar +NEW: Website: Templates of websites are now directories and not zip into core repo +NEW: Website: add 4 other templates in website module +NEW: Website: Add counters for public access of pages on a website +NEW: If we select another view list mode, we keep it +NEW: Init module bookcal +NEW: Encrypt all sensitive constants in llx_const using dolEncrypt/dolDecrypt +NEW: Invoice - Add french mention on pdf when vat debit option is on +NEW: invoice export : add accounting affectation +NEW: label on products categories filter +NEW: The link "add to bookmark" is always on top in the bookmark popup +NEW: MAIN_SEARCH_CATEGORY_PRODUCT_ON_LISTS const to show category customer filter +NEW: Make module WebservicesClient deprecated. Use module WebHook instead. +NEW: manage no email with thirdparties (better for GDPR) +NEW: Manage Position (Rank) on Contract Lines NEW: Manage VAT on all lines on purchases cycle +NEW: Page to show virtual stock at a future date +NEW: On a bank reconciled line, we can modify the bank receipt +NEW: On a form to send an email, we show all emails of all contacts of object +NEW: Option PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT showing wh on PDF +NEW: Option PRODUIT_DESC_IN_FORM accept (desktop only or +smartphone) +NEW: Page for mass stock transfer can be used with no source stock NEW: parent company column and filter in invoice and order list -NEW: private and public note columns on user, thirdparty and contact lists -NEW: Public counters feature +NEW: Add "Show Sales rep" option for PDF +NEW: Picto for shared link is clickable +NEW: possibility to select scopes with checkbox for Oauth tokens +NEW: private and public note on user, thirdparty and contact list +NEW: product categories filter on inventory list +NEW: Product supplier price: autofill default supplier VAT +NEW: Project - author field become an available column on lists +NEW: Reception - Add a from/to on search on date field +NEW: Start a simple support of recurrent events on agenda +NEW: Resize parent company column in order list +NEW: Saved token of OAUTH module are now encrypted into llx_oauth_token NEW: Save one click to select on delivery ack, on emails. NEW: scheduled job to send unpaid invoice reminder can now use the cc and bcc from email template +NEW: set thirdparty type with company modify trigger +NEW: Show also scheduled task never finished in scheduled task widget +NEW: show badge with number of extrafields in setup +NEW: show category tree in sellist and chkbxlst for common object +NEW: Show picto and color into combo for selection of tags +NEW: show product label on inventory +NEW: show sell-by and eat-by dates only if not empty +NEW: show SellBy/EatBy dates for each batch product in shipment card +NEW: Can skip accept/refuse steps for proposals (option PROPAL_SKIP_ACCEPT_REFUSE) +NEW: experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP) NEW: can substitue project title in mail template +NEW: Supplier order list - Add column private and public note NEW: The purge of files can purge only if older than a number of seconds NEW: Update ActionComm type_code on email message ticket +NEW: VAT - Admin - Add information on deadline day for submission of VAT declaration +NEW: expand/collapse permissions on user permission page +NEW: Show delivery mode on PDF for proposals NEW: Add the target to select attendees of event for emailings -NEW: add redirect on action confirm addconsumedline and addproduceline -NEW: Add the referrer-policy to "same-origin" by default on all public pages. -NEW: Add trigger to record the event of sending an email from a project #20912 -NEW: Allow download link option in module configuration (propal, order, invoice, supplier proposal) -NEW: Can enter the unit price including the VAT -NEW: Can invoice task time per different services -NEW: Can set a commercial discount by entering amount including VAT -NEW: Can set start and end dates and comment on button "Activate all services" -NEW: show date delivery planned on orders linked to company and product -NEW: filter on reception dates (from / to) in cheque paiement card - -NEW: Accountancy - add a graphic option to enable lettering function - FPC21 -NEW: Accountancy - add a way to clean some words when you generate thirdparty accounting account -NEW: Accountancy - added an option during export to export or not the lettering FPC21 -NEW: Accountancy - Invoice export : add accounting affectation -NEW: Accountancy - Manage supplier deposit with specific account -NEW: Accountancy - Model Digitaria - Add a way to clean some words when you generate thirdparty accounting account FPC22 -NEW: Agenda - start a simple support of recurrent events on agenda -NEW: Bank - add salaries & VAT in tab planned entries -NEW: Bank - on a bank reconciled line, we can modify the bank receipt -NEW: Contracts - add a method doAutoRenewContracts that can be used as a cron task -NEW: Contracts - default template of contract is not mandatory -NEW: Contracts - Manage Position (Rank) on Contract Lines -NEW: EMail - can copy/paste images into emails sent -NEW: EMail - can edit label of an emailing even once sent -NEW: EMail - can join several files by default on email form -NEW: EMail - can send an email on scheduled job error -NEW: EMail - on a form to send an email, we show all emails of all contacts of object -NEW: EMail - add the SMTP header References on ticket email created by email -NEW: EMail - add substitution key __SENDEREMAIL_SIGNATURE__ -NEW: EMail - experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP) -NEW: EMail-Collector - add IMAP port setting -NEW: EMail-Collector - add a button "Test collect" -NEW: Event-Organization - add date event (!= date project) and location on event organization -NEW: Expedition - add objectLink on expedition -NEW: Export - Add " as enclosure by default for CSV export. Keep removing CR/LF. -NEW: Extrafields - add badge in admin extrafields setup -NEW: Extrafields - can edit property css, cssview, csslist on extrafields -NEW: Extrafields - default values in extrafields are not more limited to 255 char. -NEW: Extrafields - field price with currency -NEW: Extrafields - support IP type to store IP addresses -NEW: Finance - VAT - Admin - Add information on deadline day for submission of VAT declaration -NEW: Interventions - enable online signature for interventions -NEW: Invoice - add french mention on PDF when VAT debit option is on -NEW: Members - default_lang for members -NEW: Members - table of membership types -NEW: Members - add free membership amounts at the membership type level -NEW: OAuth - possibility to select scopes with checkbox for OAuth tokens -NEW: OAuth - saved token of OAUTH module are now encrypted into llx_oauth_token -NEW: Orders - resize parent company column in order list -NEW: Products - Categories - label on products categories filter -NEW: Products - Supplier price - autofill default supplier VAT -NEW: Products - Supplier price - can sort and preselected best supplier price -NEW: Projects - add author on list -NEW: Projects - add thirdparty column to the time list (projet/tasks/time.php) -NEW: Proposals - show delivery mode on PDF for proposals -NEW: Proposals - skip accept/refuse process for proposals (option PROPAL_SKIP_ACCEPT_REFUSE) -NEW: Reception - add a from/to on search on date field -NEW: Stock - page for mass stock transfer can be used with no source stock -NEW: Stock - product categories filter on inventory list -NEW: Stock - show product label on inventory -NEW: Stock - manage virtual stock at a future date -NEW: Stock Inventory - add filter "Product subject to lot/Serial" in stock per lot/serial -NEW: Stock Inventory - can use products categories to make inventory -NEW: Supplier Order List - add column private and public note -NEW: TakePOS - add margin infos to TakePOS invoice lines -NEW: TakePOS - add price to product box in TakePOS -NEW: TakePOS - add setup parameters, can setup terminal name -NEW: TakePOS - different product list on smartphone -NEW: TakePOS - display currency in TakePOS menu -NEW: TakePOS - Header Scroll in TakePOS -NEW: TakePOS - Receipt preview in TakePOS setup -NEW: TakePOS - support of Stripe Terminal with TakePOS -NEW: Thirdparty - manage no email with thirdparties (better for GDPR) -NEW: Thirdparty - set thirdparty type with company modify trigger -NEW: Tickets - change filter type on tickets list into a multiselect combo -NEW: Tickets - add oldcopy to Ticket so triggers intercepting TICKET_MODIFY have access to old values of the updated properties -NEW: Website - can delete a whole website if disabled -NEW: Website - can remove a website template -NEW: Website - can set header "Strict-Transport-Security" in web sites. -NEW: Website - can switch status of website and page from the website toolbar -NEW: Website - Templates of websites are now directories and not zip into core repo -NEW: Website - add 4 other templates in website module - -General: -NEW: Actions: Bulk action to remove a category in list/search website pages -NEW: Cronjobs: can set a monthly frequency (or multiple) in cron tasks -NEW: Database: Encrypt all sensitive constants in llx_const -NEW: Database: Add performance index (name for company and contact) and llx_bank_url(url_id) -NEW: Database: Introduce dolEncrypt and dolDecrypt to be able to encrypt data in db -NEW: GUI: If we select another view list mode, we keep it -NEW: GUI: the link "add to bookmark" is always on top in the bookmark popup -NEW: GUI: Picto for shared link is clickable -NEW: GUI: add picto property on sub-module for password generation -NEW: GUI: show also scheduled task never finished in scheduled task widget -NEW: GUI: show badge with number of extrafields in setup -NEW: GUI: show category tree in sellist and chkbxlst for common object -NEW: GUI: show picto and color into combo for selection of tags -NEW: GUI: show sell-by and eat-by dates only if not empty -NEW: GUI: show SellBy/EatBy dates for each batch product in shipment card -NEW: GUI/Permissions: expand/collapse permissions on user permission page -NEW: Permissions: add a new advanced permission "read price" -NEW: Print: add show "Sales rep" option for PDF -NEW: Security: add fail2ban rules examples to limit access to /public pages - - Option / Const for System: -NEW: FICHINTER_ALLOW_EXTERNAL_DOWNLOAD -NEW: MAIN_CHECKBOX_LEFT_COLUMN -NEW: MAIN_EMAIL_SUPPORT_ACK -NEW: MAIN_IMAP_USE_PHPIMAP -NEW: MAIN_SEARCH_CATEGORY_PRODUCT_ON_LISTS - const to show category customer filter -NEW: PRODUCT_ALLOW_EXTERNAL_DOWNLOAD -NEW: PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT - showing warehouse on PDF -NEW: PRODUIT_DESC_IN_FORM accept - desktop only or +smartphone -NEW: PROPAL_BYPASS_VALIDATED_STATUS -NEW: PROPAL_NEW_AS_SIGNED -NEW: PROPAL_SKIP_ACCEPT_REFUSE -NEW: TIMESPENT_ALWAYS_UPDATE_THM - when it's on we always check current thm of user to update it in task time line - - Localisation: -NEW: adding JAPAN Chart-of-Account and regions/departments -NEW: adding NIF verification for Algeria +NEW: Can set background style with MAIN_LOGIN_BACKGROUND_STYLE Modules NEW: Experimental module Asset -NEW: Init module bookcal -NEW: Make module WebservicesClient deprecated. Use module WebHook instead. - For developers or integrators: ------------------------------ -NEW: ModuleBuilder can generate code of class from an existing SQL table +NEW: ModuleBuilder can generate code for a class from an existing SQL table +NEW: #22370 Modulebuilder supports 'alwayseditable' (like extrafields) NEW: #20912 Add trigger to record the event of sending an email from a project NEW: #21750 Added "Get lines and Post lines from BOM" at the REST Service -NEW: #22370 Modulebuilder supports 'alwayseditable' (like extrafields) +NEW: Removed completely the need for the library adodbtime +NEW: hook on agenda pages +NEW: hook to complete payment in TakePOS +NEW: hook "changeHelpURL" to modify target of the help button +NEW: hook formConfirm on action comm card +NEW: hook to modify supplier product html select +NEW: Add new hook for show virtual stock details on product stock card +NEW: Add new hooks for actioncomm NEW: conf->global->SYSLOG_FILE_ONEPERSESSION accept a string -NEW: All ajax pages have now a top_httphead() - - API: +NEW: translation for contact type API, setup/ticket API, shipping method API +NEW: All ajax pages have now a header build with top_httphead() +NEW: support multilang in Civilities API NEW: Add API for the partnership module NEW: Add "Get lines and Post lines from BOM" in the API -NEW: translate for contact type API, setup/ticket API, shipping method API -NEW: support multilang in Civilities API - - Hooks: -NEW: Actioncomm - add new hooks for actioncomm -NEW: Actioncomm - hook formConfirm on actioncomm card -NEW: Agenda - hook on agenda pages -NEW: Help - hook "changeHelpURL" to modify target of the help button -NEW: Product - add hook to show virtual stock details on product stock card -NEW: Product - add hook to modify supplier product html select -NEW: TakePOS - add hook to complete payment in TakePOS - - -NEW: Removed completely the need for the library adodbtime -NEW: Replace fk_categories_product with categories_product in inventory -NEW: Rewrite of SQL request. Removed the join on category (for filter on categ), replaced with a EXISTS/NOT +NEW: Replace property fk_categories_product with categories_product in inventory class +NEW: Rewrite of SQL request. Removed the join on category table (for filter on category), replaced with a EXISTS/NOT +NEW: Add oldcopy to Ticket so triggers intercepting TICKET_MODIFY have access to old values of the updated properties +NEW: #19680 Add option PRODUCT_ALLOW_EXTERNAL_DOWNLOAD to automatically have uploaded files shared publicly by a link +NEW: Add option FICHINTER_ALLOW_EXTERNAL_DOWNLOAD WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * Minimal PHP version is now PHP 7.0 instead of PHP 5.6 -* The signature of method getNomUrl() of class ProductFournisseur has been modified to match the signature of method Product +* The signature of method getNomUrl() of class ProductFournisseur has been modified to match the signature of method Product->getNomUrl() * Trigger ORDER_SUPPLIER_DISPATCH is removed, use ORDER_SUPPLIER_RECEIVE and/or LINEORDER_SUPPLIER_DISPATCH instead. * All functions fetch_all() have been set to deprecated for naming consitency, use fetchAll() instead. * Code standardization: '$user->rights->propale' is now '$user->rights->propal' everywhere. @@ -243,7 +221,7 @@ Following changes may create regressions for some external modules, but were nec * Rename the substitution for "project label" instead of "project title" in substitution variables * You must use "$objectoffield" to manipulate the current object inside the formulare of computed custom extrafields instead of $obj/$object. * Making a global search is sending the parameter using always the name search_all (instead of sometimes sall and search_all) - +* The property $url_last_version must be public if defined into module descriptor files; ***** ChangeLog for 16.0.4 compared to 16.0.3 ***** diff --git a/README.md b/README.md index 826955aef92..e4b464d77b4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Downloads per day](https://img.shields.io/sourceforge/dw/dolibarr.svg) ![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/develop.svg) -[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg?style=flat-square)](https://php.net/) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.0-8892BF.svg?style=flat-square)](https://php.net/) [![GitHub release](https://img.shields.io/github/v/release/Dolibarr/dolibarr)](https://github.com/Dolibarr/dolibarr) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5521/badge)](https://bestpractices.coreinfrastructure.org/projects/5521) diff --git a/build/generate_filelist_xml.php b/build/generate_filelist_xml.php index b122f9b0305..45d649d90d9 100755 --- a/build/generate_filelist_xml.php +++ b/build/generate_filelist_xml.php @@ -46,6 +46,7 @@ require_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php"; $includecustom=0; $includeconstants=array(); +$buildzip=0; if (empty($argv[1])) { print "Usage: ".$script_file." release=autostable|auto[-mybuild]|x.y.z[-mybuild] [includecustom=1] [includeconstant=CC:MY_CONF_NAME:value] [buildzip=1]\n"; @@ -69,6 +70,9 @@ while ($i < $argc) { if (!empty($result["includeconstant"])) { $includeconstants[$i] = $result["includeconstant"]; } + if (!empty($result["buildzip"])) { + $buildzip=1; + } if (preg_match('/includeconstant=/', strval($argv[$i]))) { $tmp=explode(':', $result['includeconstant'], 3); // $includeconstant has been set with previous parse_str() if (count($tmp) != 3) { diff --git a/dev/setup/fail2ban/jail.local b/dev/setup/fail2ban/jail.local index 733987aa45c..bd1f7959f08 100644 --- a/dev/setup/fail2ban/jail.local +++ b/dev/setup/fail2ban/jail.local @@ -31,6 +31,7 @@ maxretry = 10 [web-dol-limitpublic] ; rule to add rate limit on some public pages +; note you must keep enough for public access like agenda export, emailing trackers, stripe ipn access, ... enabled = true port = http,https filter = web-dolibarr-limitpublic @@ -38,5 +39,5 @@ logpath = /mypath/documents/documents/dolibarr.log action = %(action_mw)s bantime = 86400 ; 1 day findtime = 86400 ; 1 day -maxretry = 500 +maxretry = 1000 diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 2aed109ce26..0fbb2764ae6 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -719,7 +719,7 @@ if (count($sqlwhere) > 0) { // Export into a file with format defined into setup (FEC, CSV, ...) // Must be after definition of $sql if ($action == 'export_fileconfirm' && $user->hasRight('accounting', 'mouvements', 'export')) { - // TODO Replace the fetchAll to get all ->line followed by call to ->export(). It consumes too much memory on large export. + // TODO Replace the fetchAll to get all ->line followed by call to ->export(). It currently consumes too much memory on large export. // Replace this with the query($sql) and loop on each line to export them. $result = $object->fetchAll($sortorder, $sortfield, 0, 0, $filter, 'AND', (empty($conf->global->ACCOUNTING_REEXPORT) ? 0 : 1)); @@ -729,6 +729,7 @@ if ($action == 'export_fileconfirm' && $user->hasRight('accounting', 'mouvements // Export files then exit $accountancyexport = new AccountancyExport($db); + $formatexport = GETPOST('formatexport', 'int'); $notexportlettering = GETPOST('notexportlettering', 'alpha'); if (!empty($notexportlettering)) { @@ -745,7 +746,7 @@ if ($action == 'export_fileconfirm' && $user->hasRight('accounting', 'mouvements $withAttachment = !empty(trim(GETPOST('notifiedexportfull', 'alphanohtml'))) ? 1 : 0; // Output data on screen or download - $result = $accountancyexport->export($object->lines, $formatexportset, $withAttachment); + $result = $accountancyexport->export($object->lines, $formatexport, $withAttachment); $error = 0; if ($result < 0) { @@ -856,6 +857,17 @@ $formconfirm = ''; if ($action == 'export_file') { $form_question = array(); + $form_question['formatexport'] = array( + 'name' => 'formatexport', + 'type' => 'select', + 'label' => $langs->trans('Modelcsv'), // TODO Use Selectmodelcsv and show a select combo + 'values' => $listofformat, + 'default' => $formatexportset, + 'morecss' => 'minwidth200 maxwidth200' + ); + + $form_question['separator0'] = array('name'=>'separator0', 'type'=>'separator'); + if (getDolGlobalInt("ACCOUNTING_ENABLE_LETTERING")) { // If 1, we check by default. $checked = !empty($conf->global->ACCOUNTING_DEFAULT_NOT_EXPORT_LETTERING) ? 'true' : 'false'; @@ -866,7 +878,7 @@ if ($action == 'export_file') { 'value' => $checked, ); - $form_question['separator'] = array('name'=>'separator', 'type'=>'separator'); + $form_question['separator1'] = array('name'=>'separator1', 'type'=>'separator'); } // If 1 or not set, we check by default. @@ -903,7 +915,7 @@ if ($action == 'export_file') { ); } - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 400, 600); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").'...', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 420, 600); } //if ($action == 'delbookkeepingyear') { @@ -1362,7 +1374,7 @@ while ($i < min($num, $limit)) { $accountingjournal = new AccountingJournal($db); $result = $accountingjournal->fetch('', $line->code_journal); $journaltoshow = (($result > 0) ? $accountingjournal->getNomUrl(0, 0, 0, '', 0) : $line->code_journal); - print ''.$journaltoshow.''; + print ''.$journaltoshow.''; if (!$i) { $totalarray['nbfield']++; } diff --git a/htdocs/accountancy/class/accountancycategory.class.php b/htdocs/accountancy/class/accountancycategory.class.php index 92d493b8b29..5c13c2efba8 100644 --- a/htdocs/accountancy/class/accountancycategory.class.php +++ b/htdocs/accountancy/class/accountancycategory.class.php @@ -646,7 +646,7 @@ class AccountancyCategory // extends CommonObject } $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as t"; //if (in_array($this->db->type, array('mysql', 'mysqli'))) $sql.=' USE INDEX idx_accounting_bookkeeping_doc_date'; - $sql .= " WHERE t.entity = ".$conf->entity; + $sql .= " WHERE t.entity = ".((int) $conf->entity); if (is_array($cpt)) { $sql .= " AND t.numero_compte IN (".$this->db->sanitize($listofaccount, 1).")"; } else { diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index ed51a2aea5e..b725cafdacd 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -1177,7 +1177,9 @@ class AccountancyExport print $line->code_journal . $separator; // FEC:JournalLib - print dol_string_unaccent($langs->transnoentities($line->journal_label)) . $separator; + $labeljournal = dol_string_unaccent($langs->transnoentities($line->journal_label)); + $labeljournal = dol_string_nospecial($labeljournal, ' '); + print $labeljournal . $separator; // FEC:EcritureNum print $line->piece_num . $separator; @@ -1308,7 +1310,9 @@ class AccountancyExport print $line->code_journal . $separator; // FEC:JournalLib - print dol_string_unaccent($langs->transnoentities($line->journal_label)) . $separator; + $labeljournal = dol_string_unaccent($langs->transnoentities($line->journal_label)); + $labeljournal = dol_string_nospecial($labeljournal, ' '); + print $labeljournal . $separator; // FEC:EcritureNum print $line->piece_num . $separator; diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 5f603a973c2..17ac1d211ae 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -128,8 +128,8 @@ if ($action == 'validatehistory') { // Now make the binding. Bind automatically only for product with a dedicated account that exists into chart of account, others need a manual bind // Customer Invoice lines (must be same request than into page list.php for manual binding) - $sql = "SELECT f.rowid as facid, f.ref as ref, f.datef, f.type as ftype, f.fk_facture_source,"; - $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; + $sql = "SELECT f.rowid as facid, f.ref as ref, f.datef, f.type as ftype, f.situation_cycle_ref, f.fk_facture_source,"; + $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.situation_percent, l.tva_tx as tva_tx_line, l.vat_src_code,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.tva_tx as tva_tx_prod,"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { $sql .= " ppe.accountancy_code_sell as code_sell, ppe.accountancy_code_sell_intra as code_sell_intra, ppe.accountancy_code_sell_export as code_sell_export,"; @@ -312,6 +312,10 @@ print ''.$langs->trans("DescVentilCustomer").''.$langs->trans("DescVentilMore", $langs->transnoentitiesnoconv("ValidateHistory"), $langs->transnoentitiesnoconv("ToBind")).'
'; print '
'; +if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) { + print info_admin($langs->trans("SorryThisModuleIsNotCompatibleWithTheExperimentalFeatureOfSituationInvoices")); + print "
"; +} $y = $year_current; @@ -386,6 +390,11 @@ if ($resql) { $num = $db->num_rows($resql); while ($row = $db->fetch_row($resql)) { + // TODO When INVOICE_USE_SITUATION = 1, values here are wrong. There is no compensation on bad stored amounts + //$situation_ratio = 1; + //if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) { + //} + print ''; print ''; if ($row[0] == 'tobind') { @@ -519,6 +528,11 @@ if ($resql) { $num = $db->num_rows($resql); while ($row = $db->fetch_row($resql)) { + // TODO When INVOICE_USE_SITUATION = 1, values here are wrong. There is no compensation on bad stored amounts + //$situation_ratio = 1; + //if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) { + //} + print ''; print ''; if ($row[0] == 'tobind') { @@ -630,7 +644,6 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa print "\n"; print ''; - if (isModEnabled('margin')) { print "
\n"; print '
'; @@ -644,22 +657,41 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa print ''.$langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)).''; } print ''.$langs->trans("Total").''; - $sql = "SELECT '".$db->escape($langs->trans("Vide"))."' AS marge,"; - for ($i = 1; $i <= 12; $i++) { - $j = $i + ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) - 1; - if ($j > 12) { - $j -= 12; - } - $sql .= " SUM(".$db->ifsql("MONTH(f.datef)=".$j, - " (".$db->ifsql("fd.total_ht < 0", - " (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100))))", - " (fd.total_ht - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100)))").")", - 0).") AS month".str_pad($j, 2, '0', STR_PAD_LEFT).","; - } - $sql .= " SUM(".$db->ifsql("fd.total_ht < 0", - " (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100))))", - " (fd.total_ht - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100)))").") as total"; + if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) { + // With old situation invoice setup + $sql = "SELECT '".$db->escape($langs->trans("Vide"))."' AS marge,"; + for ($i = 1; $i <= 12; $i++) { + $j = $i + ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) - 1; + if ($j > 12) { + $j -= 12; + } + $sql .= " SUM(".$db->ifsql("MONTH(f.datef)=".$j, + " (".$db->ifsql("fd.total_ht < 0", + " (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100))))", // TODO This is bugged, we must use the percent for the invoice and fd.situation_percent is cumulated percent ! + " (fd.total_ht - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100)))").")", + 0).") AS month".str_pad($j, 2, '0', STR_PAD_LEFT).","; + } + $sql .= " SUM(".$db->ifsql("fd.total_ht < 0", + " (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100))))", // TODO This is bugged, we must use the percent for the invoice and fd.situation_percent is cumulated percent ! + " (fd.total_ht - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100)))").") as total"; + } else { + $sql = "SELECT '".$db->escape($langs->trans("Vide"))."' AS marge,"; + for ($i = 1; $i <= 12; $i++) { + $j = $i + ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) - 1; + if ($j > 12) { + $j -= 12; + } + $sql .= " SUM(".$db->ifsql("MONTH(f.datef)=".$j, + " (".$db->ifsql("fd.total_ht < 0", + " (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty)))", + " (fd.total_ht - (fd.buy_price_ht * fd.qty))").")", + 0).") AS month".str_pad($j, 2, '0', STR_PAD_LEFT).","; + } + $sql .= " SUM(".$db->ifsql("fd.total_ht < 0", + " (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty)))", + " (fd.total_ht - (fd.buy_price_ht * fd.qty))").") as total"; + } $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture"; $sql .= " WHERE f.datef >= '".$db->idate($search_date_start)."'"; diff --git a/htdocs/accountancy/customer/lines.php b/htdocs/accountancy/customer/lines.php index b8df8890a01..888cc568cf8 100644 --- a/htdocs/accountancy/customer/lines.php +++ b/htdocs/accountancy/customer/lines.php @@ -189,8 +189,8 @@ print ''."\n"; } + // Subject + if ($this->withtitletopic) { + print ''; + // Answer to a ticket : display of the thread title in readonly + if ($this->withtopicreadonly) { + print $langs->trans('SubjectAnswerToTicket').' '.$this->topic_title; + } else { + if (isset($this->withreadid) && $this->withreadid > 0) { + $subject = $langs->trans('SubjectAnswerToTicket').' '.$this->withreadid.' : '.$this->topic_title.''; + } else { + $subject = GETPOST('subject', 'alpha'); + } + print 'withemail)?' autofocus':'').' />'; + } + print ''; + } + // MESSAGE $msg = GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : ''; print ''; @@ -459,7 +465,7 @@ class FormTicket if (count($cate_arbo)) { // Categories print ''.$langs->trans("Categories").''; - print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); print ""; } } @@ -854,6 +860,8 @@ class FormTicket print ' selected="selected"'; } elseif ($arraycategories['use_default'] == "1" && !$selected && !$empty) { print ' selected="selected"'; + } elseif (count($ticketstat->cache_category_tickets) == 1) { + print ' selected="selected"'; } print '>'; @@ -1269,7 +1277,7 @@ class FormTicket } // Load translation files required by the page - $langs->loadLangs(array('other', 'mails')); + $langs->loadLangs(array('other', 'mails', 'ticket')); // Clear temp files. Must be done at beginning, before call of triggers if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) { @@ -1423,7 +1431,7 @@ class FormTicket $res = $ticketstat->fetch('', '', $this->track_id); print ''; - $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : ($conf->global->TICKETS_MESSAGE_FORCE_MAIL?'checked':'')); + $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : (getDolGlobalInt('TICKETS_MESSAGE_FORCE_MAIL')?'checked':'')); print ' '; print ''; $texttooltip = $langs->trans("TicketMessageSendEmailHelp", '{s1}'); @@ -1455,15 +1463,17 @@ class FormTicket // Subject print ''.$langs->trans('Subject').''; - print 'ref.'] '.$langs->trans('TicketNewMessage').'" />'; + print 'ref.'] '.$langs->trans('TicketNewMessage').'" />'; print ''; // Recipients / adressed-to - print ''.$langs->trans('MailRecipients').''; + print ''.$langs->trans('MailRecipients'); + print ' '.$form->textwithpicto('', $langs->trans("TicketMessageRecipientsHelp"), 1, 'help'); + print ''; if ($res) { // Retrieve email of all contacts (internal and external) - $contacts = $ticketstat->getInfosTicketInternalContact(); - $contacts = array_merge($contacts, $ticketstat->getInfosTicketExternalContact()); + $contacts = $ticketstat->getInfosTicketInternalContact(1); + $contacts = array_merge($contacts, $ticketstat->getInfosTicketExternalContact(1)); $sendto = array(); @@ -1489,8 +1499,8 @@ class FormTicket } } - if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS) { - $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO.' (generic email)'; + if (getDolGlobalInt('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS')) { + $sendto[] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO').' (generic email)'; } // Print recipient list diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index b2b5e2c6e93..e9b2ac88039 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -339,17 +339,12 @@ class Ldap * This method seems a duplicate/alias of unbind(). * * @return boolean true or false - * @deprecated ldap_close is an alias of ldap_unbind + * @deprecated ldap_close is an alias of ldap_unbind, so use unbind() instead. * @see unbind() */ public function close() { - $r_type = get_resource_type($this->connection); - if ($this->connection && ($r_type === "Unknown" || !@ldap_close($this->connection))) { - return false; - } else { - return true; - } + return $this->unbind(); } /** @@ -401,7 +396,7 @@ class Ldap public function unbind() { $this->result = true; - if ($this->connection) { + if (is_resource($this->connection) || is_object($this->connection)) { $this->result = @ldap_unbind($this->connection); } if ($this->result) { diff --git a/htdocs/core/class/menubase.class.php b/htdocs/core/class/menubase.class.php index 9544e11e075..3630d137136 100644 --- a/htdocs/core/class/menubase.class.php +++ b/htdocs/core/class/menubase.class.php @@ -152,6 +152,10 @@ class Menubase */ public $tms; + /** + * @var Menu menu + */ + public $newmenu; /** * Constructor diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index fc562913c08..3a668d3c0c6 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -71,9 +71,7 @@ class Notify 'ORDER_VALIDATE', 'PROPAL_VALIDATE', 'PROPAL_CLOSE_SIGNED', - 'PROPAL_CLOSE_SIGNED_WEB', 'PROPAL_CLOSE_REFUSED', - 'PROPAL_CLOSE_REFUSED_WEB', 'FICHINTER_VALIDATE', 'FICHINTER_ADD_CONTACT', 'ORDER_SUPPLIER_VALIDATE', @@ -359,6 +357,7 @@ class Notify global $dolibarr_main_url_root; global $action; + // Complete the array Notify::$arrayofnotifsupported if (!is_object($hookmanager)) { include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; $hookmanager = new HookManager($this->db); @@ -373,13 +372,14 @@ class Notify } } + // If the trigger code is not managed by the Notification module if (!in_array($notifcode, Notify::$arrayofnotifsupported)) { return 0; } include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - dol_syslog(get_class($this)."::send notifcode=".$notifcode.", object=".$object->id); + dol_syslog(get_class($this)."::send notifcode=".$notifcode.", object id=".$object->id); $langs->load("other"); @@ -407,7 +407,7 @@ class Notify // Check notification per third party if (!empty($object->socid) && $object->socid > 0) { $sql .= "SELECT 'tocontactid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.default_lang,"; - $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.type"; + $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.threshold, n.context, n.type"; $sql .= " FROM ".$this->db->prefix()."socpeople as c,"; $sql .= " ".$this->db->prefix()."c_action_trigger as a,"; $sql .= " ".$this->db->prefix()."notify_def as n,"; @@ -427,7 +427,7 @@ class Notify // Check notification per user $sql .= "SELECT 'touserid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.lang as default_lang,"; - $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.type"; + $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.threshold, n.context, n.type"; $sql .= " FROM ".$this->db->prefix()."user as c,"; $sql .= " ".$this->db->prefix()."c_action_trigger as a,"; $sql .= " ".$this->db->prefix()."notify_def as n"; @@ -439,6 +439,11 @@ class Notify $sql .= " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage } + // Check notification fixed + // TODO Move part found after, into a sql here + + + // Loop on all notifications enabled $result = $this->db->query($sql); if ($result) { $num = $this->db->num_rows($result); @@ -511,13 +516,9 @@ class Notify $object_type = 'propal'; $labeltouse = $conf->global->PROPAL_CLOSE_REFUSED_TEMPLATE; $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedRefused", $link); - break; - case 'PROPAL_CLOSE_REFUSED_WEB': - $link = ''.$newref.''; - $dir_output = $conf->propal->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal'); - $object_type = 'propal'; - $labeltouse = $conf->global->PROPAL_CLOSE_REFUSED_TEMPLATE; - $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedRefusedWeb", $link); + if (!empty($object->context['closedfromonlinesignature'])) { + $mesg .= ' - From online page'; + } break; case 'PROPAL_CLOSE_SIGNED': $link = ''.$newref.''; @@ -525,13 +526,9 @@ class Notify $object_type = 'propal'; $labeltouse = $conf->global->PROPAL_CLOSE_SIGNED_TEMPLATE; $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedSigned", $link); - break; - case 'PROPAL_CLOSE_SIGNED_WEB': - $link = ''.$newref.''; - $dir_output = $conf->propal->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal'); - $object_type = 'propal'; - $labeltouse = $conf->global->PROPAL_CLOSE_SIGNED_TEMPLATE; - $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedSigned", $link); + if (!empty($object->context['closedfromonlinesignature'])) { + $mesg .= ' - From online page'; + } break; case 'FICHINTER_ADD_CONTACT': $link = ''.$newref.''; @@ -651,6 +648,23 @@ class Notify $labeltouse = !empty($labeltouse) ? $labeltouse : ''; + // Replace keyword __SUPERVISOREMAIL__ + if (preg_match('/__SUPERVISOREMAIL__/', $sendto)) { + $newval = ''; + if ($user->fk_user > 0) { + $supervisoruser = new User($this->db); + $supervisoruser->fetch($user->fk_user); + if ($supervisoruser->email) { + $newval = trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname).' <'.$supervisoruser->email.'>'); + } + } + dol_syslog("Replace the __SUPERVISOREMAIL__ key into recipient email string with ".$newval); + $sendto = preg_replace('/__SUPERVISOREMAIL__/', $newval, $sendto); + $sendto = preg_replace('/,\s*,/', ',', $sendto); // in some case you can have $sendto like "email, __SUPERVISOREMAIL__ , otheremail" then you have "email, , othermail" and it's not valid + $sendto = preg_replace('/^[\s,]+/', '', $sendto); // Clean start of string + $sendto = preg_replace('/[\s,]+$/', '', $sendto); // Clean end of string + } + $parameters = array('notifcode'=>$notifcode, 'sendto'=>$sendto, 'replyto'=>$replyto, 'file'=>$filename_list, 'mimefile'=>$mimetype_list, 'filename'=>$mimefilename_list, 'outputlangs'=>$outputlangs, 'labeltouse'=>$labeltouse); if (!isset($action)) { $action = ''; @@ -721,6 +735,7 @@ class Notify } // Check notification using fixed email + // TODO Move vars NOTIFICATION_FIXEDEMAIL into table llx_notify_def and inclulde the case into previous loop of sql result if (!$error) { foreach ($conf->global as $key => $val) { $reg = array(); diff --git a/htdocs/core/class/rssparser.class.php b/htdocs/core/class/rssparser.class.php index 6992612592d..6d83fd6d6da 100644 --- a/htdocs/core/class/rssparser.class.php +++ b/htdocs/core/class/rssparser.class.php @@ -36,6 +36,8 @@ class RssParser */ public $error = ''; + public $feed_version; + private $_format = ''; private $_urlRSS; private $_language; @@ -446,7 +448,7 @@ class RssParser $itemDescription = sanitizeVal((string) $item['description']); $itemPubDate = sanitizeVal((string) $item['pubdate']); $itemId = sanitizeVal((string) $item['guid']); - $itemAuthor = sanitizeVal((string) $item['author']); + $itemAuthor = sanitizeVal((string) ($item['author'] ?? '')); } // Loop on each category diff --git a/htdocs/core/class/smtps.class.php b/htdocs/core/class/smtps.class.php index 135d9d9e8de..46193e1efea 100644 --- a/htdocs/core/class/smtps.class.php +++ b/htdocs/core/class/smtps.class.php @@ -1862,6 +1862,7 @@ class SMTPs } elseif ($type == 'alternative') { return $this->_smtpsAlternativeBoundary; } + return ''; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps diff --git a/htdocs/core/class/validate.class.php b/htdocs/core/class/validate.class.php index 31cf6300aff..37bb37aec4f 100644 --- a/htdocs/core/class/validate.class.php +++ b/htdocs/core/class/validate.class.php @@ -27,7 +27,6 @@ */ class Validate { - /** * @var DoliDb Database handler (result of a new DoliDB) */ @@ -62,7 +61,7 @@ class Validate } if (!is_object($this->outputLang) || !method_exists($this->outputLang, 'load')) { - return false; + return; } $this->outputLang->loadLangs(array('validate', 'errors')); @@ -72,7 +71,8 @@ class Validate /** * Use to clear errors msg or other ghost vars - * @return null + * + * @return void */ protected function clear() { @@ -82,8 +82,8 @@ class Validate /** * Use to clear errors msg or other ghost vars * - * @param string $errMsg your error message - * @return null + * @param string $errMsg your error message + * @return void */ protected function setError($errMsg) { @@ -93,9 +93,9 @@ class Validate /** * Check for e-mail validity * - * @param string $email e-mail address to validate - * @param int $maxLength string max length - * @return boolean Validity is ok or not + * @param string $email e-mail address to validate + * @param int $maxLength string max length + * @return boolean Validity is ok or not */ public function isEmail($email, $maxLength = false) { diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php index 7a1f68e5c6c..e54019a56b4 100644 --- a/htdocs/core/customreports.php +++ b/htdocs/core/customreports.php @@ -295,12 +295,7 @@ if (is_array($search_groupby) && count($search_groupby)) { $sqlfilters = GETPOST('search_component_params_hidden', 'alphanohtml'); if ($sqlfilters) { $errormessage = ''; - if (dolCheckFilters($sqlfilters, $errormessage)) { - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - $sql .= " WHERE (".preg_replace_callback('/'.$regexstring.'/', 'dolForgeCriteriaCallback', $sqlfilters).")"; - } else { - print $errormessage; - } + $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); }*/ $sql .= " LIMIT ".((int) ($MAXUNIQUEVALFORGROUP + 1)); @@ -420,7 +415,7 @@ $viewmode = ''; $viewmode .= '
'; $arrayofgraphs = array('bars' => 'Bars', 'lines' => 'Lines'); // also 'pies' $viewmode .= '
'.$langs->trans("Graph").'
'; -$viewmode .= $form->selectarray('search_graph', $arrayofgraphs, $search_graph, 0, 0, 0, 'minwidth100', 1); +$viewmode .= $form->selectarray('search_graph', $arrayofgraphs, $search_graph, 0, 0, 0, '', 1, 0, 0, '', 'graphtype width100'); $viewmode .= '
'; $num = 0; @@ -684,11 +679,9 @@ if (!empty($search_measures) && !empty($search_xaxis)) { $sqlfilters = $search_component_params_hidden; if ($sqlfilters) { $errormessage = ''; - if (dolCheckFilters($sqlfilters, $errormessage)) { - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'dolForgeCriteriaCallback', $sqlfilters).")"; - } else { - print $errormessage; + $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); + if ($errormessage) { + print dol_escape_htmltag($errormessage); } } $sql .= " GROUP BY "; diff --git a/htdocs/core/filemanagerdol/browser/default/browser.php b/htdocs/core/filemanagerdol/browser/default/browser.php index 0c1b29d12b2..1cf6d8612c2 100644 --- a/htdocs/core/filemanagerdol/browser/default/browser.php +++ b/htdocs/core/filemanagerdol/browser/default/browser.php @@ -49,6 +49,7 @@ if (!empty($conf->modules_parts['theme'])) { // This slow down } //print 'themepath='.$themepath.' themeparam='.$themeparam;exit; +$themeparam = ''; print ''."\n"; ?> diff --git a/htdocs/core/filemanagerdol/connectors/php/config.inc.php b/htdocs/core/filemanagerdol/connectors/php/config.inc.php index 848153d84fc..368b82c42e7 100644 --- a/htdocs/core/filemanagerdol/connectors/php/config.inc.php +++ b/htdocs/core/filemanagerdol/connectors/php/config.inc.php @@ -37,7 +37,7 @@ $pos = strstr($uri, '/'); // $pos contient alors url sans nom domaine if ($pos == '/') { $pos = ''; // si $pos vaut /, on le met a '' } -define('DOL_URL_ROOT', $pos); +//define('DOL_URL_ROOT', $pos); $entity = ((!empty($_SESSION['dol_entity']) && $_SESSION['dol_entity'] > 1) ? $_SESSION['dol_entity'] : null); // SECURITY: You must explicitly enable this "connector". (Set it to "true"). diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index c29eec57698..60adcc64003 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1003,8 +1003,8 @@ function dol_move($srcfile, $destfile, $newmask = 0, $overwriteifexists = 1, $te * @param string $srcdir Source directory * @param string $destdir Destination directory * @param int $overwriteifexists Overwrite directory if exists (1 by default) - * @param int $indexdatabase Index new file into database. - * @param int $renamedircontent Rename contents inside srcdir. + * @param int $indexdatabase Index new name of files into database. + * @param int $renamedircontent Also rename contents inside srcdir after the move to match new destination name. * * @return boolean True if OK, false if KO */ @@ -1045,7 +1045,7 @@ function dol_move_dir($srcdir, $destdir, $overwriteifexists = 1, $indexdatabase if ($file["type"] == "dir") { $res = dol_move_dir($filepath.'/'.$oldname, $filepath.'/'.$newname, $overwriteifexists, $indexdatabase, $renamedircontent); } else { - $res = dol_move($filepath.'/'.$oldname, $filepath.'/'.$newname); + $res = dol_move($filepath.'/'.$oldname, $filepath.'/'.$newname, 0, $overwriteifexists, 0, $indexdatabase); } if (!$res) { return $result; @@ -2590,54 +2590,54 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $original_file = $conf->adherent->dir_output.'/'.$original_file; } elseif ($modulepart == 'apercufacture' && !empty($conf->facture->multidir_output[$entity])) { // Wrapping for invoices (user need permission to read invoices) - if ($fuser->rights->facture->{$lire}) { + if ($fuser->hasRight('facture', $lire)) { $accessallowed = 1; } $original_file = $conf->facture->multidir_output[$entity].'/'.$original_file; } elseif ($modulepart == 'apercupropal' && !empty($conf->propal->multidir_output[$entity])) { // Wrapping pour les apercu propal - if ($fuser->rights->propal->{$lire}) { + if ($fuser->hasRight('propal', $lire)) { $accessallowed = 1; } $original_file = $conf->propal->multidir_output[$entity].'/'.$original_file; } elseif ($modulepart == 'apercucommande' && !empty($conf->commande->multidir_output[$entity])) { // Wrapping pour les apercu commande - if ($fuser->rights->commande->{$lire}) { + if ($fuser->hasRight('commande', $lire)) { $accessallowed = 1; } $original_file = $conf->commande->multidir_output[$entity].'/'.$original_file; } elseif (($modulepart == 'apercufichinter' || $modulepart == 'apercuficheinter') && !empty($conf->ficheinter->dir_output)) { // Wrapping pour les apercu intervention - if ($fuser->rights->ficheinter->{$lire}) { + if ($fuser->hasRight('ficheinter', $lire)) { $accessallowed = 1; } $original_file = $conf->ficheinter->dir_output.'/'.$original_file; } elseif (($modulepart == 'apercucontract') && !empty($conf->contrat->multidir_output[$entity])) { // Wrapping pour les apercu contrat - if ($fuser->rights->contrat->{$lire}) { + if ($fuser->hasRight('contrat', $lire)) { $accessallowed = 1; } $original_file = $conf->contrat->multidir_output[$entity].'/'.$original_file; } elseif (($modulepart == 'apercusupplier_proposal' || $modulepart == 'apercusupplier_proposal') && !empty($conf->supplier_proposal->dir_output)) { // Wrapping pour les apercu supplier proposal - if ($fuser->rights->supplier_proposal->{$lire}) { + if ($fuser->hasRight('supplier_proposal', $lire)) { $accessallowed = 1; } $original_file = $conf->supplier_proposal->dir_output.'/'.$original_file; } elseif (($modulepart == 'apercusupplier_order' || $modulepart == 'apercusupplier_order') && !empty($conf->fournisseur->commande->dir_output)) { // Wrapping pour les apercu supplier order - if ($fuser->rights->fournisseur->commande->{$lire}) { + if ($fuser->hasRight('fournisseur', 'commande', $lire)) { $accessallowed = 1; } $original_file = $conf->fournisseur->commande->dir_output.'/'.$original_file; } elseif (($modulepart == 'apercusupplier_invoice' || $modulepart == 'apercusupplier_invoice') && !empty($conf->fournisseur->facture->dir_output)) { // Wrapping pour les apercu supplier invoice - if ($fuser->rights->fournisseur->facture->{$lire}) { + if ($fuser->hasRight('fournisseur', $lire)) { $accessallowed = 1; } $original_file = $conf->fournisseur->facture->dir_output.'/'.$original_file; } elseif (($modulepart == 'holiday') && !empty($conf->holiday->dir_output)) { - if ($fuser->rights->holiday->{$read} || !empty($fuser->rights->holiday->readall) || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('holiday', $read) || !empty($fuser->rights->holiday->readall) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; // If we known $id of holiday, call checkUserAccessToObject to check permission on properties and hierarchy of leave request if ($refname && empty($fuser->rights->holiday->readall) && !preg_match('/^specimen/i', $original_file)) { @@ -2649,7 +2649,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } $original_file = $conf->holiday->dir_output.'/'.$original_file; } elseif (($modulepart == 'expensereport') && !empty($conf->expensereport->dir_output)) { - if ($fuser->rights->expensereport->{$lire} || !empty($fuser->rights->expensereport->readall) || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('expensereport', $lire) || !empty($fuser->rights->expensereport->readall) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; // If we known $id of expensereport, call checkUserAccessToObject to check permission on properties and hierarchy of expense report if ($refname && empty($fuser->rights->expensereport->readall) && !preg_match('/^specimen/i', $original_file)) { @@ -2662,72 +2662,72 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $original_file = $conf->expensereport->dir_output.'/'.$original_file; } elseif (($modulepart == 'apercuexpensereport') && !empty($conf->expensereport->dir_output)) { // Wrapping pour les apercu expense report - if ($fuser->rights->expensereport->{$lire}) { + if ($fuser->hasRight('expensereport', $lire)) { $accessallowed = 1; } $original_file = $conf->expensereport->dir_output.'/'.$original_file; } elseif ($modulepart == 'propalstats' && !empty($conf->propal->multidir_temp[$entity])) { // Wrapping pour les images des stats propales - if ($fuser->rights->propal->{$lire}) { + if ($fuser->hasRight('propal', $lire)) { $accessallowed = 1; } $original_file = $conf->propal->multidir_temp[$entity].'/'.$original_file; } elseif ($modulepart == 'orderstats' && !empty($conf->commande->dir_temp)) { // Wrapping pour les images des stats commandes - if ($fuser->rights->commande->{$lire}) { + if ($fuser->hasRight('commande', $lire)) { $accessallowed = 1; } $original_file = $conf->commande->dir_temp.'/'.$original_file; } elseif ($modulepart == 'orderstatssupplier' && !empty($conf->fournisseur->dir_output)) { - if ($fuser->rights->fournisseur->commande->{$lire}) { + if ($fuser->hasRight('fournisseur', 'commande', $lire)) { $accessallowed = 1; } $original_file = $conf->fournisseur->commande->dir_temp.'/'.$original_file; } elseif ($modulepart == 'billstats' && !empty($conf->facture->dir_temp)) { // Wrapping pour les images des stats factures - if ($fuser->rights->facture->{$lire}) { + if ($fuser->hasRight('facture', $lire)) { $accessallowed = 1; } $original_file = $conf->facture->dir_temp.'/'.$original_file; } elseif ($modulepart == 'billstatssupplier' && !empty($conf->fournisseur->dir_output)) { - if ($fuser->rights->fournisseur->facture->{$lire}) { + if ($fuser->hasRight('fournisseur', 'facture', $lire)) { $accessallowed = 1; } $original_file = $conf->fournisseur->facture->dir_temp.'/'.$original_file; } elseif ($modulepart == 'expeditionstats' && !empty($conf->expedition->dir_temp)) { // Wrapping pour les images des stats expeditions - if ($fuser->rights->expedition->{$lire}) { + if ($fuser->hasRight('expedition', $lire)) { $accessallowed = 1; } $original_file = $conf->expedition->dir_temp.'/'.$original_file; } elseif ($modulepart == 'tripsexpensesstats' && !empty($conf->deplacement->dir_temp)) { // Wrapping pour les images des stats expeditions - if ($fuser->rights->deplacement->{$lire}) { + if ($fuser->hasRight('deplacement', $lire)) { $accessallowed = 1; } $original_file = $conf->deplacement->dir_temp.'/'.$original_file; } elseif ($modulepart == 'memberstats' && !empty($conf->adherent->dir_temp)) { // Wrapping pour les images des stats expeditions - if ($fuser->rights->adherent->{$lire}) { + if ($fuser->hasRight('adherent', $lire)) { $accessallowed = 1; } $original_file = $conf->adherent->dir_temp.'/'.$original_file; } elseif (preg_match('/^productstats_/i', $modulepart) && !empty($conf->product->dir_temp)) { // Wrapping pour les images des stats produits - if ($fuser->rights->produit->{$lire} || $fuser->rights->service->{$lire}) { + if ($fuser->hasRight('produit', $lire) || $fuser->hasRight('service', $lire)) { $accessallowed = 1; } $original_file = (!empty($conf->product->multidir_temp[$entity]) ? $conf->product->multidir_temp[$entity] : $conf->service->multidir_temp[$entity]).'/'.$original_file; } elseif (in_array($modulepart, array('tax', 'tax-vat', 'tva')) && !empty($conf->tax->dir_output)) { // Wrapping for taxes - if ($fuser->rights->tax->charges->{$lire}) { + if ($fuser->hasRight('tax', 'charges', $lire)) { $accessallowed = 1; } $modulepartsuffix = str_replace('tax-', '', $modulepart); $original_file = $conf->tax->dir_output.'/'.($modulepartsuffix != 'tax' ? $modulepartsuffix.'/' : '').$original_file; } elseif ($modulepart == 'actions' && !empty($conf->agenda->dir_output)) { // Wrapping for events - if ($fuser->rights->agenda->myactions->{$read}) { + if ($fuser->hasRight('agenda', 'myactions', $read)) { $accessallowed = 1; // If we known $id of project, call checkUserAccessToObject to check permission on the given agenda event on properties and assigned users if ($refname && !preg_match('/^specimen/i', $original_file)) { @@ -2811,85 +2811,85 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, if (empty($entity) || empty($conf->societe->multidir_output[$entity])) { return array('accessallowed'=>0, 'error'=>'Value entity must be provided'); } - if ($fuser->rights->societe->{$lire}) { + if ($fuser->hasRight('societe', $lire)) { $accessallowed = 1; } $original_file = $conf->societe->multidir_output[$entity].'/contact/'.$original_file; } elseif (($modulepart == 'facture' || $modulepart == 'invoice') && !empty($conf->facture->multidir_output[$entity])) { // Wrapping for invoices - if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('facture', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->facture->multidir_output[$entity].'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('invoice').")"; } elseif ($modulepart == 'massfilesarea_proposals' && !empty($conf->propal->multidir_output[$entity])) { // Wrapping for mass actions - if ($fuser->rights->propal->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('propal', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->propal->multidir_output[$entity].'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_orders') { - if ($fuser->rights->commande->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('commande', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->commande->multidir_output[$entity].'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_sendings') { - if ($fuser->rights->expedition->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('expedition', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->expedition->dir_output.'/sending/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_invoices') { - if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('facture', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->facture->multidir_output[$entity].'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_expensereport') { - if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('facture', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->expensereport->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_interventions') { - if ($fuser->rights->ficheinter->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('ficheinter', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->ficheinter->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_supplier_proposal' && !empty($conf->supplier_proposal->dir_output)) { - if ($fuser->rights->supplier_proposal->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('supplier_proposal', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->supplier_proposal->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_supplier_order') { - if ($fuser->rights->fournisseur->commande->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('fournisseur', 'commande', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->fournisseur->commande->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_supplier_invoice') { - if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('fournisseur', 'facture', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->fournisseur->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif ($modulepart == 'massfilesarea_contract' && !empty($conf->contrat->dir_output)) { - if ($fuser->rights->contrat->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('contrat', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->contrat->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } elseif (($modulepart == 'fichinter' || $modulepart == 'ficheinter') && !empty($conf->ficheinter->dir_output)) { // Wrapping for interventions - if ($fuser->rights->ficheinter->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('ficheinter', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->ficheinter->dir_output.'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity; } elseif ($modulepart == 'deplacement' && !empty($conf->deplacement->dir_output)) { // Wrapping pour les deplacements et notes de frais - if ($fuser->rights->deplacement->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('deplacement', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->deplacement->dir_output.'/'.$original_file; //$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity; - } elseif (($modulepart == 'propal' || $modulepart == 'propale') && !empty($conf->propal->multidir_output[$entity])) { + } elseif (($modulepart == 'propal' || $modulepart == 'propale') && isset($conf->propal->multidir_output[$entity])) { // Wrapping pour les propales - if ($fuser->rights->propal->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('propal', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->propal->multidir_output[$entity].'/'.$original_file; @@ -2903,7 +2903,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('order').")"; } elseif ($modulepart == 'project' && !empty($conf->project->dir_output)) { // Wrapping pour les projets - if ($fuser->rights->projet->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('projet', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; // If we known $id of project, call checkUserAccessToObject to check permission on properties and contact of project if ($refname && !preg_match('/^specimen/i', $original_file)) { @@ -2916,7 +2916,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $original_file = $conf->project->dir_output.'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")"; } elseif ($modulepart == 'project_task' && !empty($conf->project->dir_output)) { - if ($fuser->rights->projet->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('projet', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; // If we known $id of project, call checkUserAccessToObject to check permission on properties and contact of project if ($refname && !preg_match('/^specimen/i', $original_file)) { @@ -2951,7 +2951,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."paiementfournisseur WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity; } elseif ($modulepart == 'facture_paiement' && !empty($conf->facture->dir_output)) { // Wrapping pour les rapport de paiements - if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('facture', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } if ($fuser->socid > 0) { @@ -2967,26 +2967,26 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $original_file = $conf->accounting->dir_output.'/'.$original_file; } elseif (($modulepart == 'expedition' || $modulepart == 'shipment') && !empty($conf->expedition->dir_output)) { // Wrapping pour les expedition - if ($fuser->rights->expedition->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('expedition', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->expedition->dir_output."/".(strpos('sending/', $original_file) === 0 ? '' : 'sending/').$original_file; //$original_file = $conf->expedition->dir_output."/".$original_file; } elseif (($modulepart == 'livraison' || $modulepart == 'delivery') && !empty($conf->expedition->dir_output)) { // Delivery Note Wrapping - if ($fuser->rights->expedition->delivery->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('expedition', 'delivery', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->expedition->dir_output."/".(strpos('receipt/', $original_file) === 0 ? '' : 'receipt/').$original_file; } elseif ($modulepart == 'actions' && !empty($conf->agenda->dir_output)) { // Wrapping pour les actions - if ($fuser->rights->agenda->myactions->{$read} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('agenda', 'myactions', $read) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->agenda->dir_output.'/'.$original_file; } elseif ($modulepart == 'actionsreport' && !empty($conf->agenda->dir_temp)) { // Wrapping pour les actions - if ($fuser->rights->agenda->allactions->{$read} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('agenda', 'allactions', $read) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->agenda->dir_temp."/".$original_file; @@ -2995,7 +2995,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, if (empty($entity) || (empty($conf->product->multidir_output[$entity]) && empty($conf->service->multidir_output[$entity]))) { return array('accessallowed'=>0, 'error'=>'Value entity must be provided'); } - if (($fuser->rights->produit->{$lire} || $fuser->rights->service->{$lire}) || preg_match('/^specimen/i', $original_file)) { + if (($fuser->hasRight('produit', $lire) || $fuser->hasRight('service', $lire)) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } if (isModEnabled("product")) { @@ -3008,7 +3008,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, if (empty($entity) || (empty($conf->productbatch->multidir_output[$entity]))) { return array('accessallowed'=>0, 'error'=>'Value entity must be provided'); } - if (($fuser->rights->produit->{$lire} ) || preg_match('/^specimen/i', $original_file)) { + if (($fuser->hasRight('produit', $lire)) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } if (isModEnabled('productbatch')) { @@ -3019,7 +3019,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, if (empty($entity) || empty($conf->stock->multidir_output[$entity])) { return array('accessallowed'=>0, 'error'=>'Value entity must be provided'); } - if (($fuser->rights->stock->{$lire} || $fuser->rights->stock->movement->{$lire} || $fuser->rights->stock->mouvement->{$lire}) || preg_match('/^specimen/i', $original_file)) { + if (($fuser->hasRight('stock', $lire) || $fuser->hasRight('stock', 'movement', $lire) || $fuser->hasRight('stock', 'mouvement', $lire)) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } if (isModEnabled('stock')) { @@ -3034,26 +3034,26 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."contrat WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('contract').")"; } elseif ($modulepart == 'donation' && !empty($conf->don->dir_output)) { // Wrapping pour les dons - if ($fuser->rights->don->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('don', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->don->dir_output.'/'.$original_file; } elseif ($modulepart == 'dolresource' && !empty($conf->resource->dir_output)) { // Wrapping pour les dons - if ($fuser->rights->resource->{$read} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('resource', $read) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->resource->dir_output.'/'.$original_file; } elseif (($modulepart == 'remisecheque' || $modulepart == 'chequereceipt') && !empty($conf->bank->dir_output)) { // Wrapping pour les remises de cheques - if ($fuser->rights->banque->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('banque', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->bank->dir_output.'/checkdeposits/'.$original_file; // original_file should contains relative path so include the get_exdir result } elseif (($modulepart == 'banque' || $modulepart == 'bank') && !empty($conf->bank->dir_output)) { // Wrapping for bank - if ($fuser->rights->banque->{$lire}) { + if ($fuser->hasRight('banque', $lire)) { $accessallowed = 1; } $original_file = $conf->bank->dir_output.'/'.$original_file; @@ -3096,7 +3096,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $original_file = $conf->bittorrent->dir_output.'/'.$dir.'/'.$original_file; } elseif ($modulepart == 'member' && !empty($conf->adherent->dir_output)) { // Wrapping pour Foundation module - if ($fuser->rights->adherent->{$lire} || preg_match('/^specimen/i', $original_file)) { + if ($fuser->hasRight('adherent', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } $original_file = $conf->adherent->dir_output.'/'.$original_file; diff --git a/htdocs/core/lib/fourn.lib.php b/htdocs/core/lib/fourn.lib.php index c658916e359..7093493dad9 100644 --- a/htdocs/core/lib/fourn.lib.php +++ b/htdocs/core/lib/fourn.lib.php @@ -3,7 +3,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2006 Marc Barilley * Copyright (C) 2011-2013 Philippe Grand - * Copyright (C) 2022 Frédéric France + * Copyright (C) 2022-2023 Frédéric France * * 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 @@ -29,10 +29,10 @@ /** * Prepare array with list of tabs * - * @param Object $object Object related to tabs + * @param FactureFournisseur $object Object related to tabs * @return array Array of tabs to show */ -function facturefourn_prepare_head($object) +function facturefourn_prepare_head(FactureFournisseur $object) { global $db, $langs, $conf; @@ -56,7 +56,7 @@ function facturefourn_prepare_head($object) } //if ($fac->mode_reglement_code == 'PRE') - if (!empty($conf->paymentbybanktransfer->enabled)) { + if (isModEnabled('paymentbybanktransfer')) { $nbStandingOrders = 0; $sql = "SELECT COUNT(pfd.rowid) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pfd"; @@ -132,8 +132,8 @@ function facturefourn_prepare_head($object) /** * Prepare array with list of tabs * - * @param Object $object Object related to tabs - * @return array Array of tabs to show + * @param CommandeFournisseur $object Object related to tabs + * @return array Array of tabs to show */ function ordersupplier_prepare_head(CommandeFournisseur $object) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index e6ac7f2d9f2..887d14fd36a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1125,6 +1125,7 @@ function dol_buildpath($path, $type = 0, $returnemptyifnotfound = 0) } continue; } + $regs = array(); preg_match('/^([^\?]+(\.css\.php|\.css|\.js\.php|\.js|\.png|\.jpg|\.php)?)/i', $path, $regs); // Take part before '?' if (!empty($regs[1])) { //print $key.'-'.$dirroot.'/'.$path.'-'.$conf->file->dol_url_root[$type].'
'."\n"; @@ -1672,7 +1673,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = if (!array_key_exists($level, $logLevels)) { throw new Exception('Incorrect log level'); } - if ($level > $conf->global->SYSLOG_LEVEL) { + if ($level > getDolGlobalInt('SYSLOG_LEVEL')) { return; } @@ -2324,14 +2325,12 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi } $tmptxt = $object->getLibStatut(5); $morehtmlstatus .= $tmptxt; // No status on task - } else { // Generic case - if (isset($object->status)) { - $tmptxt = $object->getLibStatut(6); - if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) { - $tmptxt = $object->getLibStatut(5); - } - $morehtmlstatus .= $tmptxt; + } elseif (method_exists($object, 'getLibStatut')) { // Generic case + $tmptxt = $object->getLibStatut(6); + if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) { + $tmptxt = $object->getLibStatut(5); } + $morehtmlstatus .= $tmptxt; } // Add if object was dispatched "into accountancy" @@ -2648,7 +2647,7 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = $format = '%Y%m%d%H%M%S'; } elseif ($format == 'dayhourlogsmall') { // Format not sensitive to language - $format = '%Y%m%d%H%M'; + $format = '%y%m%d%H%M'; } elseif ($format == 'dayhourldap') { $format = '%Y%m%d%H%M%SZ'; } elseif ($format == 'dayhourxcard') { @@ -2731,8 +2730,8 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = $dtts->setTimestamp($timetouse); $dtts->setTimezone($tzo); $newformat = str_replace( - array('%Y', '%y', '%m', '%d', '%H', '%I', '%M', '%S', '%p', 'T', 'Z', '__a__', '__A__', '__b__', '__B__'), - array('Y', 'y', 'm', 'd', 'H', 'h', 'i', 's', 'A', '__£__', '__$__', '__{__', '__}__', '__[__', '__]__'), + array('%Y', '%y', '%m', '%d', '%H', '%I', '%M', '%S', '%p', '%w', 'T', 'Z', '__a__', '__A__', '__b__', '__B__'), + array('Y', 'y', 'm', 'd', 'H', 'h', 'i', 's', 'A', 'w', '__£__', '__$__', '__{__', '__}__', '__[__', '__]__'), $format); $ret = $dtts->format($newformat); $ret = str_replace( @@ -3575,15 +3574,15 @@ function dol_print_phone($phone, $countrycode = '', $cid = 0, $socid = 0, $addli $picto = ''; } } - if ($adddivfloat) { + if ($adddivfloat == 1) { $rep .= '
'; - } else { + } elseif (empty($adddivfloat)) { $rep .= ''; } $rep .= ($withpicto ?img_picto($titlealt, 'object_'.$picto.'.png').' ' : '').$newphone; - if ($adddivfloat) { + if ($adddivfloat == 1) { $rep .= '
'; - } else { + } elseif (empty($adddivfloat)) { $rep .= ''; } } @@ -4008,8 +4007,9 @@ function dol_trunc($string, $size = 40, $trunc = 'right', $stringencoding = 'UTF * Show picto whatever it's its name (generic function) * * @param string $titlealt Text on title tag for tooltip. Not used if param notitle is set to 1. - * @param string $picto Name of image file to show ('filenew', ...) - * If no extension provided, we use '.png'. Image must be stored into theme/xxx/img directory. + * @param string $picto Name of image file to show ('filenew', ...). + * For font awesome icon (example 'user'), you can use picto_nocolor to not have the color of picto forced. + * If no extension provided and it is not a font awesome icon, we use '.png'. Image must be stored into theme/xxx/img directory. * Example: picto.png if picto.png is stored into htdocs/theme/mytheme/img * Example: picto.png@mymodule if picto.png is stored into htdocs/mymodule/img * Example: /mydir/mysubdir/picto.png if picto.png is stored into htdocs/mydir/mysubdir (pictoisfullpath must be set to 1) @@ -4047,6 +4047,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ } else { $pictowithouttext = preg_replace('/(\.png|\.gif|\.svg)$/', '', $picto); $pictowithouttext = str_replace('object_', '', $pictowithouttext); + $pictowithouttext = str_replace('_nocolor', '', $pictowithouttext); if (strpos($pictowithouttext, 'fontawesome_') !== false || preg_match('/^fa-/', $pictowithouttext)) { // This is a font awesome image 'fonwtawesome_xxx' or 'fa-xxx' @@ -4104,7 +4105,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'edit', 'ellipsis-h', 'email', 'entity', 'envelope', 'eraser', 'establishment', 'expensereport', 'external-link-alt', 'external-link-square-alt', 'eye', 'filter', 'file-code', 'file-export', 'file-import', 'file-upload', 'autofill', 'folder', 'folder-open', 'folder-plus', 'gears', 'generate', 'globe', 'globe-americas', 'graph', 'grip', 'grip_title', 'group', - 'help', 'holiday', + 'hands-helping', 'help', 'holiday', 'id-card', 'images', 'incoterm', 'info', 'intervention', 'inventory', 'intracommreport', 'jobprofile', 'knowledgemanagement', 'label', 'language', 'line', 'link', 'list', 'list-alt', 'listlight', 'loan', 'lock', 'lot', 'long-arrow-alt-right', @@ -4256,7 +4257,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ //'title_setup'=>'infobox-action', 'tools'=>'infobox-action', 'list-alt'=>'imgforviewmode', 'calendar'=>'imgforviewmode', 'calendarweek'=>'imgforviewmode', 'calendarmonth'=>'imgforviewmode', 'calendarday'=>'imgforviewmode', 'calendarperuser'=>'imgforviewmode' ); - if (!empty($arrayconvpictotomorcess[$pictowithouttext])) { + if (!empty($arrayconvpictotomorcess[$pictowithouttext]) && strpos($picto, '_nocolor') === false) { $morecss .= ($morecss ? ' ' : '').$arrayconvpictotomorcess[$pictowithouttext]; } @@ -4276,7 +4277,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'uncheck'=>'#800', 'uparrow'=>'#555', 'user-cog'=>'#999', 'country'=>'#aaa', 'globe-americas'=>'#aaa', 'region'=>'#aaa', 'state'=>'#aaa', 'website'=>'#304', 'workstation'=>'#a69944' ); - if (isset($arrayconvpictotocolor[$pictowithouttext])) { + if (isset($arrayconvpictotocolor[$pictowithouttext]) && strpos($picto, '_nocolor') === false) { $facolor = $arrayconvpictotocolor[$pictowithouttext]; } @@ -5175,7 +5176,7 @@ function dol_print_error_email($prefixcode, $errormessage = '', $errormessages = * @param string $moreattrib Options of attribute td ("" by defaut) * @param string $sortfield Current field used to sort * @param string $sortorder Current sort order - * @param string $prefix Prefix for css. Use space after prefix to add your own CSS tag. + * @param string $prefix Prefix for css. Use space after prefix to add your own CSS tag, for example 'mycss '. * @param string $tooltip Tooltip * @param string $forcenowrapcolumntitle No need for use 'wrapcolumntitle' css style * @return void @@ -7638,9 +7639,9 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, '__USER_ID__' => (string) $user->id, '__USER_LOGIN__' => (string) $user->login, '__USER_EMAIL__' => (string) $user->email, - '__USER_PHONE__' => (string) dol_print_phone($user->office_phone), - '__USER_PHONEPRO__' => (string) dol_print_phone($user->user_mobile), - '__USER_PHONEMOBILE__' => (string) dol_print_phone($user->personal_mobile), + '__USER_PHONE__' => (string) dol_print_phone($user->office_phone, '', 0, 0, '', " ", '', '', -1), + '__USER_PHONEPRO__' => (string) dol_print_phone($user->user_mobile, '', 0, 0, '', " ", '', '', -1), + '__USER_PHONEMOBILE__' => (string) dol_print_phone($user->personal_mobile, '', 0, 0, '', " ", '', '', -1), '__USER_FAX__' => (string) $user->office_fax, '__USER_LASTNAME__' => (string) $user->lastname, '__USER_FIRSTNAME__' => (string) $user->firstname, @@ -7655,8 +7656,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray = array_merge($substitutionarray, array( '__MYCOMPANY_NAME__' => $mysoc->name, '__MYCOMPANY_EMAIL__' => $mysoc->email, - '__MYCOMPANY_PHONE__' => dol_print_phone($mysoc->phone), - '__MYCOMPANY_FAX__' => dol_print_phone($mysoc->fax), + '__MYCOMPANY_PHONE__' => dol_print_phone($mysoc->phone, '', 0, 0, '', " ", '', '', -1), + '__MYCOMPANY_FAX__' => dol_print_phone($mysoc->fax, '', 0, 0, '', " ", '', '', -1), '__MYCOMPANY_PROFID1__' => $mysoc->idprof1, '__MYCOMPANY_PROFID2__' => $mysoc->idprof2, '__MYCOMPANY_PROFID3__' => $mysoc->idprof3, @@ -9093,11 +9094,9 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' } } } catch (Error $e) { - $error = 'Caught error : '; - $error .= $e->getMessage() . ', '; - $error .= 'Trace : '; - $error .= json_encode($e->getTrace()); - error_log($error, 1); + $error = 'dol_eval try/catch error : '; + $error .= $e->getMessage(); + dol_syslog($error); } } @@ -9593,7 +9592,7 @@ function printCommonFooter($zone = 'private') } // Management of focus and mandatory for fields - if ($action == 'create' || $action == 'edit' || (empty($action) && (preg_match('/new\.php/', $_SERVER["PHP_SELF"])))) { + if ($action == 'create' || $action == 'edit' || (empty($action) && (preg_match('/new\.php/', $_SERVER["PHP_SELF"]))) || ((empty($action) || $action == 'addline') && (preg_match('/card\.php/', $_SERVER["PHP_SELF"])))) { print '/* JS CODE TO ENABLE to manage focus and mandatory form fields */'."\n"; $relativepathstring = $_SERVER["PHP_SELF"]; // Clean $relativepathstring @@ -11584,15 +11583,34 @@ function jsonOrUnserialize($stringtodecode) /** - * Return if a $sqlfilters parameter is valid and will pass the preg_replace_callback() to replace Generic filter string with SQL filter string - * Example of usage: - * if ($sqlfilters) { - * $errormessage = ''; - * if (dolCheckFilters($sqlfilters, $errormessage)) { - * $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - * $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'dolForgeCriteriaCallback', $sqlfilters).")"; - * } - * } + * forgeSQLFromUniversalSearchCriteria + * + * @param string $filter String with universal search string + * @param string $error Error message + * @return string Return forged SQL string + */ +function forgeSQLFromUniversalSearchCriteria($filter, &$error = '') +{ + $regexstring = '\(([a-zA-Z0-9_\.]+:[<>!=insotlke]+:[^\(\)]+)\)'; // Must be (aaa:bbb:...) with aaa is a field name (with alias or not) and bbb is one of this operator '=', '<', '>', '<=', '>=', '!=', 'in', 'notin', 'like', 'notlike', 'is', 'isnot' + + if (!dolCheckFilters($filter, $error)) { + return '1 = 2'; // Bad balance of parenthesis, we force a SQL not found + } + + // Test the filter syntax + $t = preg_replace_callback('/'.$regexstring.'/i', 'dolForgeDummyCriteriaCallback', $filter); + $t = str_replace(array('and','or','AND','OR',' '), '', $t); // Remove the only strings allowed between each () criteria + // If the string result contains something else than '()', the syntax was wrong + if (preg_match('/[^\(\)]/', $t)) { + $error = 'Bad syntax of the search string, filter criteria is inhalited'; + return '1 = 3'; // Bad syntax of the search string, we force a SQL not found + } + + return " AND (".preg_replace_callback('/'.$regexstring.'/i', 'dolForgeCriteriaCallback', $filter).")"; +} + +/** + * Return if a $sqlfilters parameter has a valid balance of parenthesis * * @param string $sqlfilters sqlfilter string * @param string $error Error message @@ -11613,7 +11631,7 @@ function dolCheckFilters($sqlfilters, &$error = '') $counter--; } if ($counter < 0) { - $error = "Bad sqlfilters=".$sqlfilters; + $error = "Wrond balance of parenthesis in sqlfilters=".$sqlfilters; dol_syslog($error, LOG_WARNING); return false; } @@ -11623,57 +11641,92 @@ function dolCheckFilters($sqlfilters, &$error = '') } /** - * Function to forge a SQL criteria from a Generic filter string. - * Example of usage: - * if ($sqlfilters) { - * $errormessage = ''; - * if (dolCheckFilters($sqlfilters, $errormessage)) { - * $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - * $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'dolForgeCriteriaCallback', $sqlfilters).")"; - * } - * } + * Function to forge a SQL criteria from a Dolibarr filter syntax string. + * This method is called by forgeSQLFromUniversalSearchCriteria() * - * @param array $matches Array of found string by regex search. - * Example: "t.ref:like:'SO-%'" or "t.date_creation:<:'20160101'" or "t.date_creation:<:'2016-01-01 12:30:00'" or "t.nature:is:NULL" - * @return string Forged criteria. Example: "t.field like 'abc%'" + * @param array $matches Array of found string by regex search. Example: "t.ref:like:'SO-%'" or "t.date_creation:<:'20160101'" or "t.nature:is:NULL" + * @return string Forged criteria. Example: "t.field like 'abc%'" + */ +function dolForgeDummyCriteriaCallback($matches) +{ + //dol_syslog("Convert matches ".$matches[1]); + if (empty($matches[1])) { + return ''; + } + $tmp = explode(':', $matches[1]); + if (count($tmp) < 3) { + return ''; + } + + return '()'; // An empty criteria +} + +/** + * Function to forge a SQL criteria from a Dolibarr filter syntax string. + * This method is called by forgeSQLFromUniversalSearchCriteria() + * + * @param array $matches Array of found string by regex search. + * Example: "t.ref:like:'SO-%'" or "t.date_creation:<:'20160101'" or "t.date_creation:<:'2016-01-01 12:30:00'" or "t.nature:is:NULL" + * @return string Forged criteria. Example: "t.field like 'abc%'" */ function dolForgeCriteriaCallback($matches) { global $db; - dol_syslog("Convert matches ".$matches[1]); + //dol_syslog("Convert matches ".$matches[1]); if (empty($matches[1])) { return ''; } - $tmp = explode(':', $matches[1], 3); - + $tmp = explode(':', $matches[1]); if (count($tmp) < 3) { return ''; } - $operand = preg_replace('/[^a-z0-9\._]/i', '', trim($tmp[0])); - $operator = strtoupper(preg_replace('/[^a-z<>=]/i', '', trim($tmp[1]))); if ($operator == 'NOTLIKE') { $operator = 'NOT LIKE'; } + if ($operator == 'ISNOT') { + $operator = 'IS NOT'; + } + if ($operator == '!=') { + $operator = '<>'; + } - $tmpescaped = trim($tmp[2]); + $tmpescaped = $tmp[2]; $regbis = array(); - if ($operator == 'IN') { - $tmpescaped = "(".$db->sanitize($tmpescaped, 1).")"; + + if ($operator == 'IN') { // IN is allowed for list of ID or code only + //if (!preg_match('/^\(.*\)$/', $tmpescaped)) { + $tmpescaped = '('.$db->escape($db->sanitize($tmpescaped, 1, 0)).')'; + //} else { + // $tmpescaped = $db->escape($db->sanitize($tmpescaped, 1)); + //} + } elseif ($operator == 'LIKE' || $operator == 'NOT LIKE') { + if (preg_match('/^\'(.*)\'$/', $tmpescaped, $regbis)) { + $tmpescaped = $regbis[1]; + } + //$tmpescaped = "'".$db->escapeforlike($db->escape($regbis[1]))."'"; + $tmpescaped = "'".$db->escape($tmpescaped)."'"; // We do not escape the _ and % so the like will works } elseif (preg_match('/^\'(.*)\'$/', $tmpescaped, $regbis)) { $tmpescaped = "'".$db->escape($regbis[1])."'"; } else { - $tmpescaped = $db->sanitize($db->escape($tmpescaped)); + if (strtoupper($tmpescaped) == 'NULL') { + $tmpescaped = 'NULL'; + } elseif (is_int($tmpescaped)) { + $tmpescaped = (int) $tmpescaped; + } else { + $tmpescaped = (float) $tmpescaped; + } } - return $db->escape($operand).' '.$db->escape($operator)." ".$tmpescaped; + return $db->escape($tmp[0]).' '.strtoupper($operator).' '.$tmpescaped; } /** * Get timeline icon + * * @param ActionComm $actionstatic actioncomm * @param array $histo histo * @param int $key key diff --git a/htdocs/core/lib/memory.lib.php b/htdocs/core/lib/memory.lib.php index 5c4826a2dc5..3be5e902816 100644 --- a/htdocs/core/lib/memory.lib.php +++ b/htdocs/core/lib/memory.lib.php @@ -57,7 +57,7 @@ $shmoffset = 1000; // Max number of entries found into a language file. If too l /** - * Save data into a memory area shared by all users, all sessions on server + * Save data into a memory area shared by all users, all sessions on server. Note: MAIN_CACHE_COUNT must be set. * * @param string $memoryid Memory id of shared area * @param mixed $data Data to save. It must not be a null value. diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 29947dda57c..3dfccc88ea5 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -250,7 +250,9 @@ function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current - $urltouse = DOL_MAIN_URL_ROOT; + $urltouse = DOL_MAIN_URL_ROOT; // Should be "https://www.mydomain.com/mydolibarr" for example + //dol_syslog("getOnlinePaymentUrl DOL_MAIN_URL_ROOT=".DOL_MAIN_URL_ROOT); + if ($localorexternal) { $urltouse = $urlwithroot; } diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 4d9569a1cc4..7a5848adaf3 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -13,6 +13,7 @@ * Copyright (C) 2019 Lenin Rivas * Copyright (C) 2020 Nicolas ZABOURI * Copyright (C) 2021-2022 Anthony Berton + * Copyright (C) 2023 Frédéric France * * 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 @@ -1287,11 +1288,14 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_ } } // Show page nb only on iso languages (so default Helvetica font) - if (strtolower(pdf_getPDFFont($outputlangs)) == 'helvetica') { + // if (strtolower(pdf_getPDFFont($outputlangs)) == 'helvetica') { $pdf->SetXY($dims['wk'] - $dims['rm'] - 18, -$posy); - //$pdf->MultiCell(18, 2, $pdf->getPageNumGroupAlias().' / '.$pdf->getPageGroupAlias(), 0, 'R', 0); - $pdf->MultiCell(18, 2, $pdf->PageNo().' / '.$pdf->getAliasNbPages(), 0, 'R', 0); - } + // $pdf->MultiCell(18, 2, $pdf->getPageNumGroupAlias().' / '.$pdf->getPageGroupAlias(), 0, 'R', 0); + // $pdf->MultiCell(18, 2, $pdf->PageNo().' / '.$pdf->getAliasNbPages(), 0, 'R', 0); // doesn't works with all fonts + // $pagination = $pdf->getAliasNumPage().' / '.$pdf->getAliasNbPages(); // works with $pdf->Cell + $pagination = $pdf->PageNo().' / '.$pdf->getNumPages(); + $pdf->MultiCell(18, 2, $pagination, 0, 'R', 0); + // } // Show Draft Watermark if (!empty($watermark)) { @@ -2471,10 +2475,12 @@ function pdf_getLinkedObjects(&$object, $outputlangs) $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending"); if (!empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'] .= ' / '; $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref); + $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs); } else { $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending"); if (empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : ''); $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref); + $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs); } } } @@ -2508,6 +2514,8 @@ function pdf_getSizeForImage($realpath) $maxheight = (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT) ? 32 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT); include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; $tmp = dol_getImageSize($realpath); + $width = 0; + $height = 0; if ($tmp['height']) { $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight if ($width > $maxwidth) { // Pb with maxheight, so i use maxwidth diff --git a/htdocs/core/lib/propal.lib.php b/htdocs/core/lib/propal.lib.php index b5e459c8637..588418c7449 100644 --- a/htdocs/core/lib/propal.lib.php +++ b/htdocs/core/lib/propal.lib.php @@ -105,9 +105,39 @@ function propal_prepare_head($object) $head[$h][2] = 'document'; $h++; - $head[$h][0] = DOL_URL_ROOT.'/comm/propal/info.php?id='.$object->id; - $head[$h][1] = $langs->trans('Info'); - $head[$h][2] = 'info'; + + $head[$h][0] = DOL_URL_ROOT.'/comm/propal/agenda.php?id='.$object->id; + $head[$h][1] = $langs->trans("Events"); + if (isModEnabled('agenda')&& (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { + $nbEvent = 0; + // Enable caching of thirdparty count actioncomm + require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; + $cachekey = 'count_events_propal_'.$object->id; + $dataretrieved = dol_getcache($cachekey); + if (!is_null($dataretrieved)) { + $nbEvent = $dataretrieved; + } else { + $sql = "SELECT COUNT(id) as nb"; + $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm"; + $sql .= " WHERE fk_element = ".((int) $object->id); + $sql .= " AND elementtype = 'propal'"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + $nbEvent = $obj->nb; + } else { + dol_syslog('Failed to count actioncomm '.$db->lasterror(), LOG_ERR); + } + dol_setcache($cachekey, $nbEvent, 120); // If setting cache fails, this is not a problem, so we do not test result. + } + + $head[$h][1] .= '/'; + $head[$h][1] .= $langs->trans("Agenda"); + if ($nbEvent > 0) { + $head[$h][1] .= ''.$nbEvent.''; + } + } + $head[$h][2] = 'agenda'; $h++; complete_head_from_modules($conf, $langs, $object, $head, $h, 'propal', 'add', 'external'); diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index 273e7285273..64747c1bbf6 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -366,7 +366,7 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) print ''; print ''.$langs->trans("DefaultSkin").''; print ''.$conf->global->MAIN_THEME.''; - print ' '.$langs->trans("UsePersonalValue").''; + print ' '; print ' '; print ''; } else { diff --git a/htdocs/core/menus/standard/auguria_menu.php b/htdocs/core/menus/standard/auguria_menu.php index ae40ec170fc..168effd964d 100644 --- a/htdocs/core/menus/standard/auguria_menu.php +++ b/htdocs/core/menus/standard/auguria_menu.php @@ -37,6 +37,11 @@ class MenuManager public $atarget = ""; // To store default target to use onto links public $name = "auguria"; + /** + * @var Menu + */ + public $menu; + public $menu_array; public $menu_array_after; diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 19136ba492f..59c49f7fc7f 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1683,7 +1683,7 @@ function get_left_menu_accountancy($mainmenu, &$newmenu, $usemenuhider = 1, $lef // Multi journal $sql = "SELECT rowid, code, label, nature"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_journal"; - $sql .= " WHERE entity = ".$conf->entity; + $sql .= " WHERE entity = ".((int) $conf->entity); $sql .= " AND active = 1"; $sql .= " ORDER BY nature ASC, label DESC"; @@ -1734,11 +1734,12 @@ function get_left_menu_accountancy($mainmenu, &$newmenu, $usemenuhider = 1, $lef $langs->load('accountancy'); $journallabel = ''; if ($objp->label) { + $journallabelwithoutspan = $langs->transnoentities($objp->label); $journallabel = '('.$langs->transnoentities($objp->label).')'; // Label of bank account in llx_accounting_journal } - $key = $langs->trans("AccountingJournalType".strtoupper($objp->nature)); - $transferlabel = ($objp->nature && $key != "AccountingJournalType".strtoupper($langs->trans($objp->nature)) ? $key.($journallabel != $key ? ' '.$journallabel : ''): $journallabel); + $key = $langs->trans("AccountingJournalType".$objp->nature); // $objp->nature is 1, 2, 3 ... + $transferlabel = (($objp->nature && $key != "AccountingJournalType".$objp->nature) ? $key.($journallabelwithoutspan != $key ? ' '.$journallabel : ''): $journallabel); $newmenu->add('/accountancy/journal/'.$nature.'journal.php?mainmenu=accountancy&leftmenu=accountancy_journal&id_journal='.$objp->rowid, $transferlabel, 2, $user->hasRight('accounting', 'comptarapport', 'lire')); } diff --git a/htdocs/core/menus/standard/eldy_menu.php b/htdocs/core/menus/standard/eldy_menu.php index 596e1e4cc3f..de33b209383 100644 --- a/htdocs/core/menus/standard/eldy_menu.php +++ b/htdocs/core/menus/standard/eldy_menu.php @@ -36,6 +36,11 @@ class MenuManager public $atarget = ""; // To store default target to use onto links public $name = "eldy"; + /** + * @var Menu + */ + public $menu; + public $menu_array; public $menu_array_after; diff --git a/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php b/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php index 92af12427b2..afa3b56b4f5 100644 --- a/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php +++ b/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php @@ -689,7 +689,8 @@ class pdf_standard_asset extends ModelePDFAsset $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) { + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if ($object->remise_percent) { @@ -697,7 +698,7 @@ class pdf_standard_asset extends ModelePDFAsset } if ($object->remise_percent) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index 533619ed055..1cf3864d333 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -542,7 +542,8 @@ class pdf_einstein extends ModelePDFCommandes $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) { + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if ($object->remise_percent) { @@ -550,7 +551,7 @@ class pdf_einstein extends ModelePDFCommandes } if ($object->remise_percent) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php index bae583ccf4c..78b3fa24a33 100644 --- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php @@ -767,7 +767,8 @@ class pdf_eratosthene extends ModelePDFCommandes $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) { + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if ($object->remise_percent) { @@ -775,7 +776,7 @@ class pdf_eratosthene extends ModelePDFCommandes } if ($object->remise_percent) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/contract/doc/pdf_strato.modules.php b/htdocs/core/modules/contract/doc/pdf_strato.modules.php index 69b7f193a70..59a4a549242 100644 --- a/htdocs/core/modules/contract/doc/pdf_strato.modules.php +++ b/htdocs/core/modules/contract/doc/pdf_strato.modules.php @@ -45,6 +45,11 @@ class pdf_strato extends ModelePDFContract */ public $db; + /** + * @var int The environment ID when using a multicompany module + */ + public $entity; + /** * @var string model name */ @@ -114,7 +119,7 @@ class pdf_strato extends ModelePDFContract /** * Issuer - * @var Societe + * @var Societe Object that emits */ public $emetteur; @@ -138,7 +143,7 @@ class pdf_strato extends ModelePDFContract $this->description = $langs->trans("StandardContractsTemplate"); $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template - // Page size for A4 format + // Dimension page $this->type = 'pdf'; $formatarray = pdf_getFormat(); @@ -160,7 +165,7 @@ class pdf_strato extends ModelePDFContract // Get source company $this->emetteur = $mysoc; if (empty($this->emetteur->country_code)) { - $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if not defined + $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined } // Define position of columns @@ -182,7 +187,7 @@ class pdf_strato extends ModelePDFContract public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0) { // phpcs:enable - global $user, $langs, $conf, $hookmanager, $mysoc; + global $user, $langs, $conf, $mysoc, $db, $hookmanager, $nblines; if (!is_object($outputlangs)) { $outputlangs = $langs; @@ -192,15 +197,30 @@ class pdf_strato extends ModelePDFContract $outputlangs->charset_output = 'ISO-8859-1'; } - // Load traductions files required by page + // Load translation files required by page $outputlangs->loadLangs(array("main", "dict", "companies", "contracts")); - if ($conf->contrat->dir_output) { + // Show Draft Watermark + if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->CONTRACT_DRAFT_WATERMARK))) { + $this->watermark = $conf->global->CONTRACT_DRAFT_WATERMARK; + } + + global $outputlangsbis; + $outputlangsbis = null; + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) { + $outputlangsbis = new Translate('', $conf); + $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE); + $outputlangsbis->loadLangs(array("main", "dict", "companies", "bills", "products", "orders", "deliveries")); + } + + $nblines = count($object->lines); + + if ($conf->contract->multidir_output[$conf->entity]) { $object->fetch_thirdparty(); // Definition of $dir and $file if ($object->specimen) { - $dir = $conf->contrat->dir_output; + $dir = $conf->contract->multidir_output[$conf->entity]; $file = $dir."/SPECIMEN.pdf"; } else { $objectref = dol_sanitizeFileName($object->ref); @@ -210,7 +230,7 @@ class pdf_strato extends ModelePDFContract if (!file_exists($dir)) { if (dol_mkdir($dir) < 0) { - $this->error = $outputlangs->trans("ErrorCanNotCreateDir", $dir); + $this->error = $langs->trans("ErrorCanNotCreateDir", $dir); return 0; } } @@ -226,15 +246,20 @@ class pdf_strato extends ModelePDFContract global $action; $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + // Set nblines with the new command lines content after hook + $nblines = count($object->lines); + + // Create pdf instance $pdf = pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance + $pdf->SetAutoPageBreak(1, 0); + $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext = (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 9; // Height reserved to output the footer (value include bottom margin) if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) { $heightforfooter += 6; } - $pdf->SetAutoPageBreak(1, 0); if (class_exists('TCPDF')) { $pdf->setPrintHeader(false); @@ -243,7 +268,11 @@ class pdf_strato extends ModelePDFContract $pdf->SetFont(pdf_getPDFFont($outputlangs)); // Set path to the background PDF File if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) { - $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND); + $logodir = $conf->mycompany->dir_output; + if (!empty($conf->mycompany->multidir_output[$object->entity])) { + $logodir = $conf->mycompany->multidir_output[$object->entity]; + } + $pagecount = $pdf->setSourceFile($logodir.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND); $tplidx = $pdf->importPage(1); } @@ -252,10 +281,10 @@ class pdf_strato extends ModelePDFContract $pdf->SetDrawColor(128, 128, 128); $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); - $pdf->SetSubject($outputlangs->transnoentities("ContractCard")); + $pdf->SetSubject($outputlangs->transnoentities("Contract")); $pdf->SetCreator("Dolibarr ".DOL_VERSION); $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); - $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("ContractCard")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Contract")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) { $pdf->SetCompression(false); } @@ -268,7 +297,7 @@ class pdf_strato extends ModelePDFContract $pdf->useTemplate($tplidx); } $pagenb++; - $this->_pagehead($pdf, $object, 1, $outputlangs); + $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs, (is_object($outputlangsbis) ? $outputlangsbis : null)); $pdf->SetFont('', '', $default_font_size - 1); $pdf->MultiCell(0, 3, ''); // Set interline to 3 $pdf->SetTextColor(0, 0, 0); @@ -408,6 +437,7 @@ class pdf_strato extends ModelePDFContract { $pdf->commitTransaction(); } + $posYAfterDescription = $pdf->GetY(); $nexY = $pdf->GetY() + 2; $pageposafter = $pdf->getPage(); @@ -417,7 +447,7 @@ class pdf_strato extends ModelePDFContract $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. // We suppose that a too long description is moved completely on next page - if ($pageposafter > $pageposbefore) { + if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) { $pdf->setPage($pageposafter); $curY = $tab_top_newpage; } @@ -483,10 +513,6 @@ class pdf_strato extends ModelePDFContract $pdf->Output($file, 'F'); // Add pdfgeneration hook - if (!is_object($hookmanager)) { - include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; - $hookmanager = new HookManager($this->db); - } $hookmanager->initHooks(array('pdfgeneration')); $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs); global $action; @@ -500,13 +526,13 @@ class pdf_strato extends ModelePDFContract $this->result = array('fullpath'=>$file); - return 1; + return 1; // No error } else { - $this->error = $langs->trans("ErrorCanNotCreateDir", $dir); + $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir); return 0; } } else { - $this->error = $langs->trans("ErrorConstantNotDefined", "CONTRACT_OUTPUTDIR"); + $this->error = $langs->transnoentities("ErrorConstantNotDefined", "CONTRACT_OUTPUTDIR"); return 0; } } @@ -534,7 +560,9 @@ class pdf_strato extends ModelePDFContract $hidetop = -1; } + $currency = !empty($currency) ? $currency : $conf->currency; $default_font_size = pdf_getPDFFontSize($outputlangs); + /* $pdf->SetXY($this->marge_gauche, $tab_top); $pdf->MultiCell(190,8,$outputlangs->transnoentities("Description"),0,'L',0); @@ -600,76 +628,97 @@ class pdf_strato extends ModelePDFContract * @param Contrat $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output - * @return void + * @param Translate $outputlangsbis Object lang for output bis + * @param string $titlekey Translation key to show as title of document + * @return int Return topshift value */ - protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs) + protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null, $titlekey = "Contract") { - global $conf, $langs; + // phpcs:enable + global $conf, $langs, $hookmanager; - $default_font_size = pdf_getPDFFontSize($outputlangs); + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') { + $ltrdirection = 'R'; + } // Load traductions files required by page $outputlangs->loadLangs(array("main", "dict", "contract", "companies")); + $default_font_size = pdf_getPDFFontSize($outputlangs); + pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); - //Affiche le filigrane brouillon - Print Draft Watermark - if ($object->statut == 0 && (!empty($conf->global->CONTRACT_DRAFT_WATERMARK))) { - pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->CONTRACT_DRAFT_WATERMARK); - } - - //Prepare next $pdf->SetTextColor(0, 0, 60); $pdf->SetFont('', 'B', $default_font_size + 3); - $posx = $this->page_largeur - $this->marge_droite - 100; + $w = 100; + $posy = $this->marge_haute; + $posx = $this->page_largeur - $this->marge_droite - $w; $pdf->SetXY($this->marge_gauche, $posy); // Logo - $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo; - if ($this->emetteur->logo) { - if (is_readable($logo)) { - $height = pdf_getHeightForLogo($logo); - $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) + if (empty($conf->global->PDF_DISABLE_MYCOMPANY_LOGO)) { + if ($this->emetteur->logo) { + $logodir = $conf->mycompany->dir_output; + if (!empty($conf->mycompany->multidir_output[$object->entity])) { + $logodir = $conf->mycompany->multidir_output[$object->entity]; + } + if (empty($conf->global->MAIN_PDF_USE_LARGE_LOGO)) { + $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small; + } else { + $logo = $logodir.'/logos/'.$this->emetteur->logo; + } + if (is_readable($logo)) { + $height = pdf_getHeightForLogo($logo); + $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) + } else { + $pdf->SetTextColor(200, 0, 0); + $pdf->SetFont('', 'B', $default_font_size - 2); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); + } } else { - $pdf->SetTextColor(200, 0, 0); - $pdf->SetFont('', 'B', $default_font_size - 2); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L'); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); + $text = $this->emetteur->name; + $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } - } else { - $text = $this->emetteur->name; - $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); } $pdf->SetFont('', 'B', $default_font_size + 3); $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $title = $outputlangs->transnoentities("ContractCard"); - $pdf->MultiCell(100, 4, $title, '', 'R'); + $title = $outputlangs->transnoentities($titlekey); + $title .= ' '.$outputlangs->convToOutputCharset($object->ref); + if ($object->statut == $object::STATUS_DRAFT) { + $pdf->SetTextColor(128, 0, 0); + $title .= ' - '.$outputlangs->transnoentities("NotValidated"); + } + $pdf->MultiCell($w, 3, $title, '', 'R'); - $pdf->SetFont('', 'B', $default_font_size + 2); + $pdf->SetFont('', 'B', $default_font_size); + /* $posy += 5; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R'); + */ - $posy += 1; - $pdf->SetFont('', '', $default_font_size); + $posy += 3; + $pdf->SetFont('', '', $default_font_size - 1); $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date_contrat, "day", false, $outputlangs, true), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date_contrat, "day", false, $outputlangs, true), '', 'R'); if (empty($conf->global->MAIN_PDF_HIDE_CUSTOMER_CODE) && $object->thirdparty->code_client) { $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R'); } if ($showaddress) { @@ -700,6 +749,7 @@ class pdf_strato extends ModelePDFContract $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); + $pdf->SetTextColor(0, 0, 60); } // Show sender name @@ -707,13 +757,13 @@ class pdf_strato extends ModelePDFContract $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetTextColor(0, 0, 60); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell(80, 3, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); $posy = $pdf->getY(); } // Show sender information - $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); + $pdf->SetFont('', '', $default_font_size - 1); $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); @@ -736,14 +786,16 @@ class pdf_strato extends ModelePDFContract $this->recipient->name = pdfBuildThirdpartyName($thirdparty, $outputlangs); - $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, (isset($object->contact) ? $object->contact : ''), $usecontact, 'target', $object); + $mode = 'target'; + $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, (isset($object->contact) ? $object->contact : ''), $usecontact, $mode, $object); // Show recipient - $widthrecbox = 100; + $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 100; if ($this->page_largeur < 210) { $widthrecbox = 84; // To work with US executive format } - $posy = 42; + $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42; + $posy += $top_shift; $posx = $this->page_largeur - $this->marge_droite - $widthrecbox; if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) { $posx = $this->marge_gauche; @@ -761,15 +813,18 @@ class pdf_strato extends ModelePDFContract // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 4, $this->recipient->name, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $this->recipient->name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection); } + + $pdf->SetTextColor(0, 0, 0); + return $top_shift; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore @@ -785,6 +840,6 @@ class pdf_strato extends ModelePDFContract protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0) { $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0); - return pdf_pagefoot($pdf, $outputlangs, 'CONTRACT_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext); + return pdf_pagefoot($pdf, $outputlangs, 'CONTRACT_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark); } } diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 207514ca195..174648dfa8c 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -761,7 +761,8 @@ class pdf_crabe extends ModelePDFFactures $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) { + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if ($object->remise_percent) { @@ -769,7 +770,7 @@ class pdf_crabe extends ModelePDFFactures } if ($object->remise_percent) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; @@ -1232,7 +1233,7 @@ class pdf_crabe extends ModelePDFFactures $bac = new CompanyBankAccount($this->db); $bac->fetch(0, $object->thirdparty->id); $iban= $bac->iban.(($bac->iban && $bac->bic) ? ' / ' : '').$bac->bic; - $lib_mode_reg .= $outputlangs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); + $lib_mode_reg .= ' '.$outputlangs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); } $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L'); diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 98c2e4552bc..312115bb0c1 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -925,7 +925,8 @@ class pdf_sponge extends ModelePDFFactures $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) { + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if ($object->remise_percent) { @@ -933,7 +934,7 @@ class pdf_sponge extends ModelePDFFactures } if ($object->remise_percent) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; @@ -1325,7 +1326,7 @@ class pdf_sponge extends ModelePDFFactures $bac = new CompanyBankAccount($this->db); $bac->fetch(0, $object->thirdparty->id); $iban= $bac->iban.(($bac->iban && $bac->bic) ? ' / ' : '').$bac->bic; - $lib_mode_reg .= $outputlangs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); + $lib_mode_reg .= ' '.$outputlangs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); } $pdf->MultiCell($posxend - $posxval, 5, $lib_mode_reg, 0, 'L'); diff --git a/htdocs/core/modules/facture/mod_facture_mercure.php b/htdocs/core/modules/facture/mod_facture_mercure.php index 36d64132e40..27d84246a2d 100644 --- a/htdocs/core/modules/facture/mod_facture_mercure.php +++ b/htdocs/core/modules/facture/mod_facture_mercure.php @@ -53,7 +53,7 @@ class mod_facture_mercure extends ModeleNumRefFactures */ public function info() { - global $db, $conf, $langs; + global $db, $langs; $langs->load("bills"); @@ -137,35 +137,20 @@ class mod_facture_mercure extends ModeleNumRefFactures */ public function getNextValue($objsoc, $invoice, $mode = 'next') { - global $db, $conf; + global $db; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; // Get Mask value $mask = ''; if (is_object($invoice) && $invoice->type == 1) { - if (isset($conf->global->FACTURE_MERCURE_MASK_REPLACEMENT)) { - $mask = $conf->global->FACTURE_MERCURE_MASK_REPLACEMENT; - } - if (!$mask) { - if (isset($conf->global->FACTURE_MERCURE_MASK_INVOICE)) { - $mask = $conf->global->FACTURE_MERCURE_MASK_INVOICE; - } - } + $mask = getDolGlobalString('FACTURE_MERCURE_MASK_REPLACEMENT', getDolGlobalString('FACTURE_MERCURE_MASK_INVOICE')); } elseif (is_object($invoice) && $invoice->type == 2) { - if (isset($conf->global->FACTURE_MERCURE_MASK_CREDIT)) { - $mask = $conf->global->FACTURE_MERCURE_MASK_CREDIT; - } + $mask = getDolGlobalString('FACTURE_MERCURE_MASK_CREDIT'); } elseif (is_object($invoice) && $invoice->type == 3) { - if (isset($conf->global->FACTURE_MERCURE_MASK_DEPOSIT)) { - $mask = $conf->global->FACTURE_MERCURE_MASK_DEPOSIT; - } + $mask = getDolGlobalString('FACTURE_MERCURE_MASK_DEPOSIT'); } else { - if (isset($conf->global->FACTURE_MERCURE_MASK_INVOICE)) { - $mask = $conf->global->FACTURE_MERCURE_MASK_INVOICE; - } else { - $mask = ''; - } + $mask = getDolGlobalString('FACTURE_MERCURE_MASK_INVOICE'); } if (!$mask) { $this->error = 'NotConfigured'; diff --git a/htdocs/core/modules/mailings/fraise.modules.php b/htdocs/core/modules/mailings/fraise.modules.php index 9fe6a615f5d..8d55ac65864 100644 --- a/htdocs/core/modules/mailings/fraise.modules.php +++ b/htdocs/core/modules/mailings/fraise.modules.php @@ -201,11 +201,11 @@ class mailing_fraise extends MailingTargets $s .= ''; - $s .= '
'; + $s .= '
'; $s .= $langs->trans("DateEndSubscription").':  '; - $s .= $langs->trans("After").' > '.$form->selectDate(-1, 'subscriptionafter', 0, 0, 1, 'fraise', 1, 0, 0); + $s .= $langs->trans("After").' > '.$form->selectDate(-1, 'subscriptionafter', 0, 0, 1, 'fraise', 1, 0, 0); $s .= '   '; - $s .= $langs->trans("Before").' < '.$form->selectDate(-1, 'subscriptionbefore', 0, 0, 1, 'fraise', 1, 0, 0); + $s .= ''.$langs->trans("Before").' < '.$form->selectDate(-1, 'subscriptionbefore', 0, 0, 1, 'fraise', 1, 0, 0); return $s; } diff --git a/htdocs/core/modules/mailings/modules_mailings.php b/htdocs/core/modules/mailings/modules_mailings.php index 2064613d1e9..b745934d94d 100644 --- a/htdocs/core/modules/mailings/modules_mailings.php +++ b/htdocs/core/modules/mailings/modules_mailings.php @@ -48,6 +48,11 @@ class MailingTargets // This can't be abstract as it is used for some method public $tooltip = ''; + /** + * @var string The SQL string used to find the recipients + */ + public $sql; + /** * Constructor diff --git a/htdocs/core/modules/mailings/pomme.modules.php b/htdocs/core/modules/mailings/pomme.modules.php index 7fdcdeb0c60..907028ca881 100644 --- a/htdocs/core/modules/mailings/pomme.modules.php +++ b/htdocs/core/modules/mailings/pomme.modules.php @@ -118,7 +118,7 @@ class mailing_pomme extends MailingTargets $langs->load("users"); $s = ''; - $s .= ''; $s .= ''; $s .= ''; $s .= ''; @@ -126,7 +126,7 @@ class mailing_pomme extends MailingTargets $s .= ajax_combobox("filter_pomme"); $s .= ' '; - $s .= ''; $s .= ''; $s .= ''; $s .= ''; diff --git a/htdocs/core/modules/mailings/thirdparties.modules.php b/htdocs/core/modules/mailings/thirdparties.modules.php index 2f8040d4b75..fd91e5e849f 100644 --- a/htdocs/core/modules/mailings/thirdparties.modules.php +++ b/htdocs/core/modules/mailings/thirdparties.modules.php @@ -73,55 +73,77 @@ class mailing_thirdparties extends MailingTargets $cibles = array(); $addDescription = ""; + $addFilter = ""; + if (GETPOSTISSET("filter_client_thirdparties") && GETPOST("filter_client_thirdparties") <> '-1') { + $addFilter .= " AND s.client=".((int) GETPOST("filter_client_thirdparties", 'int')); + $addDescription = $langs->trans('ProspectCustomer')."="; + if (GETPOST("filter_client_thirdparties") == 0) { + $addDescription .= $langs->trans('NorProspectNorCustomer'); + } elseif (GETPOST("filter_client_thirdparties") == 1) { + $addDescription .= $langs->trans('Customer'); + } elseif (GETPOST("filter_client_thirdparties") == 2) { + $addDescription .= $langs->trans('Prospect'); + } elseif (GETPOST("filter_client_thirdparties") == 3) { + $addDescription .= $langs->trans('ProspectCustomer'); + } else { + $addDescription .= "Unknown status ".GETPOST("filter_client_thirdparties"); + } + } + if (GETPOSTISSET("filter_supplier_thirdparties") && GETPOST("filter_supplier_thirdparties") <> '-1') { + $addFilter .= " AND s.fournisseur = ".((int) GETPOST("filter_supplier_thirdparties", 'int')); + $addDescription = $langs->trans('Supplier')."="; + if (GETPOST("filter_supplier_thirdparties") == 0) { + $addDescription .= $langs->trans('No'); + } elseif (GETPOST("filter_supplier_thirdparties") == 1) { + $addDescription .= $langs->trans('Yes'); + } else { + $addDescription .= "Unknown status ".GETPOST("filter_supplier_thirdparties"); + } + } + if (GETPOSTISSET("filter_status")) { + if (strlen($addDescription) > 0) { + $addDescription .= ";"; + } + $addDescription .= $langs->trans("Status")."="; + if (GETPOST("filter_status") == '1') { + $addFilter .= " AND s.status=1"; + $addDescription .= $langs->trans("Enabled"); + } elseif (GETPOST("filter_status") == '0') { + $addFilter .= " AND s.status=0"; + $addDescription .= $langs->trans("Disabled"); + } + } + if (GETPOSTISSET("filter_status")) { + if (strlen($addDescription) > 0) { + $addDescription .= ";"; + } + $addDescription .= $langs->trans("Status")."="; + if (GETPOST("filter_status") == '1') { + $addFilter .= " AND s.status=1"; + $addDescription .= $langs->trans("Enabled"); + } elseif (GETPOST("filter_status") == '0') { + $addFilter .= " AND s.status=0"; + $addDescription .= $langs->trans("Disabled"); + } + } + if (GETPOST('default_lang', 'alpha')) { + $addFilter .= " AND s.default_lang LIKE '".$this->db->escape(GETPOST('default_lang', 'alpha'))."%'"; + $addDescription = $langs->trans('DefaultLang')."="; + } + if (GETPOST('filter_lang_thirdparties', 'alpha')) { + $addFilter .= " AND s.default_lang LIKE '".$this->db->escape(GETPOST('filter_lang_thirdparties', 'alpha'))."%'"; + $addDescription = $langs->trans('DefaultLang')."="; + } + // Select the third parties from category - if (!GETPOST('filter')) { + if (!GETPOST('filter_thirdparties') || GETPOST('filter_thirdparties') == '-1') { $sql = "SELECT s.rowid as id, s.email as email, s.nom as name, null as fk_contact, null as firstname, null as label"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= " WHERE s.email <> ''"; $sql .= " AND s.entity IN (".getEntity('societe').")"; $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; - if (GETPOST('default_lang', 'alpha')) { - $sql .= " AND s.default_lang LIKE '".$this->db->escape(GETPOST('default_lang', 'alpha'))."%'"; - } + $sql .= $addFilter; } else { - $addFilter = ""; - if (GETPOSTISSET("filter_client") && GETPOST("filter_client") <> '-1') { - $addFilter .= " AND s.client=".((int) GETPOST("filter_client", 'int')); - $addDescription = $langs->trans('ProspectCustomer')."="; - if (GETPOST("filter_client") == 0) { - $addDescription .= $langs->trans('NorProspectNorCustomer'); - } elseif (GETPOST("filter_client") == 1) { - $addDescription .= $langs->trans('Customer'); - } elseif (GETPOST("filter_client") == 2) { - $addDescription .= $langs->trans('Prospect'); - } elseif (GETPOST("filter_client") == 3) { - $addDescription .= $langs->trans('ProspectCustomer'); - } else { - $addDescription .= "Unknown status ".GETPOST("filter_client"); - } - } - if (GETPOSTISSET("filter_status")) { - if (strlen($addDescription) > 0) { - $addDescription .= ";"; - } - $addDescription .= $langs->trans("Status")."="; - if (GETPOST("filter_status") == '1') { - $addFilter .= " AND s.status=1"; - $addDescription .= $langs->trans("Enabled"); - } else { - $addFilter .= " AND s.status=0"; - $addDescription .= $langs->trans("Disabled"); - } - } - if (GETPOST('default_lang', 'alpha')) { - $addFilter .= " AND s.default_lang LIKE '".$this->db->escape(GETPOST('default_lang', 'alpha'))."%'"; - $addDescription = $langs->trans('DefaultLang')."="; - } - if (GETPOST('filter_lang_thirdparties', 'alpha')) { - $addFilter .= " AND s.default_lang LIKE '".$this->db->escape(GETPOST('filter_lang_thirdparties', 'alpha'))."%'"; - $addDescription = $langs->trans('DefaultLang')."="; - } - $sql = "SELECT s.rowid as id, s.email as email, s.nom as name, null as fk_contact, null as firstname, c.label as label"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."categorie_societe as cs, ".MAIN_DB_PREFIX."categorie as c"; $sql .= " WHERE s.email <> ''"; @@ -129,8 +151,8 @@ class mailing_thirdparties extends MailingTargets $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; $sql .= " AND cs.fk_soc = s.rowid"; $sql .= " AND c.rowid = cs.fk_categorie"; - if (GETPOST('filter', 'int') > 0) { - $sql .= " AND c.rowid=".((int) GETPOST('filter', 'int')); + if (GETPOST('filter_thirdparties', 'int') > 0) { + $sql .= " AND c.rowid=".((int) GETPOST('filter_thirdparties', 'int')); } $sql .= $addFilter; $sql .= " UNION "; @@ -141,13 +163,15 @@ class mailing_thirdparties extends MailingTargets $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; $sql .= " AND cs.fk_soc = s.rowid"; $sql .= " AND c.rowid = cs.fk_categorie"; - if (GETPOST('filter', 'int') > 0) { - $sql .= " AND c.rowid=".((int) GETPOST('filter', 'int')); + if (GETPOST('filter_thirdparties', 'int') > 0) { + $sql .= " AND c.rowid=".((int) GETPOST('filter_thirdparties', 'int')); } $sql .= $addFilter; } $sql .= " ORDER BY email"; + //print $sql;exit; + // Stock recipients emails into targets table $result = $this->db->query($sql); if ($result) { @@ -243,7 +267,8 @@ class mailing_thirdparties extends MailingTargets $langs->load("companies"); - $s = ''; // Show categories $sql = "SELECT rowid, label, type, visible"; @@ -293,7 +318,8 @@ class mailing_thirdparties extends MailingTargets $s .= ' '; - $s .= ''; $s .= ''; if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS)) { $s .= ''; @@ -309,6 +335,15 @@ class mailing_thirdparties extends MailingTargets $s .= ' '; $s .= ajax_combobox("filter_client_thirdparties"); + // filter_supplier_thirdparties + $s .= ' '; + $s .= ajax_combobox("filter_supplier_thirdparties"); + + // filter_status_thirdparties $s .= ' '; $s .= ajax_combobox("filter_status_thirdparties"); + // filter_lang_thirdparties if (getDolGlobalInt('MAIN_MULTILANGS')) { // Choose language require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; diff --git a/htdocs/core/modules/modPartnership.class.php b/htdocs/core/modules/modPartnership.class.php index 8e8421540c7..44ef6b527db 100644 --- a/htdocs/core/modules/modPartnership.class.php +++ b/htdocs/core/modules/modPartnership.class.php @@ -212,7 +212,7 @@ class modPartnership extends DolibarrModules // Dictionaries $this->dictionaries=array( - 'langs'=>'partnership@partnership', + 'langs'=>'partnership', // List of tables we want to see into dictonnary editor 'tabname'=>array("c_partnership_type"), // Label of tables @@ -291,7 +291,7 @@ class modPartnership extends DolibarrModules // 'leftmenu'=>'partnership', // 'url'=>'/partnership/partnership_list.php', // // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - // 'langs'=>'partnership@partnership', + // 'langs'=>'partnership', // 'position'=>1100+$r, // // Define condition to show or hide menu entry. Use '$conf->partnership->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. // 'enabled'=>'$conf->partnership->enabled', @@ -349,18 +349,18 @@ class modPartnership extends DolibarrModules $r = 1; /* BEGIN MODULEBUILDER EXPORT PARTNERSHIP */ /* - $langs->load("partnership@partnership"); + $langs->load("partnership"); $this->export_code[$r]=$this->rights_class.'_'.$r; $this->export_label[$r]='PartnershipLines'; // Translation key (used only if key ExportDataset_xxx_z not found) - $this->export_icon[$r]='partnership@partnership'; + $this->export_icon[$r]='partnership'; // Define $this->export_fields_array, $this->export_TypeFields_array and $this->export_entities_array - $keyforclass = 'Partnership'; $keyforclassfile='/partnership/class/partnership.class.php'; $keyforelement='partnership@partnership'; + $keyforclass = 'Partnership'; $keyforclassfile='/partnership/class/partnership.class.php'; $keyforelement='partnership'; include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; //$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text'; //unset($this->export_fields_array[$r]['t.fieldtoremove']); //$keyforclass = 'PartnershipLine'; $keyforclassfile='/partnership/class/partnership.class.php'; $keyforelement='partnershipline@partnership'; $keyforalias='tl'; //include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; - $keyforselect='partnership'; $keyforaliasextra='extra'; $keyforelement='partnership@partnership'; + $keyforselect='partnership'; $keyforaliasextra='extra'; $keyforelement='partnership'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; //$keyforselect='partnershipline'; $keyforaliasextra='extraline'; $keyforelement='partnershipline@partnership'; //include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; @@ -380,13 +380,13 @@ class modPartnership extends DolibarrModules $r = 1; /* BEGIN MODULEBUILDER IMPORT PARTNERSHIP */ /* - $langs->load("partnership@partnership"); + $langs->load("partnership"); $this->export_code[$r]=$this->rights_class.'_'.$r; $this->export_label[$r]='PartnershipLines'; // Translation key (used only if key ExportDataset_xxx_z not found) - $this->export_icon[$r]='partnership@partnership'; - $keyforclass = 'Partnership'; $keyforclassfile='/partnership/class/partnership.class.php'; $keyforelement='partnership@partnership'; + $this->export_icon[$r]='partnership'; + $keyforclass = 'Partnership'; $keyforclassfile='/partnership/class/partnership.class.php'; $keyforelement='partnership'; include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; - $keyforselect='partnership'; $keyforaliasextra='extra'; $keyforelement='partnership@partnership'; + $keyforselect='partnership'; $keyforaliasextra='extra'; $keyforelement='partnership'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; //$this->export_dependencies_array[$r]=array('mysubobject'=>'ts.rowid', 't.myfield'=>array('t.myfield2','t.myfield3')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) $this->export_sql_start[$r]='SELECT DISTINCT '; @@ -417,11 +417,11 @@ class modPartnership extends DolibarrModules // Create extrafields during init //include_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; //$extrafields = new ExtraFields($this->db); - //$result1=$extrafields->addExtraField('partnership_myattr1', "New Attr 1 label", 'boolean', 1, 3, 'thirdparty', 0, 0, '', '', 1, '', 0, 0, '', '', 'partnership@partnership', '$conf->partnership->enabled'); - //$result2=$extrafields->addExtraField('partnership_myattr2', "New Attr 2 label", 'varchar', 1, 10, 'project', 0, 0, '', '', 1, '', 0, 0, '', '', 'partnership@partnership', '$conf->partnership->enabled'); - //$result3=$extrafields->addExtraField('partnership_myattr3', "New Attr 3 label", 'varchar', 1, 10, 'bank_account', 0, 0, '', '', 1, '', 0, 0, '', '', 'partnership@partnership', '$conf->partnership->enabled'); - //$result4=$extrafields->addExtraField('partnership_myattr4', "New Attr 4 label", 'select', 1, 3, 'thirdparty', 0, 1, '', array('options'=>array('code1'=>'Val1','code2'=>'Val2','code3'=>'Val3')), 1,'', 0, 0, '', '', 'partnership@partnership', '$conf->partnership->enabled'); - //$result5=$extrafields->addExtraField('partnership_myattr5', "New Attr 5 label", 'text', 1, 10, 'user', 0, 0, '', '', 1, '', 0, 0, '', '', 'partnership@partnership', '$conf->partnership->enabled'); + //$result1=$extrafields->addExtraField('partnership_myattr1', "New Attr 1 label", 'boolean', 1, 3, 'thirdparty', 0, 0, '', '', 1, '', 0, 0, '', '', 'partnership', '$conf->partnership->enabled'); + //$result2=$extrafields->addExtraField('partnership_myattr2', "New Attr 2 label", 'varchar', 1, 10, 'project', 0, 0, '', '', 1, '', 0, 0, '', '', 'partnership', '$conf->partnership->enabled'); + //$result3=$extrafields->addExtraField('partnership_myattr3', "New Attr 3 label", 'varchar', 1, 10, 'bank_account', 0, 0, '', '', 1, '', 0, 0, '', '', 'partnership', '$conf->partnership->enabled'); + //$result4=$extrafields->addExtraField('partnership_myattr4', "New Attr 4 label", 'select', 1, 3, 'thirdparty', 0, 1, '', array('options'=>array('code1'=>'Val1','code2'=>'Val2','code3'=>'Val3')), 1,'', 0, 0, '', '', 'partnership', '$conf->partnership->enabled'); + //$result5=$extrafields->addExtraField('partnership_myattr5', "New Attr 5 label", 'text', 1, 10, 'user', 0, 0, '', '', 1, '', 0, 0, '', '', 'partnership', '$conf->partnership->enabled'); // Permissions $this->remove($options); diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index 16906c95f86..96fdb779b0b 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -104,7 +104,7 @@ class modProduct extends DolibarrModules // Boxes $this->boxes = array( 0=>array('file'=>'box_produits.php', 'enabledbydefaulton'=>'Home'), - 1=>array('file'=>'box_produits_alerte_stock.php', 'enabledbydefaulton'=>''), + 1=>array('file'=>'box_produits_alerte_stock.php', 'enabledbydefaulton'=>'Home'), 2=>array('file'=>'box_graph_product_distribution.php', 'enabledbydefaulton'=>'Home') ); diff --git a/htdocs/core/modules/modStripe.class.php b/htdocs/core/modules/modStripe.class.php index 4c5d3deea44..e691e8e3b29 100644 --- a/htdocs/core/modules/modStripe.class.php +++ b/htdocs/core/modules/modStripe.class.php @@ -118,7 +118,7 @@ class modStripe extends DolibarrModules 'url' => '', 'langs' => 'stripe', 'position' => 100, - 'enabled' => '$conf->stripe->enabled && $conf->banque->enabled && $conf->global->MAIN_FEATURES_LEVEL >= 1', + 'enabled' => 'isModEnabled("stripe") && isModenabled("banque")', 'perms' => '$user->rights->banque->lire', 'target' => '', 'user' => 0 @@ -132,7 +132,7 @@ class modStripe extends DolibarrModules 'url' => '/stripe/charge.php', 'langs' => 'stripe', 'position' => 102, - 'enabled' => '$conf->stripe->enabled && $conf->banque->enabled && $conf->global->MAIN_FEATURES_LEVEL >= 1', + 'enabled' => 'isModEnabled("stripe") && isModenabled("banque") && getDolGlobalInt("MAIN_FEATURES_LEVEL") >= 1', 'perms' => '$user->rights->banque->lire', 'target' => '', 'user' => 0 @@ -146,7 +146,7 @@ class modStripe extends DolibarrModules 'url' => '/stripe/transaction.php', 'langs' => 'stripe', 'position' => 102, - 'enabled' => '$conf->stripe->enabled && $conf->banque->enabled && $conf->global->MAIN_FEATURES_LEVEL >= 1', + 'enabled' => 'isModEnabled("stripe") && isModenabled("banque") && getDolGlobalInt("MAIN_FEATURES_LEVEL") >= 2', 'perms' => '$user->rights->banque->lire', 'target' => '', 'user' => 0 @@ -160,7 +160,7 @@ class modStripe extends DolibarrModules 'url' => '/stripe/payout.php', 'langs' => 'stripe', 'position' => 103, - 'enabled' => '$conf->stripe->enabled && $conf->banque->enabled && $conf->global->MAIN_FEATURES_LEVEL >= 1', + 'enabled' => 'isModEnabled("stripe") && isModenabled("banque")', 'perms' => '$user->rights->banque->lire', 'target' => '', 'user' => 0 diff --git a/htdocs/core/modules/payment/mod_payment_ant.php b/htdocs/core/modules/payment/mod_payment_ant.php index 03a6109bd67..6125053cbb4 100644 --- a/htdocs/core/modules/payment/mod_payment_ant.php +++ b/htdocs/core/modules/payment/mod_payment_ant.php @@ -61,7 +61,7 @@ class mod_payment_ant extends ModeleNumRefPayments */ public function info() { - global $db, $conf, $langs; + global $db, $langs; $langs->load("bills"); @@ -82,7 +82,7 @@ class mod_payment_ant extends ModeleNumRefPayments // Parametrage du prefix $texte .= ''.$langs->trans("Mask").':'; - $texte .= ''.$form->textwithpicto('', $tooltip, 1, 1).''; + $texte .= ''.$form->textwithpicto('', $tooltip, 1, 1).''; $texte .= '  '; @@ -128,7 +128,7 @@ class mod_payment_ant extends ModeleNumRefPayments require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; // We get cursor rule - $mask = $conf->global->PAYMENT_ANT_MASK; + $mask = getDolGlobalString('PAYMENT_ANT_MASK'); if (!$mask) { $this->error = 'NotConfigured'; diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index d1a64bcf039..8a35edc7968 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -117,13 +117,16 @@ class doc_generic_proposal_odt extends ModelePDFPropales $form = new Form($this->db); + $odtChosen = getDolGlobalInt('MAIN_PROPAL_CHOOSE_ODT_DOCUMENT') > 0; + $odtPath = trim(getDolGlobalString('PROPALE_ADDON_PDF_ODT_PATH')); + $texte = $this->description.".
\n"; $texte .= '
'; $texte .= ''; $texte .= ''; $texte .= ''; $texte .= ''; - if (getDolGlobalInt("MAIN_PROPAL_CHOOSE_ODT_DOCUMENT") > 0) { + if ($odtChosen) { $texte .= ''; $texte .= ''; $texte .= ''; @@ -133,7 +136,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales // List of directories area $texte .= ''; $texttitle = $langs->trans("ListOfDirectories"); - $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->PROPALE_ADDON_PDF_ODT_PATH))); + $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', $odtPath)); $listoffiles = array(); foreach ($listofdir as $key => $tmpdir) { $tmpdir = trim($tmpdir); @@ -159,7 +162,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1); $texte .= '
'; $texte .= ''; $texte .= '
'; $texte .= ''; @@ -167,7 +170,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales // Scan directories $nbofiles = count($listoffiles); - if (!empty($conf->global->PROPALE_ADDON_PDF_ODT_PATH)) { + if (!empty($odtPath)) { $texte .= $langs->trans("NumberOfModelFilesFound").': '; //$texte.=$nbofiles?'':''; $texte .= count($listoffiles); @@ -187,26 +190,26 @@ class doc_generic_proposal_odt extends ModelePDFPropales $texte .= '
'; // Set default template for different status of proposal - if (getDolGlobalInt("MAIN_PROPAL_CHOOSE_ODT_DOCUMENT") > 0) { + if ($odtChosen) { // Model for creation $list = ModelePDFPropales::liste_modeles($this->db); $texte .= ''; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= '
'.$langs->trans("DefaultModelPropalCreate").''; - $texte .= $form->selectarray('value2', $list, $conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT); + $texte .= $form->selectarray('value2', $list, getDolGlobalString('PROPALE_ADDON_PDF_ODT_DEFAULT')); $texte .= "
'.$langs->trans("DefaultModelPropalToBill").''; - $texte .= $form->selectarray('value3', $list, $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL); + $texte .= $form->selectarray('value3', $list, getDolGlobalString('PROPALE_ADDON_PDF_ODT_TOBILL')); $texte .= "
'.$langs->trans("DefaultModelPropalClosed").''; - $texte .= $form->selectarray('value4', $list, $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED); + $texte .= $form->selectarray('value4', $list, getDolGlobalString('PROPALE_ADDON_PDF_ODT_CLOSED')); $texte .= "
'; } diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index d3117e526f8..a46bd5f108c 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -653,7 +653,8 @@ class pdf_azur extends ModelePDFPropales $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) { + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if ($object->remise_percent) { @@ -661,7 +662,7 @@ class pdf_azur extends ModelePDFPropales } if ($object->remise_percent) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index ddc4e60ad4c..b8ef09f04ba 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -777,7 +777,8 @@ class pdf_cyan extends ModelePDFPropales $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) { + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if ($object->remise_percent) { @@ -785,7 +786,7 @@ class pdf_cyan extends ModelePDFPropales } if ($object->remise_percent) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php b/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php index 23feb4bfca6..c705e4c9b41 100644 --- a/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php +++ b/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php @@ -694,9 +694,10 @@ class pdf_eagle_proforma extends ModelePDFCommandes $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) $tvaligne -= ($tvaligne * $object->remise_percent) / 100; + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) $tvaligne -= ($tvaligne * $object->remise_percent) / 100; if ($object->remise_percent) $localtax1ligne -= ($localtax1ligne * $object->remise_percent) / 100; - if ($object->remise_percent) $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; + if ($object->remise_percent) $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100;*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php b/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php index d1b8331ea5d..e1cd6c8e5e6 100644 --- a/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php +++ b/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php @@ -508,9 +508,10 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $localtax1ligne = $object->lines[$i]->total_localtax1; $localtax2ligne = $object->lines[$i]->total_localtax2; - if (!empty($object->remise_percent)) { + // TODO remise_percent is an obsolete field for object parent + /*if (!empty($object->remise_percent)) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; $localtax1rate = (string) $object->lines[$i]->localtax1_tx; diff --git a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php index 43bfae86af3..92bd19f52f4 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php @@ -706,7 +706,8 @@ class pdf_cornas extends ModelePDFSuppliersOrders $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if (!empty($object->remise_percent)) { + // TODO remise_percent is an obsolete field for object parent + /*if (!empty($object->remise_percent)) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if (!empty($object->remise_percent)) { @@ -714,7 +715,7 @@ class pdf_cornas extends ModelePDFSuppliersOrders } if (!empty($object->remise_percent)) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php index cecd9737cdf..ba4dcd4c2ae 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php @@ -586,7 +586,8 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if (!empty($object->remise_percent)) { + // TODO remise_percent is an obsolete field for object parent + /*if (!empty($object->remise_percent)) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if (!empty($object->remise_percent)) { @@ -594,7 +595,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders } if (!empty($object->remise_percent)) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php b/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php index 116b6daf9be..6a8ecbc28c6 100644 --- a/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php @@ -117,13 +117,16 @@ class doc_generic_supplier_proposal_odt extends ModelePDFSupplierProposal $form = new Form($this->db); + $odtChosen = getDolGlobalInt('MAIN_SUPPLIER_PROPOSAL_CHOOSE_ODT_DOCUMENT') > 0; + $odtPath = trim(getDolGlobalString('SUPPLIER_PROPOSAL_ADDON_PDF_ODT_PATH')); + $texte = $this->description.".
\n"; $texte .= ''; $texte .= ''; $texte .= ''; $texte .= ''; $texte .= ''; - if ($conf->global->MAIN_SUPPLIER_PROPOSAL_CHOOSE_ODT_DOCUMENT > 0) { + if ($odtChosen) { $texte .= ''; $texte .= ''; $texte .= ''; @@ -133,7 +136,7 @@ class doc_generic_supplier_proposal_odt extends ModelePDFSupplierProposal // List of directories area $texte .= ''; $texttitle = $langs->trans("ListOfDirectories"); - $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_PATH))); + $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', $odtPath)); $listoffiles = array(); foreach ($listofdir as $key => $tmpdir) { $tmpdir = trim($tmpdir); @@ -159,7 +162,7 @@ class doc_generic_supplier_proposal_odt extends ModelePDFSupplierProposal $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1); $texte .= '
'; $texte .= ''; $texte .= '
'; - if ($conf->global->MAIN_SUPPLIER_PROPOSAL_CHOOSE_ODT_DOCUMENT > 0) { + if ($odtChosen) { // Model for creation $list = ModelePDFSupplierProposal::liste_modeles($this->db); $texte .= ''; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= '
'.$langs->trans("DefaultModelSupplierProposalCreate").''; - $texte .= $form->selectarray('value2', $list, $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_DEFAULT); + $texte .= $form->selectarray('value2', $list, getDolGlobalString('SUPPLIER_PROPOSAL_ADDON_PDF_ODT_DEFAULT')); $texte .= "
'.$langs->trans("DefaultModelSupplierProposalToBill").''; - $texte .= $form->selectarray('value3', $list, $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL); + $texte .= $form->selectarray('value3', $list, getDolGlobalString('SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL')); $texte .= "
'.$langs->trans("DefaultModelSupplierProposalClosed").''; - $texte .= $form->selectarray('value4', $list, $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED); + $texte .= $form->selectarray('value4', $list, getDolGlobalString('SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED')); $texte .= "
'; } diff --git a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php index 0efa9cc63be..162575f8850 100644 --- a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php @@ -563,7 +563,8 @@ class pdf_aurore extends ModelePDFSupplierProposal $localtax1_type = $object->lines[$i]->localtax1_type; $localtax2_type = $object->lines[$i]->localtax2_type; - if ($object->remise_percent) { + // TODO remise_percent is an obsolete field for object parent + /*if ($object->remise_percent) { $tvaligne -= ($tvaligne * $object->remise_percent) / 100; } if ($object->remise_percent) { @@ -571,7 +572,7 @@ class pdf_aurore extends ModelePDFSupplierProposal } if ($object->remise_percent) { $localtax2ligne -= ($localtax2ligne * $object->remise_percent) / 100; - } + }*/ $vatrate = (string) $object->lines[$i]->tva_tx; diff --git a/htdocs/core/modules/supplier_proposal/mod_supplier_proposal_saphir.php b/htdocs/core/modules/supplier_proposal/mod_supplier_proposal_saphir.php index d4282eb80ec..063591e5486 100644 --- a/htdocs/core/modules/supplier_proposal/mod_supplier_proposal_saphir.php +++ b/htdocs/core/modules/supplier_proposal/mod_supplier_proposal_saphir.php @@ -64,7 +64,7 @@ class mod_supplier_proposal_saphir extends ModeleNumRefSupplierProposal */ public function info() { - global $conf, $langs, $db; + global $langs, $db; $langs->load("bills"); @@ -83,9 +83,11 @@ class mod_supplier_proposal_saphir extends ModeleNumRefSupplierProposal $tooltip .= $langs->trans("GenericMaskCodes4a", $langs->transnoentities("CommRequest"), $langs->transnoentities("CommRequest")); $tooltip .= $langs->trans("GenericMaskCodes5"); + $mask = dolGetGlobalString('SUPPLIER_PROPOSAL_SAPHIR_MASK'); + // Parametrage du prefix $texte .= ''.$langs->trans("Mask").':'; - $texte .= ''.$form->textwithpicto('', $tooltip, 1, 1).''; + $texte .= ''.$form->textwithpicto('', $tooltip, 1, 1).''; $texte .= '  '; @@ -131,7 +133,7 @@ class mod_supplier_proposal_saphir extends ModeleNumRefSupplierProposal require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; // On defini critere recherche compteur - $mask = $conf->global->SUPPLIER_PROPOSAL_SAPHIR_MASK; + $mask = empty($conf->global->SUPPLIER_PROPOSAL_SAPHIR_MASK) ? '' : $conf->global->SUPPLIER_PROPOSAL_SAPHIR_MASK; if (!$mask) { $this->error = 'NotConfigured'; diff --git a/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php b/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php index e8a15b8f09a..81328821261 100644 --- a/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php +++ b/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php @@ -114,13 +114,16 @@ class doc_generic_user_odt extends ModelePDFUser $form = new Form($this->db); + $odtChosen = getDolGlobalInt('MAIN_PROPAL_CHOOSE_ODT_DOCUMENT') > 0; + $odtPath = trim(getDolGlobalString('USER_ADDON_PDF_ODT_PATH')); + $texte = $this->description.".
\n"; $texte .= ''; $texte .= ''; $texte .= ''; $texte .= ''; $texte .= ''; - if (!empty($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT)) { + if ($odtChosen) { $texte .= ''; $texte .= ''; $texte .= ''; @@ -130,7 +133,7 @@ class doc_generic_user_odt extends ModelePDFUser // List of directories area $texte .= ''; $texttitle = $langs->trans("ListOfDirectories"); - $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->USER_ADDON_PDF_ODT_PATH))); + $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', $odtPath)); $listoffiles = array(); foreach ($listofdir as $key => $tmpdir) { $tmpdir = trim($tmpdir); @@ -156,7 +159,7 @@ class doc_generic_user_odt extends ModelePDFUser $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1); $texte .= '
'; $texte .= ''; $texte .= '
'; $texte .= ''; @@ -166,26 +169,26 @@ class doc_generic_user_odt extends ModelePDFUser if (count($listofdir)) { $texte .= $langs->trans("NumberOfModelFilesFound").': '.count($listoffiles).''; - if (!empty($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT)) { + if ($odtChosen) { // Model for creation $list = ModelePDFUser::liste_modeles($this->db); $texte .= ''; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= '
'.$langs->trans("DefaultModelPropalCreate").''; - $texte .= $form->selectarray('value2', $list, $conf->global->USER_ADDON_PDF_ODT_DEFAULT); + $texte .= $form->selectarray('value2', $list, getDolGlobalString('USER_ADDON_PDF_ODT_DEFAULT')); $texte .= "
'.$langs->trans("DefaultModelPropalToBill").''; - $texte .= $form->selectarray('value3', $list, $conf->global->USER_ADDON_PDF_ODT_TOBILL); + $texte .= $form->selectarray('value3', $list, getDolGlobalString('USER_ADDON_PDF_ODT_TOBILL')); $texte .= "
'.$langs->trans("DefaultModelPropalClosed").''; - $texte .= $form->selectarray('value4', $list, $conf->global->USER_ADDON_PDF_ODT_CLOSED); + $texte .= $form->selectarray('value4', $list, getDolGlobalString('USER_ADDON_PDF_ODT_CLOSED')); $texte .= "
'; } diff --git a/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php b/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php index 5700870444f..5ff9d4c8526 100644 --- a/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php +++ b/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php @@ -117,13 +117,16 @@ class doc_generic_usergroup_odt extends ModelePDFUserGroup $form = new Form($this->db); + $odtChosen = getDolGlobalInt('MAIN_PROPAL_CHOOSE_ODT_DOCUMENT') > 0; + $odtPath = trim(getDolGlobalString('USERGROUP_ADDON_PDF_ODT_PATH')); + $texte = $this->description.".
\n"; $texte .= ''; $texte .= ''; $texte .= ''; $texte .= ''; $texte .= ''; - if (!empty($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT)) { + if ($odtChosen) { $texte .= ''; $texte .= ''; $texte .= ''; @@ -133,7 +136,7 @@ class doc_generic_usergroup_odt extends ModelePDFUserGroup // List of directories area $texte .= ''; $texttitle = $langs->trans("ListOfDirectories"); - $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->USERGROUP_ADDON_PDF_ODT_PATH))); + $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', $odtPath)); $listoffiles = array(); foreach ($listofdir as $key => $tmpdir) { $tmpdir = trim($tmpdir); @@ -159,7 +162,7 @@ class doc_generic_usergroup_odt extends ModelePDFUserGroup $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1); $texte .= '
'; $texte .= ''; $texte .= '
'; $texte .= ''; @@ -169,26 +172,26 @@ class doc_generic_usergroup_odt extends ModelePDFUserGroup if (count($listofdir)) { $texte .= $langs->trans("NumberOfModelFilesFound").': '.count($listoffiles).''; - if (!empty($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT)) { + if ($odtChosen) { // Model for creation $list = ModelePDFUserGroup::liste_modeles($this->db); $texte .= ''; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= ''; $texte .= ''; $texte .= '"; $texte .= '
'.$langs->trans("DefaultModelPropalCreate").''; - $texte .= $form->selectarray('value2', $list, $conf->global->USERGROUP_ADDON_PDF_ODT_DEFAULT); + $texte .= $form->selectarray('value2', $list, getDolGlobalString('USERGROUP_ADDON_PDF_ODT_DEFAULT')); $texte .= "
'.$langs->trans("DefaultModelPropalToBill").''; - $texte .= $form->selectarray('value3', $list, $conf->global->USERGROUP_ADDON_PDF_ODT_TOBILL); + $texte .= $form->selectarray('value3', $list, getDolGlobalString('USERGROUP_ADDON_PDF_ODT_TOBILL')); $texte .= "
'.$langs->trans("DefaultModelPropalClosed").''; - $texte .= $form->selectarray('value4', $list, $conf->global->USERGROUP_ADDON_PDF_ODT_CLOSED); + $texte .= $form->selectarray('value4', $list, getDolGlobalString('USERGROUP_ADDON_PDF_ODT_CLOSED')); $texte .= "
'; } diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 6bf4807ea6f..84febb58e4e 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -328,7 +328,7 @@ if ($action == 'presend') { } $contactarr = array(); - $contactarr = $tmpobject->liste_contact(-1, 'external'); + $contactarr = $tmpobject->liste_contact(-1, 'external', 0, '', 1); if (is_array($contactarr) && count($contactarr) > 0) { require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php index a87754f9883..a1045beedb9 100644 --- a/htdocs/core/tpl/login.tpl.php +++ b/htdocs/core/tpl/login.tpl.php @@ -134,10 +134,12 @@ $(document).ready(function () {
'; diff --git a/htdocs/don/class/paymentdonation.class.php b/htdocs/don/class/paymentdonation.class.php index 657a1d32d1a..1aceca10c16 100644 --- a/htdocs/don/class/paymentdonation.class.php +++ b/htdocs/don/class/paymentdonation.class.php @@ -92,6 +92,10 @@ class PaymentDonation extends CommonObject public $type_code; public $type_label; + public $chid; + public $datepaid; + public $bank_account; + public $bank_line; /** * @var string Id of external payment mode diff --git a/htdocs/don/index.php b/htdocs/don/index.php index c402ecd6f0e..c9075791663 100644 --- a/htdocs/don/index.php +++ b/htdocs/don/index.php @@ -104,7 +104,7 @@ if (!empty($conf->global->MAIN_SEARCH_FORM_ON_HOME_AREAS)) { // TODO Add a s if ($i == 0) { print ''.$langs->trans("Search").''; } - print ''; + print ''; print ''; if ($i == 0) { print ''; diff --git a/htdocs/don/list.php b/htdocs/don/list.php index a895db4f3a6..320c1616d22 100644 --- a/htdocs/don/list.php +++ b/htdocs/don/list.php @@ -289,7 +289,8 @@ if ($resql) { } print "\n"; - while ($i < min($num, $limit)) { + $imaxinloop = ($limit ? min($num, $limit) : $num); + while ($i < $imaxinloop) { $objp = $db->fetch_object($resql); $donationstatic->setVarsFromFetchObj($objp); $company = new Societe($db); @@ -314,7 +315,7 @@ if ($resql) { } print $donationstatic->getKanbanView(''); - if ($i == (min($num, $limit) - 1)) { + if ($i == ($imaxinloop - 1)) { print '
'; print ''; } diff --git a/htdocs/ecm/dir_add_card.php b/htdocs/ecm/dir_add_card.php index acdc6c2990a..5de525e17ea 100644 --- a/htdocs/ecm/dir_add_card.php +++ b/htdocs/ecm/dir_add_card.php @@ -94,13 +94,16 @@ if (!empty($section)) { // Permissions $permissiontoadd = 0; +$permissiontodelete = 0; $permissiontoupload = 0; if ($module == 'ecm') { $permissiontoadd = $user->rights->ecm->setup; + $permissiontodelete = $user->rights->ecm->setup; $permissiontoupload = $user->rights->ecm->upload; } if ($module == 'medias') { $permissiontoadd = ($user->rights->mailing->creer || $user->rights->website->write); + $permissiontodelete = ($user->rights->mailing->creer || $user->rights->website->write); $permissiontoupload = ($user->rights->mailing->creer || $user->rights->website->write); } @@ -189,7 +192,7 @@ if ($action == 'add' && $permissiontoadd) { exit; } } -} elseif ($action == 'confirm_deletesection' && $confirm == 'yes' && $permissiontoadd) { +} elseif ($action == 'confirm_deletesection' && $confirm == 'yes' && $permissiontodelete) { // Deleting file $result = $ecmdir->delete($user); setEventMessages($langs->trans("ECMSectionWasRemoved", $ecmdir->label), null, 'mesgs'); @@ -231,7 +234,8 @@ if ($action == 'create') { print ''; // Label - print ''."\n"; + print ''."\n"; print ''; foreach ($object->fields as $key => $val) { diff --git a/htdocs/eventorganization/core/actions_massactions_mail.inc.php b/htdocs/eventorganization/core/actions_massactions_mail.inc.php index 5398291e69f..2e03777c572 100644 --- a/htdocs/eventorganization/core/actions_massactions_mail.inc.php +++ b/htdocs/eventorganization/core/actions_massactions_mail.inc.php @@ -191,7 +191,6 @@ if (!$error && $massaction == 'confirm_presend_attendees') { } $substitutionarray['__EVENTORGANIZATION_ICS_LINK__'] = $html_link; $substitutionarray['__EVENTORGANIZATION_URL_LINK__'] = $url_link; - $substitutionarray['__CHECK_READ__'] = ''; $parameters = array('mode' => 'formemail'); diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index aac19c7da76..9b565954c1b 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -944,7 +944,7 @@ if ($action == 'create') { $langs->load("projects"); print ''; print ''; @@ -954,6 +954,7 @@ if ($action == 'create') { // Date delivery planned print ''; print '\n"; @@ -978,7 +979,9 @@ if ($action == 'create') { // Weight print '"; print '"; print '\n"; @@ -1030,6 +1037,7 @@ if ($action == 'create') { print ''; print ''; print ''; } @@ -1040,6 +1048,7 @@ if ($action == 'create') { if (count($list) > 1) { print ""; print '\n"; } diff --git a/htdocs/expedition/class/api_shipments.class.php b/htdocs/expedition/class/api_shipments.class.php index 6a753a24cdb..d2f9da404e4 100644 --- a/htdocs/expedition/class/api_shipments.class.php +++ b/htdocs/expedition/class/api_shipments.class.php @@ -145,11 +145,10 @@ class Shipments extends DolibarrApi // Add sql filters if ($sqlfilters) { $errormessage = ''; - if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); + if ($errormessage) { + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/expedition/list.php b/htdocs/expedition/list.php index b13db1c159b..5b109c8b29d 100644 --- a/htdocs/expedition/list.php +++ b/htdocs/expedition/list.php @@ -5,6 +5,7 @@ * Copyright (C) 2016-2021 Ferran Marcet * Copyright (C) 2019 Nicolas ZABOURI * Copyright (C) 2020 Thibault FOUCART + * Copyright (C) 2023 Christophe Battarel * * 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 @@ -72,7 +73,6 @@ $search_datedelivery_end = dol_mktime(23, 59, 59, GETPOST('search_datedelivery_e $search_datereceipt_start = dol_mktime(0, 0, 0, GETPOST('search_datereceipt_startmonth', 'int'), GETPOST('search_datereceipt_startday', 'int'), GETPOST('search_datereceipt_startyear', 'int')); $search_datereceipt_end = dol_mktime(23, 59, 59, GETPOST('search_datereceipt_endmonth', 'int'), GETPOST('search_datereceipt_endday', 'int'), GETPOST('search_datereceipt_endyear', 'int')); $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); -$socid = GETPOST('socid', 'int'); $search_user = GETPOST('search_user', 'int'); $search_sale = GETPOST('search_sale', 'int'); $search_categ_cus = GETPOST("search_categ_cus", 'int'); diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index c61249877a3..325559882d8 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -517,7 +517,7 @@ if ($id > 0 || !empty($ref)) { print '
'.$langs->trans("Label").'label).'" autofocus>
'.$langs->trans("Label").''; + print '
'.$langs->trans("AddIn").''; print $formecm->selectAllSections((GETPOST("catParent", 'alpha') ? GETPOST("catParent", 'alpha') : $ecmdir->fk_parent), 'catParent', $module); diff --git a/htdocs/ecm/index.php b/htdocs/ecm/index.php index 6edf59dcbed..6f4b9577c92 100644 --- a/htdocs/ecm/index.php +++ b/htdocs/ecm/index.php @@ -83,6 +83,12 @@ if ($user->socid) { } $result = restrictedArea($user, 'ecm', 0); +$permissiontoread = $user->hasRight('ecm', 'read'); +$permissiontocreate = $user->hasRight('ecm', 'upload'); +$permissiontocreatedir = $user->hasRight('ecm', 'setup'); +$permissiontodelete = $user->hasRight('ecm', 'upload'); +$permissiontodeletedir = $user->hasRight('ecm', 'setup'); + /* * Actions @@ -93,7 +99,7 @@ $result = restrictedArea($user, 'ecm', 0); //include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; // Upload file (code similar but different than actions_linkedfiles.inc.php) -if (GETPOST("sendit", 'alphanohtml') && !empty($conf->global->MAIN_UPLOAD_DOC)) { +if (GETPOST("sendit", 'alphanohtml') && !empty($conf->global->MAIN_UPLOAD_DOC) && $permissiontocreate) { // Define relativepath and upload_dir $relativepath = ''; if ($ecmdir->id) { @@ -130,7 +136,7 @@ if (GETPOST("sendit", 'alphanohtml') && !empty($conf->global->MAIN_UPLOAD_DOC)) } // Remove file (code similar but different than actions_linkedfiles.inc.php) -if ($action == 'confirm_deletefile') { +if ($action == 'confirm_deletefile' && $permissiontodelete) { if (GETPOST('confirm') == 'yes') { // GETPOST('urlfile','alpha') is full relative URL from ecm root dir. Contains path of all sections. @@ -152,7 +158,7 @@ if ($action == 'confirm_deletefile') { } // Add directory -if ($action == 'add' && $user->rights->ecm->setup) { +if ($action == 'add' && $permissiontocreatedir) { $ecmdir->ref = 'NOTUSEDYET'; $ecmdir->label = GETPOST("label"); $ecmdir->description = GETPOST("desc"); @@ -170,7 +176,7 @@ if ($action == 'add' && $user->rights->ecm->setup) { } // Remove directory -if ($action == 'confirm_deletesection' && GETPOST('confirm', 'alpha') == 'yes') { +if ($action == 'confirm_deletesection' && GETPOST('confirm', 'alpha') == 'yes' && $permissiontodeletedir) { $result = $ecmdir->delete($user); setEventMessages($langs->trans("ECMSectionWasRemoved", $ecmdir->label), null, 'mesgs'); @@ -180,7 +186,7 @@ if ($action == 'confirm_deletesection' && GETPOST('confirm', 'alpha') == 'yes') // Refresh directory view // This refresh list of dirs, not list of files (for preformance reason). List of files is refresh only if dir was not synchronized. // To refresh content of dir with cache, just open the dir in edit mode. -if ($action == 'refreshmanual') { +if ($action == 'refreshmanual' && $permissiontoread) { $ecmdirtmp = new EcmDirectory($db); // This part of code is same than into file ecm/ajax/ecmdatabase.php TODO Remove duplicate diff --git a/htdocs/ecm/index_auto.php b/htdocs/ecm/index_auto.php index 3944e869da0..ae641047b30 100644 --- a/htdocs/ecm/index_auto.php +++ b/htdocs/ecm/index_auto.php @@ -34,12 +34,6 @@ require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php'; // Load translation files required by the page $langs->loadLangs(array("ecm", "companies", "other", "users", "orders", "propal", "bills", "contracts")); -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'ecm', 0); - // Get parameters $socid = GETPOST('socid', 'int'); $action = GETPOST('action', 'aZ09'); @@ -87,6 +81,12 @@ $userstatic = new User($db); $error = 0; +// Security check +if ($user->socid) { + $socid = $user->socid; +} +$result = restrictedArea($user, 'ecm', 0); + /* * Actions diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 303749a16ea..108d0460193 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -44,9 +44,6 @@ require_once DOL_DOCUMENT_ROOT .'/ticket/class/ticket.class.php'; //require_once DOL_DOCUMENT_ROOT .'/holiday/class/holiday.class.php'; // Holidays (leave request) -// use Webklex\PHPIMAP; -require DOL_DOCUMENT_ROOT .'/includes/webklex/php-imap/vendor/autoload.php'; - use Webklex\PHPIMAP\ClientManager; use Webklex\PHPIMAP\Exceptions\ConnectionFailedException; use Webklex\PHPIMAP\Exceptions\InvalidWhereQueryCriteriaException; @@ -1040,6 +1037,9 @@ class EmailCollector extends CommonObject //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { + require_once DOL_DOCUMENT_ROOT.'/includes/webklex/php-imap/vendor/autoload.php'; + } dol_syslog("EmailCollector::doCollectOneCollector start for id=".$this->id." - ".$this->ref, LOG_DEBUG); diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index 9da7aa06a84..658aa8d5bb5 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -106,8 +106,8 @@ class ConferenceOrBooth extends ActionComm 'id' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), 'ref' => array('type'=>'integer', 'label'=>'Ref', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>2, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'csslist'=>'left', 'comment'=>"Id"), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax125', 'help'=>"OrganizationEvenLabelName", 'showoncombobox'=>'1', 'autofocusoncreate'=>1), - 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:t.usage_organize_event=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'position'=>52, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'picto'=>'project', 'css'=>'tdoverflowmax150 maxwidth500', 'csslist'=>'width100'), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'csslist'=>'tdoverflowmax125', 'css'=>'maxwidth500'), + 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:(t.usage_organize_event:=:1)', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'position'=>52, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'picto'=>'project', 'css'=>'tdoverflowmax150 maxwidth500', 'csslist'=>'width100'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'csslist'=>'tdoverflowmax125', 'css'=>'maxwidth500'), 'note' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3), 'fk_action' => array('type'=>'sellist:c_actioncomm:libelle:id::module LIKE (\'%@eventorganization\')', 'label'=>'Format', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>1, 'css'=>'width100', 'csslist'=>'tdoverflowmax100'), 'datep' => array('type'=>'datetime', 'label'=>'DateStart', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>1, 'showoncombobox'=>'2',), diff --git a/htdocs/eventorganization/class/conferenceorboothattendee.class.php b/htdocs/eventorganization/class/conferenceorboothattendee.class.php index afee798829f..0ac9fdb4481 100644 --- a/htdocs/eventorganization/class/conferenceorboothattendee.class.php +++ b/htdocs/eventorganization/class/conferenceorboothattendee.class.php @@ -108,7 +108,7 @@ class ConferenceOrBoothAttendee extends CommonObject 'email' => array('type'=>'mail', 'label'=>'EmailAttendee', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'autofocusoncreate'=>1, 'searchall'=>1), 'firstname' => array('type'=>'varchar(100)', 'label'=>'Firstname', 'enabled'=>'1', 'position'=>31, 'notnull'=>0, 'visible'=>1, 'index'=>1, 'searchall'=>1), 'lastname' => array('type'=>'varchar(100)', 'label'=>'Lastname', 'enabled'=>'1', 'position'=>32, 'notnull'=>0, 'visible'=>1, 'index'=>1, 'searchall'=>1), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status = 1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'position'=>40, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'position'=>40, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500'), 'email_company' => array('type'=>'mail', 'label'=>'EmailCompany', 'enabled'=>'1', 'position'=>41, 'notnull'=>0, 'visible'=>-2, 'searchall'=>1), 'date_subscription' => array('type'=>'datetime', 'label'=>'DateOfRegistration', 'enabled'=>'1', 'position'=>56, 'notnull'=>1, 'visible'=>1, 'showoncombobox'=>'1',), 'fk_invoice' => array('type'=>'integer:Facture:compta/facture/class/facture.class.php', 'label'=>'Invoice', 'enabled'=>'$conf->facture->enabled', 'position'=>57, 'notnull'=>0, 'visible'=>-1, 'index'=>0, 'picto'=>'bill', 'css'=>'tdoverflowmax150 maxwidth500'), diff --git a/htdocs/eventorganization/conferenceorboothattendee_card.php b/htdocs/eventorganization/conferenceorboothattendee_card.php index 9bab2a7f49d..cb31eb4ac62 100644 --- a/htdocs/eventorganization/conferenceorboothattendee_card.php +++ b/htdocs/eventorganization/conferenceorboothattendee_card.php @@ -47,7 +47,8 @@ $cancel = GETPOST('cancel', 'aZ09'); $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'conferenceorboothattendeecard'; // To manage different context of search $backtopage = GETPOST('backtopage', 'alpha'); $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); -//$lineid = GETPOST('lineid', 'int'); +$lineid = GETPOST('lineid', 'int'); +$mode = GETPOST('mode', 'alpha'); $conf_or_booth_id = GETPOST('conforboothid', 'int'); $fk_project = GETPOST('fk_project', 'int'); @@ -233,7 +234,7 @@ if (!empty($withproject)) { // Title $morehtmlref .= $projectstatic->title; // Thirdparty - if ($projectstatic->thirdparty->id > 0) { + if (!empty($projectstatic->thirdparty->id) && $projectstatic->thirdparty->id > 0) { $morehtmlref .= '
'.$projectstatic->thirdparty->getNomUrl(1, 'project'); } $morehtmlref .= ''; @@ -384,7 +385,7 @@ if (!empty($withproject)) { //print ''; print '
'; $linksuggest = $dolibarr_main_url_root.'/public/project/index.php?id='.$projectstatic->id; - $encodedsecurekey = dol_hash($conf->global->EVENTORGANIZATION_SECUREKEY.'conferenceorbooth'.$projectstatic->id, 'md5'); + $encodedsecurekey = dol_hash(getDolGlobalString("EVENTORGANIZATION_SECUREKEY").'conferenceorbooth'.$projectstatic->id, 'md5'); $linksuggest .= '&securekey='.urlencode($encodedsecurekey); //print ''; $link_subscription = $dolibarr_main_url_root.'/public/eventorganization/attendee_new.php?id='.$projectstatic->id.'&type=global'; - $encodedsecurekey = dol_hash($conf->global->EVENTORGANIZATION_SECUREKEY.'conferenceorbooth'.$projectstatic->id, 'md5'); + $encodedsecurekey = dol_hash(getDolGlobalString("EVENTORGANIZATION_SECUREKEY").'conferenceorbooth'.$projectstatic->id, 'md5'); $link_subscription .= '&securekey='.urlencode($encodedsecurekey); //print ''; $linksuggest = $dolibarr_main_url_root.'/public/project/index.php?id='.$projectstatic->id; - $encodedsecurekey = dol_hash($conf->global->EVENTORGANIZATION_SECUREKEY.'conferenceorbooth'.$projectstatic->id, 'md5'); + $encodedsecurekey = dol_hash(getDolUserString("EVENTORGANIZATION_SECUREKEYEVENTORGANIZATION_SECUREKEY").'conferenceorbooth'.$projectstatic->id, 'md5'); $linksuggest .= '&securekey='.urlencode($encodedsecurekey); //print ''; $link_subscription = $dolibarr_main_url_root.'/public/eventorganization/attendee_new.php?id='.$projectstatic->id.'&type=global'; - $encodedsecurekey = dol_hash($conf->global->EVENTORGANIZATION_SECUREKEY.'conferenceorbooth'.$projectstatic->id, 'md5'); + $encodedsecurekey = dol_hash(getDolUserString("EVENTORGANIZATION_SECUREKEY").'conferenceorbooth'.$projectstatic->id, 'md5'); $link_subscription .= '&securekey='.urlencode($encodedsecurekey); //print ''; if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { - print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:')=== 0)) { - print $object->showInputField($val, $key, $search[$key], '', '', 'search_', 'maxwidth125', 1); + print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', 'maxwidth125', 1); } elseif (!preg_match('/^(date|timestamp|datetime)/', $val['type'])) { - print ''; + print ''; } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { print '
'; print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); @@ -872,6 +872,7 @@ if (isset($extrafields->attributes[$object->table_element]['computed']) && is_ar // -------------------------------------------------------------------- $i = 0; $totalarray = array(); +$totalarray['nbfield'] = 0; while ($i < ($limit ? min($num, $limit) : $num)) { $obj = $db->fetch_object($resql); if (empty($obj)) { @@ -880,7 +881,6 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // Store properties in $object $object->setVarsFromFetchObj($obj); - // Show here line of result print '
'.$langs->trans("Project").''; - print img_picto('', 'project'); + print img_picto('', 'project', 'class="pictofixedwidth"'); $numprojet = $formproject->select_projects($soc->id, $projectid, 'projectid', 0); print ' id).'">'; print '
'.$langs->trans("DateDeliveryPlanned").''; + print img_picto('', 'action', 'class="pictofixedwidth"'); $date_delivery = ($date_delivery ? $date_delivery : $object->delivery_date); // $date_delivery comes from GETPOST print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1); print "
'; print $langs->trans("Weight"); - print ' '; + print ''; + print img_picto('', 'fa-balance-scale', 'class="pictofixedwidth"'); + print ' '; $text = $formproduct->selectMeasuringUnits("weight_units", "weight", GETPOST('weight_units', 'int'), 0, 2); $htmltext = $langs->trans("KeepEmptyForAutoCalculation"); print $form->textwithpicto($text, $htmltext); @@ -986,7 +989,9 @@ if ($action == 'create') { // Dim print '
'; print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth"); - print ' '; + print ' '; + print img_picto('', 'fa-ruler', 'class="pictofixedwidth"'); + print ''; print ' x '; print ' x '; print ' '; @@ -999,6 +1004,7 @@ if ($action == 'create') { print "
".$langs->trans("DeliveryMethod")."'; $expe->fetch_delivery_methods(); + print img_picto('', 'dolly', 'class="pictofixedwidth"'); print $form->selectarray("shipping_method_id", $expe->meths, GETPOST('shipping_method_id', 'int'), 1, 0, 0, "", 1); if ($user->admin) { print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); @@ -1008,6 +1014,7 @@ if ($action == 'create') { // Tracking number print "
".$langs->trans("TrackingNumber")."'; + print img_picto('', 'barcode', 'class="pictofixedwidth"'); print ''; print "
'; + print img_picto('', 'incoterm', 'class="pictofixedwidth"'); print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : '')); print '
".$langs->trans("DefaultModel")."'; + print img_picto('', 'pdf', 'class="pictofixedwidth"'); print $form->selectarray('model', $list, $conf->global->EXPEDITION_ADDON_PDF); print "
'; print $langs->trans('IncotermLabel'); print ''; - if ($user->rights->commande->creer) { + if ($user->hasRight('commande', 'creer')) { print ''.img_edit().''; } else { print ' '; diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index a4cf5a91fa2..7dd54308af4 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -2566,8 +2566,8 @@ if ($action == 'create') { print '
'; print '
'; - //var_dump($object); - print ''."\n"; + } + print "\n"; print "\n"; } @@ -507,7 +514,7 @@ $extrafields->fetch_name_optionals_label($object->table_element); // fetch optio llxHeaderVierge($langs->trans("NewSubscription")); print '
'; -print load_fiche_titre($langs->trans("NewSubscription"), '', '', 0, 0, 'center'); +print load_fiche_titre(img_picto('', 'member_nocolor', 'class="pictofixedwidth"').'   '.$langs->trans("NewSubscription"), '', '', 0, 0, 'center'); print '
'; @@ -532,7 +539,9 @@ print ''; if (!empty($conf->global->MEMBER_SKIP_TABLE) || !empty($conf->global->MEMBER_NEWFORM_FORCETYPE) || $action == 'create') { print ''; print '
'; - print '
'.$langs->trans("FieldsWithAreMandatory", '*').'
'; + + $messagemandatory = ''.$langs->trans("FieldsWithAreMandatory", '*').''; + //print '
'.$langs->trans("FieldsWithAreMandatory", '*').'
'; //print $langs->trans("FieldsWithIsForPublic",'**').'
'; print dol_get_fiche_head(''); @@ -579,7 +588,7 @@ if (!empty($conf->global->MEMBER_SKIP_TABLE) || !empty($conf->global->MEMBER_NEW $defaulttype = $tmp[0]; $isempty = 0; } - print ''.$langs->trans("Type").' *'; + print ''.$langs->trans("Type").' *'; print $form->selectarray("typeid", $adht->liste_array(1), GETPOST('typeid') ? GETPOST('typeid') : $defaulttype, $isempty); print ''."\n"; } else { @@ -591,7 +600,7 @@ if (!empty($conf->global->MEMBER_SKIP_TABLE) || !empty($conf->global->MEMBER_NEW $morphys["phy"] = $langs->trans("Physical"); $morphys["mor"] = $langs->trans("Moral"); if (empty($conf->global->MEMBER_NEWFORM_FORCEMORPHY)) { - print ''.$langs->trans('MemberNature').' *'."\n"; + print ''.$langs->trans('MemberNature').' *'."\n"; print $form->selectarray("morphy", $morphys, GETPOST('morphy'), 1); print ''."\n"; } else { @@ -609,21 +618,21 @@ if (!empty($conf->global->MEMBER_SKIP_TABLE) || !empty($conf->global->MEMBER_NEW print $formcompany->select_civility(GETPOST('civility_id'), 'civility_id').''."\n"; // Lastname - print ''.$langs->trans("Lastname").' *'."\n"; + print ''.$langs->trans("Lastname").' *'."\n"; // Firstname - print ''.$langs->trans("Firstname").' *'."\n"; + print ''.$langs->trans("Firstname").' *'."\n"; // EMail - print ''.$langs->trans("Email").(getDolGlobalString("ADHERENT_MAIL_REQUIRED") ? ' *' : '').''; + print ''.$langs->trans("Email").(getDolGlobalString("ADHERENT_MAIL_REQUIRED") ? ' *' : '').''; //print img_picto('', 'email', 'class="pictofixedwidth"'); print ''."\n"; // Login if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) { - print ''.$langs->trans("Login").' *'."\n"; - print ''.$langs->trans("Password").' *'."\n"; - print ''.$langs->trans("PasswordRetype").' *'."\n"; + print ''.$langs->trans("Login").' *'."\n"; + print ''.$langs->trans("Password").' *'."\n"; + print ''.$langs->trans("PasswordRetype").' *'."\n"; } // Gender @@ -699,7 +708,7 @@ if (!empty($conf->global->MEMBER_SKIP_TABLE) || !empty($conf->global->MEMBER_NEW // TODO Move this into generic feature. if (!empty($conf->global->MEMBER_NEWFORM_DOLIBARRTURNOVER)) { $arraybudget = array('50'=>'<= 100 000', '100'=>'<= 200 000', '200'=>'<= 500 000', '300'=>'<= 1 500 000', '600'=>'<= 3 000 000', '1000'=>'<= 5 000 000', '2000'=>'5 000 000+'); - print ''.$langs->trans("TurnoverOrBudget").' *'; + print ''.$langs->trans("TurnoverOrBudget").' *'; print $form->selectarray('budget', $arraybudget, GETPOST('budget'), 1); print ' € or $'; diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index cd793a91bfc..f67894988c9 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -160,6 +160,9 @@ if ($source == 'proposal') { // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('onlinesign')); +$error = 0; + + /* * Actions */ @@ -191,10 +194,6 @@ if ($action == 'confirm_refusepropal' && $confirm == 'yes') { if ($result < 0) { $error++; } - $result = $object->call_trigger('PROPAL_CLOSE_REFUSED_WEB', $user); - if ($result < 0) { - $error++; - } } } else { $db->rollback(); @@ -548,6 +547,7 @@ print ''; if ($action == "dosign" && empty($cancel)) { print '
'; print ''; + print ''; print '
'; print '
'; // Do not use class="reposition" here: It breaks the submit and there is a message on top to say it's ok, so going back top is better. @@ -558,7 +558,7 @@ if ($action == "dosign" && empty($cancel)) { print ' '."\n"; + } + print "\n"; print "\n"; } @@ -163,6 +170,7 @@ function llxFooterVierge() /* * Actions */ + $parameters = array(); // Note that $action and $object may have been modified by some hooks $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); @@ -262,6 +270,7 @@ if (empty($reshook) && $action == 'add') { $company->zip = GETPOST('zipcode'); $company->town = GETPOST('town'); $company->email = GETPOST('email'); + $company->url = GETPOST('url'); $company->country_id = GETPOST('country_id', 'int'); $company->state_id = GETPOST('state_id', 'int'); $company->name_alias = dolGetFirstLastname(GETPOST('firstname'), GETPOST('lastname')); @@ -295,12 +304,16 @@ if (empty($reshook) && $action == 'add') { if (empty($company->email)) { $company->email = GETPOST('email'); } + if (empty($company->url)) { + $company->url = GETPOST('url'); + } if (empty($company->state_id)) { $company->state_id = GETPOST('state_id', 'int'); } if (empty($company->name_alias)) { $company->name_alias = dolGetFirstLastname(GETPOST('firstname'), GETPOST('lastname')); } + $company->update(0); } @@ -536,7 +549,7 @@ $extrafields->fetch_name_optionals_label($object->table_element); // fetch optio llxHeaderVierge($langs->trans("NewPartnershipRequest")); print '
'; -print load_fiche_titre($langs->trans("NewPartnershipRequest"), '', '', 0, 0, 'center'); +print load_fiche_titre(img_picto('', 'hands-helping', 'class="pictofixedwidth"').'   '.$langs->trans("NewPartnershipRequest"), '', '', 0, 0, 'center'); print '
'; @@ -560,7 +573,8 @@ print ''; print '
'; -print '
'.$langs->trans("FieldsWithAreMandatory", '*').'
'; +$messagemandatory = ''.$langs->trans("FieldsWithAreMandatory", '*').''; +//print '
'.$langs->trans("FieldsWithAreMandatory", '*').'
'; //print $langs->trans("FieldsWithIsForPublic",'**').'
'; print dol_get_fiche_head(''); @@ -592,22 +606,36 @@ if (getDolGlobalString('PARTNERSHIP_NEWFORM_FORCETYPE')) { print ''."\n"; if (!getDolGlobalString('PARTNERSHIP_NEWFORM_FORCETYPE')) { - print ''."\n"; } // Company -print ''."\n"; // Lastname -print ''."\n"; +print ''."\n"; // Firstname -print ''."\n"; +print ''."\n"; // EMail -print ''."\n"; +// Url +print ''."\n"; // Address print ''."\n"; diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index cf7293109c7..2777e48c7f5 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -1663,7 +1663,7 @@ if ($ispaymentok) { $content .= $companylangs->transnoentitiesnoconv("None"); } else { $topic .= ($ispostactionok ? '' : ' ('.$companylangs->trans("WarningPostActionErrorAfterPayment").')'); - $content .= ''.$companylangs->transnoentitiesnoconv("Error").''; + $content .= ''.$companylangs->transnoentitiesnoconv("Error").''; } $content .= '
'."\n"; foreach ($postactionmessages as $postactionmessage) { diff --git a/htdocs/public/project/new.php b/htdocs/public/project/new.php index 5644123392b..bd8ccd07901 100644 --- a/htdocs/public/project/new.php +++ b/htdocs/public/project/new.php @@ -486,11 +486,11 @@ jQuery(document).ready(function () { print '
'.$langs->trans('PartnershipType').' *'."\n"; + print '
'.$langs->trans('PartnershipType').' *'."\n"; print $form->selectarray("partnershiptype", $listofpartnership, GETPOSTISSET('partnershiptype') ? GETPOST('partnershiptype', 'int') : 'ifone', 1); print '
'.$langs->trans("Company").' *'; +print '
'.$langs->trans("Company").' *'; print img_picto('', 'company', 'class="pictofixedwidth"'); print '
'.$langs->trans("Lastname").' *
'.$langs->trans("Lastname").' *
'.$langs->trans("Firstname").' *
'.$langs->trans("Firstname").' *
'.$langs->trans("Email").' *'; +print '
'.$langs->trans("Email").' *'; //print img_picto('', 'email', 'class="pictofixedwidth"'); print '
'.$langs->trans("Url").' *'; +print ''; +if (getDolGlobalString('PARTNERSHIP_BACKLINKS_TO_CHECK')) { + $listofkeytocheck = explode('|', getDolGlobalString('PARTNERSHIP_BACKLINKS_TO_CHECK')); + $i = 0; + $s = ''; + foreach ($listofkeytocheck as $val) { + $i++; + $s .= ($s ? ($i == count($listofkeytocheck) ? ' '.$langs->trans("or").' ' : ', ') : '').$val; + } + print '
'.$langs->trans("ThisUrlMustContainsAtLeastOneLinkToWebsite", $s).''; +} +print '
'.$langs->trans("Address").''."\n"; print '
'."\n"; // Lastname -print ''."\n"; +print ''."\n"; // Firstname -print ''."\n"; +print ''."\n"; // EMail -print ''."\n"; +print ''."\n"; // Company print ''."\n"; // Address @@ -538,7 +538,7 @@ $parameters['tpl_context']='public'; // define template context to public include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; // Comments print ''; -print ''; +print ''; print ''; print ''."\n"; diff --git a/htdocs/public/project/suggestbooth.php b/htdocs/public/project/suggestbooth.php index dd9c8c7cdb0..cc7b6bb8e01 100644 --- a/htdocs/public/project/suggestbooth.php +++ b/htdocs/public/project/suggestbooth.php @@ -595,13 +595,13 @@ jQuery(document).ready(function () { print '
'.$langs->trans("Lastname").' *
'.$langs->trans("Lastname").' *
'.$langs->trans("Firstname").' *
'.$langs->trans("Firstname").' *
'.$langs->trans("Email").' *
'.$langs->trans("Email").' *
'.$langs->trans("Company").'
'.$langs->trans("Message").' *'.$langs->trans("Message").' *
'."\n"; // Name -print ''; +print ''; print ''; print ''; // Email -print ''."\n"; +print ''."\n"; // Company -print ''."\n"; // Address print ''; } // Type of event -print ''."\n"; +print ''."\n"; print ''; // Label -print ''."\n"; +print ''."\n"; print ''."\n"; // Note -print ''."\n"; +print ''."\n"; print ''."\n"; print "
lastname).'" autofocus="autofocus">
'.$langs->trans("Email").'*
'.$langs->trans("Email").'*
'.$langs->trans("Company").'*'; +print '
'.$langs->trans("Company").'*'; print '
'.$langs->trans("Address").''."\n"; @@ -646,13 +646,13 @@ if (empty($conf->global->SOCIETE_DISABLE_STATE)) { print '
'.$langs->trans("Format").'*
'.$langs->trans("Format").'*'.Form::selectarray('eventtype', $arrayofconfboothtype, $eventtype, 1).'
'.$langs->trans("LabelOfBooth").'*
'.$langs->trans("LabelOfBooth").'*
'.$langs->trans("Description").'*
'.$langs->trans("Description").'*
\n"; diff --git a/htdocs/public/project/suggestconference.php b/htdocs/public/project/suggestconference.php index 417466a1f44..5078164f6ce 100644 --- a/htdocs/public/project/suggestconference.php +++ b/htdocs/public/project/suggestconference.php @@ -528,17 +528,17 @@ jQuery(document).ready(function () { print ''."\n"; // Last Name -print ''; +print ''; print ''; print ''; // First Name -print ''; +print ''; print ''; print ''; // Email -print ''."\n"; +print ''."\n"; // Company -print ''."\n"; // Address print ''; } // Type of event -print ''."\n"; +print ''."\n"; print ''; // Label -print ''."\n"; +print ''."\n"; print ''."\n"; // Note -print ''."\n"; +print ''."\n"; print ''."\n"; print "
lastname).'" autofocus="autofocus">
firstname).'" autofocus="autofocus">
'.$langs->trans("Email").'*
'.$langs->trans("Email").'*
'.$langs->trans("Company").'*'; +print '
'.$langs->trans("Company").'*'; print '
'.$langs->trans("Address").''."\n"; @@ -580,13 +580,13 @@ if (empty($conf->global->SOCIETE_DISABLE_STATE)) { print '
'.$langs->trans("Format").'*
'.$langs->trans("Format").'*'.Form::selectarray('eventtype', $arrayofconfboothtype, $eventtype, 1).'
'.$langs->trans("LabelOfconference").'*
'.$langs->trans("LabelOfconference").'*
'.$langs->trans("Description").'*
'.$langs->trans("Description").'*
\n"; diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index dd5b1db148f..9c10041a64e 100644 --- a/htdocs/public/stripe/ipn.php +++ b/htdocs/public/stripe/ipn.php @@ -43,9 +43,9 @@ require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; - require_once DOL_DOCUMENT_ROOT.'/includes/stripe/stripe-php/init.php'; require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; @@ -73,7 +73,7 @@ if (isset($_GET['connect'])) { } } -if (empty($conf->stripe->enabled)) { +if (!isModEnabled('stripe')) { httponly_accessforbidden('Module Stripe not enabled'); } @@ -100,9 +100,19 @@ if (!empty($conf->global->STRIPE_USER_ACCOUNT_FOR_ACTIONS)) { */ $payload = @file_get_contents("php://input"); -$sig_header = $_SERVER["HTTP_STRIPE_SIGNATURE"]; +$sig_header = empty($_SERVER["HTTP_STRIPE_SIGNATURE"]) ? '' : $_SERVER["HTTP_STRIPE_SIGNATURE"]; $event = null; +if (getDolGlobalString('STRIPE_DEBUG')) { + $fh = fopen(DOL_DATA_ROOT.'/dolibarr_stripe.log', 'w+'); + if ($fh) { + fwrite($fh, dol_print_date(dol_now('gmt'), 'standard').' HTTP_STRIPE_SIGNATURE='.$sig_header."\n"); + fwrite($fh, $payload); + fclose($fh); + dolChmod(DOL_DATA_ROOT.'/dolibarr_stripe.log'); + } +} + $error = 0; try { @@ -112,6 +122,8 @@ try { httponly_accessforbidden('Invalid payload', 400); } catch (\Stripe\Error\SignatureVerification $e) { httponly_accessforbidden('Invalid signature', 400); +} catch (Exception $e) { + httponly_accessforbidden('Error '.$e->getMessage(), 400); } // Do something with $event @@ -196,7 +208,6 @@ if ($event->type == 'payout.created') { return -1; } } elseif ($event->type == 'payout.paid') { - global $conf; $error = 0; $result = dolibarr_set_const($db, $service."_NEXTPAYOUT", null, 'chaine', 0, '', $conf->entity); if ($result) { @@ -298,8 +309,154 @@ if ($event->type == 'payout.created') { $db->query($sql); $db->commit(); } elseif ($event->type == 'payment_intent.succeeded') { // Called when making payment with PaymentIntent method ($conf->global->STRIPE_USE_NEW_CHECKOUT is on). + dol_syslog("object = ".var_export($event->data, true)); + // TODO: create fees - // TODO: Redirect to paymentok.php + + /* TODO LMR Enable this only if this is a payment of a Dolibarr bon_prelevement only + include_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php'; + $object = $event->data->object; + $invoice_id = $object->metadata->dol_id; + $ipaddress = $object->metadata->ipaddress; + $invoice_amount = $object->amount / 100; + $TRANSACTIONID = $object->id; + $customer_id = $object->customer; + $errorforinvoice = 0; + $paymentmethod = 'stripe'; + $now = dol_now(); + $currencyCodeType = strtoupper($object->currency); + $paymentmethodstripeid = $object->payment_method; + + global $stripearrayofkeysbyenv; + $stripeacc = $stripearrayofkeysbyenv[$servicestatus]['secret_key']; + + dol_syslog("Try to create sepa_debit with data = ".json_encode($dataforcard)); + + $s = new \Stripe\StripeClient($stripeacc); + + $paymentmethodstripe = $s->paymentMethods->retrieve($paymentmethodstripeid); + + //$paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; + $paymentTypeId = $paymentmethodstripe->type; + if ($paymentTypeId == "sepa_debit") { + $paymentTypeId = "BANCON"; + } elseif ($paymentTypeId == "card") { + $paymentTypeId = "CB"; + } + + $paiement = new Paiement($db); + $paiement->datepaye = $now; + $paiement->date = $now; + if ($currencyCodeType == $conf->currency) { + $paiement->amounts = [$invoice_id => $invoice_amount]; // Array with all payments dispatching with invoice id + } else { + $paiement->multicurrency_amounts = [$invoice_id => $invoice_amount]; // Array with all payments dispatching + + $postactionmessages[] = 'Payment was done in a different currency than currency expected of company'; + $ispostactionok = -1; + // Not yet supported, so error + $error++; + $errorforinvoice++; + } + $paiement->paiementid = $paymentTypeId; + $paiement->num_paiement = ''; + $paiement->num_payment = ''; + // Add a comment with keyword 'SellYourSaas' in text. Used by trigger. + $paiement->note_public = 'StripeSepa payment ' . dol_print_date($now, 'standard') . ' using ' . $paymentmethod . ($ipaddress ? ' from ip ' . $ipaddress : '') . ' - Transaction ID = ' . $TRANSACTIONID; + $paiement->note_private = 'StripeSepa payment ' . dol_print_date($now, 'standard') . ' using ' . $paymentmethod . ($ipaddress ? ' from ip ' . $ipaddress : '') . ' - Transaction ID = ' . $TRANSACTIONID; + $paiement->ext_payment_id = $TRANSACTIONID . ':' . $customer_id . '@' . $stripearrayofkeysbyenv[$servicestatus]['publishable_key']; + $paiement->ext_payment_site = 'stripe'; + + if (!$errorforinvoice) { + dol_syslog('* Record payment for invoice id ' . $invoice_id . '. It includes closing of invoice and regenerating document'); + + // This include closing invoices to 'paid' (and trigger including unsuspending) and regenerating document + $paiement_id = $paiement->create($user, 1); + if ($paiement_id < 0) { + $postactionmessages[] = $paiement->error . ($paiement->error ? ' ' : '') . join("
\n", $paiement->errors); + $ispostactionok = -1; + $error++; + $errorforinvoice++; + } else { + $postactionmessages[] = 'Payment created'; + } + + dol_syslog("The payment has been created for invoice id " . $invoice_id); + } + + if (!$errorforinvoice && isModEnabled('banque')) { + dol_syslog('* Add payment to bank'); + + // The bank used is the one defined into Stripe setup + $bankaccountid = 0; + if ($paymentmethod == 'stripe') { + $bankaccountid = $conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS; + } + + if ($bankaccountid > 0) { + $label = '(CustomerInvoicePayment)'; + $result = $paiement->addPaymentToBank($user, 'payment', $label, $bankaccountid, $customer_id, ''); + if ($result < 0) { + $postactionmessages[] = $paiement->error . ($paiement->error ? ' ' : '') . join("
\n", $paiement->errors); + $ispostactionok = -1; + $error++; + $errorforinvoice++; + } else { + $postactionmessages[] = 'Bank transaction of payment created (by makeStripeSepaRequest)'; + } + } else { + $postactionmessages[] = 'Setup of bank account to use in module ' . $paymentmethod . ' was not set. No way to record the payment.'; + $ispostactionok = -1; + $error++; + $errorforinvoice++; + } + } + + if (!$errorforinvoice && isModEnabled('prelevement')) { + $bon = new BonPrelevement($db); + $idbon = 0; + $sql = "SELECT dp.fk_prelevement_bons as idbon"; + $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as dp"; + $sql .= " WHERE dp.fk_facture = '".$db->escape($invoice_id)."'"; + $sql .= " AND dp.sourcetype = 'facture'"; + $sql .= " AND dp.traite = 1"; + $result = $db->query($sql); + if ($result) { + if ($db->num_rows($result)) { + $obj = $db->fetch_object($result); + $idbon = $obj->idbon; + } + } else { + $postactionmessages[] = $db->lasterror(); + $ispostactionok = -1; + $error++; + $errorforinvoice++; + } + + if (!empty($idbon)) { + $bon->fetch($idbon); + $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons"; + $sql .= " SET fk_user_credit = ".$user->id; + $sql .= ", statut = '".$db->escape($bon::STATUS_CREDITED)."'"; + $sql .= ", date_credit = '".$db->idate($now)."'"; + $sql .= ", credite = 1"; + $sql .= " WHERE rowid=".((int) $bon->id); + $sql .= " AND statut = '".$db->escape($bon::STATUS_TRANSFERED)."'"; + + $db->begin(); + $result = $db->query($sql); + if (!$result) { + $db->rollback(); + $postactionmessages[] = $db->lasterror(); + $ispostactionok = -1; + $error++; + $errorforinvoice++; + } else { + $db->commit(); + } + } + } + */ } elseif ($event->type == 'payment_intent.payment_failed') { // TODO: Redirect to paymentko.php } elseif ($event->type == 'checkout.session.completed') { // Called when making payment with new Checkout method ($conf->global->STRIPE_USE_NEW_CHECKOUT is on). @@ -313,7 +470,9 @@ if ($event->type == 'payout.created') { $companypaymentmode = new CompanyPaymentMode($db); $idthirdparty = $societeaccount->getThirdPartyID($db->escape($event->data->object->customer), 'stripe', $servicestatus); - if ($idthirdparty > 0) { // If the payment mode is on an external customer that is known in societeaccount, we can create the payment mode + if ($idthirdparty > 0) { + // If the payment mode attached is to a stripe account owned by an external customer in societe_account (so a thirdparty that has a Stripe account), + // we can create the payment mode $companypaymentmode->stripe_card_ref = $db->escape($event->data->object->id); $companypaymentmode->fk_soc = $idthirdparty; $companypaymentmode->bank = null; @@ -331,9 +490,44 @@ if ($event->type == 'payout.created') { $companypaymentmode->country_code = $db->escape($event->data->object->card->country); $companypaymentmode->status = $servicestatus; + // TODO Check that a payment mode $companypaymentmode->stripe_card_ref does not exists yet to avoid to create duplicates + // so we can remove the test on STRIPE_NO_DUPLICATE_CHECK + if (getDolGlobalString('STRIPE_NO_DUPLICATE_CHECK')) { + $db->begin(); + $result = $companypaymentmode->create($user); + if ($result < 0) { + $error++; + } + if (!$error) { + $db->commit(); + } else { + $db->rollback(); + } + } + } +} elseif ($event->type == 'payment_method.updated') { + require_once DOL_DOCUMENT_ROOT.'/societe/class/companypaymentmode.class.php'; + $companypaymentmode = new CompanyPaymentMode($db); + $companypaymentmode->fetch(0, '', 0, '', " AND stripe_card_ref = '".$db->escape($event->data->object->id)."'"); + if ($companypaymentmode->id > 0) { + // If we found a payment mode with the ID + $companypaymentmode->bank = null; + $companypaymentmode->label = null; + $companypaymentmode->number = $db->escape($event->data->object->id); + $companypaymentmode->last_four = $db->escape($event->data->object->card->last4); + $companypaymentmode->proprio = $db->escape($event->data->object->billing_details->name); + $companypaymentmode->exp_date_month = $db->escape($event->data->object->card->exp_month); + $companypaymentmode->exp_date_year = $db->escape($event->data->object->card->exp_year); + $companypaymentmode->cvn = null; + $companypaymentmode->datec = $db->escape($event->data->object->created); + $companypaymentmode->default_rib = 0; + $companypaymentmode->type = $db->escape($event->data->object->type); + $companypaymentmode->country_code = $db->escape($event->data->object->card->country); + $companypaymentmode->status = $servicestatus; + $db->begin(); if (!$error) { - $result = $companypaymentmode->create($user); + $result = $companypaymentmode->update($user); if ($result < 0) { $error++; } @@ -344,36 +538,6 @@ if ($event->type == 'payout.created') { $db->rollback(); } } -} elseif ($event->type == 'payment_method.updated') { - require_once DOL_DOCUMENT_ROOT.'/societe/class/companypaymentmode.class.php'; - $companypaymentmode = new CompanyPaymentMode($db); - $companypaymentmode->fetch(0, '', 0, '', " AND stripe_card_ref = '".$db->escape($event->data->object->id)."'"); - $companypaymentmode->bank = null; - $companypaymentmode->label = null; - $companypaymentmode->number = $db->escape($event->data->object->id); - $companypaymentmode->last_four = $db->escape($event->data->object->card->last4); - $companypaymentmode->proprio = $db->escape($event->data->object->billing_details->name); - $companypaymentmode->exp_date_month = $db->escape($event->data->object->card->exp_month); - $companypaymentmode->exp_date_year = $db->escape($event->data->object->card->exp_year); - $companypaymentmode->cvn = null; - $companypaymentmode->datec = $db->escape($event->data->object->created); - $companypaymentmode->default_rib = 0; - $companypaymentmode->type = $db->escape($event->data->object->type); - $companypaymentmode->country_code = $db->escape($event->data->object->card->country); - $companypaymentmode->status = $servicestatus; - - $db->begin(); - if (!$error) { - $result = $companypaymentmode->update($user); - if ($result < 0) { - $error++; - } - } - if (!$error) { - $db->commit(); - } else { - $db->rollback(); - } } elseif ($event->type == 'payment_method.detached') { $db->begin(); $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_rib WHERE number = '".$db->escape($event->data->object->id)."' and status = ".((int) $servicestatus); diff --git a/htdocs/public/test/test_forms.php b/htdocs/public/test/test_forms.php index acc9151798f..b7ed524e297 100644 --- a/htdocs/public/test/test_forms.php +++ b/htdocs/public/test/test_forms.php @@ -105,6 +105,75 @@ $array = array(1=>'Value 1', 2=>'Value 2', 3=>'Value 3'); $arrayselected = array(1, 3); print $form->multiselectarray('testmulti', $array, $arrayselected, '', 0, 'minwidth100'); +print '

'."\n"; + +// Test6a: Upload of big files +print "Test 6a: Upload of big files
\n"; +print "The file will be uploaded in the directory: documents/test/temp/
\n"; + +if (is_file(DOL_DOCUMENT_ROOT.'/includes/flowjs/flow.js')) { + print ''; + print ' No file selected.'; + print '
'; + print '
'; + print ''; + print ''; +} else { + print "If this message displays, please add flow.js and flow.min.js files which can be found here: https://github.com/flowjs/flow.js and place the js lib in htdocs/includes/flowjs/
\n"; +} + print '
'; // End of page diff --git a/htdocs/public/ticket/ajax/ajax.php b/htdocs/public/ticket/ajax/ajax.php index 2b637ce3647..19361320ced 100644 --- a/htdocs/public/ticket/ajax/ajax.php +++ b/htdocs/public/ticket/ajax/ajax.php @@ -19,6 +19,9 @@ /** * \file htdocs/public/ticket/ajax/ajax.php * \brief Ajax component for Ticket. + * + * This ajax component is called only by the create ticket public page. And only if TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST is set. + * This option TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST has been removed because it is a security hole. */ if (!defined('NOTOKENRENEWAL')) { @@ -54,6 +57,14 @@ $action = GETPOST('action', 'aZ09'); $id = GETPOST('id', 'int'); $email = GETPOST('email', 'alphanohtml'); +if (!isModEnabled('ticket')) { + httponly_accessforbidden('Module Ticket not enabled'); +} + +if (empty($conf->global->TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST)) { + httponly_accessforbidden('Option TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST of module ticket is not enabled'); +} + /* * View @@ -71,9 +82,18 @@ if ($action == 'getContacts') { require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; $ticket = new Ticket($db); - $contacts = $ticket->searchContactByEmail($email); - if (is_array($contacts)) { - $return['contacts'] = $contacts; + $arrayofcontacts = $ticket->searchContactByEmail($email); + if (is_array($arrayofcontacts)) { + $arrayofminimalcontacts = array(); + foreach ($arrayofcontacts as $tmpval) { + $tmpresult = new stdClass(); + $tmpresult->id = $tmpval->id; + $tmpresult->firstname = $tmpval->firstname; + $tmpresult->lastname = $tmpval->lastname; + $arrayofminimalcontacts[] = $tmpresult; + } + + $return['contacts'] = $arrayofminimalcontacts; } else { $return['error'] = $ticket->errorsToString(); } diff --git a/htdocs/public/ticket/create_ticket.php b/htdocs/public/ticket/create_ticket.php index 75111725df0..80ea664292b 100644 --- a/htdocs/public/ticket/create_ticket.php +++ b/htdocs/public/ticket/create_ticket.php @@ -1,6 +1,7 @@ * Copyright (C) 2016 Christophe Battarel + * Copyright (C) 2023 Laurent Destailleur * * 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 @@ -26,9 +27,6 @@ if (!defined('NOREQUIREUSER')) { define('NOREQUIREUSER', '1'); }*/ -if (!defined('NOTOKENRENEWAL')) { - define('NOTOKENRENEWAL', '1'); -} if (!defined('NOREQUIREMENU')) { define('NOREQUIREMENU', '1'); } diff --git a/htdocs/public/ticket/index.php b/htdocs/public/ticket/index.php index 239d9f71d59..97af18c0bb6 100644 --- a/htdocs/public/ticket/index.php +++ b/htdocs/public/ticket/index.php @@ -86,7 +86,7 @@ print '

'.(getDolGlobalString("TICKET_PUBLIC_TEXT_H print '
'; print '

'; -print '

'.dol_escape_htmltag($langs->trans("CreateTicket")).'
'; +print '

'.dol_escape_htmltag($langs->trans("CreateTicket")).'
'; print '

'.dol_escape_htmltag($langs->trans("ViewMyTicketList")).'
'; print '
'.img_picto('', 'ticket', 'class="fa-15"').'
'.dol_escape_htmltag($langs->trans("ShowTicketWithTrackId")).'
'; print '
'; diff --git a/htdocs/reception/class/api_receptions.class.php b/htdocs/reception/class/api_receptions.class.php index a7b8bdb02ce..c9f4cba44cc 100644 --- a/htdocs/reception/class/api_receptions.class.php +++ b/htdocs/reception/class/api_receptions.class.php @@ -144,11 +144,10 @@ class Receptions extends DolibarrApi // Add sql filters if ($sqlfilters) { $errormessage = ''; - if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); + if ($errormessage) { + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/recruitment/class/api_recruitment.class.php b/htdocs/recruitment/class/api_recruitment.class.php index c8e21a3e029..b665bda1279 100644 --- a/htdocs/recruitment/class/api_recruitment.class.php +++ b/htdocs/recruitment/class/api_recruitment.class.php @@ -194,11 +194,10 @@ class Recruitment extends DolibarrApi } if ($sqlfilters) { $errormessage = ''; - if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); + if ($errormessage) { + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } $sql .= $this->db->order($sortfield, $sortorder); @@ -302,11 +301,10 @@ class Recruitment extends DolibarrApi } if ($sqlfilters) { $errormessage = ''; - if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); + if ($errormessage) { + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index e3dfd4bd135..6dae3e08388 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -129,6 +129,7 @@ class RecruitmentCandidature extends CommonObject 'description' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>300, 'notnull'=>0, 'visible'=>3, 'cssview'=>'wordbreak'), 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-4, 'csslist'=>'nowraponall'), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2, 'csslist'=>'nowraponall'), + 'fk_user' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'LinkedToDolibarrUser', 'enabled'=>'1', 'position'=>600, 'notnull'=>0, 'visible'=>-1, 'csslist'=>'tdoverflowmax100'), 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'default'=>0, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Received', '3'=>'ContractProposed', '5'=>'ContractSigned', '8'=>'Refused', '9'=>'Canceled')), @@ -144,6 +145,7 @@ class RecruitmentCandidature extends CommonObject public $tms; public $fk_user_creat; public $fk_user_modif; + public $fk_user; public $lastname; public $firstname; public $email; @@ -1053,7 +1055,7 @@ class RecruitmentCandidature extends CommonObject $return .= '
'.$langs->trans("phone").' : '.$this->phone.''; } if (method_exists($this, 'getLibStatut')) { - $return .= '
'.$this->getLibStatut(5).'
'; + $return .= '
'.$this->getLibStatut(3).'
'; } $return .= '
'; $return .= '
'; diff --git a/htdocs/recruitment/class/recruitmentjobposition.class.php b/htdocs/recruitment/class/recruitmentjobposition.class.php index a63e6b012b2..b0ca58d6b8f 100644 --- a/htdocs/recruitment/class/recruitmentjobposition.class.php +++ b/htdocs/recruitment/class/recruitmentjobposition.class.php @@ -120,11 +120,11 @@ class RecruitmentJobPosition extends CommonObject 'label' => array('type'=>'varchar(255)', 'label'=>'JobLabel', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth500', 'csslist'=>'tdoverflowmax300', 'showoncombobox'=>'2', 'autofocusoncreate'=>1), 'qty' => array('type'=>'integer', 'label'=>'NbOfEmployeesExpected', 'enabled'=>'1', 'position'=>45, 'notnull'=>1, 'visible'=>1, 'default'=>'1', 'isameasure'=>'1', 'css'=>'maxwidth75imp'), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'enabled'=>'$conf->project->enabled', 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'css'=>'maxwidth500', 'picto'=>'project'), - 'fk_user_recruiter' => array('type'=>'integer:User:user/class/user.class.php:status=1', 'label'=>'ResponsibleOfRecruitement', 'enabled'=>'1', 'position'=>54, 'notnull'=>1, 'visible'=>1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), + 'fk_user_recruiter' => array('type'=>'integer:User:user/class/user.class.php:1:(statut:=:1)', 'label'=>'ResponsibleOfRecruitement', 'enabled'=>'1', 'position'=>54, 'notnull'=>1, 'visible'=>1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), 'email_recruiter' => array('type'=>'varchar(255)', 'label'=>'EmailRecruiter', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>-1, 'help'=>'ToUseAGenericEmail', 'picto'=>'email'), - 'fk_user_supervisor' => array('type'=>'integer:User:user/class/user.class.php:t.statut = 1', 'label'=>'FutureManager', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), + 'fk_user_supervisor' => array('type'=>'integer:User:user/class/user.class.php:1:(statut:=:1)', 'label'=>'FutureManager', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), 'fk_establishment' => array('type'=>'integer:Establishment:hrm/class/establishment.class.php', 'label'=>'Establishment', 'enabled'=>'$conf->hrm->enabled', 'position'=>56, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'establishment.rowid',), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'WorkPlace', 'enabled'=>'isModEnabled("societe")', 'position'=>57, 'notnull'=>-1, 'visible'=>-1, 'css'=>'maxwidth500', 'index'=>1, 'help'=>"IfJobIsLocatedAtAPartner", 'picto'=>'company'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label'=>'WorkPlace', 'enabled'=>'isModEnabled("societe")', 'position'=>57, 'notnull'=>-1, 'visible'=>-1, 'css'=>'maxwidth500', 'index'=>1, 'help'=>"IfJobIsLocatedAtAPartner", 'picto'=>'company'), 'date_planned' => array('type'=>'date', 'label'=>'DateExpected', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>1,), 'remuneration_suggested' => array('type'=>'varchar(255)', 'label'=>'Remuneration', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>1,), 'description' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>65, 'notnull'=>0, 'visible'=>3,), @@ -381,8 +381,6 @@ class RecruitmentJobPosition extends CommonObject */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') { - global $conf; - dol_syslog(__METHOD__, LOG_DEBUG); $records = array(); @@ -501,7 +499,7 @@ class RecruitmentJobPosition extends CommonObject */ public function validate($user, $notrigger = 0) { - global $conf, $langs; + global $conf; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; @@ -1087,7 +1085,7 @@ class RecruitmentJobPosition extends CommonObject */ public function doScheduledJob() { - global $conf, $langs; + //global $conf, $langs; //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; @@ -1140,7 +1138,7 @@ class RecruitmentJobPosition extends CommonObject $return .= ' | '.$langs->trans("Remuneration").' : '.$this->remuneration_suggested.''; } if (method_exists($this, 'getLibStatut')) { - $return .= '
'.$this->getLibStatut(5).' | '.$langs->trans("RecruitmentCandidatures", '', '', '', '', 5).' : '.$obj->nbapplications.'
'; + $return .= '
'.$this->getLibStatut(3).' | '.$langs->trans("RecruitmentCandidatures", '', '', '', '', 5).' : '.$obj->nbapplications.'
'; } $return .= '
'; $return .= '
'; diff --git a/htdocs/recruitment/recruitmentcandidature_card.php b/htdocs/recruitment/recruitmentcandidature_card.php index 62f7ed5cc9b..80558b67e49 100644 --- a/htdocs/recruitment/recruitmentcandidature_card.php +++ b/htdocs/recruitment/recruitmentcandidature_card.php @@ -202,38 +202,46 @@ if (empty($reshook)) { // Create user from a member if ($action == 'confirm_create_user' && $confirm == 'yes' && $user->rights->user->user->creer) { - if ($result > 0) { - $jobposition = new RecruitmentJobPosition($db); - $jobposition->fetch($object->fk_recruitmentjobposition); + $jobposition = new RecruitmentJobPosition($db); + $jobposition->fetch($object->fk_recruitmentjobposition); - // Creation user - $nuser = new User($db); - $nuser->login = GETPOST('login', 'alphanohtml'); - $nuser->fk_soc = 0; - $nuser->employee = 1; - $nuser->firstname = $object->firstname; - $nuser->lastname = $object->lastname; - $nuser->email = ''; - $nuser->personal_email = $object->email; - $nuser->personal_mobile = $object->phone; - $nuser->birth = $object->date_birth; - $nuser->salary = $object->remuneration_proposed; - $nuser->fk_user = $jobposition->fk_user_supervisor; // Supervisor - $nuser->email = $object->email; + $db->begin(); - $result = $nuser->create($user); + // Creation user + $nuser = new User($db); + $nuser->login = GETPOST('login', 'alphanohtml'); + $nuser->fk_soc = 0; + $nuser->employee = 1; + $nuser->firstname = $object->firstname; + $nuser->lastname = $object->lastname; + $nuser->email = ''; + $nuser->personal_email = $object->email; + $nuser->personal_mobile = $object->phone; + $nuser->birth = $object->date_birth; + $nuser->salary = $object->remuneration_proposed; + $nuser->fk_user = $jobposition->fk_user_supervisor; // Supervisor + $nuser->email = $object->email; - if ($result < 0) { - $langs->load("errors"); - setEventMessages($langs->trans($nuser->error), null, 'errors'); - $action = 'create_user'; - } else { - setEventMessages($langs->trans("NewUserCreated", $nuser->login), null, 'mesgs'); - $action = ''; - } - } else { - setEventMessages($object->error, $object->errors, 'errors'); + $result = $nuser->create($user); + + if ($result < 0) { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans($nuser->error), null, 'errors'); $action = 'create_user'; + } else { + $object->fk_user = $result; + + $object->update($user); + } + + if (!$error) { + $db->commit(); + + setEventMessages($langs->trans("NewUserCreated", $nuser->login), null, 'mesgs'); + $action = ''; + } else { + $db->rollback(); } } @@ -465,7 +473,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea }*/ // Author if (!empty($object->email_msgid)) { - $morehtmlref .= $langs->trans("CreatedBy").' : '; + $morehtmlref .= '
'.$langs->trans("CreatedBy").' '; if ($object->fk_user_creat > 0) { $fuser = new User($db); @@ -572,8 +580,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Button to convert into a user if ($object->status == $object::STATUS_CONTRACT_SIGNED) { if ($user->rights->user->user->creer) { - // TODO Check if a user already exists - $useralreadyexists = 0; + $useralreadyexists = $object->fk_user; if (empty($useralreadyexists)) { print ''; } else { diff --git a/htdocs/recruitment/recruitmentcandidature_list.php b/htdocs/recruitment/recruitmentcandidature_list.php index 8fcd62fc078..05524716cad 100644 --- a/htdocs/recruitment/recruitmentcandidature_list.php +++ b/htdocs/recruitment/recruitmentcandidature_list.php @@ -66,7 +66,7 @@ $pagenext = $page + 1; $object = new RecruitmentCandidature($db); $extrafields = new ExtraFields($db); $diroutputmassaction = $conf->recruitment->dir_output.'/temp/massgeneration/'.$user->id; -$hookmanager->initHooks(array('recruitmentcandidaturelist')); // Note that conf->hooks_modules contains array +$hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array of activated contexes // Fetch optionals attributes and labels $extrafields->fetch_name_optionals_label($object->table_element); @@ -102,6 +102,13 @@ foreach ($object->fields as $key => $val) { $fieldstosearchall['t.'.$key] = $val['label']; } } +/*$parameters = array('fieldstosearchall'=>$fieldstosearchall); +$reshook = $hookmanager->executeHooks('completeFieldsToSearchAll', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook > 0) { + $fieldstosearchall = $hookmanager->resArray['fieldstosearchall']; +} elseif ($reshook == 0) { + $fieldstosearchall = array_merge($fieldstosearchall, $hookmanager->resArray['fieldstosearchall']); +}*/ // Definition of array of fields for columns $arrayfields = array(); @@ -226,6 +233,9 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook $sql .= preg_replace('/^,/', '', $hookmanager->resPrint); $sql = preg_replace('/,\s*$/', '', $sql); + +$sqlfields = $sql; // $sql fields to remove for count total + $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; @@ -279,7 +289,7 @@ if (!empty($id)) { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; // Add where from hooks $parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; /* If a group by is required @@ -304,7 +314,8 @@ $sql = preg_replace('/,\s*$/', '', $sql); $nbtotalofrecords = ''; if (empty($conf->global->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('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/Ui', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql); + $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); @@ -313,7 +324,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { dol_print_error($db); } - if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } @@ -500,7 +511,7 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } foreach ($search as $key => $val) { - if (is_array($search[$key]) && count($search[$key])) { + if (is_array($search[$key])) { foreach ($search[$key] as $skey) { if ($skey != '') { $param .= '&search_'.$key.'[]='.urlencode($skey); @@ -581,7 +592,7 @@ $moreforfilter.= $langs->trans('MyFilter') . ': '; +print ''; // Action column -if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; $searchpicto = $form->showFilterButtons('left'); print $searchpicto; print ''; @@ -621,13 +632,13 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } if (!empty($arrayfields['t.'.$key]['checked'])) { - print ''; + print ''; if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { - print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1); } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1); } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { @@ -652,11 +663,11 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; // Fields from hook $parameters = array('arrayfields'=>$arrayfields); -$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; print ''; @@ -669,8 +680,9 @@ $totalarray['nbfield'] = 0; // Fields title label // -------------------------------------------------------------------- print ''; -if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; + $totalarray['nbfield']++; } foreach ($object->fields as $key => $val) { $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); @@ -680,12 +692,12 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label if (!empty($arrayfields['t.'.$key]['checked'])) { - print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''), 0, (empty($val['helplist']) ? '' : $val['helplist']))."\n"; $totalarray['nbfield']++; } } @@ -693,13 +705,13 @@ foreach ($object->fields as $key => $val) { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; // Hook fields $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray); -$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; + $totalarray['nbfield']++; } -$totalarray['nbfield']++; print ''."\n"; @@ -707,7 +719,7 @@ print ''."\n"; $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 (preg_match('/\$object/', $val)) { + if ($val && preg_match('/\$object/', $val)) { $needToFetchEachLine++; // There is at least one compute field that use $object } } @@ -739,14 +751,11 @@ while ($i < $imaxinloop) { $recuitment->fetch($obj->fk_recruitmentjobposition); $object->fk_recruitmentjobposition = $recuitment->getNomUrl(); $object->phone = $obj->phone; - // Output Kanban - if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - if ($massactionbutton || $massaction) { - $selected = 0; - } - // Output Kanban - print $object->getKanbanView(''); + if ($massactionbutton || $massaction) { + $selected = 0; } + // Output Kanban + print $object->getKanbanView(''); if ($i == ($imaxinloop - 1)) { print '
'; print ''; @@ -756,7 +765,7 @@ while ($i < $imaxinloop) { $j = 0; print ''; // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { 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; @@ -766,6 +775,9 @@ while ($i < $imaxinloop) { print ''; } print ''; + if (!$i) { + $totalarray['nbfield']++; + } } foreach ($object->fields as $key => $val) { $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); @@ -787,7 +799,7 @@ while ($i < $imaxinloop) { //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; if (!empty($arrayfields['t.'.$key]['checked'])) { - print '$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column - if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { 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; @@ -834,9 +846,9 @@ while ($i < $imaxinloop) { print ''; } print ''; - } - if (!$i) { - $totalarray['nbfield']++; + if (!$i) { + $totalarray['nbfield']++; + } } print ''."\n"; diff --git a/htdocs/recruitment/recruitmentjobposition_list.php b/htdocs/recruitment/recruitmentjobposition_list.php index 8a0d3f06540..4cb2d845828 100644 --- a/htdocs/recruitment/recruitmentjobposition_list.php +++ b/htdocs/recruitment/recruitmentjobposition_list.php @@ -593,13 +593,11 @@ while ($i < $imaxinloop) { print ''; print '
'; } - if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - if ($massactionbutton || $massaction) { - $selected = 0; - } - // Output Kanban - print $object->getKanbanView(''); + if ($massactionbutton || $massaction) { + $selected = 0; } + // Output Kanban + print $object->getKanbanView(''); if ($i == ($imaxinloop - 1)) { print '
'; print ''; diff --git a/htdocs/resource/element_resource.php b/htdocs/resource/element_resource.php index f69b82727f0..d1631d94d94 100644 --- a/htdocs/resource/element_resource.php +++ b/htdocs/resource/element_resource.php @@ -541,7 +541,7 @@ if (!$ret) { if (isModEnabled('project')) { $langs->load("projects"); $morehtmlref .= '
'.$langs->trans('Project').' '; - if ($user->rights->commande->creer) { + if ($user->hasRight('commande', 'creer')) { if ($action != 'classify') { //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; $morehtmlref .= ' : '; diff --git a/htdocs/salaries/class/salary.class.php b/htdocs/salaries/class/salary.class.php index 90666a6853d..7192a14e9d3 100644 --- a/htdocs/salaries/class/salary.class.php +++ b/htdocs/salaries/class/salary.class.php @@ -770,7 +770,7 @@ class Salary extends CommonObject $return .= '
'.$langs->trans("Amount").' : '.price($this->amount).''; } if (method_exists($this, 'LibStatut')) { - $return .= '
'.$this->LibStatut($this->paye, 5, $this->alreadypaid).'
'; + $return .= '
'.$this->getLibStatut(3, $this->alreadypaid).'
'; } $return .= '
'; $return .= '
'; diff --git a/htdocs/salaries/list.php b/htdocs/salaries/list.php index 35e82e96da1..7ef8db376b7 100644 --- a/htdocs/salaries/list.php +++ b/htdocs/salaries/list.php @@ -537,7 +537,8 @@ $totalarray = array(); $totalarray['nbfield'] = 0; $totalarray['val'] = array(); $totalarray['val']['totalttcfield'] = 0; -while ($i < ($limit ? min($num, $limit) : $num)) { +$imaxinloop = ($limit ? min($num, $limit) : $num); +while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); if (empty($obj)) { break; // Should not happen @@ -574,7 +575,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } // Output Kanban print $salstatic->getKanbanView(''); - if ($i == (min($num, $limit) - 1)) { + if ($i == ($imaxinloop - 1)) { print ''; print ''; } diff --git a/htdocs/salaries/payments.php b/htdocs/salaries/payments.php index 807ae82f9af..15b50c6dfc3 100644 --- a/htdocs/salaries/payments.php +++ b/htdocs/salaries/payments.php @@ -534,7 +534,7 @@ $i = 0; $total = 0; $totalarray = array(); $totalarray['nbfield'] = 0; -while ($i < ($limit ? min($num, $limit) : $num)) { +while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); if (empty($obj)) { break; @@ -544,8 +544,6 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // Store properties in $object $object->setVarsFromFetchObj($obj); - - $userstatic->id = $obj->uid; $userstatic->lastname = $obj->lastname; $userstatic->firstname = $obj->firstname; @@ -570,18 +568,14 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $paymentsalstatic->fk_bank = $accountlinestatic->getNomUrl(1); $paymentsalstatic->fk_user_author = $userstatic->getNomUrl(1); - - if ($mode == 'kanban') { if ($i == 0) { print ''; print '
'; } // Output Kanban - - print $paymentsalstatic->getKanbanView(''); - if ($i == (min($num, $limit) - 1)) { + if ($i == ($imaxinloop - 1)) { print '
'; print ''; } diff --git a/htdocs/societe/agenda.php b/htdocs/societe/agenda.php index dbf006f840c..67f087f9774 100644 --- a/htdocs/societe/agenda.php +++ b/htdocs/societe/agenda.php @@ -205,7 +205,6 @@ if ($socid > 0) { $cachekey = 'count_events_thirdparty_'.$object->id; $nbEvent = dol_getcache($cachekey); - // print load_fiche_titre($langs->trans("ActionsOnCompany"), $newcardbutton, ''); print_barre_liste($langs->trans("ActionsOnCompany").(is_numeric($nbEvent) ? '('.$nbEvent.')': ''), 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1); // List of all actions diff --git a/htdocs/societe/canvas/actions_card_common.class.php b/htdocs/societe/canvas/actions_card_common.class.php index fc8794aa1a8..a2b320e50db 100644 --- a/htdocs/societe/canvas/actions_card_common.class.php +++ b/htdocs/societe/canvas/actions_card_common.class.php @@ -70,6 +70,8 @@ abstract class ActionsCardCommon $object->fetch($id, $ref); } $this->object = $object; + + return $object; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index 68bba46a3cb..88e9398f5fa 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -225,11 +225,10 @@ class Contacts extends DolibarrApi // Add sql filters if ($sqlfilters) { $errormessage = ''; - if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); + if ($errormessage) { + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index 1a1b3818848..8552f257fcc 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -204,11 +204,10 @@ class Thirdparties extends DolibarrApi // Add sql filters if ($sqlfilters) { $errormessage = ''; - if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage); + if ($errormessage) { + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; - $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 01f35b9ea17..6ae3cad817a 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -5225,7 +5225,7 @@ class Societe extends CommonObject } if (method_exists($this, 'getLibStatut')) { - $return .= '
'.$this->getLibStatut(5).'
'; + $return .= '
'.$this->getLibStatut(3).'
'; } $return .= ''; $return .= ''; diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 68304f2b119..085bc0d2532 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -1356,135 +1356,135 @@ $totalarray['nbfield'] = 0; print ''; if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch actioncolumn '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.rowid']['checked'])) { print_liste_field_titre($arrayfields['s.rowid']['label'], $_SERVER["PHP_SELF"], "s.rowid", "", $param, ' data-key="id"', $sortfield, $sortorder, 'actioncolumn '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.nom']['checked'])) { print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, ' data-key="ref"', $sortfield, $sortorder, 'actioncolumn '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.name_alias']['checked'])) { print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", "", $param, "", $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.barcode']['checked'])) { print_liste_field_titre($arrayfields['s.barcode']['label'], $_SERVER["PHP_SELF"], "s.barcode", $param, '', '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.code_client']['checked'])) { print_liste_field_titre($arrayfields['s.code_client']['label'], $_SERVER["PHP_SELF"], "s.code_client", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.code_fournisseur']['checked'])) { print_liste_field_titre($arrayfields['s.code_fournisseur']['label'], $_SERVER["PHP_SELF"], "s.code_fournisseur", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.code_compta']['checked'])) { print_liste_field_titre($arrayfields['s.code_compta']['label'], $_SERVER["PHP_SELF"], "s.code_compta", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.code_compta_fournisseur']['checked'])) { print_liste_field_titre($arrayfields['s.code_compta_fournisseur']['label'], $_SERVER["PHP_SELF"], "s.code_compta_fournisseur", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.address']['checked'])) { print_liste_field_titre($arrayfields['s.address']['label'], $_SERVER['PHP_SELF'], 's.address', '', $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.zip']['checked'])) { print_liste_field_titre($arrayfields['s.zip']['label'], $_SERVER["PHP_SELF"], "s.zip", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.town']['checked'])) { print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], "s.town", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['state.nom']['checked'])) { print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['region.nom']['checked'])) { print_liste_field_titre($arrayfields['region.nom']['label'], $_SERVER["PHP_SELF"], "region.nom", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['country.code_iso']['checked'])) { print_liste_field_titre($arrayfields['country.code_iso']['label'], $_SERVER["PHP_SELF"], "country.code_iso", "", $param, '', $sortfield, $sortorder, 'center '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['typent.code']['checked'])) { print_liste_field_titre($arrayfields['typent.code']['label'], $_SERVER["PHP_SELF"], "typent.code", "", $param, "", $sortfield, $sortorder, 'center '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['staff.code']['checked'])) { print_liste_field_titre($arrayfields['staff.code']['label'], $_SERVER["PHP_SELF"], "staff.code", "", $param, '', $sortfield, $sortorder, 'center '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.price_level']['checked'])) { print_liste_field_titre($arrayfields['s.price_level']['label'], $_SERVER["PHP_SELF"], "s.price_level", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.email']['checked'])) { print_liste_field_titre($arrayfields['s.email']['label'], $_SERVER["PHP_SELF"], "s.email", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.phone']['checked'])) { print_liste_field_titre($arrayfields['s.phone']['label'], $_SERVER["PHP_SELF"], "s.phone", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.fax']['checked'])) { print_liste_field_titre($arrayfields['s.fax']['label'], $_SERVER["PHP_SELF"], "s.fax", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.url']['checked'])) { print_liste_field_titre($arrayfields['s.url']['label'], $_SERVER["PHP_SELF"], "s.url", "", $param, '', $sortfield, $sortorder); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.siren']['checked'])) { print_liste_field_titre($form->textwithpicto($langs->trans("ProfId1Short"), $textprofid[1], 1, 0), $_SERVER["PHP_SELF"], "s.siren", "", $param, '', $sortfield, $sortorder, 'nowrap '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.siret']['checked'])) { print_liste_field_titre($form->textwithpicto($langs->trans("ProfId2Short"), $textprofid[2], 1, 0), $_SERVER["PHP_SELF"], "s.siret", "", $param, '', $sortfield, $sortorder, 'nowrap '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.ape']['checked'])) { print_liste_field_titre($form->textwithpicto($langs->trans("ProfId3Short"), $textprofid[3], 1, 0), $_SERVER["PHP_SELF"], "s.ape", "", $param, '', $sortfield, $sortorder, 'nowrap '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.idprof4']['checked'])) { print_liste_field_titre($form->textwithpicto($langs->trans("ProfId4Short"), $textprofid[4], 1, 0), $_SERVER["PHP_SELF"], "s.idprof4", "", $param, '', $sortfield, $sortorder, 'nowrap '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.idprof5']['checked'])) { print_liste_field_titre($form->textwithpicto($langs->trans("ProfId5Short"), $textprofid[5], 1, 0), $_SERVER["PHP_SELF"], "s.idprof5", "", $param, '', $sortfield, $sortorder, 'nowrap '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.idprof6']['checked'])) { print_liste_field_titre($form->textwithpicto($langs->trans("ProfId6Short"), $textprofid[6], 1, 0), $_SERVER["PHP_SELF"], "s.idprof6", "", $param, '', $sortfield, $sortorder, 'nowrap '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.tva_intra']['checked'])) { print_liste_field_titre($arrayfields['s.tva_intra']['label'], $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder, 'nowrap '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['customerorsupplier']['checked'])) { print_liste_field_titre($arrayfields['customerorsupplier']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'center '); // type of customer - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.fk_prospectlevel']['checked'])) { print_liste_field_titre($arrayfields['s.fk_prospectlevel']['label'], $_SERVER["PHP_SELF"], "s.fk_prospectlevel", "", $param, '', $sortfield, $sortorder, 'center '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s.fk_stcomm']['checked'])) { print_liste_field_titre($arrayfields['s.fk_stcomm']['label'], $_SERVER["PHP_SELF"], "s.fk_stcomm", "", $param, '', $sortfield, $sortorder, 'center '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } if (!empty($arrayfields['s2.nom']['checked'])) { print_liste_field_titre($arrayfields['s2.nom']['label'], $_SERVER["PHP_SELF"], "s2.nom", "", $param, '', $sortfield, $sortorder, 'center '); - $totalarray['nbfield']++; // For the column action + $totalarray['nbfield']++; } // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 93755dbbd4d..54b8b1e22f1 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -1144,14 +1144,14 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' } print ''.img_picto($langs->trans('ShowInStripe').' - Customer and Publishable key = '.$companypaymentmodetemp->stripe_account, 'globe').' '; } - print $companypaymentmodetemp->stripe_card_ref; + print dol_escape_htmltag($companypaymentmodetemp->stripe_card_ref); print ''; // Type print ''; print img_credit_card($companypaymentmodetemp->type); print ''; // Information (Owner, ...) - print ''; + print ''; if ($companypaymentmodetemp->proprio) { print ''.$companypaymentmodetemp->proprio.'
'; } @@ -1161,7 +1161,9 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' if ($companypaymentmodetemp->exp_date_month || $companypaymentmodetemp->exp_date_year) { print ' - '.sprintf("%02d", $companypaymentmodetemp->exp_date_month).'/'.$companypaymentmodetemp->exp_date_year; } - print ''; + print ''; + // Country + print ''; if ($companypaymentmodetemp->country_code) { $img = picto_from_langcode($companypaymentmodetemp->country_code); print $img ? $img.' ' : ''; @@ -1180,12 +1182,13 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print img_picto($langs->trans("Default"), 'on'); } print ''; - print ''; if (empty($companypaymentmodetemp->stripe_card_ref)) { - print $langs->trans("Local"); + $s = $langs->trans("Local"); } else { - print $langs->trans("LocalAndRemote"); + $s = $langs->trans("LocalAndRemote"); } + print ''; + print $s; print ''; print ''; print dol_print_date($companypaymentmodetemp->tms, 'dayhour'); @@ -1195,7 +1198,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column - print ''; + print ''; if ($permissiontoaddupdatepaymentinformation) { if ($stripecu && empty($companypaymentmodetemp->stripe_card_ref)) { print ''.$langs->trans("CreateCardOnStripe").''; @@ -1361,7 +1364,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' if ($nbremote == 0 && $nblocal == 0) { $colspan = (!empty($conf->global->STRIPE_ALLOW_LOCAL_CARD) ? 10 : 9); - print ''.$langs->trans("None").''; + print ''.$langs->trans("None").''; } print ""; print ""; @@ -1480,7 +1483,6 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' // Bank name print ''.dol_escape_htmltag($rib->bank).''; // Account number - print ''; $string = ''; foreach ($rib->getFieldsToShow() as $val) { if ($val == 'BankCode') { @@ -1506,7 +1508,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' $string .= ' '.img_picto($langs->trans("ValueIsValid"), 'info'); } } - + print ''; print $string; print ''; // IBAN diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 11fb6c6e442..eb8c36fe4ba 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -232,8 +232,11 @@ if (empty($conf->stripeconnect->enabled)) { print '
'; } print ''; - $out = img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForTestWebhook").' '; - $url = dol_buildpath('/public/stripe/ipn.php?test', 3); + $out = img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForTestWebhook").' '; + $url = dol_buildpath('/public/stripe/ipn.php', 3); + $url .= '?test=1'; + //global $dolibarr_main_instance_unique_id; + //$url .= '&securitykey='.dol_hash('stripeipn-'.$dolibarr_main_instance_unique_id.'-'.$conf->global->STRIPE_TEST_PUBLISHABLE_KEY, 'md5'); $out .= ''; $out .= ajax_autoselect("onlinetestwebhookurl", 0); print '
'.$out; @@ -250,7 +253,7 @@ if (empty($conf->stripeconnect->enabled)) { $endpoint->disabled = false; } } - $endpoint->url = dol_buildpath('/public/stripe/ipn.php?test', 3); + $endpoint->url = $url; $endpoint->save(); if ($endpoint->status == 'enabled') { print ''; @@ -296,6 +299,8 @@ if (empty($conf->stripeconnect->enabled)) { print ''; $out = img_picto('', 'globe', 'class="pictofixedwidth"').' '.$langs->trans("ToOfferALinkForLiveWebhook").' '; $url = dol_buildpath('/public/stripe/ipn.php', 3); + //global $dolibarr_main_instance_unique_id; + //$url .= '?securitykey='.dol_hash('stripeipn-'.$dolibarr_main_instance_unique_id.'-'.$conf->global->STRIPE_LIVE_PUBLISHABLE_KEY, 'md5'); $out .= ''; $out .= ajax_autoselect("onlinelivewebhookurl", 0); print '
'.$out; @@ -312,7 +317,7 @@ if (empty($conf->stripeconnect->enabled)) { $endpoint->disabled = false; } } - $endpoint->url = dol_buildpath('/public/stripe/ipn.php', 3); + $endpoint->url = $url; $endpoint->save(); if ($endpoint->status == 'enabled') { print '
'; diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 7f66ae05383..732c4a57326 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -341,9 +341,10 @@ class Stripe extends CommonObject * @param string $payment_method 'pm_....' (if known) * @param string $off_session If we use an already known payment method to pay when customer is not available during the checkout flow. * @param string $noidempotency_key Do not use the idempotency_key when creating the PaymentIntent + * @param int $did ID of an existing line into llx_prelevement_demande (Dolibarr intent). If provided, no new line will be created. * @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found and failed to create */ - public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false, $payment_method = null, $off_session = 0, $noidempotency_key = 1) + public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false, $payment_method = null, $off_session = 0, $noidempotency_key = 1, $did = 0) { global $conf, $user; @@ -364,11 +365,14 @@ class Stripe extends CommonObject $stripeamount = $amount; } - $fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE; - if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) { - $fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL; - } elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) { - $fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL; + $fee = 0; + if (getDolGlobalString("STRIPE_APPLICATION_FEE_PERCENT")) { + $fee = $amount * ((float) getDolGlobalString("STRIPE_APPLICATION_FEE_PERCENT", '0') / 100) + (float) getDolGlobalString("STRIPE_APPLICATION_FEE", '0'); + } + if ($fee >= (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0') && (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0') > (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0')) { + $fee = (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MAXIMAL", '0'); + } elseif ($fee < (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0')) { + $fee = (float) getDolGlobalString("STRIPE_APPLICATION_FEE_MINIMAL", '0'); } if (!in_array($currency_code, $arrayzerounitcurrency)) { $stripefee = round($fee * 100); @@ -530,29 +534,50 @@ class Stripe extends CommonObject // Store the payment intent if (is_object($object)) { $paymentintentalreadyexists = 0; - // Check that payment intent $paymentintent->id is not already recorded. - $sql = "SELECT pi.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pi"; - $sql .= " WHERE pi.entity IN (".getEntity('societe').")"; - $sql .= " AND pi.ext_payment_site = '".$this->db->escape($service)."'"; - $sql .= " AND pi.ext_payment_id = '".$this->db->escape($paymentintent->id)."'"; - dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG); - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - if ($num) { - $obj = $this->db->fetch_object($resql); - if ($obj) { - $paymentintentalreadyexists++; - } + if ($did > 0) { + // If a payment request line provided, we do not need to recreate one, we just update it + dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG); + + $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande SET"; + $sql .= " ext_payment_site = '".$this->db->escape($service)."',"; + $sql .= " ext_payment_id = '".$this->db->escape($paymentintent->id)."'"; + $sql .= " WHERE rowid = ".((int) $did); + + $resql = $this->db->query($sql); + if ($resql) { + $paymentintentalreadyexists++; + } else { + $error++; + dol_print_error($this->db); } } else { - dol_print_error($this->db); + // Check that payment intent $paymentintent->id is not already recorded. + dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_demande", LOG_DEBUG); + + $sql = "SELECT pi.rowid"; + $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_demande as pi"; + $sql .= " WHERE pi.entity IN (".getEntity('societe').")"; + $sql .= " AND pi.ext_payment_site = '".$this->db->escape($service)."'"; + $sql .= " AND pi.ext_payment_id = '".$this->db->escape($paymentintent->id)."'"; + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num) { + $obj = $this->db->fetch_object($resql); + if ($obj) { + $paymentintentalreadyexists++; + } + } + } else { + $error++; + dol_print_error($this->db); + } } // If not, we create it. - if (!$paymentintentalreadyexists) { + if (!$error && !$paymentintentalreadyexists) { $now = dol_now(); $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site, amount)"; $sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $user->id).", '".$this->db->escape($paymentintent->id)."', ".((int) $object->id).", '".$this->db->escape($object->element)."', ".((int) $conf->entity).", '".$this->db->escape($service)."', ".((float) $amount).")"; @@ -1015,7 +1040,9 @@ class Stripe extends CommonObject dol_syslog("Try to create sepa_debit with data = ".json_encode($dataforcard)); $s = new \Stripe\StripeClient($stripeacc); + //var_dump($dataforcard);exit; + $sepa = $s->paymentMethods->create($dataforcard); if (!$sepa) { $this->error = 'Creation of payment method sepa_debit on Stripe has failed'; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 3887060d8a9..9baa56d8193 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1269,7 +1269,7 @@ if ($action == 'create') { print ''; } else { print ''; - print img_picto('', 'company').$form->select_company('', 'socid', 's.fournisseur=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300'); + print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', 's.fournisseur=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300'); // reload page to retrieve customer informations if (!empty($conf->global->RELOAD_PAGE_ON_SUPPLIER_CHANGE)) { print '