public function download($dkey = false) { $found = $this->found(); if (!$found) { return shopp_add_error(Shopp::__('Download failed. "%s" could not be found.', $this->name), 'false'); } add_action('shopp_download_success', array($this, 'downloaded')); // send immediately if the storage engine is redirecting if (isset($found['redirect'])) { $this->send(); exit; } // Close the session in case of long download @session_write_close(); // Don't want interference from the server if (function_exists('apache_setenv')) { @apache_setenv('no-gzip', 1); } @ini_set('zlib.output_compression', 0); set_time_limit(0); // Don't timeout on long downloads // Use HTTP/1.0 Expires to support bad browsers (trivia: timestamp used is the Shopp 1.0 release date) header('Expires: ' . date('D, d M Y H:i:s O', 1230648947)); header('Cache-Control: maxage=0, no-cache, must-revalidate'); header('Content-type: application/octet-stream'); header("Content-Transfer-Encoding: binary"); header('Content-Disposition: attachment; filename="' . $this->name . '"'); header('Content-Description: Delivered by ' . ShoppVersion::agent()); ignore_user_abort(true); if (ob_get_length() !== false) { while (@ob_end_flush()) { } } // Clear all open output buffers $this->send(); // Send the file data using the storage engine flush(); // Flush output to browser (to poll for connection) if (connection_aborted()) { return shopp_add_error(Shopp::__('Connection broken. Download attempt failed.'), SHOPP_COMM_ERR); } return true; }
/** * Defines the shopp() 'tag' handler for complete template customization * * Appropriately routes tag calls to the tag handler for the requested object. * * @api * @since 1.0 * * @param mixed $context The object label or Object to get the tag property from * @param string $property The property of the object to get/output * @param string|array $options Custom options for the property result in query form * (option1=value&option2=value&...) or alternatively as an associative array * @return void|bool|string Boolean values or string result or nothing if the string is output */ function shopp($context, $property = false, $options = false) { $Object = false; $result = false; $parameters = array('first', 'second', 'third'); // Parameter prototype $num = func_num_args(); // Determine number of arguments provided $fargs = func_get_args(); $context = $tag = false; // object API to use and tag name $options = array(); // options to pass to API call if ($num < 1) { // Not enough arguments to do anything, bail shopp_add_error(Shopp::__('shopp() theme tag syntax error: no object property specified.'), SHOPP_PHP_ERR); return; } // Grab the arguments (up to 3) $args = array_combine(array_slice($parameters, 0, $num), $fargs); extract($args); if (is_object($first)) { // Handle Object instances as first argument $Object = $first; $context = isset($Object->api) ? $Object->api : strtolower(get_class($Object)); $tag = strtolower($second); } elseif (false !== strpos($first, '.')) { // Handle object.tag first argument list($context, $tag) = explode('.', strtolower($first)); if ($num > 1) { $options = shopp_parse_options($second); } } elseif ('' == $context . $tag) { // Normal tag handler list($context, $tag) = array_map('strtolower', array($first, $second)); } if ($num > 2) { $options = shopp_parse_options($third); } // strip hypens from tag names $tag = str_replace('-', '', $tag); // strip get prefix from requested tag $get = false; if ('get' == substr($tag, 0, 3)) { $tag = substr($tag, 3); $get = true; } $Object = apply_filters('shopp_themeapi_object', $Object, $context, $tag); $Object = apply_filters('shopp_tag_domain', $Object, $context); // @deprecated if ('hascontext' == $tag) { return $Object; } if (!$Object) { shopp_add_error(Shopp::__("The shopp('%s') tag cannot be used in this context because the object responsible for handling it doesn't exist.", $context), SHOPP_PHP_ERR); } $themeapi = apply_filters('shopp_themeapi_context_name', $context); $result = apply_filters('shopp_themeapi_' . strtolower($themeapi . '_' . $tag), $result, $options, $Object); // tag specific tag filter $result = apply_filters('shopp_tag_' . strtolower($context . '_' . $tag), $result, $options, $Object); // @deprecated use shopp_themeapi_{api}_{tag} $result = apply_filters('shopp_themeapi_' . strtolower($themeapi), $result, $options, $tag, $Object); // global object tag filter $result = apply_filters('shopp_themeapi', $result, $options, $tag, $Object); $result = apply_filters('shopp_ml_t', $result, $options, $tag, $Object); // @deprecated use shopp_themeapi // Force boolean result if (isset($options['is'])) { if (Shopp::str_true($options['is'])) { if ($result) { return true; } } else { if (false == $result) { return true; } } return false; } // Always return a boolean if the result is boolean if (is_bool($result)) { return $result; } if ($get || isset($options['return']) && Shopp::str_true($options['return']) || isset($options['echo']) && !Shopp::str_true($options['echo'])) { return $result; } // Output the result if (is_scalar($result)) { echo $result; } else { return $result; } }
static function resetpassword($activation) { if ('none' == shopp_setting('account_system')) { return; } $user_data = false; $activation = preg_replace('/[^a-z0-9]/i', '', $activation); $errors = array(); if (empty($activation) || !is_string($activation)) { $errors[] = new ShoppError(Shopp::__('Invalid key')); } $RecoveryCustomer = new ShoppCustomer($activation, 'activation'); if (empty($RecoveryCustomer->id)) { $errors[] = new ShoppError(Shopp::__('Invalid key')); } if (!empty($errors)) { return false; } // Generate a new random password $password = wp_generate_password(); do_action_ref_array('password_reset', array($RecoveryCustomer, $password)); $RecoveryCustomer->password = wp_hash_password($password); if ('wordpress' == shopp_setting('account_system')) { $user_data = get_userdata($RecoveryCustomer->wpuser); wp_set_password($password, $user_data->ID); } $RecoveryCustomer->activation = ''; $RecoveryCustomer->save(); $subject = apply_filters('shopp_reset_password_subject', Shopp::__('[%s] New Password', get_option('blogname'))); $_ = array(); $_[] = 'From: ' . Shopp::email_from(shopp_setting('merchant_email'), shopp_setting('business_name')); $_[] = 'To: ' . $RecoveryCustomer->email; $_[] = 'Subject: ' . $subject; $_[] = 'Content-type: text/html'; $_[] = ''; $_[] = '<p>' . Shopp::__('Your new password for %s:', get_bloginfo('url')) . '</p>'; $_[] = ''; $_[] = '<ul>'; if ($user_data) { $_[] = '<li>' . Shopp::__('Login name: %s', $user_data->user_login) . '</li>'; } $_[] = '<li>' . Shopp::__('Password: %s', $password) . '</li>'; $_[] = '</ul>'; $_[] = ''; $_[] = '<p>' . Shopp::__('Click here to login: %s', Shopp::url(false, 'account')) . '</p>'; $message = apply_filters('shopp_reset_password_message', $_); if (!Shopp::email(join("\n", $message))) { shopp_add_error(Shopp::__('The e-mail could not be sent.')); Shopp::redirect(add_query_arg('acct', 'recover', Shopp::url(false, 'account'))); } else { shopp_add_error(Shopp::__('Check your email address for your new password.')); } unset($_GET['acct']); }
/** * 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; }
/** * Sets the quantity of the line item * * Sets the quantity only if stock is available or * the donation amount to the donation minimum. * * @author Jonathan Davis * @since 1.1 * * @param int $qty The quantity to set the line item to * @return void **/ public function quantity($qty = false) { $current = $this->quantity; if (false === $qty) { return $current; } if ($this->type == 'Donation' && Shopp::str_true($this->donation['var'])) { if (!(Shopp::str_true($this->donation['min']) && Shopp::floatval($qty) < $this->unitprice)) { $this->unitprice = Shopp::floatval($qty, false); } $this->quantity = 1; $qty = 1; } if (in_array($this->type, array('Membership', 'Subscription')) || 'Download' == $this->type && !shopp_setting_enabled('download_quantity')) { return $this->quantity = 1; } $qty = preg_replace('/[^\\d+]/', '', $qty); $this->quantity = (int) $qty; if (!$this->instock($qty)) { $levels = array($this->option->stock); foreach ($this->addons as $addon) { // Take into account stock levels of any addons if (Shopp::str_true($addon->inventory)) { $levels[] = $addon->stock; } } if ($qty > ($min = min($levels))) { if (shopp_setting_enabled('backorders')) { $this->backordered = $qty - $min; shopp_add_error(Shopp::__('"%s" is not available in the requested quantity. %d of the items will be backordered with delayed delivery.', $this->name, $this->backordered)); } else { shopp_add_error(Shopp::__('"%s" is not available in the requested quantity.', $this->name)); if (!$min) { return; } // don't set min to item quantity if no stock $this->quantity = $min; } } } $this->qtydelta = $this->quantity - $current; if (0 != $this->qtydelta) { $this->totals(); } }
/** * Add a developer debug error message to the Shopp log file * * @api * @since 1.3 * * @param string $message The error message to add * @param boolean $backtrace Include the call stack in the logged message * @return ShoppError The ShoppError object **/ function shopp_debug($message, $backtrace = false) { if (!SHOPP_DEBUG) { return false; } $callstack = false; if ($backtrace) { $callstack = ' ' . debug_caller(); } return shopp_add_error($message . $callstack, SHOPP_DEBUG_ERR); }
public function returned() { if ($this->id() != $_GET['rmtpay']) { return; } // Not our offsite payment $request = array_merge(array('merchant_order_id' => false, 'key' => false, 'order_number' => false, 'total' => false, 'credit_card_processed' => false, 'invoice_id' => false, 'pay_method' => false), $_GET); extract($request, EXTR_SKIP); if (Shopp::str_true($this->settings['verify']) && !$this->verify($key)) { shopp_add_error(Shopp::__('The order submitted by 2Checkout could not be verified.'), SHOPP_TRXN_ERR); Shopp::redirect(Shopp::url(false, 'checkout')); } if (empty($merchant_order_id)) { shopp_add_error(Shopp::__('The order submitted by 2Checkout did not specify a transaction ID.'), SHOPP_TRXN_ERR); Shopp::redirect(Shopp::url(false, 'checkout')); } $Purchase = ShoppPurchase(new ShoppPurchase((int) $merchant_order_id)); if (!$Purchase->exists()) { shopp_add_error(Shopp::__('The order submitted by 2Checkout did not match any submitted orders.'), SHOPP_TRXN_ERR); Shopp::redirect(Shopp::url(false, 'checkout')); } if ('Y' != $credit_card_processed) { shopp_add_order_event($Purchase->id, 'auth-fail', array('amount' => $total, 'error' => 'Declined', 'message' => Shopp::__('The payment was not completed succesfully'), 'gateway' => $this->module)); shopp_add_error(Shopp::__('The order submitted by 2Checkout did not match any submitted orders.'), SHOPP_TRXN_ERR); Shopp::redirect(Shopp::url(false, 'checkout')); } $this->Order->inprogress = $Purchase->id; add_action('shopp_authed_order_event', array(ShoppOrder(), 'notify')); add_action('shopp_authed_order_event', array(ShoppOrder(), 'accounts')); add_action('shopp_authed_order_event', array(ShoppOrder(), 'success')); shopp_add_order_event($Purchase->id, 'authed', array('txnid' => $order_number, 'amount' => (double) $total, 'fees' => false, 'gateway' => $this->module, 'paymethod' => '2Checkout', 'paytype' => $pay_method, 'payid' => $invoice_id, 'capture' => true)); Shopp::redirect(Shopp::url(false, 'thanks', false)); }
/** * Resets a customer/user password with a valid activation key * * @since 1.0 * * @param string $activation The activation key * @return void **/ static function resetpassword($activation) { if ('none' == shopp_setting('account_system') || ShoppCustomer()->loggedin()) { return; } $user_data = false; $activation = preg_replace('/[^a-z0-9]/i', '', $activation); $errors = array(); if (empty($activation) || !is_string($activation)) { $errors[] = shopp_add_error(Shopp::__("Invalid password reset key. Try copy/pasting the url in password reset email into your web browser's address bar.")); } else { $RecoveryCustomer = new ShoppCustomer($activation, 'activation'); if (empty($RecoveryCustomer->id)) { $errors[] = shopp_add_error(Shopp::__("Invalid password reset key. Try copy/pasting the url in password reset email into your web browser's address bar.")); } } if (!empty($errors)) { return false; } // Generate a new random password $password = wp_generate_password(12, false); do_action_ref_array('password_reset', array($RecoveryCustomer, $password)); $RecoveryCustomer->password = wp_hash_password($password); if ('wordpress' == shopp_setting('account_system')) { $user_data = get_userdata($RecoveryCustomer->wpuser); wp_set_password($password, $user_data->ID); } $RecoveryCustomer->activation = ''; $RecoveryCustomer->save(); $subject = apply_filters('shopp_reset_password_subject', Shopp::__('[%s] New Password', get_option('blogname'))); $_ = array(); $_[] = 'From: ' . Shopp::email_from(shopp_setting('merchant_email'), shopp_setting('business_name')); $_[] = 'To: ' . $RecoveryCustomer->email; $_[] = 'Subject: ' . $subject; $_[] = 'Content-type: text/html'; $_[] = ''; $_[] = '<p>' . Shopp::__('Your new password for %s:', get_bloginfo('url')) . '</p>'; $_[] = ''; $_[] = '<ul>'; if (apply_filters('shopp_reset_password_wpuser', true) && !empty($user_data->user_login)) { $_[] = '<li>' . Shopp::__('Login: %s', $user_data->user_login) . '</li>'; } elseif (!empty($RecoveryCustomer->email)) { $_[] = '<li>' . Shopp::__('Login: %s', $RecoveryCustomer->email) . '</li>'; } $_[] = '<li>' . Shopp::__('Password: %s', $password) . '</li>'; $_[] = '</ul>'; $_[] = ''; $_[] = '<p>' . Shopp::__('Click here to login: %s', Shopp::url(false, 'account')) . '</p>'; $message = apply_filters('shopp_reset_password_message', $_); if (!Shopp::email(join("\n", $message))) { shopp_add_notice(Shopp::__('Your password was reset to: ' . $password)); } else { shopp_add_notice(Shopp::__('Your new password has been emailed to you for your records. Your password was reset to: ' . $password)); } unset($_GET['acct']); // Auto-login $RecoveryCustomer->login(); // Login the customer if (!empty($user_data)) { // Log the WordPress user in ShoppLogin::wpuser($user_data); } // Show notice after login in case of failures during login shopp_add_notice(Shopp::__('You are now logged into your account.')); if (apply_filters('shopp_reset_password_redirect', true)) { shopp_add_notice(Shopp::__('If you wish, please use the form below to change your password to one of your choosing.')); Shopp::redirect(add_query_arg('profile', '', Shopp::url(false, 'account'))); } }
/** * Sends an email message based on a specified template file * * Sends an e-mail message in the format of a specified e-mail * template file using variable substitution for variables appearing in * the template as a bracketed [variable] with data from the * provided data array or the super-global $_POST array * * @author Jonathan Davis * @since 1.0 * * @param string $template Email template file path (or a string containing the template itself) * @param array $data The data to populate the template with * @return boolean True on success, false on failure **/ public static function email($template, array $data = array()) { $debug = defined('SHOPP_DEBUG_EMAIL') && SHOPP_DEBUG_EMAIL; $headers = array(); $to = $subject = $message = ''; $addrs = array('from', 'sender', 'reply-to', 'to', 'cc', 'bcc'); $protected = array_merge($addrs, array('subject')); if (false == strpos($template, "\n") && file_exists($template)) { $templatefile = $template; // Include to parse the PHP and Theme API tags ob_start(); ShoppStorefront::intemplate($templatefile); include $templatefile; ShoppStorefront::intemplate(''); $template = ob_get_clean(); if (empty($template)) { return shopp_add_error(Shopp::__('Could not open the email template because the file does not exist or is not readable.'), SHOPP_ADMIN_ERR, array('template' => $templatefile)); } } // Sanitize line endings $template = str_replace(array("\r\n", "\r"), "\n", $template); $lines = explode("\n", $template); // Collect headers while ($line = array_shift($lines)) { if (false === strpos($line, ':')) { continue; } // Skip invalid header lines list($header, $value) = explode(':', $line, 2); $header = strtolower($header); if (in_array($header, $protected)) { // Protect against header injection $value = str_replace(array("\n", "\r"), '', rawurldecode($value)); } if (in_array($header, array('to', 'subject'))) { $headers[$header] = trim($value); } else { $headers[$header] = $line; } } $message = join("\n", $lines); // If not already in place, setup default system email filters ShoppEmailDefaultFilters::init(); // Message filters first $message = apply_filters('shopp_email_message', $message, $headers); $headers = apply_filters('shopp_email_headers', $headers, $message); $to = $headers['to']; unset($headers['to']); $subject = $headers['subject']; unset($headers['subject']); $sent = wp_mail($to, $subject, $message, $headers); do_action('shopp_email_completed'); if ($debug) { shopp_debug("To: " . htmlspecialchars($to) . "\n"); shopp_debug("Subject: {$subject}\n\n"); shopp_debug("Headers:\n"); shopp_debug("\nMessage:\n{$message}\n"); } return $sent; }
/** * Detects if the maximum number of promotions have been applied * * @author Jonathan Davis * @since 1.3 * * @param ShoppOrderPromo $Promo A promotion object * @return boolean True if the max was reached, false otherwise **/ private function maxed(ShoppOrderPromo $Promo) { $promolimit = (int) shopp_setting('promo_limit'); // If promotion limit has been reached and the promo has // not already applied as a cart discount, cancel the loop if ($promolimit && $this->count() + 1 > $promolimit && !$this->exists($Promo->id)) { if (!empty($this->request)) { shopp_add_error(Shopp::__('No additional codes can be applied.')); } return true; } return false; }
public static function data($result) { if (!isset($_POST['data'])) { return $result; } $fields = $_POST['data']; if (apply_filters('shopp_clickwrap_required', isset($fields['clickwrap']) && 'agreed' !== $fields['clickwrap'])) { return shopp_add_error(Shopp::__('You must agree to the terms of sale.')); } return $result; }
/** * Communicates with the Shopp update service server * * @author Jonathan Davis * @since 1.1 * * @param array $request (optional) A list of request variables to send * @param array $data (optional) A list of data variables to send * @param array $options (optional) * @return string The response from the server **/ public static function callhome($request = array(), $data = array(), $options = array()) { $query = http_build_query(array_merge(array('ver' => '1.2'), $request), '', '&'); $data = http_build_query($data, '', '&'); $defaults = array('method' => 'POST', 'timeout' => 20, 'redirection' => 7, 'httpversion' => '1.0', 'user-agent' => SHOPP_GATEWAY_USERAGENT . '; ' . get_bloginfo('url'), 'blocking' => true, 'headers' => array(), 'cookies' => array(), 'body' => $data, 'compress' => false, 'decompress' => true, 'sslverify' => false); $params = array_merge($defaults, $options); $URL = ShoppSupport::HOMEPAGE . "?{$query}"; // error_log('CALLHOME REQUEST ------------------'); // error_log($URL); // error_log(json_encode($params)); $connection = new WP_Http(); $result = $connection->request($URL, $params); // error_log(json_encode($result)); // error_log('-------------- END CALLHOME REQUEST'); extract($result); if (isset($response['code']) && 200 != $response['code']) { // Fail, fallback to http instead $URL = str_replace('https://', 'http://', $URL); $connection = new WP_Http(); $result = $connection->request($URL, $params); extract($result); } if (is_wp_error($result)) { $errors = array(); foreach ($result->errors as $errname => $msgs) { $errors[] = join(' ', $msgs); } $errors = join(' ', $errors); shopp_add_error("Shopp: " . Lookup::errors('callhome', 'fail') . " {$errors} " . Lookup::errors('contact', 'admin') . " (WP_HTTP)", SHOPP_ADMIN_ERR); return false; } elseif (empty($result) || !isset($result['response'])) { shopp_add_error("Shopp: " . Lookup::errors('callhome', 'noresponse'), SHOPP_ADMIN_ERR); return false; } else { extract($result); } if (isset($response['code']) && 200 != $response['code']) { $error = Lookup::errors('callhome', 'http-' . $response['code']); if (empty($error)) { $error = Lookup::errors('callhome', 'http-unkonwn'); } shopp_add_error("Shopp: {$error}", 'callhome_comm_err', SHOPP_ADMIN_ERR); return $body; } return $body; }
public function process() { $action = $this->form('checkout'); if ('process' != $action) { return; } $Payments = ShoppOrder()->Payments; $Cart = ShoppOrder()->Cart; $forcedconfirm = 'always' == shopp_setting('order_confirmation'); $wasfree = $Cart->orderisfree(); // Get current free status $estimated = $Cart->total(); // Get current total $Cart->totals(); // Retotal after checkout to capture order total changes // We have to avoid truthiness, hence the strange logic expression if (true !== apply_filters('shopp_validate_checkout', true)) { return; } else { $this->customer(); } // Catch changes from validation // Catch originally free orders that get extra (shipping) costs added to them if ($wasfree && $Payments->count() > 1 && !$Cart->orderisfree() && empty($Payments->selected()->cards)) { shopp_add_error(Shopp::__('The order amount changed and requires that you select a payment method.')); Shopp::redirect(Shopp::url(false, 'checkout', ShoppOrder()->security())); } // Do not use shopp_checkout_processed for payment gateway redirect actions // Free order processing doesn't take over until the order is submitted for processing in `shopp_process_order` do_action('shopp_checkout_processed'); // If the cart's total changes at all, confirm the order if (apply_filters('shopp_order_confirm_needed', $estimated != $Cart->total() || $forcedconfirm)) { Shopp::redirect(Shopp::url(false, 'confirm', ShoppOrder()->security())); return; } do_action('shopp_process_order'); }
/** * Handle Shopp login processing * * @author Jonathan Davis * @since 1.0 * * @return void **/ public function process() { if (ShoppRegistration::submitted()) { new ShoppRegistration(); add_action('shopp_customer_registered', array($this, 'login')); } if (isset($_REQUEST['acct']) && 'logout' == $_REQUEST['acct'] || isset($_REQUEST['logout'])) { // Set the last logged out action to save the session and redirect to remove the logout request add_action('shopp_logged_out', array($this, 'redirect'), 100); // Trigger the logout do_action('shopp_logout'); } if ('wordpress' == shopp_setting('account_system')) { // See if the wordpress user is already logged in $user = wp_get_current_user(); // Wordpress user logged in, but Shopp customer isn't if (!empty($user->ID) && !$this->Customer->loggedin()) { if ($Account = new ShoppCustomer($user->ID, 'wpuser')) { $this->login($Account); $this->Customer->wpuser = $user->ID; return; } } } if (!self::submitted()) { return false; } // Prevent checkout form from processing remove_all_actions('shopp_process_checkout'); if (!isset($_POST['account-login']) || empty($_POST['account-login'])) { return shopp_add_error(__('You must provide a valid login name or email address to proceed.', 'Shopp'), SHOPP_AUTH_ERR); } // Add a login redirect as the very last action if a redirect parameter is provided in the request; Props @alansherwood if (isset($_REQUEST['redirect'])) { add_action('shopp_authed', array($this, 'redirect'), 100); } $mode = 'loginname'; if (false !== strpos($_POST['account-login'], '@')) { $mode = 'email'; } $this->auth($_POST['account-login'], $_POST['password-login'], $mode); }
/** * Builds a select query from an array of query fragments * * @author Jonathan Davis * @since 1.2 * * @param array $options The SQL fragments * @return string The complete SELECT SQL statement **/ public static function select($options = array()) { $defaults = array('columns' => '*', 'useindex' => '', 'joins' => array(), 'table' => '', 'where' => array(), 'groupby' => false, 'having' => array(), 'limit' => false, 'orderby' => false); $options = array_merge($defaults, $options); extract($options); if (empty($table)) { return shopp_add_error('No table specified for SELECT query.', SHOPP_DB_ERR); } $useindex = empty($useindex) ? '' : "FORCE INDEX({$useindex})"; $joins = empty($joins) ? '' : "\n\t\t" . join("\n\t\t", $joins); $where = empty($where) ? '' : "\n\tWHERE " . join(' AND ', $where); $groupby = empty($groupby) ? '' : "GROUP BY {$groupby}"; $having = empty($having) ? '' : "HAVING " . join(" AND ", $having); $orderby = empty($orderby) ? '' : "\n\tORDER BY {$orderby}"; $limit = empty($limit) ? '' : "\n\tLIMIT {$limit}"; return "SELECT {$columns}\n\tFROM {$table} {$useindex} {$joins} {$where} {$groupby} {$having} {$orderby} {$limit}"; }
/** * 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 email($addressee, $address, $subject, array $templates = array()) { global $is_IIS; shopp_debug("ShoppPurchase::email(): {$addressee},{$address},{$subject}," . _object_r($templates)); // Build the e-mail message data $email['from'] = Shopp::email_from(shopp_setting('merchant_email'), shopp_setting('business_name')); if ($is_IIS) { $email['to'] = Shopp::email_to($address); } else { $email['to'] = Shopp::email_to($address, $addressee); } $email['subject'] = $subject; $email['receipt'] = $this->receipt(); $email['url'] = get_bloginfo('url'); $email['sitename'] = get_bloginfo('name'); $email['orderid'] = $this->id; $email = apply_filters('shopp_email_receipt_data', $email); $email = apply_filters('shopp_purchase_email_message', $email); $this->message = array_merge($this->message, $email); // Load and process the template file $defaults = array('email.php', 'order.php', 'order.html'); $emails = array_merge((array) $templates, $defaults); $template = Shopp::locate_template($emails); if (!file_exists($template)) { shopp_add_error(Shopp::__('A purchase notification could not be sent because the template for it does not exist.'), SHOPP_ADMIN_ERR); return false; } // Send the email if (Shopp::email($template, $this->message)) { shopp_debug('A purchase notification was sent to: ' . $this->message['to']); return true; } shopp_debug('A purchase notification FAILED to be sent to: ' . $this->message['to']); return false; }
/** * Validate order data before transaction processing * * @author Jonathan Davis * @since 1.1 * * @return boolean Validity of the order **/ public function isvalid($report = true) { $Customer = $this->Customer; $Shipping = $this->Shipping; $Shiprates = $this->Shiprates; $Payments = $this->Payments; $Cart = $this->Cart; $valid = true; $errlevel = $report ? SHOPP_TRXN_ERR : SHOPP_DEBUG_ERR; shopp_debug('Validating order data for processing'); if (0 == $Cart->count()) { $valid = apply_filters('shopp_ordering_empty_cart', false); shopp_add_error(__('There are no items in the cart.', 'Shopp'), $errlevel); } $stock = true; foreach ($Cart as $item) { if (!$item->instock()) { $valid = apply_filters('shopp_ordering_items_outofstock', false); shopp_add_error(sprintf(__('%s does not have sufficient stock to process order.', 'Shopp'), $item->name . (empty($item->option->label) ? '' : '(' . $item->option->label . ')')), $errlevel); $stock = false; } } $valid_customer = true; if (!$Customer) { $valid_customer = apply_filters('shopp_ordering_empty_customer', false); } // No Customer // Always require name and email if (empty($Customer->firstname)) { $valid_customer = apply_filters('shopp_ordering_empty_firstname', false); } if (empty($Customer->lastname)) { $valid_customer = apply_filters('shopp_ordering_empty_lastname', false); } if (empty($Customer->email)) { $valid_customer = apply_filters('shopp_ordering_empty_email', false); } if (!$valid_customer) { $valid = false; shopp_add_error(__('There is not enough customer information to process the order.', 'Shopp'), $errlevel); } // Check for shipped items but no Shipping information $valid_shipping = true; if ($Cart->shipped() && shopp_setting_enabled('shipping')) { if (empty($Shipping->address)) { $valid_shipping = apply_filters('shopp_ordering_empty_shipping_address', false); } if (empty($Shipping->country)) { $valid_shipping = apply_filters('shopp_ordering_empty_shipping_country', false); } if (empty($Shipping->postcode)) { $valid_shipping = apply_filters('shopp_ordering_empty_shipping_postcode', false); } if ($Shiprates->count() == 0 && !$Shiprates->free()) { $valid = apply_filters('shopp_ordering_no_shipping_costs', false); $message = __('The order cannot be processed. No shipping is available to the address you provided. Please return to %scheckout%s and try again.', 'Shopp'); if ($Shiprates->realtime()) { $message = __('The order cannot be processed. The shipping rate service did not provide rates because of a problem and no other shipping is available to the address you provided. Please return to %scheckout%s and try again or contact the store administrator.', 'Shopp'); } if (!$valid) { shopp_add_error(sprintf($message, '<a href="' . Shopp::url(false, 'checkout', $this->security()) . '">', '</a>'), $errlevel); } } } if (!$valid_shipping) { $valid = false; shopp_add_error(__('The shipping address information is incomplete. The order cannot be processed.', 'Shopp'), $errlevel); } // Alert when no gateway is configured (and the order is not free) if ($Payments->count() == 0 && $Cart->total() > 0) { $valid = false; shopp_add_error(Lookup::errors('gateway', 'nogateways'), $errlevel); } return $valid; }
/** * Provides a markup widget to lookup an order by order ID and customer email address * * @api `shopp('customer.order-lookup')` * @since 1.0 * * @param string $result The output * @param array $options The options * @param ShoppCustomer $O The working object * @return string The widget markup **/ public static function order_lookup($result, $options, $O) { if (!empty($_POST['vieworder']) && !empty($_POST['purchaseid'])) { ShoppPurchase(new ShoppPurchase((int) $_POST['purchaseid'])); if (ShoppPurchase()->exists() && ShoppPurchase()->email == $_POST['email']) { ShoppPurchase()->load_purchased(); ob_start(); locate_shopp_template(array('receipt.php'), true); $content = ob_get_clean(); return apply_filters('shopp_order_lookup', $content); } else { shopp_add_error(Shopp::__('No order could be found with that information.'), SHOPP_AUTH_ERR); } } ob_start(); include SHOPP_ADMIN_PATH . "/orders/account.php"; $content = ob_get_clean(); return apply_filters('shopp_order_lookup', $content); }
/** * Processes payment method selection changes by the shopper * * @author Jonathan Davis * @since 1.3 * * @return void **/ public function request() { if (!isset($_POST['paymethod'])) { return; } if ('freeorder' == $_POST['paymethod']) { return; } // Ah, ah, ah! Shoppers can't just select free order processing $selected = $this->selected($_POST['paymethod']); if (!$this->modules($selected->processor)) { shopp_add_error(__('The payment method you selected is no longer available. Please choose another.', 'Shopp')); } if ($selected) { $this->userset = true; } unset($_POST['paymethod']); // Prevent unnecessary reprocessing on subsequent calls }