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 (); /** @var kDBItem $object */ $object = $this->getObject($params); // 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 { /** @var kDBItem $object */ $object = $this->getObject($params); $range_count = $object->GetDBField('RangeCount'); } return $range_count * $params['factor']; } }