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' ) { // TODO: auto-scalable range alghoritm (used here) has several problems: // 1. range values has meaningless values, e.g. 32, 56 and not 100, 200 as in original design // 2. count of items from last range is displayed below filter scale // 3. filter scale has fixed image background that allows only 10 positions $range_sql = str_replace('COUNT(*) AS count', 'MIN(' . $field_sql . ') AS `MinValue`, MAX(' . $field_sql . ') AS `MaxValue`', $sql); $range_values = $this->Conn->GetRow($range_sql); if ( !$range_values['MinValue'] && !$range_values['MaxValue'] ) { return ''; } $range_start = $range_values['MinValue']; $range_count = $object->GetDBField('RangeCount'); $range_size = ceil( ($range_values['MaxValue'] - $range_values['MinValue']) / $range_count ); $range_values['MaxValue'] = $range_start + $range_size * $range_count; // to compensate diff, created by "ceil" function usage $formatter_class = $item_list->GetFieldOption($filter_field, 'formatter'); $options = Array (); $count_clause = ''; $if_clause_mask = 'IF(%s BETWEEN %s AND %s, %s, %%s)'; if ( $formatter_class ) { $formatter =& $this->Application->recallObject($formatter_class); /* @var $formatter kFormatter */ 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] = $formatter->Format($range_start, $filter_field, $item_list)/* . ' - ' . $formatter->Format($range_end, $filter_field, $item_list)*/; $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; } } else { 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] = $range_start . ' - ' . $range_end; $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; } } $cache[$cache_key]['range_values'] = $range_values; $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 ) { 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); 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; 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' ) { $range_count = $object->GetDBField('RangeCount'); $range_values = $cache[$cache_key]['range_values']; $this->Application->SetVar('min_range_value', $range_values['MinValue']); $this->Application->SetVar('max_range_value', $range_values['MaxValue']); $range_size = ceil( ($range_values['MaxValue'] - $range_values['MinValue']) / $range_count ); $this->Application->SetVar('range_step', $range_size); 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', $range_values['MinValue']); $this->Application->SetVar('selected_to_range', $range_values['MaxValue']); } } if ( $ret ) { $this->Application->Parser->DataExists = true; } return $ret; } /** * 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] : ''; } }