diff --git a/ChangeLog b/ChangeLog
index 68ce6daabcd..0fe697ccb6c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -30,20 +30,20 @@ NEW: #21000 Added columns 'alias_name' on project, supplier invoice, supplier or
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
+NEW: #21399 add image for event_array
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
-NEW: #22424
+NEW: #22328 OAuth admin
+NEW: #22424 online signature for contracts
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: #22735 massaction to affect users on projects
NEW: #25594 can chose if VAT ID is unique or not for third parties
NEW: #4482 adding js to hide/show advanced option on the export data page
@@ -57,27 +57,17 @@ 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 objectLink on expedition
-NEW: Add oldcopy to Ticket so triggers intercepting TICKET_MODIFY have access to old values of the updated properties
NEW: Add option --force on CLI cron_run_jobs.php
NEW: Add option "Show price on the generated documents for receptions"
-NEW: invoice export : add accounting affectation
-NEW: label on products categories filter
-NEW: manage no email with thirdparties (better for GDPR)
NEW: Manage VAT on all lines on purchases cycle
-NEW: On a bank reconciled line, we can modify the bank receipt
NEW: parent company column and filter in invoice and order list
-NEW: possibility to select scopes with checkbox for Oauth tokens
-NEW: private and public note on user, thirdparty and contact list
+NEW: private and public note columns on user, thirdparty and contact lists
NEW: Public counters feature
-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: experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP)
NEW: can substitue project title in mail template
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: Finance - VAT - Admin - Add information on deadline day for submission of VAT declaration
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.
@@ -87,17 +77,18 @@ 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: can sort and preselected best supplier price
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 - 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
@@ -108,22 +99,29 @@ 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: Export - Add " as enclosure by default for CSV export. Keep removing CR/LF.
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: 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 - 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 supplier price - autofill default supplier VAT
+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
@@ -144,8 +142,10 @@ 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.
@@ -176,11 +176,16 @@ 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:
@@ -235,7 +240,10 @@ Following changes may create regressions for some external modules, but were nec
* Deprecated method set_billed() on shipment and reception class has been removed. Use setBilled() instead.
* Tables llx_prelevement_facture and llx_prelevement_facture_demande have been renamed into llx_prelevement and llx_prelevement_demande.
* Rename MAIN_LIST_ALLOW_NOTES into MAIN_LIST_HIDE_NOTES and rename MAIN_LIST_ALLOW_PRIVATE_NOTES into MAIN_LIST_HIDE_PRIVATE_NOTES
-* Rename the substitution for project label instead of project title in substitution variables
+* 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)
+
***** ChangeLog for 16.0.4 compared to 16.0.3 *****
@@ -243,23 +251,24 @@ Following changes may create regressions for some external modules, but were nec
FIX: Amount of localtax1 and 2 not correctly save on purchase order (the rate was saved instead)
FIX: #20415
FIX: #21280
-FIX: #23008
FIX: #22271
FIX: #22524
FIX: #22837
FIX: #22964
+FIX: #23008
FIX: #23012
FIX: #23019 Impossible to add task times to an existing draft invoice
FIX: #23072
+FIX: #23075
FIX: #23087
FIX: #23115
FIX: #23116
+FIX: #23117
FIX: #23281
FIX: #23420 : wrong check on $search_categ value causing FATAL ERROR
FIX: Accountancy - Quadra export
FIX: add border left on image product when conf activated
FIX: Add missing token when deleting template inn order_supplier admin menu
-FIX: Amount of localtax1 and 2 not correctly save on purchase order (the
FIX: API access for deactivated users
FIX: bad selection of barcode numbering module
FIX: Can't see all time spent by all user
@@ -270,8 +279,6 @@ FIX: Empty FormSetup emailTemplate type IF empty fieldvalue
FIX: Errors Handling for CreateFrom Hooks
FIX: error with dol_banner_tab, ref is needed
FIX: ExpenseReport card was not reloaded after addline
-FIX: #23075
-FIX: #23117
FIX: get multicurrency infos of propal when create order from propal with "WORKFLOW_PROPAL_AUTOCREATE_ORDER" conf
FIX: Give predictable order to inventory lines
FIX: include class multicurrency
@@ -279,7 +286,6 @@ FIX: methods declaration (backport fix 67b9a7dc07d708231d12b5e58800334d4a01ef98)
FIX: multicurrency_tx and not currency_tx
FIX: on public ticket list, only the page 1 was accessible. Other pages were 404 error.
FIX: PGSQL Integer type does not have a free lenght
-FIX: PGSQL Int type does not have a free lenght
FIX: Product list in setup.php in new Module
FIX: propal and order stats broken on Tag+User(retricted customer list)
FIX: saving of numbering module for jobs
diff --git a/dev/setup/apache/virtualhost b/dev/setup/apache/virtualhost
index e8c5f2a8f4b..7eff1859d4f 100644
--- a/dev/setup/apache/virtualhost
+++ b/dev/setup/apache/virtualhost
@@ -12,6 +12,7 @@
+ # The URLs of the web site
ServerName myvirtualalias
ServerAlias myvirtualalias
@@ -23,8 +24,13 @@
AddDefaultCharset UTF-8
- DocumentRoot "/home/.../htdocs"
+ # Detect if we are using DoliDroid
+ #SetEnvIf User-Agent DoliDroid dolidroid
+
+
+ # The directory and permissions for the web site
+ DocumentRoot "/home/.../htdocs"
AllowOverride None
Options -Indexes -MultiViews +FollowSymLinks -ExecCGI
@@ -40,39 +46,43 @@
# Leaving /public and /api, /dav, .well_known but also wrappers for document, viewimage and public json/img accessible to everyone
AuthType None
- Require all granted
Satisfy any
+ Require all granted
AuthType None
- Require all granted
Satisfy any
+ Require all granted
AuthType None
- Require all granted
Satisfy any
+ Require all granted
AuthType None
- Require all granted
Satisfy any
+ Require all granted
AuthType None
- Require all granted
Satisfy any
+ Require all granted
-
+
+ # Log directoves
ErrorLog /var/log/apache2/myvirtualalias_error_log
TransferLog /var/log/apache2/myvirtualalias_access_log
- # Compress returned resources of type php pages, text file export, css and javascript
+
+ # Compress is done on resources of type php pages, text file export, css and javascript
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript
-
AddType text/javascript .jgz
AddEncoding gzip .jgz
+
+
+ # Add cach performance directives
ExpiresActive On
ExpiresByType image/x-icon A2592000
ExpiresByType image/gif A2592000
@@ -83,19 +93,20 @@
ExpiresByType application/x-javascript A2592000
ExpiresByType application/javascript A2592000
- SSLEngine On
- # A self-signed (snakeoil) certificate can be created by installing
- # the ssl-cert package. See
- # /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
- # If both key and certificate are stored in the same file, only the
- # SSLCertificateFile directive is needed.
- #SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/cert.pem
- #SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem
- #SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.com/chain.pem
+ # To enable the SSL if the certificate file exists
+
+ SSLEngine On
+
+ # If both key and certificate are stored in the same file, only the
+ # SSLCertificateFile directive is needed.
+ SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/cert.pem
+ SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem
+ SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.com/chain.pem
+
+ #RewriteEngine on
+ #RewriteCond %{SERVER_PORT} ^80$
+ #RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]
+
- #RewriteEngine on
- #RewriteCond %{SERVER_PORT} ^80$
- #RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]
-
diff --git a/htdocs/adherents/admin/website.php b/htdocs/adherents/admin/website.php
index 14379166247..0ba5641b149 100644
--- a/htdocs/adherents/admin/website.php
+++ b/htdocs/adherents/admin/website.php
@@ -58,7 +58,7 @@ if ($action == 'setMEMBER_ENABLE_PUBLIC') {
if ($action == 'update') {
$public = GETPOST('MEMBER_ENABLE_PUBLIC');
$amount = price2num(GETPOST('MEMBER_NEWFORM_AMOUNT'), 'MT', 2);
- $editamount = GETPOST('MEMBER_NEWFORM_EDITAMOUNT');
+ $minamount = GETPOST('MEMBER_MIN_AMOUNT');
$publiccounters = GETPOST('MEMBER_COUNTERS_ARE_PUBLIC');
$payonline = GETPOST('MEMBER_NEWFORM_PAYONLINE');
$forcetype = GETPOST('MEMBER_NEWFORM_FORCETYPE', 'int');
@@ -66,7 +66,7 @@ if ($action == 'update') {
$res = dolibarr_set_const($db, "MEMBER_ENABLE_PUBLIC", $public, 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "MEMBER_NEWFORM_AMOUNT", $amount, 'chaine', 0, '', $conf->entity);
- $res = dolibarr_set_const($db, "MEMBER_NEWFORM_EDITAMOUNT", $editamount, 'chaine', 0, '', $conf->entity);
+ $res = dolibarr_set_const($db, "MEMBER_MIN_AMOUNT", $minamount, 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "MEMBER_COUNTERS_ARE_PUBLIC", $publiccounters, 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "MEMBER_NEWFORM_PAYONLINE", $payonline, 'chaine', 0, '', $conf->entity);
if ($forcetype < 0) {
@@ -232,11 +232,11 @@ if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) {
print '';
print "\n";
- // Can edit
+ // Min amount
print '
\n";
diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php
index b9963b1e16c..b44d22da312 100644
--- a/htdocs/contact/class/contact.class.php
+++ b/htdocs/contact/class/contact.class.php
@@ -133,6 +133,11 @@ class Contact extends CommonObject
public $civility_code;
public $civility;
+ /**
+ * @var string gender
+ */
+ public $gender;
+
/**
* @var int egroupware_id
*/
@@ -193,6 +198,11 @@ class Contact extends CommonObject
public $socid; // both socid and fk_soc are used
public $fk_soc; // both socid and fk_soc are used
+ /**
+ * @var string thirdparty name
+ */
+ public $socname;
+
/**
* @var int 0=inactive, 1=active
*/
@@ -206,6 +216,14 @@ class Contact extends CommonObject
*/
public $email;
+ /**
+ * Email
+ * @var string
+ * @deprecated
+ * @see $email
+ */
+ public $mail;
+
/**
* URL
* @var string
@@ -1045,12 +1063,12 @@ class Contact extends CommonObject
$this->country_id = $obj->country_id;
$this->country_code = $obj->country_id ? $obj->country_code : '';
- $this->country = $obj->country_id ? ($langs->trans('Country'.$obj->country_code) != 'Country'.$obj->country_code ? $langs->transnoentities('Country'.$obj->country_code) : $obj->country) : '';
+ $this->country = $obj->country_id ? ($langs->trans('Country'.$obj->country_code) != 'Country'.$obj->country_code ? $langs->transnoentities('Country'.$obj->country_code) : $obj->country) : '';
- $this->fk_soc = $obj->fk_soc; // Both fk_soc and socid are used
- $this->socid = $obj->fk_soc; // Both fk_soc and socid are used
- $this->socname = $obj->socname;
- $this->poste = $obj->poste;
+ $this->fk_soc = $obj->fk_soc; // Both fk_soc and socid are used
+ $this->socid = $obj->fk_soc; // Both fk_soc and socid are used
+ $this->socname = $obj->socname;
+ $this->poste = $obj->poste;
$this->statut = $obj->statut;
$this->fk_prospectlevel = $obj->fk_prospectlevel;
@@ -1066,22 +1084,22 @@ class Contact extends CommonObject
$this->phone_perso = trim($obj->phone_perso);
$this->phone_mobile = trim($obj->phone_mobile);
- $this->email = $obj->email;
+ $this->email = $obj->email;
$this->socialnetworks = ($obj->socialnetworks ? (array) json_decode($obj->socialnetworks, true) : array());
- $this->photo = $obj->photo;
- $this->priv = $obj->priv;
- $this->mail = $obj->email;
+ $this->photo = $obj->photo;
+ $this->priv = $obj->priv;
+ $this->mail = $obj->email;
$this->birthday = $this->db->jdate($obj->birthday);
- $this->note = $obj->note_private; // deprecated
- $this->note_private = $obj->note_private;
+ $this->note = $obj->note_private; // deprecated
+ $this->note_private = $obj->note_private;
$this->note_public = $obj->note_public;
- $this->default_lang = $obj->default_lang;
+ $this->default_lang = $obj->default_lang;
$this->user_id = $obj->user_id;
- $this->user_login = $obj->user_login;
+ $this->user_login = $obj->user_login;
$this->canvas = $obj->canvas;
- $this->import_key = $obj->import_key;
+ $this->import_key = $obj->import_key;
// Define gender according to civility
$this->setGenderFromCivility();
@@ -1404,6 +1422,52 @@ class Contact extends CommonObject
}
}
+ /**
+ * getTooltipContentArray
+ * @param array $params params to construct tooltip data
+ * @since v18
+ * @return array
+ */
+ public function getTooltipContentArray($params)
+ {
+ global $conf, $langs, $user;
+
+ $datas = [];
+
+ if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
+ return ['optimize' => $langs->trans("ShowContact")];
+ }
+ if (!empty($this->photo) && class_exists('Form')) {
+ $photo = '
';
+ $photo .= Form::showphoto('contact', $this, 0, 40, 0, 'photoref', 'mini', 0); // Important, we must force height so image will have height tags and if image is inside a tooltip, the tooltip manager can calculate height and position correctly the tooltip.
+ $photo .= '
';
- $label .= Form::showphoto('contact', $this, 0, 40, 0, 'photoref', 'mini', 0); // Important, we must force height so image will have height tags and if image is inside a tooltip, the tooltip manager can calculate height and position correctly the tooltip.
- $label .= '
';
- //$label .= '';
+ $result = '';
+ $params = [
+ 'id' => $this->id,
+ 'objecttype' => $this->element,
+ 'option' => $option,
+ ];
+ $classfortooltip = 'classfortooltip';
+ $dataparams = '';
+ if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
+ $classfortooltip = 'classforajaxtooltip';
+ $dataparams = ' data-params='.json_encode($params);
+ // $label = $langs->trans('Loading');
}
-
- $label .= img_picto('', $this->picto).' '.$langs->trans("Contact").'';
- $label .= ' '.$this->getLibStatut(4);
- $label .= ' '.$langs->trans("Name").': '.$this->getFullName($langs);
- //if ($this->civility_id) $label.= ' ' . $langs->trans("Civility") . ': '.$this->civility_id; // TODO Translate cibilty_id code
- if (!empty($this->poste)) {
- $label .= ' '.$langs->trans("Poste").': '.$this->poste;
- }
- $label .= ' '.$langs->trans("EMail").': '.$this->email;
- $phonelist = array();
- $country_code = empty($this->country_code) ? '': $this->country_code;
- if ($this->phone_pro) {
- $phonelist[] = dol_print_phone($this->phone_pro, $country_code, $this->id, 0, '', ' ', 'phone');
- }
- if ($this->phone_mobile) {
- $phonelist[] = dol_print_phone($this->phone_mobile, $country_code, $this->id, 0, '', ' ', 'mobile');
- }
- if ($this->phone_perso) {
- $phonelist[] = dol_print_phone($this->phone_perso, $country_code, $this->id, 0, '', ' ', 'phone');
- }
- $label .= ' '.$langs->trans("Phone").': '.implode(' ', $phonelist);
- $label .= ' '.$langs->trans("Address").': '.dol_format_address($this, 1, ' ', $langs);
+ $label = implode($this->getTooltipContentArray($params));
$url = DOL_URL_ROOT.'/contact/card.php?id='.$this->id;
@@ -1473,7 +1522,7 @@ class Contact extends CommonObject
$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
}
$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
- $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
+ $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
}
$linkstart = '';
if ($option == 'xxx') {
- $linkstart = '';
+ $linkstart = '';
$linkend = '';
}
@@ -1490,7 +1539,7 @@ class Contact extends CommonObject
if ($withpicto < 0) {
$result .= ''.Form::showphoto('contact', $this, 0, 0, 0, 'userphoto'.($withpicto == -3 ? 'small' : ''), 'mini', 0, 1).'';
} else {
- $result .= img_object(($notooltip ? '' : $label), ( $this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
+ $result .= img_object(($notooltip ? '' : $label), ( $this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1);
}
}
if ($withpicto != 2 && $withpicto != -2) {
diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php
index 6078e33cb6a..97b586a2cde 100644
--- a/htdocs/contrat/class/contrat.class.php
+++ b/htdocs/contrat/class/contrat.class.php
@@ -9,7 +9,7 @@
* Copyright (C) 2013 Florian Henry
* Copyright (C) 2014-2015 Marcos García
* Copyright (C) 2018 Nicolas ZABOURI
- * Copyright (C) 2018-2021 Frédéric France
+ * Copyright (C) 2018-2023 Frédéric France
* Copyright (C) 2015-2018 Ferran Marcet
*
* This program is free software; you can redistribute it and/or modify
@@ -185,6 +185,7 @@ class Contrat extends CommonObject
public $nbofserviceswait;
public $nbofservicesopened;
public $nbofservicesexpired;
+ public $nbofservicesclosed;
//public $lower_planned_end_date;
//public $higher_planner_end_date;
@@ -1981,6 +1982,42 @@ class Contrat extends CommonObject
}
}
+ /**
+ * getTooltipContentArray
+ * @param array $params params to construct tooltip data
+ * @since v18
+ * @return array
+ */
+ public function getTooltipContentArray($params)
+ {
+ global $conf, $langs, $user;
+
+ $datas = [];
+
+ if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
+ return ['optimize' => $langs->trans("ShowContract")];
+ }
+ if ($user->hasRight('contrat', 'lire')) {
+ $datas['picto'] = img_picto('', $this->picto).' '.$langs->trans("Contract").'';
+ /* Status of a contract is status of all services, so disabled
+ if (isset($this->statut)) {
+ $label .= ' '.$this->getLibStatut(5);
+ }*/
+ $datas['ref'] = ' '.$langs->trans('Ref').': '.($this->ref ? $this->ref : $this->id);
+ $datas['refcustomer'] = ' '.$langs->trans('RefCustomer').': '. $this->ref_customer;
+ $datas['refsupplier'] = ' '.$langs->trans('RefSupplier').': '.$this->ref_supplier;
+ if (!empty($this->total_ht)) {
+ $datas['amountht'] = ' '.$langs->trans('AmountHT').': '.price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
+ }
+ if (!empty($this->total_tva)) {
+ $datas['vatamount'] = ' '.$langs->trans('VAT').': '.price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
+ }
+ if (!empty($this->total_ttc)) {
+ $datas['amounttc'] = ' '.$langs->trans('AmountTTC').': '.price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
+ }
+ }
+ return $datas;
+ }
/**
* Return clicable name (with picto eventually)
@@ -2010,47 +2047,36 @@ class Contrat extends CommonObject
$url .= '&save_lastsearch_values=1';
}
//}
-
- $label = '';
-
- if ($user->rights->contrat->lire) {
- $label = img_picto('', $this->picto).' '.$langs->trans("Contract").'';
- /* Status of a contract is status of all services, so disabled
- if (isset($this->statut)) {
- $label .= ' '.$this->getLibStatut(5);
- }*/
- $label .= ' '.$langs->trans('Ref').': '.($this->ref ? $this->ref : $this->id);
- $ref_customer = (!empty($this->ref_customer) ? $this->ref_customer : (empty($this->ref_client) ? '' : $this->ref_client));
- $label .= ' '.$langs->trans('RefCustomer').': '.$ref_customer;
- $label .= ' '.$langs->trans('RefSupplier').': '.$this->ref_supplier;
- if (!empty($this->total_ht)) {
- $label .= ' '.$langs->trans('AmountHT').': '.price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
- }
- if (!empty($this->total_tva)) {
- $label .= ' '.$langs->trans('VAT').': '.price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
- }
- if (!empty($this->total_ttc)) {
- $label .= ' '.$langs->trans('AmountTTC').': '.price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
- }
+ $params = [
+ 'id' => $this->id,
+ 'objecttype' => $this->element,
+ ];
+ $classfortooltip = 'classfortooltip';
+ $dataparams = '';
+ if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
+ $classfortooltip = 'classforajaxtooltip';
+ $dataparams = ' data-params='.json_encode($params);
+ // $label = $langs->trans('Loading');
}
+ $label = implode($this->getTooltipContentArray($params));
+
$linkclose = '';
if (empty($notooltip) && $user->rights->contrat->lire) {
if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
- $label = $langs->trans("ShowOrder");
+ $label = $langs->trans("ShowContract");
$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
}
$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
- $linkclose .= ' class="classfortooltip"';
+ $linkclose .= $dataparams.' class="'.$classfortooltip.'"';
}
-
$linkstart = '';
$linkend = '';
$result .= $linkstart;
if ($withpicto) {
- $result .= img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
+ $result .= img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1);
}
if ($withpicto != 2) {
$result .= ($this->ref ? $this->ref : $this->id);
@@ -3072,7 +3098,26 @@ class ContratLigne extends CommonObjectLine
}
/**
- * Return clicable name (with picto eventually)
+ * getTooltipContentArray
+ * @param array $params params to construct tooltip data
+ * @since v18
+ * @return array
+ */
+ public function getTooltipContentArray($params)
+ {
+ global $conf, $langs, $user;
+
+ $datas = [];
+ $datas['label'] = $langs->trans("ShowContractOfService").': '.$this->label;
+ if (empty($datas['label'])) {
+ $datas['label'] = $this->description;
+ }
+
+ return $datas;
+ }
+
+ /**
+ * Return clicable name (with picto eventually) for ContratLigne
*
* @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
* @param int $maxlength Max length
@@ -3087,8 +3132,19 @@ class ContratLigne extends CommonObjectLine
if (empty($label)) {
$label = $this->description;
}
-
- $link = '';
+ $classfortooltip = 'classfortooltip';
+ $dataparams = '';
+ if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
+ $params = [
+ 'id' => $this->fk_contrat,
+ 'objecttype' => $this->element,
+ ];
+ $classfortooltip = 'classforajaxtooltip';
+ $dataparams = ' data-params='.json_encode($params);
+ // $label = $langs->trans('Loading');
+ }
+ $link = '';
$linkend = '';
$picto = 'service';
@@ -3097,7 +3153,7 @@ class ContratLigne extends CommonObjectLine
}
if ($withpicto) {
- $result .= ($link.img_object($label, $picto, 'class="classfortooltip"').$linkend);
+ $result .= ($link.img_object($label, $picto, $dataparams.' class="'.$classfortooltip.'"').$linkend);
}
if ($withpicto && $withpicto != 2) {
$result .= ' ';
diff --git a/htdocs/core/ajax/ajaxtooltip.php b/htdocs/core/ajax/ajaxtooltip.php
new file mode 100644
index 00000000000..60220a221ff
--- /dev/null
+++ b/htdocs/core/ajax/ajaxtooltip.php
@@ -0,0 +1,234 @@
+
+ * Copyright (C) 2018-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
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * \file htdocs/core/ajax/ajaxtooltip.php
+ * \ingroup tooltip
+ * \brief This script returns content of tooltip
+ */
+
+
+if (!defined('NOTOKENRENEWAL')) {
+ define('NOTOKENRENEWAL', 1); // Disables token renewal
+}
+if (!defined('NOREQUIREMENU')) {
+ define('NOREQUIREMENU', '1');
+}
+if (!defined('NOREQUIREHTML')) {
+ define('NOREQUIREHTML', '1');
+}
+if (!defined('NOREQUIREAJAX')) {
+ define('NOREQUIREAJAX', '1');
+}
+include '../../main.inc.php';
+include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+include_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
+
+top_httphead();
+
+// opensurvey as aZ09 id
+$id = GETPOST('id', 'aZ09');
+$objecttype = GETPOST('objecttype', 'aZ09');
+
+$html = '';
+$regs = array();
+$params = array();
+if (GETPOSTISSET('infologin')) {
+ $params['infologin'] = GETPOST('infologin', 'int');
+}
+if (GETPOSTISSET('option')) {
+ $params['option'] = GETPOST('option', 'restricthtml');
+}
+// If we ask a resource form external module (instead of default path)
+if (preg_match('/^([^@]+)@([^@]+)$/i', $objecttype, $regs)) {
+ $myobject = $regs[1];
+ $module = $regs[2];
+} else {
+ // Parse $objecttype (ex: project_task)
+ $module = $myobject = $objecttype;
+ if (preg_match('/^([^_]+)_([^_]+)/i', $objecttype, $regs)) {
+ $module = $regs[1];
+ $myobject = $regs[2];
+ }
+}
+
+// Generic case for $classpath
+$classpath = $module.'/class';
+
+// Special cases, to work with non standard path
+if ($objecttype == 'facture' || $objecttype == 'invoice') {
+ $langs->load('bills');
+ $classpath = 'compta/facture/class';
+ $module = 'facture';
+ $myobject = 'facture';
+} elseif ($objecttype == 'bank_account') {
+ $langs->loadLangs(['banks', 'compta']);
+ $classpath = 'compta/bank/class';
+ $module = 'banque';
+ $myobject = 'account';
+} elseif ($objecttype == 'category') {
+ $langs->loadLangs(['categories']);
+ $classpath = 'categories/class';
+ $module = 'categorie';
+ $myobject = 'categorie';
+} elseif ($objecttype == 'commande' || $objecttype == 'order') {
+ $langs->load('orders');
+ $classpath = 'commande/class';
+ $module = 'commande';
+ $myobject = 'commande';
+} elseif ($objecttype == 'propal') {
+ $langs->load('propal');
+ $classpath = 'comm/propal/class';
+} elseif ($objecttype == 'action') {
+ $langs->load('agenda');
+ $classpath = 'comm/action/class';
+ $module = 'agenda';
+ $myobject = 'actioncomm';
+} elseif ($objecttype == 'supplier_proposal') {
+ $langs->load('supplier_proposal');
+ $classpath = 'supplier_proposal/class';
+} elseif ($objecttype == 'shipping') {
+ $langs->load('sendings');
+ $classpath = 'expedition/class';
+ $myobject = 'expedition';
+ $module = 'expedition_bon';
+} elseif ($objecttype == 'delivery') {
+ $langs->load('deliveries');
+ $classpath = 'delivery/class';
+ $myobject = 'delivery';
+ $module = 'delivery_note';
+} elseif ($objecttype == 'contract') {
+ $langs->load('contracts');
+ $classpath = 'contrat/class';
+ $module = 'contrat';
+ $myobject = 'contrat';
+} elseif ($objecttype == 'member') {
+ $langs->load('members');
+ $classpath = 'adherents/class';
+ $module = 'adherent';
+ $myobject = 'adherent';
+} elseif ($objecttype == 'fichinter') {
+ $langs->load('interventions');
+ $classpath = 'fichinter/class';
+ $module = 'ficheinter';
+ $myobject = 'fichinter';
+} elseif ($objecttype == 'project') {
+ $langs->load('projects');
+ $classpath = 'projet/class';
+ $module = 'projet';
+} elseif ($objecttype == 'project_task') {
+ $classpath = 'projet/class';
+ $module = 'projet';
+ $myobject = 'task';
+} elseif ($objecttype == 'stock') {
+ $classpath = 'product/stock/class';
+ $module = 'stock';
+ $myobject = 'stock';
+} elseif ($objecttype == 'inventory') {
+ $classpath = 'product/inventory/class';
+ $module = 'stock';
+ $myobject = 'inventory';
+} elseif ($objecttype == 'mo') {
+ $classpath = 'mrp/class';
+ $module = 'mrp';
+ $myobject = 'mo';
+} elseif ($objecttype == 'productlot') {
+ $classpath = 'product/stock/class';
+ $module = 'stock';
+ $myobject = 'productlot';
+} elseif ($objecttype == 'usergroup') {
+ $classpath = 'user/class';
+ $module = 'user';
+ $myobject = 'usergroup';
+} elseif ($objecttype == 'dolresource') {
+ $classpath = 'resource/class';
+ $module = 'resource';
+ $myobject = 'dolresource';
+} elseif ($objecttype == 'opensurvey_sondage') {
+ $classpath = 'opensurvey/class';
+ $module = 'opensurvey';
+ $myobject = 'opensurveysondage';
+}
+
+// Generic case for $classfile and $classname
+$classfile = strtolower($myobject);
+$classname = ucfirst($myobject);
+
+if ($objecttype == 'invoice_supplier') {
+ $classfile = 'fournisseur.facture';
+ $classname = 'FactureFournisseur';
+ $classpath = 'fourn/class';
+ $module = 'fournisseur';
+} elseif ($objecttype == 'order_supplier') {
+ $classfile = 'fournisseur.commande';
+ $classname = 'CommandeFournisseur';
+ $classpath = 'fourn/class';
+ $module = 'fournisseur';
+} elseif ($objecttype == 'supplier_proposal') {
+ $classfile = 'supplier_proposal';
+ $classname = 'SupplierProposal';
+ $classpath = 'supplier_proposal/class';
+ $module = 'supplier_proposal';
+} elseif ($objecttype == 'stock') {
+ $classpath = 'product/stock/class';
+ $classfile = 'entrepot';
+ $classname = 'Entrepot';
+} elseif ($objecttype == 'facturerec') {
+ $classpath = 'compta/facture/class';
+ $classfile = 'facture-rec';
+ $classname = 'FactureRec';
+ $module = 'facture';
+} elseif ($objecttype == 'mailing') {
+ $classpath = 'comm/mailing/class';
+ $classfile = 'mailing';
+ $classname = 'Mailing';
+} elseif ($objecttype == 'adherent_type') {
+ $classpath = 'adherents/class';
+ $classfile = 'adherent_type';
+ $module = 'adherent';
+ $myobject = 'adherent_type';
+ $classname = 'AdherentType';
+} elseif ($objecttype == 'contact') {
+ $module = 'societe';
+} elseif ($objecttype == 'salary') {
+ $classpath = 'salaries/class';
+ $module = 'salaries';
+}
+// print "objecttype=".$objecttype." module=".$module." subelement=".$subelement." classfile=".$classfile." classname=".$classname." classpath=".$classpath." ";
+
+if (isModEnabled($module)) {
+ $res = dol_include_once('/'.$classpath.'/'.$classfile.'.class.php');
+ if ($res) {
+ if (class_exists($classname)) {
+ $object = new $classname($db);
+ $res = $object->fetch($id);
+ if ($res > 0) {
+ $html = $object->getTooltipContent($params);
+ } elseif ($res == 0) {
+ $html = $langs->trans('Deleted');
+ }
+ unset($object);
+ } else {
+ dol_syslog("Class with classname ".$classname." is unknown even after the include", LOG_ERR);
+ }
+ }
+}
+
+print $html;
+
+$db->close();
diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php
index cf0bfa6ed3b..4dd466d96ab 100644
--- a/htdocs/core/class/CMailFile.class.php
+++ b/htdocs/core/class/CMailFile.class.php
@@ -908,7 +908,7 @@ class CMailFile
require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
- $storage = new DoliStorage($db, $conf);
+ $storage = new DoliStorage($db, $conf, $keyforprovider);
try {
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
$expire = false;
@@ -1030,7 +1030,7 @@ class CMailFile
require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
- $storage = new DoliStorage($db, $conf);
+ $storage = new DoliStorage($db, $conf, $keyforprovider);
try {
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php
index 33f0b369c14..33d5e5a97c6 100644
--- a/htdocs/core/class/commondocgenerator.class.php
+++ b/htdocs/core/class/commondocgenerator.class.php
@@ -553,6 +553,12 @@ abstract class CommonDocGenerator
$resarray[$array_key.'_project_description'] = $object->project->description;
$resarray[$array_key.'_project_date_start'] = dol_print_date($object->project->date_start, 'day');
$resarray[$array_key.'_project_date_end'] = dol_print_date($object->project->date_end, 'day');
+ } else { // empty replacement
+ $resarray[$array_key.'_project_ref'] ='';
+ $resarray[$array_key.'_project_title'] = '';
+ $resarray[$array_key.'_project_description'] = '';
+ $resarray[$array_key.'_project_date_start'] = '';
+ $resarray[$array_key.'_project_date_end'] = '';
}
// Add vat by rates
@@ -716,6 +722,14 @@ abstract class CommonDocGenerator
foreach ($tmpproduct->array_options as $key => $label) {
$resarray["line_product_".$key] = $label;
}
+ } else {
+ // Set unused placeholders as blank
+ $extrafields->fetch_name_optionals_label("product");
+ $extralabels = $extrafields->attributes["product"]['label'];
+
+ foreach ($extralabels as $key => $label) {
+ $resarray['line_product_options_'.$key] = '';
+ }
}
return $resarray;
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index d30d88e9c37..ab4228769e1 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -593,6 +593,11 @@ abstract class CommonObject
protected $labelStatus;
protected $labelStatusShort;
+ /**
+ * @var int showphoto_on_popup
+ */
+ public $showphoto_on_popup;
+
/**
* @var array nb used in load_stateboard
*/
@@ -664,6 +669,57 @@ abstract class CommonObject
}
return -1;
}
+ /**
+ * getTooltipContentArray
+ *
+ * @since v18
+ * @param array $params params to construct tooltip data
+ * @return array
+ */
+ public function getTooltipContentArray($params)
+ {
+ return [];
+ }
+
+ /**
+ * getTooltipContent
+ *
+ * @param array $params params
+ * @since v18
+ * @return string
+ */
+ public function getTooltipContent($params)
+ {
+ global $action, $extrafields, $langs, $hookmanager;
+
+ $datas = $this->getTooltipContentArray($params);
+
+ if (!empty($extrafields->attributes[$this->table_element]['label'])) {
+ foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) {
+ if (!empty($extrafields->attributes[$this->table_element]['langfile'][$key])) {
+ $langs->load($extrafields->attributes[$this->table_element]['langfile'][$key]);
+ }
+ $labelextra = $langs->trans((string) $extrafields->attributes[$this->table_element]['label'][$key]);
+ if ($extrafields->attributes[$this->table_element]['type'][$key] == 'separate') {
+ $datas[$key]= ' '. $labelextra . '';
+ } else {
+ $value = $this->array_options['options_' . $key];
+ $datas[$key]= ' '. $labelextra . ': ' . $extrafields->showOutputField($key, $value, '', $this->table_element);
+ }
+ }
+ }
+
+ $hookmanager->initHooks(array($this->element . 'dao'));
+ $parameters = array(
+ 'tooltipcontentarray' => &$datas
+ );
+ // Note that $action and $object may have been modified by some hooks
+ $hookmanager->executeHooks('getTooltipContent', $parameters, $this, $action);
+
+ $label = implode($datas);
+
+ return $label;
+ }
/**
@@ -1336,8 +1392,8 @@ abstract class CommonObject
}
$sql .= ", t.civility as civility, t.lastname as lastname, t.firstname, t.email";
$sql .= ", tc.source, tc.element, tc.code, tc.libelle";
- $sql .= " FROM ".$this->db->prefix()."c_type_contact tc";
- $sql .= ", ".$this->db->prefix()."element_contact ec";
+ $sql .= " FROM ".$this->db->prefix()."c_type_contact tc,";
+ $sql .= " ".$this->db->prefix()."element_contact ec";
if ($source == 'internal') { // internal contact (user)
$sql .= " LEFT JOIN ".$this->db->prefix()."user t on ec.fk_socpeople = t.rowid";
}
@@ -1981,7 +2037,7 @@ abstract class CommonObject
* @param mixed $value New value
* @param string $table To force other table element or element line (should not be used)
* @param int $id To force other object id (should not be used)
- * @param string $format Data format ('text', 'date'). 'text' is used if not defined
+ * @param string $format Data format ('text', 'int', 'date'). 'text' is used if not defined
* @param string $id_field To force rowid field name. 'rowid' is used if not defined
* @param User|string $fuser Update the user of last update field with this user. If not provided, current user is used except if value is 'none'
* @param string $trigkey Trigger key to run (in most cases something like 'XXX_MODIFY')
@@ -2026,6 +2082,8 @@ abstract class CommonObject
$sql .= $field." = ".((int) $value);
} elseif ($format == 'date') {
$sql .= $field." = ".($value ? "'".$this->db->idate($value)."'" : "null");
+ } elseif ($format == 'dategmt') {
+ $sql .= $field." = ".($value ? "'".$this->db->idate($value, 'gmt')."'" : "null");
}
if ($fk_user_field) {
@@ -5284,7 +5342,7 @@ abstract class CommonObject
$sql .= ", busy";
$sql .= ", mandatory";
$sql .= ") VALUES (";
- $sql .= $resource_id;
+ $sql .= ((int) $resource_id);
$sql .= ", '".$this->db->escape($resource_type)."'";
$sql .= ", '".$this->db->escape($this->id)."'";
$sql .= ", '".$this->db->escape($this->element)."'";
@@ -6269,6 +6327,13 @@ abstract class CommonObject
}
$new_array_options[$key] = $this->db->idate($this->array_options[$key]);
break;
+ case 'datetimegmt':
+ // If data is a string instead of a timestamp, we convert it
+ if (!is_numeric($this->array_options[$key]) || $this->array_options[$key] != intval($this->array_options[$key])) {
+ $this->array_options[$key] = strtotime($this->array_options[$key]);
+ }
+ $new_array_options[$key] = $this->db->idate($this->array_options[$key], 'gmt');
+ break;
case 'link':
$param_list = array_keys($attributeParam['options']);
// 0 : ObjectName
@@ -6609,6 +6674,13 @@ abstract class CommonObject
$this->array_options["options_".$key] = $this->db->idate($this->array_options["options_".$key]);
}
break;
+ case 'datetimegmt':
+ if (empty($this->array_options["options_".$key])) {
+ $this->array_options["options_".$key] = null;
+ } else {
+ $this->array_options["options_".$key] = $this->db->idate($this->array_options["options_".$key], 'gmt');
+ }
+ break;
case 'boolean':
if (empty($this->array_options["options_".$key])) {
$this->array_options["options_".$key] = null;
diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php
index 8f8a3e54552..71d5dfdb06d 100644
--- a/htdocs/core/class/extrafields.class.php
+++ b/htdocs/core/class/extrafields.class.php
@@ -79,6 +79,7 @@ class ExtraFields
'double'=>'Float',
'date'=>'Date',
'datetime'=>'DateAndTime',
+ //'datetimegmt'=>'DateAndTimeUTC',
'boolean'=>'Boolean',
'price'=>'ExtrafieldPrice',
'pricecy'=>'ExtrafieldPriceWithCurrency',
@@ -979,7 +980,7 @@ class ExtraFields
// Add automatic css
if ($type == 'date') {
$morecss = 'minwidth100imp';
- } elseif ($type == 'datetime' || $type == 'link') {
+ } elseif ($type == 'datetime' || $type == 'datetimegmt' || $type == 'link') {
$morecss = 'minwidth200imp';
} elseif (in_array($type, array('int', 'integer', 'double', 'price'))) {
$morecss = 'maxwidth75';
@@ -1031,7 +1032,7 @@ class ExtraFields
// TODO Must also support $moreparam
$out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1);
}
- } elseif (in_array($type, array('datetime'))) {
+ } elseif (in_array($type, array('datetime', 'datetimegmt'))) {
$tmp = explode(',', $size);
$newsize = $tmp[0];
$showtime = 1;
@@ -1614,6 +1615,11 @@ class ExtraFields
if ($value !== '') {
$value = dol_print_date($value, 'dayhour', 'tzuserrel');
}
+ } elseif ($type == 'datetimegmt') {
+ $showsize = 19;
+ if ($value !== '') {
+ $value = dol_print_date($value, 'dayhour', 'gmt');
+ }
} elseif ($type == 'int') {
$showsize = 10;
} elseif ($type == 'double') {
@@ -1928,7 +1934,7 @@ class ExtraFields
$cssstring = '';
- if (in_array($type, array('date', 'datetime'))) {
+ if (in_array($type, array('date', 'datetime', 'datetimegmt'))) {
$cssstring = "center";
} elseif (in_array($type, array('int', 'price', 'double'))) {
$cssstring = "right";
@@ -2137,6 +2143,9 @@ class ExtraFields
} elseif (in_array($key_type, array('datetime'))) {
// Clean parameters
$value_key = dol_mktime(GETPOST("options_".$key."hour", 'int'), GETPOST("options_".$key."min", 'int'), GETPOST("options_".$key."sec", 'int'), GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'), 'tzuserrel');
+ } elseif (in_array($key_type, array('datetimegmt'))) {
+ // Clean parameters
+ $value_key = dol_mktime(GETPOST("options_".$key."hour", 'int'), GETPOST("options_".$key."min", 'int'), GETPOST("options_".$key."sec", 'int'), GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'), 'gmt');
} elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
$value_arr = GETPOST("options_".$key, 'array'); // check if an array
if (!empty($value_arr)) {
@@ -2228,7 +2237,7 @@ class ExtraFields
} else {
continue; // Value was not provided, we should not set it.
}
- } elseif (in_array($key_type, array('datetime'))) {
+ } elseif (in_array($key_type, array('datetime', 'datetimegmt'))) {
$dateparamname_start = $keysuffix . 'options_' . $key . $keyprefix . '_start';
$dateparamname_end = $keysuffix . 'options_' . $key . $keyprefix . '_end';
if (GETPOSTISSET($dateparamname_start . 'year') && GETPOSTISSET($dateparamname_end . 'year')) {
@@ -2236,13 +2245,24 @@ class ExtraFields
$dateparamname_end_hour = GETPOST($dateparamname_end . 'hour', 'int') !='-1' ? GETPOST($dateparamname_end . 'hour', 'int') : '23';
$dateparamname_end_min = GETPOST($dateparamname_end . 'min', 'int') !='-1' ? GETPOST($dateparamname_end . 'min', 'int') : '59';
$dateparamname_end_sec = GETPOST($dateparamname_end . 'sec', 'int') !='-1' ? GETPOST($dateparamname_end . 'sec', 'int') : '59';
- $value_key = array(
- 'start' => dol_mktime(GETPOST($dateparamname_start . 'hour', 'int'), GETPOST($dateparamname_start . 'min', 'int'), GETPOST($dateparamname_start . 'sec', 'int'), GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int'), 'tzuserrel'),
- 'end' => dol_mktime($dateparamname_end_hour, $dateparamname_end_min, $dateparamname_end_sec, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), GETPOST($dateparamname_end . 'year', 'int'), 'tzuserrel')
- );
+ if ($key_type == 'datetimegmt') {
+ $value_key = array(
+ 'start' => dol_mktime(GETPOST($dateparamname_start . 'hour', 'int'), GETPOST($dateparamname_start . 'min', 'int'), GETPOST($dateparamname_start . 'sec', 'int'), GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int'), 'gmt'),
+ 'end' => dol_mktime($dateparamname_end_hour, $dateparamname_end_min, $dateparamname_end_sec, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), GETPOST($dateparamname_end . 'year', 'int'), 'gmt')
+ );
+ } else {
+ $value_key = array(
+ 'start' => dol_mktime(GETPOST($dateparamname_start . 'hour', 'int'), GETPOST($dateparamname_start . 'min', 'int'), GETPOST($dateparamname_start . 'sec', 'int'), GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int'), 'tzuserrel'),
+ 'end' => dol_mktime($dateparamname_end_hour, $dateparamname_end_min, $dateparamname_end_sec, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), GETPOST($dateparamname_end . 'year', 'int'), 'tzuserrel')
+ );
+ }
} elseif (GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) {
// Clean parameters
- $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."sec", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int'), 'tzuserrel');
+ if ($key_type == 'datetimegmt') {
+ $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."sec", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int'), 'gmt');
+ } else {
+ $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."sec", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int'), 'tzuserrel');
+ }
} else {
continue; // Value was not provided, we should not set it.
}
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index c6cf71fbe44..7de2938e299 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -202,9 +202,10 @@ class Form
* @param string $paramid Key of parameter for id ('id', 'socid')
* @param string $gm 'auto' or 'tzuser' or 'tzuserrel' or 'tzserver' (when $typeofdata is a date)
* @param array $moreoptions Array with more options. For example array('addnowlink'=>1), array('valuealreadyhtmlescaped'=>1)
+ * @param string $editaction [=''] use GETPOST default action or set action to edit mode
* @return string HTML edit field
*/
- public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 1, $formatfunc = '', $paramid = 'id', $gm = 'auto', $moreoptions = array())
+ public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 1, $formatfunc = '', $paramid = 'id', $gm = 'auto', $moreoptions = array(), $editaction = '')
{
global $conf, $langs;
@@ -233,7 +234,10 @@ class Form
if (!empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && !preg_match('/^select;|day|datepicker|dayhour|datehourpicker/', $typeofdata)) { // TODO add jquery timepicker and support select
$ret .= $this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg);
} else {
- $editmode = (GETPOST('action', 'aZ09') == 'edit'.$htmlname);
+ if ($editaction == '') {
+ $editaction = GETPOST('action', 'aZ09');
+ }
+ $editmode = ($editaction == 'edit'.$htmlname);
if ($editmode) {
$ret .= "\n";
$ret .= '