From 2c1d4049be08c850dd79a194993b2cf2cbfe2b80 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Tue, 10 Nov 2020 17:24:17 +0100 Subject: [PATCH 1/6] Enable list filtering on date and datetime extrafields --- htdocs/core/class/extrafields.class.php | 60 +++++++++++++++---- .../tpl/extrafields_list_search_input.tpl.php | 4 +- .../tpl/extrafields_list_search_param.tpl.php | 15 +++++ .../tpl/extrafields_list_search_sql.tpl.php | 10 +++- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 4b6f43bd06e..459a7b1820d 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -948,15 +948,15 @@ class ExtraFields * Return HTML string to put an input field into a page * Code very similar with showInputField of common object * - * @param string $key Key of attribute - * @param string $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value) - * @param string $moreparam To add more parametes on html input tag - * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names) - * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names) - * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric) - * @param int $objectid Current object id - * @param string $extrafieldsobjectkey If defined (for example $object->table_element), use the new method to get extrafields data - * @param string $mode 1=Used for search filters + * @param string $key Key of attribute + * @param string|array $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value); for dates in filter mode, a range array('start'=>, 'end'=>) should be provided + * @param string $moreparam To add more parametes on html input tag + * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names) + * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names) + * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric) + * @param int $objectid Current object id + * @param string $extrafieldsobjectkey If defined (for example $object->table_element), use the new method to get extrafields data + * @param string $mode 1=Used for search filters * @return string */ public function showInputField($key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '', $objectid = 0, $extrafieldsobjectkey = '', $mode = 0) @@ -1069,8 +1069,23 @@ class ExtraFields // Do not show current date when field not required (see selectDate() method) if (!$required && $value == '') $value = '-1'; + if ($mode == 1) { + // search filter on a date extrafield shows two inputs to select a date range + $prefill = array( + 'start' => isset($value['start']) ? $value['start'] : '', + 'end' => isset($value['end']) ? $value['end'] : ''); + $out = '
' + . $langs->trans('From') . ' ' + . $form->selectDate($prefill['start'], $keyprefix . $key . $keysuffix . '_start', 0, 0, 1) + . '
' + . '
' + . $langs->trans('to') . ' ' + . $form->selectDate($prefill['end'], $keyprefix . $key . $keysuffix . '_end', 0, 0, 1) + . '
'; + } else { + $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1); + } // 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('int', 'integer'))) { @@ -2162,9 +2177,28 @@ class ExtraFields if (in_array($key_type, array('date', 'datetime'))) { - if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) continue; // Value was not provided, we should not set it. - // Clean parameters - $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), 0, GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int')); + $dateparamname_start = $keysuffix . 'options_' . $key . $keyprefix . '_start'; + $dateparamname_end = $keysuffix . 'options_' . $key . $keyprefix . '_end'; + if (GETPOSTISSET($dateparamname_start . 'year') && GETPOSTISSET($dateparamname_end . 'year')) { + // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc. + $value_key = array( + 'start' => mktime( + 0, 0, 0, + GETPOST($dateparamname_start . 'month', 'int'), + GETPOST($dateparamname_start . 'day', 'int'), + GETPOST($dateparamname_start . 'year', 'int')), + 'end' => mktime( + 23, 59, 59, + GETPOST($dateparamname_end . 'month', 'int'), + GETPOST($dateparamname_end . 'day', 'int'), + GETPOST($dateparamname_end . 'year', 'int')) + ); + } 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'), 0, GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int')); + } else { + continue; // Value was not provided, we should not set it. + } } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) { diff --git a/htdocs/core/tpl/extrafields_list_search_input.tpl.php b/htdocs/core/tpl/extrafields_list_search_input.tpl.php index 6e1dae186b1..7fece2efd1d 100644 --- a/htdocs/core/tpl/extrafields_list_search_input.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_input.tpl.php @@ -36,8 +36,8 @@ if (!empty($extrafieldsobjectkey)) // $extrafieldsobject is the $object->table_e } elseif (in_array($typeofextrafield, array('datetime', 'timestamp'))) { - // TODO - // Use showInputField in a particular manner to have input with a comparison operator, not input for a specific value date-hour-minutes + $morecss = ''; + echo $extrafields->showInputField($key, $search_array_options[$search_options_pattern.$tmpkey], '', '', $search_options_pattern, $morecss, 0, $extrafieldsobjectkey, 1); } else { diff --git a/htdocs/core/tpl/extrafields_list_search_param.tpl.php b/htdocs/core/tpl/extrafields_list_search_param.tpl.php index 6e6d6305106..009d05b30ee 100644 --- a/htdocs/core/tpl/extrafields_list_search_param.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_param.tpl.php @@ -16,6 +16,21 @@ if (!empty($search_array_options) && is_array($search_array_options)) // $extraf { $crit = $val; $tmpkey = preg_replace('/'.$search_options_pattern.'/', '', $key); + if (is_array($val) && array_key_exists('start', $val) && array_key_exists('end', $val)) { + // date range from list filters is stored as array('start' => , 'end' => ) + // start date + $param .= '&' . $search_options_pattern.$tmpkey.'_startyear' . '=' . intval(dol_print_date($val['start'], '%Y')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmonth' . '=' . intval(dol_print_date($val['start'], '%m')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startday' . '=' . intval(dol_print_date($val['start'], '%d')); + $param .= '&' . $search_options_pattern.$tmpkey.'_starthour' . '=' . intval(dol_print_date($val['start'], '%H')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmin' . '=' . intval(dol_print_date($val['start'], '%M')); + // end date + $param .= '&' . $search_options_pattern.$tmpkey.'_endyear' . '=' . intval(dol_print_date($val['end'], '%Y')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmonth' . '=' . intval(dol_print_date($val['end'], '%m')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endday' . '=' . intval(dol_print_date($val['end'], '%d')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endhour' . '=' . intval(dol_print_date($val['end'], '%H')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmin' . '=' . intval(dol_print_date($val['end'], '%M')); + } if ($val != '') $param .= '&'.$search_options_pattern.$tmpkey.'='.urlencode($val); } } diff --git a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php index 03d487ee0c0..048ca24020a 100644 --- a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php @@ -23,7 +23,15 @@ if (!empty($extrafieldsobjectkey) && !empty($search_array_options) && is_array($ if ($crit != '' && in_array($typ, array('date', 'datetime', 'timestamp'))) { - $sql .= " AND ".$extrafieldsobjectprefix.$tmpkey." = '".$db->idate($crit)."'"; + if (is_numeric($crit)) { + $sql .= " AND ".$extrafieldsobjectprefix.$tmpkey." = '".$db->idate($crit)."'"; + } elseif (is_array($crit)) { + $sql .= ' AND (' . $extrafieldsobjectprefix.$tmpkey + .' BETWEEN "' + . $db->idate($crit['start']) + . '" AND "' + . $db->idate($crit['end']) . '")'; + } } elseif (in_array($typ, array('boolean'))) { From a64c4b0cb5a74de2514279b311d4a7f765b80716 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Tue, 10 Nov 2020 17:29:03 +0100 Subject: [PATCH 2/6] support for $moreparam --- htdocs/core/class/extrafields.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 459a7b1820d..a188dafd885 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -950,7 +950,7 @@ class ExtraFields * * @param string $key Key of attribute * @param string|array $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value); for dates in filter mode, a range array('start'=>, 'end'=>) should be provided - * @param string $moreparam To add more parametes on html input tag + * @param string $moreparam To add more parameters on html input tag * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names) * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names) * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric) @@ -1074,18 +1074,18 @@ class ExtraFields $prefill = array( 'start' => isset($value['start']) ? $value['start'] : '', 'end' => isset($value['end']) ? $value['end'] : ''); - $out = '
' + $out = '
' . $langs->trans('From') . ' ' . $form->selectDate($prefill['start'], $keyprefix . $key . $keysuffix . '_start', 0, 0, 1) . '
' . '
' . $langs->trans('to') . ' ' . $form->selectDate($prefill['end'], $keyprefix . $key . $keysuffix . '_end', 0, 0, 1) - . '
'; + . '
'; } else { + // 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); } - // TODO Must also support $moreparam } elseif (in_array($type, array('int', 'integer'))) { From 952f398a609cc112e4f06748b54a24b80f6650f4 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Tue, 10 Nov 2020 23:50:42 +0100 Subject: [PATCH 3/6] Apply stickler CI recommendation to avoid concatenating string literals --- htdocs/core/class/extrafields.class.php | 3 +-- .../tpl/extrafields_list_search_param.tpl.php | 20 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index a188dafd885..b5d4852d128 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1077,8 +1077,7 @@ class ExtraFields $out = '
' . $langs->trans('From') . ' ' . $form->selectDate($prefill['start'], $keyprefix . $key . $keysuffix . '_start', 0, 0, 1) - . '
' - . '
' + . '
' . $langs->trans('to') . ' ' . $form->selectDate($prefill['end'], $keyprefix . $key . $keysuffix . '_end', 0, 0, 1) . '
'; diff --git a/htdocs/core/tpl/extrafields_list_search_param.tpl.php b/htdocs/core/tpl/extrafields_list_search_param.tpl.php index 009d05b30ee..902d4df59ca 100644 --- a/htdocs/core/tpl/extrafields_list_search_param.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_param.tpl.php @@ -19,17 +19,17 @@ if (!empty($search_array_options) && is_array($search_array_options)) // $extraf if (is_array($val) && array_key_exists('start', $val) && array_key_exists('end', $val)) { // date range from list filters is stored as array('start' => , 'end' => ) // start date - $param .= '&' . $search_options_pattern.$tmpkey.'_startyear' . '=' . intval(dol_print_date($val['start'], '%Y')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startmonth' . '=' . intval(dol_print_date($val['start'], '%m')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startday' . '=' . intval(dol_print_date($val['start'], '%d')); - $param .= '&' . $search_options_pattern.$tmpkey.'_starthour' . '=' . intval(dol_print_date($val['start'], '%H')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startmin' . '=' . intval(dol_print_date($val['start'], '%M')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startyear=' . intval(dol_print_date($val['start'], '%Y')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmonth=' . intval(dol_print_date($val['start'], '%m')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startday=' . intval(dol_print_date($val['start'], '%d')); + $param .= '&' . $search_options_pattern.$tmpkey.'_starthour=' . intval(dol_print_date($val['start'], '%H')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmin=' . intval(dol_print_date($val['start'], '%M')); // end date - $param .= '&' . $search_options_pattern.$tmpkey.'_endyear' . '=' . intval(dol_print_date($val['end'], '%Y')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endmonth' . '=' . intval(dol_print_date($val['end'], '%m')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endday' . '=' . intval(dol_print_date($val['end'], '%d')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endhour' . '=' . intval(dol_print_date($val['end'], '%H')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endmin' . '=' . intval(dol_print_date($val['end'], '%M')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endyear=' . intval(dol_print_date($val['end'], '%Y')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmonth=' . intval(dol_print_date($val['end'], '%m')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endday=' . intval(dol_print_date($val['end'], '%d')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endhour=' . intval(dol_print_date($val['end'], '%H')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmin=' . intval(dol_print_date($val['end'], '%M')); } if ($val != '') $param .= '&'.$search_options_pattern.$tmpkey.'='.urlencode($val); } From 64a62bf2c2ac0d5747aa14f012e5098d853599b8 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Tue, 22 Dec 2020 09:37:30 +0100 Subject: [PATCH 4/6] FIX (PR #15346 comment) use dol_mktime, not mktime --- htdocs/core/class/extrafields.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index b5d4852d128..1144cf5c682 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -2181,12 +2181,12 @@ class ExtraFields if (GETPOSTISSET($dateparamname_start . 'year') && GETPOSTISSET($dateparamname_end . 'year')) { // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc. $value_key = array( - 'start' => mktime( + 'start' => dol_mktime( 0, 0, 0, GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int')), - 'end' => mktime( + 'end' => dol_mktime( 23, 59, 59, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), From 5418fcd5be4277e5fcbdec9ad3bdb4e034af367b Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Fri, 8 Jan 2021 09:05:32 +0100 Subject: [PATCH 5/6] [minor fix] remove useless intval() --- .../tpl/extrafields_list_search_param.tpl.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/core/tpl/extrafields_list_search_param.tpl.php b/htdocs/core/tpl/extrafields_list_search_param.tpl.php index 902d4df59ca..adc3980fe7d 100644 --- a/htdocs/core/tpl/extrafields_list_search_param.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_param.tpl.php @@ -19,17 +19,17 @@ if (!empty($search_array_options) && is_array($search_array_options)) // $extraf if (is_array($val) && array_key_exists('start', $val) && array_key_exists('end', $val)) { // date range from list filters is stored as array('start' => , 'end' => ) // start date - $param .= '&' . $search_options_pattern.$tmpkey.'_startyear=' . intval(dol_print_date($val['start'], '%Y')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startmonth=' . intval(dol_print_date($val['start'], '%m')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startday=' . intval(dol_print_date($val['start'], '%d')); - $param .= '&' . $search_options_pattern.$tmpkey.'_starthour=' . intval(dol_print_date($val['start'], '%H')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startmin=' . intval(dol_print_date($val['start'], '%M')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startyear=' . dol_print_date($val['start'], '%Y'); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmonth=' . dol_print_date($val['start'], '%m'); + $param .= '&' . $search_options_pattern.$tmpkey.'_startday=' . dol_print_date($val['start'], '%d'); + $param .= '&' . $search_options_pattern.$tmpkey.'_starthour=' . dol_print_date($val['start'], '%H'); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmin=' . dol_print_date($val['start'], '%M'); // end date - $param .= '&' . $search_options_pattern.$tmpkey.'_endyear=' . intval(dol_print_date($val['end'], '%Y')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endmonth=' . intval(dol_print_date($val['end'], '%m')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endday=' . intval(dol_print_date($val['end'], '%d')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endhour=' . intval(dol_print_date($val['end'], '%H')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endmin=' . intval(dol_print_date($val['end'], '%M')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endyear=' . dol_print_date($val['end'], '%Y'); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmonth=' . dol_print_date($val['end'], '%m'); + $param .= '&' . $search_options_pattern.$tmpkey.'_endday=' . dol_print_date($val['end'], '%d'); + $param .= '&' . $search_options_pattern.$tmpkey.'_endhour=' . dol_print_date($val['end'], '%H'); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmin=' . dol_print_date($val['end'], '%M'); } if ($val != '') $param .= '&'.$search_options_pattern.$tmpkey.'='.urlencode($val); } From d7d44e22e3b908dabdf3b0d8f8cabd8710c0290b Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Fri, 8 Jan 2021 10:30:39 +0100 Subject: [PATCH 6/6] FIX warning when filtering on date extrafield (cannot concatenate array to string) --- htdocs/core/tpl/extrafields_list_search_param.tpl.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/tpl/extrafields_list_search_param.tpl.php b/htdocs/core/tpl/extrafields_list_search_param.tpl.php index 2443fda1acb..5fca6bc70a9 100644 --- a/htdocs/core/tpl/extrafields_list_search_param.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_param.tpl.php @@ -30,6 +30,7 @@ if (!empty($search_array_options) && is_array($search_array_options)) // $extraf $param .= '&' . $search_options_pattern.$tmpkey.'_endday=' . dol_print_date($val['end'], '%d'); $param .= '&' . $search_options_pattern.$tmpkey.'_endhour=' . dol_print_date($val['end'], '%H'); $param .= '&' . $search_options_pattern.$tmpkey.'_endmin=' . dol_print_date($val['end'], '%M'); + $val = ''; } if ($val != '') $param .= '&'.$search_options_pattern.$tmpkey.'='.urlencode($val); }