Plugin Directory

Changeset 1122729


Ignore:
Timestamp:
03/28/2015 02:47:50 PM (11 years ago)
Author:
jond
Message:

Added 1.3.9 release

Location:
shopp/trunk
Files:
1 added
46 edited

Legend:

Unmodified
Added
Removed
  • shopp/trunk/Shopp.php

    r1053635 r1122729  
    44 * Plugin URI: http://shopplugin.com
    55 * Description: An ecommerce framework for WordPress.
    6  * Version: 1.3.8
     6 * Version: 1.3.9
    77 * Author: Ingenesis Limited
    88 * Author URI: http://ingenesis.net
  • shopp/trunk/api/product.php

    r1053635 r1122729  
    6161    // Set Product slug
    6262    if ( ! empty($data['slug'])) $Product->slug = $data['slug'];
    63     if (empty($Product->slug)) $Product->slug = sanitize_title_with_dashes($Product->name);
     63    if (empty($Product->slug)) $Product->slug = sanitize_title($Product->name);
    6464    $Product->slug = wp_unique_post_slug($Product->slug, $Product->id, $Product->status, ShoppProduct::posttype(), 0);
    6565
  • shopp/trunk/api/theme/cart.php

    r1053635 r1122729  
    304304        switch ( $Discount->type() ) {
    305305            case ShoppOrderDiscount::SHIP_FREE:     $string .= Shopp::esc_html__( 'Free Shipping!' ); break;
    306             case ShoppOrderDiscount::PERCENT_OFF:   $string .= sprintf(esc_html($label), percentage($Discount->discount(), array('precision' => 0))); break;
     306            case ShoppOrderDiscount::PERCENT_OFF:   $string .= sprintf(esc_html($label), percentage((float)$Discount->discount(), array('precision' => 0))); break;
    307307            case ShoppOrderDiscount::AMOUNT_OFF:    $string .= sprintf(esc_html($label), money($Discount->discount())); break;
    308308            case ShoppOrderDiscount::CREDIT:        $string .= sprintf(esc_html($creditlabel), money($Discount->amount())); break;
  • shopp/trunk/api/theme/cartitem.php

    r1053635 r1122729  
    747747
    748748    /**
    749      * Helper function that maps the current cart item's addons to the cart item's configured product menu options
    750      *
    751      * @internal
    752      * @since 1.3
    753      *
    754      * @return array A combined list of the menu labels list and addons menu map
    755      **/
    756     private static function _addon_menus () {
    757         $menus = shopp_meta(shopp('cartitem.get-product'), 'product', 'options');
    758         $addonmenus = array();
    759         $menulabels = array();
    760         if ( isset($menus['a']) ) {
    761             foreach ( $menus['a'] as $addonmenu ) {
    762                 $menulabels[ $addonmenu['id'] ] = $addonmenu['name'];
    763                 foreach ( $addonmenu['options'] as $menuoption )
    764                     $addonmenus[ $menuoption['id'] ] = $addonmenu['id'];
    765             }
    766         }
    767         return array($menulabels, $addonmenus);
    768     }
    769 
    770     /**
    771749     * Checks if the cart item has any custom product input data assigned to it
    772750     *
     
    10411019    }
    10421020
     1021    /**
     1022     * Helper function that maps the current cart item's addons to the cart item's configured product menu options
     1023     *
     1024     * @internal
     1025     * @since 1.3
     1026     *
     1027     * @param int $id The product ID to retrieve addon menus from
     1028     * @return array A combined list of the menu labels list and addons menu map
     1029     **/
     1030    private static function _addon_menus () {
     1031        return ShoppProductThemeAPI::_addon_menus(shopp('cartitem.get-product'));
     1032    }
     1033
    10431034}
  • shopp/trunk/api/theme/customer.php

    r1053635 r1122729  
    13891389        if ( ! isset($options['label']) ) $options['label'] = Shopp::__('Save');
    13901390        $result = '<input type="hidden" name="customer" value="true" />';
     1391        $result .= wp_nonce_field('shopp_profile_update', '_wpnonce', true, false);
    13911392        $result .= '<input type="submit" name="save" id="save-button"' . inputattrs($options) . ' />';
    13921393        return $result;
     
    16121613     * - **tabindex**: Specifies the tabbing order of an element
    16131614     * - **title**: Specifies extra information about an element
    1614      * - **label**: Specifies the value of the button element
     1615     * - **label**: Specifies the value of the button element. Defaults to `Login`
     1616     * - **redirect**: Specifies the URL the customer is redirected to after login. Defaults to `$_REQUEST['redirect']`.
    16151617     * @param ShoppCustomer $O       The working object
    16161618     * @return string The button markup
    16171619     **/
    16181620    public static function submit_login ( $result, $options, $O ) {
    1619         if ( ! isset($options['label']) ) $options['label'] = Shopp::__('Login');
     1621        $request = $_GET;
     1622        $defaults = array(
     1623            'label' => Shopp::__('Login'),
     1624            'redirect' => isset($_REQUEST['redirect']) ?
     1625                $_REQUEST['redirect'] : Shopp::url($request, 'account', ShoppOrder()->security())
     1626        );
     1627        $options = array_merge($defaults, $options);
     1628        extract($options, EXTR_SKIP);
     1629
    16201630        $string = '';
    16211631        $id = 'submit-login';
    1622 
    1623         $request = $_GET;
    1624         if ( isset($request['acct']) && 'logout' == $request['acct'] ) unset($request['acct']);
    1625 
    16261632        $context = ShoppStorefront::intemplate();
     1633
     1634        if ( isset($request['acct']) && 'logout' == $request['acct'] )
     1635            unset($request['acct']);
     1636
    16271637        if ( 'checkout.php' == $context ) {
    1628             $id .= '-checkout';
    1629             $string .= '<input type="hidden" name="redirect" value="checkout" />';
    1630         } else $string .= '<input type="hidden" name="redirect" value="' . esc_attr(Shopp::url($request, 'account', ShoppOrder()->security())) . '" />';
    1631         $string .= '<input type="submit" name="submit-login" id="' . $id . '"' . inputattrs($options) . ' />';
    1632         return $string;
     1638            $redirect = 'checkout';
     1639            $id .= '-' . $redirect;
     1640        }
     1641
     1642        return '<input type="hidden" name="redirect" value="' . esc_attr($redirect) . '" />'
     1643             . '<input type="submit" name="submit-login" id="' . $id . '"' . inputattrs($options) . ' />';
     1644
    16331645    }
    16341646
  • shopp/trunk/api/theme/product.php

    r1020997 r1122729  
    21282128
    21292129        $taxes = isset($taxes) ? Shopp::str_true($taxes) : null;
     2130        $taxrates = self::_taxes($O, 'price');
    21302131        $collection_class = ShoppCollection() && isset(ShoppCollection()->slug) ? 'category-' . ShoppCollection()->slug : '';
    21312132
     
    21412142
    21422143                $currently = Shopp::str_true($pricing->sale) ? $pricing->promoprice : $pricing->price;
    2143                 $disable = ( $pricetag->type == 'N/A' || ( Shopp::str_true($pricing->inventory) && $pricing->stock == 0 ) );
    2144 
     2144                $disable = ( $pricing->type == 'N/A' || ( Shopp::str_true($pricing->inventory) && $pricing->stock == 0 ) );
    21452145                $currently = self::_taxed((float)$currently, $O, $pricing->tax, $taxes);
    21462146
     
    21572157                $_->d = $discount > 0 ? $discount : false;
    21582158
    2159                 if ( $disable && 'show' == $disabled )
     2159                if ( ! $disable || 'show' == $disabled )
    21602160                    $string .= '<option value="' . $pricing->id . '"' . ( $disable ? ' disabled="disabled"' : '' ) . '>' . esc_html(self::_variant_formatlabel($format, $_)) . '</option>' . "\n";
    21612161            }
     
    21742174            $pricekeys = array();
    21752175            foreach ($O->pricekey as $key => $pricing) {
     2176
     2177                $currently = Shopp::str_true($pricing->sale) ? $pricing->promoprice : $pricing->price;
     2178                $disable = ( $pricing->type == 'N/A' || ( Shopp::str_true($pricing->inventory) && $pricing->stock == 0 ) );
     2179                $currently = self::_taxed((float)$currently, $O, $pricing->tax, $taxes);
     2180
    21762181                $discount = 100-round($pricing->promoprice * 100 / $pricing->price);
    21772182                $_ = new StdClass();
    2178                 $_->p = 'Donation' != $pricing->type ? (float)apply_filters('shopp_product_variant_price', (Shopp::str_true($pricing->sale) ? $pricing->promoprice : $pricing->price) ) : false;
     2183                $_->p = 'Donation' != $pricing->type && ! $disable ? (float)apply_filters('shopp_product_variant_price', (Shopp::str_true($pricing->sale) ? $pricing->promoprice : $currently) ) : false;
    21792184                $_->i = Shopp::str_true($pricing->inventory);
    21802185                $_->s = $_->i ? (int)$pricing->stock : false;
     
    23832388    }
    23842389
     2390    /**
     2391     * Helper function that maps the current cart item's addons to the cart item's configured product menu options
     2392     *
     2393     * @internal
     2394     * @since 1.3
     2395     *
     2396     * @return array A combined list of the menu labels list and addons menu map
     2397     **/
     2398    public static function _addon_menus ( $productid ) {
     2399        $menus = shopp_meta($productid, 'product', 'options');
     2400        $addonmenus = array();
     2401        $menulabels = array();
     2402        if ( isset($menus['a']) ) {
     2403            foreach ( $menus['a'] as $addonmenu ) {
     2404                $menulabels[ $addonmenu['id'] ] = $addonmenu['name'];
     2405                foreach ( $addonmenu['options'] as $menuoption )
     2406                    $addonmenus[ $menuoption['id'] ] = $addonmenu['id'];
     2407            }
     2408        }
     2409        return array($menulabels, $addonmenus);
     2410    }
     2411
     2412
    23852413}
  • shopp/trunk/api/theme/purchase.php

    r1020997 r1122729  
    228228     **/
    229229    public static function card ( $result, $options, $O ) {
    230         return ( ! empty($O->card) ) ? sprintf("%'X16d", $O->card) : '';
     230        return ( ! empty($O->card) ) ? sprintf("%'X16s", $O->card) : '';
    231231    }
    232232
     
    677677    public static function item_addon ( $result, $options, $O ) {
    678678        $item = current($O->purchased);
    679         $addon = current($item->addons->meta);
     679        $addon = current($item->addons->meta)->value;
    680680        if ( false === $item || false === $addon ) return '';
    681681
    682         if ( isset($options['id']) ) return esc_html($addon->id);
    683         if ( isset($options['name']) ) return esc_html($addon->name);
    684         if ( isset($options['label']) ) return esc_html($addon->name);
    685         if ( isset($options['type']) ) return esc_html($addon->value->type);
    686         if ( isset($options['onsale']) ) return $addon->value->sale;
    687         if ( isset($options['inventory']) ) return $addon->value->inventory;
    688         if ( isset($options['sku']) ) return esc_html($addon->value->sku);
    689         if ( isset($options['unitprice']) ) return (float) $addon->value->unitprice;
    690 
    691         if ( isset($options['download']) ) {
    692             $link = false;
    693             if ( isset($addon->value->download) && isset($addon->value->dkey) ) {
    694                 $label = __('Download', 'Shopp');
    695                 if ( isset($options['linktext']) && $options['linktext'] != '' ) $label = $options['linktext'];
    696 
    697                 $dkey = $addon->value->dkey;
    698                 $request = '' == get_option('permalink_structure') ? "download/$dkey" : array('shopp_download' => $dkey);
    699                 $url = Shopp::url($request, 'catalog');
    700 
    701                 $link = '<a href="' . $url . '">' . $label . '</a>';
    702                 return esc_html($link);
     682        $defaults = array(
     683            'separator' => ' '
     684        );
     685        $options = array_merge($defaults, $options);
     686
     687        $fields = array('id', 'type', 'menu', 'label', 'sale', 'saleprice', 'price', 'inventory', 'stock', 'sku', 'weight', 'shipfee', 'unitprice');
     688
     689        $fieldset = array_intersect($fields, array_keys($options));
     690        if ( empty($fieldset) ) $fieldset = array('label');
     691
     692        $_ = array();
     693        foreach ( $fieldset as $field ) {
     694            switch ( $field ) {
     695                case 'menu':
     696                    list($menus, $menumap) = self::_addon_menus();
     697                    $_[] = isset( $menumap[ $addon->options ]) ? $menus[ $menumap[ $addon->options ] ] : '';
     698                    break;
     699                case 'weight': $_[] = $addon->dimensions['weight'];
     700                case 'saleprice':
     701                case 'price':
     702                case 'shipfee':
     703                case 'unitprice':
     704                    if ( $field === 'saleprice' ) $field = 'promoprice';
     705                    if ( isset($addon->$field) ) {
     706                        $_[] = ( isset($options['currency']) && Shopp::str_true($options['currency']) ) ?
     707                             money($addon->$field) : $addon->$field;
     708                    }
     709                    break;
     710                case 'download':
     711                    $link = false;
     712                    if ( isset($addon->download) && isset($addon->dkey) ) {
     713                        $label = __('Download', 'Shopp');
     714                        if ( isset($options['linktext']) && $options['linktext'] != '' ) $label = $options['linktext'];
     715
     716                        $dkey = $addon->dkey;
     717                        $request = '' == get_option('permalink_structure') ? "download/$dkey" : array('shopp_download' => $dkey);
     718                        $url = Shopp::url($request, 'catalog');
     719
     720                        $link = '<a href="' . $url . '">' . $label . '</a>';
     721                        return esc_html($link);
     722                    }
     723                    break;
     724                default:
     725                    if ( isset($addon->$field) )
     726                        $_[] = $addon->$field;
    703727            }
    704             return '';
     728
    705729        }
    706730
    707         return (float) $addon->value->unitprice;
     731        return join($options['separator'], $_);
    708732    }
    709733
     
    729753        if ( empty($item->addons) || ( is_string($item->addons) && ! Shopp::str_true($item->addons) ) ) return false;
    730754        $defaults = array(
    731             'prices' => 'on',
     755            'after' => '',
     756            'before' => '',
     757            'class' => '',
    732758            'download' => Shopp::__('Download'),
    733             'before' => '',
    734             'after' => '',
    735             'class' => '',
    736             'excludes' => ''
     759            'excludes' => '',
     760            'prices' => true,
     761            'separator' => ': '
    737762        );
    738763        $options = array_merge($defaults, $options);
     
    746771
    747772        $result = $before.'<ul' . $class . '>';
     773        list($menus, $menumap) = self::_addon_menus();
     774
     775        if ( false !== strpos($excludes, ',') )
     776            $excludes = explode(',', $excludes);
     777
    748778        foreach ( $item->addons->meta as $id => $addon ) {
    749             if ( in_array($addon->name, $excludes) ) continue;
     779            if ( in_array($addon->name, (array)$excludes) ) continue;
    750780            if ( 'inclusive' == $O->taxing )
    751781                $price = $addon->value->unitprice + ( $addon->value->unitprice * $taxrate );
     
    760790            }
    761791
     792            $menu = isset( $menumap[ $addon->value->options ]) ? $menus[ $menumap[ $addon->value->options ] ] : '';
     793
    762794            $pricing = Shopp::str_true($prices) ? " (" . money($price) . ")" : '';
    763             $result .= '<li>' . esc_html($addon->name . $pricing) . $link . '</li>';
     795            $result .= '<li>' . esc_html($menu . $separator . $addon->name . $pricing) . $link . '</li>';
    764796        }
    765797        $result .= '</ul>' . $after;
     
    835867    public static function item_has_addons ( $result, $options, $O ) {
    836868        $item = current($O->purchased);
    837         reset($item->addons);
    838         return ( count($item->addons) > 0 );
     869        reset($item->addons->meta);
     870        return ( count($item->addons->meta) > 0 );
    839871    }
    840872
     
    16261658    }
    16271659
     1660    /**
     1661     * Helper function that maps the current cart item's addons to the cart item's configured product menu options
     1662     *
     1663     * @internal
     1664     * @since 1.3
     1665     *
     1666     * @param int $id The product ID to retrieve addon menus from
     1667     * @return array A combined list of the menu labels list and addons menu map
     1668     **/
     1669    private static function _addon_menus () {
     1670        return ShoppProductThemeAPI::_addon_menus(shopp('purchase.get-item-product'));
     1671    }
     1672
    16281673}
  • shopp/trunk/api/theme/storefront.php

    r1053635 r1122729  
    18121812        $output .= '>';
    18131813        $output .= $pad.$cat_name;
    1814         if ( $args['products'] && isset($category->count) )
     1814
     1815        if ( Shopp::str_true($args['products']) && isset($category->count) )
    18151816            $output .= '&nbsp;&nbsp;('. $category->count .')';
    18161817        $output .= "</option>\n";
  • shopp/trunk/core/flow/Categorize.php

    r930519 r1122729  
    3838
    3939            wp_enqueue_script('postbox');
     40            wp_enqueue_script('swfupload-all');
     41
    4042            if ( user_can_richedit() ) {
    4143                wp_enqueue_script('editor');
  • shopp/trunk/core/flow/Checkout.php

    r1053635 r1122729  
    55 * Handles checkout form processing
    66 *
    7  * @author Jonathan Davis
    8  * @version 1.3
    97 * @copyright Ingenesis Limited, April 2013
    108 * @license GNU GPL version 3 (or later) {@see license.txt}
    11  * @package shopp
    12  * @subpackage order
     9 * @version 1.3
     10 * @package Shopp/Flow/Checkout
    1311 **/
    1412
     
    1816 * Checkout manager
    1917 *
    20  * @author Jonathan Davis
    2118 * @since 1.1
    2219 * @version 1.2
    23  * @package order
    2420 **/
    2521class ShoppCheckout extends FormPostFramework {
    2622
    27     private $confirmed = false;     // Flag to indicate
    28     private $Register = false;      // The ShoppRegistration manager
    29 
     23    /** @var boolean $confirmed Flag to indicate confirmed orders. */
     24    private $confirmed = false;
     25
     26    /** @var ShoppRegistration $Register The ShoppRegistration manager. */
     27    private $Register = false;
     28
     29    /** @var array $defaults The default inputs of the checkout form. */
    3030    protected $defaults = array(
    31         'guest' => false,
     31        'guest'       => false,
    3232        'sameaddress' => 'off',
    33         'firstname' => '',
    34         'lastname' => '',
    35         'phone' => '',
    36         'company' => '',
    37         'shipmethod' => false,
    38         'billing' => array(),
    39         'shipping' => array(),
    40         'info' => array(),
    41         'data' => array()
     33        'firstname'   => '',
     34        'lastname'    => '',
     35        'phone'       => '',
     36        'company'     => '',
     37        'shipmethod'  => false,
     38        'billing'     => array(),
     39        'shipping'    => array(),
     40        'info'        => array(),
     41        'data'        => array()
    4242    );
    4343
    44     public function __construct () {
    45 
    46         Shopping::restore('confirmed',$this->confirmed);
     44    /**
     45     * Constructor.
     46     *
     47     * @since 1.1
     48     *
     49     * @return void
     50     **/
     51    public function __construct() {
     52
     53        Shopping::restore('confirmed', $this->confirmed);
    4754
    4855        if ( empty($_POST) ) return;
     
    7683    }
    7784
    78     public function data () {
     85    /**
     86     * Adds custom order data to the order data registry.
     87     *
     88     * @since 1.3
     89     *
     90     * @return void
     91     **/
     92    public function data() {
    7993
    8094        if ( $this->form('data') )
     
    8397    }
    8498
    85     public function customer () {
     99    /**
     100     * Processes customer account fields.
     101     *
     102     * @since 1.3
     103     *
     104     * @return void
     105     **/
     106    public function customer() {
    86107
    87108        $Customer = ShoppOrder()->Customer;
     
    97118    }
    98119
    99     public function shipaddress () {
     120    /**
     121     * Processes changes to the shipping address.
     122     *
     123     * @since 1.3
     124     *
     125     * @return void
     126     **/
     127    public function shipaddress() {
    100128
    101129        $Cart = ShoppOrder()->Cart;
     
    113141
    114142    /**
    115      * Processes changes to the shipping method
     143     * Processes changes to the shipping method.
    116144     *
    117145     * Handles changes to the shipping method outside of other
    118      * checkout processes
    119      *
    120      * @author Jonathan Davis
    121      * @since 1.1
    122      *
    123      * @return void
    124      **/
    125     public function shipmethod () {
     146     * checkout processes.
     147     *
     148     * @since 1.1
     149     *
     150     * @return void
     151     **/
     152    public function shipmethod() {
    126153        $Shiprates = ShoppOrder()->Shiprates;
    127154        $ShippingAddress = ShoppOrder()->Shipping;
     
    146173
    147174
    148     public function billaddress () {
     175    /**
     176     * Processes changes to the billing address.
     177     *
     178     * @since 1.3
     179     *
     180     * @return void
     181     **/
     182    public function billaddress() {
    149183        $Cart = ShoppOrder()->Cart;
    150184        $BillingAddress = ShoppOrder()->Billing;
     
    162196    }
    163197
    164     public function payment () {
     198    /**
     199     * Processes payment information changes.
     200     *
     201     * @since 1.3
     202     *
     203     * @return void
     204     **/
     205    public function payment() {
     206        if ( ! $this->paycard() ) return;
     207
     208        add_filter('shopp_validate_checkout', array('ShoppFormValidation', 'paycard'));
     209
    165210        $Billing = ShoppOrder()->Billing;
    166211        $Payments = ShoppOrder()->Payments;
    167 
    168         // Change the cardtype to the selected payment service option label
    169         $Billing->cardtype = $Payments->selected()->label;
    170 
    171         if ( ! $this->paycard() ) return;
    172 
    173         add_filter('shopp_validate_checkout', array('ShoppFormValidation', 'paycard'));
    174 
    175212        $form = $this->form('billing');
     213
     214        // Change the default cardtype to the selected payment service option label
     215        $Billing->cardtype = empty($form['cardtype']) ? $Payments->selected()->label : $form['cardtype'];
    176216
    177217        // If the card number is provided over a secure connection
     
    181221
    182222        // Sanitize the card number to ensure it only contains numbers
    183         if ( ! empty($form['card']) )
    184             $Billing->card = preg_replace('/[^\d]/', '', $form['card']);
    185 
    186         $form['cardexpires'] = sprintf('%02d%02d', $form['cardexpires-mm'], $form['cardexpires-yy']);
    187 
    188         if ( ! empty($form['cardexpires-mm']) && ! empty($form['cardexpires-yy'])) {
    189             $exmm = preg_replace('/[^\d]/', '', $form['cardexpires-mm']);
    190             $exyy = preg_replace('/[^\d]/', '', $form['cardexpires-yy']);
    191             $Billing->cardexpires = mktime(0,0,0,$exmm,1,($exyy)+2000);
     223        if ( strlen( $PAN = self::digitsonly($form['card']) ) > 4 )
     224            $Billing->card = $PAN;
     225
     226        if ( ! empty($form['cardexpires-mm']) && ! empty($form['cardexpires-yy']) ) {
     227            $exmm = self::digitsonly($form['cardexpires-mm']);
     228            $exyy = self::digitsonly($form['cardexpires-yy']);
     229            $Billing->cardexpires = mktime(0, 0, 0, $exmm, 1, $exyy + 2000);
    192230        } else $Billing->cardexpires = 0;
    193231
    194         $Billing->cvv = preg_replace('/[^\d]/', '', $form['cvv']);
     232        $Billing->cvv = self::digitsonly($form['cvv']);
    195233
    196234        // Extra card security check fields
    197235        if ( ! empty($form['xcsc']) ) {
    198236            $Billing->xcsc = array();
    199             foreach ( (array)$form['xcsc'] as $field => $value ) {
     237            foreach ( (array) $form['xcsc'] as $field => $value ) {
    200238                $Billing->Billing->xcsc[] = $field; // Add to the XCSC registry of fields
    201239                $Billing->$field = $value;          // Add the property
     
    206244
    207245    /**
    208      * Determine if payment card data has been submitted
    209      *
    210      * @author Jonathan Davis
    211      * @since 1.1
    212      *
    213      * @return boolean
    214      **/
    215     public function paycard () {
    216         $fields = array('card','cardexpires-mm','cardexpires-yy','cvv');
     246     * Determine if payment card data has been submitted.
     247     *
     248     * @since 1.1
     249     *
     250     * @return boolean True if payment card information was submitted, false otherwise.
     251     **/
     252    public function paycard() {
     253        $fields = array('card', 'cardexpires-mm', 'cardexpires-yy', 'cvv');
    217254        $billing = $this->form('billing');
    218255        foreach ( $fields as $field )
     
    223260
    224261    /*
    225      * Checkout form processing
     262     * Checkout form processing.
    226263     *
    227264     * Handles taking user input from the checkout form and
    228      * processing the information into useable order data
    229      *
    230      * @author Jonathan Davis
    231      * @since 1.1
    232      *
    233      * @return void
    234      **/
    235     public function process () {
     265     * processing the information into useable order data.
     266     *
     267     * @since 1.1
     268     *
     269     * @return void
     270     **/
     271    public function process() {
     272
     273        $action = $this->form('checkout');
     274        if ( 'process' != $action ) return;
     275
    236276        $Payments = ShoppOrder()->Payments;
    237277        $Cart = ShoppOrder()->Cart;
    238278
    239279        $forcedconfirm = 'always' == shopp_setting('order_confirmation');
    240 
    241         $action = $this->form('checkout');
    242 
    243         if ( ! $action || 'process' != $action) return;
    244 
    245280        $wasfree = $Cart->orderisfree(); // Get current free status
    246281        $estimated = $Cart->total();     // Get current total
     
    254289        // Catch originally free orders that get extra (shipping) costs added to them
    255290        if ( $wasfree && $Payments->count() > 1 && ! $Cart->orderisfree() && empty($Payments->selected()->cards) ) {
    256             shopp_add_error( __('The order amount changed and requires that you select a payment method.','Shopp') );
    257             Shopp::redirect( Shopp::url(false,'checkout', ShoppOrder()->security()) );
     291            shopp_add_error( Shopp::__('The order amount changed and requires that you select a payment method.') );
     292            Shopp::redirect( Shopp::url(false, 'checkout', ShoppOrder()->security()) );
    258293        }
    259294
     
    272307
    273308    /**
    274      * Account registration processing
    275      *
    276      * @author Jonathan Davis
    277      * @since 1.3
    278      **/
    279     public function registration () {
     309     * Account registration processing.
     310     *
     311     * @since 1.3
     312     **/
     313    public function registration() {
    280314
    281315        // Validation already conducted during the checkout process
     
    290324
    291325    /**
    292      * Confirms the order and starts order processing
    293      *
    294      * @author Jonathan Davis
    295      * @since 1.1
    296      *
    297      * @return void
    298      **/
    299     public function confirmed () {
     326     * Confirms the order and starts order processing.
     327     *
     328     * @since 1.1
     329     *
     330     * @return void
     331     **/
     332    public function confirmed() {
    300333
    301334        if ( 'confirmed' == $this->form('checkout') ) {
     
    306339    }
    307340
     341    /**
     342     * Filters a string to provide only the digits found in the string.
     343     *
     344     * @since 1.3.9
     345     *
     346     * @param string $string The string to filter
     347     * @return string The string of digits
     348     **/
     349    protected static function digitsonly( $string ) {
     350        $filtered = filter_var($string, FILTER_SANITIZE_NUMBER_INT);
     351        return str_replace(array('+', '-'), '', $filtered);
     352    }
     353
    308354}
  • shopp/trunk/core/flow/Dashboard.php

    r1020997 r1122729  
    266266        $purchasetable = ShoppDatabaseObject::tablename(ShoppPurchase::$table);
    267267        $purchasedtable = ShoppDatabaseObject::tablename(Purchased::$table);
    268         $txnstatus_labels = Lookup::txnstatus_labels();
     268        $txnlabels = Lookup::txnstatus_labels();
    269269
    270270        if ( ! ( $Orders = get_transient('shopp_dashboard_orders') ) ) {
     
    274274
    275275        if ( ! empty($Orders) ) {
    276             echo '<table class="widefat">';
    277             echo '<tr><th scope="col">'.__('Name','Shopp').'</th><th scope="col">'.__('Date','Shopp').'</th><th scope="col" class="num">'.__('Items','Shopp').'</th><th scope="col" class="num">'.__('Total','Shopp').'</th><th scope="col" class="num">'.__('Status','Shopp').'</th></tr>';
    278             echo '<tbody id="orders" class="list orders">';
     276
     277            echo  '<table class="widefat">'
     278                . '<thead>'
     279                . ' <tr>'
     280                . '     <th scope="col">' . __('Name','Shopp') . '</th>'
     281                . '     <th scope="col">' . __('Date','Shopp') . '</th>'
     282                . '     <th scope="col" class="num">' . Shopp::__('Items') . '</th>'
     283                . '     <th scope="col" class="num">' . Shopp::__('Total') . '</th>'
     284                . '     <th scope="col" class="num">' . Shopp::__('Status') . '</th>'
     285                . ' </tr>'
     286                . '</thead>'
     287                . ' <tbody id="orders" class="list orders">';
     288
    279289            $even = false;
    280290            foreach ( $Orders as $Order ) {
    281291                $classes = array();
    282292                if ( $even = !$even ) $classes[] = 'alternate';
    283                 $txnstatus = isset($txnstatus_labels[ $Order->txnstatus ]) ? $txnstatus_labels[$Order->txnstatus] : $Order->txnstatus;
     293                $txnstatus = isset($txnlabels[ $Order->txnstatus ]) ?
     294                    $txnlabels[$Order->txnstatus] : $Order->txnstatus;
     295                $status = isset($statusLabels[ $Order->status ]) ?
     296                    $statusLabels[ $Order->status ] : $Order->status;
     297                $contact = '' == $Order->firstname . $Order->lastname ?
     298                    '(no contact name)' : $Order->firstname . ' ' . $Order->lastname;
     299                $url = add_query_arg(array('page' => ShoppAdmin()->pagename('orders'), 'id' => $Order->id), admin_url('admin.php'));
    284300                $classes[] = strtolower(preg_replace('/[^\w]/', '_', $Order->txnstatus));
    285301
    286                 echo '<tr class="' . join(' ',$classes) . '">';
    287                 echo '<td><a class="row-title" href="'.add_query_arg(array('page'=>ShoppAdmin()->pagename('orders'),'id'=>$Order->id),admin_url('admin.php')).'" title="View &quot;Order '.$Order->id.'&quot;">'.((empty($Order->firstname) && empty($Order->lastname))?'(no contact name)':$Order->firstname.' '.$Order->lastname).'</a></td>';
    288                 echo '<td>'.date("Y/m/d",mktimestamp($Order->created)).'</td>';
    289                 echo '<td class="num items">'.$Order->items.'</td>';
    290                 echo '<td class="num total">'.money($Order->total).'</td>';
    291                 echo '<td class="num status">'.$statusLabels[ $Order->status ].'</td>';
    292                 echo '</tr>';
     302                echo  '<tr class="' . join(' ',$classes) . '">'
     303                    . ' <td><a class="row-title" href="' . $url . '" title="View &quot;Order '.$Order->id.'&quot;">'.((empty($Order->firstname) && empty($Order->lastname))?'(no contact name)':$Order->firstname.' '.$Order->lastname).'</a></td>'
     304                    . ' <td>'.date("Y/m/d",mktimestamp($Order->created)).'</td>'
     305                    . ' <td class="num items">'.$Order->items.'</td>'
     306                    . ' <td class="num total">'.money($Order->total).'</td>'
     307                    . ' <td class="num status">'.$statusLabels[ $Order->status ].'</td>'
     308                    . '</tr>';
    293309            }
     310
    294311            echo '</tbody></table>';
     312
    295313        } else {
    296             echo '<p>'.__('No orders, yet.','Shopp').'</p>';
     314            echo '<p>' . Shopp::__('No orders, yet.') . '</p>';
    297315        }
    298316
  • shopp/trunk/core/flow/Order.php

    r1053635 r1122729  
    258258
    259259        // Duplicate purchase prevention #3142
     260        $timeout = SHOPP_GATEWAY_TIMEOUT + 5;
    260261        $lockid = 'shopp_order_' . ShoppShopping()->session();
    261262        if ( get_transient($lockid) ) {
     
    263264
    264265            // Wait until the lock is cleared
    265             $waited = 0; $timeout = SHOPP_GATEWAY_TIMEOUT + 5;
     266            $waited = 0;
    266267            while ( get_transient($lockid) && $waited++ < $timeout )
    267268                sleep(1);
     
    273274            return;
    274275
    275         } else set_transient($lockid, true, $timeout);
     276        } else {
     277            set_transient($lockid, true, $timeout);
     278            add_action('shutdown', create_function('', 'delete_transient("' . $lockid . '");'));
     279        }
    276280
    277281        shopp_add_order_event(false, 'purchase', array(
  • shopp/trunk/core/flow/Pages.php

    r1020997 r1122729  
    251251        add_filter('comments_array', array($this, 'nocomment'));
    252252        add_filter('wpseo_replacements', array($this, 'wpseo')); // compatibility helper for WPSEO
     253        add_filter('get_the_excerpt', create_function('$c', 'remove_filter("get_the_excerpt", "wp_trim_excerpt"); return $c;'), 5);
     254
    253255    }
    254256
     
    10031005            locate_shopp_template($templates, true);
    10041006        }
    1005         $content = ob_get_contents();
    1006         ob_end_clean();
     1007        $content = ob_get_clean();
    10071008
    10081009        return apply_filters('shopp_category_template', $content);
     
    10491050        $atts['template'] = array('product-shortcode.php', 'product.php');
    10501051        ShoppStorefront()->shortcoded[] = get_the_ID();
    1051         return apply_filters('shopp_product_shortcode', shopp('catalog.get-product', $atts));
     1052        return apply_filters('shopp_product_shortcode', shopp('storefront.get-product', $atts));
    10521053    }
    10531054
  • shopp/trunk/core/flow/Scripts.php

    r1020997 r1122729  
    288288    $scripts->add_data('system', 'group', 1);
    289289
    290     $scripts->add('shopp-swfobject', '/ui/behaviors/swfupload/plugins/swfupload.swfobject.min.js', array(), $version);
    291     $scripts->add_data('shopp-swfobject', 'group', 1);
    292 
    293     $scripts->add('shopp-swfupload-queue', '/ui/behaviors/swfupload/plugins/swfupload.queue.min.js', array(), $version);
    294     $scripts->add_data('shopp-swfupload-queue', 'group', 1);
    295 
    296290    $scripts->add('spin', '/ui/behaviors/spin.js', array('jquery'), $version);
    297291    $scripts->add_data('spin', 'group', 1);
    298 
    299     $scripts->add('swfupload', '/ui/behaviors/swfupload/swfupload.min.js', array('jquery','shopp-swfobject'), $version);
    300     $scripts->add_data('swfupload', 'group', 1);
    301292
    302293    $scripts->add('suggest', '/ui/behaviors/suggest.js', array('jquery'), $version);
  • shopp/trunk/core/flow/Service.php

    r1053635 r1122729  
    303303        $selected = shopp_setting('purchaselog_columns');
    304304        if ( empty($selected) ) $selected = array_keys($exportcolumns);
    305 
    306         $Gateways = array_merge($Shopp->Gateways->modules, array('ShoppFreeOrder' => $Shopp->Gateways->freeorder));
    307 
     305       
     306        $Gateways = $Shopp->Gateways;
     307       
    308308        include $this->ui('orders.php');
    309309    }
     
    429429            $reason = (int)$_POST['reason'];
    430430            $amount = Shopp::floatval($_POST['amount']);
     431            $Purchase->load_events();
    431432
    432433            if (!empty($_POST['message'])) {
     
    435436            }
    436437
    437             if (!Shopp::str_true($_POST['send'])) { // Force the order status
    438                 shopp_add_order_event($Purchase->id,'notice',array(
    439                     'user' => $user->ID,
    440                     'kind' => 'refunded',
    441                     'notice' => __('Marked Refunded','Shopp')
    442                 ));
    443                 shopp_add_order_event($Purchase->id,'refunded',array(
    444                     'txnid' => $Purchase->txnid,
    445                     'gateway' => $Gateway->module,
    446                     'amount' => $amount
    447                 ));
    448                 shopp_add_order_event($Purchase->id,'voided',array(
    449                     'txnorigin' => $Purchase->txnid,    // Original transaction ID (txnid of original Purchase record)
    450                     'txnid' => time(),                  // Transaction ID for the VOID event
    451                     'gateway' => $Gateway->module       // Gateway handler name (module name from @subpackage)
    452                 ));
    453             } else {
    454                 shopp_add_order_event($Purchase->id,'refund',array(
    455                     'txnid' => $Purchase->txnid,
    456                     'gateway' => $Gateway->module,
    457                     'amount' => $amount,
    458                     'reason' => $reason,
    459                     'user' => $user->ID
    460                 ));
    461             }
    462 
    463             if (!empty($_POST['message']))
    464                 $this->addnote($Purchase->id,$_POST['message']);
    465 
    466             $Purchase->load_events();
     438            if ( $amount <= $Purchase->captured - $Purchase->refunded ) {
     439
     440                if ( ! Shopp::str_true($_POST['send']) ) { // Force the order status
     441                    shopp_add_order_event($Purchase->id,'notice',array(
     442                        'user' => $user->ID,
     443                        'kind' => 'refunded',
     444                        'notice' => __('Marked Refunded','Shopp')
     445                    ));
     446                    shopp_add_order_event($Purchase->id,'refunded',array(
     447                        'txnid' => $Purchase->txnid,
     448                        'gateway' => $Gateway->module,
     449                        'amount' => $amount
     450                    ));
     451                    shopp_add_order_event($Purchase->id,'voided',array(
     452                        'txnorigin' => $Purchase->txnid,    // Original transaction ID (txnid of original Purchase record)
     453                        'txnid' => time(),                  // Transaction ID for the VOID event
     454                        'gateway' => $Gateway->module       // Gateway handler name (module name from @subpackage)
     455                    ));
     456                } else {
     457                    shopp_add_order_event($Purchase->id,'refund',array(
     458                        'txnid' => $Purchase->txnid,
     459                        'gateway' => $Gateway->module,
     460                        'amount' => $amount,
     461                        'reason' => $reason,
     462                        'user' => $user->ID
     463                    ));
     464                }
     465
     466                if ( ! empty($_POST['message']) )
     467                    $this->addnote($Purchase->id, $_POST['message']);
     468
     469                $Purchase->load_events();
     470
     471            } else $this->notice(Shopp::__('Refund failed. Cannot refund more than the current balance.'), 'error');
     472
    467473        }
    468474
  • shopp/trunk/core/flow/Warehouse.php

    r1023860 r1122729  
    5151            wp_enqueue_script('postbox');
    5252            wp_enqueue_script('wp-lists');
     53            wp_enqueue_script('swfupload-all');
     54
    5355            if ( user_can_richedit() ) {
    5456                wp_enqueue_script('editor');
     
    6466            shopp_enqueue_script('priceline');
    6567            shopp_enqueue_script('ocupload');
    66             shopp_enqueue_script('swfupload');
    6768            shopp_enqueue_script('jquery-tmpl');
    6869            shopp_enqueue_script('suggest');
    6970            shopp_enqueue_script('search-select');
    70             shopp_enqueue_script('shopp-swfupload-queue');
    7171
    7272            do_action('shopp_product_editor_scripts');
     
    982982        $error = false;
    983983        if ( isset($_FILES['Filedata']['error']) ) $error = $_FILES['Filedata']['error'];
    984         if ( $error ) die( json_encode(array("error" => Lookup::errors('uploads', $error))) );
    985 
    986         if (!is_uploaded_file($_FILES['Filedata']['tmp_name']))
    987             die(json_encode(array("error" => __('The file could not be saved because the upload was not found on the server.','Shopp'))));
    988 
    989         if (!is_readable($_FILES['Filedata']['tmp_name']))
    990             die(json_encode(array("error" => __('The file could not be saved because the web server does not have permission to read the upload.','Shopp'))));
    991 
    992         if ($_FILES['Filedata']['size'] == 0)
    993             die(json_encode(array("error" => __('The file could not be saved because the uploaded file is empty.','Shopp'))));
     984        if ( $error ) die( json_encode(array('error' => Lookup::errors('uploads', $error))) );
     985
     986        if ( ! @is_uploaded_file($_FILES['Filedata']['tmp_name']) )
     987            die(json_encode(array('error' => Shopp::__('The file could not be saved because the upload was not found on the server.'))));
     988
     989        if ( 0 == $_FILES['Filedata']['size'] )
     990            die(json_encode(array('error' => Shopp::__('The file could not be saved because the uploaded file is empty.'))));
    994991
    995992        FileAsset::mimetypes();
     
    10031000        $File->filename = $File->name;
    10041001
    1005         list($extension, $mimetype, $properfile) = wp_check_filetype_and_ext($_FILES['Filedata']['tmp_name'],$File->name);
     1002        list($extension, $mimetype, $properfile) = wp_check_filetype_and_ext($_FILES['Filedata']['tmp_name'], $File->name);
    10061003        if ( empty($mimetype) ) $mimetype = 'application/octet-stream';
    10071004        $File->mime = $mimetype;
    10081005
    1009         if ( ! empty($properfile))
     1006        if ( ! empty($properfile) )
    10101007            $File->name = $File->filename = $properfile;
    10111008
    10121009        $File->size = filesize($_FILES['Filedata']['tmp_name']);
    1013         $File->store($_FILES['Filedata']['tmp_name'],'upload');
     1010        $File->store($_FILES['Filedata']['tmp_name'], 'upload');
    10141011
    10151012        $Error = ShoppErrors()->code('storage_engine_save');
    1016         if (!empty($Error)) die( json_encode( array('error' => $Error->message(true)) ) );
     1013        if ( ! empty($Error) )
     1014            die( json_encode( array('error' => $Error->message(true)) ) );
    10171015
    10181016        $File->save();
     
    10201018        do_action('add_product_download', $File,$_FILES['Filedata']);
    10211019
    1022         echo json_encode(array('id' => $File->id, 'name' => stripslashes($File->name), 'type' => $File->mime, 'size' => $File->size));
     1020        echo json_encode(array(
     1021            'id' => $File->id,
     1022            'name' => stripslashes($File->name),
     1023            'type' => $File->mime,
     1024            'size' => $File->size
     1025        ));
    10231026    }
    10241027
     
    10311034    public static function images () {
    10321035        $context = false;
    1033 
    10341036        $error = false;
    1035         if (isset($_FILES['Filedata']['error'])) $error = $_FILES['Filedata']['error'];
    1036         if ( $error ) die( json_encode(array("error" => Lookup::errors('uploads', $error))) );
    1037 
    1038         $valid_contexts = array('product','category');
    1039 
    1040         if (isset($_REQUEST['type']) && in_array(strtolower($_REQUEST['type']),$valid_contexts) ) {
     1037        $valid_contexts = array('product', 'category');
     1038
     1039        if ( isset($_FILES['Filedata']['error']) )
     1040            $error = $_FILES['Filedata']['error'];
     1041        if ( $error ) die( json_encode(array('error' => Lookup::errors('uploads', $error))) );
     1042
     1043        if ( isset($_REQUEST['type']) && in_array(strtolower($_REQUEST['type']), $valid_contexts ) ) {
    10411044            $parent = $_REQUEST['parent'];
    10421045            $context = strtolower($_REQUEST['type']);
    10431046        }
    10441047
    1045         if (!$context)
    1046             die(json_encode(array("error" => __('The file could not be saved because the server cannot tell whether to attach the asset to a product or a category.','Shopp'))));
    1047 
    1048         if (!is_uploaded_file($_FILES['Filedata']['tmp_name']))
    1049             die(json_encode(array("error" => __('The file could not be saved because the upload was not found on the server.','Shopp'))));
    1050 
    1051         if (!is_readable($_FILES['Filedata']['tmp_name']))
    1052             die(json_encode(array("error" => __('The file could not be saved because the web server does not have permission to read the upload from the server\'s temporary directory.','Shopp'))));
    1053 
    1054         if ($_FILES['Filedata']['size'] == 0)
    1055             die(json_encode(array("error" => __('The file could not be saved because the uploaded file is empty.','Shopp'))));
     1048        if ( ! $context )
     1049            die(json_encode(array('error' => Shopp::__('The file could not be saved because the server cannot tell whether to attach the asset to a product or a category.'))));
     1050
     1051        if ( ! @is_uploaded_file($_FILES['Filedata']['tmp_name']) )
     1052            die(json_encode(array('error' => Shopp::__('The file could not be saved because the upload was not found on the server.'))));
     1053
     1054        if ( 0 == $_FILES['Filedata']['size'] )
     1055            die(json_encode(array('error' => Shopp::__('The file could not be saved because the uploaded file is empty.'))));
    10561056
    10571057        // Save the source image
    1058         if ($context == "category") $Image = new CategoryImage();
     1058        if ( 'category' == $context )
     1059            $Image = new CategoryImage();
    10591060        else $Image = new ProductImage();
    10601061
    10611062        $Image->parent = $parent;
    1062         $Image->type = "image";
    1063         $Image->name = "original";
     1063        $Image->type = 'image';
     1064        $Image->name = 'original';
    10641065        $Image->filename = $_FILES['Filedata']['name'];
    1065         list($Image->width, $Image->height, $Image->mime, $Image->attr) = getimagesize($_FILES['Filedata']['tmp_name']);
     1066
     1067        $context = 'upload';
     1068        $tempfile = $_FILES['Filedata']['tmp_name'];
     1069
     1070        if ( ! @is_readable($tempfile) ) {
     1071
     1072            $context = 'file';
     1073            $tempfile = get_temp_dir() . $Image->filename;
     1074
     1075            if ( ! @move_uploaded_file($_FILES['Filedata']['tmp_name'], $tempfile) )
     1076                die(json_encode(array('error' => Shopp::__('The file could not be saved because the web server does not have permission to read the upload.'))));
     1077
     1078        }
     1079
     1080        list($Image->width, $Image->height, $Image->mime, $Image->attr) = getimagesize($tempfile);
    10661081        $Image->mime = image_type_to_mime_type($Image->mime);
    1067         $Image->size = filesize($_FILES['Filedata']['tmp_name']);
    1068 
    1069         if ( ! $Image->unique() ) die(json_encode(array("error" => __('The image already exists, but a new filename could not be generated.','Shopp'))));
    1070 
    1071         $Image->store($_FILES['Filedata']['tmp_name'],'upload');
     1082        $Image->size = filesize($tempfile);
     1083
     1084        if ( ! $Image->unique() ) die(json_encode(array('error' => Shopp::__('The image already exists, but a new filename could not be generated.'))));
     1085
     1086        $Image->store($tempfile, $context);
     1087
     1088        if( 'file' == $context )
     1089            unlink($tempfile);
     1090
    10721091        $Error = ShoppErrors()->code('storage_engine_save');
    1073         if (!empty($Error)) die( json_encode( array('error' => $Error->message(true)) ) );
     1092        if ( ! empty($Error) ) die( json_encode( array('error' => $Error->message(true)) ) );
    10741093
    10751094        $Image->save();
    10761095
    1077         if (empty($Image->id))
    1078             die(json_encode(array("error" => __('The image reference was not saved to the database.','Shopp'))));
    1079 
    1080         echo json_encode(array("id"=>$Image->id));
     1096        if ( empty($Image->id) )
     1097            die(json_encode(array('error' => Shopp::__('The image reference was not saved to the database.'))));
     1098
     1099        echo json_encode(array('id' => $Image->id));
    10811100        exit;
    10821101    }
  • shopp/trunk/core/library/Core.php

    r1053635 r1122729  
    803803        return join( ', ', $stack );
    804804
     805    }
     806
     807    /**
     808     * Outputs debug structures to the browser console.
     809     *
     810     * @since 1.3.9
     811     *
     812     * @param mixed $data The data to display in the console.
     813     * @return void
     814     **/
     815    public static function debug ( $data ) {
     816
     817        $backtrace  = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
     818
     819        list($debugcall, $callby, ) = $backtrace;
     820
     821        $stack = array();
     822        foreach ( $backtrace as $id => $call ) {
     823            if ( 'debug' == $caller['function'] ) continue;
     824            $ref = empty($call['file']) ? 'Call #' . $id : basename($call['file']) . ' @ '. $call['line'];
     825
     826            $stack[ $ref ] = isset( $call['class'] ) ?
     827                $call['class'] . $call['type'] . $call['function'] . "()"
     828                : $call['function'];
     829        }
     830        $callstack = (object) $stack;
     831
     832        $caller = ( empty($callby['class']) ? '' : $callby['class'] . $callby['type'] ) . $callby['function'] . '() from ' . $debugcall['file'] . ' @ ' . $debugcall['line'];
     833
     834        shopp_custom_script('shopp', "
     835            console.group('Debug " . $caller . "');
     836            console.debug(" . json_encode($data) . ");
     837            console.log('Call stack: %O', " . json_encode($stack) . ");
     838            console.groupEnd();
     839        ");
    805840    }
    806841
  • shopp/trunk/core/library/Error.php

    r970959 r1122729  
    413413        $this->loglevel = shopp_setting('error_logging');
    414414
    415         $this->dir = defined('SHOPP_LOG_PATH') ? SHOPP_LOG_PATH : sys_get_temp_dir();
     415        $this->dir = defined('SHOPP_LOG_PATH') ? SHOPP_LOG_PATH : get_temp_dir();
    416416        $this->dir = sanitize_path($this->dir); // Windows path sanitiation
    417417
     
    467467        }
    468468        $message = date("Y-m-d H:i:s", time())." - ".$error->message(false, true)."$debug\n";
    469         error_log($message, 3, $this->logfile);     // Log to Shopp error log file
     469        @error_log($message, 3, $this->logfile);        // Log to Shopp error log file
    470470        error_log($error->message(false, true));    // Log to PHP error log file
    471471    }
     
    480480     **/
    481481    public function reset () {
    482         $this->log = fopen($this->logfile, 'w');
     482        $this->log = @fopen($this->logfile, 'w');
    483483        fwrite($this->log, '');
    484         fclose($this->log);
     484        @fclose($this->log);
    485485    }
    486486
  • shopp/trunk/core/library/Modules.php

    r905841 r1122729  
    397397    }
    398398
     399    /**
     400     * Parse the base version number from the module.
     401     *
     402     * This method just grabs the numbers out of version
     403     * and avoids version tags like 'dev' or 'beta'.
     404     *
     405     * @since 1.2
     406     *
     407     * @return string|bool The version number string, or false otherwise
     408     **/
    399409    public static function baseversion ( $version ) {
    400410        preg_match('/^[\d\.]+/', $version, $baseversion);
    401         return $baseversion[0];
     411        return isset($baseversion[0]) ? $baseversion[0] : false;
    402412    }
    403413
  • shopp/trunk/core/library/Session.php

    r1053635 r1122729  
    448448        $entropy .= uniqid(mt_rand(), true);
    449449
     450        // Check for open_basedir restrictions
     451        $openbasedir = false === strpos(ini_get('open_basedir'), DIRECTORY_SEPARATOR);
     452
    450453        // Try adding entropy from the Unix random number generator
    451         if ( is_readable('/dev/urandom') && $h = fopen('/dev/urandom', 'rb') ) {
     454        if ( $openbasedir && @is_readable('/dev/urandom') && $h = fopen('/dev/urandom', 'rb') ) {
    452455            if ( function_exists('stream_set_read_buffer') )
    453456                stream_set_read_buffer($h, 0);
  • shopp/trunk/core/library/Version.php

    r1053635 r1122729  
    2222
    2323    /** @type int PATCH The maintenance patch version number */
    24     const PATCH = 8;
     24    const PATCH = 9;
    2525
    2626    /** @type string PRERELEASE The prerelease designation (dev, beta, RC1) */
     
    2828
    2929    /** @type string CODENAME The release project code name */
    30     const CODENAME = 'Barsoom';
     30    const CODENAME = 'Cydonia';
    3131
    3232    /** @type int DB The database schema version */
  • shopp/trunk/core/model/Cart.php

    r1053635 r1122729  
    8888
    8989        add_action('shopp_cart_item_retotal', array($this, 'processtime') );
    90         add_action('shopp_cart_item_retotal', array($this, 'itemtaxes') );
     90        add_action('shopp_cart_item_taxes', array($this, 'itemtaxes') );
    9191
    9292        add_action('shopp_init', array($this, 'tracking'));
  • shopp/trunk/core/model/Collection.php

    r1020997 r1122729  
    520520
    521521    static function register ( $class ) {
    522         global $Shopp,$ShoppTaxonomies;
     522        global $ShoppTaxonomies;
    523523
    524524        $namespace = get_class_property($class, 'namespace');
    525525        $taxonomy = get_class_property($class, 'taxon');
    526526        $hierarchical = get_class_property($class, 'hierarchical');
    527         $slug = SHOPP_NAMESPACE_TAXONOMIES ? ShoppPages()->baseslug() . '/' . $namespace : $namespace;
    528         register_taxonomy($taxonomy, array(ShoppProduct::$posttype), array(
    529             'hierarchical' => $hierarchical,
    530             'labels' => call_user_func(array($class,'labels'),$class),
    531             'show_ui' => true,
    532             'query_var' => true,
    533             'rewrite' => array( 'slug' => $slug, 'with_front' => false ),
    534             'update_count_callback' => array('ProductTaxonomy', 'recount'),
    535             'capabilities' => array(
    536                 'manage_terms' => 'shopp_categories',
    537                 'edit_terms'   => 'shopp_categories',
    538                 'delete_terms' => 'shopp_categories',
    539                 'assign_terms' => 'shopp_categories',
    540             )
    541         ));
    542 
    543         add_filter($taxonomy.'_rewrite_rules',array('ProductCollection','pagerewrites'));
    544 
    545         $ShoppTaxonomies[$taxonomy] = $class;
     527
     528        $slug = SHOPP_NAMESPACE_TAXONOMIES ?
     529            ShoppPages()->baseslug() . '/' . $namespace : $namespace;
     530
     531        register_taxonomy($taxonomy,
     532            array(ShoppProduct::$posttype),
     533            apply_filters('shopp_register_taxonomy_' . $taxonomy, array(
     534                'hierarchical' => $hierarchical,
     535                'labels' => call_user_func(array($class, 'labels'), $class),
     536                'show_ui' => true,
     537                'query_var' => true,
     538                'rewrite' => array('slug' => $slug, 'with_front' => false),
     539                'update_count_callback' => array('ProductTaxonomy', 'recount'),
     540                'capabilities' => array(
     541                    'manage_terms' => 'shopp_categories',
     542                    'edit_terms'   => 'shopp_categories',
     543                    'delete_terms' => 'shopp_categories',
     544                    'assign_terms' => 'shopp_categories',
     545                )
     546        )));
     547
     548        add_filter($taxonomy . '_rewrite_rules', array('ProductCollection', 'pagerewrites'));
     549
     550        $ShoppTaxonomies[ $taxonomy ] = $class;
    546551    }
    547552
    548553    static function labels () {
    549554        return array(
    550             'name' => __('Catalog Groups','Shopp'),
    551             'singular_name' => __('Catalog Group','Shopp'),
    552             'search_items' => __('Search Catalog Group','Shopp'),
    553             'popular_items' => __('Popular','Shopp'),
    554             'all_items' => __('Show All','Shopp'),
    555             'parent_item' => __('Parent Catalog Group','Shopp'),
    556             'parent_item_colon' => __('Parent Catalog Group:','Shopp'),
    557             'edit_item' => __('Edit Catalog Group','Shopp'),
    558             'update_item' => __('Update Catalog Group','Shopp'),
    559             'add_new_item' => __('New Catalog Group','Shopp'),
    560             'new_item_name' => __('New Catalog Group Name','Shopp'),
    561             'separate_items_with_commas' => __('Separate catalog groups with commas','Shopp'),
    562             'add_or_remove_items' => __('Add or remove catalog groups','Shopp'),
    563             'choose_from_most_used' => __('Choose from the most used catalog groups','Shopp')
     555            'name'                       => Shopp::__('Catalog Groups'),
     556            'singular_name'              => Shopp::__('Catalog Group'),
     557            'search_items'               => Shopp::__('Search Catalog Group'),
     558            'popular_items'              => Shopp::__('Popular'),
     559            'all_items'                  => Shopp::__('Show All'),
     560            'parent_item'                => Shopp::__('Parent Catalog Group'),
     561            'parent_item_colon'          => Shopp::__('Parent Catalog Group:'),
     562            'edit_item'                  => Shopp::__('Edit Catalog Group'),
     563            'update_item'                => Shopp::__('Update Catalog Group'),
     564            'add_new_item'               => Shopp::__('New Catalog Group'),
     565            'new_item_name'              => Shopp::__('New Catalog Group Name'),
     566            'separate_items_with_commas' => Shopp::__('Separate catalog groups with commas'),
     567            'add_or_remove_items'        => Shopp::__('Add or remove catalog groups'),
     568            'choose_from_most_used'      => Shopp::__('Choose from the most used catalog groups')
    564569        );
    565570    }
     
    14901495
    14911496    public function load ( array $options = array() ) {
    1492         $this->loading = array_merge( $this->_options, $options );
     1497        $this->loading = $options = array_merge( $this->_options, $options );
    14931498
    14941499        if ( isset($this->loading['show']) ) {
     
    16101615    public function smart ( array $options = array() ) {
    16111616        $this->loading['where'] = array("s.featured='on'");
    1612         $this->loading['order'] = 'newest';
     1617        $this->loading['order'] = empty($options['order']) ? 'newest' : $options['order']; // Default order to newest
    16131618    }
    16141619
  • shopp/trunk/core/model/Customer.php

    r1020997 r1122729  
    423423        if ( empty($_POST['customer']) ) return; // Not a valid customer profile update request
    424424
     425        check_admin_referer('shopp_profile_update');
     426
    425427        $defaults = array(
    426428            'phone' => '',
     
    474476
    475477        $this->updated(self::PROFILE, true);
     478
     479        if ( $this->_password_change )
     480            Shopp::redirect(Shopp::url(false, 'account'));
    476481
    477482    }
  • shopp/trunk/core/model/Discounts.php

    r1053635 r1122729  
    133133        // Check for failed promo codes
    134134        if ( empty($this->request) || $this->codeapplied( $this->request ) ) return;
    135        
     135
    136136        if( $this->validcode($this->request) ) {
    137137            shopp_add_error( Shopp::__('&quot;%s&quot; does not apply to the current order.', $this->request) );
    138             $this->request = false; 
     138            $this->request = false;
    139139        } else {
    140140            shopp_add_error( Shopp::__('&quot;%s&quot; is not a valid code.', $this->request) );
     
    484484        return isset( $this->codes[ strtolower($code) ]);
    485485    }
    486    
     486
    487487    /**
    488488     * Checks if a given code is attached to a valid rule
     
    496496    public function validcode( $code ) {
    497497        $Promotions = ShoppOrder()->Promotions;
    498        
     498
    499499        foreach($Promotions as $promo) {
    500500            if( empty($promo->code) ) continue;
     
    858858
    859859    }
    860    
     860
    861861    public function get_property() {
    862         return $this->property; 
     862        return $this->property;
    863863    }
    864864
  • shopp/trunk/core/model/Gateway.php

    r1020997 r1122729  
    551551     * @since 1.2
    552552     *
    553      * @return void
     553     * @param string $gateway The gateway hook name
     554     * @return GatewayFramework The activated gateway object.
    554555     **/
    555556    public function &get ( $gateway ) {
    556         if ( empty($this->active) ) $this->settings();
    557         if ( ! isset($this->active[ $gateway ]) ) return false;
    558         return $this->active[ $gateway ];
     557
     558        if ( empty($this->active) )
     559            $this->settings(); // Reload settings
     560
     561        if ( 'ShoppFreeOrder' == $gateway )
     562            return $this->freeorder;
     563        elseif ( isset($this->active[ $gateway ]) )
     564            return $this->active[ $gateway ];
     565        elseif ( isset($this->active[ "Shopp$gateway" ]) ) // @see #3256
     566            return $Gateways->active[ "Shopp$gateway" ];
     567
     568        $false = false;
     569        return $false;
     570
    559571    }
    560572
  • shopp/trunk/core/model/Item.php

    r1053635 r1122729  
    215215        if ( ! empty($Price->download) ) $this->download = $Price->download;
    216216
    217         if ( 'Shipped' == $Price->type ) $this->shipped = true;
     217        $this->shipped = ( 'Shipped' == $Price->type );
    218218
    219219        if ( $this->shipped ) {
     
    917917     **/
    918918    public function taxes ( $quantity = 1 ) {
    919         if ( ! $this->istaxed ) return;
     919        if ( ! $this->istaxed ) return do_action('shopp_cart_item_taxes', $this);
    920920
    921921        $Tax = ShoppOrder()->Tax;
     
    955955        }
    956956
     957        do_action('shopp_cart_item_taxes', $this);
    957958    }
    958959
  • shopp/trunk/core/model/Product.php

    r1053635 r1122729  
    12211221
    12221222        foreach ( $ids as $id ) { // Recount taxonomy counts #2968
     1223            $laststatus = get_post_status($id);
    12231224            $Post = new StdClass;
    12241225            $Post->ID = $id;
    12251226            $Post->post_type = ShoppProduct::$posttype;
    1226             wp_transition_post_status($status, $Product->status, $Post);
     1227            wp_transition_post_status($status, $laststatus, $Post);
    12271228        }
    12281229
  • shopp/trunk/core/model/Promotion.php

    r865739 r1122729  
    4646        $price_table = ShoppDatabaseObject::tablename(ShoppPrice::$table);
    4747
    48         $where_notdiscounted = array("0 = FIND_IN_SET($this->id,discounts)");
     48        // $where_notdiscounted = array("0 = FIND_IN_SET($this->id,discounts)");
    4949        $where = array();
     50        $excludes = array();
     51
    5052        // Go through each rule to construct an SQL query
    5153        // that gets all applicable product & price ids
    52         if (!empty($this->rules) && is_array($this->rules)) {
    53             foreach ($this->rules as $rule) {
    54 
    55                 if (ShoppPromo::$values[$rule['property']] == "price")
    56                     $value = Shopp::floatval($rule['value']);
    57                 else $value = $rule['value'];
    58 
    59                 switch($rule['logic']) {
    60                     case "Is equal to": $match = "='$value'"; break;
    61                     case "Is not equal to": $match = "!='$value'"; break;
    62                     case "Contains": $match = " LIKE '%$value%'"; break;
    63                     case "Does not contain": $match = " NOT LIKE '%$value%'"; break;
    64                     case "Begins with": $match = " LIKE '$value%'"; break;
    65                     case "Ends with": $match = " LIKE '%$value'"; break;
    66                     case "Is greater than": $match = "> $value"; break;
    67                     case "Is greater than or equal to": $match = ">= $value"; break;
    68                     case "Is less than": $match = "< $value"; break;
    69                     case "Is less than or equal to": $match = "<= $value"; break;
    70                 }
    71 
    72                 switch($rule['property']) {
    73                     case "Name":
    74                         $where[] = "p.post_title$match";
    75                         $joins[$product_table] = "INNER JOIN $product_table as p ON prc.product=p.id";
    76                         break;
    77                     case "Category":
    78                         $where[] = "tm.name$match";
    79                         global $wpdb;
    80                         $joins[$wpdb->term_relationships] = "INNER JOIN $wpdb->term_relationships AS tr ON (prc.product=tr.object_id)";
    81                         $joins[$wpdb->term_taxonomy] = "INNER JOIN $wpdb->term_taxonomy AS tt ON (tr.term_taxonomy_id=tt.term_taxonomy_id)";
    82                         $joins[$wpdb->terms] = "INNER JOIN $wpdb->terms AS tm ON (tm.term_id=tt.term_id)";
    83                         break;
    84                     case "Variation": $where[] = "prc.label$match"; break;
    85                     case "Price": $where[] = "prc.price$match"; break;
    86                     case "Sale price": $where[] = "(prc.onsale='on' AND prc.saleprice$match)"; break;
    87                     case "Type": $where[] = "prc.type$match"; break;
    88                     case "In stock": $where[] = "(prc.inventory='on' AND prc.stock$match)"; break;
    89                 }
    90 
     54        foreach ( (array) $this->rules as $rule ) {
     55
     56            if ( 'price' == ShoppPromo::$values[ $rule['property'] ] )
     57                $value = Shopp::floatval($rule['value']);
     58            else $value = $rule['value'];
     59
     60            switch( $rule['logic'] ) {
     61                case "Is equal to": $match = "='$value'"; break;
     62                case "Is not equal to": $match = "!='$value'"; break;
     63                case "Contains": $match = " LIKE '%$value%'"; break;
     64                case "Does not contain": $match = " NOT LIKE '%$value%'"; break;
     65                case "Begins with": $match = " LIKE '$value%'"; break;
     66                case "Ends with": $match = " LIKE '%$value'"; break;
     67                case "Is greater than": $match = "> $value"; break;
     68                case "Is greater than or equal to": $match = ">= $value"; break;
     69                case "Is less than": $match = "< $value"; break;
     70                case "Is less than or equal to": $match = "<= $value"; break;
    9171            }
    9272
    93         }
    94 
    95         $operator = 'all' == strtolower($this->search)?' AND ': ' OR ';
    96         if (!empty($where)) $where = "WHERE ".join($operator,$where);
     73            switch( $rule['property'] ) {
     74                case "Name":
     75                    $where[] = "p.post_title$match";
     76                    $joins[ $product_table ] = "INNER JOIN $product_table as p ON prc.product=p.id";
     77                    break;
     78                case "Category":
     79                    $where[] = "tm.name$match";
     80                    if ( '!' == $match{0} )
     81                        $excludes[] = "tm.name" . ltrim($match, '!');
     82                    global $wpdb;
     83                    $joins[ $wpdb->term_relationships ] = "INNER JOIN $wpdb->term_relationships AS tr ON (prc.product=tr.object_id)";
     84                    $joins[ $wpdb->term_taxonomy ] = "INNER JOIN $wpdb->term_taxonomy AS tt ON (tr.term_taxonomy_id=tt.term_taxonomy_id)";
     85                    $joins[ $wpdb->terms ] = "INNER JOIN $wpdb->terms AS tm ON (tm.term_id=tt.term_id)";
     86                    break;
     87                case "Variation": $where[] = "prc.label$match"; break;
     88                case "Price": $where[] = "prc.price$match"; break;
     89                case "Sale price": $where[] = "(prc.onsale='on' AND prc.saleprice$match)"; break;
     90                case "Type": $where[] = "prc.type$match"; break;
     91                case "In stock": $where[] = "(prc.inventory='on' AND prc.stock$match)"; break;
     92            }
     93
     94        }
     95
     96
     97        $operator = 'all' == strtolower($this->search) ? ' AND ' : ' OR ';
     98
     99        if ( ! empty($where) ) $where = "WHERE " . join($operator, $where);
    97100        else $where = false;
    98101
    99         if (!empty($joins)) $joins = join(' ',$joins);
     102        if ( ! empty($joins) ) $joins = join(' ', $joins);
    100103        else $joins = false;
    101104
    102105        // Find all the pricetags the promotion is *currently assigned* to
    103106        $query = "SELECT id FROM $price_table WHERE 0 < FIND_IN_SET($this->id,discounts)";
    104         $current = sDB::query($query,'array','col','id');
     107        $current = sDB::query($query, 'array', 'col', 'id');
     108
     109        $exclude = '';
     110        if ( ! empty($excludes) ) {
     111            // Find all the pricetags the promotion should exclude
     112            $subquery = "SELECT prc.id FROM $price_table AS prc $joins WHERE " . join( ' OR ', $excludes);
     113            $exclude = " AND prc.id NOT IN ($subquery)";
     114        }
    105115
    106116        // Find all the pricetags the promotion is *going to apply* to
    107117        $query = "SELECT prc.id,prc.product,prc.discounts FROM $price_table AS prc
    108118                    $joins
    109                     $where";
    110         $updates = sDB::query($query,'array','col','id');
     119                    $where $exclude";
     120        $updates = sDB::query($query, 'array', 'col', 'id');
    111121
    112122        // Determine which records need promo added to and removed from
    113         $added = array_diff($updates,$current);
    114         $removed = array_diff($current,$updates);
     123        $added = array_diff($updates, $current);
     124        $removed = array_diff($current, $updates);
    115125
    116126        // Add discounts to specific rows
    117127        $query = "UPDATE $price_table
    118128                    SET discounts=CONCAT(discounts,IF(discounts='','$this->id',',$this->id'))
    119                     WHERE id IN (".join(',',$added).")";
    120         if (!empty($added)) sDB::query($query);
     129                    WHERE id IN (" . join(',', $added) . ")";
     130        if ( ! empty($added) ) sDB::query($query);
    121131
    122132        // Remove discounts from pricetags that now don't match the conditions
    123         if (!empty($removed)) $this->uncatalog($removed);
     133        if ( ! empty($removed) ) $this->uncatalog($removed);
    124134
    125135        // Recalculate product stats for products with pricetags that have changed
    126136        $Collection = new PromoProducts(array('id' => $this->id));
    127         $Collection->load( array('load'=>array('prices'),'pagination' => false) );
     137        $Collection->load( array('load' => array('prices'), 'pagination' => false) );
    128138    }
    129139
     
    132142
    133143        $table = ShoppDatabaseObject::tablename(ShoppPrice::$table);
    134         echo "SELECT id,product,discounts,FIND_IN_SET($this->id,discounts) AS offset FROM $table WHERE id IN ('" . join(',', $pricetags) . "')";
     144        //echo "SELECT id,product,discounts,FIND_IN_SET($this->id,discounts) AS offset FROM $table WHERE id IN ('" . join(',', $pricetags) . "')";
    135145        $discounted = sDB::query("SELECT id,product,discounts,FIND_IN_SET($this->id,discounts) AS offset FROM $table WHERE id IN ('" . join(',', $pricetags) . "')", 'array');
    136146
     
    140150            $promos = explode(',', $pricetag->discounts);
    141151            array_splice($promos, ($pricetag->offset - 1), 1); // Remove the located promotion ID from the discounts list
    142             echo "UPDATE $table SET discounts='" . join(',', $promos) . "' WHERE id=$pricetag->id";
     152            //echo "UPDATE $table SET discounts='" . join(',', $promos) . "' WHERE id=$pricetag->id";
    143153            sDB::query("UPDATE $table SET discounts='" . join(',', $promos) . "' WHERE id=$pricetag->id");
    144154        }
     
    146156        // Force resum on products next load
    147157        $summary = ShoppDatabaseObject::tablename('summary');
    148         echo "UPDATE $summary SET modified='" . ProductSummary::RECALCULATE . "' WHERE product IN (" . join(',', $products). ")";
     158        //echo "UPDATE $summary SET modified='" . ProductSummary::RECALCULATE . "' WHERE product IN (" . join(',', $products). ")";
    149159        sDB::query("UPDATE $summary SET modified='" . ProductSummary::RECALCULATE . "' WHERE product IN (" . join(',', $products). ")");
    150160    }
  • shopp/trunk/core/model/Purchase.php

    r970959 r1122729  
    286286
    287287    public function capturable () {
     288        if ( empty($this->events) ) $this->load_events();
    288289        if ( ! $this->authorized ) return 0.0;
    289290        return ($this->authorized - (float)$this->captured);
     
    291292
    292293    public function refundable () {
     294        if ( empty($this->events) ) $this->load_events();
    293295        if (!$this->captured) return 0.0;
    294296        return ($this->captured - (float)$this->refunded);
     
    296298
    297299    public function gateway () {
    298         $Shopp = Shopp::object();
    299         $Gateways = $Shopp->Gateways;
     300        $Gateways = Shopp::object()->Gateways;
    300301
    301302        $processor = $this->gateway;
    302303        if ( 'ShoppFreeOrder' == $processor ) return $Gateways->freeorder;
    303         if ( isset($Gateways->active[ $processor ]) ) return $Gateways->active[ $processor ];
    304         else {
    305             foreach ( $Gateways->active as $Gateway ) {
    306                 if ($processor != $Gateway->name) continue;
    307                 return $Gateway;
    308                 break;
    309             }
    310         }
     304
     305        $Gateway = $Gateways->get($processor);
     306
     307        if ( ! $Gateway ) {
     308            foreach ( $Gateways->active as $Gateway )
     309                if ( $processor == $Gateway->name )
     310                    return $Gateway;
     311        } else return $Gateway;
     312
    311313        return false;
    312314    }
  • shopp/trunk/core/model/Shiprates.php

    r970959 r1122729  
    8383    public function item ( ShoppShippableItem $Item ) {
    8484
    85         if ( ! $Item->shippable ) return; // Don't track the item
     85        if ( ! $Item->shippable ) {
     86            $this->takeoff($Item->id);
     87            return; // Don't track the item
     88        }
    8689
    8790        $this->shippable[ $Item->id ] = $Item->shipsfree;
     
    434437
    435438/**
    436  * Converts a line item object to on that is compatible with the ShoppShiprates system
     439 * Converts a line item object to one that is compatible with the ShoppShiprates system
    437440 *
    438441 * @author Jonathan Davis
  • shopp/trunk/core/ui/behaviors/address.js

    r1053635 r1122729  
    5252    var sameaddr = $('.sameaddress'),
    5353        shipFields = $('#shipping-address-fields'),
    54         billFields = $('#billing-address-fields');
     54        billFields = $('#billing-address-fields'),
     55        keepLastValue = function () { // Save the current value of the field
     56            $(this).attr('data-last', $(this).val());
     57        };
    5558
    56     // Update name fields
    57     $('#firstname,#lastname').change(function () {
    58         $('#billing-name,#shipping-name').filter(function() {
    59             return ( this.value === '' );
    60         }).val(new String($('#firstname').val()+" "+$('#lastname').val()).trim());
    61     });
     59    // Handle changes to the firstname and lastname fields
     60    $('#firstname,#lastname').each(keepLastValue).change(function () {
     61        var namefield = $(this); // Reference to the modified field
     62            lastfirstname = $('#firstname').attr('data-last'),
     63            lastlastname = $('#lastname').attr('data-last'),
     64            firstlast = ( ( $('#firstname').val() ).trim() + " " + ( $('#lastname').val() ).trim() ).trim();
     65
     66            namefield.val( (namefield.val()).trim() );
     67
     68        // Update the billing name and shipping name
     69        $('#billing-name,#shipping-name').each(function() {
     70            var value = $(this).val();
     71
     72            if ( value.trim().length == 0 ) {
     73                // Empty billing or shipping name
     74                $('#billing-name,#shipping-name').val(firstlast);
     75            } else if ( '' != value && ( $('#firstname').val() == value || $('#lastname').val() == value ) ) {
     76                // Only one name entered (so far), add the other name
     77                $(this).val(firstlast);
     78            } else if ( 'firstname' == namefield.attr('id') && value.indexOf(lastlastname) != -1 ) {
     79                // firstname changed & last lastname matched
     80                $(this).val( value.replace(lastfirstname, namefield.val()).trim() );
     81            } else if ( 'lastname' == namefield.attr('id') && value.indexOf(lastfirstname) != -1 ) {
     82                // lastname changed & last firstname matched
     83                $(this).val( value.replace(lastlastname, namefield.val()).trim() );
     84            }
     85
     86        });
     87
     88    }).change(keepLastValue);
    6289
    6390    // Update state/province
  • shopp/trunk/core/ui/behaviors/address.min.js

    r1053635 r1122729  
    44 * Licensed under the GPLv3 {@see license.txt}
    55 */
    6 (function($){jQuery.fn.upstate=function(){if(typeof regions==="undefined"){return}$(this).change(function(e,init){var $this=$(this),prefix=$this.attr("id").split("-")[0],country=$this.val(),state=$this.parents().find("#"+prefix+"-state"),menu=$this.parents().find("#"+prefix+"-state-menu"),options='<option value=""></option>';if(menu.length==0){return true}if(menu.hasClass("hidden")){menu.removeClass("hidden").hide()}if(regions[country]||(init&&menu.find("option").length>1)){state.setDisabled(true).addClass("_important").hide();if(regions[country]){$.each(regions[country],function(value,label){options+='<option value="'+value+'">'+label+"</option>"});if(!init){menu.empty().append(options).setDisabled(false).show().focus()}if(menu.hasClass("auto-required")){menu.addClass("required")}}else{if(menu.hasClass("auto-required")){menu.removeClass("required")}}menu.setDisabled(false).show();$("label[for="+state.attr("id")+"]").attr("for",menu.attr("id"))}else{menu.empty().setDisabled(true).hide();state.setDisabled(false).show().removeClass("_important");$("label[for="+menu.attr("id")+"]").attr("for",state.attr("id"));if(!init){state.val("").focus()}}}).trigger("change",[true]);return $(this)}})(jQuery);jQuery(document).ready(function($){var sameaddr=$(".sameaddress"),shipFields=$("#shipping-address-fields"),billFields=$("#billing-address-fields");$("#firstname,#lastname").change(function(){$("#billing-name,#shipping-name").filter(function(){return(this.value==="")}).val(new String($("#firstname").val()+" "+$("#lastname").val()).trim())});$("#billing-country,#shipping-country").upstate();sameaddr.change(function(e,init){var refocus=false,bc=$("#billing-country"),sc=$("#shipping-country"),prime="billing"==sameaddr.val()?shipFields:billFields,alt="shipping"==sameaddr.val()?shipFields:billFields;if(sameaddr.is(":checked")){prime.removeClass("half");alt.hide().find(".required").setDisabled(true)}else{prime.addClass("half");alt.show().find(".disabled:not(._important)").setDisabled(false);if(!init){refocus=true}}if(bc.is(":visible")){bc.trigger("change.localemenu",[init])}if(sc.is(":visible")){sc.trigger("change.localemenu",[init])}if(refocus){alt.find("input:first").focus()}}).trigger("change",[true]).click(function(){$(this).change()})});
     6(function($){jQuery.fn.upstate=function(){if(typeof regions==="undefined"){return}$(this).change(function(e,init){var $this=$(this),prefix=$this.attr("id").split("-")[0],country=$this.val(),state=$this.parents().find("#"+prefix+"-state"),menu=$this.parents().find("#"+prefix+"-state-menu"),options='<option value=""></option>';if(menu.length==0){return true}if(menu.hasClass("hidden")){menu.removeClass("hidden").hide()}if(regions[country]||(init&&menu.find("option").length>1)){state.setDisabled(true).addClass("_important").hide();if(regions[country]){$.each(regions[country],function(value,label){options+='<option value="'+value+'">'+label+"</option>"});if(!init){menu.empty().append(options).setDisabled(false).show().focus()}if(menu.hasClass("auto-required")){menu.addClass("required")}}else{if(menu.hasClass("auto-required")){menu.removeClass("required")}}menu.setDisabled(false).show();$("label[for="+state.attr("id")+"]").attr("for",menu.attr("id"))}else{menu.empty().setDisabled(true).hide();state.setDisabled(false).show().removeClass("_important");$("label[for="+menu.attr("id")+"]").attr("for",state.attr("id"));if(!init){state.val("").focus()}}}).trigger("change",[true]);return $(this)}})(jQuery);jQuery(document).ready(function($){var sameaddr=$(".sameaddress"),shipFields=$("#shipping-address-fields"),billFields=$("#billing-address-fields"),keepLastValue=function(){$(this).attr("data-last",$(this).val())};$("#firstname,#lastname").each(keepLastValue).change(function(){var namefield=$(this);lastfirstname=$("#firstname").attr("data-last"),lastlastname=$("#lastname").attr("data-last"),firstlast=(($("#firstname").val()).trim()+" "+($("#lastname").val()).trim()).trim();namefield.val((namefield.val()).trim());$("#billing-name,#shipping-name").each(function(){var value=$(this).val();if(value.trim().length==0){$("#billing-name,#shipping-name").val(firstlast)}else{if(""!=value&&($("#firstname").val()==value||$("#lastname").val()==value)){$(this).val(firstlast)}else{if("firstname"==namefield.attr("id")&&value.indexOf(lastlastname)!=-1){$(this).val(value.replace(lastfirstname,namefield.val()).trim())}else{if("lastname"==namefield.attr("id")&&value.indexOf(lastfirstname)!=-1){$(this).val(value.replace(lastlastname,namefield.val()).trim())}}}}})}).change(keepLastValue);$("#billing-country,#shipping-country").upstate();sameaddr.change(function(e,init){var refocus=false,bc=$("#billing-country"),sc=$("#shipping-country"),prime="billing"==sameaddr.val()?shipFields:billFields,alt="shipping"==sameaddr.val()?shipFields:billFields;if(sameaddr.is(":checked")){prime.removeClass("half");alt.hide().find(".required").setDisabled(true)}else{prime.addClass("half");alt.show().find(".disabled:not(._important)").setDisabled(false);if(!init){refocus=true}}if(bc.is(":visible")){bc.trigger("change.localemenu",[init])}if(sc.is(":visible")){sc.trigger("change.localemenu",[init])}if(refocus){alt.find("input:first").focus()}}).trigger("change",[true]).click(function(){$(this).change()})});
  • shopp/trunk/core/ui/behaviors/cart.js

    r1020997 r1122729  
    117117    });
    118118
    119     $('input[type=image]').click(function () { $(this.form).submit(); });
     119    $('#cart input[type=image]').click(function () { $(this.form).submit(); });
    120120
    121121    // "Add to cart" button behaviors
  • shopp/trunk/core/ui/behaviors/cart.min.js

    r1020997 r1122729  
    44 * Licensed under the GPLv3 {@see license.txt}
    55 */
    6 ;function addtocart(form){var $=jQuery,options=$(form).find("select.options"),selections=true;if(options){options.each(function(i,menu){if($(menu).val()==""){return(selections=false)}});if(!selections){if(!$s.opreq){$s.opreq="You must select the options for this item before you can add it to your shopping cart."}alert($s.opreq);return false}}if($(form).find("input.addtocart").hasClass("ajax-html")){ShoppCartAjaxRequest(form,"html")}else{if($(form).find("input.addtocart").hasClass("ajax")){ShoppCartAjaxRequest(form)}else{form.submit()}}return false}function ShoppCartAjaxRequest(form,response){if(!response){response="json"}var $=jQuery,url=form.action,$form=$(form),data=$form.serialize(),datatype=(response=="json"?"json":"html");$form.trigger("shopp_cart_ajax_request",data);$.ajax({type:"POST",url:url,data:data+"&response="+response,timeout:10000,dataType:datatype,success:function(cart){$form.trigger("shopp_cart_ajax_success",cart,response);ShoppCartAjaxHandler(cart,response);$form.trigger("shopp_cart_ajax_successful",cart,response)},error:function(){}})}function ShoppCartAjaxHandler(cart,response){var $=jQuery,label="",Item=false,Totals=false,widget=$(".widget_shoppcartwidget div.widget-all"),wrapper=$("#shopp-cart-ajax"),ui=widget.length>0?widget:wrapper,actions=ui.find("ul"),status=ui.find("p.status"),added=ui.find("div.added").empty().hide(),item=$('<div class="added"></div>');if(response=="html"){$(wrapper).trigger("shopp_cart_ajax_html",ui,cart);return ui.html(cart)}if(cart.Item){Item=cart.Item}if(cart.Totals){Totals=cart.Totals}if(added.length==1){item=added}else{item.prependTo(ui).hide()}if(Item.option&&Item.option.label&&Item.option.label!=""){label=" ("+Item.option.label+")"}if(Item.image){$('<p><img src="'+cart.imguri+cart.Item.image.id+'" alt="" width="96"  height="96" /></p>').appendTo(item)}$("<p />").html("<strong>"+Item.name+"</strong>"+label).appendTo(item);$("<p />").html(asMoney(new Number(Item.unitprice))).appendTo(item);status.html('<a href="'+cart.url+'"><span id="shopp-sidecart-items">'+Totals.quantity+"</span> <strong>"+$ct.items+"</strong> &mdash; <strong>"+$ct.total+'</strong> <span id="shopp-sidecart-total">'+asMoney(new Number(Totals.total))+"</span></a>");if(actions.size()!=1){actions=$("<ul />").appendTo(ui)}actions.html('<li><a href="'+cart.url+'">'+cart.label+'</a></li><li><a href="'+cart.checkouturl+'">'+cart.checkoutLabel+"</a></li>");$(wrapper).trigger("shopp_cart_ajax_item",item,cart);item.slideDown()}jQuery(document).ready(function($){$("#cart #shipping-country").change(function(){this.form.submit()});$("input[type=image]").click(function(){$(this.form).submit()});$("input.addtocart").each(function(){var button=$(this),form=button.closest("form");if(!form){return false}form.unbind("submit.validate").bind("submit.addtocart",function(e){e.preventDefault();if(form.hasClass("validate")){if(!validate(this)){return false}}addtocart(this)});if(button.attr("type")=="button"){button.click(function(){form.submit()})}})});
     6;function addtocart(form){var $=jQuery,options=$(form).find("select.options"),selections=true;if(options){options.each(function(i,menu){if($(menu).val()==""){return(selections=false)}});if(!selections){if(!$s.opreq){$s.opreq="You must select the options for this item before you can add it to your shopping cart."}alert($s.opreq);return false}}if($(form).find("input.addtocart").hasClass("ajax-html")){ShoppCartAjaxRequest(form,"html")}else{if($(form).find("input.addtocart").hasClass("ajax")){ShoppCartAjaxRequest(form)}else{form.submit()}}return false}function ShoppCartAjaxRequest(form,response){if(!response){response="json"}var $=jQuery,url=form.action,$form=$(form),data=$form.serialize(),datatype=(response=="json"?"json":"html");$form.trigger("shopp_cart_ajax_request",data);$.ajax({type:"POST",url:url,data:data+"&response="+response,timeout:10000,dataType:datatype,success:function(cart){$form.trigger("shopp_cart_ajax_success",cart,response);ShoppCartAjaxHandler(cart,response);$form.trigger("shopp_cart_ajax_successful",cart,response)},error:function(){}})}function ShoppCartAjaxHandler(cart,response){var $=jQuery,label="",Item=false,Totals=false,widget=$(".widget_shoppcartwidget div.widget-all"),wrapper=$("#shopp-cart-ajax"),ui=widget.length>0?widget:wrapper,actions=ui.find("ul"),status=ui.find("p.status"),added=ui.find("div.added").empty().hide(),item=$('<div class="added"></div>');if(response=="html"){$(wrapper).trigger("shopp_cart_ajax_html",ui,cart);return ui.html(cart)}if(cart.Item){Item=cart.Item}if(cart.Totals){Totals=cart.Totals}if(added.length==1){item=added}else{item.prependTo(ui).hide()}if(Item.option&&Item.option.label&&Item.option.label!=""){label=" ("+Item.option.label+")"}if(Item.image){$('<p><img src="'+cart.imguri+cart.Item.image.id+'" alt="" width="96"  height="96" /></p>').appendTo(item)}$("<p />").html("<strong>"+Item.name+"</strong>"+label).appendTo(item);$("<p />").html(asMoney(new Number(Item.unitprice))).appendTo(item);status.html('<a href="'+cart.url+'"><span id="shopp-sidecart-items">'+Totals.quantity+"</span> <strong>"+$ct.items+"</strong> &mdash; <strong>"+$ct.total+'</strong> <span id="shopp-sidecart-total">'+asMoney(new Number(Totals.total))+"</span></a>");if(actions.size()!=1){actions=$("<ul />").appendTo(ui)}actions.html('<li><a href="'+cart.url+'">'+cart.label+'</a></li><li><a href="'+cart.checkouturl+'">'+cart.checkoutLabel+"</a></li>");$(wrapper).trigger("shopp_cart_ajax_item",item,cart);item.slideDown()}jQuery(document).ready(function($){$("#cart #shipping-country").change(function(){this.form.submit()});$("#cart input[type=image]").click(function(){$(this.form).submit()});$("input.addtocart").each(function(){var button=$(this),form=button.closest("form");if(!form){return false}form.unbind("submit.validate").bind("submit.addtocart",function(e){e.preventDefault();if(form.hasClass("validate")){if(!validate(this)){return false}}addtocart(this)});if(button.attr("type")=="button"){button.click(function(){form.submit()})}})});
  • shopp/trunk/core/ui/behaviors/editors.js

    r1020997 r1122729  
    714714    swfu,
    715715    settings = {
    716         button_text: '<span class="button">'+ADD_IMAGE_BUTTON_TEXT+'</span>',
    717         button_text_style: '.button { text-align: center; font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana,sans-serif; font-size: 9px; color: #333333; }',
     716        button_text: ADD_IMAGE_BUTTON_TEXT,
     717        button_text_style: '.buttonText{text-align:center;font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana,_sans;font-size:9px;color:#333333;}',
    718718        button_text_top_padding: 3,
    719719        button_height: "22",
     
    722722        button_placeholder_id: "swf-uploader-button",
    723723        upload_url : ajaxurl,
    724         flash_url : uidir+'/behaviors/swfupload/swfupload.swf',
     724        flash_url : uidir+'/behaviors/swfupload.swf',
    725725        file_queue_limit : 0,
    726726        file_size_limit : filesizeLimit+'b',
  • shopp/trunk/core/ui/behaviors/editors.min.js

    r1020997 r1122729  
    44 * Licensed under the GPLv3 {@see license.txt}
    55 */
    6 ;function NestedMenu(i,target,dataname,defaultlabel,data,items,sortoptions){var $=jQuery,_=this;if(!sortoptions){sortoptions={axis:"y"}}_.items=items;_.dataname=dataname;_.index=i;_.element=$('<li><div class="move"></div><input type="hidden" name="'+dataname.replace("[","-").replace("]","-")+'-sortorder[]" value="'+i+'" class="sortorder" /><input type="hidden" name="'+dataname+"["+i+'][id]" class="id" /><input type="text" name="'+dataname+"["+i+'][name]" class="label" /><button type="button" class="delete"><span class="shoppui-minus"></span></button></li>').appendTo($(target).children("ul"));_.moveHandle=_.element.find("div.move");_.sortorder=_.element.find("input.sortorder");_.id=_.element.find("input.id");_.label=_.element.find("input.label");_.deleteButton=_.element.find("button.delete").bind("delete",function(){var deletes=$(target).find("input.deletes");if($(_.id).val()!=""){deletes.val((deletes.val()=="")?$(_.id).val():deletes.val()+","+$(_.id).val())}if(items){_.itemsElement.remove()}_.element.remove()}).click(function(){$(this).trigger("delete")});if(_.items){if(items.type=="list"){_.itemsElement=$("<ul></ul>").appendTo(items.target).hide()}else{_.itemsElement=$("<li></li>").appendTo(items.target).hide()}}_.selected=function(){$(target).find("ul li").removeClass("selected");$(_.element).addClass("selected");if(items){$(items.target).children().hide();$(_.itemsElement).show()}};_.element.click(this.selected).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")});_.label.mouseup(function(e){this.select()}).focus(function(){$(this).keydown(function(e){e.stopPropagation();if(e.keyCode==13){$(this).blur().unbind("keydown")}})});_.id.val(_.index);if(data&&data.id){_.id.val(data.id)}if(data&&data.name){_.label.val(htmlentities(data.name))}else{_.label.val(defaultlabel+" "+_.index)}if(!$(target).children("ul").hasClass("ui-sortable")){$(target).children("ul").sortable(sortoptions)}else{$(target).children("ul").sortable("refresh")}}function NestedMenuContent(i,target,dataname,data){var $=jQuery;this.contents=$('<textarea name="'+dataname+"["+i+'][value]" cols="40" rows="7"></textarea>').appendTo(target);if(data&&data.value){this.contents.val(htmlentities(data.value))}}function NestedMenuOption(i,target,dataname,defaultlabel,data){var $=jQuery,_=this;_.index=$(target).contents().length;_.element=$('<li class="option"><div class="move"></div><input type="hidden" name="'+dataname+"["+i+"][options]["+this.index+'][id]" class="id" /><input type="text" name="'+dataname+"["+i+"][options]["+this.index+'][name]" class="label" /><button type="button" class="delete"><span class="shoppui-minus"></span></button></li>').appendTo(target);_.moveHandle=_.element.find("div.move");_.id=_.element.find("input.id");_.label=_.element.find("input.label");_.deleteButton=_.element.find("button.delete").click(function(){$(_.element).remove()});_.element.hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")});_.label.click(function(){this.select()}).focus(function(){$(this).keydown(function(e){e.stopPropagation();if(e.keyCode==13){$(this).blur().unbind("keydown")}})});_.id.val(_.index);if(data.id){_.id.val(data.id)}if(data.name){_.label.val(htmlentities(data.name))}if(!data.name){_.label.val(defaultlabel+" "+(_.index+1))}}function loadVariations(options,prices){if(!options){return}var $=jQuery;$.each(options,function(key,option){if(option&&option.id){addVariationOptionsMenu(option)}});$.each(prices,function(k,p){if(p.context=="variation"){Pricelines.add(p.options.split(","),p,"#variations-pricing")}});Pricelines.updateVariationsUI();$.each(options,function(key,option){if(!(option&&option.options)){return}$.each(option.options,function(i,data){if(data&&data.id&&data.linked=="on"){Pricelines.linkVariations(data.id)}})})}function addVariationOptionsMenu(data){var $=jQuery,menus=$("#variations-menu"),entries=$("#variations-list"),addMenuButton=$("#addVariationMenu"),addOptionButton=$("#addVariationOption"),linkOptionVariations=$("#linkOptionVariations"),id=variationsidx,menu=new NestedMenu(id,menus,"meta[options][v]",OPTION_MENU_DEFAULT,data,{target:entries,type:"list"},{axis:"y",update:function(){orderOptions(menus,entries)}});menu.addOption=function(data){var init=false,option,optionid;if(!data){data=new Object()}if(!data.id){init=true;data.id=optionsidx}else{if(data.id>optionsidx){optionsidx=data.id}}option=new NestedMenuOption(menu.index,menu.itemsElement,"meta[options][v]",NEW_OPTION_DEFAULT,data);optionsidx++;optionid=option.id.val();option.linkIcon=$('<span class="shoppui-link"></span>').appendTo(option.moveHandle);option.linked=$('<input type="hidden" name="meta[options][v]['+menu.index+"][options]["+option.index+'][linked]" class="linked" />').val(data.linked?data.linked:"off").appendTo(option.element).change(function(){if($(this).val()=="on"){option.linkIcon.removeClass("hidden")}else{option.linkIcon.addClass("hidden")}}).change();option.selected=function(){if(option.element.hasClass("selected")){entries.find("ul li").removeClass("selected");selectedMenuOption=false}else{entries.find("ul li").removeClass("selected");$(option.element).addClass("selected");selectedMenuOption=option}linkOptionVariations.change()};option.element.click(option.selected);productOptions[optionid]=option.label;option.label.blur(function(){updateVariationLabels()});option.deleteButton.unbind("click");option.deleteButton.click(function(){if(menu.itemsElement.children().length==1){deleteVariationPrices([optionid],true)}else{deleteVariationPrices([optionid])}option.element.remove()});if(!init){addVariationPrices(optionid)}else{addVariationPrices()}entries.dequeue().animate({scrollTop:entries.prop("scrollHeight")-entries.height()},200);option.label.click().focus().select().keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();option.label.blur();addOptionButton.focus()});menu.items.push(option)};menu.items=new Array();if(data&&data.options){$.each(data.options,function(){menu.addOption(this)})}else{menu.addOption();menu.addOption()}menu.itemsElement.sortable({axis:"y",update:function(){orderVariationPrices()}});menu.element.unbind("click",menu.click).click(function(){menu.selected();$(addOptionButton).unbind("click").click(menu.addOption)});optionMenus[variationsidx++]=menu;menu.deleteButton.unbind("click").click(function(){var deletedOptions=new Array();$(menu.itemsElement).find("li").not(".ui-sortable-helper").find("input.id").each(function(i,id){deletedOptions.push($(id).val())});deleteVariationPrices(deletedOptions,true);$(this).trigger("delete")});if(!data){entries.dequeue().animate({scrollTop:entries.attr("scrollHeight")-entries.height()},200);menu.label.click().focus().select().keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();addOptionButton.focus()})}}function buildVariations(){var $=jQuery,i,setid,fields,index,combos=new Array(),optionSets=$("#variations-list ul"),totalSets=optionSets.length,lastOptionSet=totalSets-1,address=new Array(optionSets.length),totalOptions=new Array(optionSets.length),totalVariations=0;optionSets.each(function(id,set){totalOptions[id]=$(set).children().length;if(totalVariations==0){totalVariations=$(set).children().length}else{totalVariations=totalVariations*$(set).children().length}address[id]=0});for(i=0;i<totalVariations;i++){for(setid=0;setid<optionSets.length;setid++){fields=$(optionSets[setid]).children("li").not(".ui-sortable-helper").children("input.id");if(!combos[i]){combos[i]=[$(fields[address[setid]]).val()]}else{combos[i].push($(fields[address[setid]]).val())}}if(++address[lastOptionSet]>=totalOptions[lastOptionSet]){for(index=lastOptionSet;index>-1;index--){if(address[index]<totalOptions[index]){continue}address[index]=0;if(index-1>-1){address[(index-1)]++}}}}return combos}function addVariationPrices(data){if(data){return}var $=jQuery,key,preKey,updated=buildVariations(),variationPricing=$("#variations-pricing"),variationPricelines=$(variationPricing).children(),added=false;$(updated).each(function(id,options){key=xorkey(options);preKey=xorkey(options.slice(0,options.length-1));if(preKey==""){preKey=-1}if(!Pricelines.row[key]){if(Pricelines.row[preKey]){Pricelines.row[key]=Pricelines.row[preKey];delete Pricelines.row[preKey];Pricelines.row[key].setOptions(options)}else{if(variationPricelines.length==0){Pricelines.add(options,{context:"variation"},"#variations-pricing")}else{Pricelines.add(options,{context:"variation"},Pricelines.row[xorkey(updated[(id-1)])].row,"after")}added=true}}});if(added){Pricelines.updateVariationsUI()}}function deleteVariationPrices(optionids,reduce){var $=jQuery,updated=buildVariations(),reduced=false,i,key,modOptions,newkey,dbPriceId;$(updated).each(function(id,options){key=xorkey(options);for(i=0;i<optionids.length;i++){if(options.indexOf(optionids[i])!=-1){modOptions=new Array();$(options).each(function(index,option){if(option!=optionids[i]){modOptions.push(option)}});newkey=xorkey(modOptions);if(reduce&&!Pricelines.row[newkey]){if(newkey!=0){Pricelines.row[newkey]=Pricelines.row[key]}else{Pricelines.row[key].row.remove()}delete Pricelines.row[key];if(Pricelines.row[newkey]){Pricelines.row[newkey].setOptions(modOptions);reduced=true}}else{if(Pricelines.row[key]){dbPriceId=$("#priceid-"+Pricelines.row[key].id).val();if($("#deletePrices").val()==""){$("#deletePrices").val(dbPriceId)}else{$("#deletePrices").val($("#deletePrices").val()+","+dbPriceId)}Pricelines.remove(key)}}}}});if(reduced){Pricelines.updateVariationsUI()}}function optionMenuExists(label){if(!label){return false}var $=jQuery,found=false;$.each(optionMenus,function(id,menu){if(menu&&$(menu.label).val()==label){return(found=id)}});if(optionMenus[found]){return optionMenus[found]}return found}function optionMenuItemExists(menu,label){if(!menu||!menu.items||!label){return false}var $=jQuery,found=false;$.each(menu.items,function(id,item){if(item&&$(item.label).val()==label){return(found=true)}});return found}function updateVariationLabels(){var $=jQuery,updated=buildVariations();$(updated).each(function(id,options){var key=xorkey(options);if(Pricelines.row[key]){Pricelines.row[key].updateLabel()}})}function orderOptions(menus,options){var $=jQuery;$(menus).find("ul li").not(".ui-sortable-helper").find("input.id").each(function(i,menuid){if(menuid){$(optionMenus[$(menuid).val()].itemsElement).appendTo(options)}});orderVariationPrices()}function orderVariationPrices(){var $=jQuery,key,updated=buildVariations();$(updated).each(function(id,options){key=xorkey(options);if(key>0&&Pricelines.row[key]){Pricelines.reorderVariation(key,options)}});Pricelines.updateVariationsUI("tabs")}function xorkey(ids){if(!(ids instanceof Array)){ids=[ids]}for(var key=0,i=0;i<ids.length;i++){key=key^(ids[i]*7001)}return key}function variationsToggle(){var $=jQuery,toggle=$(this),ui=$("#variations"),baseprice=$("#product-pricing");if(toggle.prop("checked")){if(Pricelines.row[0]){Pricelines.row[0].disable()}baseprice.hide();ui.show()}else{ui.hide();baseprice.show();if(Pricelines.row[0]){Pricelines.row[0].enable()}}}function addonsToggle(){var $=jQuery,toggle=$(this),ui=$("#addons");if(toggle.prop("checked")){ui.show()}else{ui.hide()}}function clearLinkedIcons(){jQuery("#variations-list input.linked").val("off").change()}function linkVariationsButton(){var $=jQuery;if(selectedMenuOption){if(selectedMenuOption.linked.val()=="off"){if(Pricelines.allLinked()){clearLinkedIcons();Pricelines.unlinkAll()}selectedMenuOption.linked.val("on").change();Pricelines.linkVariations(selectedMenuOption.id.val())}else{selectedMenuOption.linked.val("off").change();Pricelines.unlinkVariations(selectedMenuOption.id.val())}}else{clearLinkedIcons();if(Pricelines.allLinked()){Pricelines.unlinkAll()}else{Pricelines.linkAll()}}$(this).change()}function linkVariationsButtonLabel(){var $=jQuery;if(selectedMenuOption){if(selectedMenuOption.linked.val()=="on"){$(this).find("small").html(" "+UNLINK_VARIATIONS)}else{$(this).find("small").html(" "+LINK_VARIATIONS)}}else{if(Pricelines.allLinked()){$(this).find("small").html(" "+UNLINK_ALL_VARIATIONS)}else{$(this).find("small").html(" "+LINK_ALL_VARIATIONS)}}}function loadAddons(addons,prices){var $=jQuery;if(!addons){return}$.each(addons,function(key,addon){newAddonGroup(addon)});$.each(prices,function(key,price){if(price.context=="addon"){var group=addonOptionsGroup[price.options];Pricelines.add(price.options,this,"#addon-pricegroup-"+group)}});Pricelines.updateVariationsUI()}function newAddonGroup(data){var $=jQuery,menus=$("#addon-menu"),entries=$("#addon-list"),addMenuButton=$("#newAddonGroup"),addOptionButton=$("#addAddonOption"),id=addon_group_idx,menu=new NestedMenu(id,menus,"meta[options][a]",ADDON_GROUP_DEFAULT,data,{target:entries,type:"list"},{axis:"y",update:function(){orderAddonGroups()}});menu.itemsElement.attr("id","addon-group-"+id);menu.pricegroup=$('<div id="addon-pricegroup-'+id+'" />').appendTo("#addon-pricing");menu.pricegroupLabel=$("<label />").html("<h4>"+menu.label.val()+"</h4>").prependTo(menu.pricegroup);menu.updatePriceLabel=function(){menu.pricegroupLabel.html("<h4>"+menu.label.val()+"</h4>")};menu.label.blur(menu.updatePriceLabel);menu.addOption=function(data){var init=false,option,optionid;if(!data){data=new Object()}if(!data.id){init=true;data.id=addonsidx}else{if(data.id>addonsidx){addonsidx=data.id}}option=new NestedMenuOption(menu.index,menu.itemsElement,"meta[options][a]",NEW_OPTION_DEFAULT,data);addonsidx++;optionid=option.id.val();option.selected=function(){if(option.element.hasClass("selected")){entries.find("ul li").removeClass("selected");selectedMenuOption=false}else{entries.find("ul li").removeClass("selected");$(option.element).addClass("selected");selectedMenuOption=option}};option.element.click(option.selected);productAddons[optionid]=option.label;option.label.blur(function(){Pricelines.row[optionid].updateLabel()});option.deleteButton.unbind("click");option.deleteButton.click(function(){var dbPriceid=Pricelines.row[optionid].data.id,dP=$("#deletePrices");if(dbPriceid){if(dP.val()==""){dP.val(dbPriceid)}else{dP.val(dP.val()+","+dbPriceid)}}Pricelines.row[optionid].row.remove();option.element.remove()});if(init){Pricelines.add(optionid,{context:"addon"},menu.pricegroup)}addonOptionsGroup[optionid]=menu.index;menu.items.push(option);entries.dequeue().animate({scrollTop:entries.attr("scrollHeight")-entries.height()},200);option.label.click().focus().select().keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();option.label.blur();addOptionButton.focus()})};menu.items=new Array();if(data&&data.options){$.each(data.options,function(){menu.addOption(this)})}else{menu.addOption();menu.addOption()}menu.itemsElement.sortable({axis:"y",update:function(){orderAddonPrices(menu.index)}});menu.element.unbind("click",menu.click);menu.element.click(function(){menu.selected();$(addOptionButton).unbind("click").click(menu.addOption)});addonGroups[addon_group_idx++]=menu;menu.deleteButton.unbind("click").click(function(){$("#addon-list #addon-group-"+menu.index+" li").not(".ui-sortable-helper").find("input.id").each(function(id,option){var optionid=$(option).val(),dbPriceid,dP=$("#deletePrices");if(Pricelines.row[optionid]){dbPriceid=Pricelines.row[optionid].data.id;if(dbPriceid){if(dP.val()==""){dP.val(dbPriceid)}else{dP.val(dP.val()+","+dbPriceid)}}Pricelines.row[optionid].row.remove()}});menu.deleteButton.trigger("delete");menu.pricegroup.remove();menu.element.remove()});if(!data){menus.dequeue().animate({scrollTop:menus.attr("scrollHeight")-menus.height()},200);menu.label.click().focus().select().keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();menu.label.blur();addMenuButton.focus()})}}function orderAddonGroups(){var $=jQuery,menu;$("#addon-menu ul li").not(".ui-sortable-helper").find("input.id").each(function(i,menuid){menu=addonGroups[$(menuid).val()];menu.pricegroup.appendTo("#addon-pricing")})}function orderAddonPrices(index){var $=jQuery,menu=addonGroups[index];$("#addon-list #addon-group-"+menu.index+" li").not(".ui-sortable-helper").find("input.id").each(function(id,option){Pricelines.reorderAddon($(option).val(),menu.pricegroup)})}function readableFileSize(size){var units=new Array("bytes","KB","MB","GB"),sized=size*1,unit=0;if(sized==0){return sized}while(sized>1000){sized=sized/1024;unit++}return sized.toFixed(2)+" "+units[unit]}function addDetail(data){var $=jQuery,i,optionsmenu,menus=$("#details-menu"),entries=$("#details-list"),id=detailsidx++,menu=new NestedMenu(id,menus,"details","Detail Name",data,{target:entries});if(data&&data.options){optionsmenu=$('<select name="details['+menu.index+'][value]"></select>').appendTo(menu.itemsElement);$("<option></option>").appendTo(optionsmenu);for(i in data.options){$("<option>"+data.options[i]["name"]+"</option>").appendTo(optionsmenu)}if(data&&data.value){optionsmenu.val(htmlentities(data.value))}}else{menu.item=new NestedMenuContent(menu.index,menu.itemsElement,"details",data)}if(!data||data.add){menu.add=$('<input type="hidden" name="details['+menu.index+'][new]" value="true" />').appendTo(menu.element);menus.dequeue().animate({scrollTop:menus.attr("scrollHeight")-menus.height()},200);menu.label.click().focus().select();if(menu.item){menu.item.contents.keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();$("#addDetail").focus()})}}}function ImageUploads(id,type){var $=jQuery,swfu,settings={button_text:'<span class="button">'+ADD_IMAGE_BUTTON_TEXT+"</span>",button_text_style:'.button { text-align: center; font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana,sans-serif; font-size: 9px; color: #333333; }',button_text_top_padding:3,button_height:"22",button_width:"100",button_image_url:uidir+"/icons/buttons.png",button_placeholder_id:"swf-uploader-button",upload_url:ajaxurl,flash_url:uidir+"/behaviors/swfupload/swfupload.swf",file_queue_limit:0,file_size_limit:filesizeLimit+"b",file_types:"*.jpg;*.jpeg;*.png;*.gif",file_types_description:"Web-compatible Image Files",file_upload_limit:filesizeLimit,post_params:{action:"shopp_upload_image",parent:id,type:type},swfupload_loaded_handler:swfuLoaded,file_queue_error_handler:imageFileQueueError,file_dialog_complete_handler:imageFileDialogComplete,upload_start_handler:startImageUpload,upload_progress_handler:imageUploadProgress,upload_error_handler:imageUploadError,upload_success_handler:imageUploadSuccess,custom_settings:{loaded:false,targetHolder:false,progressBar:false,sorting:false},prevent_swf_caching:$.ua.msie,debug:imageupload_debug};if(flashuploader){swfu=new SWFUpload(settings)}$("#image-upload").upload({name:"Filedata",action:ajaxurl,params:{action:"shopp_upload_image",type:type},onSubmit:function(){this.targetHolder=$('<li id="image-uploading"><input type="hidden" name="images[]" value="" /><div class="progress"><div class="bar"></div><div class="gloss"></div></div></li>').appendTo("#lightbox");this.progressBar=this.targetHolder.find("div.bar");this.sorting=this.targetHolder.find("input")},onComplete:function(results){var image=false,img,deleteButton,targetHolder=this.targetHolder;try{image=$.parseJSON(results)}catch(ex){image.error=results}if(!image||!image.id){targetHolder.remove();if(image.error){alert(image.error)}else{alert(UNKNOWN_UPLOAD_ERROR)}return false}targetHolder.attr({id:"image-"+image.id});this.sorting.val(image.id);img=$('<img src="?siid='+image.id+'" width="96" height="96" class="handle" />').appendTo(targetHolder).hide();deleteButton=$('<button type="button" name="deleteImage" value="'+image.src+'" class="delete"><span class="shoppui-minus"></span></button>').appendTo($(targetHolder)).hide();$(this.progressBar).animate({width:"76px"},250,function(){$(this).parent().fadeOut(500,function(){$(this).remove();$(img).fadeIn("500");enableDeleteButton(deleteButton)})})}});$(document).load(function(){if(!swfu.loaded){$("#product-images .swfupload").remove()}});sorting();$("#lightbox li").each(function(){$(this).dblclick(function(){var id=$(this).attr("id")+"-details",src=$("#"+id),srcid=src.find("input[type=hidden]").val(),srcthumb=src.find("img"),srctitle=src.find("input.imagetitle"),srcalt=src.find("input.imagealt"),srcCropped=src.find("input.imagecropped"),ui=$('<div class="image-details-editor"><div class="details-editor"><img class="thumb" width="96" height="96" /><div class="details"><p><label>'+IMAGE_DETAILS_TITLE_LABEL+': </label><input type="text" name="title" /></p><p><label>'+IMAGE_DETAILS_ALT_LABEL+': </label><input type="text" name="alt" /></p></div></div><div class="cropping"><p class="clear">'+IMAGE_DETAILS_CROP_LABEL+': <select name="cropimage"><option></option></select></p><div class="cropui"></div><br class="clear"/></div><input type="button" class="button-primary alignright" value="&nbsp;&nbsp;'+IMAGE_DETAILS_DONE+'&nbsp;&nbsp;" /></div>'),thumb=ui.find("img").attr("src",srcthumb.attr("src")),titlefield=ui.find("input[name=title]").val(srctitle.val()).change(function(){srctitle.val(titlefield.val())}),altfield=ui.find("input[name=alt]").val(srcalt.val()).change(function(){srcalt.val(altfield.val())}),doneButton=ui.find("input[type=button]").click(function(){$.colorbox.close()}),cropping=ui.find("div.cropping").hide(),croptool=ui.find("div.cropui"),cropselect=ui.find("select[name=cropimage]").change(function(){if(cropselect.val()==""){croptool.empty();$.colorbox.resize();return}var d=cropselect.val().split(":"),init=srcCropped.filter("input[alt="+cropselect.val()+"]").val().split(",");croptool.empty().scaleCrop({imgsrc:"?siid="+srcid,target:{width:parseInt(d[0],10),height:parseInt(d[1],10)},init:{x:parseInt(init[0],10),y:parseInt(init[1],10),s:new Number(init[2])}}).ready(function(){var padding=125;$.colorbox.resize({innerWidth:(parseInt(d[0],10))+padding})}).bind("change.scalecrop",function(e,c){if(!c.s){c.s=1}if(c){srcCropped.filter("input[alt="+cropselect.val()+"]").val(c.x+","+c.y+","+c.s)}})});if(srcCropped.size()>0){srcCropped.each(function(i,e){var d=$(e).attr("alt");$('<option value="'+d+'">'+(i+1)+": "+d.replace(":","&times;")+"</option>").appendTo(cropselect)});cropping.show()}$.colorbox({title:IMAGE_DETAILS_TEXT,html:ui})});enableDeleteButton($(this).find("button.delete"))});function swfuLoaded(){$("#browser-uploader").hide();swfu.loaded=true}function sorting(){if($("#lightbox li").size()>0){$("#lightbox").sortable({opacity:0.8})}}function imageFileQueueError(file,error,message){if(error==SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED){alert("You selected too many files to upload at one time. "+(message===0?"You have reached the upload limit.":"You may upload "+(message>1?"up to "+message+" files.":"only one file.")));return}else{alert(message)}}function imageFileDialogComplete(selected,queued){try{this.startUpload()}catch(ex){this.debug(ex)}}function startImageUpload(file){this.targetHolder=$('<li class="image uploading"><input type="hidden" name="images[]" /><div class="progress"><div class="bar"></div><div class="gloss"></div></div></li>').appendTo($("#lightbox"));this.progressBar=this.targetHolder.find("div.bar");this.sorting=this.targetHolder.find("input")}function imageUploadProgress(file,loaded,total){this.progressBar.animate({width:Math.ceil((loaded/total)*76)+"px"},100)}function imageUploadError(file,error,message){}function imageUploadSuccess(file,results){var image=false,img,deleteButton,targetHolder=this.targetHolder;try{image=$.parseJSON(results)}catch(ex){targetHolder.remove();alert(results);return false}if(!image.id){targetHolder.remove();if(image.error){alert(image.error)}else{alert(UNKNOWN_UPLOAD_ERROR)}return true}targetHolder.attr({id:"image-"+image.id});this.sorting.val(image.id);img=$('<img src="?siid='+image.id+'" width="96" height="96" class="handle" />').appendTo(targetHolder).hide();deleteButton=$('<button type="button" name="deleteImage" value="'+image.id+'" class="delete"><span class="shoppui-minus"></span></button>').appendTo(targetHolder).hide();sorting();this.progressBar.animate({width:"76px"},250,function(){$(this).parent().fadeOut(500,function(){$(this).remove();$(img).fadeIn("500");enableDeleteButton(deleteButton)})})}function enableDeleteButton(button){button.hide();button.parent().hover(function(){button.show()},function(){button.hide()});button.click(function(){if(confirm(DELETE_IMAGE_WARNING)){var imgid=(button.val().substr(0,1)=="<")?button.find("input[name=ieisstupid]").val():button.val(),deleteImages=$("#deleteImages"),deleting=deleteImages.val();deleteImages.val(deleting==""?imgid:deleting+","+imgid);$("#confirm-delete-images").show();button.parent().fadeOut(500,function(){$(this).remove()})}})}}jQuery.fn.FileChooser=function(line,status){var $=jQuery,_=this,chooser=$("#chooser"),importurl=chooser.find(".fileimport"),importstatus=chooser.find(".status"),attach=$("#attach-file"),dlpath=$("#download_path-"+line),dlname=$("#download_file-"+line),file=$("#file-"+line),stored=false,nostatus=0,progressbar=false;_.line=line;_.status=status;chooser.unbind("change").on("change",".fileimport",function(e){importstatus.attr("class","status").addClass("shoppui-spinner shoppui-spinfx shoppui-spinfx-steps8");$.ajax({url:fileverify_url+"&action=shopp_verify_file&t=download",type:"POST",data:"url="+importurl.val(),timeout:10000,dataType:"text",success:function(results){importstatus.attr("class","status");if(results=="OK"){return importstatus.addClass("shoppui-ok-sign")}if(results=="NULL"){importstatus.attr("title",FILE_NOT_FOUND_TEXT)}if(results=="ISDIR"){importstatus.attr("title",FILE_ISDIR_TEXT)}if(results=="READ"){importstatus.attr("title",FILE_NOT_READ_TEXT)}importstatus.addClass("shoppui-warning-sign")}})});importurl.unbind("keydown").unbind("keypress").suggest(sugg_url+"&action=shopp_storage_suggestions&t=download",{delay:500,minchars:3,multiple:false,onSelect:function(){importurl.trigger("change")}});$(this).click(function(){fileUploads.updateLine(line,status);importstatus.attr("class","status");attach.unbind("click").click(function(){$.colorbox.hide();if(stored){dlpath.val(importurl.val());importurl.val("").attr("class","fileimport");return true}var importid=false,importdata=false,importfile=importurl.val(),completed=function(f){if(!f.name){return $this.attr("class","")}file.attr("class","file").html('<span class="icon shoppui-file '+f.mime.replace("/"," ")+'"></span>'+f.name+"<br /><small>"+readableFileSize(f.size)+"</small>");dlpath.val(f.path);dlname.val(f.name);importurl.val("").attr("class","fileimport")},importing=function(){var ui=file.find("div.progress"),progressbar=ui.find("div.bar"),scale=ui.outerWidth(),dataframe=$("#import-file-"+line).get(0).contentWindow,p=dataframe.importProgress,f=dataframe.importFile;if(f!==undefined){if(f.error){return file.attr("class","error").html("<small>"+f.error+"</small>")}if(!f.path){return file.attr("class","error").html("<small>"+FILE_UNKNOWN_IMPORT_ERROR+"</small>")}if(f.stored){return completed(f)}else{savepath=f.path.split("/");importid=savepath[savepath.length-1]}}if(!p){p=0}if(p===0&&nostatus++>60){return file.attr("class","error").html("<small>"+FILE_UNKNOWN_IMPORT_ERROR+"</small>")}progressbar.animate({width:Math.ceil(p*scale)+"px"},100);if(p==1){if(progressbar){progressbar.css({width:"100%"}).fadeOut(500,function(){completed(f)})}return}setTimeout(importing,100)};setTimeout(importing,100);file.attr("class","").html('<div class="progress"><div class="bar"></div><div class="gloss"></div></div><iframe id="import-file-'+line+'" width="0" height="0" src="'+fileimport_url+"&action=shopp_import_file&url="+importfile+'"></iframe>')})});$(this).colorbox({title:"File Selector",innerWidth:"360",innerHeight:"140",inline:true,href:chooser})};function FileUploader(button,defaultButton){var $=jQuery,_=this;_.swfu=false;_.settings={button_text:'<span class="button">'+UPLOAD_FILE_BUTTON_TEXT+"</span>",button_text_style:'.button { text-align: center; font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana,sans-serif; font-size: 9px; color: #333333; }',button_text_top_padding:3,button_height:"22",button_width:"100",button_image_url:uidir+"/icons/buttons.png",button_placeholder_id:button,button_action:SWFUpload.BUTTON_ACTION.SELECT_FILE,flash_url:uidir+"/behaviors/swfupload/swfupload.swf",upload_url:ajaxurl,file_queue_limit:1,file_size_limit:filesizeLimit+"b",file_types:"*.*",file_types_description:"All Files",file_upload_limit:filesizeLimit,post_params:{action:"shopp_upload_file"},swfupload_loaded_handler:swfuLoaded,file_queue_error_handler:fileQueueError,file_dialog_complete_handler:fileDialogComplete,upload_start_handler:startUpload,upload_progress_handler:uploadProgress,upload_success_handler:uploadSuccess,custom_settings:{loaded:false,targetCell:false,targetLine:false,progressBar:false},prevent_swf_caching:$.ua.msie,debug:fileupload_debug};if(flashuploader){_.swfu=new SWFUpload(_.settings)}defaultButton.upload({name:"Filedata",action:ajaxurl,params:{action:"shopp_upload_file"},onSubmit:function(){$.colorbox.hide();_.targetCell.attr("class","").html("");$('<div class="progress"><div class="bar"></div><div class="gloss"></div></div>').appendTo(_.targetCell);_.progressBar=_.targetCell.find("div.bar")},onComplete:function(results){$.colorbox.close();var filedata=false,targetHolder=_.targetCell;try{filedata=$.parseJSON(results)}catch(ex){filedata.error=results}if(!filedata.id&&!filedata.name){targetHolder.html(NO_DOWNLOAD);if(filedata.error){alert(filedata.error)}else{alert(UNKNOWN_UPLOAD_ERROR)}return false}filedata.type=filedata.type.replace(/\//gi," ");$(_.progressBar).animate({width:"76px"},250,function(){$(this).parent().fadeOut(500,function(){targetHolder.attr("class","file").html('<div class="icon shoppui-file '+filedata.type+'"></div>'+filedata.name+"<br /><small>"+readableFileSize(filedata.size)+'</small><input type="hidden" name="price['+_.targetLine+'][download]" value="'+filedata.id+'" />');$(this).remove()})})}});$(_).load(function(){if(!_.swfu||!_.swfu.loaded){$(defaultButton).parent().parent().find(".swfupload").remove()}});function swfuLoaded(){$(defaultButton).hide();this.loaded=true}_.updateLine=function(line,status){if(!_.swfu){_.targetLine=line;_.targetCell=status}else{_.swfu.targetLine=line;_.swfu.targetCell=status}};function fileQueueError(file,error,message){if(error==SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED){alert("You selected too many files to upload at one time. "+(message===0?"You have reached the upload limit.":"You may upload "+(message>1?"up to "+message+" files.":"only one file.")));return}else{alert(message)}}function fileDialogComplete(selected,queued){$.colorbox.hide();if(!selected){return}try{this.startUpload()}catch(ex){this.debug(ex)}}function startUpload(file){this.targetCell.attr("class","").html("");$('<div class="progress"><div class="bar"></div><div class="gloss"></div></div>').appendTo(this.targetCell);this.progressBar=this.targetCell.find("div.bar")}function uploadProgress(file,loaded,total){this.progressBar.animate({width:Math.ceil((loaded/total)*76)+"px"},100)}function uploadSuccess(file,results){var filedata=false,targetCell=this.targetCell,i=this.targetLine;$.colorbox.close();try{filedata=$.parseJSON(results)}catch(ex){filedata.error=results}if(!filedata.id&&!filedata.name){targetCell.html(NO_DOWNLOAD);if(filedata.error){alert(filedata.error)}else{alert(UNKNOWN_UPLOAD_ERROR)}return false}filedata.type=filedata.type.replace(/\//gi," ");$(this.progressBar).animate({width:"76px"},250,function(){$(this).parent().fadeOut(500,function(){$(this).remove();$(targetCell).attr("class","file").html('<div class="icon shoppui-file '+filedata.type+'"></div>'+filedata.name+"<br /><small>"+readableFileSize(filedata.size)+'</small><input type="hidden" name="price['+i+'][download]" value="'+filedata.id+'" />')})})}}function SlugEditor(id,type){var $=jQuery,_=this,editbs=$("#edit-slug-buttons"),edit=editbs.find(".edit"),view=editbs.find(".view"),editorbs=$("#editor-slug-buttons"),save=editorbs.find(".save"),cancel=editorbs.find(".cancel"),full=$("#editable-slug-full");_.permalink=function(){var i,c=0,editor=$("#editable-slug"),revert_editor=editor.html(),real_slug=$("#slug_input"),revert_slug=real_slug.html(),slug=full.html();editbs.hide();editorbs.show();save.unbind("click").click(function(){var slug=editor.children("input").val(),title=$("#title").val();$.post(editslug_url+"&action=shopp_edit_slug",{id:id,type:type,slug:slug,title:title},function(data){editor.html(revert_editor);if(data!=-1){editor.html(data);full.html(data);real_slug.val(data)}view.attr("href",canonurl+full.html());editorbs.hide();editbs.show()},"text")});cancel.unbind("click").click(function(){editor.html(revert_editor);editorbs.hide();editbs.show();real_slug.attr("value",revert_slug)});for(i=0;i<slug.length;++i){if("%"==slug.charAt(i)){c++}}slug_value=(c>slug.length/4)?"":slug;editor.html('<input type="text" id="new-post-slug" value="'+slug_value+'" />').children("input").keypress(function(e){var key=e.which;if(key==13||key==27){e.preventDefault()}if(13==key){save.click()}if(27==key){cancel.click()}real_slug.val(this.value)}).focus()};edit.click(_.permalink)};
     6;function NestedMenu(i,target,dataname,defaultlabel,data,items,sortoptions){var $=jQuery,_=this;if(!sortoptions){sortoptions={axis:"y"}}_.items=items;_.dataname=dataname;_.index=i;_.element=$('<li><div class="move"></div><input type="hidden" name="'+dataname.replace("[","-").replace("]","-")+'-sortorder[]" value="'+i+'" class="sortorder" /><input type="hidden" name="'+dataname+"["+i+'][id]" class="id" /><input type="text" name="'+dataname+"["+i+'][name]" class="label" /><button type="button" class="delete"><span class="shoppui-minus"></span></button></li>').appendTo($(target).children("ul"));_.moveHandle=_.element.find("div.move");_.sortorder=_.element.find("input.sortorder");_.id=_.element.find("input.id");_.label=_.element.find("input.label");_.deleteButton=_.element.find("button.delete").bind("delete",function(){var deletes=$(target).find("input.deletes");if($(_.id).val()!=""){deletes.val((deletes.val()=="")?$(_.id).val():deletes.val()+","+$(_.id).val())}if(items){_.itemsElement.remove()}_.element.remove()}).click(function(){$(this).trigger("delete")});if(_.items){if(items.type=="list"){_.itemsElement=$("<ul></ul>").appendTo(items.target).hide()}else{_.itemsElement=$("<li></li>").appendTo(items.target).hide()}}_.selected=function(){$(target).find("ul li").removeClass("selected");$(_.element).addClass("selected");if(items){$(items.target).children().hide();$(_.itemsElement).show()}};_.element.click(this.selected).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")});_.label.mouseup(function(e){this.select()}).focus(function(){$(this).keydown(function(e){e.stopPropagation();if(e.keyCode==13){$(this).blur().unbind("keydown")}})});_.id.val(_.index);if(data&&data.id){_.id.val(data.id)}if(data&&data.name){_.label.val(htmlentities(data.name))}else{_.label.val(defaultlabel+" "+_.index)}if(!$(target).children("ul").hasClass("ui-sortable")){$(target).children("ul").sortable(sortoptions)}else{$(target).children("ul").sortable("refresh")}}function NestedMenuContent(i,target,dataname,data){var $=jQuery;this.contents=$('<textarea name="'+dataname+"["+i+'][value]" cols="40" rows="7"></textarea>').appendTo(target);if(data&&data.value){this.contents.val(htmlentities(data.value))}}function NestedMenuOption(i,target,dataname,defaultlabel,data){var $=jQuery,_=this;_.index=$(target).contents().length;_.element=$('<li class="option"><div class="move"></div><input type="hidden" name="'+dataname+"["+i+"][options]["+this.index+'][id]" class="id" /><input type="text" name="'+dataname+"["+i+"][options]["+this.index+'][name]" class="label" /><button type="button" class="delete"><span class="shoppui-minus"></span></button></li>').appendTo(target);_.moveHandle=_.element.find("div.move");_.id=_.element.find("input.id");_.label=_.element.find("input.label");_.deleteButton=_.element.find("button.delete").click(function(){$(_.element).remove()});_.element.hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")});_.label.click(function(){this.select()}).focus(function(){$(this).keydown(function(e){e.stopPropagation();if(e.keyCode==13){$(this).blur().unbind("keydown")}})});_.id.val(_.index);if(data.id){_.id.val(data.id)}if(data.name){_.label.val(htmlentities(data.name))}if(!data.name){_.label.val(defaultlabel+" "+(_.index+1))}}function loadVariations(options,prices){if(!options){return}var $=jQuery;$.each(options,function(key,option){if(option&&option.id){addVariationOptionsMenu(option)}});$.each(prices,function(k,p){if(p.context=="variation"){Pricelines.add(p.options.split(","),p,"#variations-pricing")}});Pricelines.updateVariationsUI();$.each(options,function(key,option){if(!(option&&option.options)){return}$.each(option.options,function(i,data){if(data&&data.id&&data.linked=="on"){Pricelines.linkVariations(data.id)}})})}function addVariationOptionsMenu(data){var $=jQuery,menus=$("#variations-menu"),entries=$("#variations-list"),addMenuButton=$("#addVariationMenu"),addOptionButton=$("#addVariationOption"),linkOptionVariations=$("#linkOptionVariations"),id=variationsidx,menu=new NestedMenu(id,menus,"meta[options][v]",OPTION_MENU_DEFAULT,data,{target:entries,type:"list"},{axis:"y",update:function(){orderOptions(menus,entries)}});menu.addOption=function(data){var init=false,option,optionid;if(!data){data=new Object()}if(!data.id){init=true;data.id=optionsidx}else{if(data.id>optionsidx){optionsidx=data.id}}option=new NestedMenuOption(menu.index,menu.itemsElement,"meta[options][v]",NEW_OPTION_DEFAULT,data);optionsidx++;optionid=option.id.val();option.linkIcon=$('<span class="shoppui-link"></span>').appendTo(option.moveHandle);option.linked=$('<input type="hidden" name="meta[options][v]['+menu.index+"][options]["+option.index+'][linked]" class="linked" />').val(data.linked?data.linked:"off").appendTo(option.element).change(function(){if($(this).val()=="on"){option.linkIcon.removeClass("hidden")}else{option.linkIcon.addClass("hidden")}}).change();option.selected=function(){if(option.element.hasClass("selected")){entries.find("ul li").removeClass("selected");selectedMenuOption=false}else{entries.find("ul li").removeClass("selected");$(option.element).addClass("selected");selectedMenuOption=option}linkOptionVariations.change()};option.element.click(option.selected);productOptions[optionid]=option.label;option.label.blur(function(){updateVariationLabels()});option.deleteButton.unbind("click");option.deleteButton.click(function(){if(menu.itemsElement.children().length==1){deleteVariationPrices([optionid],true)}else{deleteVariationPrices([optionid])}option.element.remove()});if(!init){addVariationPrices(optionid)}else{addVariationPrices()}entries.dequeue().animate({scrollTop:entries.prop("scrollHeight")-entries.height()},200);option.label.click().focus().select().keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();option.label.blur();addOptionButton.focus()});menu.items.push(option)};menu.items=new Array();if(data&&data.options){$.each(data.options,function(){menu.addOption(this)})}else{menu.addOption();menu.addOption()}menu.itemsElement.sortable({axis:"y",update:function(){orderVariationPrices()}});menu.element.unbind("click",menu.click).click(function(){menu.selected();$(addOptionButton).unbind("click").click(menu.addOption)});optionMenus[variationsidx++]=menu;menu.deleteButton.unbind("click").click(function(){var deletedOptions=new Array();$(menu.itemsElement).find("li").not(".ui-sortable-helper").find("input.id").each(function(i,id){deletedOptions.push($(id).val())});deleteVariationPrices(deletedOptions,true);$(this).trigger("delete")});if(!data){entries.dequeue().animate({scrollTop:entries.attr("scrollHeight")-entries.height()},200);menu.label.click().focus().select().keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();addOptionButton.focus()})}}function buildVariations(){var $=jQuery,i,setid,fields,index,combos=new Array(),optionSets=$("#variations-list ul"),totalSets=optionSets.length,lastOptionSet=totalSets-1,address=new Array(optionSets.length),totalOptions=new Array(optionSets.length),totalVariations=0;optionSets.each(function(id,set){totalOptions[id]=$(set).children().length;if(totalVariations==0){totalVariations=$(set).children().length}else{totalVariations=totalVariations*$(set).children().length}address[id]=0});for(i=0;i<totalVariations;i++){for(setid=0;setid<optionSets.length;setid++){fields=$(optionSets[setid]).children("li").not(".ui-sortable-helper").children("input.id");if(!combos[i]){combos[i]=[$(fields[address[setid]]).val()]}else{combos[i].push($(fields[address[setid]]).val())}}if(++address[lastOptionSet]>=totalOptions[lastOptionSet]){for(index=lastOptionSet;index>-1;index--){if(address[index]<totalOptions[index]){continue}address[index]=0;if(index-1>-1){address[(index-1)]++}}}}return combos}function addVariationPrices(data){if(data){return}var $=jQuery,key,preKey,updated=buildVariations(),variationPricing=$("#variations-pricing"),variationPricelines=$(variationPricing).children(),added=false;$(updated).each(function(id,options){key=xorkey(options);preKey=xorkey(options.slice(0,options.length-1));if(preKey==""){preKey=-1}if(!Pricelines.row[key]){if(Pricelines.row[preKey]){Pricelines.row[key]=Pricelines.row[preKey];delete Pricelines.row[preKey];Pricelines.row[key].setOptions(options)}else{if(variationPricelines.length==0){Pricelines.add(options,{context:"variation"},"#variations-pricing")}else{Pricelines.add(options,{context:"variation"},Pricelines.row[xorkey(updated[(id-1)])].row,"after")}added=true}}});if(added){Pricelines.updateVariationsUI()}}function deleteVariationPrices(optionids,reduce){var $=jQuery,updated=buildVariations(),reduced=false,i,key,modOptions,newkey,dbPriceId;$(updated).each(function(id,options){key=xorkey(options);for(i=0;i<optionids.length;i++){if(options.indexOf(optionids[i])!=-1){modOptions=new Array();$(options).each(function(index,option){if(option!=optionids[i]){modOptions.push(option)}});newkey=xorkey(modOptions);if(reduce&&!Pricelines.row[newkey]){if(newkey!=0){Pricelines.row[newkey]=Pricelines.row[key]}else{Pricelines.row[key].row.remove()}delete Pricelines.row[key];if(Pricelines.row[newkey]){Pricelines.row[newkey].setOptions(modOptions);reduced=true}}else{if(Pricelines.row[key]){dbPriceId=$("#priceid-"+Pricelines.row[key].id).val();if($("#deletePrices").val()==""){$("#deletePrices").val(dbPriceId)}else{$("#deletePrices").val($("#deletePrices").val()+","+dbPriceId)}Pricelines.remove(key)}}}}});if(reduced){Pricelines.updateVariationsUI()}}function optionMenuExists(label){if(!label){return false}var $=jQuery,found=false;$.each(optionMenus,function(id,menu){if(menu&&$(menu.label).val()==label){return(found=id)}});if(optionMenus[found]){return optionMenus[found]}return found}function optionMenuItemExists(menu,label){if(!menu||!menu.items||!label){return false}var $=jQuery,found=false;$.each(menu.items,function(id,item){if(item&&$(item.label).val()==label){return(found=true)}});return found}function updateVariationLabels(){var $=jQuery,updated=buildVariations();$(updated).each(function(id,options){var key=xorkey(options);if(Pricelines.row[key]){Pricelines.row[key].updateLabel()}})}function orderOptions(menus,options){var $=jQuery;$(menus).find("ul li").not(".ui-sortable-helper").find("input.id").each(function(i,menuid){if(menuid){$(optionMenus[$(menuid).val()].itemsElement).appendTo(options)}});orderVariationPrices()}function orderVariationPrices(){var $=jQuery,key,updated=buildVariations();$(updated).each(function(id,options){key=xorkey(options);if(key>0&&Pricelines.row[key]){Pricelines.reorderVariation(key,options)}});Pricelines.updateVariationsUI("tabs")}function xorkey(ids){if(!(ids instanceof Array)){ids=[ids]}for(var key=0,i=0;i<ids.length;i++){key=key^(ids[i]*7001)}return key}function variationsToggle(){var $=jQuery,toggle=$(this),ui=$("#variations"),baseprice=$("#product-pricing");if(toggle.prop("checked")){if(Pricelines.row[0]){Pricelines.row[0].disable()}baseprice.hide();ui.show()}else{ui.hide();baseprice.show();if(Pricelines.row[0]){Pricelines.row[0].enable()}}}function addonsToggle(){var $=jQuery,toggle=$(this),ui=$("#addons");if(toggle.prop("checked")){ui.show()}else{ui.hide()}}function clearLinkedIcons(){jQuery("#variations-list input.linked").val("off").change()}function linkVariationsButton(){var $=jQuery;if(selectedMenuOption){if(selectedMenuOption.linked.val()=="off"){if(Pricelines.allLinked()){clearLinkedIcons();Pricelines.unlinkAll()}selectedMenuOption.linked.val("on").change();Pricelines.linkVariations(selectedMenuOption.id.val())}else{selectedMenuOption.linked.val("off").change();Pricelines.unlinkVariations(selectedMenuOption.id.val())}}else{clearLinkedIcons();if(Pricelines.allLinked()){Pricelines.unlinkAll()}else{Pricelines.linkAll()}}$(this).change()}function linkVariationsButtonLabel(){var $=jQuery;if(selectedMenuOption){if(selectedMenuOption.linked.val()=="on"){$(this).find("small").html(" "+UNLINK_VARIATIONS)}else{$(this).find("small").html(" "+LINK_VARIATIONS)}}else{if(Pricelines.allLinked()){$(this).find("small").html(" "+UNLINK_ALL_VARIATIONS)}else{$(this).find("small").html(" "+LINK_ALL_VARIATIONS)}}}function loadAddons(addons,prices){var $=jQuery;if(!addons){return}$.each(addons,function(key,addon){newAddonGroup(addon)});$.each(prices,function(key,price){if(price.context=="addon"){var group=addonOptionsGroup[price.options];Pricelines.add(price.options,this,"#addon-pricegroup-"+group)}});Pricelines.updateVariationsUI()}function newAddonGroup(data){var $=jQuery,menus=$("#addon-menu"),entries=$("#addon-list"),addMenuButton=$("#newAddonGroup"),addOptionButton=$("#addAddonOption"),id=addon_group_idx,menu=new NestedMenu(id,menus,"meta[options][a]",ADDON_GROUP_DEFAULT,data,{target:entries,type:"list"},{axis:"y",update:function(){orderAddonGroups()}});menu.itemsElement.attr("id","addon-group-"+id);menu.pricegroup=$('<div id="addon-pricegroup-'+id+'" />').appendTo("#addon-pricing");menu.pricegroupLabel=$("<label />").html("<h4>"+menu.label.val()+"</h4>").prependTo(menu.pricegroup);menu.updatePriceLabel=function(){menu.pricegroupLabel.html("<h4>"+menu.label.val()+"</h4>")};menu.label.blur(menu.updatePriceLabel);menu.addOption=function(data){var init=false,option,optionid;if(!data){data=new Object()}if(!data.id){init=true;data.id=addonsidx}else{if(data.id>addonsidx){addonsidx=data.id}}option=new NestedMenuOption(menu.index,menu.itemsElement,"meta[options][a]",NEW_OPTION_DEFAULT,data);addonsidx++;optionid=option.id.val();option.selected=function(){if(option.element.hasClass("selected")){entries.find("ul li").removeClass("selected");selectedMenuOption=false}else{entries.find("ul li").removeClass("selected");$(option.element).addClass("selected");selectedMenuOption=option}};option.element.click(option.selected);productAddons[optionid]=option.label;option.label.blur(function(){Pricelines.row[optionid].updateLabel()});option.deleteButton.unbind("click");option.deleteButton.click(function(){var dbPriceid=Pricelines.row[optionid].data.id,dP=$("#deletePrices");if(dbPriceid){if(dP.val()==""){dP.val(dbPriceid)}else{dP.val(dP.val()+","+dbPriceid)}}Pricelines.row[optionid].row.remove();option.element.remove()});if(init){Pricelines.add(optionid,{context:"addon"},menu.pricegroup)}addonOptionsGroup[optionid]=menu.index;menu.items.push(option);entries.dequeue().animate({scrollTop:entries.attr("scrollHeight")-entries.height()},200);option.label.click().focus().select().keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();option.label.blur();addOptionButton.focus()})};menu.items=new Array();if(data&&data.options){$.each(data.options,function(){menu.addOption(this)})}else{menu.addOption();menu.addOption()}menu.itemsElement.sortable({axis:"y",update:function(){orderAddonPrices(menu.index)}});menu.element.unbind("click",menu.click);menu.element.click(function(){menu.selected();$(addOptionButton).unbind("click").click(menu.addOption)});addonGroups[addon_group_idx++]=menu;menu.deleteButton.unbind("click").click(function(){$("#addon-list #addon-group-"+menu.index+" li").not(".ui-sortable-helper").find("input.id").each(function(id,option){var optionid=$(option).val(),dbPriceid,dP=$("#deletePrices");if(Pricelines.row[optionid]){dbPriceid=Pricelines.row[optionid].data.id;if(dbPriceid){if(dP.val()==""){dP.val(dbPriceid)}else{dP.val(dP.val()+","+dbPriceid)}}Pricelines.row[optionid].row.remove()}});menu.deleteButton.trigger("delete");menu.pricegroup.remove();menu.element.remove()});if(!data){menus.dequeue().animate({scrollTop:menus.attr("scrollHeight")-menus.height()},200);menu.label.click().focus().select().keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();menu.label.blur();addMenuButton.focus()})}}function orderAddonGroups(){var $=jQuery,menu;$("#addon-menu ul li").not(".ui-sortable-helper").find("input.id").each(function(i,menuid){menu=addonGroups[$(menuid).val()];menu.pricegroup.appendTo("#addon-pricing")})}function orderAddonPrices(index){var $=jQuery,menu=addonGroups[index];$("#addon-list #addon-group-"+menu.index+" li").not(".ui-sortable-helper").find("input.id").each(function(id,option){Pricelines.reorderAddon($(option).val(),menu.pricegroup)})}function readableFileSize(size){var units=new Array("bytes","KB","MB","GB"),sized=size*1,unit=0;if(sized==0){return sized}while(sized>1000){sized=sized/1024;unit++}return sized.toFixed(2)+" "+units[unit]}function addDetail(data){var $=jQuery,i,optionsmenu,menus=$("#details-menu"),entries=$("#details-list"),id=detailsidx++,menu=new NestedMenu(id,menus,"details","Detail Name",data,{target:entries});if(data&&data.options){optionsmenu=$('<select name="details['+menu.index+'][value]"></select>').appendTo(menu.itemsElement);$("<option></option>").appendTo(optionsmenu);for(i in data.options){$("<option>"+data.options[i]["name"]+"</option>").appendTo(optionsmenu)}if(data&&data.value){optionsmenu.val(htmlentities(data.value))}}else{menu.item=new NestedMenuContent(menu.index,menu.itemsElement,"details",data)}if(!data||data.add){menu.add=$('<input type="hidden" name="details['+menu.index+'][new]" value="true" />').appendTo(menu.element);menus.dequeue().animate({scrollTop:menus.attr("scrollHeight")-menus.height()},200);menu.label.click().focus().select();if(menu.item){menu.item.contents.keydown(function(e){var key=e.keyCode||e.which;if(key!=9){return}e.preventDefault();$("#addDetail").focus()})}}}function ImageUploads(id,type){var $=jQuery,swfu,settings={button_text:ADD_IMAGE_BUTTON_TEXT,button_text_style:'.buttonText{text-align:center;font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana,_sans;font-size:9px;color:#333333;}',button_text_top_padding:3,button_height:"22",button_width:"100",button_image_url:uidir+"/icons/buttons.png",button_placeholder_id:"swf-uploader-button",upload_url:ajaxurl,flash_url:uidir+"/behaviors/swfupload.swf",file_queue_limit:0,file_size_limit:filesizeLimit+"b",file_types:"*.jpg;*.jpeg;*.png;*.gif",file_types_description:"Web-compatible Image Files",file_upload_limit:filesizeLimit,post_params:{action:"shopp_upload_image",parent:id,type:type},swfupload_loaded_handler:swfuLoaded,file_queue_error_handler:imageFileQueueError,file_dialog_complete_handler:imageFileDialogComplete,upload_start_handler:startImageUpload,upload_progress_handler:imageUploadProgress,upload_error_handler:imageUploadError,upload_success_handler:imageUploadSuccess,custom_settings:{loaded:false,targetHolder:false,progressBar:false,sorting:false},prevent_swf_caching:$.ua.msie,debug:imageupload_debug};if(flashuploader){swfu=new SWFUpload(settings)}$("#image-upload").upload({name:"Filedata",action:ajaxurl,params:{action:"shopp_upload_image",type:type},onSubmit:function(){this.targetHolder=$('<li id="image-uploading"><input type="hidden" name="images[]" value="" /><div class="progress"><div class="bar"></div><div class="gloss"></div></div></li>').appendTo("#lightbox");this.progressBar=this.targetHolder.find("div.bar");this.sorting=this.targetHolder.find("input")},onComplete:function(results){var image=false,img,deleteButton,targetHolder=this.targetHolder;try{image=$.parseJSON(results)}catch(ex){image.error=results}if(!image||!image.id){targetHolder.remove();if(image.error){alert(image.error)}else{alert(UNKNOWN_UPLOAD_ERROR)}return false}targetHolder.attr({id:"image-"+image.id});this.sorting.val(image.id);img=$('<img src="?siid='+image.id+'" width="96" height="96" class="handle" />').appendTo(targetHolder).hide();deleteButton=$('<button type="button" name="deleteImage" value="'+image.src+'" class="delete"><span class="shoppui-minus"></span></button>').appendTo($(targetHolder)).hide();$(this.progressBar).animate({width:"76px"},250,function(){$(this).parent().fadeOut(500,function(){$(this).remove();$(img).fadeIn("500");enableDeleteButton(deleteButton)})})}});$(document).load(function(){if(!swfu.loaded){$("#product-images .swfupload").remove()}});sorting();$("#lightbox li").each(function(){$(this).dblclick(function(){var id=$(this).attr("id")+"-details",src=$("#"+id),srcid=src.find("input[type=hidden]").val(),srcthumb=src.find("img"),srctitle=src.find("input.imagetitle"),srcalt=src.find("input.imagealt"),srcCropped=src.find("input.imagecropped"),ui=$('<div class="image-details-editor"><div class="details-editor"><img class="thumb" width="96" height="96" /><div class="details"><p><label>'+IMAGE_DETAILS_TITLE_LABEL+': </label><input type="text" name="title" /></p><p><label>'+IMAGE_DETAILS_ALT_LABEL+': </label><input type="text" name="alt" /></p></div></div><div class="cropping"><p class="clear">'+IMAGE_DETAILS_CROP_LABEL+': <select name="cropimage"><option></option></select></p><div class="cropui"></div><br class="clear"/></div><input type="button" class="button-primary alignright" value="&nbsp;&nbsp;'+IMAGE_DETAILS_DONE+'&nbsp;&nbsp;" /></div>'),thumb=ui.find("img").attr("src",srcthumb.attr("src")),titlefield=ui.find("input[name=title]").val(srctitle.val()).change(function(){srctitle.val(titlefield.val())}),altfield=ui.find("input[name=alt]").val(srcalt.val()).change(function(){srcalt.val(altfield.val())}),doneButton=ui.find("input[type=button]").click(function(){$.colorbox.close()}),cropping=ui.find("div.cropping").hide(),croptool=ui.find("div.cropui"),cropselect=ui.find("select[name=cropimage]").change(function(){if(cropselect.val()==""){croptool.empty();$.colorbox.resize();return}var d=cropselect.val().split(":"),init=srcCropped.filter("input[alt="+cropselect.val()+"]").val().split(",");croptool.empty().scaleCrop({imgsrc:"?siid="+srcid,target:{width:parseInt(d[0],10),height:parseInt(d[1],10)},init:{x:parseInt(init[0],10),y:parseInt(init[1],10),s:new Number(init[2])}}).ready(function(){var padding=125;$.colorbox.resize({innerWidth:(parseInt(d[0],10))+padding})}).bind("change.scalecrop",function(e,c){if(!c.s){c.s=1}if(c){srcCropped.filter("input[alt="+cropselect.val()+"]").val(c.x+","+c.y+","+c.s)}})});if(srcCropped.size()>0){srcCropped.each(function(i,e){var d=$(e).attr("alt");$('<option value="'+d+'">'+(i+1)+": "+d.replace(":","&times;")+"</option>").appendTo(cropselect)});cropping.show()}$.colorbox({title:IMAGE_DETAILS_TEXT,html:ui})});enableDeleteButton($(this).find("button.delete"))});function swfuLoaded(){$("#browser-uploader").hide();swfu.loaded=true}function sorting(){if($("#lightbox li").size()>0){$("#lightbox").sortable({opacity:0.8})}}function imageFileQueueError(file,error,message){if(error==SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED){alert("You selected too many files to upload at one time. "+(message===0?"You have reached the upload limit.":"You may upload "+(message>1?"up to "+message+" files.":"only one file.")));return}else{alert(message)}}function imageFileDialogComplete(selected,queued){try{this.startUpload()}catch(ex){this.debug(ex)}}function startImageUpload(file){this.targetHolder=$('<li class="image uploading"><input type="hidden" name="images[]" /><div class="progress"><div class="bar"></div><div class="gloss"></div></div></li>').appendTo($("#lightbox"));this.progressBar=this.targetHolder.find("div.bar");this.sorting=this.targetHolder.find("input")}function imageUploadProgress(file,loaded,total){this.progressBar.animate({width:Math.ceil((loaded/total)*76)+"px"},100)}function imageUploadError(file,error,message){}function imageUploadSuccess(file,results){var image=false,img,deleteButton,targetHolder=this.targetHolder;try{image=$.parseJSON(results)}catch(ex){targetHolder.remove();alert(results);return false}if(!image.id){targetHolder.remove();if(image.error){alert(image.error)}else{alert(UNKNOWN_UPLOAD_ERROR)}return true}targetHolder.attr({id:"image-"+image.id});this.sorting.val(image.id);img=$('<img src="?siid='+image.id+'" width="96" height="96" class="handle" />').appendTo(targetHolder).hide();deleteButton=$('<button type="button" name="deleteImage" value="'+image.id+'" class="delete"><span class="shoppui-minus"></span></button>').appendTo(targetHolder).hide();sorting();this.progressBar.animate({width:"76px"},250,function(){$(this).parent().fadeOut(500,function(){$(this).remove();$(img).fadeIn("500");enableDeleteButton(deleteButton)})})}function enableDeleteButton(button){button.hide();button.parent().hover(function(){button.show()},function(){button.hide()});button.click(function(){if(confirm(DELETE_IMAGE_WARNING)){var imgid=(button.val().substr(0,1)=="<")?button.find("input[name=ieisstupid]").val():button.val(),deleteImages=$("#deleteImages"),deleting=deleteImages.val();deleteImages.val(deleting==""?imgid:deleting+","+imgid);$("#confirm-delete-images").show();button.parent().fadeOut(500,function(){$(this).remove()})}})}}jQuery.fn.FileChooser=function(line,status){var $=jQuery,_=this,chooser=$("#chooser"),importurl=chooser.find(".fileimport"),importstatus=chooser.find(".status"),attach=$("#attach-file"),dlpath=$("#download_path-"+line),dlname=$("#download_file-"+line),file=$("#file-"+line),stored=false,nostatus=0,progressbar=false;_.line=line;_.status=status;chooser.unbind("change").on("change",".fileimport",function(e){importstatus.attr("class","status").addClass("shoppui-spinner shoppui-spinfx shoppui-spinfx-steps8");$.ajax({url:fileverify_url+"&action=shopp_verify_file&t=download",type:"POST",data:"url="+importurl.val(),timeout:10000,dataType:"text",success:function(results){importstatus.attr("class","status");if(results=="OK"){return importstatus.addClass("shoppui-ok-sign")}if(results=="NULL"){importstatus.attr("title",FILE_NOT_FOUND_TEXT)}if(results=="ISDIR"){importstatus.attr("title",FILE_ISDIR_TEXT)}if(results=="READ"){importstatus.attr("title",FILE_NOT_READ_TEXT)}importstatus.addClass("shoppui-warning-sign")}})});importurl.unbind("keydown").unbind("keypress").suggest(sugg_url+"&action=shopp_storage_suggestions&t=download",{delay:500,minchars:3,multiple:false,onSelect:function(){importurl.trigger("change")}});$(this).click(function(){fileUploads.updateLine(line,status);importstatus.attr("class","status");attach.unbind("click").click(function(){$.colorbox.hide();if(stored){dlpath.val(importurl.val());importurl.val("").attr("class","fileimport");return true}var importid=false,importdata=false,importfile=importurl.val(),completed=function(f){if(!f.name){return $this.attr("class","")}file.attr("class","file").html('<span class="icon shoppui-file '+f.mime.replace("/"," ")+'"></span>'+f.name+"<br /><small>"+readableFileSize(f.size)+"</small>");dlpath.val(f.path);dlname.val(f.name);importurl.val("").attr("class","fileimport")},importing=function(){var ui=file.find("div.progress"),progressbar=ui.find("div.bar"),scale=ui.outerWidth(),dataframe=$("#import-file-"+line).get(0).contentWindow,p=dataframe.importProgress,f=dataframe.importFile;if(f!==undefined){if(f.error){return file.attr("class","error").html("<small>"+f.error+"</small>")}if(!f.path){return file.attr("class","error").html("<small>"+FILE_UNKNOWN_IMPORT_ERROR+"</small>")}if(f.stored){return completed(f)}else{savepath=f.path.split("/");importid=savepath[savepath.length-1]}}if(!p){p=0}if(p===0&&nostatus++>60){return file.attr("class","error").html("<small>"+FILE_UNKNOWN_IMPORT_ERROR+"</small>")}progressbar.animate({width:Math.ceil(p*scale)+"px"},100);if(p==1){if(progressbar){progressbar.css({width:"100%"}).fadeOut(500,function(){completed(f)})}return}setTimeout(importing,100)};setTimeout(importing,100);file.attr("class","").html('<div class="progress"><div class="bar"></div><div class="gloss"></div></div><iframe id="import-file-'+line+'" width="0" height="0" src="'+fileimport_url+"&action=shopp_import_file&url="+importfile+'"></iframe>')})});$(this).colorbox({title:"File Selector",innerWidth:"360",innerHeight:"140",inline:true,href:chooser})};function FileUploader(button,defaultButton){var $=jQuery,_=this;_.swfu=false;_.settings={button_text:'<span class="button">'+UPLOAD_FILE_BUTTON_TEXT+"</span>",button_text_style:'.button { text-align: center; font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana,sans-serif; font-size: 9px; color: #333333; }',button_text_top_padding:3,button_height:"22",button_width:"100",button_image_url:uidir+"/icons/buttons.png",button_placeholder_id:button,button_action:SWFUpload.BUTTON_ACTION.SELECT_FILE,flash_url:uidir+"/behaviors/swfupload/swfupload.swf",upload_url:ajaxurl,file_queue_limit:1,file_size_limit:filesizeLimit+"b",file_types:"*.*",file_types_description:"All Files",file_upload_limit:filesizeLimit,post_params:{action:"shopp_upload_file"},swfupload_loaded_handler:swfuLoaded,file_queue_error_handler:fileQueueError,file_dialog_complete_handler:fileDialogComplete,upload_start_handler:startUpload,upload_progress_handler:uploadProgress,upload_success_handler:uploadSuccess,custom_settings:{loaded:false,targetCell:false,targetLine:false,progressBar:false},prevent_swf_caching:$.ua.msie,debug:fileupload_debug};if(flashuploader){_.swfu=new SWFUpload(_.settings)}defaultButton.upload({name:"Filedata",action:ajaxurl,params:{action:"shopp_upload_file"},onSubmit:function(){$.colorbox.hide();_.targetCell.attr("class","").html("");$('<div class="progress"><div class="bar"></div><div class="gloss"></div></div>').appendTo(_.targetCell);_.progressBar=_.targetCell.find("div.bar")},onComplete:function(results){$.colorbox.close();var filedata=false,targetHolder=_.targetCell;try{filedata=$.parseJSON(results)}catch(ex){filedata.error=results}if(!filedata.id&&!filedata.name){targetHolder.html(NO_DOWNLOAD);if(filedata.error){alert(filedata.error)}else{alert(UNKNOWN_UPLOAD_ERROR)}return false}filedata.type=filedata.type.replace(/\//gi," ");$(_.progressBar).animate({width:"76px"},250,function(){$(this).parent().fadeOut(500,function(){targetHolder.attr("class","file").html('<div class="icon shoppui-file '+filedata.type+'"></div>'+filedata.name+"<br /><small>"+readableFileSize(filedata.size)+'</small><input type="hidden" name="price['+_.targetLine+'][download]" value="'+filedata.id+'" />');$(this).remove()})})}});$(_).load(function(){if(!_.swfu||!_.swfu.loaded){$(defaultButton).parent().parent().find(".swfupload").remove()}});function swfuLoaded(){$(defaultButton).hide();this.loaded=true}_.updateLine=function(line,status){if(!_.swfu){_.targetLine=line;_.targetCell=status}else{_.swfu.targetLine=line;_.swfu.targetCell=status}};function fileQueueError(file,error,message){if(error==SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED){alert("You selected too many files to upload at one time. "+(message===0?"You have reached the upload limit.":"You may upload "+(message>1?"up to "+message+" files.":"only one file.")));return}else{alert(message)}}function fileDialogComplete(selected,queued){$.colorbox.hide();if(!selected){return}try{this.startUpload()}catch(ex){this.debug(ex)}}function startUpload(file){this.targetCell.attr("class","").html("");$('<div class="progress"><div class="bar"></div><div class="gloss"></div></div>').appendTo(this.targetCell);this.progressBar=this.targetCell.find("div.bar")}function uploadProgress(file,loaded,total){this.progressBar.animate({width:Math.ceil((loaded/total)*76)+"px"},100)}function uploadSuccess(file,results){var filedata=false,targetCell=this.targetCell,i=this.targetLine;$.colorbox.close();try{filedata=$.parseJSON(results)}catch(ex){filedata.error=results}if(!filedata.id&&!filedata.name){targetCell.html(NO_DOWNLOAD);if(filedata.error){alert(filedata.error)}else{alert(UNKNOWN_UPLOAD_ERROR)}return false}filedata.type=filedata.type.replace(/\//gi," ");$(this.progressBar).animate({width:"76px"},250,function(){$(this).parent().fadeOut(500,function(){$(this).remove();$(targetCell).attr("class","file").html('<div class="icon shoppui-file '+filedata.type+'"></div>'+filedata.name+"<br /><small>"+readableFileSize(filedata.size)+'</small><input type="hidden" name="price['+i+'][download]" value="'+filedata.id+'" />')})})}}function SlugEditor(id,type){var $=jQuery,_=this,editbs=$("#edit-slug-buttons"),edit=editbs.find(".edit"),view=editbs.find(".view"),editorbs=$("#editor-slug-buttons"),save=editorbs.find(".save"),cancel=editorbs.find(".cancel"),full=$("#editable-slug-full");_.permalink=function(){var i,c=0,editor=$("#editable-slug"),revert_editor=editor.html(),real_slug=$("#slug_input"),revert_slug=real_slug.html(),slug=full.html();editbs.hide();editorbs.show();save.unbind("click").click(function(){var slug=editor.children("input").val(),title=$("#title").val();$.post(editslug_url+"&action=shopp_edit_slug",{id:id,type:type,slug:slug,title:title},function(data){editor.html(revert_editor);if(data!=-1){editor.html(data);full.html(data);real_slug.val(data)}view.attr("href",canonurl+full.html());editorbs.hide();editbs.show()},"text")});cancel.unbind("click").click(function(){editor.html(revert_editor);editorbs.hide();editbs.show();real_slug.attr("value",revert_slug)});for(i=0;i<slug.length;++i){if("%"==slug.charAt(i)){c++}}slug_value=(c>slug.length/4)?"":slug;editor.html('<input type="text" id="new-post-slug" value="'+slug_value+'" />').children("input").keypress(function(e){var key=e.which;if(key==13||key==27){e.preventDefault()}if(13==key){save.click()}if(27==key){cancel.click()}real_slug.val(this.value)}).focus()};edit.click(_.permalink)};
  • shopp/trunk/core/ui/orders/order.php

    r1053635 r1122729  
    216216                                                <?php endif; ?>
    217217                                                <?php foreach ( (array)$Item->data as $name => $value ): ?>
    218                                                     <li><small><?php echo apply_filters('shopp_purchased_data_name', $name); ?>: <strong><?php echo apply_filters('shopp_purchased_data_value', $value); ?></strong></small></li>
     218                                                    <li><small><?php echo apply_filters('shopp_purchased_data_name', $name); ?>: <strong><?php echo apply_filters('shopp_purchased_data_value', $value, $name); ?></strong></small></li>
    219219                                                <?php endforeach; ?>
    220220                                                <?php endif; ?>
  • shopp/trunk/core/ui/orders/orders.php

    r905841 r1122729  
    7878            $txnstatus = isset($txnstatus_labels[$Order->txnstatus]) ? $txnstatus_labels[$Order->txnstatus] : $Order->txnstatus;
    7979            $classes[] = strtolower(preg_replace('/[^\w]/','_',$Order->txnstatus));
    80             $gateway = $Gateways[$Order->gateway]->name;
    81 
     80
     81            $Gateway = $Gateways->get($Order->gateway);
     82            if ( $Gateway ) $gateway = $Gateway->name;
    8283
    8384            $addrfields = array('city','state','country');
  • shopp/trunk/core/ui/reports/discounts.php

    r1020997 r1122729  
    3636    }
    3737
    38     function columns () {
     38    function columns() {
    3939        return array(
    4040            'period'    => __('Period', 'Shopp'),
     
    4646    }
    4747
    48     static function orders ( $data ) { return intval($data->orders); }
     48    static function orders( $data ) {
     49        return intval( isset($data->orders) ? $data->orders : 0);
     50    }
    4951
    50     static function items ( $data ) { return intval($data->items); }
     52    static function items( $data ) {
     53        return intval( isset($data->items) ? $data->items : 0);
     54    }
    5155
    52     static function subtotal ( $data ) { return money($data->subtotal); }
     56    static function subtotal( $data ) {
     57        return money( isset($data->subtotal) ? $data->subtotal : 0 );
     58    }
    5359
    54     static function discounts ( $data ) { return money($data->discounts); }
     60    static function discounts( $data ) {
     61        return money( isset($data->discounts) ? $data->discounts : 0 );
     62    }
    5563
    5664}
  • shopp/trunk/core/ui/settings/downloads.php

    r930519 r1122729  
    88    ?>
    99
    10     <form name="settings" id="checkout" action="<?php echo add_query_arg('tab', $this->tab, esc_url($this->url)); ?>" method="post">
     10    <form name="settings" id="checkout" action="<?php echo esc_url($this->url); ?>" method="post">
    1111        <?php wp_nonce_field('shopp-settings-downloads'); ?>
    1212
  • shopp/trunk/core/ui/settings/management.php

    r930519 r1122729  
    7979        states = <?php echo json_encode($statesLabels); ?>,
    8080        reasons = <?php echo json_encode($reasonLabels); ?>;
    81     $('#order-statuslabels').labelset(labels,'#statusLabel');
    82     $("#order-statuslabels select").each(function(i,menu){
    83         var menuid = $(menu).attr('id'),
    84             id = menuid.substr(menuid.indexOf('-')+1);
     81    $('#order-statuslabels').labelset(labels, '#statusLabel');
     82    $("#order-statuslabels select").each(function(){
     83        var menuid = $(this).attr('id'),
     84            id = menuid.substr(menuid.indexOf('-') + 1);
    8585
    86         if(states != null && states[id] != undefined)
    87             $(this).find("option[value="+states[id]+"]").attr("selected", "selected");
     86        if ( states != null && states[id] != undefined )
     87            $(this).val(states[id]);
    8888    });
    89     $('#order-cancelreasons').labelset(reasons,'#reasonLabel');
     89    $('#order-cancelreasons').labelset(reasons, '#reasonLabel');
    9090});
    9191/* ]]> */
  • shopp/trunk/readme.txt

    r970959 r1122729  
    11=== Shopp ===
    2 Contributors: jond, barry.hughes, clifgriffin, jdillick, lorenzocaum, chaoix
     2Contributors: jond, barry.hughes, clifgriffin, jdillick, lorenzocaum, chaoix, crunnells
    33Donate link: http://shopp.me/shopp-donate
    44Tags: ecommerce, e-commerce, wordpress ecommerce, shopp, shop, shopping, cart, store, storefront, sales, sell, catalog, checkout, accounts, secure, variations, variants, reports, downloads, digital, downloadable, inventory, stock, shipping, taxes, shipped, addons, widgets, shortcodes
    55Requires at least: 3.5
    6 Tested up to: 3.9
     6Tested up to: 4.1.1
    77Stable tag: trunk
    88License: GPLv3 or later
  • shopp/trunk/storage/core/FSStorage.php

    r905841 r1122729  
    6363        $error = false;
    6464        if (empty($data)) $error = "$this->module: There is no file data to store.";
    65 
     65       
     66        $filepath = self::sanitize($this->path.'/'.$asset->filename);
    6667        switch ($type) {
    6768            case 'upload':
    68 
    69                 if ( ! is_readable($data) ) $error = "$this->module: Could not read the file.";
    70                 elseif (move_uploaded_file($data,self::sanitize($this->path.'/'.$asset->filename))) return $asset->filename;
     69                if (move_uploaded_file($data,$filepath)) break;
    7170                else $error = "$this->module: Could not move the uploaded file to the storage repository.";
    7271                $buffer = ob_get_contents();
     
    7473            case 'file':
    7574                if ( ! is_readable($data) ) $error = "$this->module: Could not read the file.";
    76                 elseif (copy($data,self::sanitize($this->path.'/'.$asset->filename))) return $asset->filename;
     75                elseif (copy($data,$filepath)) break;
    7776                else $error = "$this->module: Could not move the file to the storage repository.";
    7877                break;
    7978            default:
    80                 if (file_put_contents(self::sanitize($this->path.'/'.$asset->filename),$data) > 0) return $asset->filename;
     79                if (file_put_contents($filepath,$data) > 0) break;
    8180                else $error = "$this->module: Could not store the file data.";
    8281        }
     
    8685            return $error;
    8786        }
    88 
     87       
     88        // Set correct file permissions
     89        $filestat = stat($filepath);
     90        $perms = $filestat['mode'] & 0000666;
     91        @ chmod( $filepath, $perms );
     92       
     93        return $asset->filename;
     94       
    8995    }
    9096
  • shopp/trunk/templates/login.php

    r821385 r1122729  
    2525                    <?php shopp( 'customer.password-login', 'size=20&title=' . __( 'Password', 'Shopp' ) ); ?>
    2626                </span>
    27                 <span><?php shopp( 'customer.login-button' ); ?></span>
     27                <span>
     28                    <label>&nbsp;</label>
     29                    <?php shopp( 'customer.login-button' ); ?>
     30                </span>
    2831            </li>
    2932            <li>
  • shopp/trunk/templates/receipt.php

    r821385 r1122729  
    8383                        <?php shopp( 'purchase.item-download' ); ?>
    8484                        <?php shopp( 'purchase.item-addons-list' ); ?>
     85                        <?php shopp( 'purchase.item-inputs-list' ); ?>
    8586                    </td>
    8687                    <td><?php shopp( 'purchase.item-quantity' ); ?></td>
Note: See TracChangeset for help on using the changeset viewer.