/** * _setobject - returns the global context object used in the shopp('cartitem) call * * @internal * @since 1.2 * * @return ShoppCartItem|bool The working ShoppCartItem context **/ public static function _setobject($Object, $object) { if (is_object($Object) && is_a($Object, 'Item')) { return $Object; } if (strtolower($object) != 'cartitem') { return $Object; } else { $Cart = ShoppOrder()->Cart; $Item = false; if (isset($Cart->_item_loop)) { $Item = $Cart->current(); $Item->_id = $Cart->key(); return $Item; } elseif (isset($Cart->_shipped_loop)) { $Item = current($Cart->shipped); $Item->_id = key($Cart->shipped); return $Item; } elseif (isset($Cart->_downloads_loop)) { $Item = current($Cart->downloads); $Item->_id = key($Cart->downloads); return $Item; } return false; } }
/** * Get and set the global ShoppCustomer object * * @api * @since 1.2 * * @param ShoppCustomer $Object (optional) the specified ShoppCustomer object * @return ShoppCustomer the current global customer object **/ function ShoppCustomer($Object = false) { $Order = ShoppOrder(); if ($Object && is_a($Object, 'ShoppCustomer')) { $Order->Customer = $Object; } return $Order->Customer; }
function checkout() { if (version_compare(SHOPP_VERSION, '1.1.9', '<=')) { $this->Order->Billing->cardtype = "BillmateBank"; $this->Order->confirm = true; } else { $Order = ShoppOrder(); $Order->Billing->cardtype = 'BillmateBank'; $Order->confirm = true; } }
function checkout() { if (version_compare(SHOPP_VERSION, '1.1.9', '<=')) { $this->Order->Billing->cardtype = "BillmateCardpay"; $this->Order->confirm = true; $this->Order->capture = $this->settings['authentication_method'] == 'sale' ? 'YES' : 'NO'; } else { $Order = ShoppOrder(); $Order->Billing->cardtype = 'BillmateCardpay'; $Order->capture = $this->settings['authentication_method'] == 'sale' ? 'YES' : 'NO'; $Order->confirm = true; } }
public static function login($result) { $Customer = ShoppOrder()->Customer; if ($Customer->loggedin()) { return $result; } $accounts = shopp_setting('account_system'); $pleaselogin = '******' . Shopp::__('If you have an account with us, please login now.'); // This specific !isset condition checks if the loginname is not provided // If no loginname is provided, but an account system is used, we need to // generate a new login name for the customer if ('wordpress' == $accounts && !isset($_POST['loginname'])) { ShoppLoginGenerator::object(); $_POST['loginname'] = ShoppLoginGenerator::name(); if (apply_filters('shopp_login_required', empty($_POST['loginname']))) { return shopp_add_error(Shopp::__('A login could not be created with the information you provided. Enter a different name or email address.') . $pleaselogin); } shopp_debug('Login set to ' . $_POST['loginname'] . ' for WordPress account creation.'); } // Validate unique email address for new account if (in_array($accounts, array('wordpress', 'shopp')) && !$Customer->session(ShoppCustomer::GUEST)) { $ShoppCustomer = new ShoppCustomer($_POST['email'], 'email'); if (apply_filters('shopp_email_exists', 'wordpress' == $accounts ? email_exists($_POST['email']) : $ShoppCustomer->exists())) { return shopp_add_error(Shopp::__('The email address you entered is already in use. Enter a different email address to create a new account.') . $pleaselogin); } } // Validate WP login if (isset($_POST['loginname'])) { if (apply_filters('shopp_login_required', empty($_POST['loginname']))) { return shopp_add_error(Shopp::__('You must enter a login name for your account.')); } if (apply_filters('shopp_login_valid', !validate_username($_POST['loginname']))) { $sanitized = sanitize_user($_POST['loginname'], true); $illegal = array_diff(str_split($_POST['loginname']), str_split($sanitized)); return shopp_add_error(Shopp::__('The login name provided includes invalid characters: %s', esc_html(join(' ', $illegal)))); } if (apply_filters('shopp_login_exists', username_exists($_POST['loginname']))) { return shopp_add_error(Shopp::__('"%s" is already in use. Enter a different login name to create a new account.', esc_html($_POST['loginname'])) . $pleaselogin); } } return $result; }
/** * Calculates the order Totals * * @author Jonathan Davis * @since 1.3 * * @return void **/ public function totals() { // Setup totals counter if (false === $this->Totals) { $this->Totals = new OrderTotals(); } $Totals = $this->Totals; do_action('shopp_cart_totals_init', $Totals); $Shipping = ShoppOrder()->Shiprates; $Discounts = ShoppOrder()->Discounts; // Identify downloadable products $downloads = $this->downloads(); $shipped = $this->shipped(); do_action('shopp_cart_item_totals', $Totals); // Update cart item totals $items = $this->keys(); // Use local array for iterating foreach ($items as $itemid) { // Allow other code to iterate the cart in this loop $Item = $this->get($itemid); $Item->totals(); } $Totals->register(new OrderAmountShipping(array('id' => 'cart', 'amount' => $Shipping->calculate()))); if (apply_filters('shopp_tax_shipping', shopp_setting_enabled('tax_shipping'))) { $Totals->register(new OrderAmountShippingTax($Totals->total('shipping'))); } // Calculate discounts $Totals->register(new OrderAmountDiscount(array('id' => 'cart', 'amount' => $Discounts->amount()))); // Apply credits to discount the order $Discounts->credits(); if ($Discounts->shipping()) { // If shipping discounts changed, recalculate shipping amount $Totals->register(new OrderAmountShipping(array('id' => 'cart', 'amount' => $Shipping->calculate()))); } // Ensure taxes are recalculated $Totals->total('tax'); do_action_ref_array('shopp_cart_retotal', array(&$Totals)); return $Totals; }
public function smart(array $options = array()) { $this->name = __('Customers also bought…', 'Shopp'); $this->controls = false; $where = array("true=false"); $scope = array(); $Product = ShoppProduct(); $Order = ShoppOrder(); $Cart = $Order->Cart; // Use the current product is available if (!empty($Product->id)) { $this->product = $Product; } // Or load a product specified if (!empty($options['product'])) { if ('recent-cartitem' == $options['product']) { // Use most recently added item in the cart $this->product = new ShoppProduct($Cart->added()->product); } elseif (preg_match('/^[\\d+]$/', $options['product'])) { // Load by specified id $this->product = new ShoppProduct($options['product']); } else { $this->product = new ShoppProduct($options['product'], 'slug'); // Load by specified slug } } if (empty($this->product->id)) { $loading = compact('where'); $this->loading = array_merge($options, $loading); return; } $this->name = Shopp::__('Customers that bought "%s" also bought…', $this->product->name); $purchased = ShoppDatabaseObject::tablename(Purchased::$table); $query = "SELECT p2,((psum - (sum1 * sum2 / n)) / sqrt((sum1sq - pow(sum1, 2.0) / n) * (sum2sq - pow(sum2, 2.0) / n))) AS r, n\n\t\t\t\t\t\t\t\tFROM (\n\t\t\t\t\t\t\t\t\tSELECT n1.product AS p1,n2.product AS p2,SUM(n1.quantity) AS sum1,SUM(n2.quantity) AS sum2,\n\t\t\t\t\t\t\t\t\t\tSUM(n1.quantity * n1.quantity) AS sum1sq,SUM(n2.quantity * n2.quantity) AS sum2sq,\n\t\t\t\t\t\t\t\t\t\tSUM(n1.quantity * n2.quantity) AS psum,COUNT(*) AS n\n\t\t\t\t\t\t\t\t\tFROM {$purchased} AS n1\n\t\t\t\t\t\t\t\t\tLEFT JOIN {$purchased} AS n2 ON n1.purchase = n2.purchase\n\t\t\t\t\t\t\t\t\tWHERE n1.product != n2.product\n\t\t\t\t\t\t\t\t\tGROUP BY n1.product,n2.product\n\t\t\t\t\t\t\t\t) AS step1\n\t\t\t\t\t\t\t\tORDER BY r DESC, n DESC"; $cachehash = 'alsobought_' . md5($query); $cached = Shopp::cache_get($cachehash, 'shopp_collection_alsobought'); if ($cached) { $matches = $cached; } else { $matches = sDB::query($query, 'array', 'col', 'p2'); Shopp::cache_set($cachehash, $matches, 'shopp_collection_alsobought', 14400); //Expires in 4 hours } if (empty($matches)) { $loading = compact('where'); $this->loading = array_merge($options, $loading); return; } $where = array("p.id IN (" . join(',', $matches) . ")"); $loading = compact('columns', 'joins', 'where', 'groupby', 'order'); $this->loading = array_merge($options, $loading); if (isset($options['controls']) && Shopp::str_true($options['controls'])) { unset($this->controls); } }
/** * Provides the submit login button markup * * @api `shopp('customer.submit-login')` * @since 1.0 * * @param string $result The output * @param array $options The options * - **autocomplete**: (on, off) Specifies whether an `<input>` element should have autocomplete enabled * - **accesskey**: Specifies a shortcut key to activate/focus an element. Linux/Windows: `[Alt]`+`accesskey`, Mac: `[Ctrl]``[Opt]`+`accesskey` * - **class**: The class attribute specifies one or more class-names for an element * - **disabled**: Specifies that an `<input>` element should be disabled * - **placeholder**: Specifies a short hint that describes the expected value of an `<input>` element * - **required**: Adds a class that specified an input field must be filled out before submitting the form, enforced by JS * - **tabindex**: Specifies the tabbing order of an element * - **title**: Specifies extra information about an element * - **label**: Specifies the value of the button element. Defaults to `Login` * - **redirect**: Specifies the URL the customer is redirected to after login. Defaults to `$_REQUEST['redirect']`. * @param ShoppCustomer $O The working object * @return string The button markup **/ public static function submit_login($result, $options, $O) { $request = $_GET; $defaults = array('label' => Shopp::__('Login'), 'redirect' => isset($_REQUEST['redirect']) ? $_REQUEST['redirect'] : Shopp::url($request, 'account', ShoppOrder()->security())); $options = array_merge($defaults, $options); extract($options, EXTR_SKIP); $string = ''; $id = 'submit-login'; $context = ShoppStorefront::intemplate(); if (isset($request['acct']) && 'logout' == $request['acct']) { unset($request['acct']); } if ('checkout.php' == $context) { $redirect = 'checkout'; $id .= '-' . $redirect; } return '<input type="hidden" name="redirect" value="' . esc_attr($redirect) . '" />' . '<input type="submit" name="submit-login" id="' . $id . '"' . inputattrs($options) . ' />'; }
public function fromshipping() { $Shipping = ShoppOrder()->Shipping; $fields = array($this->address, $this->xaddress, $this->city); $address = join('', $fields); if (empty($address)) { $this->copydata($Shipping, '', array('type')); } }
/** * Provides a custom text field for collecting any number of custom order fields * * @api `shopp('checkout.order-data')` * @since 1.0 * * @param string $result The output * @param array $options The options * - **name**: **REQUIRED** The name of the customer info field * - **mode**: `input` (input, value) Provide the `input` markup or the current `value` of the `name` field * - **type**: `hidden` (textarea, menu, hidden, radio, checkbox, button, submit) The type of input markup to generate * - **options**: Comma-separated option values * - **autocomplete**: (on, off) Specifies whether an `<input>` element should have autocomplete enabled * - **accesskey**: Specifies a shortcut key to activate/focus an element. Linux/Windows: `[Alt]`+`accesskey`, Mac: `[Ctrl]``[Opt]`+`accesskey` * - **alt**: Specifies an alternate text for images (only for type="image") * - **checked**: Specifies that an `<input>` element should be pre-selected when the page loads (for type="checkbox" or type="radio") * - **class**: The class attribute specifies one or more class-names for an element * - **disabled**: Specifies that an `<input>` element should be disabled * - **format**: Specifies special field formatting class names for JS validation * - **minlength**: Sets a minimum length for the field enforced by JS validation * - **maxlength**: Specifies the maximum number of characters allowed in an `<input>` element * - **placeholder**: Specifies a short hint that describes the expected value of an `<input>` element * - **readonly**: Specifies that an input field is read-only * - **required**: Adds a class that specified an input field must be filled out before submitting the form, enforced by JS * - **size**: Specifies the width, in characters, of an `<input>` element * - **src**: Specifies the URL of the image to use as a submit button (only for type="image") * - **tabindex**: Specifies the tabbing order of an element * - **cols**: Specifies the visible width of a `<textarea>` * - **rows**: Specifies the visible number of lines in a `<textarea>` * - **title**: Specifies extra information about an element * - **value**: Specifies the value of an `<input>` element * @param ShoppOrder $O The working object * @return string The custom order data field markup **/ public static function order_data($result, $options, $O) { $select_attrs = array('title', 'class', 'disabled', 'required', 'size', 'tabindex', 'accesskey'); $defaults = array('name' => false, 'data' => false, 'mode' => false, 'title' => '', 'type' => 'hidden', 'value' => '', 'options' => ''); if (isset($options['name']) && array_key_exists($options['name'], ShoppOrder()->data)) { $defaults['value'] = ShoppOrder()->data[$options['name']]; } if (isset($options['type']) && 'textarea' == $options['type']) { $defaults['cols'] = '30'; $defaults['rows'] = '3'; } $op = array_merge($defaults, $options); extract($op); // Allowed input types $allowed_types = array("text", "hidden", "password", "checkbox", "radio", "textarea", "menu"); // Input types that can override option-specified value with the loaded data value $value_override = array("text", "hidden", "password", "textarea", "menu"); /// Allowable attributes for textarea inputs $textarea_attrs = array('accesskey', 'title', 'tabindex', 'class', 'disabled', 'required', 'maxlength'); if (!$name) { // Iterator for order data if (!isset($O->_data_loop)) { reset($O->data); $O->_data_loop = true; } else { next($O->data); } if (current($O->data) !== false) { return true; } else { unset($O->_data_loop); return false; } } if (isset($O->data[$name])) { $data = $O->data[$name]; } if ($name && $mode == "value") { return apply_filters('shopp_checkout_order_data', $data); } if (!in_array($type, $allowed_types)) { $type = 'hidden'; } if (empty($title)) { $title = $name; } $id = 'order-data-' . sanitize_title_with_dashes($name); if (in_array($type, $value_override) && !empty($data)) { $op['value'] = $value = $data; } switch (strtolower($type)) { case "textarea": return '<textarea name="data[' . $name . ']" cols="' . $cols . '" rows="' . $rows . '" id="' . $id . '" ' . inputattrs($op, $textarea_attrs) . '>' . $value . '</textarea>'; break; case "menu": $menuvalues = true; if (is_string($options)) { $menuvalues = false; $options = explode(',', $options); } return '<select name="data[' . $name . ']" id="' . $id . '" ' . inputattrs($op, $select_attrs) . '>' . menuoptions($options, $value, $menuvalues) . '</select>'; break; default: return '<input type="' . $type . '" name="data[' . $name . ']" id="' . $id . '" ' . inputattrs($op) . ' />'; break; } }
/** * Formats monetary amounts for handing off to the gateway * * Supports specifying an order total by name (subtotal, tax, shipping, total) * * @author Jonathan Davis * @since 1.2 * * @param string|float|int $amount The amount (or name of the amount total) to format * @return string Formatted amount **/ public function amount($amount, array $format = array()) { $register = false; if (is_string($amount)) { $register = $amount; $Cart = ShoppOrder()->Cart; $amount = $Cart->total($amount); if (false === $amount) { $register = false; } } elseif (!(is_int($amount) || is_float($amount))) { return $amount; } $defaults = array('precision' => $this->precision, 'decimals' => $this->decimals, 'thousands' => $this->thousands); $format = array_merge($defaults, $format); extract($format); if (!empty($register)) { // Allow targeting specific amounts for filtering $amount = apply_filters("shopp_gateway_{$register}_amount", $amount); } $amount = apply_filters('shopp_gateway_amount', abs($amount)); return number_format($amount, $precision, $decimals, $thousands); }
/** * Removes an addon from a cartitem. The addonkey should be the numeric ID of the addon. * * @api * * @param mixed $itemkey * @param mixed $addonkey * @return bool */ function shopp_rmv_cart_item_addon($itemkey = false, $addonkey = false) { $Order = ShoppOrder(); $exists = false; if (false === $itemkey || false === $addonkey) { shopp_debug(__FUNCTION__ . " failed: item and addon parameter required."); return false; } if (!($item = shopp_cart_item($itemkey))) { shopp_debug(__FUNCTION__ . " failed: no such item {$itemkey}"); return false; } if (false === ($addons = shopp_cart_item_addons($itemkey))) { return false; // Debug message will already have been generated in shopp_cart_item_addons() } if (!isset($addons[$addonkey])) { shopp_debug(__FUNCTION__ . " failed: addon {$addonkey} was not found in item {$itemkey}"); return false; } $revised = array(); foreach ($addons as $addon) { if ($addonkey == $addon->id) { $revised[] = (int) ($addonkey * -1); } else { $revised[] = $addon->id; } } return $Order->Cart->change($itemkey, $item->product, (int) $item->priceline, $revised); }
/** * Checks if the current product is in the shopping cart * * @api `shopp('product.in-cart')` * @since 1.1 * * @param string $result The output * @param array $options The options * @param ShoppProduct $O The working object * @return bool True if the product is in the cart, false otherwise **/ public static function in_cart($result, $options, $O) { $Cart = ShoppOrder()->Cart; if ($Cart->count == 0) { return false; } // Cart is empty foreach ($Cart as $Item) { if ($Item->product == $O->id) { return true; } } return false; }
/** * Determines all applicable tax rates for the store or an item * * @author Jonathan Davis * @since 1.0 * @version 1.3 * * @param Object $Item (optional) The ShoppProduct, ShoppCartItem or ShoppPurchased object to find tax rates for * @return float The determined tax rate **/ public static function taxrates($Item = null) { $Tax = new ShoppTax(); $Order = ShoppOrder(); // Setup taxable address $Tax->address($Order->Billing, $Order->Shipping, $Order->Cart->shipped()); $taxes = array(); if (is_null($Item)) { $Tax->rates($taxes); } else { $Tax->rates($taxes, $Tax->item($Item)); } return apply_filters('shopp_taxrates', $taxes); }
public function shipping_costs() { if (!isset($_GET['method'])) { die(0); } $Order = ShoppOrder(); $Shiprates = $Order->Shiprates; $selected = $Shiprates->selected(); if ($selected === false || isset($selected->slug) && $_GET['method'] != $selected->slug) { $Shiprates->selected($_GET['method']); } echo (string) $Order->Cart->totals(); exit; }
/** * Calculates estimated delivery timeframes * * @author Jonathan Davis * @since 1.2 * * @return string Delivery estimate string **/ public function delivery(array $data = array()) { $defaults = array('mindelivery' => '1w', 'maxdelivery' => '2w'); $data = array_merge($defaults, $data); $cart = ShoppOrder()->Cart->processing; $min = shopp_setting('order_processing_min'); $max = shopp_setting('order_processing_max'); $earliest = apply_filters('shopp_mindelivery_estimate', ShippingFramework::daytimes($min, $cart['min'], $data['mindelivery']), $data, $this); $latest = apply_filters('shopp_maxdelivery_estimate', ShippingFramework::daytimes($max, $cart['max'], $data['maxdelivery']), $data, $this); return $earliest . '-' . $latest; }
/** * Calculate taxes that apply to the item * * @author Jonathan Davis * @since 1.3 * * @param integer $quantity The taxable quantity of items * @return void **/ public function taxes($quantity = 1) { if (!$this->istaxed) { return do_action('shopp_cart_item_taxes', $this); } $Tax = ShoppOrder()->Tax; if (empty($Tax)) { $Tax = new ShoppTax(); } // ShoppTax support for Dev API calls // For all the price units (base product and any addons), // distribute discounts across taxable amounts using weighted averages $_ = array(); if ($this->unitprice > 0) { $taxable = 0; foreach ($this->taxable as $amount) { $_[] = $amount - $amount / $this->unitprice * $this->discount; } } $taxable = (double) array_sum($_); $taxableqty = $this->bogof && $this->bogof != $this->quantity ? $this->quantity - $this->bogof : $this->quantity; $Tax->rates($this->taxes, $Tax->item($this)); $this->unittax = ShoppTax::calculate($this->taxes, $taxable); $this->tax = $Tax->total($this->taxes, (int) $taxableqty); // Handle inclusive tax price adjustments for non-EU markets or alternate tax rate markets $adjustment = ShoppTax::adjustment($this->taxes); if (1 != $adjustment) { if (!isset($this->taxprice)) { $this->taxprice = $this->unitprice; } // Modify the unitprice from the original tax inclusive price and update the discounted price $this->unitprice = $this->taxprice / $adjustment; $this->priced = $this->unitprice - $this->discount; } elseif (isset($this->taxprice)) { // Undo tax price adjustments $this->unitprice = $this->taxprice; unset($this->taxprice); } do_action('shopp_cart_item_taxes', $this); }
/** * Handler for profile updates in the account dashboard * * @author Jonathan Davis * @since 1.1 * * @return boolean|string output based on the account menu request **/ public function profile() { if (empty($_POST['customer'])) { return; } // Not a valid customer profile update request check_admin_referer('shopp_profile_update'); $defaults = array('phone' => '', 'password' => null, 'confirm-password' => null, 'info' => null, 'billing' => array(), 'shipping' => array()); $updates = array_merge($defaults, $_POST); extract($updates, EXTR_SKIP); $phone = preg_replace('/[^\\d\\(\\)\\-+\\. (ext|x)]/', '', $phone); // Update this ShoppCustomer model $this->updates($updates); if (is_array($info)) { $this->info = $info; } // Add info fields if ('' != $password . $updates['confirm-password'] && $password == $updates['confirm-password']) { $this->password = wp_hash_password($password); if ('wordpress' == shopp_setting('account_system') && !empty($this->wpuser)) { wp_set_password($password, $this->wpuser); } $this->_password_change = true; } else { if (!empty($password)) { shopp_add_error(Shopp::__('The passwords you entered do not match. Please re-enter your passwords.')); } $this->_password_change = false; } do_action('shopp_customer_update', $this); $this->save(); $this->load_info(); $addresses = array('billing' => 'Billing', 'shipping' => 'Shipping'); foreach ($addresses as $type => $Address) { if (empty($updates[$type])) { continue; } $Updated = ShoppOrder()->{$Address}; $Updated->customer = $this->id; $Updated->updates($updates[$type]); $Updated->save(); } $this->updated(self::PROFILE, true); if ($this->_password_change) { Shopp::redirect(Shopp::url(false, 'account')); } }
public function content($content) { global $wp_query; // Test that this is the main query and it is the confirm order page if (!$wp_query->is_main_query() || !is_shopp_page('confirm')) { return $content; } $Errors = ShoppErrors(); $Order = ShoppOrder(); do_action('shopp_init_confirmation'); $Order->validated = $Order->isvalid(); ob_start(); ShoppStorefront()->_confirm_page_content = true; if ($Errors->exist(SHOPP_COMM_ERR)) { echo ShoppStorefront::errors(array('errors-confirm.php', 'errors.php')); } locate_shopp_template(array('confirm.php'), true); $content = ob_get_contents(); unset(ShoppStorefront()->_confirm_page_content); ob_end_clean(); return apply_filters('shopp_order_confirmation', $content); }
/** * Provides the count of the total number of discounts applied to the cart * * @api `shopp('cart.total-discounts')` * @since 1.2 * * @param string $result The output * @param array $options The options * @param ShoppCart $O The working object * @return int The number of discounts on the cart **/ public static function total_discounts($result, $options, $O) { return (int) ShoppOrder()->Discounts->count(); }
/** * Provides markup for a menu of the shipping options * * @api `shopp('shipping.option-menu')` * @since 1.2 * * @param string $result The output * @param array $options The options * - **difference**: `on` (on,off) Provide the cost difference relative to the currently selected shipping method option * - **times**: `off` (on,off) Show the estimated delivery time frames in the menu * - **class**: The class attribute specifies one or more class-names for menu * - **dateformat**: Sets the PHP date formatting to use. Defaults to the WordPress date and time formats * - **dateseparator**: `—` Sets the separator character between the two dates in the delivery estimate * @param ShoppShiprates $O The working object * @return string The menu markup **/ public static function option_menu($result, $options, $O) { $Order = ShoppOrder(); $Shiprates = $Order->Shiprates; $defaults = array('difference' => true, 'times' => false, 'class' => false, 'dateformat' => get_option('date_format'), 'dateseparator' => '—'); $options = array_merge($defaults, $options); extract($options); $classes = 'shopp shipmethod'; if (!empty($class)) { $classes = $class . ' ' . $classes; } $_ = array(); $selected_option = $Shiprates->selected(); $_[] = '<select name="shipmethod" class="' . $classes . '">'; foreach ($O as $method) { $cost = money($method->amount); $delivery = false; if (Shopp::str_true($times) && !empty($method->delivery)) { $delivery = self::_delivery_format($method->delivery, $options) . ' '; } if ($selected_option && Shopp::str_true($difference)) { $diff = $method->amount - $selected_option->amount; $pre = $diff < 0 ? '-' : '+'; $cost = $pre . money(abs($diff)); } $selected = $selected_option && $selected_option->slug == $method->slug ? ' selected="selected"' : false; $_[] = '<option value="' . esc_attr($method->slug) . '"' . $selected . '>' . $method->name . ' ( ' . $delivery . $cost . ' )</option>'; } $_[] = '</select>'; return join('', $_); }
public function __construct($taxable) { $Tax = ShoppOrder()->Tax; $taxes = array(); $Tax->rates($taxes); $firstrate = reset($taxes); if ($firstrate) { $this->rate = $firstrate->rate; } $this->id = 'shipping'; $this->amount = ShoppTax::calculate($taxes, $taxable); $this->label = Shopp::__('Shipping Tax'); }
/** * Verify the authenticity of a PDT message sent by PayPal * * @author Jonathan Davis, John Dillick * @since 1.0 * * @return boolean True if valid, false otherwise **/ protected function pdtvalid() { $ids = array($this->id(), 'PPS'); // 'PPS' is a backwards compatible ID for PDT requests if (!in_array($_REQUEST['rmtpay'], $ids)) { return false; } // not PDT message shopp_debug('Processing PDT request: ' . json_encode($_REQUEST)); if (!Shopp::str_true($this->settings['pdtverify']) || !isset($_REQUEST['tx'])) { ShoppOrder()->success(); return true; // if PDT verify is off, skip this process } $_ = array(); $_['cmd'] = '_notify-synch'; $_['at'] = $this->settings['pdttoken']; $_['tx'] = $_REQUEST['tx']; $message = $this->encode($_); // Build the request $response = $this->send($message); // Send it $response = $this->pdtreply($response); // Parse the response into a ShoppPayPalStandardMessage-compatible structure shopp_debug('PayPal PDT _notify-synch reply: ' . json_encode($response)); // Shift the first element off to get the verification status and have a clean data array for ShoppPayPalStandardMessage if ('SUCCESS' != array_shift($response)) { shopp_debug('The transaction was not verified by PayPal.'); // We run the success() method here to reset the shopping session and // redirect the shopper to the "thanks" page with an "order in progress" message // so the cart will be ready for a new order. Otherwise, the customer could resubmit the // prior order and PayPal will give them "that transaction has already been completed" message. ShoppOrder()->success(); return false; } $this->Message = new ShoppPayPalStandardMessage($response); shopp_debug('PayPal PDT response protocol: ' . _object_r($this->Message)); // Everything looks good, return true and let the order PDT order processing handle it from here return true; }
/** * Unapply the discount * * This primarily involves resetting the Cart Item->freeshipping property. * * @author Jonathan Davis * @since 1.3 * * @return void Description... **/ public function unapply() { $Cart = ShoppOrder()->Cart; if (self::SHIP_FREE == $this->type) { $Shiprates = ShoppOrder()->Shiprates; foreach ($this->items as $id => $item) { $CartItem = $Cart->get($id); $CartItem->freeshipping = false; } } }
/** * Adds shopp('checkout.offlineinstructions') Theme API support * * @author Jonathan Davis * @since 1.1 * * @return void **/ public function instructions($result, $options) { add_filter('shopp_offline_payment_instructions', 'stripslashes'); add_filter('shopp_offline_payment_instructions', 'wptexturize'); add_filter('shopp_offline_payment_instructions', 'convert_chars'); add_filter('shopp_offline_payment_instructions', 'wpautop'); $paymethod = shopp('purchase', 'get-paymethod'); $Payments = ShoppOrder()->Payments; if (!$Payments->exists($paymethod)) { return false; } $Paymethod = $Payments->get($paymethod); list($module, $id) = explode('-', $Paymethod->setting); if (!isset($this->settings[$id])) { return false; } $settings = $this->settings[$id]; if (!empty($settings['instructions'])) { return apply_filters('shopp_offline_payment_instructions', $settings['instructions']); } return false; }
function checkout() { $this->isPermitted(); if (empty($_POST['billmate']['pno'])) { new ShoppError(__('Please enter personal number', 'shopp-billmate-invoice'), 2); echo '<script type="text/javascript">window.location.href="' . shoppurl(false, 'checkout') . '";</script>'; die; } if (version_compare(SHOPP_VERSION, '1.1.9', '<=')) { $this->Order->Billing->cardtype = "Billmate Invoice"; $this->Order->confirm = true; $this->Order->pno = $_POST['billmate']['pno']; $this->Order->billmatephone = $_POST['billmate']['phone']; $this->Order->overritedefaultaddress = !empty($_POST['geturl']) ? true : false; } else { $Order = ShoppOrder(); $Order->Billing->cardtype = 'Billmate Invoice'; $Order->pno = $_POST['billmate']['pno']; $Order->billmatephone = $_POST['billmate']['phone']; $Order->overritedefaultaddress = !empty($_POST['geturl']) ? true : false; $Order->confirm = true; } }
/** * Setup and process account dashboard page requests * * @author Jonathan Davis * @since 1.2 * * @return void **/ public function dashboard() { $Order = ShoppOrder(); $this->add_dashboard('logout', __('Logout', 'Shopp')); $this->add_dashboard('orders', __('Your Orders', 'Shopp'), true, array(ShoppCustomer(), 'load_orders')); $this->add_dashboard('downloads', __('Downloads', 'Shopp'), true, array(ShoppCustomer(), 'load_downloads')); $this->add_dashboard('profile', __('My Account', 'Shopp'), true); // Pages not in menu navigation $this->add_dashboard('login', __('Login to your Account'), false); $this->add_dashboard('recover', __('Password Recovery'), false); $this->add_dashboard('rp', __('Password Recovery'), false); $this->add_dashboard('menu', __('Dashboard', 'Shopp'), false); do_action('shopp_account_menu'); // Always handle customer profile updates add_action('shopp_account_management', array(ShoppCustomer(), 'profile')); // Add dashboard page specific handlers add_action('shopp_account_management', array($this, 'dashboard_handler')); $query = $_SERVER['QUERY_STRING']; $query = html_entity_decode($query); $query = explode('&', $query); $request = 'menu'; $id = false; foreach ($query as $queryvar) { $value = false; if (false !== strpos($queryvar, '=')) { list($key, $value) = explode('=', $queryvar); } else { $key = $queryvar; } if (in_array($key, array_keys($this->dashboard))) { $request = $key; $id = $value; } } $this->account = compact('request', 'id'); $download_request = get_query_var('s_dl'); if (!ShoppCustomer()->loggedin()) { $screens = array('login', 'recover', 'rp'); if (!in_array($this->account['request'], $screens)) { $this->account = array('request' => 'login', 'id' => false); } } do_action('shopp_account_management'); if ('rp' == $request) { ShoppAccountPage::resetpassword($_GET['rp']); } if (isset($_POST['recover-login'])) { ShoppAccountPage::recovery(); } }
/** * 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 static function process() { // We have to avoid truthiness, hence the strange logic expression if (true !== apply_filters('shopp_validate_registration', true)) { return; } $Customer = ShoppOrder()->Customer; do_action('shopp_customer_registration', $Customer); if ($Customer->session(ShoppCustomer::GUEST)) { $Customer->type = __('Guest', 'Shopp'); // No cuts $Customer->wpuser = 0; // No buts unset($Customer->password); // No coconuts } else { // WordPress account integration used, customer has no wp user if ('wordpress' == shopp_setting('account_system') && empty($Customer->wpuser)) { if ($wpuser = get_current_user_id()) { $Customer->wpuser = $wpuser; } else { $Customer->create_wpuser(); } // not logged in, create new account } if (!$Customer->exists(true)) { $Customer->id = false; shopp_debug('Creating new Shopp customer record'); if (empty($Customer->password)) { $Customer->password = wp_generate_password(12, true); } if ('shopp' == shopp_setting('account_system')) { $Customer->notification(); } $Customer->password = wp_hash_password($Customer->password); if (isset($Customer->passhash)) { $Customer->password = $Customer->passhash; } } else { unset($Customer->password); } // Existing customer, do not overwrite password field! } // New customer, save hashed password $Customer->save(); $Customer->password = ''; // Update billing and shipping addresses $addresses = array('Billing', 'Shipping'); foreach ($addresses as $Address) { if (empty(ShoppOrder()->{$Address}->address)) { continue; } $Address = ShoppOrder()->{$Address}; $Address->customer = $Customer->id; $Address->save(); } do_action('shopp_customer_registered', $Customer); // Auto-login $Customer->login(); // Login the customer if (!empty($Customer->wpuser)) { // Log the WordPress user in ShoppLogin::wpuser(get_user_by('id', $Customer->wpuser)); } if (apply_filters('shopp_registration_redirect', false)) { Shopp::redirect(Shopp::url(false, 'account')); } }
/** * shopp_add_order - create an order from the cart and associate with a customer * * @api * @since 1.2 * * @param int $customer the customer that the order will be created for * @return bool|ShoppPurchase false on failure, Purchase object of recently created order on success **/ function shopp_add_order($customer = false) { // check customer if (!($Customer = shopp_customer((int) $customer))) { shopp_debug(__FUNCTION__ . " failed: Invalid customer."); return false; } if (!shopp_cart_items_count()) { shopp_debug(__FUNCTION__ . " failed: No items in cart."); return false; } $Order = ShoppOrder(); $Order->Customer = $Customer; $Order->Billing = $Customer->Billing; $Order->Billing->cardtype = 'api'; $Order->Shipping = $Customer->Shipping; shopp_add_order_event(false, 'purchase', array('gateway' => 'GatewayFramework')); shopp_empty_cart(); return ($Purchase = ShoppPurchase()) ? $Purchase : false; }