Plugin Directory

Changeset 930519


Ignore:
Timestamp:
06/11/2014 05:54:35 PM (12 years ago)
Author:
jond
Message:

Added 1.3.4 release

Location:
shopp/trunk
Files:
1 added
81 edited

Legend:

Unmodified
Added
Removed
  • shopp/trunk/Shopp.php

    r905841 r930519  
    44 * Plugin URI: http://shopplugin.com
    55 * Description: An ecommerce framework for WordPress.
    6  * Version: 1.3.3
     6 * Version: 1.3.4
    77 * Author: Ingenesis Limited
    88 * Author URI: http://ingenesis.net
  • shopp/trunk/api/admin.php

    r821385 r930519  
    2929 * @return integer The position the menu was added
    3030 **/
    31 function shopp_admin_add_menu ( string $label, string $page, integer $position = null, $handler = false, string $access = null, string $icon = null ) {
     31function shopp_admin_add_menu ( $label, $page, $position = null, $handler = false, $access = null, $icon = null ) {
    3232
    3333    global $menu;
     
    7676 * @return integer The position the menu was added
    7777 **/
    78 function shopp_admin_add_submenu ( string $label, string $page, string $menu = null, $handler = false, string $access = null ) {
     78function shopp_admin_add_submenu ( $label, $page, $menu = null, $handler = false, $access = null ) {
    7979
    8080    $Admin = ShoppAdmin();
  • shopp/trunk/api/cart.php

    r831831 r930519  
    156156 * @return bool true for success, false on failure
    157157 **/
    158 function shopp_set_cart_item_variant ( string $item = null, int $variant = null ) {
     158function shopp_set_cart_item_variant ( $item = null, $variant = null ) {
    159159
    160160    if ( null === $item ) {
     
    269269 * @return void
    270270 **/
    271 function shopp_add_cart_discount_code( string $code = null ) {
     271function shopp_add_cart_discount_code( $code = null ) {
    272272    if ( null === $code || empty($code) ) {
    273273        shopp_debug(__FUNCTION__ . " failed: Missing code parameter.");
  • shopp/trunk/api/core.php

    r905841 r930519  
    190190 * @return ShoppPage The requested ShoppPage if found, false otherwise
    191191 **/
    192 function shopp_get_page ( string $pagename ) {
     192function shopp_get_page ( $pagename ) {
    193193    return ShoppPages()->get($pagename);
    194194}
     
    202202 * @return void
    203203 **/
    204 function shopp_register_page ( string $classname ) {
     204function shopp_register_page ( $classname ) {
    205205    ShoppPages()->register($classname);
    206206}
  • shopp/trunk/api/theme/cart.php

    r905841 r930519  
    6161        'updatebutton' => 'update_button',
    6262        'url' => 'url',
     63        'hassavings' => 'has_savings',
     64        'savings' => 'savings',
    6365
    6466        /* Deprecated tag names - do not use */
     
    512514    // Check if any of the items in the cart are on sale
    513515    public static function has_savings ( $result, $options, $O ) {
    514         // loop thru cart looking for $Item->sale == "on"
     516        // loop thru cart looking for $Item->sale == "on" or "1" etc
    515517        foreach( $O as $item ) {
    516             if ( 'on' == $item->sale ) return true;
     518            if ( str_true( $item->sale ) ) return true;
    517519        }
    518520
  • shopp/trunk/api/theme/collection.php

    r905841 r930519  
    164164            'collapse' => true,
    165165            'wrap' => true,
    166             'before' => '<div class="category-description">',
     166            'before' => '<div class="category-description">' . "\n\n",
    167167            'after' => '</div>'
    168168        );
  • shopp/trunk/api/theme/product.php

    r905841 r930519  
    403403    public static function buy_now ( $result, $options, $O ) {
    404404        if ( ! isset($options['value']) ) $options['value'] = Shopp::__('Buy Now');
    405         return self::addtocart( $result, $options, $O );
     405        return self::add_to_cart( $result, $options, $O );
    406406    }
    407407
     
    14481448    }
    14491449
    1450     public static function _variant_formatlabel ( string $format, $var ) {
     1450    public static function _variant_formatlabel ( $format, $var ) {
    14511451        $data = (array)$var;
    14521452
  • shopp/trunk/core/flow/Admin.php

    r865739 r930519  
    227227     * @return void
    228228     **/
    229     private function addpage ( string $name, string $label, string $controller, string $parent = null) {
     229    private function addpage ( $name, $label, $controller, $parent = null ) {
    230230        $page = $this->pagename($name);
    231231
     
    294294     * @return string The screen id of the given menu name
    295295     **/
    296     public function menu ( string $name, string $menu = null ) {
     296    public function menu ( $name, $menu = null ) {
    297297
    298298        if ( isset($menu) ) $this->menus[ $name ] = $menu;
     
    791791    public $parent = false;
    792792
    793     public function __construct ( string $name, string $page, string $label, string $controller, string $parent = null ) {
     793    public function __construct ( $name, $page, $label, $controller, $parent = null ) {
    794794        $this->name = $name;
    795795        $this->page = $page;
     
    820820    }
    821821
    822     public static function button ( string $button, string $name, array $options = array() ) {
     822    public static function button ( $button, $name, array $options = array() ) {
    823823        $buttons = array(
    824824            'add' => array('class' => 'add', 'title' => Shopp::__('Add'), 'icon' => 'shoppui-plus', 'type' => 'submit'),
     
    10651065     * @param array $args [optional]
    10661066     */
    1067     public static function addmetabox(string $id, string $title, $callback, string $posttype, $context = 'advanced', $priority = 'default', array $args = null) {
     1067    public static function addmetabox(string $id, $title, $callback, $posttype, $context = 'advanced', $priority = 'default', array $args = null) {
    10681068        self::$metaboxes[$id] = $callback;
    10691069        $args = (array) $args;
  • shopp/trunk/core/flow/Categorize.php

    r831831 r930519  
    508508    public function products_cols () {
    509509        register_column_headers($this->screen, array(
    510             'name'      => '<div class="shoppui-spin-align"><div class="shoppui-spinner shoppui-spinfx shoppui-spinfx-steps8"></div></div>',
     510            'name'      => '<div class="shoppui-spin-align"><div class="shoppui-spinner shoppui-spinfx shoppui-spinfx-steps8 hidden"></div></div>',
    511511            'title'     => Shopp::__('Product'),
    512512            'sold'      => Shopp::__('Sold'),
  • shopp/trunk/core/flow/Install.php

    r905841 r930519  
    10371037
    10381038        if ( $db_version <= 1200 ) {
    1039            // All existing sessions must be cleared and restarted, 1.3 sessions are not compatible with any prior version of Shopp
    1040             $sessions_table = ShoppDatabaseObject::tablename('shopping');
     1039            // All existing sessions must be cleared and restarted, 1.3 sessions are not compatible with any prior version of Shopp
     1040            ShoppShopping()->reset();
     1041            $sessions_table = ShoppDatabaseObject::tablename('shopping');
    10411042            sDB::query("DELETE FROM $sessions_table");
    1042 
     1043   
    10431044            $meta_table = ShoppDatabaseObject::tablename('meta');
    10441045            sDB::query("UPDATE $meta_table SET value='on' WHERE name='theme_templates' AND (value != '' AND value != 'off')");
    10451046            sDB::query("DELETE FROM $meta_table WHERE type='image' AND value LIKE '%O:10:\"ShoppError\"%'"); // clean up garbage from legacy bug
    10461047            sDB::query("DELETE FROM $meta_table WHERE CONCAT('', name *1) = name AND context = 'category' AND type = 'meta'"); // clean up bad category meta
    1047 
     1048   
    10481049            // Update purchase gateway values to match new prefixed class names
    10491050            $gateways = array(
     
    10531054                'TestMode' => 'ShoppTestMode',
    10541055                'FreeOrder' => 'ShoppFreeOrder'
    1055 
     1056   
    10561057            );
    10571058            foreach ($gateways as $name => $classname)
    10581059                sDB::query("UPDATE $purchase_table SET gateway='$classname' WHERE gateway='$name'");
    1059 
     1060   
    10601061            $activegateways = explode(',', shopp_setting('active_gateways'));
    10611062            foreach ($activegateways as &$setting)
  • shopp/trunk/core/flow/Login.php

    r831831 r930519  
    127127     * @return void
    128128     **/
    129     public function auth ( string $id, string $password, $type = 'email') {
     129    public function auth ( $id, $password, $type = 'email') {
    130130
    131131        do_action('shopp_auth');
  • shopp/trunk/core/flow/Order.php

    r905841 r930519  
    111111        // Initialize/reinitalize the current location
    112112        add_action('shopp_init', array($this, 'locate'), 20);
    113 
    114113
    115114    }
     
    780779     **/
    781780    public function securecard () {
    782         if ( ! empty($this->Billing->card) && strlen($this->Billing->card) > 4 ) {
    783             $this->Billing->card = substr($this->Billing->card, -4);
    784 
    785             // Card data is truncated, switch the cart to normal mode
    786             ShoppShopping()->secured(false);
    787         }
     781        $this->Billing->card = '';
     782
     783        // Card data is gone, switch the cart to normal mode
     784        ShoppShopping()->secured(false);
    788785    }
    789786
  • shopp/trunk/core/flow/Pages.php

    r905841 r930519  
    4242    }
    4343
    44     public function register ( string $StorefrontPageClass ) {
     44    public function register ( $StorefrontPageClass ) {
    4545
    4646        if ( ! class_exists($StorefrontPageClass) ) return false;
     
    8484    }
    8585
    86     public function slugpage ( string $slug ) {
     86    public function slugpage ( $slug ) {
    8787        if ( ! isset($this->slugs[ $slug ]) ) return false;
    8888        return $this->get( $this->slugs[ $slug ] );
     
    495495
    496496        $errors = array();
    497         if (empty($activation) || !is_string($activation))
    498             $errors[] = new ShoppError(__('Invalid key', 'Shopp'));
     497        if ( empty($activation) || ! is_string($activation) )
     498            $errors[] = new ShoppError(Shopp::__('Invalid key'));
    499499
    500500        $RecoveryCustomer = new ShoppCustomer($activation, 'activation');
    501         if (empty($RecoveryCustomer->id))
    502             $errors[] = new ShoppError(__('Invalid key', 'Shopp'));
    503 
    504         if (!empty($errors)) return false;
     501        if ( empty($RecoveryCustomer->id) )
     502            $errors[] = new ShoppError(Shopp::__('Invalid key'));
     503
     504        if ( ! empty($errors) ) return false;
    505505
    506506        // Generate a new random password
    507507        $password = wp_generate_password();
    508508
    509         do_action_ref_array('password_reset', array(&$RecoveryCustomer, $password));
     509        do_action_ref_array('password_reset', array($RecoveryCustomer, $password));
    510510
    511511        $RecoveryCustomer->password = wp_hash_password($password);
     
    518518        $RecoveryCustomer->save();
    519519
    520         $subject = apply_filters('shopp_reset_password_subject', sprintf(__('[%s] New Password', 'Shopp'), get_option('blogname')));
     520        $subject = apply_filters('shopp_reset_password_subject', Shopp::__('[%s] New Password', get_option('blogname')));
    521521
    522522        $_ = array();
    523523        $_[] = 'From: ' . Shopp::email_from( shopp_setting('merchant_email'), shopp_setting('business_name') );
    524         $_[] = 'To: '.$RecoveryCustomer->email;
    525         $_[] = 'Subject: '.$subject;
     524        $_[] = 'To: ' . $RecoveryCustomer->email;
     525        $_[] = 'Subject: ' . $subject;
     526        $_[] = 'Content-type: text/html';
    526527        $_[] = '';
    527         $_[] = '<p>'.sprintf(__('Your new password for %s:', 'Shopp'), get_option('siteurl')).'</p>';
     528        $_[] = '<p>' . Shopp::__('Your new password for %s:', get_option('siteurl')) . '</p>';
    528529        $_[] = '';
    529530        $_[] = '<ul>';
    530         if ($user_data)
    531             $_[] = '<li>'.sprintf(__('Login name: %s', 'Shopp'), $user_data->user_login).'</li>';
    532         $_[] = '<li>'.sprintf(__('Password: %s'), $password).'</li>';
     531        if ( $user_data )
     532            $_[] = '<li>' . Shopp::__('Login name: %s', $user_data->user_login) . '</li>';
     533        $_[] = '<li>' . Shopp::__('Password: %s', $password) . '</li>';
    533534        $_[] = '</ul>';
    534535        $_[] = '';
    535         $_[] = '<p>'.__('Click here to login:').' '.Shopp::url(false, 'account').'</p>';
     536        $_[] = '<p>' . Shopp::__('Click here to login: %s', Shopp::url(false, 'account')) . '</p>';
    536537        $message = apply_filters('shopp_reset_password_message', $_);
    537538
    538         if (!Shopp::email(join("\n", $message))) {
    539             new ShoppError(__('The e-mail could not be sent.'), 'password_reset_email', SHOPP_ERR);
     539        if ( ! Shopp::email(join("\n", $message)) ) {
     540            shopp_add_error(Shopp::__('The e-mail could not be sent.'));
    540541            Shopp::redirect( add_query_arg( 'acct', 'recover', Shopp::url(false, 'account') ) );
    541         } else new ShoppError(__('Check your email address for your new password.', 'Shopp'), 'password_reset_email', SHOPP_ERR);
     542        } else shopp_add_error(Shopp::__('Check your email address for your new password.'));
    542543
    543544        unset($_GET['acct']);
    544545    }
    545 
    546546
    547547}
     
    619619    }
    620620
    621     public function head () {
    622         ?>
    623         <script type="text/javascript">
    624         //<![CDATA[
    625             document.body.className += ' js-on';
    626         //]]>
    627         </script>
    628 <?php
     621    public function head () {?>
     622        <script type="text/javascript">//<![CDATA[ checkout JS-support detection
     623            document.documentElement.className += ' js-on'; //]]></script><?php
    629624    }
    630625
     
    805800    }
    806801
    807     public function wp_title ( string $title, string $sep = null, $placement = null ) {
     802    public function wp_title ( $title, $sep = null, $placement = null ) {
    808803        if ( is_null($sep) ) $sep = '&mdash;';
    809804        if ( is_null($placement) ) $placement = '';
  • shopp/trunk/core/flow/Report.php

    r865739 r930519  
    6767            'locations' => array( 'class' => 'LocationsReport', 'name' => __('Locations Report','Shopp'), 'label' => __('Locations','Shopp') ),
    6868            'products' => array( 'class' => 'ProductsReport', 'name' => __('Products Report','Shopp'), 'label' => __('Products','Shopp') ),
     69            'payment-types' => array( 'class' => 'PaymentTypesReport', 'name' => __('Payment Types Report','Shopp'), 'label' => __('Payment Types','Shopp') ),
    6970        ));
    7071    }
     
    452453     * @return string Date index column SQL statement
    453454     **/
    454     public function timecolumn ( string $column ) {
     455    public function timecolumn ( $column ) {
    455456        $tzoffset = date('Z')/3600;
    456457        $column = "CONVERT_TZ($column,'+00:00','".($tzoffset>=0?'+':'-')."$tzoffset:00')";
     
    474475     * @return string The UNIX_TIMESTAMP SQL column fragment
    475476     **/
    476     static function unixtime ( string $column ) {
     477    static function unixtime ( $column ) {
    477478        $tzoffset = date('Z')/3600;
    478479        return "UNIX_TIMESTAMP(CONVERT_TZ($column,'+00:00','".($tzoffset>=0?'+':'-')."$tzoffset:00'))";
     
    490491     * @return int The number of periods
    491492     **/
    492     public function range ( integer $starts, integer $ends, $scale = 'day') {
     493    public function range ( $starts, $ends, $scale = 'day') {
    493494        $oneday = 86400;
    494495        $years = date('Y',$ends)-date('Y',$starts);
     
    533534     * @return string Formatted week range label
    534535     **/
    535     static function weekrange ( int $ts, $formats=array('F j','F j Y') ) {
     536    static function weekrange ( $ts, $formats=array('F j','F j Y') ) {
    536537        $weekday = date('w',$ts);
    537538        $startweek = $ts-($weekday*86400);
  • shopp/trunk/core/flow/Resources.php

    r865739 r930519  
    195195            }
    196196
    197             if ( __('Guest','Shopp') != ShoppCustomer()->type ) {
    198 
    199                 // Account restriction checks
    200                 if ( $accounts && ! ShoppCustomer()->loggedin() ) {
     197            // If accounts are used and this is not a guest account
     198            if ( $accounts && Shopp::__('Guest') != ShoppCustomer()->type ) {
     199
     200                // User must be logged in when accounts are being used
     201                if ( ! ShoppCustomer()->loggedin() ) {
    201202                    shopp_add_error(Shopp::__('You must login to download purchases.'));
    202203                    $forbidden = true;
    203204                }
    204205
    205                 // File owner authorization check
    206                 if ($accounts && ShoppCustomer()->id != $Purchase->customer) {
     206                // Logged in account must be the owner of the purchase
     207                if ( ShoppCustomer()->id != $Purchase->customer ) {
    207208                    shopp_add_error(Shopp::__('You are not authorized to download the requested file.'));
    208209                    $forbidden = true;
     
    213214            // Download limit checking
    214215            if (shopp_setting('download_limit') // Has download credits available
    215                     && $Purchased->downloads+1 > shopp_setting('download_limit')) {
     216                    && $Purchased->downloads + 1 > shopp_setting('download_limit')) {
    216217                shopp_add_error(Shopp::__('&quot;%s&quot; is no longer available for download because the download limit has been reached.', $name));
    217218                $forbidden = true;
  • shopp/trunk/core/flow/Scripts.php

    r821385 r930519  
    343343            // Currency formatting
    344344            'cp' => $settings['cpos'],
    345             'c' => $settings['currency'],
    346             'p' => (int)$settings['precision'],
    347             't' => $settings['thousands'],
    348             'd' => $settings['decimals']
     345            'c'  => $settings['currency'],
     346            'p'  => (int)$settings['precision'],
     347            't'  => $settings['thousands'],
     348            'd'  => $settings['decimals']
    349349        );
    350         if (isset($settings['grouping']))
     350        if ( isset($settings['grouping']) )
    351351            $currency['g'] = is_array($settings['grouping']) ? join(',',$settings['grouping']) : $settings['grouping'];
    352352
     
    365365    // Checkout page settings & localization
    366366    shopp_localize_script('checkout', '$co', array(
    367         'ajaxurl' => admin_url('admin-ajax.php'),
    368         'loginname' => __('You did not enter a login.','Shopp'),
    369         'loginpwd' => __('You did not enter a password to login with.','Shopp'),
     367        'ajaxurl' =>    admin_url('admin-ajax.php'),
     368        'loginname' =>  Shopp::__('You did not enter a login.'),
     369        'loginpwd' =>   Shopp::__('You did not enter a password to login with.'),
     370        'badpan' =>     Shopp::__('Not a valid card number.'),
     371        'submitting' => Shopp::__('Submitting&hellip;'),
     372        'error' =>      Shopp::__('An error occurred while submitting your order. Please try submitting your order again.'),
     373        'timeout' =>    (int)SHOPP_SUBMIT_TIMEOUT
    370374    ));
    371375
  • shopp/trunk/core/flow/Service.php

    r905841 r930519  
    2525    public $orders = array();
    2626    public $ordercount = false;
     27
     28    protected $ui = 'orders';
    2729
    2830    /**
     
    304306        $Gateways = array_merge($Shopp->Gateways->modules, array('ShoppFreeOrder' => $Shopp->Gateways->freeorder));
    305307
    306         include(SHOPP_ADMIN_PATH."/orders/orders.php");
     308        include $this->ui('orders.php');
    307309    }
    308310
     
    349351            'total' => __('Total','Shopp')
    350352        )));
    351         include(SHOPP_ADMIN_PATH."/orders/events.php");
    352         include(SHOPP_ADMIN_PATH."/orders/ui.php");
     353        include $this->ui('events.php');
     354        include $this->ui('ui.php');
    353355        do_action('shopp_order_manager_layout');
    354356    }
     
    600602        foreach ($countrydata as $iso => $c) {
    601603            if ($base['country'] == $iso) $base_region = $c['region'];
    602             $countries[$iso] = $c['name'];
     604            $countries[ $iso ] = $c['name'];
    603605        }
    604606        $Purchase->_countries = $countries;
    605607
    606608        $regions = Lookup::country_zones();
    607         $Purchase->_billing_states = array_merge(array(''=>'&nbsp;'),(array)$regions[$Purchase->country]);
    608         $Purchase->_shipping_states = array_merge(array(''=>'&nbsp;'),(array)$regions[$Purchase->shipcountry]);
     609        $Purchase->_billing_states = array_merge(array('' => '&nbsp;'), (array)$regions[ $Purchase->country ]);
     610        $Purchase->_shipping_states = array_merge(array('' => '&nbsp;'), (array)$regions[ $Purchase->shipcountry ]);
    609611
    610612        $carriers_menu = $carriers_json = array();
     
    612614        $shipcarriers = Lookup::shipcarriers();
    613615
    614         if (empty($shipping_carriers)) {
    615             $serviceareas = array('*',$base['country']);
    616             foreach ($shipcarriers as $code => $carrier) {
    617                 if (!in_array($carrier->areas,$serviceareas)) continue;
    618                 $carriers_menu[$code] = $carrier->name;
    619                 $carriers_json[$code] = array($carrier->name,$carrier->trackpattern);
     616        $carriers_menu['NOTRACKING'] = Shopp::__('No Tracking');
     617        $carriers_json['NOTRACKING'] = array(Shopp::__('No Tracking'), false);
     618        if ( empty($shipping_carriers) ) {
     619            $serviceareas = array('*', $base['country']);
     620            foreach ( $shipcarriers as $code => $carrier ) {
     621                if ( ! in_array($carrier->areas, $serviceareas) ) continue;
     622                $carriers_menu[ $code ] = $carrier->name;
     623                $carriers_json[ $code ] = array($carrier->name,$carrier->trackpattern);
    620624            }
    621625        } else {
    622626            foreach ($shipping_carriers as $code) {
    623                 $carriers_menu[$code] = $shipcarriers[$code]->name;
    624                 $carriers_json[$code] = array($shipcarriers[$code]->name,$shipcarriers[$code]->trackpattern);
     627                $carriers_menu[ $code ] = $shipcarriers[ $code ]->name;
     628                $carriers_json[ $code ] = array($shipcarriers[ $code ]->name, $shipcarriers[ $code ]->trackpattern);
    625629            }
    626630        }
    627631        unset($carrierdata);
    628632
    629         if (empty($statusLabels)) $statusLabels = array('');
    630 
    631         include(SHOPP_ADMIN_PATH."/orders/order.php");
     633        if ( empty($statusLabels) ) $statusLabels = array('');
     634
     635        include $this->ui('order.php');
    632636    }
    633637
  • shopp/trunk/core/flow/Setup.php

    r865739 r930519  
    185185            $taxonomy = ProductCategory::$taxon;
    186186            $terms = get_terms( $taxonomy, array('hide_empty' => 0,'fields'=>'ids') );
    187             wp_update_term_count_now( $terms, $taxonomy );
     187            if ( ! empty($terms) )
     188                wp_update_term_count_now( $terms, $taxonomy );
    188189        }
    189190
  • shopp/trunk/core/flow/Storefront.php

    r905841 r930519  
    361361     * @return void
    362362     **/
    363     public function maintenance ( string $template ) {
     363    public function maintenance ( $template ) {
    364364        // Only run if in maintenance mode
    365365        if ( ! is_shopp_page() ) return $template;
     
    410410     * @return string The output of the templates
    411411     **/
    412     public function pages ( string $template ) {
     412    public function pages ( $template ) {
    413413        // Catch smart collection pages
    414414        if ( is_shopp_collection() )
     
    432432    }
    433433
    434     public function collections ( string $template ) {
     434    public function collections ( $template ) {
    435435        if ( ! is_shopp_collection() ) return $template;
    436436
     
    10181018    }
    10191019
    1020     public function autowrap ( string $content ) {
     1020    public function autowrap ( $content ) {
    10211021        if ( ! in_array(get_the_ID(), $this->shortcoded) ) return $content;
    10221022        return ShoppStorefront::wrapper($content);
     
    10311031     * @return string The template file being loaded
    10321032     **/
    1033     public static function intemplate ( string $template = null ) {
     1033    public static function intemplate ( $template = null ) {
    10341034        if ( isset($template) )
    10351035            self::$template = basename($template);
     
    10481048     * @return string The wrapped markup
    10491049     **/
    1050     static function wrapper ( string $string ) {
    1051 
    1052         $classes = array('shopp_page');
     1050    static function wrapper ( $string ) {
     1051
     1052        $classes = array('shoppage', 'shopp_page');
    10531053
    10541054        $views = array('list', 'grid');
  • shopp/trunk/core/flow/System.php

    r905841 r930519  
    137137
    138138        $sub = 'settings';
     139        $term_recount = false;
    139140        if (shopp_setting_enabled('shipping')) $sub = 'rates';
    140141        if ( isset($_GET['sub']) && in_array( $_GET['sub'],array_keys($this->subscreens) ) )
     
    660661        else $gateways = explode(',', $active_gateways);
    661662
    662         $gateways = array_filter($gateways, create_function('$g', 'return class_exists($g, false);'));
     663        $gateways = array_filter($gateways, array($Gateways, 'moduleclass'));
    663664
    664665        if ( ! empty($_GET['delete']) ) {
  • shopp/trunk/core/flow/Warehouse.php

    r905841 r930519  
    6969            shopp_enqueue_script('search-select');
    7070            shopp_enqueue_script('shopp-swfupload-queue');
     71
    7172            do_action('shopp_product_editor_scripts');
    7273            add_action('admin_head',array(&$this,'layout'));
     
    7778        }
    7879
    79         if ('inventory' == $this->view && 'on' == shopp_setting('inventory'))
     80        if ( 'inventory' == $this->view && shopp_setting_enabled('inventory') )
    8081            do_action('shopp_inventory_manager_scripts');
    8182
    82         add_action('load-' . $this->screen, array($this,'workflow'));
     83        add_action('load-' . $this->screen, array($this, 'workflow'));
    8384
    8485        do_action('shopp_product_admin_scripts');
    8586
    86         // Load the search model for indexing
    87         if (!class_exists('ContentParser'))
    88             require(SHOPP_MODEL_PATH.'/Search.php');
    8987        new ContentParser();
    90         add_action('shopp_product_saved',array(&$this,'index'),99,1);
     88        add_action('shopp_product_saved', array($this, 'index'), 99, 1);
    9189    }
    9290
     
    10199     **/
    102100    public function admin () {
    103         if (!empty($_GET['id'])) $this->editor();
    104         else {
     101        if ( ! empty($_GET['id']) ) {
     102            $this->editor();
     103        } else {
    105104            $this->manager();
    106105
    107106            global $Products;
    108             if ($Products->total == 0) return;
     107            if ( 0 == $Products->total ) return;
    109108
    110109            // Save workflow list
     
    134133            'duplicate' => false,
    135134            'next' => false
    136             );
    137         $args = array_merge($defaults,$_REQUEST);
    138         extract($args,EXTR_SKIP);
    139 
    140         if (!is_array($selected)) $selected = array($selected);
    141 
    142         if (!defined('WP_ADMIN') || !isset($page)
    143             || $page != $this->Admin->pagename('products'))
     135        );
     136        $args = array_merge($defaults, $_REQUEST);
     137        extract($args, EXTR_SKIP);
     138
     139        if ( ! is_array($selected) ) $selected = array($selected);
     140
     141        if ( ! defined('WP_ADMIN') || ! isset($page)
     142            || $this->Admin->pagename('products') != $page )
    144143                return false;
    145144
    146145        $adminurl = admin_url('admin.php');
    147146
    148         if ($page == $this->Admin->pagename('products') && ($action !== false || isset($_GET['delete_all']))) {
     147        if ( $this->Admin->pagename('products') == $page && ( false !== $action || isset($_GET['delete_all']) ) ) {
    149148            if (isset($_GET['delete_all'])) $action = 'emptytrash';
    150149            switch ($action) {
     
    261260        );
    262261
    263         $args = array_merge($defaults,$_GET);
     262        $args = array_merge($defaults, $_GET);
    264263        if ( false !== ( $user_per_page = get_user_option($per_page_option['option']) ) ) $args['per_page'] = $user_per_page;
    265         extract($args,EXTR_SKIP);
    266 
    267         $url = add_query_arg(array_merge($_GET,array('page'=>$this->Admin->pagename('products'))),admin_url('admin.php'));
     264        extract($args, EXTR_SKIP);
     265
     266        $url = ShoppAdminController::url($_GET);
    268267
    269268        $subs = array(
    270             'all' =>        array('label' => __('All','Shopp'),         'where'=>array("p.post_status!='trash'")),
    271             'published' =>  array('label' => __('Published','Shopp'),   'where'=>array("p.post_status='publish'")),
    272             'drafts' =>     array('label' => __('Drafts','Shopp'),      'where'=>array("p.post_status='draft'")),
    273             'onsale' =>     array('label' => __('On Sale','Shopp'),     'where'=>array("s.sale='on' AND p.post_status != 'trash'")),
    274             'featured' =>   array('label' => __('Featured','Shopp'),    'where'=>array("s.featured='on' AND p.post_status != 'trash'")),
    275             'bestselling'=> array('label' => __('Bestselling','Shopp'), 'where'=>array("p.post_status!='trash'",BestsellerProducts::threshold()." < s.sold"),'order' => 'bestselling'),
    276             'inventory' =>  array('label' => __('Inventory','Shopp'),   'where'=>array("s.inventory='on' AND p.post_status != 'trash'")),
    277             'trash' =>      array('label' => __('Trash','Shopp'),       'where'=>array("p.post_status='trash'"))
     269            'all' =>        array('label' => Shopp::__('All'),         'where' => array("p.post_status!='trash'")),
     270            'published' =>  array('label' => Shopp::__('Published'),   'where' => array("p.post_status='publish'")),
     271            'drafts' =>     array('label' => Shopp::__('Drafts'),      'where' => array("p.post_status='draft'")),
     272            'onsale' =>     array('label' => Shopp::__('On Sale'),     'where' => array("s.sale='on' AND p.post_status != 'trash'")),
     273            'featured' =>   array('label' => Shopp::__('Featured'),    'where' => array("s.featured='on' AND p.post_status != 'trash'")),
     274            'bestselling'=> array('label' => Shopp::__('Bestselling'), 'where' => array("p.post_status!='trash'", BestsellerProducts::threshold() . " < s.sold"),'order' => 'bestselling'),
     275            'inventory' =>  array('label' => Shopp::__('Inventory'),   'where' => array("s.inventory='on' AND p.post_status != 'trash'")),
     276            'trash' =>      array('label' => Shopp::__('Trash'),       'where' => array("p.post_status='trash'"))
    278277        );
    279278
    280         if (!shopp_setting_enabled('inventory')) unset($subs['inventory']);
    281 
    282         switch ($view) {
     279        if ( ! shopp_setting_enabled('inventory') ) unset($subs['inventory']);
     280
     281        switch ( $view ) {
    283282            case 'inventory':
    284283                if ( shopp_setting_enabled('inventory') ) $is_inventory = true;
     
    291290
    292291
    293         if ($is_inventory) $per_page = 50;
     292        if ( $is_inventory ) $per_page = 50;
    294293        $pagenum = absint( $paged );
    295         $start = ($per_page * ($pagenum-1));
    296 
    297         $where = $subs[$this->view]['where'];
    298 
    299         if (!empty($s)) {
    300             $SearchResults = new SearchResults(array('search'=>$s,'published'=>'off','paged'=>-1));
     294        $start = ( $per_page * ( $pagenum - 1 ) );
     295
     296        $where = $subs[ $this->view ]['where'];
     297
     298        if ( ! empty($s) ) {
     299            $SearchResults = new SearchResults(array('search' => $s, 'nostock' => 'on', 'published' => 'off', 'paged' => -1));
    301300            $SearchResults->load();
    302301            $ids = array_keys($SearchResults->products);
    303             $where[] = "p.ID IN (".join(',',$ids).")";
    304         }
    305 
    306         if (!empty($cat)) {
     302            $where[] = "p.ID IN (" . join(',', $ids) . ")";
     303        }
     304
     305        if ( ! empty($cat) ) {
    307306            global $wpdb;
    308             $joins[$wpdb->term_relationships] = "INNER JOIN $wpdb->term_relationships AS tr ON (p.ID=tr.object_id)";
    309             $joins[$wpdb->term_taxonomy] = "INNER JOIN $wpdb->term_taxonomy AS tt ON (tr.term_taxonomy_id=tt.term_taxonomy_id AND tt.term_id=$cat)";
     307            $joins[ $wpdb->term_relationships ] = "INNER JOIN $wpdb->term_relationships AS tr ON (p.ID=tr.object_id)";
     308            $joins[ $wpdb->term_taxonomy ] = "INNER JOIN $wpdb->term_taxonomy AS tt ON (tr.term_taxonomy_id=tt.term_taxonomy_id AND tt.term_id=$cat)";
    310309            if (-1 == $cat) {
    311                 unset($joins[$wpdb->term_taxonomy]);
    312                 $joins[$wpdb->term_relationships] = "LEFT JOIN $wpdb->term_relationships AS tr ON (p.ID=tr.object_id)";
     310                unset($joins[ $wpdb->term_taxonomy ]);
     311                $joins[ $wpdb->term_relationships ] = "LEFT JOIN $wpdb->term_relationships AS tr ON (p.ID=tr.object_id)";
    313312                $where[] = 'tr.object_id IS NULL';
    314313            }
     
    316315
    317316        // Detect custom taxonomies
    318         $taxonomies = array_intersect(get_object_taxonomies(ShoppProduct::$posttype),array_keys($_GET));
     317        $taxonomies = array_intersect(get_object_taxonomies(ShoppProduct::$posttype), array_keys($_GET));
    319318        if ( ! empty($taxonomies) ) {
    320319            foreach ($taxonomies as $n => $taxonomy) {
    321320                global $wpdb;
    322                 $term = get_term_by('slug',$_GET[ $taxonomy ],$taxonomy);
     321                $term = get_term_by('slug', $_GET[ $taxonomy ], $taxonomy);
    323322                if ( ! empty($term->term_id) ) {
    324                     $joins[$wpdb->term_relationships.'_'.$n] = "INNER JOIN $wpdb->term_relationships AS tr$n ON (p.ID=tr$n.object_id)";
    325                     $joins[$wpdb->term_taxonomy.'_'.$n] = "INNER JOIN $wpdb->term_taxonomy AS tt$n ON (tr$n.term_taxonomy_id=tt$n.term_taxonomy_id AND tt$n.term_id=$term->term_id)";
     323                    $joins[ $wpdb->term_relationships . '_' . $n ] = "INNER JOIN $wpdb->term_relationships AS tr$n ON (p.ID=tr$n.object_id)";
     324                    $joins[ $wpdb->term_taxonomy . '_' . $n ] = "INNER JOIN $wpdb->term_taxonomy AS tt$n ON (tr$n.term_taxonomy_id=tt$n.term_taxonomy_id AND tt$n.term_id=$term->term_id)";
    326325                }
    327326            }
     
    329328
    330329        if ( ! empty($sl) && shopp_setting_enabled('inventory') ) {
    331             switch($sl) {
     330            switch( $sl ) {
    332331                case "ns":
    333                     foreach ($where as &$w) $w = str_replace("s.inventory='on'","s.inventory='off'",$w);
     332                    foreach ( $where as &$w ) $w = str_replace("s.inventory='on'", "s.inventory='off'", $w);
    334333                    $where[] = "s.inventory='off'";
    335334                    break;
     
    339338                case "ls":
    340339                    $ls = shopp_setting('lowstock_level');
    341                     if (empty($ls)) $ls = '0';
     340                    if ( empty($ls) ) $ls = '0';
    342341                    $where[] = "(s.inventory='on' AND s.lowstock != 'none')";
    343342                    break;
     
    353352        $ps = ShoppDatabaseObject::tablename(ProductSummary::$table);
    354353
    355         $orderdirs = array('asc','desc');
    356         if (in_array($order,$orderdirs)) $orderd = strtolower($order);
     354        $orderdirs = array('asc', 'desc');
     355        if ( in_array($order, $orderdirs) ) $orderd = strtolower($order);
    357356        else $orderd = 'asc';
    358357
    359         if (isset($subs[$this->view]['order'])) $order = $subs[$this->view]['order'];
     358        if ( isset($subs[ $this->view ]['order']) ) $order = $subs[ $this->view ]['order'];
    360359
    361360        $ordercols = '';
    362         switch ($orderby) {
     361        switch ( $orderby ) {
    363362            case 'name': $order = 'title'; if ('desc' == $orderd) $order = 'reverse'; break;
    364363            case 'price': $order = 'lowprice'; if ('desc' == $orderd) $order = 'highprice'; break;
     
    371370        }
    372371
    373         if (in_array($this->view,array('onsale','featured','inventory')))
    374             $joins[$ps] = "INNER JOIN $ps AS s ON p.ID=s.product";
     372        if ( in_array($this->view, array('onsale', 'featured', 'inventory')) )
     373            $joins[ $ps ] = "INNER JOIN $ps AS s ON p.ID=s.product";
    375374
    376375        $loading = array(
    377             'where' => $where,
    378             'joins' => $joins,
    379             'limit'=>"$start,$per_page",
    380             'load' => array('categories','coverimages'),
     376            'where'     => $where,
     377            'joins'     => $joins,
     378            'limit'     => "$start,$per_page",
     379            'load'      => array('categories', 'coverimages'),
    381380            'published' => false,
    382             'order' => $order,
    383             'nostock' => true,
    384             // 'debug' => true
     381            'order'     => $order,
     382            'nostock'   => true,
     383            // 'debug'  => true
    385384        );
    386385
     
    390389        }
    391390
    392         if ($is_inventory) { // Override for inventory products
     391        if ( $is_inventory ) { // Override for inventory products
    393392            $where[] = "(pt.context='product' OR pt.context='variation') AND pt.type != 'N/A'";
    394393            $loading = array(
    395                 'columns' => "pt.id AS stockid,IF(pt.context='variation',CONCAT(p.post_title,': ',pt.label),p.post_title) AS post_title,pt.sku AS sku,pt.stock AS stock",
    396                 'joins' => array_merge(array($pt => "LEFT JOIN $pt AS pt ON p.ID=pt.product"),$joins),
    397                 'where' => $where,
    398                 'groupby' => 'pt.id',
    399                 'orderby' => str_replace('s.', 'pt.', $ordercols),
    400                 'limit'=>"$start,$per_page",
    401                 'nostock' => true,
     394                'columns'   => "pt.id AS stockid,IF(pt.context='variation',CONCAT(p.post_title,': ',pt.label),p.post_title) AS post_title,pt.sku AS sku,pt.stock AS stock",
     395                'joins'     => array_merge(array($pt => "LEFT JOIN $pt AS pt ON p.ID=pt.product"),$joins),
     396                'where'     => $where,
     397                'groupby'   => 'pt.id',
     398                'orderby'   => str_replace('s.', 'pt.', $ordercols),
     399                'limit'     => "$start,$per_page",
     400                'nostock'   => true,
    402401                'published' => false,
    403                 // 'debug' => true
     402                // 'debug'  => true
    404403            );
    405404        }
    406405
    407406        // Override loading product meta and limiting by pagination in the workflow list
    408         if ($workflow) {
     407        if ( $workflow ) {
    409408            unset($loading['limit']);
    410409            $loading['ids'] = true;
     
    418417        // Overpagination protection, redirect to page 1 if the requested page doesn't exist
    419418        $num_pages = ceil($this->products->total / $per_page);
    420         if ($paged > 1 && $paged > $num_pages) Shopp::redirect( add_query_arg('paged', null, $url ) );
     419        if ( $paged > 1 && $paged > $num_pages ) Shopp::redirect( add_query_arg('paged', null, $url ) );
    421420
    422421        // Return a list of product keys for workflow list requests
    423         if ($workflow) return $this->products->worklist();
     422        if ( $workflow ) return $this->products->worklist();
    424423
    425424        // Get sub-screen counts
    426425        $subcounts = wp_cache_get('shopp_product_subcounts','shopp_admin');
    427         if ($subcounts) {
     426        if ( $subcounts ) {
    428427            foreach ($subcounts as $name => $total)
    429                 if (isset($subs[$name])) $subs[$name]['total'] = $total;
     428                if ( isset($subs[ $name ]) ) $subs[ $name ]['total'] = $total;
    430429        } else {
    431430            $subcounts = array();
    432             foreach ($subs as $name => &$subquery) {
     431            foreach ( $subs as $name => &$subquery ) {
    433432                $subquery['total'] = 0;
    434433                $query = array(
     
    439438                );
    440439
    441                 $query = array_merge($query,$subquery);
     440                $query = array_merge($query, $subquery);
    442441                $query['where'][] = "p.post_type='shopp_product'";
    443442
    444                 if (in_array($name,array('onsale','bestselling','featured','inventory')))
    445                     $query['joins'][$ps] = "INNER JOIN $ps AS s ON p.ID=s.product";
     443                if ( in_array($name, array('onsale', 'bestselling', 'featured', 'inventory')) )
     444                    $query['joins'][ $ps ] = "INNER JOIN $ps AS s ON p.ID=s.product";
    446445
    447446                $query = sDB::select($query);
    448                 $subquery['total'] = sDB::query($query,'auto','col','total');
    449                 $subcounts[$name] = $subquery['total'];
    450             }
    451             wp_cache_set('shopp_product_subcounts',$subcounts,'shopp_admin');
     447                $subquery['total'] = sDB::query($query, 'auto', 'col', 'total');
     448                $subcounts[ $name ] = $subquery['total'];
     449            }
     450            wp_cache_set('shopp_product_subcounts', $subcounts, 'shopp_admin');
    452451        }
    453452
     
    526525        }
    527526
    528         if ( 'off' == shopp_setting('inventory') ) unset($subs['inventory']);
     527        if ( 'off' == shopp_setting('inventory') ) unset($this->subs['inventory']);
    529528        switch ($view) {
    530529            case 'inventory':
     
    686685        $post_type = ShoppProduct::posttype();
    687686
     687        // Re-index menu options to maintain order in JS #2930
     688        foreach ( $Product->options as &$types ) {
     689            foreach ( $types as &$menu )
     690                $menu['options'] = array_values($menu['options']);
     691        }
     692
    688693        do_action('add_meta_boxes', ShoppProduct::$posttype, $Product);
    689694        do_action('add_meta_boxes_' . ShoppProduct::$posttype, $Product);
  • shopp/trunk/core/library/Catalog.php

    r905841 r930519  
    109109     * @return object The loaded Category object
    110110     **/
    111     static function load_collection ( string $slug, array $options = array() ) {
     111    static function load_collection ( $slug, array $options = array() ) {
    112112        $Shopp = Shopp::object();
    113113
  • shopp/trunk/core/library/Core.php

    r865739 r930519  
    327327     * @return string The formatted localized date/time
    328328     **/
    329     public static function _d ( string $format, $timestamp = null ) {
     329    public static function _d ( $format, $timestamp = null ) {
    330330
    331331        $tokens = array(
     
    373373     * @return void
    374374     **/
    375     public static function _jse ( string $text) {
     375    public static function _jse ( $text) {
    376376        echo json_encode(Shopp::translate($text));
    377377    }
     
    15381538     * @return array Formatting options list
    15391539     **/
    1540     public static function scan_money_format ( string $format ) {
     1540    public static function scan_money_format ( $format ) {
    15411541        $f = array(
    15421542            'cpos' => true,
     
    20532053     * @return string Prefixed template file
    20542054     **/
    2055     public static function template_prefix ( string $name ) {
     2055    public static function template_prefix ( $name ) {
    20562056        return apply_filters('shopp_template_directory', 'shopp') . '/' . $name;
    20572057    }
     
    22762276     * @return void Description...
    22772277     **/
    2278     public function trim_deep ( $value ) {
     2278    public static function trim_deep ( $value ) {
    22792279
    22802280        if ( is_object($value) ) {
  • shopp/trunk/core/library/DB.php

    r905841 r930519  
    13331333     * @return mixed
    13341334     **/
    1335     public function tag ( string $property, array $options = array() ) {
     1335    public function tag ( $property, array $options = array() ) {
    13361336        $options = array_merge( array('return' => true), shopp_parse_options($options) );
    13371337        return shopp($this, $property, $options);
  • shopp/trunk/core/library/Error.php

    r831831 r930519  
    8787    }
    8888
    89     public function reporting ( integer $reporting = null ) {
     89    public function reporting ( $reporting = null ) {
    9090        if ( isset($reporting) ) $this->reporting = $reporting;
    9191        return $this->reporting;
     
    117117     * @return array A list of errors
    118118     **/
    119     public function get ( integer $level = null ) {
     119    public function get ( $level = null ) {
    120120        if ( is_null($level) ) $level = SHOPP_DEBUG_ERR;
    121121
     
    136136     * @return array A list of errors
    137137     **/
    138     public function level ( integer $level = null ) {
     138    public function level ( $level = null ) {
    139139        if ( is_null($level) ) $level = SHOPP_ALL_ERR;
    140140
     
    154154     * @return ShoppError The error object
    155155     **/
    156     public function code ( string $code ) {
     156    public function code ( $code ) {
    157157        if ( ! empty($code) && isset($this->errors[ $code ]) )
    158158            return $this->errors[ $code ];
     
    168168     * @return array A list of errors
    169169     **/
    170     public function source ( string $source ) {
     170    public function source ( $source ) {
    171171        if ( empty($source) ) return array();
    172172
     
    186186     * @return void
    187187     **/
    188     public function exist ( integer $level = null ) {
     188    public function exist ( $level = null ) {
    189189        if ( is_null($level) ) $level = SHOPP_DEBUG_ERR;
    190190
     
    445445     * @return integer The logging level
    446446     **/
    447     public function loglevel ( integer $level = null ) {
     447    public function loglevel ( $level = null ) {
    448448        if ( isset($level) ) $this->loglevel = $level;
    449449        return $this->loglevel;
     
    607607        $_[] = 'To: ' . $this->recipients;
    608608        $_[] = 'Subject: ' . __('Shopp Notification', 'Shopp');
     609        $_[] = 'Content-type: text/html';
     610
    609611        $_[] = '';
    610612        $_[] = __('This is an automated notification message generated by the Shopp installation at ' . get_bloginfo('url') . '.', 'Shopp');
  • shopp/trunk/core/library/Framework.php

    r831831 r930519  
    4040     * @return mixed Returns the entry
    4141     **/
    42     public function &add ( string $key, $entry ) {
     42    public function &add ( $key, $entry ) {
    4343        $this->_list[$key] = $entry;
    4444        $this->_added = $key;
     
    5555     * @return The added entry or false if no added entries
    5656     **/
    57     public function added ( string $key = null ) {
     57    public function added ( $key = null ) {
    5858        if ( ! is_null($key) && $this->exists($key) )
    5959            $this->_added = $key;
     
    104104     * @return boolean True if successful, false otherwise
    105105     **/
    106     public function update ( string $key, $entry ) {
     106    public function update ( $key, $entry ) {
    107107        if ( ! $this->exists($key) ) return false;
    108108        if ( is_array($this->_list[ $key ]) && is_array($entry) )
     
    431431    protected $defaults = array();
    432432
    433     public function form ( string $key = null, boolean $latest = null ) {
     433    public function form ( $key = null, boolean $latest = null ) {
    434434
    435435        if ( true === $latest ) $this->updateform();
  • shopp/trunk/core/library/Loader.php

    r905841 r930519  
    444444    'ordertotals' => '/model/Totals.php',
    445445    'paycard' => '/model/Gateway.php',
     446    'paymenttypesreport' => '/ui/reports/payment-types.php',
    446447    'porterstemmer' => '/model/Search.php',
    447448    'postcodemapping' => '/model/Address.php',
  • shopp/trunk/core/library/Session.php

    r831831 r930519  
    2828    public $secure = false;
    2929
     30    const PHP_SESSION = '__php_session_';
     31    const PHP_EXPIRES = '__php_session_expires_';
     32
    3033    /**
    3134     * The session manager constructor
     
    125128                if ( empty($key) && ! is_ssl() ) Shopp::redirect( Shopp::force_ssl( Shopp::raw_request_url(), true ) );
    126129
     130                $this->secured(true); // Maintain session security
     131
    127132                $readable = sDB::query("SELECT AES_DECRYPT('" .
    128133                                        mysql_real_escape_string(
     
    151156        do_action('shopp_session_load');
    152157
    153         // Read standard session data
    154         if ( @file_exists("$this->path/sess_$id") )
    155             return (string) @file_get_contents("$this->path/sess_$id");
     158        // Read PHP session data from WP
     159        if ( $php = get_option(self::PHP_SESSION . $id) )
     160            return (string) $php;
    156161
    157162        return $loaded;
     
    173178            trigger_error("Could not clear session data.");
    174179
    175         // Handle clean-up of file storage sessions
    176         if ( is_writable("$this->path/sess_$id") )
    177             @unlink($file);
     180        // Handle clean-up of PHP sessions
     181        delete_option(self::PHP_SESSION . $id);
    178182
    179183        unset($this->session, $this->ip, $this->data);
     
    217221
    218222        // Save standard session data for compatibility
    219         if ( ! empty($session) )
    220             return false === file_put_contents("$this->path/sess_$id",$session) ? false : true;
     223        if ( ! empty($session) ) {
     224            $sessionid = self::PHP_SESSION . $id;
     225            $exists = get_option($sessionid);
     226
     227            $expiresid = self::PHP_EXPIRES . $id;
     228            $lifetime = time() + (int) ini_get('session.gc_maxlifetime');
     229            $expires = get_option($expiresid);
     230            if ( false == $expiresid )
     231                add_option($expiresid, $lifetime, '', 'no' );
     232            else update_option($expiresid, $lifetime);
     233
     234            if ( false === $exists ) // Add new global session data, do not autoload
     235                return add_option($sessionid, $session, '', 'no');
     236            return update_option($sessionid, $session);
     237        }
    221238
    222239        return true;
     
    244261            trigger_error("Could not delete cached session data.");
    245262
    246         // Garbage collection for file-system sessions
    247         if( $dh = opendir($this->path) ) {
    248 
    249             while( ( $file = readdir($dh) ) !== false ) {
    250                 if ( false === strpos($file, 'sess_') ) continue;
    251 
    252                 $file = $this->path . "/$file";
    253 
    254                 if ( filemtime($file) + $lifetime < time() && is_writable($file) ) {
    255                     if ( @unlink($file) === false ) {
    256                         break;
    257                     }
    258                 }
    259             }
    260 
    261             closedir($dh);
    262         }
     263        // Garbage collection for PHP sessions
     264        global $wpdb;
     265        $time = time();
     266        $session = self::PHP_SESSION;
     267        $expires = self::PHP_EXPIRES;
     268
     269        sDB::query("DELETE FROM $wpdb->options AS t1 JOIN {$wpdb->options} AS t2 ON t2.option_name = replace(t1.option_name, '_expires', '')
     270                WHERE (t1.option_name LIKE '$session%' OR t1.option_name LIKE '$expires %') AND t1.option_value < '$time'");
    263271
    264272        return true;
     
    307315    }
    308316
    309 
    310317}
  • shopp/trunk/core/library/Shopp.php

    r905841 r930519  
    121121     **/
    122122    public function constants () {
    123         if ( ! defined('SHOPP_VERSION') )               define( 'SHOPP_VERSION', ShoppVersion::release() );
    124         if ( ! defined('SHOPP_GATEWAY_USERAGENT') )     define( 'SHOPP_GATEWAY_USERAGENT', ShoppVersion::agent() );
     123        if ( ! defined('SHOPP_VERSION') )              define( 'SHOPP_VERSION', ShoppVersion::release() );
     124        if ( ! defined('SHOPP_GATEWAY_USERAGENT') )    define( 'SHOPP_GATEWAY_USERAGENT', ShoppVersion::agent() );
    125125
    126126        // @deprecated
    127         if ( ! defined('SHOPP_HOME') )                  define( 'SHOPP_HOME', ShoppSupport::HOMEPAGE );
    128         if ( ! defined('SHOPP_CUSTOMERS') )             define( 'SHOPP_CUSTOMERS', ShoppSupport::FORUMS);
    129         if ( ! defined('SHOPP_DOCS') )                  define( 'SHOPP_DOCS', ShoppSupport::DOCS );
     127        if ( ! defined('SHOPP_HOME') )                 define( 'SHOPP_HOME', ShoppSupport::HOMEPAGE );
     128        if ( ! defined('SHOPP_CUSTOMERS') )            define( 'SHOPP_CUSTOMERS', ShoppSupport::FORUMS);
     129        if ( ! defined('SHOPP_DOCS') )                 define( 'SHOPP_DOCS', ShoppSupport::DOCS );
    130130
    131131        // Helper for line break output
    132         if ( ! defined('BR') )                          define('BR', '<br />');
     132        if ( ! defined('BR') )                         define('BR', '<br />');
    133133
    134134        // Overrideable config macros
    135         if ( ! defined('SHOPP_NOSSL') )                 define('SHOPP_NOSSL', false);                   // Require SSL to protect transactions, overrideable for development
    136         if ( ! defined('SHOPP_PREPAYMENT_DOWNLOADS') )  define('SHOPP_PREPAYMENT_DOWNLOADS', false);    // Require payment capture granting access to downloads
    137         if ( ! defined('SHOPP_SESSION_TIMEOUT') )       define('SHOPP_SESSION_TIMEOUT', 172800);        // Sessions live for 2 days
    138         if ( ! defined('SHOPP_CART_EXPIRES') )          define('SHOPP_CART_EXPIRES', 1209600);          // Carts are stashed for up to 2 weeks
    139         if ( ! defined('SHOPP_QUERY_DEBUG') )           define('SHOPP_QUERY_DEBUG', false);             // Debugging queries is disabled by default
    140         if ( ! defined('SHOPP_GATEWAY_TIMEOUT') )       define('SHOPP_GATEWAY_TIMEOUT', 10);            // Gateway connections timeout after 10 seconds
    141         if ( ! defined('SHOPP_SHIPPING_TIMEOUT') )      define('SHOPP_SHIPPING_TIMEOUT', 10);           // Shipping provider connections timeout after 10 seconds
    142         if ( ! defined('SHOPP_TEMP_PATH') )             define('SHOPP_TEMP_PATH', sys_get_temp_dir());  // Use the system defined temporary directory
    143         if ( ! defined('SHOPP_ADDONS') )                define('SHOPP_ADDONS', WP_CONTENT_DIR . '/shopp-addons');   // A configurable directory to keep Shopp addons
    144         if ( ! defined('SHOPP_NAMESPACE_TAXONOMIES') )  define('SHOPP_NAMESPACE_TAXONOMIES', true);     // Add taxonomy namespacing for permalinks /shop/category/category-name, /shopp/tag/tag-name
     135        if ( ! defined('SHOPP_NOSSL') )                define('SHOPP_NOSSL', false);                             // Require SSL to protect transactions, overrideable for development
     136        if ( ! defined('SHOPP_PREPAYMENT_DOWNLOADS') ) define('SHOPP_PREPAYMENT_DOWNLOADS', false);              // Require payment capture granting access to downloads
     137        if ( ! defined('SHOPP_SESSION_TIMEOUT') )      define('SHOPP_SESSION_TIMEOUT', 172800);                  // Sessions live for 2 days
     138        if ( ! defined('SHOPP_CART_EXPIRES') )         define('SHOPP_CART_EXPIRES', 1209600);                    // Carts are stashed for up to 2 weeks
     139        if ( ! defined('SHOPP_QUERY_DEBUG') )          define('SHOPP_QUERY_DEBUG', false);                       // Debugging queries is disabled by default
     140        if ( ! defined('SHOPP_GATEWAY_TIMEOUT') )      define('SHOPP_GATEWAY_TIMEOUT', 10);                      // Gateway connections timeout after 10 seconds
     141        if ( ! defined('SHOPP_SHIPPING_TIMEOUT') )     define('SHOPP_SHIPPING_TIMEOUT', 10);                     // Shipping provider connections timeout after 10 seconds
     142        if ( ! defined('SHOPP_SUBMIT_TIMEOUT') )       define('SHOPP_SUBMIT_TIMEOUT', 20);                       // Order submission timeout
     143        if ( ! defined('SHOPP_TEMP_PATH') )            define('SHOPP_TEMP_PATH', sys_get_temp_dir());            // Use the system defined temporary directory
     144        if ( ! defined('SHOPP_ADDONS') )               define('SHOPP_ADDONS', WP_CONTENT_DIR . '/shopp-addons'); // A configurable directory to keep Shopp addons
     145        if ( ! defined('SHOPP_NAMESPACE_TAXONOMIES') ) define('SHOPP_NAMESPACE_TAXONOMIES', true);               // Add taxonomy namespacing for permalinks /shop/category/category-name, /shopp/tag/tag-name
    145146
    146147    }
  • shopp/trunk/core/library/Version.php

    r905841 r930519  
    2222
    2323    /** @type int PATCH The maintenance patch version number */
    24     const PATCH = 3;
     24    const PATCH = 4;
    2525
    2626    /** @type string PRERELEASE The prerelease designation (dev, beta, RC1) */
     
    2828
    2929    /** @type string CODENAME The release project code name */
    30     const CODENAME = 'Olympus Mons';
     30    const CODENAME = 'Sojourner';
    3131
    3232    /** @type int DB The database schema version */
  • shopp/trunk/core/model/Asset.php

    r865739 r930519  
    227227        'scaling' => array('all', 'matte', 'crop', 'width', 'height'),
    228228        'sharpen' => 0,
    229         'quality' => 80
     229        'quality' => 80,
     230        'fill' => 16777215
    230231    );
    231232
     
    400401            self::SCALE => ( isset($args[ self::SCALE ]) ) ? (int) $args[ self::SCALE ] : 0,
    401402            self::SHARPEN => ( isset($args[ self::SHARPEN ]) ) ? (int) $args[ self::SHARPEN ] : self::$defaults['sharpen'],
    402             self::QUALITY => ( isset($args[ self::QUALITY ]) ) ? (int) $args[ self::QUALITY ] : self::$defaults['quality']
     403            self::QUALITY => ( isset($args[ self::QUALITY ]) ) ? (int) $args[ self::QUALITY ] : self::$defaults['quality'],
     404            self::FILL => ( isset($args[ self::FILL ]) ) ? (int) $args[ self::FILL ] : self::$defaults['fill']
    403405        );
    404406
     
    604606
    605607        ignore_user_abort(true);
    606         ob_end_flush(); // Don't use the PHP output buffer
     608        while(@ob_end_flush()); // Don't use the PHP output buffer
    607609
    608610        $this->send();  // Send the file data using the storage engine
     
    704706     * @return string The option name
    705707     **/
    706     public function fit ( integer $setting ) {
     708    public function fit ( $setting ) {
    707709        if ( isset(self::$fittings[ $setting ]) )
    708710            return self::$fittings[ $setting ];
     
    718720     * @return integer The option value
    719721     **/
    720     public function quality ( integer $setting ) {
     722    public function quality ( $setting ) {
    721723        if ( isset(self::$qualities[ $setting ])  )
    722724            return self::$qualities[ $setting ];
  • shopp/trunk/core/model/Cart.php

    r905841 r930519  
    209209                if ( empty($prices) ) $prices[] = false; // Use default price for product if none provided
    210210                foreach($prices as $price)
    211                     $result = $this->additem($quantity, $Product, $price, $category, $data, $addons);
     211                    $result = $this->additem($quantity, $Product, $price, $category, apply_filters('shopp_cartitem_data', $data), $addons);
     212
    212213            }
    213214        }
     
    304305        }
    305306
     307        do_action('shopp_cart_before_add_item', array($NewItem) );
     308
    306309        $id = $NewItem->fingerprint();
    307310
     
    344347     * @return boolean
    345348     **/
    346     public function rmvitem ( string $id ) {
     349    public function rmvitem ( $id ) {
    347350        $Item = $this->get($id);
    348351
     
    486489     * @return boolean
    487490     **/
    488     public function change ( string $item, integer $product, integer $pricing, array $addons = array() ) {
     491    public function change ( $item, $product, $pricing, array $addons = array() ) {
    489492
    490493        // Don't change anything if everything is the same
     
    615618
    616619        $items = $this->keys(); // Use local array for iterating
    617         foreach ( $items as $itemid ) { // Allow other code to interate the cart in this loop
     620        foreach ( $items as $itemid ) { // Allow other code to iterate the cart in this loop
    618621            $Item = $this->get($itemid);
    619622            $Item->totals();
     
    652655     * @return float The total amount for the register
    653656     **/
    654     public function total ( string $register = null, string $entry = null ) {
     657    public function total ( $register = null, $entry = null ) {
    655658
    656659        // Setup totals counter
     
    715718     **/
    716719    public function downloads () {
    717         return $this->filteritems('download');
     720        return $this->filteritems('downloads');
    718721    }
    719722
     
    739742     * @return boolean True if the item is of the specified type, false otherwise
    740743     **/
    741     private function filteritems ($type) {
    742         $types = array('shipped','downloads','recurring');
    743         if ( ! in_array($type,$types) ) return false;
     744    private function filteritems ( $type ) {
     745        $types = array('shipped', 'downloads', 'recurring');
     746        if ( ! in_array($type, $types) ) return false;
    744747
    745748        $this->$type = array();
    746749        foreach ($this as $key => $item) {
    747             if ( ! $item->$type ) continue;
    748             $this->{$type}[$key] = $item;
     750            $prop = rtrim($type, 's'); // No plural properties
     751            if ( ! $item->$prop ) continue;
     752            $this->{$type}[ $key ] = $item;
    749753        }
    750754
  • shopp/trunk/core/model/Collection.php

    r905841 r930519  
    14971497    }
    14981498
    1499     public static function slugs ( string $class ) {
     1499    public static function slugs ( $class ) {
    15001500        return apply_filters( 'shopp_' . strtolower($class) . '_collection_slugs', get_class_property($class, 'slugs') );
    15011501    }
     
    15041504        $this->loading = array_merge( $this->_options, $options );
    15051505
    1506         if ( isset($options['show']) )
    1507             $this->loading['limit'] = $options['show'];
     1506        if ( isset($this->loading['show']) ) {
     1507            $this->loading['limit'] = $this->loading['show'];
     1508            unset($this->loading['show']);
     1509        }
    15081510
    15091511        if ( isset($options['pagination']) )
    15101512            $this->loading['pagination'] = $options['pagination'];
    1511            
     1513
    15121514        if ( isset($options['exclude']) ) {
    1513             $exclude = $options['exclude']; 
     1515            $exclude = $options['exclude'];
    15141516
    15151517            if ( is_numeric(str_replace(',','',$exclude)) ) {
     
    15191521                $this->loading['where'][] = "tr.term_taxonomy_id NOT IN ($exclude)";
    15201522                $this->loading['where'][] = "tt.taxonomy = 'shopp_category'";
    1521             } 
     1523            }
    15221524        }
    15231525
     
    19011903        $terms = array();
    19021904
    1903         $term = get_term_by('name',$this->tag,ProductTag::$taxon);
     1905        $term = get_term_by('name', $this->tag, ProductTag::$taxon);
    19041906
    19051907        if ( false !== strpos($options['tag'], ',') ) {
     
    19111913        } else $terms[] = $term->term_id;
    19121914
     1915        if ( empty($terms) ) return;
     1916
    19131917        $this->name = isset($options['title']) ? $options['title'] : Shopp::__('Products tagged &quot;%s&quot;', $this->tag);
    19141918        $this->uri = urlencode($this->tag);
     
    19211925        $columns = 'COUNT(p.ID) AS score';
    19221926        $groupby = 'p.ID';
    1923         $order = 'score DESC';
    1924         $loading = compact('columns', 'joins', 'where', 'groupby', 'order');
     1927        $orderby = 'score DESC';
     1928        $loading = compact('columns', 'joins', 'where', 'groupby', 'orderby');
    19251929        $this->loading = array_merge($options, $loading);
     1930
    19261931    }
    19271932
     
    19731978
    19741979        // Use the current product is available
    1975         if (!empty($Product->id))
     1980        if ( ! empty($Product->id) )
    19761981            $this->product = ShoppProduct();
    19771982
     
    19992004            $where = array("p.id != {$this->product->id}");
    20002005            // Load the product's tags if they are not available
    2001             if (empty($this->product->tags))
     2006            if ( empty($this->product->tags) )
    20022007                $this->product->load_data(array('tags'));
    20032008
    2004             if (!$scope) $scope = array_keys($this->product->tags);
    2005         }
    2006         if (empty($scope)) return false;
     2009            if ( empty($scope) ) $scope = array_keys($this->product->tags);
     2010        }
     2011
     2012        if ( empty($scope) ) return false;
    20072013
    20082014        $this->name = __("Products related to","Shopp")." &quot;".stripslashes($name)."&quot;";
     
    20112017
    20122018        global $wpdb;
    2013         $joins[$wpdb->term_relationships] = "INNER JOIN $wpdb->term_relationships AS tr ON (p.ID=tr.object_id)";
    2014         $joins[$wpdb->term_taxonomy] = "INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
    2015         $where[] = "tt.term_id IN (".join(',',$scope).")";
     2019        $joins[ $wpdb->term_relationships ] = "INNER JOIN $wpdb->term_relationships AS tr ON (p.ID=tr.object_id)";
     2020        $joins[ $wpdb->term_taxonomy ] = "INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
     2021        $where[] = "tt.term_id IN (" . join(',', $scope) . ")";
    20162022        $columns = 'COUNT(p.ID) AS score';
    20172023        $groupby = 'p.ID';
    2018         $order = 'score DESC';
    2019         $loading = compact('columns','joins','where','groupby','order');
    2020         $this->loading = array_merge($options, $this->loading);
    2021 
    2022         if (isset($options['order'])) $this->loading['order'] = $options['order'];
    2023         if (isset($options['controls']) && Shopp::str_true($options['controls']))
     2024        $orderby = 'score DESC';
     2025        $loading = compact('columns', 'joins', 'where', 'groupby', 'orderby');
     2026
     2027        $this->loading = array_merge($options, $loading);
     2028
     2029        if ( isset($options['order']) ) $this->loading['order'] = $options['order'];
     2030        if ( isset($options['controls']) && Shopp::str_true($options['controls']) )
    20242031            unset($this->controls);
     2032
    20252033    }
    20262034
  • shopp/trunk/core/model/Customer.php

    r905841 r930519  
    597597            $prefix.'phone' => __('Customer\'s Phone Number','Shopp'),
    598598            $prefix.'company' => __('Customer\'s Company','Shopp'),
     599            $prefix.'type' => __('Customer Type','Shopp'),
    599600            $prefix.'marketing' => __('Customer\'s Marketing Preference','Shopp'),
    600601            // $prefix.'info' => __('Customer\'s Custom Information','Shopp'), @todo Re-enable by switching to customer meta data in 1.2
  • shopp/trunk/core/model/Discounts.php

    r905841 r930519  
    291291     * @return void
    292292     **/
    293     private function undiscount ( integer $id ) {
     293    private function undiscount ( $id ) {
    294294
    295295        if ( ! $this->exists($id) ) return false;
     
    357357     * @return string The current request
    358358     **/
    359     public function request ( string $request = null ) {
     359    public function request ( $request = null ) {
    360360
    361361        if ( isset($request) ) $this->request = $request;
     
    364364    }
    365365
    366     public function credit ( string $request = null ) {
     366    public function credit ( $request = null ) {
    367367
    368368        if ( isset($request) ) $this->credit = $request;
     
    476476     * @return boolean True if the code is applied, false otherwise
    477477     **/
    478     public function codeapplied ( string $code ) {
     478    public function codeapplied ( $code ) {
    479479        return isset( $this->codes[ strtolower($code) ]);
    480480    }
     
    912912     * @return integer The id of the discount
    913913     **/
    914     public function id ( integer $id = null ) {
     914    public function id ( $id = null ) {
    915915        if ( isset($id) ) $this->id = $id;
    916916        return $this->id;
     
    928928     * @return string The name of the discount
    929929     **/
    930     public function name ( string $name = null ) {
     930    public function name ( $name = null ) {
    931931        if ( isset($name) ) $this->name = $name;
    932932
     
    10201020     * @return string The code for the discount
    10211021     **/
    1022     public function code ( string $code = null ) {
     1022    public function code ( $code = null ) {
    10231023        if ( isset($code) ) $this->code = $code;
    10241024        return $this->code;
     
    10511051     * @return integer The ShoppOrderDiscount type
    10521052     **/
    1053     public function type ( string $type = null ) {
     1053    public function type ( $type = null ) {
    10541054        if ( isset($type) ) {
    10551055            switch ( strtolower($type) ) {
     
    10741074     * @return integer the ShoppOrderDiscount target
    10751075     **/
    1076     public function target ( string $target = null ) {
     1076    public function target ( $target = null ) {
    10771077        if ( isset($target) ) {
    10781078            switch ( strtolower($target) ) {
     
    11671167     * @return boolean True if it exists, false otherwise
    11681168     **/
    1169     public function hasitem ( string $key ) {
     1169    public function hasitem ( $key ) {
    11701170        return isset($this->items[ $key ]);
    11711171    }
  • shopp/trunk/core/model/Gateway.php

    r865739 r930519  
    518518
    519519        foreach ( $gateways as $gateway ) {
    520             if ( false !== strpos($gateway, '-') ) list($gateway, $id) = explode('-', $gateway);
    521             $upgraded = 'Shopp' . $gateway;
    522             if ( in_array($gateway, $modules) && !in_array($gateway, $this->activated) )
    523                 $this->activated[] = $this->modules[ $gateway ]->classname;
    524             // @todo Remove legacy gateway settings migrations
    525             elseif ( false === strpos($gateway, 'Shopp') && in_array($upgraded, $modules) && ! in_array($upgraded, $this->activated) )
    526                 $this->activated[] = $this->modules[ $upgraded ]->classname;
     520            $moduleclass = $this->moduleclass($gateway);
     521            if ( ! empty($moduleclass) )
     522                $this->activated[] = $moduleclass;
    527523        }
    528524
     
    618614        return sanitize_key($classname);
    619615    }
     616
     617    /**
     618     * Returns the classname of a valid module
     619     *
     620     * @since 1.3.4
     621     *
     622     * @return string|bool Class name of the module, or false if not a valid module
     623     **/
     624    public function moduleclass ( $gateway ) {
     625
     626        // Handled suffixed multi-instance gateways names (e.g. OfflinePayments-0)
     627        if ( false !== strpos($gateway, '-') )
     628            list($gateway, $id) = explode('-', $gateway);
     629
     630        // Check for namespaced and non-namespaced derivitives
     631        $namespaced = 'Shopp' . $gateway;
     632
     633        $module = false;
     634        if ( isset($this->modules[ $namespaced ]) ) $module = $this->modules[ $namespaced ];
     635        elseif ( isset($this->modules[ $gateway ]) ) $module = $this->modules[ $gateway ];
     636
     637        // If no valid module exists return false, otherwise provide the class name
     638        if ( empty($module) ) return false;
     639        else return $module->classname;
     640
     641    }
     642
    620643
    621644} // END class GatewayModules
     
    870893     * @return string The masked PAN value
    871894     **/
    872     public static function mask ( $value, string $mask = null ) {
     895    public static function mask ( $value, $mask = null ) {
    873896        if ( empty($value) ) return $value;
     897
     898        if ( ! self::checksum($value) ) return $value;
    874899
    875900        if ( ! isset($mask) ) $mask = 'X';
  • shopp/trunk/core/model/Image.php

    r821385 r930519  
    3030    private $dy = 0;
    3131    private $alpha = false;
     32    private $complexity = false;
    3233
    3334    public function __construct ( $data, $width, $height ) {
     
    200201
    201202    /**
    202      * Performs an unsharp mask on the processed image
    203      *
    204      * Photoshop-like unsharp mask processing using image convolution.
    205      * Original algorithm by Torstein Hansi
    206      *
    207      * @author Jonathan Davis
    208      * @since 1.0
    209      * @version 2.1.1
    210      * @copyright Torstein Hansi <thoensi_at_netcom_dot_no>, July 2003
    211      *
     203     * Calculate the visual complexity of the image
     204     *
     205     * Provides a fast method for determining visual complexity of
     206     * an image by comparing a raw image size to jpeg image file size.
     207     * The JPEG compression algorithm is really good at compressing
     208     * repetitive areas (low detail) areas of an image and gives us
     209     * a good enough indicator for the complexity in an image.
     210     *
     211     * @author Jonathan Davis
     212     * @since 1.3.4
     213     *
     214     * @return float A complexity amount (jpeg size to raw gd size)
     215     **/
     216    public function complexity () {
     217
     218        $image =& $this->src->image;
     219
     220        if ( false !== $this->complexity ) return $this->complexity;
     221
     222        ob_start(); imagegd($image);
     223        $source = strlen(ob_get_clean());
     224
     225        ob_start(); imagejpeg($image);
     226        $jpeg = strlen(ob_get_clean());
     227
     228        $this->complexity = 0.7 - ( $jpeg / $source );
     229        error_log("Complexity: $this->complexity");
     230
     231        return $this->complexity;
     232
     233    }
     234
     235    /**
     236     * Performs an unsharp mask on the image
     237     *
     238     * Smart unsharp masking looks at the visual complexity
     239     * of the image to determine how to vary the strength of
     240     * the sharpening and the narrowness of the edge threshold.
     241     *
     242     * @author Jonathan Davis
     243     * @since 1.3.4
     244     * @version 1.0
     245     *
     246     * @param int $amount Strength of the sharpening (0-100)
     247     * @param int $threshold The narrowness of the sharpening filter (0-255)
    212248     * @return void
    213249     **/
    214     public function UnsharpMask ( $amount = 50, $radius = 0.5, $threshold = 3 ) {
     250    public function sharpen ( $amount = 100, $threshold = null ) {
     251
    215252        if ( ! isset($this->processed) ) $image =& $this->src->image;
    216253        else $image = &$this->processed;
    217254
    218         // Attempt to calibrate the parameters to Photoshop
    219         if ( $amount > 500 ) $amount = 500;
    220         $amount = $amount * 0.016;
    221         if ( $radius > 50 ) $radius = 50;
    222         $radius = $radius * 2;
     255        // Don't unsharp mask if we have a very low detail image
     256        $complexity = $this->complexity();
     257        if ( $complexity < 0.15 ) return;
     258
     259        if ( $amount > 100 ) $amount = 100;
     260
     261        // Calibration to a reasonable strength
     262        $amount = ( $amount * (1 + $complexity) ) * 0.01618;
     263
     264        // Calibrate the threshold to the image complexity
     265        if ( empty($threshold) ) $threshold = 10 - ( $complexity * 13 );
    223266        if ( $threshold > 255 ) $threshold = 255;
    224267
    225         $radius = abs( round($radius) );
    226         if ( 0 == $radius ) return $image;
     268        // Create a gausian blur for edge detection
    227269        $w = imagesx($image); $h = imagesy($image);
    228         $canvas = imagecreatetruecolor($w, $h);
    229270        $blur = imagecreatetruecolor($w, $h);
    230 
    231         /**
    232          * Gaussian blur matrix:
    233          *  1    2    1
    234          *  2    4    2
    235          *  1    2    1
    236          **/
    237 
    238         if ( function_exists('imageconvolution') ) { // PHP >= 5.1
    239             $matrix = array(
    240                 array( 1, 2, 1 ),
    241                 array( 2, 4, 2 ),
    242                 array( 1, 2, 1 )
    243             );
    244             imagecopy ($blur, $image, 0, 0, 0, 0, $w, $h);
    245             imageconvolution($blur, $matrix, 16, 0);
    246         } else {
    247 
    248             // Move copies of the image around one pixel at the time and merge them with weight
    249             // according to the matrix. The same matrix is simply repeated for higher radii.
    250             for ($i = 0; $i < $radius; $i++)    {
    251                 imagecopy ($blur, $image, 0, 0, 1, 0, $w - 1, $h); // left
    252                 imagecopymerge ($blur, $image, 1, 0, 0, 0, $w, $h, 50); // right
    253                 imagecopymerge ($blur, $image, 0, 0, 0, 0, $w, $h, 50); // center
    254                 imagecopy ($canvas, $blur, 0, 0, 0, 0, $w, $h);
    255 
    256                 imagecopymerge ($blur, $canvas, 0, 0, 0, 1, $w, $h - 1, 33.33333 ); // up
    257                 imagecopymerge ($blur, $canvas, 0, 1, 0, 0, $w, $h, 25); // down
    258             }
    259         }
    260 
    261         if ( $threshold > 0 ){
    262             // Calculate the difference between the blurred pixels and the original
    263             // and set the pixels
    264             for ( $x = 0; $x < $w-1; $x++ ) { // each row
    265                 for ( $y = 0; $y < $h; $y++ ) { // each pixel
    266 
    267                     $rgbOrig = ImageColorAt($image, $x, $y);
    268                     $rOrig = ( ($rgbOrig >> 16) & 0xFF );
    269                     $gOrig = ( ($rgbOrig >> 8) & 0xFF );
    270                     $bOrig = ( $rgbOrig & 0xFF );
    271 
    272                     $rgbBlur = ImageColorAt($blur, $x, $y);
    273 
    274                     $rBlur = ( ($rgbBlur >> 16) & 0xFF );
    275                     $gBlur = ( ($rgbBlur >> 8) & 0xFF );
    276                     $bBlur = ( $rgbBlur & 0xFF );
    277 
    278                     // When the masked pixels differ less from the original
    279                     // than the threshold specifies, they are set to their original value.
    280                     $rNew = ( abs($rOrig - $rBlur) >= $threshold)
    281                         ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig))
    282                         : $rOrig;
    283                     $gNew = ( abs($gOrig - $gBlur) >= $threshold)
    284                         ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig))
    285                         : $gOrig;
    286                     $bNew = ( abs($bOrig - $bBlur) >= $threshold)
    287                         ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig))
    288                         : $bOrig;
    289 
    290 
    291 
    292                     if ( ($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew) ) {
    293                             $pixCol = ImageColorAllocate($image, $rNew, $gNew, $bNew);
    294                             ImageSetPixel($image, $x, $y, $pixCol);
    295                         }
    296                 }
    297             }
    298         } else {
    299             for ( $x = 0; $x < $w; $x++ ) { // each row
    300                 for ( $y = 0; $y < $h; $y++ ) { // each pixel
    301                     $rgbOrig = ImageColorAt($image, $x, $y);
    302                     $rOrig = ( ($rgbOrig >> 16) & 0xFF );
    303                     $gOrig = ( ($rgbOrig >> 8) & 0xFF );
    304                     $bOrig = ( $rgbOrig & 0xFF );
    305 
    306                     $rgbBlur = ImageColorAt($blur, $x, $y);
    307 
    308                     $rBlur = ( ($rgbBlur >> 16) & 0xFF );
    309                     $gBlur = ( ($rgbBlur >> 8) & 0xFF );
    310                     $bBlur = ( $rgbBlur & 0xFF );
    311 
    312                     $rNew = ( $amount * ($rOrig - $rBlur) ) + $rOrig;
    313                         if ( $rNew > 255 ) $rNew = 255;
    314                         elseif ( $rNew < 0 ) $rNew = 0;
    315                     $gNew = ( $amount * ($gOrig - $gBlur) ) + $gOrig;
    316                         if ( $gNew > 255 ) $gNew = 255;
    317                         elseif ($gNew < 0 ) $gNew = 0;
    318                     $bNew = ( $amount * ($bOrig - $bBlur) ) + $bOrig;
    319                         if ( $bNew > 255 ) $bNew = 255;
    320                         elseif ( $bNew < 0 ) $bNew = 0;
    321                     $rgbNew = ( $rNew << 16 ) + ( $gNew << 8 ) + $bNew;
    322                         ImageSetPixel($image, $x, $y, $rgbNew);
    323                 }
    324             }
    325         }
    326 
    327         imagedestroy($canvas);
     271        imagecopy ($blur, $image, 0, 0, 0, 0, $w, $h);
     272        imagefilter($blur, IMG_FILTER_GAUSSIAN_BLUR);
     273
     274        // Walk through each pixel of the image
     275        for ( $x = 0; $x < $w - 1 ; $x++ ) { // each row
     276            for ( $y = 0; $y < $h - 1 ; $y++ ) { // each pixel
     277
     278                $changed = false;
     279                $pixel = array(
     280                    'src' => imagecolorsforindex($image, imagecolorat($image, $x, $y) ),
     281                    'blur' => imagecolorsforindex($blur, imagecolorat($blur, $x, $y) )
     282                );
     283                $channels = array_keys($pixel['src']);
     284
     285                // If masked pixel channel value differs enough ($threshold) from the original,
     286                // we found an edge. Boost the edge contrast by a strength ($amount) of the
     287                // color channel difference between the blurred mask pixel and the source image pixel.
     288                // Otherwise leave the pixel alone to preserve smooth surfaces/gradients.
     289                foreach ( $channels as $channel ) {
     290
     291                    $src = $pixel['src'][ $channel ];
     292                    $mask = $pixel['blur'][ $channel ];
     293
     294                    // Calculate the difference
     295                    $diff = $src - $mask;
     296
     297                    // If the difference is more than the threshold, we're near an edge
     298                    if ( abs($diff) >= $threshold ) {
     299                        // Change the pixel channel with the difference factored by the strength amount
     300                        $value = ( $amount * $diff ) + $src;
     301
     302                        // Ceiling/floor values (if is faster than min/max)
     303                        if ( $value > 255 ) $value = 255;
     304                        elseif ( $value < 0 ) $value = 0;
     305
     306                        // Save the channel value
     307                        $$channel = $value;
     308                        $changed = true;
     309                    } else $$channel = $src;
     310                }
     311
     312                if ( $changed ) { // Update the pixel in the image with the new color
     313                    $color = imagecolorallocatealpha($image, $red, $green, $blue, $alpha);
     314                    imagesetpixel($image, $x, $y, $color);
     315                }
     316            }
     317        }
     318
    328319        imagedestroy($blur);
     320        imagefilter($image, IMG_FILTER_SMOOTH, 16); // Just enough to anti-alias edges
    329321
    330322    }
     
    333325     * Convert a decimal-encoded hexadecimal color to RGB color values
    334326     *
    335      * Uses bit-shifty voodoo magic to pick the color spectrum apart.
     327     * Uses bit-shifty voodoo to pick the color channels apart.
    336328     *
    337329     * @author Jonathan Davis
  • shopp/trunk/core/model/Item.php

    r905841 r930519  
    169169
    170170        if ( shopp_setting_enabled('taxes') ) {
     171            $this->taxable = array(); // Re-init during ShoppCart::change() loads #2922
    171172            if ( Shopp::str_true($Price->tax) ) $this->taxable[] = $baseprice;
    172173            $this->istaxed =  array_sum($this->taxable) > 0 ;
     
    930931        $taxableqty = ( $this->bogof && $this->bogof != $this->quantity ) ? $this->quantity - $this->bogof : $this->quantity;
    931932
    932 
    933933        $Tax->rates($this->taxes, $Tax->item($this));
    934934
  • shopp/trunk/core/model/Payments.php

    r865739 r930519  
    150150     * @return ShoppPaymentOption The selected payment option (or false)
    151151     **/
    152     public function selected ( string $selection = null ) {
     152    public function selected ( $selection = null ) {
    153153
    154154        if ( isset($selection) ) {
     
    181181     * @return string The payment processor class name
    182182     **/
    183     public function processor ( string $processor = null ) {
     183    public function processor ( $processor = null ) {
    184184
    185185        $selected = $this->selected();
     
    265265     * @return GatewayFramework A payment gateway class (or boolean false if not valid)
    266266     **/
    267     private function modules ( string $module = null ) {
     267    private function modules ( $module = null ) {
    268268        $Shopp = Shopp::object();
    269269
  • shopp/trunk/core/model/Search.php

    r821385 r930519  
    3030    public $Product = false;
    3131    public $properties = array(
    32         'name','prices','summary','description','specs','categories','tags'
     32        'name', 'prices', 'summary', 'description', 'specs', 'categories', 'tags'
    3333    );
    3434
     
    4343    function __construct ($id) {
    4444        $this->Product = new ShoppProduct($id);
    45         $this->Product->load_data(array('prices','specs','categories','tags'));
     45        $this->Product->load_data(array('prices', 'specs', 'categories', 'tags'));
    4646    }
    4747
     
    5555     **/
    5656    function index () {
    57         $properties = apply_filters('shopp_index_product_properties',$this->properties);
    58         foreach ($properties as $property) {
    59             switch ($property) {
     57        $properties = apply_filters('shopp_index_product_properties', $this->properties);
     58        foreach ( $properties as $property ) {
     59            switch ( $property ) {
    6060                case "prices":
    6161                    $prices = array();
    62                     foreach ($this->Product->prices as $price) {
     62                    foreach ( $this->Product->prices as $price ) {
    6363                        if ($price->type == "N/A") continue; // Skip disabled pricelines
    6464                        $prices[] = "$price->label $price->sku";
    6565                    }
    66                     $content = join(' ',$prices);
     66                    $content = join(' ', $prices);
    6767                    break;
    6868                case "specs":
    6969                    $specs = array();
    70                     foreach ($this->Product->specs as $Spec)
     70                    foreach ( $this->Product->specs as $Spec )
    7171                        $specs[] = "$Spec->name $Spec->value";
    72                     $content = join(' ',$specs);
     72                    $content = join(' ', $specs);
    7373                    break;
    7474                case "categories":
    7575                    $categories = array();
    76                     foreach ($this->Product->categories as $Category)
     76                    foreach ( $this->Product->categories as $Category )
    7777                        $categories[] = $Category->name;
    78                     $content = join(' ',$categories);
     78                    $content = join(' ', $categories);
    7979                    break;
    8080                case "tags":
    8181                    $tags = array();
    82                     foreach ($this->Product->tags as $Tag)
     82                    foreach ( $this->Product->tags as $Tag )
    8383                        $tags[] = $Tag->name;
    84                     $content = join(' ',$tags);
     84                    $content = join(' ', $tags);
    8585                    break;
    8686                default: $content = $this->Product->{$property}; break;
    8787            }
    88             $Indexer = new ContentIndex($this->Product->id,$property);
     88            $Indexer = new ContentIndex($this->Product->id, $property);
    8989            $Indexer->save($content);
    9090        }
     
    113113     * @author Jonathan Davis
    114114     *
     115     * @param int $product The ID of the indexed product
     116     * @param string $type The type of index to load
    115117     * @return void
    116118     **/
    117     function __construct ($product,$type) {
     119    function __construct ( $product, $type ) {
    118120        $this->init(self::$table);
    119         $this->load($product,$type);
     121        $this->load($product, $type);
    120122    }
    121123
     
    130132     * @return void
    131133     **/
    132     function load ($product=false,$type=false) {
     134    function load ( $product = false, $type = false ) {
    133135        $this->product = $product;
    134136        $this->type = $type;
    135         if (empty($product) || empty($type)) return false; // Nothing to load
     137        if ( empty($product) || empty($type) ) return false; // Nothing to load
    136138
    137139        $r = sDB::query("SELECT id,created FROM $this->_table WHERE product='$product' AND type='$type' LIMIT 1");
    138         if (!empty($r->id)) {
     140        if ( ! empty($r->id) ) {
    139141            $this->id = $r->id;
    140142            $this->created = mktimestamp($r->created);
     
    153155     **/
    154156    function save () {
     157
    155158        list($content,) = func_get_args();
    156         if (empty($this->product) || empty($this->type) || empty($content))
     159        $content = apply_filters('shopp_index_content', $content, $this);
     160        if ( empty($this->product) || empty($this->type) || empty($content) )
    157161            return false;
    158162
    159163        $factoring = Lookup::index_factors();
    160         if (isset($factoring[$this->type])) $this->factor = $factoring[$this->type];
     164        if ( isset($factoring[ $this->type ])) $this->factor = $factoring[ $this->type ];
    161165        else $this->factor = 1;
    162166
    163         $this->terms = apply_filters('shopp_index_content',$content);
     167        $this->terms = $content;
    164168
    165169        parent::save();
     170
    166171    }
    167172
    168173} // END class ContentIndex
    169174
    170 if ( ! class_exists('SearchParser',false) ):
     175if ( ! class_exists('SearchParser', false) ):
    171176/**
    172177 * SearchParser class
     
    190195     **/
    191196    function __construct () {
    192         add_filter('shopp_search_query',array('SearchParser','MarkupFilter'));
    193         add_filter('shopp_search_query',array('SearchParser','CurrencyFilter'));
    194         add_filter('shopp_search_query',array('SearchParser','StopFilter'));
    195         add_filter('shopp_search_query',array('SearchParser','AccentFilter'));
    196         add_filter('shopp_search_query',array('SearchParser','LowercaseFilter'));
    197         add_filter('shopp_search_query',array('SearchParser','NormalizeFilter'));
     197        add_filter('shopp_search_query', array('SearchParser', 'MarkupFilter'));
     198        add_filter('shopp_search_query', array('SearchParser', 'CurrencyFilter'));
     199        add_filter('shopp_search_query', array('SearchParser', 'StopFilter'));
     200        add_filter('shopp_search_query', array('SearchParser', 'AccentFilter'));
     201        add_filter('shopp_search_query', array('SearchParser', 'LowercaseFilter'));
     202        add_filter('shopp_search_query', array('SearchParser', 'NormalizeFilter'));
    198203    }
    199204
     
    207212     * @return object The price matching object
    208213     **/
    209     static function PriceMatching ($query) {
     214    static function PriceMatching ( $query ) {
    210215        $pricematch = self::_pricematch_regex();
    211         preg_match_all("/$pricematch/",$query,$matches,PREG_SET_ORDER);
    212         if (empty($matches)) return false;
     216        preg_match_all("/$pricematch/", $query, $matches, PREG_SET_ORDER);
     217        if ( empty($matches) ) return false;
    213218        $_->op = $matches[0][0][0];
    214         $_->op = (in_array($_->op,array("<",">")))?$_->op:'';
     219        $_->op = ( in_array($_->op, array("<", ">")) ) ? $_->op : '';
    215220        $_->min = Shopp::floatval($matches[0][1]);
    216221        $_->max = Shopp::floatval($matches[0][4]);
    217222        $_->target = $_->min;
    218         if ($_->max > 0) $_->op = "-"; // Range matching
     223        if ( $_->max > 0 ) $_->op = "-"; // Range matching
    219224
    220225        // Roundabout price match
    221         if (empty($_->op) && empty($_->max)) {
    222             $_->min = $_->target-($_->target/2);
    223             $_->max = $_->target+($_->target/2);
     226        if ( empty($_->op) && empty($_->max) ) {
     227            $_->min = $_->target - ( $_->target / 2 );
     228            $_->max = $_->target + ( $_->target / 2 );
    224229        }
    225230
     
    230235endif;
    231236
    232 if ( ! class_exists('BooleanParser',false) ):
     237if ( ! class_exists('BooleanParser', false) ):
    233238/**
    234239 * BooleanParser class
     
    252257     **/
    253258    function __construct () {
    254         add_filter('shopp_boolean_search',array('BooleanParser','MarkupFilter'));
    255         add_filter('shopp_boolean_search',array('BooleanParser','CurrencyFilter'));
    256         add_filter('shopp_boolean_search',array('BooleanParser','AccentFilter'));
    257         add_filter('shopp_boolean_search',array('BooleanParser','StopFilter'));
    258         add_filter('shopp_boolean_search',array('BooleanParser','LowercaseFilter'));
    259         add_filter('shopp_boolean_search',array('BooleanParser','NormalizeFilter'));
    260         add_filter('shopp_boolean_search',array('BooleanParser','StemFilter'));
    261         add_filter('shopp_boolean_search',array('BooleanParser','KeywordFilter'));
     259        add_filter('shopp_boolean_search', array('BooleanParser', 'MarkupFilter'));
     260        add_filter('shopp_boolean_search', array('BooleanParser', 'CurrencyFilter'));
     261        add_filter('shopp_boolean_search', array('BooleanParser', 'AccentFilter'));
     262        add_filter('shopp_boolean_search', array('BooleanParser', 'StopFilter'));
     263        add_filter('shopp_boolean_search', array('BooleanParser', 'LowercaseFilter'));
     264        add_filter('shopp_boolean_search', array('BooleanParser', 'NormalizeFilter'));
     265        add_filter('shopp_boolean_search', array('BooleanParser', 'StemFilter'));
     266        add_filter('shopp_boolean_search', array('BooleanParser', 'KeywordFilter'));
    262267    }
    263268
     
    265270endif;
    266271
    267 if ( ! class_exists('ShortwordParser',false) ):
     272if ( ! class_exists('ShortwordParser', false) ):
    268273/**
    269274 * ShortwordParser class
     
    287292     **/
    288293    function __construct () {
    289         add_filter('shopp_shortword_search',array('ShortwordParser','MarkupFilter'));
    290         add_filter('shopp_shortword_search',array('ShortwordParser','CurrencyFilter'));
    291         add_filter('shopp_shortword_search',array('ShortwordParser','AccentFilter'));
    292         add_filter('shopp_shortword_search',array('ShortwordParser','LowercaseFilter'));
    293         add_filter('shopp_shortword_search',array('ShortwordParser','ShortwordFilter'));
    294         add_filter('shopp_shortword_search',array('ShortwordParser','StopFilter'));
    295         add_filter('shopp_shortword_search',array('ShortwordParser','NormalizeFilter'));
     294        add_filter('shopp_shortword_search', array('ShortwordParser', 'MarkupFilter'));
     295        add_filter('shopp_shortword_search', array('ShortwordParser', 'CurrencyFilter'));
     296        add_filter('shopp_shortword_search', array('ShortwordParser', 'AccentFilter'));
     297        add_filter('shopp_shortword_search', array('ShortwordParser', 'LowercaseFilter'));
     298        add_filter('shopp_shortword_search', array('ShortwordParser', 'ShortwordFilter'));
     299        add_filter('shopp_shortword_search', array('ShortwordParser', 'StopFilter'));
     300        add_filter('shopp_shortword_search', array('ShortwordParser', 'NormalizeFilter'));
    296301    }
    297302
     
    299304endif;
    300305
    301 if ( ! class_exists('ContentParser',false) ):
     306if ( ! class_exists('ContentParser', false) ):
    302307class ContentParser extends SearchTextFilters {
    303308
     
    311316     **/
    312317    function __construct () {
    313         add_filter('shopp_index_content',array('ContentParser','MarkupFilter'));
    314         add_filter('shopp_index_content',array('ContentParser','AccentFilter'));
    315         add_filter('shopp_index_content',array('ContentParser','LowercaseFilter'));
    316         add_filter('shopp_index_content',array('ContentParser','NormalizeFilter'));
    317         add_filter('shopp_index_content',array('ContentParser','StemFilter'));
     318        add_filter('shopp_index_content', array('ContentParser', 'MarkupFilter'));
     319        add_filter('shopp_index_content', array('ContentParser', 'AccentFilter'));
     320        add_filter('shopp_index_content', array('ContentParser', 'LowercaseFilter'));
     321        add_filter('shopp_index_content', array('ContentParser', 'NormalizeFilter'));
     322        add_filter('shopp_index_content', array('ContentParser', 'StemFilter'));
    318323    }
    319324
     
    346351        extract($format);
    347352
    348         $pre = ($cpos?''.preg_quote($currency).($symbol?'':'?'):'');
    349         $amount = '[\d'.preg_quote($thousands).']+';
    350         $fractional = '('.preg_quote($decimals).'\d{'.$precision.'}?)?';
    351         $post = (!$cpos?''.preg_quote($currency).($symbol?'':'?'):'');
    352         return $pre.$amount.$fractional.$post;
     353        $pre = ( $cpos ? '' . preg_quote($currency) . ( $symbol ? '' : '?' ) : '' );
     354        $amount = '[\d' . preg_quote($thousands) . ']+';
     355        $fractional = '(' . preg_quote($decimals) . '\d{' . $precision . '}?)?';
     356        $post = ( ! $cpos ? '' . preg_quote($currency) . ( $symbol ? '' : '?' ) : '' );
     357        return $pre . $amount . $fractional . $post;
    353358    }
    354359
     
    379384     * @return string text with markup tags removed
    380385     **/
    381     static function MarkupFilter ($text) {
     386    static function MarkupFilter ( $text ) {
    382387        return strip_tags($text);
    383388    }
     
    392397     * @return string Transposed text
    393398     **/
    394     static function LowercaseFilter ($text) {
     399    static function LowercaseFilter ( $text ) {
    395400        return strtolower($text);
    396401    }
     
    408413     * @return string The cleaned text
    409414     **/
    410     static function StopFilter ($text) {
     415    static function StopFilter ( $text ) {
    411416        $stopwords = Lookup::stopwords();
    412         $replacements = implode('|',$stopwords);
    413         return preg_replace("/\b($replacements)\b/",'',$text);
     417        $replacements = implode('|', $stopwords);
     418        return preg_replace("/\b($replacements)\b/", '', $text);
    414419    }
    415420
     
    429434
    430435        // Collapse hyphenated prefix words
    431         $text = preg_replace("/(\s?\w{1,3})\-(\w+)\b/","$1$2",$text);
     436        $text = preg_replace("/(\s?\w{1,3})\-(\w+)\b/", "$1$2", $text);
    432437
    433438        // Collapse words with periods and commas
    434         $text = preg_replace("/[\.\']/",'',$text);
     439        $text = preg_replace("/[\.\']/", '', $text);
    435440
    436441        // Translate any other non-word characters to spaces
    437         $text = preg_replace("/[^\w\d\s\p{L}\_\"]/u",' ',$text);
     442        $text = preg_replace("/[^\w\d\s\p{L}\_\"]/u", ' ', $text);
    438443
    439444        // Collapse the spaces
    440         $text = preg_replace("/\s+/m",' ',$text);
     445        $text = preg_replace("/\s+/m", ' ', $text);
    441446
    442447        return trim($text);
     
    452457     * @return string Converted text
    453458     **/
    454     static function AccentFilter ($text) {
    455         if (!function_exists('remove_accents'))
     459    static function AccentFilter ( $text ) {
     460        if ( ! function_exists('remove_accents') )
    456461            require( ABSPATH . WPINC . '/formatting.php' );
    457462        return remove_accents($text);
     
    467472     * @return string The boolean search string
    468473     **/
    469     static function KeywordFilter ($text) {
    470         if (!defined('SHOPP_SEARCH_LOGIC')) define('SHOPP_SEARCH_LOGIC','OR');
    471         $logic = (strtoupper(SHOPP_SEARCH_LOGIC) == "AND")?"+":"";
     474    static function KeywordFilter ( $text ) {
     475        if ( ! defined('SHOPP_SEARCH_LOGIC') ) define('SHOPP_SEARCH_LOGIC', 'OR');
     476        $logic = strtoupper(SHOPP_SEARCH_LOGIC) == 'AND' ? '+' : '';
    472477
    473478        $tokens = array();
    474         $token = strtok($text,' ');
    475         while ($token) {
     479        $token = strtok($text, ' ');
     480        while ( $token ) {
    476481            // find double quoted tokens
    477             if ($token{0} == '"') {
    478                 $token .= ' '.strtok('"').'"';
     482            if ( '"' == $token{0} ) {
     483                $token .= ' ' . strtok('"') . '"';
    479484                $tokens[] = $token;
    480485            } else {
     
    483488            $token = strtok(' ');
    484489        }
    485         return implode(' ',$tokens);
     490        return implode(' ', $tokens);
    486491    }
    487492
     
    495500     * @return string The shortword search string
    496501     **/
    497     static function ShortwordFilter ($text) {
    498         $text = preg_replace('/\b\w{4,}\b/','',$text);
    499         $text = preg_replace('/ +/','|',$text);
     502    static function ShortwordFilter ( $text ) {
     503        $text = preg_replace('/\b\w{4,}\b/', '', $text);
     504        $text = preg_replace('/ +/', '|', $text);
    500505        return $text;
    501506    }
     
    510515     * @return string search query without price search
    511516     **/
    512     static function CurrencyFilter ($text) {
     517    static function CurrencyFilter ( $text ) {
    513518        $pricematch = self::_pricematch_regex();
    514         $text = preg_replace("/$pricematch/",'',$text);
     519        $text = preg_replace("/$pricematch/", '', $text);
    515520        return $text;
    516521    }
     
    525530     * @return string The text plus the generated word stems
    526531     **/
    527     static function StemFilter ($text) {
     532    static function StemFilter ( $text ) {
    528533        // Filter out short words for stemming
    529         $source = preg_replace("/\b\w{1,3}\b/",'',$text);
     534        $source = preg_replace("/\b\w{1,3}\b/", '', $text);
    530535        $_ = array();
    531         $token = strtok($source,' ');
     536        $token = strtok($source, ' ');
    532537        while ($token) {
    533538            $stem = PorterStemmer::Stem($token);
    534             if ($stem != $token) $_[] = $stem;
     539            if ( $stem != $token ) $_[] = $stem;
    535540            $token = strtok(' ');
    536541        }
    537542
    538         return !empty($_)?"$text ".join(' ',$_):$text;
     543        return ! empty($_) ? "$text " . join(' ', $_) : $text;
    539544    }
    540545
     
    563568     * @package shopp
    564569     *
    565      * @param  string $word Word to stem
     570     * @param  $word Word to stem
    566571     * @return string Stemmed word
    567572     **/
    568     public static function Stem ($word) {
    569         if (strlen($word) <= 2)
     573    public static function Stem ( $word ) {
     574        if ( strlen($word) <= 2 )
    570575            return $word;
    571576
     
    583588     * Step 1
    584589     **/
    585     private static function step1ab ($word) {
     590    private static function step1ab ( $word ) {
    586591        // Part a
    587         if (substr($word, -1) == 's') {
     592        if ( substr($word, -1) == 's') {
    588593               self::replace($word, 'sses', 'ss')
    589594            OR self::replace($word, 'ies', 'i')
     
    593598
    594599        // Part b
    595         if (substr($word, -2, 1) != 'e' OR !self::replace($word, 'eed', 'ee', 0)) { // First rule
     600        if ( substr($word, -2, 1) != 'e' OR !self::replace($word, 'eed', 'ee', 0) ) { // First rule
    596601            $v = self::$regex_vowel;
    597602
    598603            // ing and ed
    599             if (   preg_match("#$v+#", substr($word, 0, -3)) && self::replace($word, 'ing', '')
    600                 OR preg_match("#$v+#", substr($word, 0, -2)) && self::replace($word, 'ed', '')) { // Note use of && and OR, for precedence reasons
     604            if ( preg_match("#$v+#", substr($word, 0, -3)) && self::replace($word, 'ing', '')
     605                OR preg_match("#$v+#", substr($word, 0, -2)) && self::replace($word, 'ed', '') ) { // Note use of && and OR, for precedence reasons
    601606
    602607                // If one of above two test successful
     
    629634     * @param string $word Word to stem
    630635     **/
    631     private static function step1c($word) {
     636    private static function step1c ( $word ) {
    632637        $v = self::$regex_vowel;
    633638
    634         if (substr($word, -1) == 'y' && preg_match("#$v+#", substr($word, 0, -1))) {
     639        if ( substr($word, -1) == 'y' && preg_match("#$v+#", substr($word, 0, -1)) ) {
    635640            self::replace($word, 'y', 'i');
    636641        }
     
    645650     * @param string $word Word to stem
    646651     **/
    647     private static function step2($word) {
     652    private static function step2 ( $word ) {
    648653        switch (substr($word, -2, 1)) {
    649654            case 'a':
     
    702707     * @param string $word String to stem
    703708     **/
    704     private static function step3 ($word) {
    705         switch (substr($word, -2, 1)) {
     709    private static function step3 ( $word ) {
     710        switch ( substr($word, -2, 1) ) {
    706711            case 'a':
    707712                self::replace($word, 'ical', 'ic', 0);
     
    739744     * @param string $word Word to stem
    740745     **/
    741     private static function step4 ($word) {
    742         switch (substr($word, -2, 1)) {
     746    private static function step4 ( $word ) {
     747        switch ( substr($word, -2, 1) ) {
    743748            case 'a':
    744749                self::replace($word, 'al', '', 1);
     
    808813     * @param string $word Word to stem
    809814     **/
    810     private static function step5 ($word) {
     815    private static function step5 ( $word ) {
    811816        // Part a
    812817        if (substr($word, -1) == 'e') {
     
    833838     * arg is given, then the preceding string must match that m count at least.
    834839     *
    835      * @param  string $str   String to check
    836      * @param  string $check Ending to check for
    837      * @param  string $repl  Replacement string
     840     * @param  $str   String to check
     841     * @param  $check Ending to check for
     842     * @param  $repl  Replacement string
    838843     * @param  int    $m     Optional minimum number of m() to meet
    839844     * @return bool          Whether the $check string was at the end
     
    841846     *                       that it was replaced.
    842847     **/
    843     private static function replace (&$str, $check, $repl, $m = null) {
     848    private static function replace ( &$str, $check, $repl, $m = null ) {
    844849        $len = 0 - strlen($check);
    845850
    846         if (substr($str, $len) == $check) {
     851        if ( substr($str, $len) == $check ) {
    847852            $substr = substr($str, 0, $len);
    848             if (is_null($m) OR self::m($substr) > $m)
     853            if ( is_null($m) OR self::m($substr) > $m )
    849854                $str = $substr . $repl;
    850855            return true;
     
    867872     * <c>vcvcvc<v> gives 3
    868873     *
    869      * @param  string $str The string to return the m count for
     874     * @param  $str The string to return the m count for
    870875     * @return int         The m count
    871876     **/
    872     private static function m ($str) {
     877    private static function m ( $str ) {
    873878        $c = self::$regex_consonant;
    874879        $v = self::$regex_vowel;
     
    887892     * of the same consonant next to each other at the end of the string.
    888893     *
    889      * @param  string $str String to check
     894     * @param  $str String to check
    890895     * @return bool        Result
    891896     **/
    892     private static function doubleConsonant ($str) {
     897    private static function doubleConsonant ( $str ) {
    893898        $c = self::$regex_consonant;
    894899
     
    899904     * Checks for ending CVC sequence where second C is not W, X or Y
    900905     *
    901      * @param  string $str String to check
     906     * @param  $str String to check
    902907     * @return bool        Result
    903908     **/
    904     private static function cvc ($str) {
     909    private static function cvc ( $str ) {
    905910        $c = self::$regex_consonant;
    906911        $v = self::$regex_vowel;
  • shopp/trunk/core/model/Shiprates.php

    r865739 r930519  
    5858     * @return ShoppShiprateService The currently selected shiprate service
    5959     **/
    60     public function selected ( string $selected = null ) {
     60    public function selected ( $selected = null ) {
    6161
    6262        if ( is_null($selected) ) {
     
    9999     * @return void
    100100     **/
    101     public function takeoff ( string $id ) {
     101    public function takeoff ( $id ) {
    102102
    103103        if ( isset($this->shippable[ $id ]) )
     
    173173     * @return void
    174174     **/
    175     public function track ( string $name, &$value ) {
     175    public function track ( $name, &$value ) {
    176176        $this->track[ $name ] = &$value;
    177177    }
     
    219219        do_action('shopp_calculate_shipping_init');     // Initialize shipping modules
    220220
     221        parent::clear();                                    // clear existing rates before we pull new ones
     222       
    221223        $this->items();                                 // Send items to shipping modules that package them
    222224
  • shopp/trunk/core/model/Tax.php

    r905841 r930519  
    163163     * @return boolean True if the country matches or false
    164164     **/
    165     protected function taxcountry ( string $country ) {
     165    protected function taxcountry ( $country ) {
    166166        if ( empty($country) ) return false;
    167167        $EU = self::EUVAT == $country && in_array($this->address['country'], Lookup::country_euvat());
     
    178178     * @return boolean True if the zone matches or false
    179179     **/
    180     protected function taxzone ( string $zone ) {
     180    protected function taxzone ( $zone ) {
    181181        if ( empty($zone) ) return true;
    182182        return ($this->address['zone'] == $zone);
     
    192192     * @return boolean True if the rules match enough to apply, false otherwise
    193193     **/
    194     protected function taxrules ( array $rules, string $logic ) {
     194    protected function taxrules ( array $rules, $logic ) {
    195195        if ( empty($rules) ) return true;
    196196
     
    301301        if ( ! shopp_setting_enabled('tax_inclusive') ) return 1;
    302302
    303         $baserates = ShoppTax::baserates($this);
     303        $baserates = ShoppTax::baserates();
    304304        $baserate = reset($baserates);
    305305        $appliedrate = reset($rates);
     
    400400     * @return float $total
    401401     **/
    402     public function total ( array &$taxes, integer $quantity ) {
     402    public function total ( array &$taxes, $quantity ) {
    403403
    404404        $total = 0;
     
    471471     * @return boolean True if matched or false
    472472     **/
    473     private function ShoppCartItem ( string $property, string $value ) {
     473    private function ShoppCartItem ( $property, $value ) {
    474474        $CartItem = $this->Object;
    475475        switch ( $property ) {
     
    491491     * @return boolean True if matched or false
    492492     **/
    493     private function ShoppProduct ( string $property, string $value ) {
     493    private function ShoppProduct ( $property, $value ) {
    494494        $Product = $this->Object;
    495495        switch ( $property ) {
  • shopp/trunk/core/model/Totals.php

    r821385 r930519  
    6464     * @return OrderAmount The order amount entry
    6565     **/
    66     public function &entry ( string $register, string $id = null ) {
     66    public function &entry ( $register, $id = null ) {
    6767        $false = false;
    6868        if ( ! isset($this->register[ $register ]) ) return $false;
     
    8686     * @return boolean True if succesful, false otherwise
    8787     **/
    88     public function takeoff ( string $register, string $id ) {
     88    public function takeoff ( $register, $id ) {
    8989
    9090        if ( ! isset($this->register[ $register ]) ) return false;
     
    106106     * @return boolean True if successful
    107107     **/
    108     public function reset ( string $register ) {
     108    public function reset ( $register ) {
    109109
    110110        if ( ! isset($this->register[ $register ]) ) return false;
     
    126126     * @return boolean True for success, false otherwise
    127127     **/
    128     public function update ( string $register, $entry ) {
     128    public function update ( $register, $entry ) {
    129129        if ( ! isset($this->register[ $register ]) ) return false;
    130130
     
    210210     * @return boolean True when the register has changed
    211211     **/
    212     public function haschanged ( string $register ) {
     212    public function haschanged ( $register ) {
    213213        $check = isset($this->checks[ $register ]) ? $this->checks[$register] : 0;
    214214        $this->checks[$register] = hash('crc32b', serialize($this->register[$register]) );
     
    271271     * @return void
    272272     **/
    273     static public function register ( string $class ) {
     273    static public function register ( $class ) {
    274274        $register = get_class_property($class, 'register');
    275275        self::$handlers[ $register ] = $class;
     
    285285     * @return string The class name of the handler
    286286     **/
    287     static private function handler ( string $register ) {
     287    static private function handler ( $register ) {
    288288        if ( isset(self::$handlers[ $register ]) )
    289289            return self::$handlers[ $register ];
     
    301301     * @return OrderTotalAmount An constructed OrderTotalAmount object
    302302     **/
    303     static public function add ( OrderTotals $Totals, string $register, array $options = array() ) {
     303    static public function add ( OrderTotals $Totals, $register, array $options = array() ) {
    304304        $RegisterClass = self::handler($register);
    305305
     
    700700    protected $label = '';
    701701
    702     public function __construct ( ShoppItemTax &$Tax, string $itemid ) {
     702    public function __construct ( ShoppItemTax &$Tax, $itemid ) {
    703703
    704704        $this->items[ $itemid ] = &$Tax->total;
     
    709709    }
    710710
    711     public function unapply ( string $itemid ) {
     711    public function unapply ( $itemid ) {
    712712        if ( isset($this->items[ $itemid ]) );
    713713            unset($this->items[ $itemid ]);
  • shopp/trunk/core/ui/behaviors/catalog.js

    r865739 r930519  
    217217    _.order = ($.inArray(order,ordering) != -1)?order:'normal';
    218218
    219     _.slides = $(_.element).find('li:not(li.clear)').hide().css('visibility','visible');;
     219    _.slides = $(_.element).find('li:not(li.clear)').hide().css('visibility','visible');
    220220    _.total = _.slides.length;
    221221    _.slide = 0;
     
    373373    if (!form) return false;
    374374    var $ = jqnc(),
     375        $form = $(form),
    375376        passed = true,
    376377        passwords = [],
     
    416417    });
    417418
    418     form.shopp_validation = false;
    419     $(form).trigger('shopp_validate',[error]);
    420     if (form.shopp_validation) {
    421         error = form.shopp_validation;
     419    $form.data('error', error).trigger('shopp_validate');
     420
     421    if ( 'undefined' != form.shopp_validation )
     422        $form.data('error', form.shopp_validation);
     423
     424    if ( $form.data('error') ) {
     425        error = $form.data('error');
    422426        if (error[1] && $('#'+error[1].id).length > 0) {
    423427            $('#'+error[1].id).addClass('error');
     
    427431
    428432    if (error.length > 0) {
    429         error[1].focus();
     433        if ( error[1] instanceof jQuery )
     434            error[1].focus();
    430435        if ($(form).hasClass('validation-alerts')) alert(error[0]);
    431436        passed = false;
     
    439444 **/
    440445function validateForms () {
    441     jQuery('form.validate').bind('submit.validate',function (e) {
     446    jQuery('form.validate').on('submit.validate',function (e) {
    442447        return validate(this);
    443448    });
  • shopp/trunk/core/ui/behaviors/catalog.min.js

    r821385 r930519  
    1 /*
     1/*!
    22 * catalog.js - Shopp catalog behaviors library
    33 * Copyright © 2008-2010 by Ingenesis Limited
    44 * Licensed under the GPLv3 {@see license.txt}
    55 */
    6 function ProductOptionsMenus(target,settings){var $=jqnc(),i=0,previous=false,current=false,menucache=new Array(),menus=$(target),disabled="disabled",defaults={disabled:true,pricetags:true,format:"%l (%p)",taxrate:0,prices:{}},settings=$.extend(defaults,settings);menus.each(function(id,menu){current=menu;menucache[id]=$(menu).children();if($.ua.msie){disabledHandler(menu)}if(id>0){previous=menus[id-1]}if(menus.length==1){optionPriceTags()}else{if(previous){$(previous).change(function(){if(menus.index(current)==menus.length-1){optionPriceTags()}if(this.selectedIndex==0&&this.options[0].value==""){$(menu).attr(disabled,true)}else{$(menu).removeAttr(disabled)}}).change()}}i++});function optionPriceTags(){var selected=new Array(),currentSelection=$(current).val();menus.not(current).each(function(){if($(this).val()!=""){selected.push($(this).val())}});$(current).empty();menucache[menus.index(current)].each(function(id,option){$(option).appendTo($(current))});$(current).val(currentSelection);$(current).children("option").each(function(){var tax,optiontext,previoustag,pricetag,f=false,option=$(this),o={l:f,p:f,s:f,d:f,r:f,u:f},keys=selected.slice(),price;if(option.val()!=""){if(!this._label){this._label=option.text()}o.l=this._label;keys.push(option.val());price=settings.prices[xorkey(keys)]||settings.prices[xorkey(keys,"deprecated")];if(price){if(price.p&&settings.pricetags){pricetag=new Number(price.p);tax=price.tax?new Number(pricetag*settings.taxrate):0;o.p=asMoney(new Number(pricetag+tax))}if($.ua.msie){option.css("color","#373737")}if((price.i&&price.s<1)||price.t=="N/A"){if(option.attr("selected")){option.parent().attr("selectedIndex",0)}if(!settings.disabled){option.remove()}else{optionDisable(option)}}else{option.removeAttr(disabled).show()}if(price.i){o.s=price.s;o.u=price.u}if(price.t=="N/A"&&!settings.disabled){option.remove()}option.text(formatlabel(settings.format,o))}else{if(!settings.disabled){option.remove()}else{optionDisable(option)}}}})}function xorkey(ids,deprecated){if(!(ids instanceof Array)){ids=[ids]}for(var key=0,i=0,mod=deprecated?101:7001;i<ids.length;i++){key=key^(ids[i]*mod)}return key}function optionDisable(option){option.attr(disabled,true);if(!$.browser.msie){return}option.css("color","#ccc")}function disabledHandler(menu){$(menu).change(function(){var _=this,firstEnabled;if(!_.options[_.selectedIndex].disabled){_.lastSelected=_.selectedIndex;return true}if(_.lastSelected){_.selectedIndex=_.lastSelected}else{firstEnabled=$(_).children("option:not(:disabled)").get(0);_.selectedIndex=firstEnabled?firstEnabled.index:0}})}function formatlabel(f,v){var m="([^ ]*)",rescape=function(t){return t.toString().replace(/[$]/g,"$$$$")};$.each(v,function(p){if(v&&v[p]!=undefined){var pattern=new RegExp("("+m+"%"+p+m+")");label="$2"+rescape(v[p])+"$3";if(v[p]===false){label=""}if(v[p]===""){label=""}f=f.replace(pattern,label)}});return f}}function catalogViewHandler(){var $=jqnc(),display=$("#shopp"),expires=new Date(),toggles={list:"grid",grid:"list"};expires.setTime(expires.getTime()+(30*86400000));$.each(toggles,function(view,lastview){display.find("ul.views li button."+view).click(function(){display.removeClass(lastview).addClass(view);document.cookie="shopp_catalog_view="+view+"; expires="+expires+"; path=/"}).hover(function(){$(this).toggleClass("hover")})})}function ShoppGallery(id,evt,tw){var $=jqnc(),gallery=$(id),previews=gallery.find("ul.previews"),thumbnails=gallery.find("ul.thumbnails li");if(!evt){evt="click"}if(tw){gallery.find("ul.thumbnails").css("width",tw+"px")}thumbnails.bind(evt,function(){var previous,target=$("#"+$(this).attr("class").split(" ")[0]);if(!target.hasClass("active")){previous=gallery.find("ul.previews li.active");target.addClass("active").hide();if(previous.length){previous.fadeOut(800,function(){previous.removeClass("active")})}target.appendTo(previews).fadeIn(500)}})}function ShoppSlideshow(element,duration,delay,fx,order){var $=jqnc(),_=this,effects;_.element=$(element);var effects={fade:[{display:"none"},{opacity:"show"}],"slide-down":[{display:"block",top:_.element.height()*-1},{top:0}],"slide-up":[{display:"block",top:_.element.height()},{top:0}],"slide-left":[{display:"block",left:_.element.width()*-1},{left:0}],"slide-right":[{display:"block",left:_.element.width()},{left:0}],wipe:[{display:"block",height:0},{height:_.element.height()}]},ordering=["normal","reverse","shuffle"];_.duration=(!duration)?800:duration;_.delay=(!delay)?7000:delay;fx=(!fx)?"fade":fx;_.effect=(!effects[fx])?effects.fade:effects[fx];order=(!order)?"normal":order;_.order=($.inArray(order,ordering)!=-1)?order:"normal";_.slides=$(_.element).find("li:not(li.clear)").hide().css("visibility","visible");_.total=_.slides.length;_.slide=0;_.shuffling=new Array();_.startTransition=function(){var index,selected,prev=$(_.slides[_.slide-1]).removeClass("active");$(_.slides[_.slide]).css(_.effect[0]).appendTo(_.element).animate(_.effect[1],_.duration,function(){prev.css(_.effect[0])}).addClass("active");switch(_.order){case"shuffle":if(_.shuffling.length==0){_.shuffleList();index=$.inArray(_.slide,_.shuffling);if(index!=-1){_.shuffling.splice(index,1)}}selected=Math.floor(Math.random()*_.shuffling.length);_.slide=_.shuffling[selected];_.shuffling.splice(selected,1);break;case"reverse":_.slide=(_.slide-1<0)?_.slides.length-1:_.slide-1;break;default:_.slide=(_.slide+1==_.total)?0:_.slide+1}if(_.slides.length==1){return}setTimeout(_.startTransition,_.delay)};_.transitionTo=function(slide){_.slide=slide;_.startTransition()};_.shuffleList=function(){for(var i=0;i<_.total;i++){_.shuffling.push(i)}};_.startTransition()}function slideshows(){var $=jqnc(),classes,options,map;$("ul.slideshow").each(function(){classes=$(this).attr("class");options={};map={fx:new RegExp(/([\w_-]+?)\-fx/),order:new RegExp(/([\w_-]+?)\-order/),duration:new RegExp(/duration\-(\d+)/),delay:new RegExp(/delay\-(\d+)/)};$.each(map,function(name,pattern){if(option=classes.match(pattern)){options[name]=option[1]}});new ShoppSlideshow(this,options.duration,options.delay,options.fx,options.order)})}function ShoppCarousel(element,duration){var $=jqnc(),spacing,_=this,visible=1,carousel=$(element),list=carousel.find("ul"),items=list.find("> li");_.duration=(!duration)?800:duration;_.cframe=carousel.find("div.frame");visible=Math.round(_.cframe.innerWidth()/items.outerWidth());if(visible<1){visible=1}spacing=Math.round(((_.cframe.innerWidth()%items.outerWidth())/items.length)/2);items.css("margin","0 "+spacing+"px");_.pageWidth=(items.outerWidth()+(spacing*2))*visible;_.page=1;_.pages=Math.ceil(items.length/visible);if((items.length%visible)!=0){list.append(new Array(visible-(items.length%visible)+1).join('<li class="empty" style="width: '+items.outerWidth()+"px; height: 1px; margin: 0 "+spacing+'px"/>'));items=list.find("> li")}items.filter(":first").before(items.slice(-visible).clone().addClass("cloned"));items.filter(":last").after(items.slice(0,visible).clone().addClass("cloned"));items=list.find("> li");_.cframe.scrollLeft(_.pageWidth);_.scrollLeft=carousel.find("button.left");_.scrollRight=carousel.find("button.right");_.scrolltoPage=function(page){var dir=page<_.page?-1:1,delta=Math.abs(_.page-page),scrollby=_.pageWidth*dir*delta;_.cframe.filter(":not(:animated)").animate({scrollLeft:"+="+scrollby},_.duration,function(){if(page==0){_.cframe.scrollLeft(_.pageWidth*_.pages);page=_.pages}else{if(page>_.pages){_.cframe.scrollLeft(_.pageWidth);page=1}}_.page=page})};_.scrollLeft.click(function(){return _.scrolltoPage(_.page-1)});_.scrollRight.click(function(){return _.scrolltoPage(_.page+1)})}function carousels(){var $=jqnc(),classes,options,map;$("div.carousel").each(function(){classes=$(this).attr("class");options={};map={duration:new RegExp(/duration\-(\d+)/)};$.each(map,function(name,pattern){if(option=classes.match(pattern)){options[name]=option[1]}});new ShoppCarousel(this,options.duration)})}function validate(form){if(!form){return false}var $=jqnc(),passed=true,passwords=[],error=[],inputs=$(form).find("input,select,textarea").not(":hidden"),required="required",title="title";$.fn.reverse=(typeof[]._reverse=="undefined")?[].reverse:[]._reverse;$.each(inputs.reverse(),function(id,field){input=$(field).removeClass("error");label=$("label[for="+input.attr("id")+"]").removeClass("error");if(true===input.attr("disabled")||"disabled"==input.attr("disabled")){return}if(input.hasClass(required)&&input.val()==""){error=new Array($cv.field.replace(/%s/,input.attr(title)),field)}if(input.hasClass(required)&&input.attr("type")=="checkbox"&&!input.attr("checked")){error=new Array($cv.chkbox.replace(/%s/,input.attr(title)),field)}if(input.hasClass("email")&&!input.val().match(new RegExp(/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i))){error=new Array($cv.email,field)}if(input.attr("class")&&(chars=input.attr("class").match(new RegExp("min(\\d+)")))){if(input.val()!=""&&input.val().length<chars[1]){error=new Array($cv.minlen.replace(/%s/,input.attr(title)).replace(/%d/,chars[1]),field)}}if(input.hasClass("passwords")){passwords.push(field);if(passwords.length==2&&passwords[0].value!=passwords[1].value){error=new Array($cv.pwdmm,passwords[1])}}if(error[1]&&error[1].id==input.attr("id")){input.addClass("error");label.addClass("error")}});form.shopp_validation=false;$(form).trigger("shopp_validate",[error]);if(form.shopp_validation){error=form.shopp_validation;if(error[1]&&$("#"+error[1].id).length>0){$("#"+error[1].id).addClass("error");$("label[for="+error[1].id+"]").addClass("error")}}if(error.length>0){error[1].focus();if($(form).hasClass("validation-alerts")){alert(error[0])}passed=false}return passed}function validateForms(){jQuery("form.validate").bind("submit.validate",function(e){return validate(this)})}jQuery(document).ready(function($){validateForms();catalogViewHandler();slideshows();carousels();if($.fn.colorbox){$("a.shopp-zoom").colorbox({photo:true});$("a.shopp-zoom.gallery").each(function(){var id=$(this).attr("class").match(/product\_(\d+)/)[1];if(typeof(cbo)!="undefined"){$(this).attr("rel","gallery-"+id).colorbox(cbo)}else{$(this).attr("rel","gallery-"+id).colorbox({slideshow:true,slideshowSpeed:3500})}})}$("select.shopp-orderby-menu").change(function(){this.form.submit()});$("select.shopp-categories-menu").change(function(){document.location.href=$(this).val()});if($s.nocache){$(window).unload(function(){return})}});
     6function ProductOptionsMenus(m,c){var g=jqnc(),h=0,k=false,n=false,o=new Array(),f=g(m),e="disabled",d={disabled:true,pricetags:true,format:"%l (%p)",taxrate:0,prices:{}},c=g.extend(d,c);f.each(function(q,i){n=i;o[q]=g(i).children();if(g.ua.msie){a(i)}if(q>0){k=f[q-1]}if(f.length==1){p()}else{if(k){g(k).change(function(){if(f.index(n)==f.length-1){p()}if(this.selectedIndex==0&&this.options[0].value==""){g(i).attr(e,true)}else{g(i).removeAttr(e)}}).change()}}h++});function p(){var q=new Array(),i=g(n).val();f.not(n).each(function(){if(g(this).val()!=""){q.push(g(this).val())}});g(n).empty();o[f.index(n)].each(function(s,r){g(r).appendTo(g(n))});g(n).val(i);g(n).children("option").each(function(){var s,w,x,z,v=false,t=g(this),r={l:v,p:v,s:v,d:v,r:v,u:v},y=q.slice(),u;if(t.val()!=""){if(!this._label){this._label=t.text()}r.l=this._label;y.push(t.val());u=c.prices[b(y)]||c.prices[b(y,"deprecated")];if(u){if(u.p&&c.pricetags){z=new Number(u.p);s=u.tax?new Number(z*c.taxrate):0;r.p=asMoney(new Number(z+s))}if(g.ua.msie){t.css("color","#373737")}if((u.i&&u.s<1)||u.t=="N/A"){if(t.attr("selected")){t.parent().attr("selectedIndex",0)}if(!c.disabled){t.remove()}else{j(t)}}else{t.removeAttr(e).show()}if(u.i){r.s=u.s;r.u=u.u}if(u.t=="N/A"&&!c.disabled){t.remove()}t.text(l(c.format,r))}else{if(!c.disabled){t.remove()}else{j(t)}}}})}function b(u,q){if(!(u instanceof Array)){u=[u]}for(var t=0,s=0,r=q?101:7001;s<u.length;s++){t=t^(u[s]*r)}return t}function j(i){i.attr(e,true);if(!g.browser.msie){return}i.css("color","#ccc")}function a(i){g(i).change(function(){var q=this,r;if(!q.options[q.selectedIndex].disabled){q.lastSelected=q.selectedIndex;return true}if(q.lastSelected){q.selectedIndex=q.lastSelected}else{r=g(q).children("option:not(:disabled)").get(0);q.selectedIndex=r?r.index:0}})}function l(r,q){var i="([^ ]*)",s=function(u){return u.toString().replace(/[$]/g,"$$$$")};g.each(q,function(u){if(q&&q[u]!=undefined){var t=new RegExp("("+i+"%"+u+i+")");label="$2"+s(q[u])+"$3";if(q[u]===false){label=""}if(q[u]===""){label=""}r=r.replace(t,label)}});return r}}function catalogViewHandler(){var c=jqnc(),d=c("#shopp"),a=new Date(),b={list:"grid",grid:"list"};a.setTime(a.getTime()+(30*86400000));c.each(b,function(e,f){d.find("ul.views li button."+e).click(function(){d.removeClass(f).addClass(e);document.cookie="shopp_catalog_view="+e+"; expires="+a+"; path=/"}).hover(function(){c(this).toggleClass("hover")})})}function ShoppGallery(g,b,c){var e=jqnc(),a=e(g),d=a.find("ul.previews"),f=a.find("ul.thumbnails li");if(!b){b="click"}if(c){a.find("ul.thumbnails").css("width",c+"px")}f.bind(b,function(){var h,i=e("#"+e(this).attr("class").split(" ")[0]);if(!i.hasClass("active")){h=a.find("ul.previews li.active");i.addClass("active").hide();if(h.length){h.fadeOut(800,function(){h.removeClass("active")})}i.appendTo(d).fadeIn(500)}})}function ShoppSlideshow(g,e,h,d,c){var f=jqnc(),i=this,b;i.element=f(g);var b={fade:[{display:"none"},{opacity:"show"}],"slide-down":[{display:"block",top:i.element.height()*-1},{top:0}],"slide-up":[{display:"block",top:i.element.height()},{top:0}],"slide-left":[{display:"block",left:i.element.width()*-1},{left:0}],"slide-right":[{display:"block",left:i.element.width()},{left:0}],wipe:[{display:"block",height:0},{height:i.element.height()}]},a=["normal","reverse","shuffle"];i.duration=(!e)?800:e;i.delay=(!h)?7000:h;d=(!d)?"fade":d;i.effect=(!b[d])?b.fade:b[d];c=(!c)?"normal":c;i.order=(f.inArray(c,a)!=-1)?c:"normal";i.slides=f(i.element).find("li:not(li.clear)").hide().css("visibility","visible");i.total=i.slides.length;i.slide=0;i.shuffling=new Array();i.startTransition=function(){var j,k,l=f(i.slides[i.slide-1]).removeClass("active");f(i.slides[i.slide]).css(i.effect[0]).appendTo(i.element).animate(i.effect[1],i.duration,function(){l.css(i.effect[0])}).addClass("active");switch(i.order){case"shuffle":if(i.shuffling.length==0){i.shuffleList();j=f.inArray(i.slide,i.shuffling);if(j!=-1){i.shuffling.splice(j,1)}}k=Math.floor(Math.random()*i.shuffling.length);i.slide=i.shuffling[k];i.shuffling.splice(k,1);break;case"reverse":i.slide=(i.slide-1<0)?i.slides.length-1:i.slide-1;break;default:i.slide=(i.slide+1==i.total)?0:i.slide+1}if(i.slides.length==1){return}setTimeout(i.startTransition,i.delay)};i.transitionTo=function(j){i.slide=j;i.startTransition()};i.shuffleList=function(){for(var j=0;j<i.total;j++){i.shuffling.push(j)}};i.startTransition()}function slideshows(){var c=jqnc(),b,a,d;c("ul.slideshow").each(function(){b=c(this).attr("class");a={};d={fx:new RegExp(/([\w_-]+?)\-fx/),order:new RegExp(/([\w_-]+?)\-order/),duration:new RegExp(/duration\-(\d+)/),delay:new RegExp(/delay\-(\d+)/)};c.each(d,function(e,f){if(option=b.match(f)){a[e]=option[1]}});new ShoppSlideshow(this,a.duration,a.delay,a.fx,a.order)})}function ShoppCarousel(d,b){var c=jqnc(),g,h=this,a=1,i=c(d),e=i.find("ul"),f=e.find("> li");h.duration=(!b)?800:b;h.cframe=i.find("div.frame");a=Math.round(h.cframe.innerWidth()/f.outerWidth());if(a<1){a=1}g=Math.round(((h.cframe.innerWidth()%f.outerWidth())/f.length)/2);f.css("margin","0 "+g+"px");h.pageWidth=(f.outerWidth()+(g*2))*a;h.page=1;h.pages=Math.ceil(f.length/a);if((f.length%a)!=0){e.append(new Array(a-(f.length%a)+1).join('<li class="empty" style="width: '+f.outerWidth()+"px; height: 1px; margin: 0 "+g+'px"/>'));f=e.find("> li")}f.filter(":first").before(f.slice(-a).clone().addClass("cloned"));f.filter(":last").after(f.slice(0,a).clone().addClass("cloned"));f=e.find("> li");h.cframe.scrollLeft(h.pageWidth);h.scrollLeft=i.find("button.left");h.scrollRight=i.find("button.right");h.scrolltoPage=function(k){var j=k<h.page?-1:1,m=Math.abs(h.page-k),l=h.pageWidth*j*m;h.cframe.filter(":not(:animated)").animate({scrollLeft:"+="+l},h.duration,function(){if(k==0){h.cframe.scrollLeft(h.pageWidth*h.pages);k=h.pages}else{if(k>h.pages){h.cframe.scrollLeft(h.pageWidth);k=1}}h.page=k})};h.scrollLeft.click(function(){return h.scrolltoPage(h.page-1)});h.scrollRight.click(function(){return h.scrolltoPage(h.page+1)})}function carousels(){var c=jqnc(),b,a,d;c("div.carousel").each(function(){b=c(this).attr("class");a={};d={duration:new RegExp(/duration\-(\d+)/)};c.each(d,function(e,f){if(option=b.match(f)){a[e]=option[1]}});new ShoppCarousel(this,a.duration)})}function validate(a){if(!a){return false}var d=jqnc(),i=d(a),c=true,b=[],g=[],e=d(a).find("input,select,textarea").not(":hidden"),f="required",h="title";d.fn.reverse=(typeof[]._reverse=="undefined")?[].reverse:[]._reverse;d.each(e.reverse(),function(k,j){input=d(j).removeClass("error");label=d("label[for="+input.attr("id")+"]").removeClass("error");if(true===input.attr("disabled")||"disabled"==input.attr("disabled")){return}if(input.hasClass(f)&&input.val()==""){g=new Array($cv.field.replace(/%s/,input.attr(h)),j)}if(input.hasClass(f)&&input.attr("type")=="checkbox"&&!input.attr("checked")){g=new Array($cv.chkbox.replace(/%s/,input.attr(h)),j)}if(input.hasClass("email")&&!input.val().match(new RegExp(/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.([a-z][a-z0-9]+)|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i))){g=new Array($cv.email,j)}if(input.attr("class")&&(chars=input.attr("class").match(new RegExp("min(\\d+)")))){if(input.val()!=""&&input.val().length<chars[1]){g=new Array($cv.minlen.replace(/%s/,input.attr(h)).replace(/%d/,chars[1]),j)}}if(input.hasClass("passwords")){b.push(j);if(b.length==2&&b[0].value!=b[1].value){g=new Array($cv.pwdmm,b[1])}}if(g[1]&&g[1].id==input.attr("id")){input.addClass("error");label.addClass("error")}});i.data("error",g).trigger("shopp_validate");if("undefined"!=a.shopp_validation){i.data("error",a.shopp_validation)}if(i.data("error")){g=i.data("error");if(g[1]&&d("#"+g[1].id).length>0){d("#"+g[1].id).addClass("error");d("label[for="+g[1].id+"]").addClass("error")}}if(g.length>0){if(g[1] instanceof jQuery){g[1].focus()}if(d(a).hasClass("validation-alerts")){alert(g[0])}c=false}return c}function validateForms(){jQuery("form.validate").on("submit.validate",function(a){return validate(this)})}jQuery(document).ready(function(a){validateForms();catalogViewHandler();slideshows();carousels();if(a.fn.colorbox){a("a.shopp-zoom").colorbox({photo:true});a("a.shopp-zoom.gallery").each(function(){var b=a(this).attr("class").match(/product\_(\d+)/)[1];if(typeof(cbo)!="undefined"){a(this).attr("rel","gallery-"+b).colorbox(cbo)}else{a(this).attr("rel","gallery-"+b).colorbox({slideshow:true,slideshowSpeed:3500})}})}a("select.shopp-orderby-menu").change(function(){this.form.submit()});a("select.shopp-categories-menu").change(function(){document.location.href=a(this).val()});if($s.nocache){a(window).unload(function(){return})}});
  • shopp/trunk/core/ui/behaviors/checkout.js

    r821385 r930519  
    1919        checkoutButtons = $('.payoption-button'),
    2020        checkoutButton = $('.payoption-' + decodeURIComponent(d_pm)),
     21        submitButtons = checkoutButtons.find('input'),
    2122        checkoutProcess = $('#shopp-checkout-function'),
    2223        localeFields = $('#checkout.shopp li.locale');
     
    3031    }
    3132
     33    $.fn.extend({
     34        disableSubmit: function () {
     35            var $this = $(this);
     36            $this.data('timeout',
     37                setTimeout(function () { $this.enableSubmit(); alert($co.error); }, $co.timeout * 1000)
     38            );
     39            return $this.data('label',$this.val()).prop('disabled',true).addClass('disabled').val($co.submitting);
     40        },
     41        enableSubmit: function () {
     42            var $this = $(this);
     43            clearTimeout($this.data('timeout'));
     44            return $this.prop('disabled', false).removeClass('disabled').val($this.data('label'));
     45        },
     46    });
     47
     48    submitButtons.on('click', function () {
     49        $(this).disableSubmit();
     50        setTimeout(function () { checkoutForm.submit(); }, 1);
     51    });
     52
    3253    // Validate paycard number before submit
    33     checkoutForm.bind('shopp_validate',function () {
    34         if (!validcard()) this.shopp_validation = ["Not a valid card number.",billCard.get(0)];
     54    checkoutForm.on('shopp_validate', function () {
     55        if ( ! validcard() ) checkoutForm.data('error', [$co.badpan, billCard.get(0)]);
     56        if ( checkoutForm.data('error').length > 0 ) submitButtons.enableSubmit();
    3557    });
    3658
     
    4567
    4668        $('.paycard.xcsc').attr('disabled',true).addClass('disabled');
    47         if (!card || !card['inputs']) return;
    48 
    49         $.each(card['inputs'],function (input,inputlen) {
    50             $('#billing-xcsc-'+input).attr('disabled',false).removeClass('disabled');
     69        if ( ! card || ! card['inputs'] ) return;
     70
     71        $.each(card['inputs'], function (input,inputlen) {
     72            $('#billing-xcsc-'+input).attr('disabled', false).removeClass('disabled');
    5173        });
    5274
     
    6890
    6991    submitLogin.click(function (e) {
    70         checkoutForm.unbind('submit.validate').bind('submit.validlogin',function (e) {
     92        checkoutForm.unbind('submit.validate').bind('submit.validlogin', function (e) {
    7193            var error = false;
    72             if ('' == passwordLogin.val()) error = [$co.loginpwd,passwordLogin];
    73             if ('' == accountLogin.val()) error = [$co.loginname,accountLogin];
     94            if ( '' == passwordLogin.val() ) error = [$co.loginpwd, passwordLogin];
     95            if ( '' == accountLogin.val() ) error = [$co.loginname, accountLogin];
    7496            if (error) {
    7597                e.preventDefault();
  • shopp/trunk/core/ui/behaviors/checkout.min.js

    r821385 r930519  
    1 /*
     1/*!
    22 * checkout.js - Shopp catalog behaviors library
    33 * Copyright © 2008-2010 by Ingenesis Limited
    44 * Licensed under the GPLv3 {@see license.txt}
    55 */
    6 jQuery(document).ready(function(){var $=jqnc(),login=false,sameaddr=$(".sameaddress"),submitLogin=$("#submit-login-checkout"),accountLogin=$("#account-login-checkout"),passwordLogin=$("#password-login-checkout"),guest=$("#guest-checkout"),checkoutForm=$("#checkout.shopp"),paymethods=$("#checkout.shopp [name=paymethod]"),localeMenu=$("#billing-locale"),billCard=$("#billing-card"),billCardtype=$("#billing-cardtype"),checkoutButtons=$(".payoption-button"),checkoutButton=$(".payoption-"+decodeURIComponent(d_pm)),checkoutProcess=$("#shopp-checkout-function"),localeFields=$("#checkout.shopp li.locale");if(checkoutForm.find("input[name=checkout]").val()=="process"){checkoutButtons.hide();if(checkoutButton.length==0){checkoutButton=$(".payoption-0")}checkoutButton.show();paymethods.change(paymethod_select).change()}checkoutForm.bind("shopp_validate",function(){if(!validcard()){this.shopp_validation=["Not a valid card number.",billCard.get(0)]}});billCard.change(validcard);billCardtype.change(function(){var cardtype=new String(billCardtype.val()).toLowerCase(),card=paycards[cardtype];$(".paycard.xcsc").attr("disabled",true).addClass("disabled");if(!card||!card.inputs){return}$.each(card.inputs,function(input,inputlen){$("#billing-xcsc-"+input).attr("disabled",false).removeClass("disabled")})}).change();billCardtype.change(function(){var cardtype=new String(billCardtype.val()).toLowerCase();for(var key in paycards){if(checkoutForm.hasClass("cardtype-"+key)){checkoutForm.removeClass("cardtype-"+key)}}checkoutForm.addClass("cardtype-"+cardtype)}).change();if(localeMenu.children().size()==0){localeFields.hide()}submitLogin.click(function(e){checkoutForm.unbind("submit.validate").bind("submit.validlogin",function(e){var error=false;if(""==passwordLogin.val()){error=[$co.loginpwd,passwordLogin]}if(""==accountLogin.val()){error=[$co.loginname,accountLogin]}if(error){e.preventDefault();checkoutForm.unbind("submit.validlogin").bind("submit.validate",function(e){return validate(this)});alert(error[0]);error[1].focus().addClass("error");return false}checkoutProcess.val("login")})});$("#billing-country, .billing-state, #shipping-country, .shipping-state").bind("change.localemenu",function(e,init){var sameaddress=sameaddr.is(":checked")?sameaddr.val():false,country="shipping"==sameaddress?$("#billing-country").val():$("#shipping-country").val(),state="shipping"==sameaddress?$('.billing-state[disabled!="true"]').val():$('.shipping-state[disabled!="true"]').val(),id=country+state,options,locale;if(init||!localeMenu.get(0)||(!sameaddress&&($(this).is("#billing-country")||$(this).is(".billing-state")))){return}localeMenu.empty().attr("disabled",true);if(locales&&(locale=locales[id])||(locale=locales[country])){options+="<option></option>";$.each(locale,function(index,label){options+='<option value="'+label+'">'+label+"</option>"});$(options).appendTo(localeMenu);localeMenu.removeAttr("disabled");localeFields.show()}});guest.change(function(e){var passwords=checkoutForm.find("input.passwords"),labels=[];$.each(passwords,function(){labels.push("label[for="+$(this).attr("id")+"]")});labels=checkoutForm.find(labels.join(","));if(guest.is(":checked")){passwords.setDisabled(true).hide();labels.hide()}else{passwords.setDisabled(false).show();labels.show()}}).trigger("change");$("#shopp form").on("change",".shipmethod",function(){if($.inArray($("#checkout #shopp-checkout-function").val(),["process","confirmed"])!=-1){var prefix=".shopp-cart.cart-",spans="span"+prefix,inputs="input"+prefix,fields=["shipping","tax","total"],selectors=[],values={},retry=0,disableset=".shopp .shipmethod, .payoption-button input",$this=$(this),send=function(){$(disableset).attr("disabled",true);$.getJSON($co.ajaxurl+"?action=shopp_ship_costs&method="+$this.val(),function(r){if(!r&&retry++<2){return setTimeout(send,1000)}$(disableset).attr("disabled",false);$.each(fields,function(i,name){if(!r||undefined==r[name]){$(spans+name).html(values[name]);return}$(spans+name).html(asMoney(new Number(r[name])));$(inputs+name).val(new Number(r[name]))})})};$.each(fields,function(i,name){selectors.push(spans+name);values[name]=$(spans+name).html()});if(!c_upd){c_upd="?"}$(selectors.join(",")).html(c_upd);send()}else{$(this).parents("form").submit()}});$(window).load(function(){$(document).trigger("shopp_paymethod",[paymethods.val()])});function paymethod_select(e){var $this=$(this),paymethod=decodeURIComponent($(this).val()),checkoutButton=$(".payoption-"+paymethod),options="",pc=false;if(this!=window&&$this.attr&&"radio"==$this.attr("type")&&!$this.is(":checked")){return}$(document).trigger("shopp_paymethod",[paymethod]);checkoutButtons.hide();if(checkoutButton.length==0){checkoutButton=$(".payoption-0")}if(pm_cards[paymethod]&&pm_cards[paymethod].length>0){checkoutForm.find(".payment,.paycard").show();checkoutForm.find(".paycard.disabled").attr("disabled",false).removeClass("disabled");if(typeof(paycards)!=="undefined"){$.each(pm_cards[paymethod],function(a,s){if(!paycards[s]){return}pc=paycards[s];options+='<option value="'+pc.symbol+'">'+pc.name+"</option>"});billCardtype.html(options).change()}}else{checkoutForm.find(".payment,.paycard").hide();checkoutForm.find(".paycard").attr("disabled",true).addClass("disabled")}checkoutButton.show()}function validcard(){if(billCard.length==0){return true}if(billCard.attr("disabled")){return true}var v=billCard.val().replace(/\D/g,""),paymethod=paymethods.filter(":checked").val()?paymethods.filter(":checked").val():paymethods.val(),card=false;if(!paymethod){paymethod=decodeURIComponent(d_pm)}if(billCard.val().match(/(X)+\d{4}/)){return true}if(!pm_cards[paymethod]){return true}$.each(pm_cards[paymethod],function(a,s){var pc=paycards[s],pattern=new RegExp(pc.pattern.substr(1,pc.pattern.length-2));if(v.match(pattern)){card=pc.symbol;return billCardtype.val(card).change()}});if(!luhn(v)){return false}return card}function luhn(n){n=n.toString().replace(/\D/g,"").split("").reverse();if(!n.length){return false}var total=0;for(i=0;i<n.length;i++){n[i]=parseInt(n[i],10);total+=i%2?2*n[i]-(n[i]>4?9:0):n[i]}return(total%10)==0}});if(!locales){var locales=false};
     6jQuery(document).ready(function(){var d=jqnc(),m=false,e=d(".sameaddress"),c=d("#submit-login-checkout"),n=d("#account-login-checkout"),j=d("#password-login-checkout"),l=d("#guest-checkout"),k=d("#checkout.shopp"),q=d("#checkout.shopp [name=paymethod]"),a=d("#billing-locale"),s=d("#billing-card"),o=d("#billing-cardtype"),u=d(".payoption-button"),b=d(".payoption-"+decodeURIComponent(d_pm)),r=u.find("input"),p=d("#shopp-checkout-function"),h=d("#checkout.shopp li.locale");if(k.find("input[name=checkout]").val()=="process"){u.hide();if(b.length==0){b=d(".payoption-0")}b.show();q.change(g).change()}d.fn.extend({disableSubmit:function(){var v=d(this);v.data("timeout",setTimeout(function(){v.enableSubmit();alert($co.error)},$co.timeout*1000));return v.data("label",v.val()).prop("disabled",true).addClass("disabled").val($co.submitting)},enableSubmit:function(){var v=d(this);clearTimeout(v.data("timeout"));return v.prop("disabled",false).removeClass("disabled").val(v.data("label"))}});r.on("click",function(){d(this).disableSubmit();setTimeout(function(){k.submit()},1)});k.on("shopp_validate",function(){if(!f()){k.data("error",[$co.badpan,s.get(0)])}if(k.data("error").length>0){r.enableSubmit()}});s.change(f);o.change(function(){var w=new String(o.val()).toLowerCase(),v=paycards[w];d(".paycard.xcsc").attr("disabled",true).addClass("disabled");if(!v||!v.inputs){return}d.each(v.inputs,function(x,y){d("#billing-xcsc-"+x).attr("disabled",false).removeClass("disabled")})}).change();o.change(function(){var v=new String(o.val()).toLowerCase();for(var w in paycards){if(k.hasClass("cardtype-"+w)){k.removeClass("cardtype-"+w)}}k.addClass("cardtype-"+v)}).change();if(a.children().size()==0){h.hide()}c.click(function(v){k.unbind("submit.validate").bind("submit.validlogin",function(x){var w=false;if(""==j.val()){w=[$co.loginpwd,j]}if(""==n.val()){w=[$co.loginname,n]}if(w){x.preventDefault();k.unbind("submit.validlogin").bind("submit.validate",function(y){return validate(this)});alert(w[0]);w[1].focus().addClass("error");return false}p.val("login")})});d("#billing-country, .billing-state, #shipping-country, .shipping-state").bind("change.localemenu",function(y,B){var A=e.is(":checked")?e.val():false,z="shipping"==A?d("#billing-country").val():d("#shipping-country").val(),x="shipping"==A?d('.billing-state[disabled!="true"]').val():d('.shipping-state[disabled!="true"]').val(),C=z+x,w,v;if(B||!a.get(0)||(!A&&(d(this).is("#billing-country")||d(this).is(".billing-state")))){return}a.empty().attr("disabled",true);if(locales&&(v=locales[C])||(v=locales[z])){w+="<option></option>";d.each(v,function(E,D){w+='<option value="'+D+'">'+D+"</option>"});d(w).appendTo(a);a.removeAttr("disabled");h.show()}});l.change(function(v){var w=k.find("input.passwords"),x=[];d.each(w,function(){x.push("label[for="+d(this).attr("id")+"]")});x=k.find(x.join(","));if(l.is(":checked")){w.setDisabled(true).hide();x.hide()}else{w.setDisabled(false).show();x.show()}}).trigger("change");d("#shopp form").on("change",".shipmethod",function(){if(d.inArray(d("#checkout #shopp-checkout-function").val(),["process","confirmed"])!=-1){var x=".shopp-cart.cart-",A="span"+x,y="input"+x,z=["shipping","tax","total"],D=[],E={},v=0,C=".shopp .shipmethod, .payoption-button input",B=d(this),w=function(){d(C).attr("disabled",true);d.getJSON($co.ajaxurl+"?action=shopp_ship_costs&method="+B.val(),function(F){if(!F&&v++<2){return setTimeout(w,1000)}d(C).attr("disabled",false);d.each(z,function(H,G){if(!F||undefined==F[G]){d(A+G).html(E[G]);return}d(A+G).html(asMoney(new Number(F[G])));d(y+G).val(new Number(F[G]))})})};d.each(z,function(G,F){D.push(A+F);E[F]=d(A+F).html()});if(!c_upd){c_upd="?"}d(D.join(",")).html(c_upd);w()}else{d(this).parents("form").submit()}});d(window).load(function(){d(document).trigger("shopp_paymethod",[q.val()])});function g(A){var z=d(this),y=decodeURIComponent(d(this).val()),v=d(".payoption-"+y),x="",w=false;if(this!=window&&z.attr&&"radio"==z.attr("type")&&!z.is(":checked")){return}d(document).trigger("shopp_paymethod",[y]);u.hide();if(v.length==0){v=d(".payoption-0")}if(pm_cards[y]&&pm_cards[y].length>0){k.find(".payment,.paycard").show();k.find(".paycard.disabled").attr("disabled",false).removeClass("disabled");if(typeof(paycards)!=="undefined"){d.each(pm_cards[y],function(B,C){if(!paycards[C]){return}w=paycards[C];x+='<option value="'+w.symbol+'">'+w.name+"</option>"});o.html(x).change()}}else{k.find(".payment,.paycard").hide();k.find(".paycard").attr("disabled",true).addClass("disabled")}v.show()}function f(){if(s.length==0){return true}if(s.attr("disabled")){return true}var w=s.val().replace(/\D/g,""),y=q.filter(":checked").val()?q.filter(":checked").val():q.val(),x=false;if(!y){y=decodeURIComponent(d_pm)}if(s.val().match(/(X)+\d{4}/)){return true}if(!pm_cards[y]){return true}d.each(pm_cards[y],function(v,A){var z=paycards[A],B=new RegExp(z.pattern.substr(1,z.pattern.length-2));if(w.match(B)){x=z.symbol;return o.val(x).change()}});if(!t(w)){return false}return x}function t(w){w=w.toString().replace(/\D/g,"").split("").reverse();if(!w.length){return false}var v=0;for(i=0;i<w.length;i++){w[i]=parseInt(w[i],10);v+=i%2?2*w[i]-(w[i]>4?9:0):w[i]}return(v%10)==0}});if(!locales){var locales=false};
  • shopp/trunk/core/ui/behaviors/editors.js

    r821385 r930519  
    618618            .find('input.id')
    619619            .each(function (id,option) {
    620                 var optionid = $(option).val(),dbPriceid, dP=$('#deletePrices');;
     620                var optionid = $(option).val(),dbPriceid, dP=$('#deletePrices');
    621621                if (Pricelines.row[optionid]) {
    622622                    dbPriceid = Pricelines.row[optionid].data.id;
  • shopp/trunk/core/ui/behaviors/setup.js

    r821385 r930519  
    2020        $.getJSON(zones_url+'&action=shopp_country_zones&country='+baseop.val(),
    2121            function(data) {
    22                 baseopZone.hide().empty().attr('disabled',true);;
     22                baseopZone.hide().empty().attr('disabled',true);
    2323                if (!data) return true;
    2424
  • shopp/trunk/core/ui/behaviors/tinymce/dialog.php

    r821385 r930519  
    8080
    8181                if (window.tinyMCE) {
    82                     window.tinyMCE.execInstanceCommand('content', 'mceInsertContent', false, tag);
     82                    var tmce_ver = window.tinyMCE.majorVersion;
     83                    if ( tmce_ver >= "4" ) {
     84                        window.tinyMCE.execCommand('mceInsertContent', false, tag);
     85                    } else {
     86                        window.tinyMCE.execInstanceCommand('content', 'mceInsertContent', false, tag);
     87                    }
    8388                    tinyMCEPopup.editor.execCommand('mceRepaint');
    8489                    tinyMCEPopup.close();
  • shopp/trunk/core/ui/categories/products.js

    r821385 r930519  
    7676            $.ajax({
    7777                url:updates_url+"&action=shopp_category_products_order",
    78                 timeout:3000,
     78                timeout:5000,
    7979                type: "POST",
    8080                datatype:'text',
    8181                data:updates.serialize(),
    82                 success:function (result) {
     82                success:function (r) {
     83                    updating.hide();
     84                },
     85                error:function (r, e) {
    8386                    updating.hide();
    8487                }
    8588            });
    86 
    87 
    8889        }
    89 
    9090
    9191    };
  • shopp/trunk/core/ui/categories/products.min.js

    r821385 r930519  
    1 jQuery(document).ready(function(){var a=jqnc();a.fn.dragrow=function(b){var e=a(this),c=e.find("tbody > tr"),f=typeof a(document).attr("onselectstart")!="undefined",d={onDrop:function(){}},b=a.extend(d,b);return c.bind("mousedown.dragrow",function(h){var g=a(this).fadeTo("fast",0.4);lastY=h.pageY;a("tr",g.parent()).not(g).bind("mouseenter.dragrow",function(){var i=a(this);if(h.pageY>lastY){i.after(g)}else{i.before(g)}lastY=h.pageY});a("body").bind("mouseup.dragrow",function(){g.fadeTo("fast",1);a("tr",g.parent()).unbind("mouseenter.dragrow");a("body").unbind("mouseup.dragrow");if(f){a(document).unbind("selectstart")}b.onDrop(g)});h.preventDefault();if(f){a(document).bind("selectstart",function(){return false})}return false}).css("cursor","move")};a.fn.arrangeRows=function(c){var d=a(this);d.dragrow({onDrop:b});b();d.find("button[name=top]").hover(function(){a(this).toggleClass("hover")}).click(function(){var f=a(this).parent().parent(),e=f.find("input[name^=position]");if(e.val()==0){return false}f.insertBefore(f.parent().find("tr:first"));b()});d.find("button[name=bottom]").hover(function(){a(this).toggleClass("hover")}).click(function(){var f=a(this).parent().parent(),e=f.find("input[name^=position]");f.insertAfter(f.parent().find("tr:last"));b()});function b(){var f=a("#category-id"),e=d.find("th.column-move img");d.find("tbody tr input[name^=position]").each(function(j,i){var h=a(i),g=j+1;if((h.attr("alt")!=""&&g!=h.attr("alt"))||h.val()=="0"){h.val(g).attr("alt",g);f=f.add(h)}else{if(h.attr("alt")==""){h.val(g).attr("alt",g)}else{h.val(g)}}});if(f.size()==1){return}e.hide().show();a.ajax({url:updates_url+"&action=shopp_category_products_order",timeout:3000,type:"POST",datatype:"text",data:f.serialize(),success:function(g){e.hide()}})}};a("#arrange-products").arrangeRows()});
     1jQuery(document).ready(function(){var a=jqnc();a.fn.dragrow=function(b){var e=a(this),c=e.find("tbody > tr"),f=typeof a(document).attr("onselectstart")!="undefined",d={onDrop:function(){}},b=a.extend(d,b);return c.bind("mousedown.dragrow",function(h){var g=a(this).fadeTo("fast",0.4);lastY=h.pageY;a("tr",g.parent()).not(g).bind("mouseenter.dragrow",function(){var i=a(this);if(h.pageY>lastY){i.after(g)}else{i.before(g)}lastY=h.pageY});a("body").bind("mouseup.dragrow",function(){g.fadeTo("fast",1);a("tr",g.parent()).unbind("mouseenter.dragrow");a("body").unbind("mouseup.dragrow");if(f){a(document).unbind("selectstart")}b.onDrop(g)});h.preventDefault();if(f){a(document).bind("selectstart",function(){return false})}return false}).css("cursor","move")};a.fn.arrangeRows=function(c){var d=a(this);d.dragrow({onDrop:b});b();d.find("button[name=top]").hover(function(){a(this).toggleClass("hover")}).click(function(){var f=a(this).parent().parent(),e=f.find("input[name^=position]");if(e.val()==0){return false}f.insertBefore(f.parent().find("tr:first"));b()});d.find("button[name=bottom]").hover(function(){a(this).toggleClass("hover")}).click(function(){var f=a(this).parent().parent(),e=f.find("input[name^=position]");f.insertAfter(f.parent().find("tr:last"));b()});function b(){var f=a("#category-id"),e=d.find("th.column-name .shoppui-spinner");d.find("tbody tr input[name^=position]").each(function(j,i){var h=a(i),g=j+1;if((h.attr("alt")!=""&&g!=h.attr("alt"))||h.val()=="0"){h.val(g).attr("alt",g);f=f.add(h)}else{if(h.attr("alt")==""){h.val(g).attr("alt",g)}else{h.val(g)}}});if(f.size()==1){return}e.hide().show();a.ajax({url:updates_url+"&action=shopp_category_products_order",timeout:5000,type:"POST",datatype:"text",data:f.serialize(),success:function(g){e.hide()},error:function(g,h){e.hide()}})}};a("#arrange-products").arrangeRows()});
  • shopp/trunk/core/ui/orders/events.php

    r821385 r930519  
    424424
    425425    function details () {
     426        if ( 'NOTRACKING' == $this->carrier_name() )
     427            return Shopp::__('No Tracking');
    426428        return sprintf('%s: %s',$this->carrier_name(),$this->tracklink());
    427429    }
  • shopp/trunk/core/ui/orders/order.php

    r905841 r930519  
    4343                foreach ($columns as $column => $column_title) {
    4444                    $classes = array($column,"column-$column");
    45                     if ( in_array($column,$hidden) ) $classes[] = 'hidden';
     45                    if ( in_array($column, $hidden) ) $classes[] = 'hidden';
    4646
    4747                    switch ($column) {
     
    157157                        <tr class="<?php echo esc_attr(join(' ',$rowclasses)); ?>">
    158158                    <?php
    159 
    160159                        if ( isset($_GET['editline']) && (int)$_GET['editline'] == $id ) {
    161160                            $data = array(
    162                                 '${lineid}' => (int)$_GET['editline'],
    163                                 '${itemname}' => $itemname,
    164                                 '${quantity}' => $Item->quantity,
    165                                 '${unitprice}'     => money($Item->unitprice),
    166                                 '${total}'    => money( $Item->total+($Purchase->taxing != 'inclusive'?$Item->unittax*$Item->quantity:0) )
     161                                '${lineid}'    => (int)$_GET['editline'],
     162                                '${itemname}'  => $itemname,
     163                                '${quantity}'  => $Item->quantity,
     164                                '${unitprice}' => money($Item->unitprice),
     165                                '${total}'     => money($Item->total)
    167166                            );
    168                             echo ShoppUI::template($itemeditor,$data);
     167                            echo ShoppUI::template($itemeditor, $data);
    169168                        } else {
    170169
    171170                            foreach ($columns as $column => $column_title) {
    172                                 $classes = array($column,"column-$column");
    173                                 if ( in_array($column,$hidden) ) $classes[] = 'hidden';
     171                                $classes = array($column, "column-$column");
     172                                if ( in_array($column, $hidden) ) $classes[] = 'hidden';
    174173
    175174                                ob_start();
    176                                 switch ($column) {
     175                                switch ( $column ) {
    177176                                    case 'items':
    178177                                    ShoppProduct( new ShoppProduct($Item->product) ); // @todo Find a way to make this more efficient by loading product slugs with load_purchased()?
    179178                                    $viewurl = shopp('product.get-url');
    180                                     $editurl = ShoppAdminController::url( array('id' => $Purchase->id, 'editline'=>$id) );
    181                                     $rmvurl = ShoppAdminController::url( array('id' => $Purchase->id, 'rmvline'=>$id) );
     179                                    $editurl = ShoppAdminController::url( array('id' => $Purchase->id, 'editline'=> $id) );
     180                                    $rmvurl = ShoppAdminController::url( array('id' => $Purchase->id, 'rmvline'=> $id) );
     181                                    $producturl = add_query_arg( array('page' => 'shopp-products', 'id' => $Item->product), admin_url('admin.php') );
    182182                                        ?>
    183183                                            <td class="<?php echo esc_attr(join(' ',$classes)); ?>">
    184                                                 <a href="<?php echo add_query_arg(array('page' => 'shopp-products','id' => $Item->product),admin_url('admin.php')); ?>">
     184                                                <a href="<?php echo $producturl; ?>">
    185185                                                    <?php
    186186                                                    $Product = new ShoppProduct($Item->product);
     
    193193                                                    <?php
    194194                                                    }
    195                                                     echo $Item->name;
    196                                                     if (!empty($Item->optionlabel)) echo "({$Item->optionlabel})"; ?>
     195                                                    echo apply_filters('shopp_purchased_item_name', $itemname); ?>
    197196                                                </a>
    198197                                                <div class="row-actions">
     
    206205                                                <?php if (!empty($Item->sku)): ?><li><small><?php _e('SKU','Shopp'); ?>: <strong><?php echo $Item->sku; ?></strong></small></li><?php endif; ?>
    207206
    208                                                 <?php if (isset($Item->addons) && isset($Item->addons->meta)): ?>
    209                                                     <?php foreach ((array)$Item->addons->meta as $id => $addon):
    210                                                         if ( $Purchase->taxing != "inclusive" )
    211                                                             $addonprice = $addon->value->unitprice+($addon->value->unitprice*$taxrate);
     207                                                <?php if ( isset($Item->addons) && isset($Item->addons->meta) ): ?>
     208                                                    <?php foreach ( (array)$Item->addons->meta as $id => $addon ):
     209                                                        if ( "inclusive" != $Purchase->taxing )
     210                                                            $addonprice = $addon->value->unitprice + ( $addon->value->unitprice * $taxrate );
    212211                                                        else $addonprice = $addon->value->unitprice;
    213212
    214213                                                        ?>
    215                                                         <li><small><?php echo apply_filters('shopp_purchased_addon_name',$addon->name); ?><?php if (!empty($addon->value->sku)) echo apply_filters('shopp_purchased_addon_sku',' [SKU: '.$addon->value->sku.']'); ?>: <strong><?php echo apply_filters('shopp_purchased_addon_unitprice',money($addonprice)); ?></strong></small></li>
     214                                                        <li><small><?php echo apply_filters('shopp_purchased_addon_name', $addon->name); ?><?php if ( ! empty($addon->value->sku) ) echo apply_filters('shopp_purchased_addon_sku',' [SKU: ' . $addon->value->sku . ']'); ?>: <strong><?php echo apply_filters('shopp_purchased_addon_unitprice', money($addonprice)); ?></strong></small></li>
    216215                                                    <?php endforeach; ?>
    217216                                                <?php endif; ?>
    218                                                 <?php foreach ($Item->data as $name => $value): ?>
    219                                                     <li><small><?php echo apply_filters('shopp_purchased_data_name',$name); ?>: <strong><?php echo apply_filters('shopp_purchased_data_value',$value); ?></strong></small></li>
     217                                                <?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>
    220219                                                <?php endforeach; ?>
    221220                                                <?php endif; ?>
    222                                                 <?php do_action_ref_array('shopp_after_purchased_data',array(&$Item,&$Purchase)); ?>
     221                                                <?php do_action_ref_array('shopp_after_purchased_data', array($Item, $Purchase)); ?>
    223222                                                </ul>
    224223                                            </td>
     
    229228                                        $classes[] = 'num';
    230229                                        ?>
    231                                             <td class="<?php echo esc_attr(join(' ',$classes)); ?>"><?php echo $Item->quantity; ?></td>
     230                                            <td class="<?php echo esc_attr(join(' ', $classes)); ?>"><?php echo $Item->quantity; ?></td>
    232231                                        <?php
    233232                                        break;
     
    236235                                    $classes[] = 'money';
    237236                                        ?>
    238                                             <td class="<?php echo esc_attr(join(' ',$classes)); ?>"><?php $amount = $Item->unitprice+($Purchase->taxing != 'inclusive'?$Item->unittax:0);
    239                                                 echo money($amount); ?></td>
     237                                            <td class="<?php echo esc_attr(join(' ', $classes)); ?>"><?php echo money($Item->unitprice); ?></td>
    240238                                        <?php
    241239                                        break;
     
    244242                                        $classes[] = 'money';
    245243                                        ?>
    246                                             <td class="<?php echo esc_attr(join(' ',$classes)); ?>"><?php $amount = $Item->total+($Purchase->taxing != 'inclusive'?$Item->unittax*$Item->quantity:0);
    247                                                 echo money($amount); ?></td>
     244                                            <td class="<?php echo esc_attr(join(' ', $classes)); ?>"><?php echo money($Item->total); ?></td>
    248245                                        <?php
    249246                                        break;
     
    251248                                    default:
    252249                                        ?>
    253                                             <td class="<?php echo esc_attr(join(' ',$classes)); ?>">
     250                                            <td class="<?php echo esc_attr(join(' ', $classes)); ?>">
    254251                                            <?php do_action( 'shopp_manage_order_' . sanitize_key($column) .'_column_data', $column, $Product, $Item, $Purchase ); ?>
    255252                                            </td>
     
    259256                                $output = ob_get_contents();
    260257                                ob_end_clean();
    261                                 echo apply_filters('shopp_manage_order_'.$column.'_column',$output);
     258                                echo apply_filters('shopp_manage_order_' . $column . '_column', $output);
    262259                            }
    263260                        }
  • shopp/trunk/core/ui/reports/sales.php

    r831831 r930519  
    3232        $where[] = "$starts < " . self::unixtime('o.created');
    3333        $where[] = "$ends > " . self::unixtime('o.created');
    34         $where[] = "o.txnstatus IN ('authed', 'captured', 'CHARGED')";;
     34        $where[] = "o.txnstatus IN ('authed', 'captured', 'CHARGED')";
    3535
    3636        $where = join(" AND ",$where);
  • shopp/trunk/core/ui/reports/tax.php

    r831831 r930519  
    2121        $where[] = "$starts < " . self::unixtime('o.created');
    2222        $where[] = "$ends > " . self::unixtime('o.created');
     23        $where[] = "o.txnstatus IN ('authed', 'captured', 'CHARGED')";
    2324
    2425        $where = join(" AND ",$where);
     
    2627        $orders_table = ShoppDatabaseObject::tablename('purchase');
    2728        $purchased_table = ShoppDatabaseObject::tablename('purchased');
     29
    2830        $query = "SELECT CONCAT($id) AS id,
    2931                            UNIX_TIMESTAMP(o.created) as period,
    3032                            COUNT(DISTINCT o.id) AS orders,
    3133                            SUM(o.subtotal) as subtotal,
    32                             SUM(IF(p.unittax > 0,p.total,0)) AS taxable,
    33                             AVG(p.unittax/p.unitprice) AS rate,
     34                            ( SELECT SUM(IF(p.unittax > 0,p.total,0)) FROM $purchased_table AS p WHERE o.id = p.purchase ) AS taxable,
     35                            ( SELECT AVG(p.unittax/p.unitprice) FROM $purchased_table AS p WHERE o.id = p.purchase ) AS rate,
    3436                            SUM(o.tax) as tax
    35                     FROM $purchased_table AS p
    36                     JOIN $orders_table AS o ON p.purchase=o.id
     37                    FROM $orders_table AS o
    3738                    WHERE $where
    3839                    GROUP BY CONCAT($id)";
     
    4344    function columns () {
    4445        return array(
    45             'period'=>__('Period','Shopp'),
    46             'orders'=>__('Orders','Shopp'),
    47             'subtotal'=>__('Subtotal','Shopp'),
    48             'taxable'=>__('Taxable Amount','Shopp'),
    49             'rate'=>__('Tax Rate','Shopp'),
    50             'tax'=>__('Total Tax','Shopp')
     46            'period'   => Shopp::__('Period'),
     47            'orders'   => Shopp::__('Orders'),
     48            'subtotal' => Shopp::__('Subtotal'),
     49            'taxable'  => Shopp::__('Taxable Amount'),
     50            'rate'     => Shopp::__('Tax Rate'),
     51            'tax'      => Shopp::__('Total Tax')
    5152        );
    5253    }
    5354
    54     static function orders ($data) { return intval($data->orders); }
     55    static function orders ( $data ) { return intval($data->orders); }
    5556
    56     static function subtotal ($data) { return money($data->subtotal); }
     57    static function subtotal ( $data ) { return money($data->subtotal); }
    5758
    58     static function taxable ($data) { return money($data->taxable); }
     59    static function taxable ( $data ) { return money($data->taxable); }
    5960
    60     static function tax ($data) { return money($data->tax); }
     61    static function tax ( $data ) { return money($data->tax); }
    6162
    62     static function rate ($data) { return percentage($data->rate*100); }
     63    static function rate ( $data ) { return percentage($data->rate * 100); }
    6364
    6465}
  • shopp/trunk/core/ui/settings/advanced.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/checkout.php

    r821385 r930519  
    33    <?php
    44
    5         shopp_admin_screen_tabs();;
     5        shopp_admin_screen_tabs();
    66        do_action('shopp_admin_notices');
    77
  • shopp/trunk/core/ui/settings/downloads.php

    r821385 r930519  
    33    <?php
    44
    5         shopp_admin_screen_tabs();;
     5        shopp_admin_screen_tabs();
    66        do_action('shopp_admin_notices');
    77
  • shopp/trunk/core/ui/settings/images.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/log.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/management.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/pages.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/payments.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/presentation.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/setup.php

    r865739 r930519  
    55    <?php
    66
    7         shopp_admin_screen_tabs();;
     7        shopp_admin_screen_tabs();
    88        do_action('shopp_admin_notices');
    99
  • shopp/trunk/core/ui/settings/shipping.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/shiprates.php

    r821385 r930519  
    33    <?php
    44
    5         shopp_admin_screen_tabs();;
     5        shopp_admin_screen_tabs();
    66        do_action('shopp_admin_notices');
    77
  • shopp/trunk/core/ui/settings/storage.php

    r821385 r930519  
    44    <?php
    55
    6         shopp_admin_screen_tabs();;
     6        shopp_admin_screen_tabs();
    77        do_action('shopp_admin_notices');
    88
  • shopp/trunk/core/ui/settings/taxes.php

    r821385 r930519  
    33    <?php
    44
    5         shopp_admin_screen_tabs();;
     5        shopp_admin_screen_tabs();
    66        do_action('shopp_admin_notices');
    77
  • shopp/trunk/core/ui/settings/taxrates.php

    r905841 r930519  
    33    <?php
    44
    5         shopp_admin_screen_tabs();;
     5        shopp_admin_screen_tabs();
    66        do_action('shopp_admin_notices');
    77
  • shopp/trunk/core/ui/styles/admin.css

    r905841 r930519  
    4040#products-manager .column-name img { margin-right: 3px; }
    4141
    42 .column-featured .feature { font-size: 16px; display: block; border: none; padding: 0; margin: 0 auto; }
     42.column-featured .feature { font-size: 16px; display: inline-block; border: none; padding: 0; margin: 0 auto; }
    4343.column-featured .shoppui-star { font-family: 'shopp-icons'; color: #B1B1B1; background: -webkit-linear-gradient(top, #fff, #E8E8E8 50%, #CDCDCD 60%, #BDBDBD); -webkit-background-clip: text; -webkit-text-fill-color: transparent; position: relative; }
    4444.column-featured .shoppui-star:hover { font-family: 'shopp-icons'; color: #B1B1B1; background: -webkit-linear-gradient(top, #fff, #E8E8E8 50%, #CDCDCD 60%, #BDBDBD); -webkit-background-clip: text; -webkit-text-fill-color: transparent; position: relative; }
     
    557557#order .right-column { width:100%;display: inline;}
    558558#order #main-column { margin-left:280px; }
     559#order .column-qty { text-align: center; }
    559560
    560561#order .meta-boxes .inside { line-height:1.3em; }
     
    760761tr.inline-edit-row td  { padding: 10px; border-bottom: 1px solid #e1e1e1; border-top: 1px solid #e1e1e1; }
    761762.inline-edit-row label { line-height: 20px; font-size: 11px; }
    762 
    763763.inline-edit-row span { display: inline-block; }
     764.shopp-settings td > div { padding-bottom: 8px; }
    764765
    765766#order-contact iframe { width: 100%; }
  • shopp/trunk/core/ui/styles/catalog.css

    r821385 r930519  
    1818
    1919.shopp_page div.description,
    20 .shopp_page .products,
    21 .shopp_page .products ul,
    22 .shopp_page .products li.row,
    23 .shopp_page .category,
    2420.shopp_page .cart,
    2521.shopp_page .cart table {overflow:hidden;}
     
    6056
    6157/* Category Products */
    62 .shopp_page .products {text-indent:0;text-align:left;padding:0;margin:0;}
    63 .shopp_page .products li {background:none;padding:0;margin:0;list-style:none;}
     58.shopp_page .products {text-indent:0;text-align:left;padding:0;margin:0;list-style:none;zoom:1;}
     59.shopp_page .products:before,
     60.shopp_page .products:after {content:"";display: table;}
     61.shopp_page .products:after {clear:both;}
     62
     63.shopp_page .products .product {background:none;padding:0;margin:0;list-style:none;}
    6464
    6565.shopp_page  .frame { border: none; }
    66 .shopp_page .products, .shopp_page .products ul { position: relative; width: 100%; margin: 0; padding: 0; overflow: hidden; }
    67 .shopp_page .products li.product { float: left; position: relative; }
    68 .shopp_page .products li.product.first { clear: both; }
     66.shopp_page .products, .shopp_page .products ul { position: relative; width: 100%; margin: 0; padding: 0; }
     67.shopp_page .products > .product { float: left; position: relative; }
     68.shopp_page .products > .product.first { clear: both; margin-left: 0; }
     69.shopp-product ul,
     70.shopp-product ol { display: inline-block; }
     71.shopp-product ul.breadcrumb,
     72.shopp-product ul.variations { padding-left: 0; }
    6973
    7074/* Deprecated row class support */
     
    8185.shopp_page .tagcloud li,
    8286.shopp.tagcloud li {display:inline;margin-right:10px;line-height:1.2;padding:0;background-image:none;}
    83 .shopp.tagcloud li.level-1 {font-size: 2em;}
    84 .shopp.tagcloud li.level-2 {font-size: 1.5em;}
    85 .shopp.tagcloud li.level-3 {font-size: 1.25em;}
    86 .shopp.tagcloud li.level-4 {font-size: 1em;}
    87 .shopp.tagcloud li.level-5 {font-size: 0.875em;}
    88 .shopp.tagcloud li.level-6 {font-size: 0.75em;}
    89 .shopp.tagcloud li.level-7 {font-size: 0.688em;}
     87.shopp.tagcloud .level-1 {font-size: 2em;}
     88.shopp.tagcloud .level-2 {font-size: 1.5em;}
     89.shopp.tagcloud .level-3 {font-size: 1.25em;}
     90.shopp.tagcloud .level-4 {font-size: 1em;}
     91.shopp.tagcloud .level-5 {font-size: 0.875em;}
     92.shopp.tagcloud .level-6 {font-size: 0.75em;}
     93.shopp.tagcloud .level-7 {font-size: 0.688em;}
    9094
    9195
  • shopp/trunk/gateways/2Checkout/2Checkout.php

    r821385 r930519  
    44 *
    55 * @author Jonathan Davis
    6  * @copyright Ingenesis Limited, 27 May, 2009
     6 * @copyright Ingenesis Limited, May 2009-2014
    77 * @package shopp
    8  * @version 1.3
     8 * @version 1.3.4
    99 * @since 1.1
    1010 **/
     
    1717    public $secure = false;
    1818    public $saleonly = true;
    19     public $precision = 2;
    20     public $decimals = '.';
    21     public $thousands = '';
    2219
    2320    // URLs
    24     public $url = 'https://www.2checkout.com/checkout/purchase';    // Multi-page checkout
    25     public $surl = 'https://www.2checkout.com/checkout/spurchase'; // Single-page, CC-only checkout
     21    const LIVEURL = 'https://www.2checkout.com/checkout/purchase';
     22    const SANDBOX = 'https://sandbox.2checkout.com/checkout/purchase';
    2623
    2724    public function __construct () {
    2825        parent::__construct();
    2926
    30         $this->setup('sid','verify','secret','returnurl','testmode','singlepage');
    31 
    32         $this->settings['returnurl'] = add_query_arg('rmtpay','process',Shopp::url(false,'thanks',false));
    33 
    34         // add_action('shopp_txn_update',array(&$this,'notifications'));
    35         add_action('shopp__2checkout_sale', array($this,'sale'));
    36 
    37     }
    38 
    39     public function actions () {
    40         add_action('shopp_process_checkout', array(&$this,'checkout'),9);
    41         add_action('shopp_init_checkout',array(&$this,'init'));
    42 
    43         add_action('shopp_init_confirmation',array(&$this,'confirmation'));
    44         add_action('shopp_remote_payment',array(&$this,'returned'));
    45     }
    46 
    47     public function confirmation () {
    48         add_filter('shopp_confirm_url',array(&$this,'url'));
    49         add_filter('shopp_confirm_form',array(&$this,'form'));
    50     }
    51 
    52     public function checkout () {
    53         $this->Order->confirm = true;
    54     }
    55 
    56     public function url ($url) {
    57         if ($this->settings['singlepage'] == "on") return $this->surl;
    58         return $this->url;
    59     }
    60 
    61     public function form ($form) {
     27        $this->setup('sid', 'verify', 'secret', 'testmode');
     28
     29        add_filter('shopp_purchase_order_2checkout_processing', array($this, 'processing'));
     30        add_action('shopp_remote_payment', array($this, 'returned'));
     31
     32    }
     33
     34    public function actions () { /* Not implemented */ }
     35
     36    public function processing () {
     37        return array($this, 'submit');
     38    }
     39
     40    public function form ( ShoppPurchase $Purchase ) {
    6241
    6342        $purchasetable = ShoppDatabaseObject::tablename(ShoppPurchase::$table);
    64         $next = sDB::query("SELECT IF ((MAX(id)) > 0,(MAX(id)+1),1) AS id FROM $purchasetable LIMIT 1");
    6543
    6644        $Order = $this->Order;
     
    6846        $Billing = $Order->Billing;
    6947        $Shipping = $Order->Shipping;
    70         $Order->_2COcart_order_id = date('mdy').'-'.date('His').'-'.$next->id;
    7148
    7249        // Build the transaction
     
    7451
    7552        // Required
    76         $_['sid']               = $this->settings['sid'];
    77         $_['total']             = $this->amount('total');
    78         $_['cart_order_id']     = $Order->_2COcart_order_id;
    79         $_['vendor_order_id']   = $this->session;
    80         $_['id_type']           = 1;
     53        $_['sid']               = $this->settings['sid'];
     54        $_['mode']              = '2CO';
     55        $_['total']             = $this->amount('total');
     56        $_['merchant_order_id'] = $Purchase->id;
     57        $_['id_type']           = 1;
    8158
    8259        // Extras
    83         if ($this->settings['testmode'] == "on")
    84             $_['demo']          = "Y";
    85 
    86         $_['fixed']             = "Y";
    87         $_['skip_landing']      = "1";
    88 
    89         $_['x_Receipt_Link_URL'] = $this->settings['returnurl'];
     60        if ( Shopp::str_true($this->settings['testmode']) )
     61            $_['demo']          = "Y";
     62
     63        $_['fixed']             = "Y";
     64        $_['skip_landing']      = "1";
     65        $_['currency_code']     = $this->currency();
     66
     67        $_['x_receipt_link_url'] = $this->settings['returnurl'];
    9068
    9169        // Line Items
    92         foreach($this->Order->Cart->contents as $i => $Item) {
    93             $id = $i+1;
    94             $_['c_prod_'.$id]           = 'shopp_pid-'.$Item->product.','.$Item->quantity;
    95             $_['c_name_'.$id]           = $Item->name;
    96             $_['c_description_'.$id]    = !empty($Item->option->label)?$Item->option->label:'';
    97             $_['c_price_'.$id]          = $this->amount($Item->unitprice);
    98 
    99         }
     70        $i = 0;
     71        foreach ( $Order->Cart as $id => $Item ) {
     72            $_['li_' . $i . '_product_id'] = 'shopp_pid-'.$Item->product.','.$Item->quantity;
     73            $_['li_' . $i . '_type']       = 'product';
     74            $_['li_' . $i . '_name']       = $this->itemname($Item);
     75            $_['li_' . $i . '_quantity']   = $Item->quantity;
     76            $_['li_' . $i . '_price']      = $this->amount($Item->unitprice);
     77            $_['li_' . $i . '_tangible']   = $Item->shipped ? 'Y' : 'N';
     78            $i++;
     79        }
     80
     81        // Shipping
     82        $_['li_' . $i . '_type']     = 'shipping';
     83        $_['li_' . $i . '_name']     = Shopp::__('Shipping');
     84        $_['li_' . $i . '_quantity'] = 1;
     85        $_['li_' . $i . '_price']    = $this->amount('shipping');
     86        $_['li_' . $i . '_tangible'] = 'N';
     87
     88        $i++;
     89
     90        // Taxes
     91        $_['li_' . $i . '_type']     = 'tax';
     92        $_['li_' . $i . '_name']     = Shopp::__('Taxes');
     93        $_['li_' . $i . '_quantity'] = 1;
     94        $_['li_' . $i . '_price']    = $this->amount('tax');
     95        $_['li_' . $i . '_tangible'] = 'N';
     96
    10097
    10198        $_['card_holder_name']      = $Billing->name;
     
    117114        $_['ship_country']          = $Shipping->country;
    118115
    119         return $form.$this->format($_);
    120     }
     116        return $this->format($_);
     117    }
     118
     119    /**
     120     * Builds a form to send the order to PayPal for processing
     121     *
     122     * @author Jonathan Davis
     123     * @since 1.3
     124     *
     125     * @return string PayPal cart form
     126     **/
     127    public function submit ( ShoppPurchase $Purchase ) {
     128        $id = sanitize_key( $this->module );
     129        $title = Shopp::__( 'Sending order to 2Checkout&hellip;' );
     130        $message = '<form id="' . $id . '" action="' . self::LIVEURL . '" method="POST">' .
     131                    $this->form( $Purchase ) .
     132                    '<h1>' . $title . '</h1>' .
     133                    '<noscript>' .
     134                    '<p>' . Shopp::__( 'Click the &quot;Submit Order to 2Checkout&quot; button below to submit your order to 2Checkout for payment processing:' ) . '</p>' .
     135                    '<p><input type="submit" name="submit" value="' . Shopp::__('Submit Order to 2Checkout'). '" id="' . $id . '" /></p>' .
     136                    '</noscript>' .
     137                    '</form>' .
     138                    '<script type="text/javascript">document.getElementById("' . $id . '").submit();</script></body></html>';
     139
     140        wp_die( $message, $title, array( 'response' => 200 ) );
     141    }
     142
    121143
    122144    public function returned () {
    123145
    124         if (Shopp::str_true($this->settings['verify']) && !$this->verify($_POST['key'])) {
    125             new ShoppError(__('The order submitted to 2Checkout could not be verified.','Shopp'),'2co_validation_error',SHOPP_TRXN_ERR);
    126             Shopp::redirect( Shopp::url( false, 'checkout' ) );
    127 
    128         }
    129 
    130         if (empty($_POST['order_number'])) {
    131             new ShoppError(__('The order submitted by 2Checkout did not specify a transaction ID.','Shopp'),'2co_validation_error',SHOPP_TRXN_ERR);
    132             Shopp::redirect( Shopp::url( false, 'checkout' ) );
    133         }
    134 
    135         // Create the order and begin processing it
    136         shopp_add_order_event(false, 'purchase', array(
    137             'gateway' => $this->module,
    138             'txnid' => $_POST['order_number']
     146        if ( $this->id() != $_GET['rmtpay'] ) return; // Not our offsite payment
     147
     148        $request = array_merge(array(
     149            'merchant_order_id' => false,
     150            'key' => false,
     151            'order_number' => false,
     152            'total' => false,
     153            'credit_card_processed' => false,
     154            'invoice_id' => false,
     155            'pay_method' => false
     156        ), $_GET);
     157        extract($request, EXTR_SKIP);
     158
     159        if ( Shopp::str_true($this->settings['verify']) && ! $this->verify($key) ) {
     160            shopp_add_error(Shopp::__('The order submitted to 2Checkout could not be verified.'), SHOPP_TRXN_ERR);
     161            Shopp::redirect(Shopp::url(false, 'checkout'));
     162        }
     163
     164        if ( empty($merchant_order_id) ) {
     165            shopp_add_error(Shopp::__('The order submitted by 2Checkout did not specify a transaction ID.'), SHOPP_TRXN_ERR);
     166            Shopp::redirect(Shopp::url(false, 'checkout'));
     167        }
     168
     169        $Purchase = ShoppPurchase(new ShoppPurchase((int)$merchant_order_id));
     170        if ( ! $Purchase->exists() ) {
     171            shopp_add_error(Shopp::__('The order submitted by 2Checkout did not match any submitted orders.'), SHOPP_TRXN_ERR);
     172            Shopp::redirect(Shopp::url(false, 'checkout'));
     173        }
     174
     175        if ( 'Y' != $credit_card_processed ) {
     176            shopp_add_order_event($Purchase->id, 'auth-fail', array(
     177                'amount' => $total, // Amount to be authorized
     178                'error' => 'Declined', // Error code (if provided)
     179                'message' => Shopp::__('The payment was not completed succesfully'), // Error message reported by the gateway
     180                'gateway' => $this->module, // The gateway module name
     181            ));
     182            shopp_add_error(Shopp::__('The order submitted by 2Checkout did not match any submitted orders.'), SHOPP_TRXN_ERR);
     183            Shopp::redirect(Shopp::url(false, 'checkout'));
     184        }
     185
     186        add_action( 'shopp_authed_order_event', array( ShoppOrder(), 'notify' ) );
     187        add_action( 'shopp_authed_order_event', array( ShoppOrder(), 'accounts' ) );
     188        add_action( 'shopp_authed_order_event', array( ShoppOrder(), 'success' ) );
     189
     190        shopp_add_order_event($Purchase->id, 'authed', array(
     191            'txnid' => $order_number,   // Transaction ID
     192            'amount' => (float)$total,  // Gross amount authorized
     193            'fees' => false,            // Fees associated with transaction
     194            'gateway' => $this->module, // The gateway module name
     195            'paymethod' => '2Checkout', // Payment method (payment method label from payment settings)
     196            'paytype' => $pay_method,   // Type of payment (check, MasterCard, etc)
     197            'payid' => $invoice_id,     // Payment ID (last 4 of card or check number or other payment id)
     198            'capture' => true           // Capture flag
    139199        ));
    140200
     
    144204    }
    145205
    146     public function sale ($Event) {
     206    public function authed ( ShoppPurchase $Order ) {
    147207
    148208        $Paymethod = $this->Order->paymethod();
    149209        $Billing = $this->Order->Billing;
    150210
    151         shopp_add_order_event($Event->order, 'authed', array(
     211        shopp_add_order_event($Order->id, 'authed', array(
    152212            'txnid' => $_POST['order_number'],                      // Transaction ID
    153213            'amount' => $_POST['total'],                            // Gross amount authorized
     
    161221    }
    162222
    163     public function notification () {
    164         // INS updates not implemented
    165     }
    166 
    167     public function verify ($key) {
     223    protected function verify ( $key ) {
    168224        if ( Shopp::str_true($this->settings['testmode']) ) return true;
    169         $order = $_POST['order_number'];
     225        $order = $_GET['order_number'];
     226        $total = $_GET['total'];
    170227
    171228        $verification = strtoupper(md5($this->settings['secret'] .
    172229                            $this->settings['sid'] .
    173230                            $order .
    174                             $this->amount('total')
     231                            $total
    175232                        ));
    176233
    177234        return ( $verification == $key );
     235    }
     236
     237    protected function returnurl () {
     238        return add_query_arg('rmtpay', $this->id(), Shopp::url(false, 'thanks'));
     239    }
     240
     241    protected function itemname ( $Item ) {
     242        $name = $Item->name . ( empty($Item->option->label) ? '' : ' ' . $Item->option->label );
     243        $name = str_replace(array('<', '>'), '', $name);
     244        return substr($name, 0, 128);
    178245    }
    179246
     
    187254        ));
    188255
    189         $this->ui->text(0,array(
    190             'name' => 'returnurl',
    191             'size' => 40,
    192             'value' => $this->settings['returnurl'],
    193             'readonly' => 'readonly',
    194             'classes' => 'selectall',
    195             'label' => __('Copy as the <strong>Approved URL</strong> & <strong>Pending URL</strong> in your 2Checkout Vendor Area under the <strong>Account &rarr; Site Management</strong> settings page.','Shopp')
    196         ));
    197 
    198         $this->ui->checkbox(1,array(
    199             'name' => 'testmode',
    200             'checked' => $this->settings['testmode'],
    201             'label' => __('Enable test mode','Shopp')
    202         ));
    203 
    204         $this->ui->checkbox(1,array(
    205             'name' => 'singlepage',
    206             'checked' => $this->settings['singlepage'],
    207             'label' => __('Single-page, credit card only checkout','Shopp')
    208         ));
    209 
    210         $this->ui->checkbox(1,array(
     256
     257        $this->ui->checkbox(0,array(
    211258            'name' => 'verify',
    212259            'checked' => $this->settings['verify'],
     
    214261        ));
    215262
    216         $this->ui->text(1,array(
     263        $this->ui->text(0,array(
    217264            'name' => 'secret',
    218265            'size' => 10,
     
    221268        ));
    222269
    223         $this->ui->p(1,array(
     270        $this->ui->checkbox(0,array(
     271            'name' => 'testmode',
     272            'checked' => $this->settings['testmode'],
     273            'label' => __('Enable test mode','Shopp')
     274        ));
     275
     276        $this->ui->text(1, array(
    224277            'name' => 'returnurl',
    225             'size' => 40,
    226             'value' => $this->settings['returnurl'],
     278            'size' => 64,
     279            'value' => $this->returnurl(),
    227280            'readonly' => 'readonly',
    228             'classes' => 'selectall',
    229             'content' => '<span style="width: 300px;">&nbsp;</span>'
    230         ));
    231 
    232         $this->ui->behaviors( $this->secretjs() );
    233     }
    234 
    235     public function secretjs () {
    236         ob_start(); ?>
    237 jQuery(document).bind('_2checkoutSettings',function () {
    238     var $=jqnc(),p='#_2checkout-',v=$(p+'verify'),s=$(p+'secret');
    239     v.change(function () { v.attr('checked') ? s.parent().fadeIn('fast') : s.parent().hide(); }).change();
    240 });
    241 <?php
    242         $script = ob_get_contents(); ob_end_clean();
    243         return $script;
     281            'class' => 'selectall',
     282            'label' => __('Copy as the <strong>Approved URL</strong> & <strong>Pending URL</strong> in your 2Checkout Vendor Area under the <strong>Account &rarr; Site Management</strong> settings page.','Shopp')
     283        ));
     284
     285        $script = "var tc ='shopp2checkout';jQuery(document).bind(tc+'Settings',function(){var $=jqnc(),p='#'+tc+'-',v=$(p+'verify'),t=$(p+'secret');v.change(function(){v.prop('checked')?t.parent().fadeIn('fast'):t.parent().hide();}).change();});";
     286        $this->ui->behaviors( $script );
    244287    }
    245288
  • shopp/trunk/gateways/PayPal/PayPalStandard.php

    r905841 r930519  
    464464            $_['item_name'] = $Subscription->name . ( ( ! empty( $Subscription->option->label ) ) ? ' (' . $Subscription->option->label . ')' : '' );
    465465
     466            $trial_discounts = apply_filters('shopp_paypalstandard_discount_trials', false);
     467
    466468            // Trial pricing
    467469            if ( $Subscription->has_trial() ) {
    468470                $trial = $Subscription->trial();
    469471                $trial['period'] = strtoupper($trial['period']);
     472                $trialprice = $this->amount( $trial['price'] );
     473
     474                if ( $this->amount('discount') > 0 && $trial_discounts )
     475                    $trialprice -= $this->amount('discount');
    470476
    471477                // normalize trial interval
     
    475481                $_['p1']    = $trial['interval'];
    476482                $_['t1']    = $trial['period'];
     483            } elseif ( $this->amount('discount') > 0 && $trial_discounts ) {
     484                // When no trial discounts are created, add a discount to a trial offer using
     485                // the interval and period of the normal subscription, but at a discounted price
     486                $_['a1']    = $this->amount( $Subscription->subprice ) - $this->amount('discount');
     487                $_['p1']    = $recurring['interval'];
     488                $_['t1']    = $recurring['period'];
    477489            }
    478             $_['a3']    = $this->amount( $Subscription->subprice );
     490
     491            $subprice = $this->amount( $Subscription->subprice );
     492
     493            if ( $this->amount('discount') > 0 && ! $trial_discounts )
     494                $subprice -= $this->amount('discount');
     495            $_['a3']    = $subprice;
    479496            $_['p3']    = $recurring['interval'];
    480497            $_['t3']    = $recurring['period'];
     
    852869    }
    853870
    854     public static function currencies ( string $currency ) {
     871    public static function currencies ( $currency ) {
    855872
    856873        if ( in_array($currency, self::$currencies) )
  • shopp/trunk/readme.md

    r821385 r930519  
    1616- [Knowledge Base](https://shopplugin.com/kb/) - Troubleshooting articles for the most common problems and error messages
    1717- [Support Help Desk](https://shopplugin.com/support/forum/help-desk) - Open a ticket with the Shopp support team
    18 - [WorkShopp](http:///workshopp.com/) - Tutorials and screencasts for Shopp
     18- [WorkShopp](http://workshopp.com/) - Tutorials and screencasts for Shopp
    1919- [API Reference](https://shopplugin.com/api/) - Online developer's reference guide
    2020- [Professionals](https://shopplugin.com/professionals/) - Shopp developers available for consulting work
  • shopp/trunk/services/image.php

    r865739 r930519  
    197197        // Post sharpen
    198198        if ( ! $alpha && $this->sharpen > 0 )
    199             $Resized->UnsharpMask($this->sharpen);
     199            $Resized->sharpen($this->sharpen);
    200200
    201201        $ResizedImage = new ImageAsset();
  • shopp/trunk/shipping/core/ItemQuantity.php

    r821385 r930519  
    3939
    4040            $amount = 0;
     41            $matched = false;
    4142            $tiers = array_reverse($tiers);
     43           
    4244            foreach ( $tiers as $tier ) {
    4345                extract($tier);
    4446                $amount = Shopp::floatval($rate);           // Capture the rate amount
    45                 if ( (int)$this->items >= (int)$threshold ) break;
     47               
     48                if ( (int)$this->items >= (int)$threshold ) {
     49                    $matched = true;
     50                    break; 
     51                }
    4652            }
     53           
     54            if ( ! $matched ) return $options;
    4755
    4856            $rate = array(
  • shopp/trunk/shipping/core/OrderAmount.php

    r831831 r930519  
    3636
    3737            $amount = 0;
     38            $matched = false;
    3839            $tiers = array_reverse($tiers);
     40           
    3941            foreach ( $tiers as $tier ) {
    4042                extract($tier);
    4143                $amount = Shopp::floatval($rate);           // Capture the rate amount
    42                 if ( $Order->Cart->total('order') >= Shopp::floatval($threshold) ) break;
     44               
     45                if ( $Order->Cart->total('order') >= Shopp::floatval($threshold) ) {
     46                    $matched = true;
     47                    break;
     48                }
    4349            }
     50           
     51            if ( ! $matched ) return $options;
    4452
    4553            $rate = array(
  • shopp/trunk/shipping/core/OrderWeight.php

    r821385 r930519  
    3939
    4040            $amount = 0;
     41            $matched = false;
    4142            $tiers = array_reverse($tiers);
     43           
    4244            foreach ( $tiers as $tier ) {
    4345                extract($tier);
    4446                $amount = Shopp::floatval($rate);           // Capture the rate amount
    45                 if ( $this->weight >= $threshold ) break;
     47               
     48                if ( $this->weight >= $threshold ) {
     49                    $matched = true;
     50                    break; 
     51                }
    4652            }
     53           
     54            if ( ! $matched ) return $options;
    4755
    4856            $rate = array(
  • shopp/trunk/shipping/core/PercentageAmount.php

    r821385 r930519  
    3232
    3333            $amount = 0;
     34            $matched = false;
    3435            $tiers = array_reverse($tiers);
     36           
    3537            foreach ( $tiers as $tier ) {
    3638                extract($tier);
    3739                $amount = (Shopp::floatval($rate) / 100) * $Order->Cart->total('order');
    38                 if ( $Order->Cart->total('order') >= Shopp::floatval($threshold) ) break;
     40               
     41                if ( $Order->Cart->total('order') >= Shopp::floatval($threshold) ) {
     42                    $matched = true;
     43                    break;
     44                }
    3945            }
     46           
     47            if ( ! $matched ) return $options;
    4048
    4149            $rate = array(
Note: See TracChangeset for help on using the changeset viewer.