Index: branches/5.2.x/core/units/filters/item_filter_tp.php =================================================================== diff -u -N -r15152 -r15165 --- branches/5.2.x/core/units/filters/item_filter_tp.php (.../item_filter_tp.php) (revision 15152) +++ branches/5.2.x/core/units/filters/item_filter_tp.php (.../item_filter_tp.php) (revision 15165) @@ -1,322 +1,322 @@ -Application->isAdmin ) { - return ; - } - - $block_params['filter_field'] = $object->GetDBField('FilterField'); - $block_params['filter_type'] = $object->GetDBField('FilterType'); - } - - /** - * Lists filter options - * - * @param Array $params - * @return string - * @access protected - */ - protected function ListFilterOptions($params) - { - static $cache = Array (); - - $object = $this->getObject($params); - /* @var $object kDBItem */ - - // get item list to be filtered - $this->Application->ProcessParsedTag($params['prefix'], 'InitList', $params); - $tag_processor = $this->Application->recallTagProcessor( $params['prefix'] ); - $item_list = $tag_processor->GetList($params); - - $filter_type = $object->GetDBField('FilterType'); - $filter_field = $object->GetDBField('FilterField'); - $cache_key = $filter_field . '_' . $filter_type; - - if ( !isset($cache[$cache_key]) ) { - $cache[$cache_key] = Array ('counts' => Array (), 'options' => Array ()); - - $field_sql = $item_list->isCalculatedField($filter_field) ? $item_list->extractCalculatedFields('`' . $filter_field . '`', 1, true) : '`' . $item_list->TableName . '`.`' . $filter_field . '`'; - $sql = $item_list->getCountSQL( $item_list->GetSelectSQL(true, false, $field_sql) ); - - if ( in_array($filter_type, Array ('select', 'radio', 'checkbox')) ) { - $options = $item_list->GetFieldOption($filter_field, 'options', false, Array ()); - - if ( $item_list->GetFieldOption($filter_field, 'use_phrases') ) { - $options = array_map(Array (&$this->Application, 'Phrase'), $options); - } - - $cache[$cache_key]['options'] = $options; - - $count_sql = str_replace('COUNT(*) AS count', 'COUNT(*), ' . $field_sql . ' AS GroupField', $sql) . ' GROUP BY GroupField'; - $cache[$cache_key]['counts'] = $this->Conn->GetCol($count_sql, 'GroupField'); - } - elseif ( $filter_type == 'range' ) { - $filter_params = $this->Application->GetVar('filter_params', Array ()); - $filter_params = isset($filter_params[$filter_field]) ? $filter_params[$filter_field] : Array (); - - if ( isset($filter_params['max_value']) ) { - $max_value = $filter_params['max_value']; - } - else { - $max_sql = str_replace('COUNT(*) AS count', 'MAX(' . $field_sql . ')', $sql); - $max_value = $this->Conn->GetOne($max_sql); - } - - if ( !$max_value ) { - return ''; - } - - $range_start = 0; - $range_count = $object->GetDBField('RangeCount'); - $max_value = $this->getClosestValue($max_value / $range_count) * $range_count; - - if ( $max_value <= $range_count ) { - $range_count = floor($range_count / 2); - } - - $range_size = $max_value / $range_count; - -// $range_size = ceil( $max_value / $range_count ); -// $max_value = $range_size * $range_count; // to compensate diff, created by "ceil" function usage - - $options = Array (); - $count_clause = ''; - $if_clause_mask = 'IF(%s BETWEEN %s AND %s, %s, %%s)'; - - for ($range_number = 0; $range_number < $range_count; $range_number++) { - $range_end = $range_start + $range_size; - $option_key = sprintf('%01.2f', $range_start) . '-' . sprintf('%01.2f', $range_end); - $options[$option_key] = $this->applyFormatting($range_start, $params); - - $sql_part = sprintf($if_clause_mask, $field_sql, $range_start, $range_end, $this->Conn->qstr($option_key)); - $count_clause = $count_clause ? sprintf($count_clause, $sql_part) : $sql_part; - $range_start = $range_end; - } - - $options[sprintf('%01.2f', $range_start) . '-' . sprintf('%01.2f', $range_start)] = $this->applyFormatting($range_start, $params); - - $cache[$cache_key]['max_value'] = $max_value; - $cache[$cache_key]['options'] = $options; - - $count_clause = sprintf($count_clause, $this->Conn->qstr($option_key)); - $count_sql = str_replace('COUNT(*) AS count', 'COUNT(*), ' . $count_clause . ' AS GroupField', $sql) . ' GROUP BY GroupField'; - $cache[$cache_key]['counts'] = $this->Conn->GetCol($count_sql, 'GroupField'); - } - } - - $options = $cache[$cache_key]['options']; - $counts = $cache[$cache_key]['counts']; - - if ( !$options || array_sum($counts) == 0 ) { - // no options in the filter OR no records to operate on - return ''; - } - - if ( $filter_type != 'range' ) { - $counts[''] = array_sum($counts); - $options = kUtil::array_merge_recursive(Array ('' => 'All'), $options); - } - - $ret = ''; - $block_params = $this->prepareTagParams($params); - $block_params['name'] = $params['render_as']; - $selected_value = $this->getFilterValue($filter_field); - - if ( $filter_type == 'range' && $params['type'] == 'count' ) { - // don't display last count, that corresponds to fake option - array_pop($options); - } - - $last_option_title = end($options); - - foreach ($options as $option_key => $option_title) { - $block_params['key'] = $option_key; - $block_params['title'] = $option_title; - $block_params['count'] = isset($counts[$option_key]) ? $counts[$option_key] : 0; - $block_params['is_last'] = $option_title == $last_option_title; - - if ( strpos($selected_value, '|') === false ) { - $block_params['selected'] = "$selected_value" === "$option_key"; - } - else { - $block_params['selected'] = strpos($selected_value, '|' . $option_key . '|') !== false; - } - - $ret .= $this->Application->ParseBlock($block_params); - } - - // set global vars to be used by jQuery UI slider - if ( $filter_type == 'range' ) { - $max_value = $cache[$cache_key]['max_value']; - - $this->Application->SetVar('min_range_value', 0); - $this->Application->SetVar('max_range_value', $max_value); - - $range_count = $object->GetDBField('RangeCount'); - - if ( $max_value <= $range_count ) { - $range_count = floor($range_count / 2); - } - - $range_size = $max_value / $range_count; - $this->Application->SetVar('range_step', $range_size); - -// $this->Application->SetVar('range_step', 1); - - if ( $selected_value ) { - list ($from_selected_value, $to_selected_value) = explode('-', $selected_value); - - $this->Application->SetVar('selected_from_range', $from_selected_value); - $this->Application->SetVar('selected_to_range', $to_selected_value); - } - else { - $this->Application->SetVar('selected_from_range', 0); - $this->Application->SetVar('selected_to_range', $max_value); - } - } - - if ( $ret ) { - $this->Application->Parser->DataExists = true; - } - - return $ret; - } - - /** - * Formats value to display in filter - * - * @param mixed $value - * @param Array $params - * @return string - */ - function applyFormatting($value, $params) - { - if ( isset($params['currency']) && $params['currency']) { - $iso = $this->GetISO($params['currency']); - $value = $this->ConvertCurrency($value, $iso); - - $decimal_tag = isset($params['decimal_tag']) ? $params['decimal_tag'] : ''; - $value = $this->AddCurrencySymbol($value, $iso, $decimal_tag); - } - - return $value; - } - - /** - * Returns next closest value to given one - * - * @param float $value - * @return int - * @access protected - */ - protected function getClosestValue($value) - { - $scale = Array (0, 1, 2, 5, 10, 20, 25, 30, 40, 50, 100, 150, 200, 250, 300, 400, 500, 1000, 1500, 2000, 2500, 3000, 5000, 10000); - - foreach ($scale as $scale_value) { - if ( $scale_value >= $value ) { - return $scale_value; - } - } - - return end($scale); - } - - /** - * Filter input name - * - * @param Array $params - * @return string - * @access protected - */ - protected function FilterInputName($params) - { - $field = $this->Application->Parser->GetParam('filter_field'); - - $ret = 'filters[' . $field . ']'; - - if (array_key_exists('as_preg', $params) && $params['as_preg']) { - $ret = preg_quote($ret, '/'); - } - - return $ret; - } - - /** - * Returns filter value - * - * @param Array $params - * @return string - * @access protected - */ - protected function FilterField($params) - { - $field = $this->Application->Parser->GetParam('filter_field'); - - return $this->getFilterValue($field); - } - - /** - * Returns filter value - * - * @param string $field - * @return string - * @access protected - */ - protected function getFilterValue($field) - { - $filters = $this->Application->GetVar('filters', Array ()); - - return array_key_exists($field, $filters) ? $filters[$field] : ''; - } - - /** - * Returns calculated range slider height - * - * @param Array $params - * @return string - * @access protected - */ - protected function SliderHeight($params) - { - // range count could be dynamically changed in PrintFilterOptions tag - $max_value = $this->Application->GetVar('max_range_value'); - - if ( $max_value !== false ) { - $range_count = $max_value / $this->Application->GetVar('range_step'); - } - else { - $object = $this->getObject($params); - /* @var $object kDBItem */ - - $range_count = $object->GetDBField('RangeCount'); - } - - return $range_count * $params['factor']; - } -} +Application->isAdmin ) { + return ; + } + + $block_params['filter_field'] = $object->GetDBField('FilterField'); + $block_params['filter_type'] = $object->GetDBField('FilterType'); + } + + /** + * Lists filter options + * + * @param Array $params + * @return string + * @access protected + */ + protected function ListFilterOptions($params) + { + static $cache = Array (); + + $object = $this->getObject($params); + /* @var $object kDBItem */ + + // get item list to be filtered + $this->Application->ProcessParsedTag($params['prefix'], 'InitList', $params); + $tag_processor = $this->Application->recallTagProcessor( $params['prefix'] ); + $item_list = $tag_processor->GetList($params); + + $filter_type = $object->GetDBField('FilterType'); + $filter_field = $object->GetDBField('FilterField'); + $cache_key = $filter_field . '_' . $filter_type; + + if ( !isset($cache[$cache_key]) ) { + $cache[$cache_key] = Array ('counts' => Array (), 'options' => Array ()); + + $field_sql = $item_list->isCalculatedField($filter_field) ? $item_list->extractCalculatedFields('`' . $filter_field . '`', 1, true) : '`' . $item_list->TableName . '`.`' . $filter_field . '`'; + $sql = $item_list->getCountSQL( $item_list->GetSelectSQL(true, false, $field_sql) ); + + if ( in_array($filter_type, Array ('select', 'radio', 'checkbox')) ) { + $options = $item_list->GetFieldOption($filter_field, 'options', false, Array ()); + + if ( $item_list->GetFieldOption($filter_field, 'use_phrases') ) { + $options = array_map(Array (&$this->Application, 'Phrase'), $options); + } + + $cache[$cache_key]['options'] = $options; + + $count_sql = str_replace('COUNT(*) AS count', 'COUNT(*), ' . $field_sql . ' AS GroupField', $sql) . ' GROUP BY GroupField'; + $cache[$cache_key]['counts'] = $this->Conn->GetCol($count_sql, 'GroupField'); + } + elseif ( $filter_type == 'range' ) { + $filter_params = $this->Application->GetVar('filter_params', Array ()); + $filter_params = isset($filter_params[$filter_field]) ? $filter_params[$filter_field] : Array (); + + if ( isset($filter_params['max_value']) ) { + $max_value = $filter_params['max_value']; + } + else { + $max_sql = str_replace('COUNT(*) AS count', 'MAX(' . $field_sql . ')', $sql); + $max_value = $this->Conn->GetOne($max_sql); + } + + if ( !$max_value ) { + return ''; + } + + $range_start = 0; + $range_count = $object->GetDBField('RangeCount'); + $max_value = $this->getClosestValue($max_value / $range_count) * $range_count; + + if ( $max_value <= $range_count ) { + $range_count = floor($range_count / 2); + } + + $range_size = $max_value / $range_count; + +// $range_size = ceil( $max_value / $range_count ); +// $max_value = $range_size * $range_count; // to compensate diff, created by "ceil" function usage + + $options = Array (); + $count_clause = ''; + $if_clause_mask = 'IF(%s BETWEEN %s AND %s, %s, %%s)'; + + for ($range_number = 0; $range_number < $range_count; $range_number++) { + $range_end = $range_start + $range_size; + $option_key = sprintf('%01.2f', $range_start) . '-' . sprintf('%01.2f', $range_end); + $options[$option_key] = $this->applyFormatting($range_start, $params); + + $sql_part = sprintf($if_clause_mask, $field_sql, $range_start, $range_end, $this->Conn->qstr($option_key)); + $count_clause = $count_clause ? sprintf($count_clause, $sql_part) : $sql_part; + $range_start = $range_end; + } + + $options[sprintf('%01.2f', $range_start) . '-' . sprintf('%01.2f', $range_start)] = $this->applyFormatting($range_start, $params); + + $cache[$cache_key]['max_value'] = $max_value; + $cache[$cache_key]['options'] = $options; + + $count_clause = sprintf($count_clause, $this->Conn->qstr($option_key)); + $count_sql = str_replace('COUNT(*) AS count', 'COUNT(*), ' . $count_clause . ' AS GroupField', $sql) . ' GROUP BY GroupField'; + $cache[$cache_key]['counts'] = $this->Conn->GetCol($count_sql, 'GroupField'); + } + } + + $options = $cache[$cache_key]['options']; + $counts = $cache[$cache_key]['counts']; + + if ( !$options || array_sum($counts) == 0 ) { + // no options in the filter OR no records to operate on + return ''; + } + + if ( $filter_type != 'range' ) { + $counts[''] = array_sum($counts); + $options = kUtil::array_merge_recursive(Array ('' => 'All'), $options); + } + + $ret = ''; + $block_params = $this->prepareTagParams($params); + $block_params['name'] = $params['render_as']; + $selected_value = $this->getFilterValue($filter_field); + + if ( $filter_type == 'range' && $params['type'] == 'count' ) { + // don't display last count, that corresponds to fake option + array_pop($options); + } + + $last_option_title = end($options); + + foreach ($options as $option_key => $option_title) { + $block_params['key'] = $option_key; + $block_params['title'] = $option_title; + $block_params['count'] = isset($counts[$option_key]) ? $counts[$option_key] : 0; + $block_params['is_last'] = $option_title == $last_option_title; + + if ( strpos($selected_value, '|') === false ) { + $block_params['selected'] = "$selected_value" === "$option_key"; + } + else { + $block_params['selected'] = strpos($selected_value, '|' . $option_key . '|') !== false; + } + + $ret .= $this->Application->ParseBlock($block_params); + } + + // set global vars to be used by jQuery UI slider + if ( $filter_type == 'range' ) { + $max_value = $cache[$cache_key]['max_value']; + + $this->Application->SetVar('min_range_value', 0); + $this->Application->SetVar('max_range_value', $max_value); + + $range_count = $object->GetDBField('RangeCount'); + + if ( $max_value <= $range_count ) { + $range_count = floor($range_count / 2); + } + + $range_size = $max_value / $range_count; + $this->Application->SetVar('range_step', $range_size); + +// $this->Application->SetVar('range_step', 1); + + if ( $selected_value ) { + list ($from_selected_value, $to_selected_value) = explode('-', $selected_value); + + $this->Application->SetVar('selected_from_range', $from_selected_value); + $this->Application->SetVar('selected_to_range', $to_selected_value); + } + else { + $this->Application->SetVar('selected_from_range', 0); + $this->Application->SetVar('selected_to_range', $max_value); + } + } + + if ( $ret ) { + $this->Application->Parser->DataExists = true; + } + + return $ret; + } + + /** + * Formats value to display in filter + * + * @param mixed $value + * @param Array $params + * @return string + */ + function applyFormatting($value, $params) + { + if ( isset($params['currency']) && $params['currency']) { + $iso = $this->GetISO($params['currency']); + $value = $this->ConvertCurrency($value, $iso); + + $decimal_tag = isset($params['decimal_tag']) ? $params['decimal_tag'] : ''; + $value = $this->AddCurrencySymbol($value, $iso, $decimal_tag); + } + + return $value; + } + + /** + * Returns next closest value to given one + * + * @param float $value + * @return int + * @access protected + */ + protected function getClosestValue($value) + { + $scale = Array (0, 1, 2, 5, 10, 20, 25, 30, 40, 50, 100, 150, 200, 250, 300, 400, 500, 1000, 1500, 2000, 2500, 3000, 5000, 10000); + + foreach ($scale as $scale_value) { + if ( $scale_value >= $value ) { + return $scale_value; + } + } + + return end($scale); + } + + /** + * Filter input name + * + * @param Array $params + * @return string + * @access protected + */ + protected function FilterInputName($params) + { + $field = $this->Application->Parser->GetParam('filter_field'); + + $ret = 'filters[' . $field . ']'; + + if (array_key_exists('as_preg', $params) && $params['as_preg']) { + $ret = preg_quote($ret, '/'); + } + + return $ret; + } + + /** + * Returns filter value + * + * @param Array $params + * @return string + * @access protected + */ + protected function FilterField($params) + { + $field = $this->Application->Parser->GetParam('filter_field'); + + return $this->getFilterValue($field); + } + + /** + * Returns filter value + * + * @param string $field + * @return string + * @access protected + */ + protected function getFilterValue($field) + { + $filters = $this->Application->GetVar('filters', Array ()); + + return array_key_exists($field, $filters) ? $filters[$field] : ''; + } + + /** + * Returns calculated range slider height + * + * @param Array $params + * @return string + * @access protected + */ + protected function SliderHeight($params) + { + // range count could be dynamically changed in PrintFilterOptions tag + $max_value = $this->Application->GetVar('max_range_value'); + + if ( $max_value !== false ) { + $range_count = $max_value / $this->Application->GetVar('range_step'); + } + else { + $object = $this->getObject($params); + /* @var $object kDBItem */ + + $range_count = $object->GetDBField('RangeCount'); + } + + return $range_count * $params['factor']; + } +}