/** * Initializes the Shopp runtime environment * * @author Jonathan Davis * @since 1.0 * * @return void **/ public function init() { $this->Collections = array(); $this->Locale = new ShoppBaseLocale(); $this->Order = new ShoppOrder(); $this->Gateways = new GatewayModules(); $this->Shipping = new ShippingModules(); $this->Storage = new StorageEngines(); $this->APIs = new ShoppAPIModules(); // Start the shopping session $this->Shopping = ShoppShopping(); new ShoppLogin(); do_action('shopp_init'); }
/** * Handles shopping cart requests * * @author Jonathan Davis * @since 1.1 * * @return void **/ public function cart() { if (isset($_REQUEST['shopping']) && 'reset' == strtolower($_REQUEST['shopping'])) { ShoppShopping()->reset(); Shopp::redirect(Shopp::url()); } if (empty($_REQUEST['cart'])) { return true; } do_action('shopp_cart_request'); if (isset($_REQUEST['checkout'])) { Shopp::redirect(Shopp::url(false, 'checkout', $this->security())); } if (isset($_REQUEST['ajax'])) { $Cart = ShoppOrder()->Cart; $Cart->totals(); $Cart->ajax(); } $redirect = false; if (isset($_REQUEST['redirect'])) { $redirect = $_REQUEST['redirect']; } switch ($redirect) { case 'checkout': Shopp::redirect(Shopp::url(false, $redirect, ShoppOrder()->security())); break; default: if (!empty($_REQUEST['redirect'])) { Shopp::safe_redirect($_REQUEST['redirect']); } else { Shopp::redirect(Shopp::url(false, 'cart')); } } exit; }
/** * Setup the module for runtime * * Auto-loads settings for the module and setups defaults * * @author Jonathan Davis * @since 1.1 * * @return void **/ public function __construct() { $this->module = get_class($this); $this->session = ShoppShopping()->session; $this->Order = ShoppOrder(); if ('ShoppFreeOrder' != $this->module) { // There are no settings for ShoppFreeOrder $this->settings = shopp_setting($this->module); // @todo Remove legacy gateway settings migrations // Attempt to copy old settings if this is a new prefixed gateway class if (empty($this->settings) && false !== strpos($this->module, 'Shopp')) { $legacy = substr($this->module, 5); $this->settings = shopp_setting($legacy); if (!empty($this->settings)) { shopp_set_setting($this->module, $this->settings); } } } if (!isset($this->settings['label']) && $this->cards) { $this->settings['label'] = __('Credit Card', 'Shopp'); } $this->baseop = ShoppBaseLocale()->settings(); $this->currency = ShoppBaseCurrency()->code(); $this->precision = ShoppBaseCurrency()->precision(); $this->_loadcards(); $gateway = GatewayModules::hookname($this->module); add_action('shopp_init', array($this, 'myactions'), 30); add_action('shopp_' . $gateway . '_refunded', array($this, 'cancelorder')); if ($this->authonly) { add_filter('shopp_purchase_order_' . $gateway . '_processing', create_function('', 'return "auth";')); } elseif ($this->saleonly) { add_filter('shopp_purchase_order_' . $gateway . '_processing', create_function('', 'return "sale";')); } }
/** * Provides the URL for the referring page * * The referrer is the page the shopper was visiting before being * sent to the cart page. If no referring page is available, the * catalog page URL is given instead. * * @api `shopp('cart.referrer')` * @since 1.1 * * @param string $result The output * @param array $options The options * @param ShoppCart $O The working object * @return string The referring page's URL **/ public static function referrer($result, $options, $O) { $Shopping = ShoppShopping(); $referrer = $Shopping->data->referrer; if (!$referrer) { $referrer = shopp('catalog', 'url', 'return=1'); } return $referrer; }
/** * Handles product file download requests * * @author Jonathan Davis * @since 1.1 * * @return void **/ public function download() { $Shopp = Shopp::object(); $download = $this->request['shopp_download']; $Purchase = false; $Purchased = false; if (defined('WP_ADMIN')) { $forbidden = false; $Download = new ProductDownload($download); } else { $Order = ShoppOrder(); $accounts = 'none' != shopp_setting('account_system'); $Download = new ProductDownload(); $Download->loadby_dkey($download); $Purchased = $Download->purchased(); $Purchase = new ShoppPurchase($Purchased->purchase); $Purchase->load_events(); $name = $Purchased->name . (!empty($Purchased->optionlabel) ? ' (' . $Purchased->optionlabel . ')' : ''); $forbidden = false; // Voided orders if ($Purchase->isvoid()) { shopp_add_error(Shopp::__('"%s" cannot be downloaded because the order has been cancelled.', $name)); $forbidden = true; } // Purchase Completion check if (!$Purchase->ispaid() && !SHOPP_PREPAYMENT_DOWNLOADS) { shopp_add_error(Shopp::__('"%s" cannot be downloaded because payment has not been received yet.', $name)); $forbidden = true; } // If accounts are used and this is not a guest account if ($accounts && Shopp::__('Guest') != ShoppCustomer()->type) { // User must be logged in when accounts are being used if (!ShoppCustomer()->loggedin()) { shopp_add_error(Shopp::__('You must login to download purchases.')); $forbidden = true; } // Logged in account must be the owner of the purchase if (ShoppCustomer()->id != $Purchase->customer) { shopp_add_error(Shopp::__('You are not authorized to download the requested file.')); $forbidden = true; } } // Download limit checking if (shopp_setting('download_limit') && $Purchased->downloads + 1 > shopp_setting('download_limit')) { shopp_add_error(Shopp::__('"%s" is no longer available for download because the download limit has been reached.', $name)); $forbidden = true; } // Download expiration checking if (shopp_setting('download_timelimit') && $Purchased->created + shopp_setting('download_timelimit') < current_time('timestamp')) { shopp_add_error(Shopp::__('"%s" is no longer available for download because it has expired.', 'Shopp', $name)); $forbidden = true; } // IP restriction checks if ('ip' == shopp_setting('download_restriction') && !empty($Purchase->ip) && $Purchase->ip != $_SERVER['REMOTE_ADDR']) { shopp_add_error(Shopp::__('"%s" cannot be downloaded because your computer could not be verified as the system the file was purchased from.', $name)); $forbidden = true; } do_action_ref_array('shopp_download_request', array($Purchased)); } if (apply_filters('shopp_download_forbidden', $forbidden, $Purchased)) { Shopp::redirect(add_query_arg('downloads', '', Shopp::url(false, 'account')), true, 303); } // Send the download $download = $Download->download(); if (is_a($download, 'ShoppError')) { // If the result is an error redirect to the account downloads page Shopp::redirect(add_query_arg('downloads', '', Shopp::url(false, 'account')), true, 303); } else { do_action_ref_array('shopp_download_success', array($Purchased, $Purchase, $Download)); // @deprecated use shopp_download_order_event instead shopp_add_order_event($Purchase->id, 'download', array('purchased' => $Purchased->id, 'download' => $Download->id, 'ip' => ShoppShopping()->ip, 'customer' => ShoppCustomer()->id)); } exit; }
public function load(array $options = array()) { $thisclass = get_class($this); $slug = isset($this->slug) ? $this->slug : sanitize_key($thisclass); $Storefront = ShoppStorefront(); $Shopping = ShoppShopping(); $Processing = new ShoppProduct(); $summary_table = ShoppDatabaseObject::tablename(ProductSummary::$table); $defaults = array('columns' => false, 'useindex' => false, 'joins' => array(), 'where' => array(), 'groupby' => false, 'orderby' => false, 'having' => array(), 'limit' => false, 'order' => false, 'page' => false, 'paged' => false, 'nostock' => null, 'pagination' => true, 'published' => true, 'ids' => false, 'adjacent' => false, 'product' => false, 'load' => array('coverimages'), 'inventory' => false, 'taxquery' => false, 'debug' => false); $loading = array_merge($defaults, $options); $loading = apply_filters("shopp_collection_load_options", $loading); $loading = apply_filters("shopp_{$slug}_collection_load_options", $loading); extract($loading); // Setup pagination $this->paged = false; $this->pagination = false === $paged ? shopp_setting('catalog_pagination') : $paged; $page = false === $page ? get_query_var('paged') : $page; $this->page = (int) $page > 0 || preg_match('/(0\\-9|[A-Z])/', $page) ? $page : 1; // Hard product limit per category to keep resources "reasonable" $hardlimit = apply_filters('shopp_category_products_hardlimit', 1000); // Enforce the where parameter as an array if (!is_array($where)) { return shopp_debug('The "where" parameter for ' . __METHOD__ . ' must be formatted as an array.'); } // Inventory filtering if (shopp_setting_enabled('inventory') && (is_null($nostock) && !shopp_setting_enabled('outofstock_catalog') || !is_null($nostock) && !Shopp::str_true($nostock))) { $where[] = "( s.inventory='off' OR (s.inventory='on' AND s.stock > 0) )"; } if (Shopp::str_true($published)) { $where[] = "p.post_status='publish'"; } // Multiple taxonomy queries if (is_array($taxquery)) { $tqdefaults = array('relation' => 'AND', 'include_children' => true); $taxquery = array_merge($tqdefaults, $taxquery); $TQ = new WP_Tax_Query($taxquery); $sql = $TQ->get_sql($Processing->_table, 'ID'); unset($TQ); $joins['taxquery'] = self::taxquery($sql['join']); $where[] = self::taxquery($sql['where']); } // Sort Order if (!$orderby) { $titlesort = "p.post_title ASC"; $defaultsort = empty($order) ? $titlesort : $order; // Define filterable built-in sort methods (you're welcome) $sortmethods = apply_filters('shopp_collection_sort_methods', array('bestselling' => "s.sold DESC,{$titlesort}", 'highprice' => "maxprice DESC,{$titlesort}", 'lowprice' => "minprice ASC,{$titlesort}", 'newest' => "p.post_date DESC,{$titlesort}", 'oldest' => "p.post_date ASC,{$titlesort}", 'random' => "RAND(" . crc32($Shopping->session) . ")", 'chaos' => "RAND(" . time() . ")", 'reverse' => "p.post_title DESC", 'title' => $titlesort, 'custom' => is_subclass_of($this, 'ProductTaxonomy') ? "tr.term_order ASC,{$titlesort}" : $defaultsort, 'recommended' => is_subclass_of($this, 'ProductTaxonomy') ? "tr.term_order ASC,{$titlesort}" : $defaultsort, 'default' => $defaultsort)); // Handle valid user browsing sort change requests if (isset($_REQUEST['sort']) && !empty($_REQUEST['sort']) && array_key_exists(strtolower($_REQUEST['sort']), $sortmethods)) { $Storefront->browsing['sortorder'] = strtolower($_REQUEST['sort']); } // Collect sort setting sources (Shopp admin setting, User browsing setting, programmer specified setting) $sortsettings = array(shopp_setting('default_product_order'), isset($Storefront->browsing['sortorder']) ? $Storefront->browsing['sortorder'] : false, !empty($order) ? $order : false); // Go through setting sources to determine most applicable setting $sorting = 'title'; foreach ($sortsettings as $setting) { if (!empty($setting) && isset($sortmethods[strtolower($setting)])) { $sorting = strtolower($setting); } } $orderby = $sortmethods[$sorting]; } if (empty($orderby)) { $orderby = 'p.post_title ASC'; } // Pagination if (empty($limit)) { if ($this->pagination > 0 && is_numeric($this->page) && Shopp::str_true($pagination)) { if (!$this->pagination || $this->pagination < 0) { $this->pagination = $hardlimit; } $start = $this->pagination * ($this->page - 1); $limit = "{$start},{$this->pagination}"; } else { $limit = $hardlimit; } $limited = false; // Flag that the result set does not have forced limits } else { $limited = true; } // The result set has forced limits // Core query components // Load core product data and product summary columns $cols = array('p.ID', 'p.post_title', 'p.post_name', 'p.post_excerpt', 'p.post_status', 'p.post_date', 'p.post_modified', 's.modified AS summed', 's.sold', 's.grossed', 's.maxprice', 's.minprice', 's.ranges', 's.taxed', 's.stock', 's.lowstock', 's.inventory', 's.featured', 's.variants', 's.addons', 's.sale'); if ($ids) { $cols = array('p.ID'); } $columns = "SQL_CALC_FOUND_ROWS " . join(',', $cols) . ($columns !== false ? ',' . $columns : ''); $table = "{$Processing->_table} AS p"; $where[] = "p.post_type='" . ShoppProduct::posttype() . "'"; $joins[$summary_table] = "LEFT OUTER JOIN {$summary_table} AS s ON s.product=p.ID"; $options = compact('columns', 'useindex', 'table', 'joins', 'where', 'groupby', 'having', 'limit', 'orderby'); // Alphabetic pagination if ('alpha' === $pagination || preg_match('/(0\\-9|[A-Z])/', $page)) { // Setup Roman alphabet navigation $alphanav = array_merge(array('0-9'), range('A', 'Z')); $this->alpha = array_combine($alphanav, array_fill(0, count($alphanav), 0)); // Setup alphabetized index query $a = $options; $a['columns'] = "count(DISTINCT p.ID) AS total,IF(LEFT(p.post_title,1) REGEXP '[0-9]',LEFT(p.post_title,1),LEFT(SOUNDEX(p.post_title),1)) AS letter"; $a['groupby'] = "letter"; $alphaquery = sDB::select($a); $cachehash = 'collection_alphanav_' . md5($alphaquery); $cached = Shopp::cache_get($cachehash, 'shopp_collection_alphanav'); if ($cached) { // Load from object cache, if available $this->alpha = $cached; $cached = false; } else { // Run query and cache results $expire = apply_filters('shopp_collection_cache_expire', 43200); $alpha = sDB::query($alphaquery, 'array', array($this, 'alphatable')); Shopp::cache_set($cachehash, $alpha, 'shopp_collection_alphanav', $expire); } $this->paged = true; if ($this->page == 1) { $this->page = '0-9'; } $alphafilter = $this->page == "0-9" ? "(LEFT(p.post_title,1) REGEXP '[0-9]') = 1" : "IF(LEFT(p.post_title,1) REGEXP '[0-9]',LEFT(p.post_title,1),LEFT(SOUNDEX(p.post_title),1))='{$this->page}'"; $options['where'][] = $alphafilter; } $query = sDB::select(apply_filters('shopp_collection_query', $options)); if ($debug) { echo $query . BR . BR; } // Load from cached results if available, or run the query and cache the results $cachehash = 'collection_' . md5($query); $cached = Shopp::cache_get($cachehash, 'shopp_collection'); if ($cached) { $this->products = $cached->products; $this->total = $cached->total; } else { $expire = apply_filters('shopp_collection_cache_expire', 43200); $cache = new stdClass(); if ($ids) { $cache->products = $this->products = sDB::query($query, 'array', 'col', 'ID'); } else { $cache->products = $this->products = sDB::query($query, 'array', array($Processing, 'loader')); } $cache->total = $this->total = sDB::found(); // If running a limited set, the reported total found should not exceed the limit (but can because of SQL_CALC_FOUND_ROWS) // Don't use the limit if it is offset if ($limited && false === strpos($limit, ',')) { $cache->total = $this->total = min($limit, $this->total); } Shopp::cache_set($cachehash, $cache, 'shopp_collection', $expire); } if (false === $this->products) { $this->products = array(); } if ($ids) { return $this->size() > 0; } // Finish up pagination construction if ($this->pagination > 0 && $this->total > $this->pagination) { $this->pages = ceil($this->total / $this->pagination); if ($this->pages > 1) { $this->paged = true; } } // Load all requested product meta from other data sources $Processing->load_data($load, $this->products); // If products are missing summary data, resum them if (isset($Processing->resum) && !empty($Processing->resum)) { $Processing->load_data(array('prices'), $Processing->resum); } unset($Processing); // Free memory $this->loaded = true; return $this->size() > 0; }
/** * Secures the payment card by truncating it to the last four digits * * @author Jonathan Davis * @since 1.2 * * @return void **/ public function securecard() { $this->Billing->card = ''; // Card data is gone, switch the cart to normal mode ShoppShopping()->secured(false); }
/** * Builds a hidden form to submit the order to PayPal * * @author Jonathan Davis * @since 1.0 * * @param ShoppPurchase $Purchase The order to submit to PayPal * @return string PayPal order form contents **/ public function form(ShoppPurchase $Purchase) { $Shopping = ShoppShopping(); $Order = ShoppOrder(); $Cart = $Order->Cart; $Customer = $Order->Customer; $_ = array(); $_['cmd'] = '_cart'; $_['upload'] = 1; $_['business'] = $this->settings['account']; $_['invoice'] = $Purchase->id; $_['custom'] = $Shopping->session; // Options if (Shopp::str_true($this->settings['pdtverify'])) { $_['return'] = apply_filters('shopp_paypalstandard_returnurl', Shopp::url(array('rmtpay' => $this->id(), 'utm_nooverride' => '1'), 'checkout', false)); } else { $_['return'] = Shopp::url(false, 'thanks'); } $_['cancel_return'] = Shopp::url(false, 'cart'); $_['notify_url'] = $this->ipnurl(); $_['rm'] = 1; // Return with no transaction data // Pre-populate PayPal Checkout $_['lc'] = $this->baseop['country']; $_['charset'] = 'utf-8'; $_['bn'] = 'shopplugin.net[WPS]'; $_['first_name'] = $Customer->firstname; $_['last_name'] = $Customer->lastname; $AddressType = 'Shipping'; // Disable shipping fields if no shipped items in cart if (empty($Order->Cart->shipped)) { $AddressType = 'Billing'; $_['no_shipping'] = 1; } $Address = $Order->{$AddressType}; if (!empty($Order->Cart->shipped)) { $shipname = explode(' ', $Address->name); $_['first_name'] = array_shift($shipname); $_['last_name'] = join(' ', $shipname); } $_['address_override'] = 1; $_['address1'] = $Address->address; if (!empty($Address->xaddress)) { $_['address2'] = $Address->xaddress; } $_['city'] = $Address->city; $_['state'] = $Address->state; $_['zip'] = $Address->postcode; $_['country'] = $Address->country; $_['email'] = $Customer->email; $phone = parse_phone($Order->Customer->phone); if (!empty($phone) && in_array($Order->Billing->country, array('US', 'CA'))) { $_['night_phone_a'] = $phone['area']; $_['night_phone_b'] = $phone['prefix']; $_['night_phone_c'] = $phone['exchange']; } else { $_['night_phone_b'] = $phone['raw']; } // Include page style option, if provided if (isset($_GET['pagestyle'])) { $_['pagestyle'] = $_GET['pagestyle']; } // Transaction $_['currency_code'] = $this->currency(); // Recurring Non-Free Item $Cart->recurring(); $Subscription = reset($Cart->recurring); if ($Cart->recurring() && $Subscription->unitprice > 0) { $tranges = array('D' => array('min' => 1, 'max' => 90), 'W' => array('min' => 1, 'max' => 52), 'M' => array('min' => 1, 'max' => 24), 'Y' => array('min' => 1, 'max' => 5)); $recurring = $Subscription->recurring(); $recurring['period'] = strtoupper($recurring['period']); //normalize recurring interval $recurring['interval'] = min(max($recurring['interval'], $tranges[$recurring['period']]['min']), $tranges[$recurring['period']]['max']); $_['cmd'] = '_xclick-subscriptions'; $_['rm'] = 2; // Return with transaction data $_['item_number'] = $Subscription->product; $_['item_name'] = $Subscription->name . (!empty($Subscription->option->label) ? ' (' . $Subscription->option->label . ')' : ''); $trial_discounts = apply_filters('shopp_paypalstandard_discount_trials', false); // Trial pricing if ($Subscription->has_trial()) { $trial = $Subscription->trial(); $trial['period'] = strtoupper($trial['period']); $trialprice = $this->amount($trial['price']); if ($this->amount('discount') > 0 && $trial_discounts) { $trialprice -= $this->amount('discount'); } // normalize trial interval $trial['interval'] = min(max($trial['interval'], $tranges[$trial['period']]['min']), $tranges[$trial['period']]['max']); $_['a1'] = $this->amount($trial['price']); $_['p1'] = $trial['interval']; $_['t1'] = $trial['period']; } elseif ($this->amount('discount') > 0 && $trial_discounts) { // When no trial discounts are created, add a discount to a trial offer using // the interval and period of the normal subscription, but at a discounted price $_['a1'] = $this->amount($Subscription->subprice) - $this->amount('discount'); $_['p1'] = $recurring['interval']; $_['t1'] = $recurring['period']; } $subprice = $this->amount($Subscription->subprice); if ($this->amount('discount') > 0 && !$trial_discounts) { $subprice -= $this->amount('discount'); } $_['a3'] = $subprice; $_['p3'] = $recurring['interval']; $_['t3'] = $recurring['period']; $_['src'] = 1; if ($recurring['cycles']) { $_['srt'] = (int) $recurring['cycles']; } } else { // Line Items $id = 0; foreach ($Order->Cart as $i => $Item) { $id++; $_['item_number_' . $id] = $id; $_['item_name_' . $id] = $Item->name . (!empty($Item->option->label) ? ' ' . $Item->option->label : ''); $_['amount_' . $id] = $this->amount($Item->unitprice); $_['quantity_' . $id] = $Item->quantity; // $_['weight_'.$id] = $Item->quantity; } // Workaround a PayPal limitation of not correctly handling no subtotals or // handling discounts in the amount of the item subtotals by adding the // shipping fee to the line items to get included in the subtotal. If no // shipping fee is available use 0.01 to satisfy minimum order amount requirements // Additionally, this condition should only be possible when using the shopp('cart','paypal') // Theme API tag which would circumvent normal checkout and use PayPal even for free orders if ((double) $this->amount('order') == 0 || (double) $this->amount('order') - (double) $this->amount('discount') == 0) { $id++; $_['item_number_' . $id] = $id; $_['item_name_' . $id] = apply_filters('paypal_freeorder_handling_label', __('Shipping & Handling', 'Shopp')); $_['amount_' . $id] = $this->amount(max((double) $this->amount('shipping'), 0.01)); $_['quantity_' . $id] = 1; } else { $_['handling_cart'] = $this->amount('shipping'); } $_['discount_amount_cart'] = $this->amount('discount'); $_['tax_cart'] = $this->amount('tax'); $_['amount'] = $this->amount('total'); } $_ = apply_filters('shopp_paypal_standard_form', $_); return $this->format($_); }
/** * Redirects the browser to a specified URL * * A wrapper for the wp_redirect function * * @author Jonathan Davis * @since 1.0 * * @param string $uri The URI to redirect to * @param boolean $exit (optional) Exit immediately after the redirect (defaults to true, set to false to override) * @return void **/ public static function redirect($uri, $exit = true, $status = 302) { shopp_debug("Redirecting to: {$uri}"); remove_action('shutdown', array(ShoppShopping(), 'save')); ShoppShopping()->save(); wp_redirect($uri, $status); if ($exit) { exit; } }
/** * Processes payment information changes. * * @since 1.3 * * @return void **/ public function payment() { if (!$this->paycard()) { return; } add_filter('shopp_validate_checkout', array('ShoppFormValidation', 'paycard')); $Billing = ShoppOrder()->Billing; $Payments = ShoppOrder()->Payments; $form = $this->form('billing'); // Change the default cardtype to the selected payment service option label $Billing->cardtype = empty($form['cardtype']) ? $Payments->selected()->label : $form['cardtype']; // If the card number is provided over a secure connection // Change the cart to operate in secure mode if (!empty($form['card']) && is_ssl()) { ShoppShopping()->secured(true); } // Sanitize the card number to ensure it only contains numbers if (strlen($PAN = self::digitsonly($form['card'])) > 4) { $Billing->card = $PAN; } if (!empty($form['cardexpires-mm']) && !empty($form['cardexpires-yy'])) { $exmm = self::digitsonly($form['cardexpires-mm']); $exyy = self::digitsonly($form['cardexpires-yy']); $Billing->cardexpires = mktime(0, 0, 0, $exmm, 1, $exyy + 2000); } else { $Billing->cardexpires = 0; } $Billing->cvv = self::digitsonly($form['cvv']); // Extra card security check fields if (!empty($form['xcsc'])) { $Billing->xcsc = array(); foreach ((array) $form['xcsc'] as $field => $value) { $Billing->Billing->xcsc[] = $field; // Add to the XCSC registry of fields $Billing->{$field} = $value; // Add the property } } }
/** * Clear the Customer-related session data * * @author Jonathan Davis * @since 1.0 * * @return void **/ public function logout() { $Shopp = Shopp::object(); $Order = ShoppOrder(); $Shopping = ShoppShopping(); $this->Customer->clear(); $this->Billing->clear(); $this->Shipping->clear(); $this->Shipping->locate(); do_action('shopp_logged_out', $this->Customer); }
public function upgrade_130() { global $wpdb; $db_version = ShoppSettings::dbversion(); if ($db_version < 1201) { // 1.3 schema changes $this->upschema(); // All existing sessions must be cleared and restarted, 1.3 & 1.3.6 sessions are not compatible with any prior version of Shopp ShoppShopping()->reset(); $sessions_table = ShoppDatabaseObject::tablename('shopping'); sDB::query("DELETE FROM {$sessions_table}"); // Remove all the temporary PHP native session data from the options table sDB::query("DELETE FROM from {$wpdb->options} WHERE option_name LIKE '__php_session_*'"); } if ($db_version < 1200) { $meta_table = ShoppDatabaseObject::tablename('meta'); sDB::query("UPDATE {$meta_table} SET value='on' WHERE name='theme_templates' AND (value != '' AND value != 'off')"); sDB::query("DELETE FROM {$meta_table} WHERE type='image' AND value LIKE '%O:10:\"ShoppError\"%'"); // clean up garbage from legacy bug sDB::query("DELETE FROM {$meta_table} WHERE CONCAT('', name *1) = name AND context = 'category' AND type = 'meta'"); // clean up bad category meta // Update purchase gateway values to match new prefixed class names $gateways = array('PayPalStandard' => 'ShoppPayPalStandard', '_2Checkout' => 'Shopp2Checkout', 'OfflinePayment' => 'ShoppOfflinePayment', 'TestMode' => 'ShoppTestMode', 'FreeOrder' => 'ShoppFreeOrder'); foreach ($gateways as $name => $classname) { sDB::query("UPDATE {$purchase_table} SET gateway='{$classname}' WHERE gateway='{$name}'"); } $activegateways = explode(',', shopp_setting('active_gateways')); foreach ($activegateways as &$setting) { if (false === strpos($setting, 'Shopp')) { $setting = str_replace(array_keys($gateways), $gateways, $setting); } } shopp_set_setting('active_gateways', join(',', $activegateways)); } if ($db_version < 1200 && shopp_setting_enabled('tax_inclusive')) { $price_table = ShoppDatabaseObject::tablename('price'); $taxrates = shopp_setting('taxrates'); $baseop = shopp_setting('base_operations'); $taxtaxes = array(); // Capture taxonomy condition tax rates $basetaxes = array(); // Capture base of operations rate(s) foreach ($taxrates as $rate) { if (!($baseop['country'] == $rate['country'] || ShoppTax::ALL == $rate['country'])) { continue; } if (!empty($rate['zone']) && $baseop['zone'] != $rate['zone']) { continue; } if (!empty($rate['rules']) && $rate['logic'] == 'any') { // Capture taxonomy conditional rates foreach ($rate['rules'] as $raterule) { if ('product-category' == $raterule['p']) { $taxname = ProductCategory::$taxon . '::' . $raterule['v']; } elseif ('product-tags' == $raterule['p']) { $taxname = ProductTag::$taxon . '::' . $raterule['v']; } $taxtaxes[$taxname] = Shopp::floatval($rate['rate']) / 100; } } else { $basetaxes[] = Shopp::floatval($rate['rate']) / 100; } } // Find products by in each taxonomy termno $done = array(); // Capture each set into the "done" list foreach ($taxtaxes as $taxterm => $taxrate) { list($taxonomy, $name) = explode('::', $taxterm); $Collection = new ProductCollection(); $Collection->load(array('ids' => true, 'taxquery' => array(array('taxonomy' => $taxonomy, 'field' => 'name', 'terms' => $name)))); $query = "UPDATE {$price_table} SET price=price+(price*{$taxrate}) WHERE tax='on' AND product IN (" . join(',', $Collection->products) . ")"; sDB::query($query); $done = array_merge($done, $Collection->products); } // Update the rest of the prices (skipping those we've already done) with the tax rate that matches the base of operations $taxrate = array_sum($basetaxes); // Merge all the base taxes into a single rate $done = empty($done) ? '' : " AND product NOT IN (" . join(',', $done) . ")"; $query = "UPDATE {$price_table} SET price=price+(price*{$taxrate}) WHERE tax='on'{$done}"; sDB::query($query); } }
/** * Reset the shopping session * * Controls the cart to allocate a new session ID and transparently * move existing session data to the new session ID. * * @since 1.0 * * @param string $session (optional) Specify a session to load into this one * @return bool True on success, false otherwise **/ static function resession($session = false) { $Shopping = ShoppShopping(); do_action('shopp_pre_resession', $session); // Save the current session $Shopping->save(); if ($session) { // loading session $Shopping->preload($session); do_action('shopp_resession'); return true; } else { $Shopping->reprovision(); } do_action('shopp_reset_session'); // @deprecated do_action('shopp_reset_session') do_action('shopp_resession'); return true; }