function tag($property, $options = array())
    {
        global $Shopp;
        switch ($property) {
            case "link":
            case "url":
                if (SHOPP_PERMALINKS) {
                    $url = esc_url(add_query_arg($_GET, $Shopp->shopuri . urldecode($this->slug) . "/"));
                } else {
                    $url = add_query_arg('shopp_pid', $this->id, $Shopp->shopuri);
                }
                return $url;
                break;
            case "found":
                if (empty($this->id)) {
                    return false;
                }
                $load = array('prices', 'images', 'specs');
                if (isset($options['load'])) {
                    $load = explode(",", $options['load']);
                }
                $this->load_data($load);
                return true;
                break;
            case "id":
                return $this->id;
                break;
            case "name":
                return $this->name;
                break;
            case "slug":
                return $this->slug;
                break;
            case "summary":
                return $this->summary;
                break;
            case "description":
                return apply_filters('shopp_product_description', $this->description);
            case "isfeatured":
            case "is-featured":
                return $this->featured == "on";
                break;
            case "price":
                if (empty($this->prices)) {
                    $this->load_data(array('prices'));
                }
                if (!isset($options['taxes'])) {
                    $options['taxes'] = null;
                }
                // $taxrate = 0;
                // $taxes = false;
                // $base = $Shopp->Settings->get('base_operations');
                // if ($base['vat']) $taxes = true;
                // if (isset($options['taxes'])) $taxes = (value_is_true($options['taxes']));
                // if ($taxes) $taxrate = $Shopp->Cart->taxrate();
                if (count($this->options) > 0) {
                    $taxrate = shopp_taxrate($options['taxes']);
                    if ($this->pricerange['min']['price'] == $this->pricerange['max']['price']) {
                        return money($this->pricerange['min']['price'] + $this->pricerange['min']['price'] * $taxrate);
                    } else {
                        if (!empty($options['starting'])) {
                            return $options['starting'] . " " . money($this->pricerange['min']['price'] + $this->pricerange['min']['price'] * $taxrate);
                        }
                        return money($this->pricerange['min']['price'] + $this->pricerange['min']['price'] * $taxrate) . " — " . money($this->pricerange['max']['price'] + $this->pricerange['max']['price'] * $taxrate);
                    }
                } else {
                    $taxrate = shopp_taxrate($options['taxes'], $this->prices[0]->tax);
                    return money($this->prices[0]->price + $this->prices[0]->price * $taxrate);
                }
                break;
            case "weight":
                if (empty($this->prices)) {
                    $this->load_data(array('prices'));
                }
                $unit = isset($options['units']) && !value_is_true($options['units']) ? false : $Shopp->Settings->get('weight_unit');
                if (!$this->weightrange['min']) {
                    return false;
                }
                $string = $this->weightrange['min'] == $this->weightrange['max'] ? round($this->weightrange['min'], 3) : round($this->weightrange['min'], 3) . " - " . round($this->weightrange['max'], 3);
                $string .= $unit ? " {$unit}" : "";
                return $string;
                break;
            case "onsale":
                if (empty($this->prices)) {
                    $this->load_data(array('prices'));
                }
                if (empty($this->prices)) {
                    return false;
                }
                return $this->onsale;
                // if (empty($this->prices)) $this->load_prices();
                $sale = false;
                if (count($this->prices) > 1) {
                    foreach ($this->prices as $pricetag) {
                        if (isset($pricetag->onsale) && $pricetag->onsale == "on") {
                            $sale = true;
                        }
                    }
                    return $sale;
                } else {
                    return $this->prices[0]->onsale == "on" ? true : false;
                }
                break;
            case "saleprice":
                if (empty($this->prices)) {
                    $this->load_data(array('prices'));
                }
                if (!isset($options['taxes'])) {
                    $options['taxes'] = null;
                }
                $pricetag = 'price';
                if ($this->onsale) {
                    $pricetag = 'saleprice';
                }
                if (count($this->options) > 0) {
                    $taxrate = shopp_taxrate($options['taxes']);
                    if ($this->pricerange['min'][$pricetag] == $this->pricerange['max'][$pricetag]) {
                        return money($this->pricerange['min'][$pricetag] + $this->pricerange['min'][$pricetag] * $taxrate);
                    } else {
                        if (!empty($options['starting'])) {
                            return $options['starting'] . " " . money($this->pricerange['min'][$pricetag] + $this->pricerange['min'][$pricetag] * $taxrate);
                        }
                        return money($this->pricerange['min'][$pricetag] + $this->pricerange['min'][$pricetag] * $taxrate) . " — " . money($this->pricerange['max'][$pricetag] + $this->pricerange['max'][$pricetag] * $taxrate);
                    }
                } else {
                    $taxrate = shopp_taxrate($options['taxes'], $this->prices[0]->tax);
                    return money($this->prices[0]->promoprice + $this->prices[0]->promoprice * $taxrate);
                }
                break;
            case "has-savings":
                return $this->onsale && $this->pricerange['min']['saved'] > 0 ? true : false;
                break;
            case "savings":
                if (empty($this->prices)) {
                    $this->load_data(array('prices'));
                }
                if (!isset($options['taxes'])) {
                    $options['taxes'] = null;
                }
                $taxrate = shopp_taxrate($options['taxes']);
                if (!isset($options['show'])) {
                    $options['show'] = '';
                }
                if ($options['show'] == "%" || $options['show'] == "percent") {
                    if ($this->options > 1) {
                        if (round($this->pricerange['min']['savings']) == round($this->pricerange['max']['savings'])) {
                            return percentage($this->pricerange['min']['savings']);
                        } else {
                            return percentage($this->pricerange['min']['savings']) . " — " . percentage($this->pricerange['max']['savings']);
                        }
                    } else {
                        return percentage($this->pricerange['max']['savings']);
                    }
                } else {
                    if ($this->options > 1) {
                        if ($this->pricerange['min']['saved'] == $this->pricerange['max']['saved']) {
                            return money($this->pricerange['min']['saved'] + $this->pricerange['min']['saved'] * $taxrate);
                        } else {
                            return money($this->pricerange['min']['saved'] + $this->pricerange['min']['saved'] * $taxrate) . " — " . money($this->pricerange['max']['saved'] + $this->pricerange['max']['saved'] * $taxrate);
                        }
                    } else {
                        return money($this->pricerange['max']['saved'] + $this->pricerange['max']['saved'] * $taxrate);
                    }
                }
                break;
            case "freeshipping":
                if (empty($this->prices)) {
                    $this->load_data(array('prices'));
                }
                // if (empty($this->prices)) $this->load_prices();
                return $this->freeshipping;
            case "thumbnail":
                if (empty($this->imagesets)) {
                    $this->load_data(array('images'));
                }
                if (empty($options['class'])) {
                    $options['class'] = '';
                } else {
                    $options['class'] = ' class="' . $options['class'] . '"';
                }
                if (isset($this->thumbnail)) {
                    $img = $this->thumbnail;
                    $title = !empty($img->properties['title']) ? ' title="' . attribute_escape($img->properties['title']) . '"' : '';
                    $width = isset($options['width']) ? $options['width'] : $img->properties['width'];
                    $height = isset($options['height']) ? $options['height'] : $img->properties['height'];
                    if (isset($options['width']) && !isset($options['height'])) {
                        $scale = $width / $img->properties['width'];
                        $height = round($img->properties['height'] * $scale);
                    }
                    if (isset($options['height']) && !isset($options['width'])) {
                        $scale = $height / $img->properties['height'];
                        $width = round($img->properties['width'] * $scale);
                    }
                    if (!empty($options['title'])) {
                        $title = ' title="' . attribute_escape($options['title']) . '"';
                    }
                    $alt = attribute_escape(!empty($img->properties['alt']) ? $img->properties['alt'] : $this->name);
                    return '<img src="' . $img->uri . '"' . $title . ' alt="' . $alt . '"  width="' . $width . '" height="' . $height . '" ' . $options['class'] . ' />';
                    break;
                }
                break;
            case "hasimages":
            case "has-images":
                if (empty($options['type'])) {
                    $options['type'] = "thumbnail";
                }
                if (empty($this->images)) {
                    $this->load_data(array('images'));
                }
                if (!empty($this->imagesets[$options['type']])) {
                    $this->imageset =& $this->imagesets[$options['type']];
                    return true;
                } else {
                    return false;
                }
                break;
            case "images":
                if (!$this->imageset) {
                    return false;
                }
                if (!$this->imageloop) {
                    reset($this->imageset);
                    $this->imageloop = true;
                } else {
                    next($this->imageset);
                }
                if (current($this->imageset)) {
                    return true;
                } else {
                    $this->imageloop = false;
                    $this->imageset = false;
                    return false;
                }
                break;
            case "image":
                $img = current($this->imageset);
                if (isset($options['property'])) {
                    switch (strtolower($options['property'])) {
                        case "url":
                            return $img->uri;
                        case "width":
                            return $img->properties['width'];
                        case "height":
                            return $img->properties['height'];
                        case "title":
                            return attribute_escape($img->properties['title']);
                        case "alt":
                            return attribute_escape($img->properties['alt']);
                        default:
                            return $img->id;
                    }
                }
                if (!isset($options['class'])) {
                    $options['class'] = false;
                }
                if (!empty($options['class'])) {
                    $options['class'] = ' class="' . $options['class'] . '"';
                }
                $title = !empty($img->properties['title']) ? ' title="' . attribute_escape($img->properties['title']) . '"' : '';
                $width = isset($options['width']) ? $options['width'] : $img->properties['width'];
                $height = isset($options['height']) ? $options['height'] : $img->properties['height'];
                if (isset($options['width']) && !isset($options['height'])) {
                    $scale = $width / $img->properties['width'];
                    $height = round($img->properties['height'] * $scale);
                }
                if (isset($options['height']) && !isset($options['width'])) {
                    $scale = $height / $img->properties['height'];
                    $width = round($img->properties['width'] * $scale);
                }
                if (!empty($options['title'])) {
                    $title = ' title="' . attribute_escape($options['title']) . '"';
                }
                $alt = attribute_escape(!empty($img->properties['alt']) ? $img->properties['alt'] : $this->name);
                $string = "";
                if (!isset($options['zoomfx'])) {
                    $options['zoomfx'] = "shopp-thickbox";
                }
                if (!empty($options['zoom'])) {
                    $string .= '<a href="' . $Shopp->imguri . $img->src . '/' . str_replace('small_', '', $img->name) . '" class="' . $options['zoomfx'] . '" rel="product-gallery">';
                }
                $string .= '<img src="' . $img->uri . '"' . $title . ' alt="' . $alt . '" width="' . $width . '" height="' . $height . '" ' . $options['class'] . ' />';
                if (!empty($options['zoom'])) {
                    $string .= "</a>";
                }
                return $string;
                break;
            case "gallery":
                if (empty($this->images)) {
                    $this->load_data(array('images'));
                }
                if (!isset($options['zoomfx'])) {
                    $options['zoomfx'] = "shopp-thickbox";
                }
                if (!isset($options['preview'])) {
                    $options['preview'] = "click";
                }
                $previews = '<ul class="previews">';
                $firstPreview = true;
                if (!empty($this->imagesets['small'])) {
                    foreach ($this->imagesets['small'] as $img) {
                        if ($firstPreview) {
                            $previews .= '<li id="preview-fill"' . ($firstPreview ? ' class="fill"' : '') . '>';
                            $previews .= '<img src="' . $Shopp->uri . '/core/ui/icons/clear.png' . '" alt="' . $img->datatype . '" width="' . $img->properties['width'] . '" height="' . $img->properties['height'] . '" />';
                            $previews .= '</li>';
                        }
                        $title = !empty($img->properties['title']) ? ' title="' . attribute_escape($img->properties['title']) . '"' : '';
                        $alt = attribute_escape(!empty($img->properties['alt']) ? $img->properties['alt'] : $img->name);
                        $rel = isset($options['rel']) && $options['rel'] ? ' rel="product_' . $this->id . '_gallery"' : '';
                        $previews .= '<li id="preview-' . $img->src . '"' . ($firstPreview ? ' class="active"' : '') . '>';
                        $previews .= '<a href="' . $Shopp->imguri . $img->src . '/' . str_replace('small_', '', $img->name) . '" class="product_' . $this->id . '_gallery ' . $options['zoomfx'] . '"' . $rel . '>';
                        $previews .= '<img src="' . $Shopp->imguri . $img->id . '"' . $title . ' alt="' . $alt . '" width="' . $img->properties['width'] . '" height="' . $img->properties['height'] . '" />';
                        $previews .= '</a>';
                        $previews .= '</li>';
                        $firstPreview = false;
                    }
                }
                $previews .= '</ul>';
                $thumbs = "";
                if (isset($this->imagesets['thumbnail']) && count($this->imagesets['thumbnail']) > 1) {
                    $thumbsize = 32;
                    if (isset($options['thumbsize'])) {
                        $thumbsize = $options['thumbsize'];
                    }
                    $thumbwidth = $thumbsize;
                    $thumbheight = $thumbsize;
                    if (isset($options['thumbwidth'])) {
                        $thumbwidth = $options['thumbwidth'];
                    }
                    if (isset($options['thumbheight'])) {
                        $thumbheight = $options['thumbheight'];
                    }
                    $firstThumb = true;
                    $thumbs = '<ul class="thumbnails">';
                    foreach ($this->imagesets['thumbnail'] as $img) {
                        if (isset($options['thumbwidth']) && !isset($options['thumbheight'])) {
                            $scale = $thumbwidth / $img->properties['width'];
                            $thumbheight = round($img->properties['height'] * $scale);
                        }
                        if (isset($options['thumbheight']) && !isset($options['thumbwidth'])) {
                            $scale = $thumbheight / $img->properties['height'];
                            $thumbwidth = round($img->properties['width'] * $scale);
                        }
                        $title = !empty($img->properties['title']) ? ' title="' . attribute_escape($img->properties['title']) . '"' : '';
                        $alt = attribute_escape(!empty($img->properties['alt']) ? $img->properties['alt'] : $img->name);
                        $thumbs .= '<li id="thumbnail-' . $img->src . '" class="preview-' . $img->src . ($firstThumb ? ' first' : ' test') . '">';
                        $thumbs .= '<img src="' . $Shopp->imguri . $img->id . '"' . $title . ' alt="' . $alt . '" width="' . $thumbwidth . '" height="' . $thumbheight . '" />';
                        $thumbs .= '</li>';
                        $firstThumb = false;
                    }
                    $thumbs .= '</ul>';
                }
                $result = '<div id="gallery-' . $this->id . '" class="gallery">' . $previews . $thumbs . '</div>';
                $result .= '<script type="text/javascript"><!--
					jQuery(document).ready( function() {  shopp_gallery("#gallery-' . $this->id . '","' . $options['preview'] . '"); }); 
					// --></script>';
                return $result;
                break;
            case "has-categories":
                if (empty($this->categories)) {
                    $this->load_data(array('categories'));
                }
                if (count($this->categories) > 0) {
                    return true;
                } else {
                    return false;
                }
                break;
            case "categories":
                if (!$this->categoryloop) {
                    reset($this->categories);
                    $this->categoryloop = true;
                } else {
                    next($this->categories);
                }
                if (current($this->categories)) {
                    return true;
                } else {
                    $this->categoryloop = false;
                    return false;
                }
                break;
            case "in-category":
                if (empty($this->categories)) {
                    $this->load_data(array('categories'));
                }
                if (isset($options['id'])) {
                    $field = "id";
                }
                if (isset($options['name'])) {
                    $field = "name";
                }
                if (isset($options['slug'])) {
                    $field = "slug";
                }
                foreach ($this->categories as $category) {
                    if ($category->{$field} == $options[$field]) {
                        return true;
                    }
                }
                return false;
            case "category":
                $category = current($this->categories);
                if (isset($options['show'])) {
                    if ($options['show'] == "id") {
                        return $category->id;
                    }
                    if ($options['show'] == "slug") {
                        return $category->slug;
                    }
                }
                return $category->name;
                break;
            case "has-tags":
                if (empty($this->tags)) {
                    $this->load_data(array('tags'));
                }
                if (count($this->tags) > 0) {
                    return true;
                } else {
                    return false;
                }
                break;
            case "tags":
                if (!$this->tagloop) {
                    reset($this->tags);
                    $this->tagloop = true;
                } else {
                    next($this->tags);
                }
                if (current($this->tags)) {
                    return true;
                } else {
                    $this->tagloop = false;
                    return false;
                }
                break;
            case "tagged":
                if (empty($this->tags)) {
                    $this->load_data(array('tags'));
                }
                if (isset($options['id'])) {
                    $field = "id";
                }
                if (isset($options['name'])) {
                    $field = "name";
                }
                foreach ($this->tags as $tag) {
                    if ($tag->{$field} == $options[$field]) {
                        return true;
                    }
                }
                return false;
            case "tag":
                $tag = current($this->tags);
                if (isset($options['show'])) {
                    if ($options['show'] == "id") {
                        return $tag->id;
                    }
                }
                return $tag->name;
                break;
            case "has-specs":
                if (empty($this->specs)) {
                    $this->load_data(array('specs'));
                }
                if (count($this->specs) > 0) {
                    $this->merge_specs();
                    return true;
                } else {
                    return false;
                }
                break;
            case "specs":
                if (!$this->specloop) {
                    reset($this->specs);
                    $this->specloop = true;
                } else {
                    next($this->specs);
                }
                if (current($this->specs)) {
                    return true;
                } else {
                    $this->specloop = false;
                    return false;
                }
                break;
            case "spec":
                $string = "";
                $separator = ": ";
                $delimiter = ", ";
                if (isset($options['separator'])) {
                    $separator = $options['separator'];
                }
                if (isset($options['delimiter'])) {
                    $separator = $options['delimiter'];
                }
                $spec = current($this->specs);
                if (is_array($spec->content)) {
                    $spec->content = join($delimiter, $spec->content);
                }
                if (isset($options['name']) && !empty($options['name']) && isset($this->specskey[$options['name']])) {
                    $spec = $this->specskey[$options['name']];
                    if (is_array($spec)) {
                        if (isset($options['index'])) {
                            foreach ($spec as $index => $entry) {
                                if ($index + 1 == $options['index']) {
                                    $content = $entry->content;
                                }
                            }
                        } else {
                            foreach ($spec as $entry) {
                                $contents[] = $entry->content;
                            }
                            $content = join($delimiter, $contents);
                        }
                    } else {
                        $content = $spec->content;
                    }
                    $string = apply_filters('shopp_product_spec', $content);
                    return $string;
                }
                if (isset($options['name']) && isset($options['content'])) {
                    $string = "{$spec->name}{$separator}" . apply_filters('shopp_product_spec', $spec->content);
                } elseif (isset($options['name'])) {
                    $string = $spec->name;
                } elseif (isset($options['content'])) {
                    $string = apply_filters('shopp_product_spec', $spec->content);
                } else {
                    $string = "{$spec->name}{$separator}" . apply_filters('shopp_product_spec', $spec->content);
                }
                return $string;
                break;
            case "has-variations":
                return $this->variations == "on" && !empty($this->options);
                break;
            case "variations":
                $string = "";
                if (!isset($options['mode'])) {
                    if (!$this->priceloop) {
                        reset($this->prices);
                        $this->priceloop = true;
                    } else {
                        next($this->prices);
                    }
                    $thisprice = current($this->prices);
                    if ($thisprice && $thisprice->type == "N/A") {
                        next($this->prices);
                    }
                    if (current($this->prices)) {
                        return true;
                    } else {
                        $this->priceloop = false;
                        return false;
                    }
                    return true;
                }
                if ($this->outofstock) {
                    return false;
                }
                // Completely out of stock, hide menus
                if (!isset($options['taxes'])) {
                    $options['taxes'] = null;
                }
                $defaults = array('defaults' => '', 'disabled' => 'show', 'before_menu' => '', 'after_menu' => '');
                $options = array_merge($defaults, $options);
                if (!isset($options['label'])) {
                    $options['label'] = "on";
                }
                if (!isset($options['required'])) {
                    $options['required'] = __('You must select the options for this item before you can add it to your shopping cart.', 'Shopp');
                }
                if ($options['mode'] == "single") {
                    if (!empty($options['before_menu'])) {
                        $string .= $options['before_menu'] . "\n";
                    }
                    if (value_is_true($options['label'])) {
                        $string .= '<label for="product-options' . $this->id . '">Options: </label> ' . "\n";
                    }
                    $string .= '<select name="products[' . $this->id . '][price]" id="product-options' . $this->id . '">';
                    if (!empty($options['defaults'])) {
                        $string .= '<option value="">' . $options['defaults'] . '</option>' . "\n";
                    }
                    foreach ($this->prices as $pricetag) {
                        if ($pricetag->context != "variation") {
                            continue;
                        }
                        $taxrate = shopp_taxrate($options['taxes'], $pricetag->tax);
                        $currently = $pricetag->sale == "on" ? $pricetag->promoprice : $pricetag->price;
                        $disabled = $pricetag->inventory == "on" && $pricetag->stock == 0 ? ' disabled="disabled"' : '';
                        $price = '  (' . money($currently) . ')';
                        if ($pricetag->type != "N/A") {
                            $string .= '<option value="' . $pricetag->id . '"' . $disabled . '>' . $pricetag->label . $price . '</option>' . "\n";
                        }
                    }
                    $string .= '</select>';
                    if (!empty($options['after_menu'])) {
                        $string .= $options['after_menu'] . "\n";
                    }
                } else {
                    $taxrate = shopp_taxrate($options['taxes'], true);
                    ob_start();
                    ?>
					<script type="text/javascript">
					<!--
					(function($) {
						$(document).ready(function () {
							productOptions[<?php 
                    echo $this->id;
                    ?>
] = new Array();
							productOptions[<?php 
                    echo $this->id;
                    ?>
]['pricing'] = <?php 
                    echo json_encode($this->pricekey);
                    ?>
;
							options_default = <?php 
                    echo !empty($options['defaults']) ? 'true' : 'false';
                    ?>
;
							options_required = "<?php 
                    echo $options['required'];
                    ?>
";
							
							productOptions[<?php 
                    echo $this->id;
                    ?>
]['menu'] = new ProductOptionsMenus('select<?php 
                    if (isset($Shopp->Category->slug)) {
                        echo ".category-" . $Shopp->Category->slug;
                    }
                    ?>
.product<?php 
                    echo $this->id;
                    ?>
',<?php 
                    echo $options['disabled'] == "hide" ? "true" : "false";
                    ?>
,productOptions[<?php 
                    echo $this->id;
                    ?>
]['pricing'],<?php 
                    echo empty($taxrate) ? '0' : $taxrate;
                    ?>
);
						});
					})(jQuery)
					//-->
					</script>
					<?php 
                    $script = ob_get_contents();
                    ob_end_clean();
                    $options['after_menu'] = $script . $options['after_menu'];
                    if (isset($this->options['variations'])) {
                        foreach ($this->options['variations'] as $id => $menu) {
                            if (!empty($options['before_menu'])) {
                                $string .= $options['before_menu'] . "\n";
                            }
                            if (value_is_true($options['label'])) {
                                $string .= '<label for="options-' . $id . '">' . $menu['menu'] . '</label> ' . "\n";
                            }
                            $string .= '<select name="products[' . $this->id . '][options][]" class="product' . $this->id . ' options">';
                            if (!empty($options['defaults'])) {
                                $string .= '<option value="">' . $options['defaults'] . '</option>' . "\n";
                            }
                            foreach ($menu['label'] as $key => $option) {
                                $string .= '<option value="' . $menu['id'][$key] . '">' . $option . '</option>' . "\n";
                            }
                            $string .= '</select>';
                            if (!empty($options['after_menu'])) {
                                $string .= $options['after_menu'] . "\n";
                            }
                        }
                    } else {
                        foreach ($this->options as $id => $menu) {
                            if (!empty($options['before_menu'])) {
                                $string .= $options['before_menu'] . "\n";
                            }
                            if (value_is_true($options['label'])) {
                                $string .= '<label for="options-' . $menu['id'] . '">' . $menu['name'] . '</label> ' . "\n";
                            }
                            $category_class = isset($Shopp->Category->slug) ? 'category-' . $Shopp->Category->slug : '';
                            $string .= '<select name="products[' . $this->id . '][options][]" class="' . $category_class . ' product' . $this->id . ' options" id="options-' . $menu['id'] . '">';
                            if (!empty($options['defaults'])) {
                                $string .= '<option value="">' . $options['defaults'] . '</option>' . "\n";
                            }
                            foreach ($menu['options'] as $key => $option) {
                                $string .= '<option value="' . $option['id'] . '">' . $option['name'] . '</option>' . "\n";
                            }
                            $string .= '</select>';
                            if (!empty($options['after_menu'])) {
                                $string .= $options['after_menu'] . "\n";
                            }
                        }
                    }
                }
                return $string;
                break;
            case "variation":
                $variation = current($this->prices);
                if (!isset($options['taxes'])) {
                    $options['taxes'] = null;
                }
                $taxrate = shopp_taxrate($options['taxes'], $variation->tax);
                $weightunit = isset($options['units']) && !value_is_true($options['units']) ? false : $Shopp->Settings->get('weight_unit');
                $string = '';
                if (array_key_exists('id', $options)) {
                    $string .= $variation->id;
                }
                if (array_key_exists('label', $options)) {
                    $string .= $variation->label;
                }
                if (array_key_exists('type', $options)) {
                    $string .= $variation->type;
                }
                if (array_key_exists('sku', $options)) {
                    $string .= $variation->sku;
                }
                if (array_key_exists('price', $options)) {
                    $string .= money($variation->price + $variation->price * $taxrate);
                }
                if (array_key_exists('saleprice', $options)) {
                    $string .= money($variation->saleprice + $variation->saleprice * $taxrate);
                }
                if (array_key_exists('stock', $options)) {
                    $string .= $variation->stock;
                }
                if (array_key_exists('weight', $options)) {
                    $string .= round($variation->weight, 3) . ($weightunit ? " {$weightunit}" : false);
                }
                if (array_key_exists('shipfee', $options)) {
                    $string .= money(floatvalue($variation->shipfee));
                }
                if (array_key_exists('sale', $options)) {
                    return $variation->sale == "on";
                }
                if (array_key_exists('shipping', $options)) {
                    return $variation->shipping == "on";
                }
                if (array_key_exists('tax', $options)) {
                    return $variation->tax == "on";
                }
                if (array_key_exists('inventory', $options)) {
                    return $variation->inventory == "on";
                }
                return $string;
                break;
            case "has-addons":
                if (isset($this->options['addons'])) {
                    return true;
                } else {
                    return false;
                }
                break;
                break;
            case "donation":
            case "amount":
            case "quantity":
                if ($this->outofstock) {
                    return false;
                }
                if (!isset($options['value'])) {
                    $options['value'] = 1;
                }
                if (!isset($options['input'])) {
                    $options['input'] = "text";
                }
                if (!isset($options['labelpos'])) {
                    $options['labelpos'] = "before";
                }
                if (!isset($options['label'])) {
                    $label = "";
                } else {
                    $label = '<label for="quantity' . $this->id . '">' . $options['label'] . '</label>';
                }
                $result = "";
                if ($options['labelpos'] == "before") {
                    $result .= "{$label} ";
                }
                if (!$this->priceloop) {
                    reset($this->prices);
                }
                $variation = current($this->prices);
                if (isset($options['input']) && $options['input'] == "menu") {
                    if (!isset($options['options'])) {
                        $values = "1-15,20,25,30,40,50,75,100";
                    } else {
                        $values = $options['options'];
                    }
                    if ($this->inventory && $this->pricerange['max']['stock'] == 0) {
                        return "";
                    }
                    if (strpos($values, ",") !== false) {
                        $values = explode(",", $values);
                    } else {
                        $values = array($values);
                    }
                    $qtys = array();
                    foreach ($values as $value) {
                        if (strpos($value, "-") !== false) {
                            $value = explode("-", $value);
                            if ($value[0] >= $value[1]) {
                                $qtys[] = $value[0];
                            } else {
                                for ($i = $value[0]; $i < $value[1] + 1; $i++) {
                                    $qtys[] = $i;
                                }
                            }
                        } else {
                            $qtys[] = $value;
                        }
                    }
                    $result .= '<select name="products[' . $this->id . '][quantity]" id="quantity-' . $this->id . '">';
                    foreach ($qtys as $qty) {
                        $amount = $qty;
                        $selected = isset($this->quantity) ? $this->quantity : 1;
                        if ($variation->type == "Donation" && $variation->donation['var'] == "on") {
                            if ($variation->donation['min'] == "on" && $amount < $variation->price) {
                                continue;
                            }
                            $amount = money($amount);
                            $selected = $variation->price;
                        } else {
                            if ($this->inventory && $amount > $this->pricerange['max']['stock']) {
                                continue;
                            }
                        }
                        $result .= '<option' . ($qty == $selected ? ' selected="selected"' : '') . ' value="' . $qty . '">' . $amount . '</option>';
                    }
                    $result .= '</select>';
                    if ($options['labelpos'] == "after") {
                        $result .= " {$label}";
                    }
                    return $result;
                }
                if (valid_input($options['input'])) {
                    if (!isset($options['size'])) {
                        $options['size'] = 3;
                    }
                    if ($variation->type == "Donation" && $variation->donation['var'] == "on") {
                        if ($variation->donation['min']) {
                            $options['value'] = $variation->price;
                        }
                        $options['class'] .= " currency";
                    }
                    $result = '<input type="' . $options['input'] . '" name="products[' . $this->id . '][quantity]" id="quantity-' . $this->id . '"' . inputattrs($options) . ' />';
                }
                if ($options['labelpos'] == "after") {
                    $result .= " {$label}";
                }
                return $result;
                break;
            case "input":
                if (!isset($options['type']) || $options['type'] != "menu" && $options['type'] != "textarea" && !valid_input($options['type'])) {
                    $options['type'] = "text";
                }
                if (!isset($options['name'])) {
                    return "";
                }
                if ($options['type'] == "menu") {
                    $result = '<select name="products[' . $this->id . '][data][' . $options['name'] . ']" id="data-' . $options['name'] . '-' . $this->id . '">';
                    if (isset($options['options'])) {
                        $menuoptions = preg_split('/,(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/', $options['options']);
                    }
                    if (is_array($menuoptions)) {
                        foreach ($menuoptions as $option) {
                            $selected = "";
                            $option = trim($option, '"');
                            if (isset($options['default']) && $options['default'] == $option) {
                                $selected = ' selected="selected"';
                            }
                            $result .= '<option value="' . $option . '"' . $selected . '>' . $option . '</option>';
                        }
                    }
                    $result .= '</select>';
                } elseif ($options['type'] == "textarea") {
                    if (isset($options['cols'])) {
                        $cols = ' cols="' . $options['cols'] . '"';
                    }
                    if (isset($options['rows'])) {
                        $rows = ' rows="' . $options['rows'] . '"';
                    }
                    $result .= '<textarea  name="products[' . $this->id . '][data][' . $options['name'] . ']" id="data-' . $options['name'] . '-' . $this->id . '"' . $cols . $rows . '>' . $options['value'] . '</textarea>';
                } else {
                    $result = '<input type="' . $options['type'] . '" name="products[' . $this->id . '][data][' . $options['name'] . ']" id="data-' . $options['name'] . '-' . $this->id . '"' . inputattrs($options) . ' />';
                }
                return $result;
                break;
            case "outofstock":
                if ($this->outofstock) {
                    $label = isset($options['label']) ? $options['label'] : $Shopp->Settings->get('outofstock_text');
                    $string = '<span class="outofstock">' . $label . '</span>';
                    return $string;
                } else {
                    return false;
                }
                break;
            case "buynow":
                if (!isset($options['value'])) {
                    $options['value'] = __("Buy Now", "Shopp");
                }
            case "addtocart":
                if (!isset($options['class'])) {
                    $options['class'] = "addtocart";
                } else {
                    $options['class'] .= " addtocart";
                }
                if (!isset($options['value'])) {
                    $options['value'] = __("Add to Cart", "Shopp");
                }
                $string = "";
                if ($this->outofstock) {
                    $string .= '<span class="outofstock">' . $Shopp->Settings->get('outofstock_text') . '</span>';
                    return $string;
                }
                $string .= '<input type="hidden" name="products[' . $this->id . '][product]" value="' . $this->id . '" />';
                if (!empty($this->prices[0]) && $this->prices[0]->type != "N/A") {
                    $string .= '<input type="hidden" name="products[' . $this->id . '][price]" value="' . $this->prices[0]->id . '" />';
                }
                if (!empty($Shopp->Category)) {
                    if (SHOPP_PERMALINKS) {
                        $string .= '<input type="hidden" name="products[' . $this->id . '][category]" value="' . $Shopp->Category->uri . '" />';
                    } else {
                        $string .= '<input type="hidden" name="products[' . $this->id . '][category]" value="' . (!empty($Shopp->Category->id) ? $Shopp->Category->id : $Shopp->Category->slug) . '" />';
                    }
                }
                $string .= '<input type="hidden" name="cart" value="add" />';
                if (isset($options['ajax'])) {
                    $options['class'] .= " ajax";
                    $string .= '<input type="hidden" name="ajax" value="true" />';
                    $string .= '<input type="button" name="addtocart" ' . inputattrs($options) . ' />';
                } else {
                    $string .= '<input type="submit" name="addtocart" ' . inputattrs($options) . ' />';
                }
                return $string;
        }
    }
 function tag($id, $property, $options = array())
 {
     global $Shopp;
     // Return strings with no options
     switch ($property) {
         case "id":
             return $id;
         case "name":
             return $this->name;
         case "link":
         case "url":
             return SHOPP_PERMALINKS ? $Shopp->shopuri . $this->slug : add_query_arg('shopp_pid', $this->product, $Shopp->shopuri);
         case "sku":
             return $this->sku;
     }
     $taxes = false;
     if (isset($options['taxes'])) {
         $taxes = $options['taxes'];
     }
     if ($property == "unitprice" || $property == "total" || $property == "options") {
         $taxrate = shopp_taxrate($taxes, $this->taxable);
     }
     // Handle currency values
     $result = "";
     switch ($property) {
         case "unitprice":
             $result = (double) $this->unitprice + $this->unitprice * $taxrate;
             break;
         case "total":
             $result = (double) $this->total + $this->total * $taxrate;
             break;
         case "tax":
             $result = (double) $this->tax;
             break;
     }
     if (is_float($result)) {
         if (isset($options['currency']) && !value_is_true($options['currency'])) {
             return $result;
         } else {
             return money($result);
         }
     }
     // Handle values with complex options
     switch ($property) {
         case "quantity":
             $result = $this->quantity;
             if ($this->type == "Donation" && $this->donation['var'] == "on") {
                 return $result;
             }
             if (isset($options['input']) && $options['input'] == "menu") {
                 if (!isset($options['value'])) {
                     $options['value'] = $this->quantity;
                 }
                 if (!isset($options['options'])) {
                     $values = "1-15,20,25,30,35,40,45,50,60,70,80,90,100";
                 } else {
                     $values = $options['options'];
                 }
                 if (strpos($values, ",") !== false) {
                     $values = explode(",", $values);
                 } else {
                     $values = array($values);
                 }
                 $qtys = array();
                 foreach ($values as $value) {
                     if (strpos($value, "-") !== false) {
                         $value = explode("-", $value);
                         if ($value[0] >= $value[1]) {
                             $qtys[] = $value[0];
                         } else {
                             for ($i = $value[0]; $i < $value[1] + 1; $i++) {
                                 $qtys[] = $i;
                             }
                         }
                     } else {
                         $qtys[] = $value;
                     }
                 }
                 $result = '<select name="items[' . $id . '][' . $property . ']">';
                 foreach ($qtys as $qty) {
                     $result .= '<option' . ($qty == $this->quantity ? ' selected="selected"' : '') . ' value="' . $qty . '">' . $qty . '</option>';
                 }
                 $result .= '</select>';
             } elseif (isset($options['input']) && valid_input($options['input'])) {
                 if (!isset($options['size'])) {
                     $options['size'] = 5;
                 }
                 if (!isset($options['value'])) {
                     $options['value'] = $this->quantity;
                 }
                 $result = '<input type="' . $options['input'] . '" name="items[' . $id . '][' . $property . ']" id="items-' . $id . '-' . $property . '" ' . inputattrs($options) . '/>';
             } else {
                 $result = $this->quantity;
             }
             break;
         case "remove":
             $label = __("Remove");
             if (isset($options['label'])) {
                 $label = $options['label'];
             }
             if (isset($options['class'])) {
                 $class = ' class="' . $options['class'] . '"';
             } else {
                 $class = ' class="remove"';
             }
             if (isset($options['input'])) {
                 switch ($options['input']) {
                     case "button":
                         $result = '<button type="submit" name="remove[' . $id . ']" value="' . $id . '"' . $class . ' tabindex="">' . $label . '</button>';
                         break;
                     case "checkbox":
                         $result = '<input type="checkbox" name="remove[' . $id . ']" value="' . $id . '"' . $class . ' tabindex="" title="' . $label . '"/>';
                         break;
                 }
             } else {
                 $result = '<a href="' . add_query_arg(array('cart' => 'update', 'item' => $id, 'quantity' => 0), $Shopp->link('cart')) . '"' . $class . '>' . $label . '</a>';
             }
             break;
         case "optionlabel":
             $result = $this->optionlabel;
             break;
         case "options":
             $class = "";
             if (isset($options['show']) && strtolower($options['show']) == "selected") {
                 return !empty($this->optionlabel) ? $options['before'] . $this->optionlabel . $options['after'] : '';
             }
             if (isset($options['class'])) {
                 $class = ' class="' . $options['class'] . '" ';
             }
             if (count($this->options) > 1) {
                 $result .= $options['before'];
                 $result .= '<input type="hidden" name="items[' . $id . '][product]" value="' . $this->product . '"/>';
                 $result .= ' <select name="items[' . $id . '][price]" id="items-' . $id . '-price"' . $class . '>';
                 $result .= $this->options($this->price, $taxrate);
                 $result .= '</select>';
                 $result .= $options['after'];
             }
             break;
         case "hasinputs":
         case "has-inputs":
             return count($this->data) > 0;
             break;
         case "inputs":
             if (!$this->dataloop) {
                 reset($this->data);
                 $this->dataloop = true;
             } else {
                 next($this->data);
             }
             if (current($this->data)) {
                 return true;
             } else {
                 $this->dataloop = false;
                 return false;
             }
             break;
         case "input":
             $data = current($this->data);
             $name = key($this->data);
             if (isset($options['name'])) {
                 return $name;
             }
             return $data;
             break;
         case "inputs-list":
         case "inputslist":
             if (empty($this->data)) {
                 return false;
             }
             $before = "";
             $after = "";
             $classes = "";
             $excludes = array();
             if (!empty($options['class'])) {
                 $classes = ' class="' . $options['class'] . '"';
             }
             if (!empty($options['exclude'])) {
                 $excludes = explode(",", $options['exclude']);
             }
             if (!empty($options['before'])) {
                 $before = $options['before'];
             }
             if (!empty($options['after'])) {
                 $after = $options['after'];
             }
             $result .= $before . '<ul' . $classes . '>';
             foreach ($this->data as $name => $data) {
                 if (in_array($name, $excludes)) {
                     continue;
                 }
                 $result .= '<li><strong>' . $name . '</strong>: ' . $data . '</li>';
             }
             $result .= '</ul>' . $after;
             return $result;
             break;
         case "thumbnail":
             if (!empty($options['class'])) {
                 $options['class'] = ' class="' . $options['class'] . '"';
             }
             if (isset($this->thumbnail)) {
                 $img = $this->thumbnail;
                 $width = isset($options['width']) ? $options['width'] : $img->properties['height'];
                 $height = isset($options['height']) ? $options['height'] : $img->properties['height'];
                 return '<img src="' . $Shopp->imguri . $img->id . '" alt="' . $this->name . ' ' . $img->datatype . '" width="' . $width . '" height="' . $height . '" ' . $options['class'] . ' />';
                 break;
             }
     }
     if (!empty($result)) {
         return $result;
     }
     return false;
 }
