public function load_facets() { if ('off' == $this->facetedmenus) { return; } $output = ''; $this->filters(); $Storefront = ShoppStorefront(); if (!$Storefront) { return; } $CategoryFilters =& $Storefront->browsing[$this->slug]; $Filtered = new ProductCategory($this->id); $filtering = array_merge($Filtered->facetsql(array()), array('ids' => true, 'limit' => 1000)); $Filtered->load($filtering); $ids = join(',', $Filtered->worklist()); // Load price facet filters first if ('disabled' != $this->pricerange) { $Facet = $this->facets['price']; $Facet->link = add_query_arg(array('s_ff' => 'on', urlencode($Facet->slug) => ''), shopp('category', 'get-url')); if (!$this->loaded) { $this->load(); } if ('auto' == $this->pricerange) { $ranges = auto_ranges($this->pricing->average, $this->pricing->max, $this->pricing->min, $this->pricing->uniques); } else { $ranges = $this->priceranges; } if (!empty($ranges)) { $casewhen = ''; foreach ($ranges as $index => $r) { $minprice = $r['max'] > 0 ? " AND minprice <= {$r['max']}" : ""; $casewhen .= " WHEN (minprice >= {$r['min']}{$minprice}) THEN {$index}"; } $sumtable = ShoppDatabaseObject::tablename(ProductSummary::$table); $query = "SELECT count(*) AS total, CASE {$casewhen} END AS rangeid\n\t\t\t\t\tFROM {$sumtable}\n\t\t\t\t\tWHERE product IN ({$ids}) GROUP BY rangeid"; $counts = sDB::query($query, 'array', 'col', 'total', 'rangeid'); foreach ($ranges as $id => $range) { if (!isset($counts[$id]) || $counts[$id] < 1) { continue; } $label = money($range['min']) . ' — ' . money($range['max']); if ($range['min'] == 0) { $label = sprintf(__('Under %s', 'Shopp'), money($range['max'])); } if ($range['max'] == 0) { $label = sprintf(__('%s and up', 'Shopp'), money($range['min'])); } $FacetFilter = new ProductCategoryFacetFilter(); $FacetFilter->label = $label; $FacetFilter->param = urlencode($range['min'] . '-' . $range['max']); $FacetFilter->count = $counts[$id]; $Facet->filters[$FacetFilter->param] = $FacetFilter; } } // END !empty($ranges) } // Identify facet menu types to treat numeric and string contexts properly @bug #2014 $custom = array(); foreach ($this->facets as $Facet) { if ('custom' == $Facet->type) { $custom[] = sDB::escape($Facet->name); } } // Load spec aggregation data $spectable = ShoppDatabaseObject::tablename(Spec::$table); $query = "SELECT spec.name,spec.value,\n\t\t\tIF(0 >= FIND_IN_SET(spec.name,'" . join(",", $custom) . "'),IF(spec.numeral > 0,spec.name,spec.value),spec.value) AS merge, count(DISTINCT spec.value) AS uniques,\n\t\t\tcount(*) AS count,avg(numeral) AS avg,max(numeral) AS max,min(numeral) AS min\n\t\t\tFROM {$spectable} AS spec\n\t\t\tWHERE spec.parent IN ({$ids}) AND spec.context='product' AND spec.type='spec' AND (spec.value != '' OR spec.numeral > 0) GROUP BY merge"; $specdata = sDB::query($query, 'array', 'index', 'name', true); foreach ($this->specs as $spec) { if ('disabled' == $spec['facetedmenu']) { continue; } $slug = sanitize_title_with_dashes($spec['name']); if (!isset($this->facets[$slug])) { continue; } $Facet =& $this->facets[$slug]; $Facet->link = add_query_arg(array('s_ff' => 'on', urlencode($Facet->slug) => ''), shopp('category', 'get-url')); // For custom menu presets switch ($spec['facetedmenu']) { case 'custom': $data = $specdata[$Facet->name]; $counts = array(); foreach ($data as $d) { $counts[$d->value] = $d->count; } foreach ($spec['options'] as $option) { if (!isset($counts[$option['name']]) || $counts[$option['name']] < 1) { continue; } $FacetFilter = new ProductCategoryFacetFilter(); $FacetFilter->label = $option['name']; $FacetFilter->param = urlencode($option['name']); $FacetFilter->count = $counts[$FacetFilter->label]; $Facet->filters[$FacetFilter->param] = $FacetFilter; } break; case 'ranges': foreach ($spec['options'] as $i => $option) { $matches = array(); $format = '%s-%s'; $next = 0; if (isset($spec['options'][$i + 1])) { if (preg_match('/(\\d+[\\.\\,\\d]*)/', $spec['options'][$i + 1]['name'], $matches)) { $next = $matches[0]; } } $matches = array(); $range = array("min" => 0, "max" => 0); if (preg_match('/^(.*?)(\\d+[\\.\\,\\d]*)(.*)$/', $option['name'], $matches)) { $base = $matches[2]; $format = $matches[1] . '%s' . $matches[3]; if (!isset($spec['options'][$i + 1])) { $range['min'] = $base; } else { $range = array("min" => $base, "max" => $next - 1); } } if ($i == 1) { $href = add_query_arg($slug, urlencode(sprintf($format, '0', $range['min'])), $link); $label = __('Under ', 'Shopp') . sprintf($format, $range['min']); $list .= '<li><a href="' . $href . '">' . $label . '</a></li>'; } $href = add_query_arg($slug, urlencode(sprintf($format, $range['min'], $range['max'])), $link); $label = sprintf($format, $range['min']) . ' — ' . sprintf($format, $range['max']); if ($range['max'] == 0) { $label = sprintf($format, $range['min']) . ' ' . __('and up', 'Shopp'); } $list .= '<li><a href="' . $href . '">' . $label . '</a></li>'; } break; default: if (!isset($specdata[$Facet->name])) { break; } $data = $specdata[$Facet->name]; if (!is_array($data)) { $data = array($data); } if ($data[0]->min + $data[0]->max + $data[0]->avg == 0) { // Generate facet filters from text values foreach ($data as $option) { $FacetFilter = new ProductCategoryFacetFilter(); $FacetFilter->label = $option->value; $FacetFilter->param = urlencode($option->value); $FacetFilter->count = $option->count; $Facet->filters[$FacetFilter->param] = $FacetFilter; } } else { $data = reset($data); $format = '%s'; if (preg_match('/^(.*?)(\\d+[\\.\\,\\d]*)(.*)$/', $data->value, $matches)) { $format = $matches[1] . '%s' . $matches[3]; } $ranges = auto_ranges($data->avg, $data->max, $data->min, $data->uniques); if (!empty($ranges)) { $casewhen = ''; foreach ($ranges as $index => $r) { $max = $r['max'] > 0 ? " AND spec.numeral <= {$r['max']}" : ""; $casewhen .= " WHEN (spec.numeral >= {$r['min']}{$max}) THEN {$index}"; } $query = "SELECT count(*) AS total, CASE {$casewhen} END AS rangeid\n\t\t\t\t\t\t\t\tFROM {$spectable} AS spec\n\t\t\t\t\t\t\t\tWHERE spec.parent IN ({$ids}) AND spec.name='{$Facet->name}' AND spec.context='product' AND spec.type='spec' AND spec.numeral > 0 GROUP BY rangeid"; $counts = sDB::query($query, 'array', 'col', 'total', 'rangeid'); foreach ($ranges as $id => $range) { if (!isset($counts[$id]) || $counts[$id] < 1) { continue; } $label = sprintf($format, $range['min']) . ' — ' . sprintf($format, $range['max']); if ($range['min'] == 0) { $label = __('Under ', 'Shopp') . sprintf($format, $range['max']); } elseif ($range['max'] == 0) { $label = sprintf($format, $range['min']) . ' ' . __('and up', 'Shopp'); } $FacetFilter = new ProductCategoryFacetFilter(); $FacetFilter->label = $label; $FacetFilter->param = urlencode($range['min'] . '-' . $range['max']); $FacetFilter->count = $counts[$id]; $Facet->filters[$FacetFilter->param] = $FacetFilter; } } // END !empty($ranges) } } // END switch } }
/** * ecart('category','...') tags * * @since 1.0 * @version 1.1 * * @param string $property The property to handle * @param array $options (optional) The tag options to process * @return mixed **/ function tag ($property,$options=array()) { global $Ecart; $db = DB::get(); switch ($property) { case "link": case "url": return ecarturl(ECART_PRETTYURLS?'category/'.$this->uri:array('ecart_category'=>$this->id)); break; case "feed-url": case "feedurl": $uri = 'category/'.$this->uri; if ($this->slug == "tag") $uri = $this->slug.'/'.$this->tag; return ecarturl(ECART_PRETTYURLS?"$uri/feed":array('ecart_category'=>urldecode($this->uri),'src'=>'category_rss')); case "id": return $this->id; break; case "parent": return $this->parent; break; case "name": return $this->name; break; case "slug": return urldecode($this->slug); break; case "description": return wpautop($this->description); break; case "total": return $this->loaded?$this->total:false; break; case "has-products": case "loadproducts": case "load-products": case "hasproducts": if (empty($this->id) && empty($this->slug)) return false; if (isset($options['load'])) { $dataset = explode(",",$options['load']); $options['load'] = array(); foreach ($dataset as $name) $options['load'][] = trim($name); } else { $options['load'] = array('prices'); } if (!$this->loaded) $this->load_products($options); if (count($this->products) > 0) return true; else return false; break; case "products": if (!isset($this->_product_loop)) { reset($this->products); $Ecart->Product = current($this->products); $this->_pindex = 0; $this->_rindex = false; $this->_product_loop = true; } else { $Ecart->Product = next($this->products); $this->_pindex++; } if (current($this->products) !== false) return true; else { unset($this->_product_loop); $this->_pindex = 0; return false; } break; case "row": if (!isset($this->_rindex) || $this->_rindex === false) $this->_rindex = 0; else $this->_rindex++; if (empty($options['products'])) $options['products'] = $Ecart->Settings->get('row_products'); if (isset($this->_rindex) && $this->_rindex > 0 && $this->_rindex % $options['products'] == 0) return true; else return false; break; case "has-categories": case "hascategories": if (empty($this->children)) $this->load_children(); return (!empty($this->children)); break; case "is-subcategory": case "issubcategory": return ($this->parent != 0); break; case "subcategories": if (!isset($this->_children_loop)) { reset($this->children); $this->child = current($this->children); $this->_cindex = 0; $this->_children_loop = true; } else { $this->child = next($this->children); $this->_cindex++; } if ($this->child !== false) return true; else { unset($this->_children_loop); $this->_cindex = 0; $this->child = false; return false; } break; case "subcategory-list": if (isset($Ecart->Category->controls)) return false; $defaults = array( 'title' => '', 'before' => '', 'after' => '', 'class' => '', 'exclude' => '', 'orderby' => 'name', 'order' => 'ASC', 'depth' => 0, 'childof' => 0, 'parent' => false, 'showall' => false, 'linkall' => false, 'linkcount' => false, 'dropdown' => false, 'hierarchy' => false, 'products' => false, 'wraplist' => true, 'showsmart' => false ); $options = array_merge($defaults,$options); extract($options, EXTR_SKIP); if (!$this->children) $this->load_children(array('orderby'=>$orderby,'order'=>$order)); if (empty($this->children)) return false; $string = ""; $depthlimit = $depth; $depth = 0; $exclude = explode(",",$exclude); $classes = ' class="ecart_categories'.(empty($class)?'':' '.$class).'"'; $wraplist = value_is_true($wraplist); if (value_is_true($dropdown)) { $count = 0; $string .= $title; $string .= '<select name="ecart_cats" id="ecart-'.$this->slug.'-subcategories-menu" class="ecart-categories-menu">'; $string .= '<option value="">'.__('Select a sub-category…','Ecart').'</option>'; foreach ($this->children as &$category) { if (!empty($show) && $count+1 > $show) break; if (value_is_true($hierarchy) && $depthlimit && $category->depth >= $depthlimit) continue; if ($category->products == 0) continue; // Only show categories with products if (value_is_true($hierarchy) && $category->depth > $depth) { $parent = &$previous; if (!isset($parent->path)) $parent->path = '/'.$parent->slug; } $padding = str_repeat(" ",$category->depth*3); $category_uri = empty($category->id)?$category->uri:$category->id; $link = ECART_PRETTYURLS?ecarturl("category/$category->uri"):ecarturl(array('ecart_category'=>$category_uri)); $total = ''; if (value_is_true($products)) $total = ' ('.$category->products.')'; $string .= '<option value="'.htmlentities($link).'">'.$padding.$category->name.$total.'</option>'; $previous = &$category; $depth = $category->depth; $count++; } $string .= '</select>'; } else { if (!empty($class)) $classes = ' class="'.$class.'"'; $string .= $title.'<ul'.$classes.'>'; $count = 0; foreach ($this->children as &$category) { if (!isset($category->total)) $category->total = 0; if (!isset($category->depth)) $category->depth = 0; if (!empty($category->id) && in_array($category->id,$exclude)) continue; // Skip excluded categories if ($depthlimit && $category->depth >= $depthlimit) continue; if (value_is_true($hierarchy) && $category->depth > $depth) { $parent = &$previous; if (!isset($parent->path)) $parent->path = $parent->slug; $string = substr($string,0,-5); // Remove the previous </li> $active = ''; if (isset($Ecart->Category) && !empty($parent->slug) && preg_match('/(^|\/)'.$parent->path.'(\/|$)/',$Ecart->Category->uri)) { $active = ' active'; } $subcategories = '<ul class="children'.$active.'">'; $string .= $subcategories; } if (value_is_true($hierarchy) && $category->depth < $depth) { for ($i = $depth; $i > $category->depth; $i--) { if (substr($string,strlen($subcategories)*-1) == $subcategories) { // If the child menu is empty, remove the <ul> to avoid breaking standards $string = substr($string,0,strlen($subcategories)*-1).'</li>'; } else $string .= '</ul></li>'; } } $category_uri = empty($category->id)?$category->uri:$category->id; $link = ECART_PRETTYURLS? ecarturl("category/$category->uri"): ecarturl(array('ecart_category'=>$category_uri)); $total = ''; if (value_is_true($products) && $category->total > 0) $total = ' <span>('.$category->total.')</span>'; $current = ''; if (isset($Ecart->Category) && $Ecart->Category->slug == $category->slug) $current = ' class="current"'; $listing = ''; if ($category->total > 0 || isset($category->smart) || $linkall) $listing = '<a href="'.$link.'"'.$current.'>'.$category->name.($linkcount?$total:'').'</a>'.(!$linkcount?$total:''); else $listing = $category->name; if (value_is_true($showall) || $category->total > 0 || isset($category->smart) || $category->children) $string .= '<li'.$current.'>'.$listing.'</li>'; $previous = &$category; $depth = $category->depth; $count++; } if (value_is_true($hierarchy) && $depth > 0) for ($i = $depth; $i > 0; $i--) { if (substr($string,strlen($subcategories)*-1) == $subcategories) { // If the child menu is empty, remove the <ul> to avoid breaking standards $string = substr($string,0,strlen($subcategories)*-1).'</li>'; } else $string .= '</ul></li>'; } if ($wraplist) $string .= '</ul>'; } return $string; break; case "section-list": if (empty($this->id)) return false; if (isset($Ecart->Category->controls)) return false; if (empty($Ecart->Catalog->categories)) $Ecart->Catalog->load_categories(array("where"=>"(pd.status='publish' OR pd.id IS NULL)")); if (empty($Ecart->Catalog->categories)) return false; if (!$this->children) $this->load_children(); $defaults = array( 'title' => '', 'before' => '', 'after' => '', 'class' => '', 'classes' => '', 'exclude' => '', 'total' => '', 'current' => '', 'listing' => '', 'depth' => 0, 'parent' => false, 'showall' => false, 'linkall' => false, 'dropdown' => false, 'hierarchy' => false, 'products' => false, 'wraplist' => true ); $options = array_merge($defaults,$options); extract($options, EXTR_SKIP); $string = ""; $depthlimit = $depth; $depth = 0; $wraplist = value_is_true($wraplist); $exclude = explode(",",$exclude); $section = array(); // Identify root parent if (empty($this->id)) return false; $parent = '_'.$this->id; while($parent != 0) { if (!isset($Ecart->Catalog->categories[$parent])) break; if ($Ecart->Catalog->categories[$parent]->parent == 0 || $Ecart->Catalog->categories[$parent]->parent == $parent) break; $parent = '_'.$Ecart->Catalog->categories[$parent]->parent; } $root = $Ecart->Catalog->categories[$parent]; if ($this->id == $parent && empty($this->children)) return false; // Build the section $section[] = $root; $in = false; foreach ($Ecart->Catalog->categories as &$c) { if ($in && $c->depth == $root->depth) break; // Done if ($in) $section[] = $c; if (!$in && isset($c->id) && $c->id == $root->id) $in = true; } if (value_is_true($dropdown)) { $string .= $title; $string .= '<select name="ecart_cats" id="ecart-'.$this->slug.'-subcategories-menu" class="ecart-categories-menu">'; $string .= '<option value="">'.__('Select a sub-category…','Ecart').'</option>'; foreach ($section as &$category) { if (value_is_true($hierarchy) && $depthlimit && $category->depth >= $depthlimit) continue; if (in_array($category->id,$exclude)) continue; // Skip excluded categories if ($category->products == 0) continue; // Only show categories with products if (value_is_true($hierarchy) && $category->depth > $depth) { $parent = &$previous; if (!isset($parent->path)) $parent->path = '/'.$parent->slug; } $padding = str_repeat(" ",$category->depth*3); $category_uri = empty($category->id)?$category->uri:$category->id; $link = ECART_PRETTYURLS?ecarturl("category/$category->uri"):ecarturl(array('ecart_category'=>$category_uri)); $total = ''; if (value_is_true($products)) $total = ' ('.$category->total.')'; $string .= '<option value="'.htmlentities($link).'">'.$padding.$category->name.$total.'</option>'; $previous = &$category; $depth = $category->depth; } $string .= '</select>'; } else { if (!empty($class)) $classes = ' class="'.$class.'"'; $string .= $title; if ($wraplist) $string .= '<ul'.$classes.'>'; foreach ($section as &$category) { if (in_array($category->id,$exclude)) continue; // Skip excluded categories if (value_is_true($hierarchy) && $depthlimit && $category->depth >= $depthlimit) continue; if (value_is_true($hierarchy) && $category->depth > $depth) { $parent = &$previous; if (!isset($parent->path) && isset($parent->slug)) $parent->path = $parent->slug; $string = substr($string,0,-5); $string .= '<ul class="children">'; } if (value_is_true($hierarchy) && $category->depth < $depth) $string .= '</ul></li>'; $category_uri = empty($category->id)?$category->uri:$category->id; $link = ECART_PRETTYURLS?ecarturl("category/$category->uri"):ecarturl(array('ecart_category'=>$category_uri)); if (value_is_true($products)) $total = ' <span>('.$category->total.')</span>'; if ($category->total > 0 || isset($category->smart) || $linkall) $listing = '<a href="'.$link.'"'.$current.'>'.$category->name.$total.'</a>'; else $listing = $category->name; if (value_is_true($showall) || $category->total > 0 || $category->children) $string .= '<li>'.$listing.'</li>'; $previous = &$category; $depth = $category->depth; } if (value_is_true($hierarchy) && $depth > 0) for ($i = $depth; $i > 0; $i--) $string .= '</ul></li>'; if ($wraplist) $string .= '</ul>'; } return $string; break; case "pagination": if (!$this->paged) return ""; $defaults = array( 'label' => __("Pages:","Ecart"), 'next' => __("next","Ecart"), 'previous' => __("previous","Ecart"), 'jumpback' => '«', 'jumpfwd' => '»', 'show' => 1000, 'before' => '<div>', 'after' => '</div>' ); $options = array_merge($defaults,$options); extract($options); $_ = array(); if (isset($this->alpha) && $this->paged) { $_[] = $before.$label; $_[] = '<ul class="paging">'; foreach ($this->alpha as $alpha) { $link = $this->pagelink($alpha->letter); if ($alpha->total > 0) $_[] = '<li><a href="'.$link.'">'.$alpha->letter.'</a></li>'; else $_[] = '<li><span>'.$alpha->letter.'</span></li>'; } $_[] = '</ul>'; $_[] = $after; return join("\n",$_); } if ($this->pages > 1) { if ( $this->pages > $show ) $visible_pages = $show + 1; else $visible_pages = $this->pages + 1; $jumps = ceil($visible_pages/2); $_[] = $before.$label; $_[] = '<ul class="paging">'; if ( $this->page <= floor(($show) / 2) ) { $i = 1; } else { $i = $this->page - floor(($show) / 2); $visible_pages = $this->page + floor(($show) / 2) + 1; if ($visible_pages > $this->pages) $visible_pages = $this->pages + 1; if ($i > 1) { $link = $this->pagelink(1); $_[] = '<li><a href="'.$link.'">1</a></li>'; $pagenum = ($this->page - $jumps); if ($pagenum < 1) $pagenum = 1; $link = $this->pagelink($pagenum); $_[] = '<li><a href="'.$link.'">'.$jumpback.'</a></li>'; } } // Add previous button if (!empty($previous) && $this->page > 1) { $prev = $this->page-1; $link = $this->pagelink($prev); $_[] = '<li class="previous"><a href="'.$link.'">'.$previous.'</a></li>'; } else $_[] = '<li class="previous disabled">'.$previous.'</li>'; // end previous button while ($i < $visible_pages) { $link = $this->pagelink($i); if ( $i == $this->page ) $_[] = '<li class="active">'.$i.'</li>'; else $_[] = '<li><a href="'.$link.'">'.$i.'</a></li>'; $i++; } if ($this->pages > $visible_pages) { $pagenum = ($this->page + $jumps); if ($pagenum > $this->pages) $pagenum = $this->pages; $link = $this->pagelink($pagenum); $_[] = '<li><a href="'.$link.'">'.$jumpfwd.'</a></li>'; $_[] = '<li><a href="'.$link.'">'.$this->pages.'</a></li>'; } // Add next button if (!empty($next) && $this->page < $this->pages) { $pagenum = $this->page+1; $link = $this->pagelink($pagenum); $_[] = '<li class="next"><a href="'.$link.'">'.$next.'</a></li>'; } else $_[] = '<li class="next disabled">'.$next.'</li>'; $_[] = '</ul>'; $_[] = $after; } return join("\n",$_); break; case "has-faceted-menu": return ($this->facetedmenus == "on"); break; case "faceted-menu": if ($this->facetedmenus == "off") return; $output = ""; $CategoryFilters =& $Ecart->Flow->Controller->browsing[$this->slug]; $link = $_SERVER['REQUEST_URI']; if (!isset($options['cancel'])) $options['cancel'] = "X"; if (strpos($_SERVER['REQUEST_URI'],"?") !== false) list($link,$query) = explode("?",$_SERVER['REQUEST_URI']); $query = $_GET; $query = http_build_query($query); $link = esc_url($link).'?'.$query; $list = ""; if (is_array($CategoryFilters)) { foreach($CategoryFilters AS $facet => $filter) { $href = add_query_arg('ecart_catfilters['.urlencode($facet).']','',$link); if (preg_match('/^(.*?(\d+[\.\,\d]*).*?)\-(.*?(\d+[\.\,\d]*).*)$/',$filter,$matches)) { $label = $matches[1].' — '.$matches[3]; if ($matches[2] == 0) $label = __('Under ','Ecart').$matches[3]; if ($matches[4] == 0) $label = $matches[1].' '.__('and up','Ecart'); } else $label = $filter; if (!empty($filter)) $list .= '<li><strong>'.$facet.'</strong>: '.stripslashes($label).' <a href="'.$href.'=" class="cancel">'.$options['cancel'].'</a></li>'; } $output .= '<ul class="filters enabled">'.$list.'</ul>'; } if ($this->pricerange == "auto" && empty($CategoryFilters['Price'])) { if (!$this->loaded) $this->load_products(); $list = ""; $this->priceranges = auto_ranges($this->pricing['average'],$this->pricing['max'],$this->pricing['min']); foreach ($this->priceranges as $range) { $href = add_query_arg('ecart_catfilters[Price]',urlencode(money($range['min']).'-'.money($range['max'])),$link); $label = money($range['min']).' — '.money($range['max']-0.01); if ($range['min'] == 0) $label = __('Under ','Ecart').money($range['max']); elseif ($range['max'] == 0) $label = money($range['min']).' '.__('and up','Ecart'); $list .= '<li><a href="'.$href.'">'.$label.'</a></li>'; } if (!empty($this->priceranges)) $output .= '<h4>'.__('Price Range','Ecart').'</h4>'; $output .= '<ul>'.$list.'</ul>'; } $catalogtable = DatabaseObject::tablename(Catalog::$table); $producttable = DatabaseObject::tablename(Product::$table); $spectable = DatabaseObject::tablename(Spec::$table); $query = "SELECT spec.name,spec.value, IF(spec.numeral > 0,spec.name,spec.value) AS merge, count(*) AS total,avg(numeral) AS avg,max(numeral) AS max,min(numeral) AS min FROM $catalogtable AS cat LEFT JOIN $producttable AS p ON cat.product=p.id LEFT JOIN $spectable AS spec ON p.id=spec.parent AND spec.context='product' AND spec.type='spec' WHERE cat.parent=$this->id AND cat.type='category' AND spec.value != '' AND spec.value != '0' GROUP BY merge ORDER BY spec.name,merge"; $results = $db->query($query,AS_ARRAY); $specdata = array(); foreach ($results as $data) { if (isset($specdata[$data->name])) { if (!is_array($specdata[$data->name])) $specdata[$data->name] = array($specdata[$data->name]); $specdata[$data->name][] = $data; } else $specdata[$data->name] = $data; } if (is_array($this->specs)) { foreach ($this->specs as $spec) { $list = ""; if (!empty($CategoryFilters[$spec['name']])) continue; // For custom menu presets if ($spec['facetedmenu'] == "custom" && !empty($spec['options'])) { foreach ($spec['options'] as $option) { $href = add_query_arg('ecart_catfilters['.$spec['name'].']',urlencode($option['name']),$link); $list .= '<li><a href="'.$href.'">'.$option['name'].'</a></li>'; } $output .= '<h4>'.$spec['name'].'</h4><ul>'.$list.'</ul>'; // For preset ranges } elseif ($spec['facetedmenu'] == "ranges" && !empty($spec['options'])) { foreach ($spec['options'] as $i => $option) { $matches = array(); $format = '%s-%s'; $next = 0; if (isset($spec['options'][$i+1])) { if (preg_match('/(\d+[\.\,\d]*)/',$spec['options'][$i+1]['name'],$matches)) $next = $matches[0]; } $matches = array(); $range = array("min" => 0,"max" => 0); if (preg_match('/^(.*?)(\d+[\.\,\d]*)(.*)$/',$option['name'],$matches)) { $base = $matches[2]; $format = $matches[1].'%s'.$matches[3]; if (!isset($spec['options'][$i+1])) $range['min'] = $base; else $range = array("min" => $base, "max" => ($next-1)); } if ($i == 1) { $href = add_query_arg('ecart_catfilters['.$spec['name'].']', urlencode(sprintf($format,'0',$range['min'])),$link); $label = __('Under ','Ecart').sprintf($format,$range['min']); $list .= '<li><a href="'.$href.'">'.$label.'</a></li>'; } $href = add_query_arg('ecart_catfilters['.$spec['name'].']', urlencode(sprintf($format,$range['min'],$range['max'])), $link); $label = sprintf($format,$range['min']).' — '.sprintf($format,$range['max']); if ($range['max'] == 0) $label = sprintf($format,$range['min']).' '.__('and up','Ecart'); $list .= '<li><a href="'.$href.'">'.$label.'</a></li>'; } $output .= '<h4>'.$spec['name'].'</h4><ul>'.$list.'</ul>'; // For automatically building the menu options } elseif ($spec['facetedmenu'] == "auto" && isset($specdata[$spec['name']])) { if (is_array($specdata[$spec['name']])) { // Generate from text values foreach ($specdata[$spec['name']] as $option) { $href = add_query_arg('ecart_catfilters['.$spec['name'].']',urlencode($option->value),$link); $list .= '<li><a href="'.$href.'">'.$option->value.'</a></li>'; } $output .= '<h4>'.$spec['name'].'</h4><ul>'.$list.'</ul>'; } else { // Generate number ranges $format = '%s'; if (preg_match('/^(.*?)(\d+[\.\,\d]*)(.*)$/',$specdata[$spec['name']]->content,$matches)) $format = $matches[1].'%s'.$matches[3]; $ranges = auto_ranges($specdata[$spec['name']]->avg,$specdata[$spec['name']]->max,$specdata[$spec['name']]->min); foreach ($ranges as $range) { $href = add_query_arg('ecart_catfilters['.$spec['name'].']', urlencode($range['min'].'-'.$range['max']), $link); $label = sprintf($format,$range['min']).' — '.sprintf($format,$range['max']); if ($range['min'] == 0) $label = __('Under ','Ecart').sprintf($format,$range['max']); elseif ($range['max'] == 0) $label = sprintf($format,$range['min']).' '.__('and up','Ecart'); $list .= '<li><a href="'.$href.'">'.$label.'</a></li>'; } if (!empty($list)) $output .= '<h4>'.$spec['name'].'</h4>'; $output .= '<ul>'.$list.'</ul>'; } } } } return $output; break; case "hasimages": case "has-images": if (empty($this->images)) $this->load_images(); if (empty($this->images)) return false; return true; break; case "images": if (!isset($this->_images_loop)) { reset($this->images); $this->_images_loop = true; } else next($this->images); if (current($this->images) !== false) return true; else { unset($this->_images_loop); return false; } break; case "coverimage": case "thumbnail": // deprecated // Force select the first loaded image unset($options['id']); $options['index'] = 0; case "image": if (empty($this->images)) $this->load_images(); if (!(count($this->images) > 0)) return ""; // Compatibility defaults $_size = 96; $_width = $Ecart->Settings->get('gallery_thumbnail_width'); $_height = $Ecart->Settings->get('gallery_thumbnail_height'); if (!$_width) $_width = $_size; if (!$_height) $_height = $_size; $defaults = array( 'img' => false, 'id' => false, 'index' => false, 'class' => '', 'width' => false, 'height' => false, 'width_a' => false, 'height_a' => false, 'size' => false, 'fit' => false, 'sharpen' => false, 'quality' => false, 'bg' => false, 'alt' => '', 'title' => '', 'zoom' => '', 'zoomfx' => 'ecart-zoom', 'property' => false ); $options = array_merge($defaults,$options); extract($options); // Select image by database id if ($id !== false) { for ($i = 0; $i < count($this->images); $i++) { if ($img->id == $id) { $img = $this->images[$i]; break; } } if (!$img) return ""; } // Select image by index position in the list if ($index !== false && isset($this->images[$index])) $img = $this->images[$index]; // Use the current image pointer by default if (!$img) $img = current($this->images); if ($size !== false) $width = $height = $size; if (!$width) $width = $_width; if (!$height) $height = $_height; $scale = $fit?array_search($fit,$img->_scaling):false; $sharpen = $sharpen?min($sharpen,$img->_sharpen):false; $quality = $quality?min($quality,$img->_quality):false; $fill = $bg?hexdec(ltrim($bg,'#')):false; list($width_a,$height_a) = array_values($img->scaled($width,$height,$scale)); if ($size == "original") { $width_a = $img->width; $height_a = $img->height; } if ($width_a === false) $width_a = $width; if ($height_a === false) $height_a = $height; $alt = esc_attr(empty($alt)?(empty($img->alt)?$img->name:$img->alt):$alt); $title = empty($title)?$img->title:$title; $titleattr = empty($title)?'':' title="'.esc_attr($title).'"'; $classes = empty($class)?'':' class="'.esc_attr($class).'"'; $src = ecarturl($img->id,'images'); if ($size != "original") { $src = add_query_string( $img->resizing($width,$height,$scale,$sharpen,$quality,$fill), trailingslashit(ecarturl($img->id,'images')).$img->filename ); } switch (strtolower($property)) { case "id": return $img->id; break; case "url": case "src": return $src; break; case "title": return $title; break; case "alt": return $alt; break; case "width": return $width_a; break; case "height": return $height_a; break; case "class": return $class; break; } $imgtag = '<img src="'.$src.'"'.$titleattr.' alt="'.$alt.'" width="'.$width_a.'" height="'.$height_a.'" '.$classes.' />'; if (value_is_true($zoom)) return '<a href="'.ecarturl($img->id,'images').'/'.$img->filename.'" class="'.$zoomfx.'" rel="product-'.$this->id.'">'.$imgtag.'</a>'; return $imgtag; break; case "slideshow": $options['load'] = array('images'); if (!$this->loaded) $this->load_products($options); if (count($this->products) == 0) return false; $defaults = array( 'width' => '440', 'height' => '180', 'fit' => 'crop', 'fx' => 'fade', 'duration' => 1000, 'delay' => 7000, 'order' => 'normal' ); $options = array_merge($defaults,$options); extract($options, EXTR_SKIP); $href = ecarturl(ECART_PERMALINKS?trailingslashit('000'):'000','images'); $imgsrc = add_query_string("$width,$height",$href); $string = '<ul class="slideshow '.$fx.'-fx '.$order.'-order duration-'.$duration.' delay-'.$delay.'">'; $string .= '<li class="clear"><img src="'.$imgsrc.'" width="'.$width.'" height="'.$height.'" /></li>'; foreach ($this->products as $Product) { if (empty($Product->images)) continue; $string .= '<li><a href="'.$Product->tag('url').'">'; $string .= $Product->tag('image',array('width'=>$width,'height'=>$height,'fit'=>$fit)); $string .= '</a></li>'; } $string .= '</ul>'; return $string; break; case "carousel": $options['load'] = array('images'); if (!$this->loaded) $this->load_products($options); if (count($this->products) == 0) return false; $defaults = array( 'imagewidth' => '96', 'imageheight' => '96', 'fit' => 'all', 'duration' => 500 ); $options = array_merge($defaults,$options); extract($options, EXTR_SKIP); $string = '<div class="carousel duration-'.$duration.'">'; $string .= '<div class="frame">'; $string .= '<ul>'; foreach ($this->products as $Product) { if (empty($Product->images)) continue; $string .= '<li><a href="'.$Product->tag('url').'">'; $string .= $Product->tag('image',array('width'=>$imagewidth,'height'=>$imageheight,'fit'=>$fit)); $string .= '</a></li>'; } $string .= '</ul></div>'; $string .= '<button type="button" name="left" class="left"> </button>'; $string .= '<button type="button" name="right" class="right"> </button>'; $string .= '</div>'; return $string; break; } }
function tag($property, $options = array()) { global $Shopp; $db = DB::get(); $page = $Shopp->link('catalog'); if (SHOPP_PERMALINKS) { $imageuri = trailingslashit($page) . "images/"; } else { $imageuri = add_query_arg('shopp_image', '=', $page); } if (SHOPP_PERMALINKS) { $pages = $Shopp->Settings->get('pages'); if ($page == trailingslashit(get_bloginfo('url'))) { $page .= $pages['catalog']['name'] . "/"; } } switch ($property) { case "link": case "url": return SHOPP_PERMALINKS ? $Shopp->shopuri . "category/" . urldecode($this->uri) : add_query_arg('shopp_category', $this->id, $Shopp->shopuri); break; case "id": return $this->id; break; case "name": return $this->name; break; case "slug": return urldecode($this->slug); break; case "description": return wpautop($this->description); break; case "total": return $this->total; break; case "has-products": case "hasproducts": if (empty($this->id) && empty($this->slug)) { return false; } if (isset($options['load'])) { $dataset = explode(",", $options['load']); $options['load'] = array(); foreach ($dataset as $name) { $options['load'][] = trim($name); } } else { $options['load'] = array('prices'); } if (!$this->loaded) { $this->load_products($options); } if (count($this->products) > 0) { return true; } else { return false; } break; case "products": if (!$this->productloop) { reset($this->products); $Shopp->Product = current($this->products); $this->productsidx = 0; $this->productloop = true; } else { $Shopp->Product = next($this->products); $this->productsidx++; } if (current($this->products)) { $Shopp->Product = current($this->products); return true; } else { $this->productloop = false; return false; } break; case "row": if (empty($options['products'])) { $options['products'] = $Shopp->Settings->get('row_products'); } if ($this->productsidx > 0 && $this->productsidx % $options['products'] == 0) { return true; } else { return false; } break; case "has-categories": case "hascategories": if (empty($this->children)) { $this->load_children(); } return !empty($this->children); break; case "is-subcategory": case "issubcategory": return $this->parent != 0; break; case "subcategories": if (!$this->childloop) { reset($this->children); $this->child = current($this->children); $this->childidx = 0; $this->childloop = true; } else { $this->child = next($this->children); $this->childidx++; } if (current($this->children)) { $this->child = current($this->children); return true; } else { $this->childloop = false; return false; } break; case "subcategory-list": if (isset($Shopp->Category->controls)) { return false; } $defaults = array('title' => '', 'before' => '', 'after' => '', 'class' => '', 'depth' => 0, 'orderby' => 'name', 'order' => 'ASC', 'parent' => false, 'showall' => false, 'dropdown' => false, 'hierarchy' => false, 'products' => false); $options = array_merge($defaults, $options); extract($options, EXTR_SKIP); if (!$this->children) { $this->load_children(array('orderby' => $orderby, 'order' => $order)); } if (empty($this->children)) { return false; } $string = ""; $depthlimit = $depth; $depth = 0; $count = 0; if (value_is_true($dropdown)) { $string .= $title; $string .= '<select name="shopp_cats" id="shopp-' . $this->slug . '-subcategories-menu" class="shopp-categories-menu">'; $string .= '<option value="">' . __('Select a sub-category…', 'Shopp') . '</option>'; foreach ($this->children as &$category) { if (!empty($show) && $count + 1 > $show) { break; } if (value_is_true($hierarchy) && $depthlimit && $category->depth >= $depthlimit) { continue; } if ($category->products == 0) { continue; } // Only show categories with products if (value_is_true($hierarchy) && $category->depth > $depth) { $parent =& $previous; if (!isset($parent->path)) { $parent->path = '/' . $parent->slug; } } $padding = str_repeat(" ", $category->depth * 3); if (SHOPP_PERMALINKS) { $link = $Shopp->shopuri . 'category/' . $category->uri; } else { $link = add_query_arg('shopp_category', $category->id, $Shopp->shopuri); } $total = ''; if (value_is_true($products)) { $total = ' (' . $category->products . ')'; } $string .= '<option value="' . htmlentities($link) . '">' . $padding . $category->name . $total . '</option>'; $previous =& $category; $depth = $category->depth; $count++; } $string .= '</select>'; $string .= '<script type="text/javascript">'; $string .= 'var menu = document.getElementById(\'shopp-' . $this->slug . '-subcategories-menu\');'; $string .= 'if (menu)'; $string .= ' menu.onchange = function () {'; $string .= ' document.location.href = this.options[this.selectedIndex].value;'; $string .= ' }'; $string .= '</script>'; } else { if (!empty($class)) { $classes = ' class="' . $class . '"'; } $string .= $title . '<ul' . $classes . '>'; foreach ($this->children as &$category) { if (!empty($show) && $count + 1 > $show) { break; } if (value_is_true($hierarchy) && $depthlimit && $category->depth >= $depthlimit) { continue; } if (value_is_true($hierarchy) && $category->depth > $depth) { $parent =& $previous; if (!isset($parent->path)) { $parent->path = $parent->slug; } $string .= '<ul class="children">'; } if (value_is_true($hierarchy) && $category->depth < $depth) { $string .= '</ul>'; } if (SHOPP_PERMALINKS) { $link = $Shopp->shopuri . 'category/' . $category->uri; } else { $link = add_query_arg('shopp_category', $category->id, $Shopp->shopuri); } $total = ''; if (value_is_true($products)) { $total = ' (' . $category->products . ')'; } if (value_is_true($showall) || $category->products > 0 || $category->smart) { // Only show categories with products $string .= '<li><a href="' . $link . '">' . $category->name . '</a>' . $total . '</li>'; } $previous =& $category; $depth = $category->depth; $count++; } if (value_is_true($hierarchy)) { for ($i = 0; $i < $depth; $i++) { $string .= "</ul>"; } } $string .= '</ul>'; } return $string; break; case "section-list": if (empty($this->id)) { return false; } if (isset($Shopp->Category->controls)) { return false; } if (empty($Shopp->Catalog->categories)) { $Shopp->Catalog->load_categories(array("where" => "(pd.published='on' OR pd.id IS NULL)")); } if (empty($Shopp->Catalog->categories)) { return false; } if (!$this->children) { $this->load_children(); } $defaults = array('title' => '', 'before' => '', 'after' => '', 'class' => '', 'classes' => '', 'exclude' => '', 'total' => '', 'current' => '', 'listing' => '', 'depth' => 0, 'parent' => false, 'showall' => false, 'linkall' => false, 'dropdown' => false, 'hierarchy' => false, 'products' => false, 'wraplist' => true); $options = array_merge($defaults, $options); extract($options, EXTR_SKIP); $string = ""; $depthlimit = $depth; $depth = 0; $wraplist = value_is_true($wraplist); $exclude = explode(",", $exclude); $section = array(); // Identify root parent if (empty($this->id)) { return false; } $parent = $this->id; while ($parent != 0) { if ($Shopp->Catalog->categories[$parent]->parent == 0 || $Shopp->Catalog->categories[$parent]->parent == $parent) { break; } $parent = $Shopp->Catalog->categories[$parent]->parent; } $root = $Shopp->Catalog->categories[$parent]; if ($this->id == $parent && empty($this->children)) { return false; } // Build the section $section[] = $root; $in = false; foreach ($Shopp->Catalog->categories as &$c) { if ($in && $c->depth == $root->depth) { break; } // Done if ($in) { $section[] = $c; } if (!$in && isset($c->id) && $c->id == $root->id) { $in = true; } } if (value_is_true($dropdown)) { $string .= $title; $string .= '<select name="shopp_cats" id="shopp-' . $this->slug . '-subcategories-menu" class="shopp-categories-menu">'; $string .= '<option value="">' . __('Select a sub-category…', 'Shopp') . '</option>'; foreach ($section as &$category) { if (value_is_true($hierarchy) && $depthlimit && $category->depth >= $depthlimit) { continue; } if (in_array($category->id, $exclude)) { continue; } // Skip excluded categories if ($category->products == 0) { continue; } // Only show categories with products if (value_is_true($hierarchy) && $category->depth > $depth) { $parent =& $previous; if (!isset($parent->path)) { $parent->path = '/' . $parent->slug; } } $padding = str_repeat(" ", $category->depth * 3); if (SHOPP_PERMALINKS) { $link = $Shopp->shopuri . 'category/' . $category->uri; } else { $link = add_query_arg('shopp_category', $category->id, $Shopp->shopuri); } $total = ''; if (value_is_true($products)) { $total = ' (' . $category->total . ')'; } $string .= '<option value="' . htmlentities($link) . '">' . $padding . $category->name . $total . '</option>'; $previous =& $category; $depth = $category->depth; } $string .= '</select>'; $string .= '<script type="text/javascript">'; $string .= 'var menu = document.getElementById(\'shopp-' . $this->slug . '-subcategories-menu\');'; $string .= 'if (menu)'; $string .= ' menu.onchange = function () {'; $string .= ' document.location.href = this.options[this.selectedIndex].value;'; $string .= ' }'; $string .= '</script>'; } else { if (!empty($class)) { $classes = ' class="' . $class . '"'; } $string .= $title; if ($wraplist) { $string .= '<ul' . $classes . '>'; } foreach ($section as &$category) { if (in_array($category->id, $exclude)) { continue; } // Skip excluded categories if (value_is_true($hierarchy) && $depthlimit && $category->depth >= $depthlimit) { continue; } if (value_is_true($hierarchy) && $category->depth > $depth) { $parent =& $previous; if (!isset($parent->path) && isset($parent->slug)) { $parent->path = $parent->slug; } $string = substr($string, 0, -5); $string .= '<ul class="children">'; } if (value_is_true($hierarchy) && $category->depth < $depth) { $string .= '</ul></li>'; } if (SHOPP_PERMALINKS) { $link = $Shopp->shopuri . 'category/' . $category->uri; } else { $link = add_query_arg('shopp_category', $category->id, $Shopp->shopuri); } if (value_is_true($products)) { $total = ' <span>(' . $category->total . ')</span>'; } if ($category->total > 0 || isset($category->smart) || $linkall) { $listing = '<a href="' . $link . '"' . $current . '>' . $category->name . $total . '</a>'; } else { $listing = $category->name; } if (value_is_true($showall) || $category->total > 0 || $category->children) { $string .= '<li>' . $listing . '</li>'; } $previous =& $category; $depth = $category->depth; } if (value_is_true($hierarchy) && $depth > 0) { for ($i = $depth; $i > 0; $i--) { $string .= '</ul></li>'; } } if ($wraplist) { $string .= '</ul>'; } } return $string; break; case "pagination": if (!$this->paged) { return ""; } global $wp; // Set options if (!isset($options['label'])) { $options['label'] = __("Pages:", "Shopp"); } if (!isset($options['next'])) { $options['next'] = __("next", "Shopp"); } if (!isset($options['previous'])) { $options['previous'] = __("previous", "Shopp"); } $navlimit = 1000; if (!empty($options['show'])) { $navlimit = $options['show']; } $before = "<div>" . $options['label']; // Set the label if (!empty($options['before'])) { $before = $options['before']; } $after = "</div>"; if (!empty($options['after'])) { $after = $options['after']; } $type = "category"; if (isset($wp->query_vars['shopp_tag'])) { $type = "tag"; } $string = ""; if (isset($this->alpha) && $this->paged) { $string .= '<ul class="paging">'; foreach ($this->alpha as $alpha) { $link = SHOPP_PERMALINKS ? "{$page}" . "{$type}/{$this->uri}/page/{$alpha->letter}/" : "{$page}&shopp_{$type}={$this->uri}&paged={$alpha->letter}"; if ($alpha->total > 0) { $string .= '<li><a href="' . $link . '">' . $alpha->letter . '</a></li>'; } else { $string .= '<li><span>' . $alpha->letter . '</span></li>'; } } $string .= '</ul>'; return $string; } if ($this->pages > 1) { if ($this->pages > $navlimit) { $visible_pages = $navlimit + 1; } else { $visible_pages = $this->pages + 1; } $jumps = ceil($visible_pages / 2); $string .= $before; $string .= '<ul class="paging">'; if ($this->page <= floor($navlimit / 2)) { $i = 1; } else { $i = $this->page - floor($navlimit / 2); $visible_pages = $this->page + floor($navlimit / 2) + 1; if ($visible_pages > $this->pages) { $visible_pages = $this->pages + 1; } if ($i > 1) { $link = SHOPP_PERMALINKS ? "{$page}" . "{$type}/{$this->uri}/page/{$i}/" : "{$page}&shopp_{$type}={$this->uri}&paged={$i}"; $string .= '<li><a href="' . $link . '">1</a></li>'; $pagenum = $this->page - $jumps; if ($pagenum < 1) { $pagenum = 1; } $link = SHOPP_PERMALINKS ? "{$page}" . "{$type}/{$this->uri}/page/{$pagenum}/" : "{$page}&shopp_{$type}={$this->uri}&paged={$pagenum}"; $string .= '<li><a href="' . $link . '">«</a></li>'; } } // Add previous button if (!value_is_true($options['previous']) && $this->page > 1) { $prev = $this->page - 1; $link = SHOPP_PERMALINKS ? "{$page}" . "{$type}/{$this->uri}/page/{$prev}/" : "{$page}&shopp_{$type}={$this->uri}&paged={$prev}"; $string .= '<li class="previous"><a href="' . $link . '">' . $options['previous'] . '</a></li>'; } else { $string .= '<li class="previous disabled">' . $options['previous'] . '</li>'; } // end previous button while ($i < $visible_pages) { $link = SHOPP_PERMALINKS ? "{$page}" . "{$type}/{$this->uri}/page/{$i}/" : "{$page}&shopp_{$type}={$this->uri}&paged={$i}"; if ($i == $this->page) { $string .= '<li class="active">' . $i . '</li>'; } else { $string .= '<li><a href="' . $link . '">' . $i . '</a></li>'; } $i++; } if ($this->pages > $visible_pages) { $pagenum = $this->page + $jumps; if ($pagenum > $this->pages) { $pagenum = $this->pages; } $link = SHOPP_PERMALINKS ? "{$page}" . "{$type}/{$this->uri}/page/{$pagenum}/" : "{$page}&shopp_{$type}={$this->uri}&paged={$pagenum}"; $string .= '<li><a href="' . $link . '">»</a></li>'; $link = SHOPP_PERMALINKS ? "{$page}" . "{$type}/{$this->uri}/page/{$this->pages}/" : "{$page}&shopp_{$type}={$this->uri}&paged={$this->pages}"; $string .= '<li><a href="' . $link . '">' . $this->pages . '</a></li>'; } // Add next button if (!value_is_true($options['next']) && $this->page < $this->pages) { $next = $this->page + 1; $link = SHOPP_PERMALINKS ? "{$page}" . "{$type}/{$this->uri}/page/{$next}/" : "{$page}&shopp_{$type}={$this->uri}&paged={$next}"; $string .= '<li class="next"><a href="' . $link . '">' . $options['next'] . '</a></li>'; } else { $string .= '<li class="next disabled">' . $options['next'] . '</li>'; } $string .= '</ul>'; $string .= $after; } return $string; break; case "has-faceted-menu": return $this->facetedmenus == "on"; break; case "faceted-menu": if ($this->facetedmenus == "off") { return; } $output = ""; $CategoryFilters =& $Shopp->Cart->data->Category[$this->slug]; $link = $_SERVER['REQUEST_URI']; if (!isset($options['cancel'])) { $options['cancel'] = "X"; } if (strpos($_SERVER['REQUEST_URI'], "?") !== false) { list($link, $query) = explode("?", $_SERVER['REQUEST_URI']); } $query = $_GET; unset($query['shopp_catfilters']); $query = http_build_query($query); if (!empty($query)) { $query .= '&'; } $list = ""; if (is_array($CategoryFilters)) { foreach ($CategoryFilters as $facet => $filter) { $href = add_query_arg('shopp_catfilters[' . urlencode($facet) . ']', '', esc_url($link)); if (preg_match('/^(.*?(\\d+[\\.\\,\\d]*).*?)\\-(.*?(\\d+[\\.\\,\\d]*).*)$/', $filter, $matches)) { $label = $matches[1] . ' — ' . $matches[3]; if ($matches[2] == 0) { $label = __('Under ', 'Shopp') . $matches[3]; } if ($matches[4] == 0) { $label = $matches[1] . ' ' . __('and up', 'Shopp'); } } else { $label = $filter; } if (!empty($filter)) { $list .= '<li><strong>' . $facet . '</strong>: ' . stripslashes($label) . ' <a href="' . $href . '" class="cancel">' . $options['cancel'] . '</a></li>'; } } $output .= '<ul class="filters enabled">' . $list . '</ul>'; } if ($this->pricerange == "auto" && empty($CategoryFilters['Price'])) { if (!$this->loaded) { $this->load_products(); } $list = ""; $this->priceranges = auto_ranges($this->pricing['average'], $this->pricing['max'], $this->pricing['min']); foreach ($this->priceranges as $range) { $href = add_query_arg('shopp_catfilters[Price]', urlencode(money($range['min']) . '-' . money($range['max'])), esc_url($link)); $label = money($range['min']) . ' — ' . money($range['max'] - 0.01); if ($range['min'] == 0) { $label = __('Under ', 'Shopp') . money($range['max']); } elseif ($range['max'] == 0) { $label = money($range['min']) . ' ' . __('and up', 'Shopp'); } $list .= '<li><a href="' . $href . '">' . $label . '</a></li>'; } if (!empty($this->priceranges)) { $output .= '<h4>' . __('Price Range', 'Shopp') . '</h4>'; } $output .= '<ul>' . $list . '</ul>'; } $catalogtable = DatabaseObject::tablename(Catalog::$table); $producttable = DatabaseObject::tablename(Product::$table); $spectable = DatabaseObject::tablename(Spec::$table); $results = $db->query("SELECT spec.name,spec.content,\n\t\t\t\t\tIF(spec.numeral > 0,spec.name,spec.content) AS merge,\n\t\t\t\t\tcount(*) AS total,avg(numeral) AS avg,max(numeral) AS max,min(numeral) AS min \n\t\t\t\t\tFROM {$catalogtable} AS cat \n\t\t\t\t\tLEFT JOIN {$producttable} AS p ON cat.product=p.id \n\t\t\t\t\tLEFT JOIN {$spectable} AS spec ON spec.product=p.id \n\t\t\t\t\tWHERE cat.category={$this->id} GROUP BY merge ORDER BY spec.name,merge", AS_ARRAY); $specdata = array(); foreach ($results as $data) { if (isset($specdata[$data->name])) { if (!is_array($specdata[$data->name])) { $specdata[$data->name] = array($specdata[$data->name]); } $specdata[$data->name][] = $data; } else { $specdata[$data->name] = $data; } } if (is_array($this->specs)) { foreach ($this->specs as $spec) { $list = ""; if (!empty($CategoryFilters[$spec['name']])) { continue; } // For custom menu presets if ($spec['facetedmenu'] == "custom" && !empty($spec['options'])) { foreach ($spec['options'] as $option) { $href = add_query_arg('shopp_catfilters[' . $spec['name'] . ']', urlencode($option['name']), esc_url($_SERVER['REQUEST_URI'])); $list .= '<li><a href="' . $href . '">' . $option['name'] . '</a></li>'; } $output .= '<h4>' . $spec['name'] . '</h4><ul>' . $list . '</ul>'; // For preset ranges } elseif ($spec['facetedmenu'] == "ranges" && !empty($spec['options'])) { foreach ($spec['options'] as $i => $option) { $matches = array(); $format = '%s'; $next = 0; if (isset($spec['options'][$i + 1])) { if (preg_match('/(\\d+[\\.\\,\\d]*)/', $spec['options'][$i + 1]['name'], $matches)) { $next = $matches[0]; } } $matches = array(); $range = array("min" => 0, "max" => 0); if (preg_match('/^(.*?)(\\d+[\\.\\,\\d]*)(.*)$/', $option['name'], $matches)) { $base = $matches[2]; $format = $matches[1] . '%s' . $matches[3]; if (!isset($spec['options'][$i + 1])) { $range['min'] = $base; } else { $range = array("min" => $base, "max" => $next - 1); } } if ($i == 1) { $href = esc_url($link . '?' . $query) . 'shopp_catfilters[' . $spec['name'] . ']=' . urlencode(sprintf($format, '0') . '-' . sprintf($format, $range['min'])); $label = __('Under ', 'Shopp') . sprintf($format, $range['min']); $list .= '<li><a href="' . $href . '">' . $label . '</a></li>'; } $href = esc_url($link . '?' . $query) . 'shopp_catfilters[' . $spec['name'] . ']=' . urlencode(sprintf($format, $range['min']) . '-' . sprintf($format, $range['max'])); $label = sprintf($format, $range['min']) . ' — ' . sprintf($format, $range['max']); if ($range['max'] == 0) { $label = sprintf($format, $range['min']) . ' ' . __('and up', 'Shopp'); } $list .= '<li><a href="' . $href . '">' . $label . '</a></li>'; } $output .= '<h4>' . $spec['name'] . '</h4><ul>' . $list . '</ul>'; // For automatically building the menu options } elseif ($spec['facetedmenu'] == "auto" && isset($specdata[$spec['name']])) { if (is_array($specdata[$spec['name']])) { // Generate from text values foreach ($specdata[$spec['name']] as $option) { $href = esc_url($link . '?' . $query) . 'shopp_catfilters[' . $spec['name'] . ']=' . urlencode($option->content); $list .= '<li><a href="' . $href . '">' . $option->content . '</a></li>'; } $output .= '<h4>' . $spec['name'] . '</h4><ul>' . $list . '</ul>'; } else { // Generate number ranges $format = '%s'; if (preg_match('/^(.*?)(\\d+[\\.\\,\\d]*)(.*)$/', $specdata[$spec['name']]->content, $matches)) { $format = $matches[1] . '%s' . $matches[3]; } $ranges = auto_ranges($specdata[$spec['name']]->avg, $specdata[$spec['name']]->max, $specdata[$spec['name']]->min); foreach ($ranges as $range) { $href = esc_url($link . '?' . $query . 'shopp_catfilters[' . $spec['name'] . ']=' . urlencode($range['min'] . '-' . $range['max'])); $label = sprintf($format, $range['min']) . ' — ' . sprintf($format, $range['max']); if ($range['min'] == 0) { $label = __('Under ', 'Shopp') . sprintf($format, $range['max']); } elseif ($range['max'] == 0) { $label = sprintf($format, $range['min']) . ' ' . __('and up', 'Shopp'); } $list .= '<li><a href="' . $href . '">' . $label . '</a></li>'; } if (!empty($list)) { $output .= '<h4>' . $spec['name'] . '</h4>'; } $output .= '<ul>' . $list . '</ul>'; } } } } return $output; break; case "thumbnail": if (empty($this->images)) { $this->load_images(); } if (!empty($options['class'])) { $options['class'] = ' class="' . $options['class'] . '"'; } if (isset($this->thumbnail)) { $img = $this->thumbnail; return '<img src="' . $imageuri . $img->id . '" alt="' . $this->name . ' ' . $img->datatype . '" width="' . $img->properties['width'] . '" height="' . $img->properties['height'] . '" ' . $options['class'] . ' />'; break; } break; case "has-images": if (empty($options['type'])) { $options['type'] = "thumbnail"; } if (empty($this->images)) { $this->load_images(); } return count($this->images[$options['type']]) > 0; break; case "images": if (empty($options['type'])) { $options['type'] = "thumbnail"; } if (!$this->imageloop) { reset($this->images[$options['type']]); $this->imageloop = true; } else { next($this->images[$options['type']]); } if (current($this->images[$options['type']])) { return true; } else { $this->imageloop = false; return false; } break; case "image": if (empty($options['type'])) { $options['type'] = "thumbnail"; } $img = current($this->images[$options['type']]); if (!empty($options['class'])) { $options['class'] = ' class="' . $options['class'] . '"'; } $string = ""; if (!empty($options['zoom'])) { $string .= '<a href="' . $imageuri . $img->src . '/' . str_replace('small_', '', $img->name) . '" class="shopp-thickbox" rel="product-gallery">'; } $string .= '<img src="' . $imageuri . $img->id . '" alt="' . $this->name . ' ' . $img->datatype . '" width="' . $img->properties['width'] . '" height="' . $img->properties['height'] . '" ' . $options['class'] . ' />'; if (!empty($options['zoom'])) { $string .= "</a>"; } return $string; break; } }