示例#3
0
/**
 * shopp_product_variant_set_saleprice - set the sale price of a variant
 *
 * @api
 * @since 1.2
 *
 * @param int/Price $variant (required) The priceline id to set the sale price on, or the Price object to change.  If Price object is specified, the object will be returned, but not saved to the database.
 * @param bool $flag (optional default:false) true for on, false for off. Turns on or off the sale flag on the variant.  If false, price is ignored.
 * @param float $price the price to be set
 * @param string $context (optional default:variant) enforces the priceline is a 'product','variant', or 'addon'
 * @return bool/Price false on failure, true if Price saved, else the modified Price object.
 **/
function shopp_product_variant_set_saleprice($variant = false, $flag = false, $price = 0.0, $context = 'variant')
{
    $context = 'variant' == $context ? 'variation' : $context;
    $save = true;
    if (is_object($variant) && is_a($variant, 'ShoppPrice')) {
        $Price = $variant;
        $save = false;
    } else {
        if (false == $variant) {
            shopp_debug(__FUNCTION__ . " failed: Variant id required.");
            return false;
        }
        $Price = new ShoppPrice($variant);
        if (empty($Price->id) || $Price->context != $context) {
            shopp_debug(__FUNCTION__ . " failed: No such {$context} with id {$variant}.");
        }
    }
    $Price->sale = "off";
    if ($flag) {
        $Price->sale = "on";
        if (shopp_setting_enabled('tax_inclusive') && isset($Price->tax) && Shopp::str_true($Price->tax)) {
            $Product = new ShoppProduct($Price->product);
            $taxrate = shopp_taxrate(null, true, $Product);
            $price = Shopp::floatval($price / (1 + $taxrate));
        }
        $Price->saleprice = $price;
    }
    if ($save) {
        return $Price->save();
    }
    return $Price;
}
 function tag($property, $options = array())
 {
     global $Shopp;
     if ($property == "item-unitprice" || $property == "item-total") {
         $taxrate = shopp_taxrate($options['taxes']);
     }
     // Return strings with no options
     switch ($property) {
         case "url":
             return $Shopp->link('cart');
             break;
         case "id":
             return $this->id;
             break;
         case "date":
             if (empty($options['format'])) {
                 $options['format'] = get_option('date_format');
             }
             return _d($options['format'], is_int($this->created) ? $this->created : mktimestamp($this->created));
             break;
         case "card":
             return !empty($this->card) ? sprintf("%'X16d", $this->card) : '';
             break;
         case "cardtype":
             return $this->cardtype;
             break;
         case "transactionid":
             return $this->transactionid;
             break;
         case "firstname":
             return $this->firstname;
             break;
         case "lastname":
             return $this->lastname;
             break;
         case "company":
             return $this->company;
             break;
         case "email":
             return $this->email;
             break;
         case "phone":
             return $this->phone;
             break;
         case "address":
             return $this->address;
             break;
         case "xaddress":
             return $this->xaddress;
             break;
         case "city":
             return $this->city;
             break;
         case "state":
             if (strlen($this->state > 2)) {
                 return $this->state;
             }
             $regions = $Shopp->Settings->get('zones');
             $states = $regions[$this->country];
             return $states[$this->state];
             break;
         case "postcode":
             return $this->postcode;
             break;
         case "country":
             $countries = $Shopp->Settings->get('target_markets');
             return $countries[$this->country];
             break;
         case "shipaddress":
             return $this->shipaddress;
             break;
         case "shipxaddress":
             return $this->shipxaddress;
             break;
         case "shipcity":
             return $this->shipcity;
             break;
         case "shipstate":
             if (strlen($this->shipstate > 2)) {
                 return $this->shipstate;
             }
             $regions = $Shopp->Settings->get('zones');
             $states = $regions[$this->country];
             return $states[$this->shipstate];
             break;
         case "shippostcode":
             return $this->shippostcode;
             break;
         case "shipcountry":
             $countries = $Shopp->Settings->get('target_markets');
             return $countries[$this->shipcountry];
             break;
         case "shipmethod":
             return $this->shipmethod;
             break;
         case "totalitems":
             return count($this->purchased);
             break;
         case "hasitems":
             if (count($this->purchased) > 0) {
                 return true;
             } else {
                 return false;
             }
             break;
         case "items":
             if (!$this->looping) {
                 reset($this->purchased);
                 $this->looping = true;
             } else {
                 next($this->purchased);
             }
             if (current($this->purchased)) {
                 return true;
             } else {
                 $this->looping = false;
                 reset($this->purchased);
                 return false;
             }
         case "item-id":
             $item = current($this->purchased);
             return $item->id;
             break;
         case "item-product":
             $item = current($this->purchased);
             return $item->product;
             break;
         case "item-price":
             $item = current($this->purchased);
             return $item->price;
             break;
         case "item-name":
             $item = current($this->purchased);
             return $item->name;
             break;
         case "item-description":
             $item = current($this->purchased);
             return $item->description;
             break;
         case "item-options":
             $item = current($this->purchased);
             return !empty($item->optionlabel) ? $options['before'] . $item->optionlabel . $options['after'] : '';
             break;
         case "item-sku":
             $item = current($this->purchased);
             return $item->sku;
             break;
         case "item-download":
             $item = current($this->purchased);
             if (empty($item->download)) {
                 return "";
             }
             if (!isset($options['label'])) {
                 $options['label'] = __('Download', 'Shopp');
             }
             $classes = "";
             if (isset($options['class'])) {
                 $classes = ' class="' . $options['class'] . '"';
             }
             if (SHOPP_PERMALINKS) {
                 $url = $Shopp->shopuri . "download/" . $item->dkey;
             } else {
                 $url = add_query_arg('shopp_download', $item->dkey, $Shopp->link('account'));
             }
             return '<a href="' . $url . '"' . $classes . '>' . $options['label'] . '</a>';
             break;
         case "item-quantity":
             $item = current($this->purchased);
             return $item->quantity;
             break;
         case "item-unitprice":
             $item = current($this->purchased);
             return money($item->unitprice + $item->unitprice * $taxrate);
             break;
         case "item-total":
             $item = current($this->purchased);
             return money($item->total + $item->total * $taxrate);
             break;
         case "item-has-inputs":
         case "item-hasinputs":
             $item = current($this->purchased);
             return count($item->data) > 0;
             break;
         case "item-inputs":
             $item = current($this->purchased);
             if (!$this->itemdataloop) {
                 reset($item->data);
                 $this->itemdataloop = true;
             } else {
                 next($item->data);
             }
             if (current($item->data)) {
                 return true;
             } else {
                 $this->itemdataloop = false;
                 return false;
             }
             break;
         case "item-input":
             $item = current($this->purchased);
             $data = current($item->data);
             $name = key($item->data);
             if (isset($options['name'])) {
                 return $name;
             }
             return $data;
             break;
         case "item-inputs-list":
         case "item-inputslist":
         case "item-inputs-list":
         case "iteminputslist":
             $item = current($this->purchased);
             if (empty($item->data)) {
                 return false;
             }
             $before = "";
             $after = "";
             $classes = "";
             $excludes = array();
             if (!empty($options['class'])) {
                 $classes = ' class="' . $options['class'] . '"';
             }
             if (!empty($options['exclude'])) {
                 $excludes = explode(",", $options['exclude']);
             }
             if (!empty($options['before'])) {
                 $before = $options['before'];
             }
             if (!empty($options['after'])) {
                 $after = $options['after'];
             }
             $result .= $before . '<ul' . $classes . '>';
             foreach ($item->data as $name => $data) {
                 if (in_array($name, $excludes)) {
                     continue;
                 }
                 $result .= '<li><strong>' . $name . '</strong>: ' . $data . '</li>';
             }
             $result .= '</ul>' . $after;
             return $result;
             break;
         case "has-data":
         case "hasdata":
             return is_array($this->data) && count($this->data) > 0;
             break;
         case "orderdata":
             if (!$this->dataloop) {
                 reset($this->data);
                 $this->dataloop = true;
             } else {
                 next($this->data);
             }
             if (current($this->data) !== false) {
                 return true;
             } else {
                 $this->dataloop = false;
                 return false;
             }
             break;
         case "data":
             if (!is_array($this->data)) {
                 return false;
             }
             $data = current($this->data);
             $name = key($this->data);
             if (isset($options['name'])) {
                 return $name;
             }
             return $data;
             break;
         case "has-promo":
         case "haspromo":
             if (empty($options['name'])) {
                 return false;
             }
             return in_array($options['name'], $this->promos);
             break;
         case "subtotal":
             return money($this->subtotal);
             break;
         case "hasfreight":
             return !empty($this->shipmethod) || $this->freight > 0;
         case "freight":
             return money($this->freight);
             break;
         case "hasdiscount":
             return $this->discount > 0;
         case "discount":
             return money($this->discount);
             break;
         case "hastax":
             return $this->tax > 0 ? true : false;
         case "tax":
             return money($this->tax);
             break;
         case "total":
             return money($this->total);
             break;
         case "status":
             $labels = $Shopp->Settings->get('order_status');
             if (empty($labels)) {
                 $labels = array('');
             }
             return $labels[$this->status];
             break;
     }
 }