Пример #1
0
 public function calculate(&$options, $Order)
 {
     foreach ($this->methods as $slug => $method) {
         $tiers = isset($method['table']) ? $this->tablerate($method['table']) : false;
         if (false === $tiers) {
             continue;
         }
         // Skip methods that don't match at all
         $amount = 0;
         $matched = false;
         $tiers = array_reverse($tiers);
         foreach ($tiers as $tier) {
             extract($tier);
             $amount = Shopp::floatval($rate);
             // Capture the rate amount
             if ($this->weight >= $threshold) {
                 $matched = true;
                 break;
             }
         }
         if (!$matched) {
             return $options;
         }
         $rate = array('slug' => $slug, 'name' => $method['label'], 'amount' => $amount, 'delivery' => $this->delivery($method), 'items' => false);
         $options[$slug] = new ShippingOption($rate);
     }
     return $options;
 }
Пример #2
0
 public function screen()
 {
     $Shopp = Shopp::object();
     if (!current_user_can('shopp_settings_checkout')) {
         wp_die(__('You do not have sufficient permissions to access this page.'));
     }
     $purchasetable = ShoppDatabaseObject::tablename(ShoppPurchase::$table);
     $next = sDB::query("SELECT IF ((MAX(id)) > 0,(MAX(id)+1),1) AS id FROM {$purchasetable} LIMIT 1");
     $next_setting = shopp_setting('next_order_id');
     if ($next->id > $next_setting) {
         $next_setting = $next->id;
     }
     $term_recount = false;
     if (!empty($_POST['save'])) {
         check_admin_referer('shopp-setup-management');
         $next_order_id = $_POST['settings']['next_order_id'] = intval($_POST['settings']['next_order_id']);
         if ($next_order_id >= $next->id) {
             if (sDB::query("ALTER TABLE {$purchasetable} AUTO_INCREMENT=" . sDB::escape($next_order_id))) {
                 $next_setting = $next_order_id;
             }
         }
         $_POST['settings']['order_shipfee'] = Shopp::floatval($_POST['settings']['order_shipfee']);
         // Recount terms when this setting changes
         if (isset($_POST['settings']['inventory']) && $_POST['settings']['inventory'] != shopp_setting('inventory')) {
             $term_recount = true;
         }
         shopp_set_formsettings();
         $this->notice(Shopp::__('Management settings saved.'), 'notice', 20);
     }
     if ($term_recount) {
         $taxonomy = ProductCategory::$taxon;
         $terms = get_terms($taxonomy, array('hide_empty' => 0, 'fields' => 'ids'));
         if (!empty($terms)) {
             wp_update_term_count_now($terms, $taxonomy);
         }
     }
     $states = array(__('Map the label to an order state:', 'Shopp') => array_merge(array('' => ''), Lookup::txnstatus_labels()));
     $statusLabels = shopp_setting('order_status');
     $statesLabels = shopp_setting('order_states');
     $reasonLabels = shopp_setting('cancel_reasons');
     if (empty($reasonLabels)) {
         $reasonLabels = array(__('Not as described or expected', 'Shopp'), __('Wrong size', 'Shopp'), __('Found better prices elsewhere', 'Shopp'), __('Product is missing parts', 'Shopp'), __('Product is defective or damaaged', 'Shopp'), __('Took too long to deliver', 'Shopp'), __('Item out of stock', 'Shopp'), __('Customer request to cancel', 'Shopp'), __('Item discontinued', 'Shopp'), __('Other reason', 'Shopp'));
     }
     $promolimit = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '15', '20', '25');
     $lowstock = shopp_setting('lowstock_level');
     if (empty($lowstock)) {
         $lowstock = 0;
     }
     include $this->ui('management.php');
 }
Пример #3
0
 /**
  * Iterates loaded products in buffered batches and generates a feed-friendly item record
  *
  * NOTE: To modify the output of the RSS generator, use
  * the filter hooks provided in a separate plugin or
  * in the theme functions.php file.
  *
  * @author Jonathan Davis
  * @since 1.0
  * @version 1.1
  *
  * @return string A feed item record
  **/
 public function feed()
 {
     $paged = 100;
     // Buffer 100 products at a time.
     $loop = false;
     $product = ShoppProduct();
     if ($product) {
         $loop = shopp($this, 'products');
         if (!$loop) {
             $product = false;
         } else {
             $product = ShoppProduct();
         }
     }
     if (!($product || $loop)) {
         if (!$this->products) {
             $page = 1;
         } else {
             $page = $this->page + 1;
         }
         if ($this->pages > 0 && $page > $this->pages) {
             return false;
         }
         $this->load(array('load' => array('prices', 'specs', 'categories', 'coverimages'), 'paged' => $paged, 'page' => $page));
         $loop = shopp($this, 'products');
         if (!$loop) {
             return false;
         }
         // Loop ended, bail out
         $product = ShoppProduct();
         if (!$product) {
             return false;
         }
         // No products, bail
     }
     $item = array();
     $item['guid'] = shopp($product, 'get-id');
     $item['title'] = $product->name;
     $item['link'] = shopp($product, 'get-url');
     $item['pubDate'] = date('D, d M Y H:i O', $product->publish);
     // Item Description
     $item['description'] = '';
     $item['description'] .= '<table><tr>';
     $Image = current($product->images);
     if (!empty($Image)) {
         $item['description'] .= '<td><a href="' . $item['link'] . '" title="' . $product->name . '">';
         $item['description'] .= '<img src="' . esc_attr(add_query_string($Image->resizing(75, 75, 0), Shopp::url($Image->id, 'images'))) . '" alt="' . $product->name . '" width="75" height="75" />';
         $item['description'] .= '</a></td>';
     }
     $pricing = "";
     $priceindex = 'price';
     if (Shopp::str_true($product->sale)) {
         $priceindex = 'saleprice';
     }
     if ($product->min[$priceindex] != $product->max[$priceindex]) {
         $pricing .= Shopp::__('from') . ' ';
     }
     $pricing .= money($product->min[$priceindex]);
     $item['description'] .= "<td><p><big>{$pricing}</big></p>";
     $item['description'] .= apply_filters('shopp_rss_description', $product->summary, $product) . '</td></tr></table>';
     $item['description'] = '<![CDATA[' . $item['description'] . ']]>';
     // Google Base Namespace
     // http://www.google.com/support/merchants/bin/answer.py?hl=en&answer=188494
     // Below are Google Base specific attributes
     // You can use the shopp_rss_item filter hook to add new item attributes or change the existing attributes
     if ($Image) {
         $item['g:image_link'] = add_query_string($Image->resizing(400, 400, 0), Shopp::url($Image->id, 'images'));
     }
     $item['g:condition'] = 'new';
     $item['g:availability'] = shopp_setting_enabled('inventory') && $product->outofstock ? 'out of stock' : 'in stock';
     $price = Shopp::floatval(Shopp::str_true($product->sale) ? $product->min['saleprice'] : $product->min['price']);
     if (!empty($price)) {
         $item['g:price'] = $price;
         $item['g:price_type'] = "starting";
     }
     // Include product_type using Shopp category taxonomies
     foreach ($product->categories as $category) {
         $ancestry = array($category->name);
         $ancestors = get_ancestors($category->term_id, $category->taxonomy);
         foreach ((array) $ancestors as $ancestor) {
             $term = get_term($ancestor, $category->taxonomy);
             if ($term) {
                 array_unshift($ancestry, $term->name);
             }
         }
         $item['g:product_type[' . $category->term_id . ']'] = join(' > ', $ancestry);
     }
     $brand = shopp($product, 'get-spec', 'name=Brand');
     if (!empty($brand)) {
         $item['g:brand'] = $brand;
     }
     $gtins = array('UPC', 'EAN', 'JAN', 'ISBN-13', 'ISBN-10', 'ISBN');
     foreach ($gtins as $id) {
         $gtin = shopp($product, 'get-spec', 'name=' . $id);
         if (!empty($gtin)) {
             $item['g:gtin'] = $gtin;
             break;
         }
     }
     $mpn = shopp($product, 'get-spec', 'name=MPN');
     if (!empty($mpn)) {
         $item['g:mpn'] = $mpn;
     }
     // Check the product specs for matching Google Base information
     $g_props = array('MPN' => 'mpn', 'Color' => 'color', 'Material' => 'material', 'Pattern' => 'pattern', 'Size' => 'size', 'Gender' => 'gender', 'Age Group' => 'age_group', 'Google Product Category' => 'google_product_category');
     foreach (apply_filters('shopp_googlebase_spec_map', $g_props) as $name => $key) {
         $value = shopp($product, 'get-spec', 'name=' . $name);
         if (!empty($value)) {
             $item["g:{$key}"] = $value;
         }
     }
     return apply_filters('shopp_rss_item', $item, $product);
 }
Пример #4
0
 public function shiprates()
 {
     if (!current_user_can('shopp_settings_shipping')) {
         wp_die(__('You do not have sufficient permissions to access this page.'));
     }
     $Shopp = Shopp::object();
     $Shipping = $Shopp->Shipping;
     $Shipping->settings();
     // Load all installed shipping modules for settings UIs
     $methods = $Shopp->Shipping->methods;
     $edit = false;
     if (isset($_REQUEST['id'])) {
         $edit = (int) $_REQUEST['id'];
     }
     $active = shopp_setting('active_shipping');
     if (!$active) {
         $active = array();
     }
     if (!empty($_GET['delete'])) {
         check_admin_referer('shopp_delete_shiprate');
         $delete = $_GET['delete'];
         $index = false;
         if (strpos($delete, '-') !== false) {
             list($delete, $index) = explode('-', $delete);
         }
         if (array_key_exists($delete, $active)) {
             if (is_array($active[$delete])) {
                 if (array_key_exists($index, $active[$delete])) {
                     unset($active[$delete][$index]);
                     if (empty($active[$delete])) {
                         unset($active[$delete]);
                     }
                 }
             } else {
                 unset($active[$delete]);
             }
             $updated = __('Shipping method setting removed.', 'Shopp');
             shopp_set_setting('active_shipping', $active);
         }
     }
     if (isset($_POST['module'])) {
         check_admin_referer('shopp-settings-shiprate');
         $setting = false;
         $module = isset($_POST['module']) ? $_POST['module'] : false;
         $id = isset($_POST['id']) ? $_POST['id'] : false;
         if ($id == $module) {
             if (isset($_POST['settings'])) {
                 shopp_set_formsettings();
             }
             /** Save shipping service settings **/
             $active[$module] = true;
             shopp_set_setting('active_shipping', $active);
             $updated = __('Shipping settings saved.', 'Shopp');
             // Cancel editing if saving
             if (isset($_POST['save'])) {
                 unset($_REQUEST['id']);
             }
             $Errors = ShoppErrors();
             do_action('shopp_verify_shipping_services');
             if ($Errors->exist()) {
                 // Get all addon related errors
                 $failures = $Errors->level(SHOPP_ADDON_ERR);
                 if (!empty($failures)) {
                     $updated = __('Shipping settings saved but there were errors: ', 'Shopp');
                     foreach ($failures as $error) {
                         $updated .= '<p>' . $error->message(true, true) . '</p>';
                     }
                 }
             }
         } else {
             /** Save shipping calculator settings **/
             $setting = $_POST['id'];
             if (empty($setting)) {
                 // Determine next available setting ID
                 $index = 0;
                 if (is_array($active[$module])) {
                     $index = count($active[$module]);
                 }
                 $setting = "{$module}-{$index}";
             }
             // Cancel editing if saving
             if (isset($_POST['save'])) {
                 unset($_REQUEST['id']);
             }
             $setting_module = $setting;
             $id = 0;
             if (false !== strpos($setting, '-')) {
                 list($setting_module, $id) = explode('-', $setting);
             }
             // Prevent fishy stuff from happening
             if ($module != $setting_module) {
                 $module = false;
             }
             // Save shipping calculator settings
             $Shipper = $Shipping->get($module);
             if ($Shipper && isset($_POST[$module])) {
                 $Shipper->setting($id);
                 $_POST[$module]['label'] = stripslashes($_POST[$module]['label']);
                 // Sterilize $values
                 foreach ($_POST[$module]['table'] as $i => &$row) {
                     if (isset($row['rate'])) {
                         $row['rate'] = Shopp::floatval($row['rate']);
                     }
                     if (!isset($row['tiers'])) {
                         continue;
                     }
                     foreach ($row['tiers'] as &$tier) {
                         if (isset($tier['rate'])) {
                             $tier['rate'] = Shopp::floatval($tier['rate']);
                         }
                     }
                 }
                 // Delivery estimates: ensure max equals or exceeds min
                 ShippingFramework::sensibleestimates($_POST[$module]['mindelivery'], $_POST[$module]['maxdelivery']);
                 shopp_set_setting($Shipper->setting, $_POST[$module]);
                 if (!array_key_exists($module, $active)) {
                     $active[$module] = array();
                 }
                 $active[$module][(int) $id] = true;
                 shopp_set_setting('active_shipping', $active);
                 $this->notice(Shopp::__('Shipping settings saved.'));
             }
         }
     }
     $Shipping->settings();
     // Load all installed shipping modules for settings UIs
     $Shipping->ui();
     // Setup setting UIs
     $installed = array();
     $shiprates = array();
     // Registry for activated shipping rate modules
     $settings = array();
     // Registry of loaded settings for table-based shipping rates for JS
     foreach ($Shipping->active as $name => $module) {
         if (version_compare($Shipping->modules[$name]->since, '1.2') == -1) {
             continue;
         }
         // Skip 1.1 modules, they are incompatible
         $default_name = strtolower($name);
         $fullname = $module->methods();
         $installed[$name] = $fullname;
         if ($module->ui->tables) {
             $defaults[$default_name] = $module->ui->settings();
             $defaults[$default_name]['name'] = $fullname;
             $defaults[$default_name]['label'] = __('Shipping Method', 'Shopp');
         }
         if (array_key_exists($name, $active)) {
             $ModuleSetting = $active[$name];
         } else {
             continue;
         }
         // Not an activated shipping module, go to the next one
         // Setup shipping service shipping rate entries and settings
         if (!is_array($ModuleSetting)) {
             $shiprates[$name] = $name;
             continue;
         }
         // Setup shipping calcualtor shipping rate entries and settings
         foreach ($ModuleSetting as $id => $m) {
             $setting = "{$name}-{$id}";
             $shiprates[$setting] = $name;
             $settings[$setting] = shopp_setting($setting);
             $settings[$setting]['id'] = $setting;
             $settings[$setting] = array_merge($defaults[$default_name], $settings[$setting]);
             if (isset($settings[$setting]['table'])) {
                 usort($settings[$setting]['table'], array('ShippingFramework', '_sorttier'));
                 foreach ($settings[$setting]['table'] as &$r) {
                     if (isset($r['tiers'])) {
                         usort($r['tiers'], array('ShippingFramework', '_sorttier'));
                     }
                 }
             }
         }
     }
     if (isset($_REQUEST['id'])) {
         $edit = $_REQUEST['id'];
         $id = false;
         if (strpos($edit, '-') !== false) {
             list($module, $id) = explode('-', $edit);
         } else {
             $module = $edit;
         }
         if (isset($Shipping->active[$module])) {
             $Shipper = $Shipping->get($module);
             if (!$Shipper->singular) {
                 $Shipper->setting($id);
                 $Shipper->initui($Shipping->modules[$module]->name);
                 // Re-init setting UI with loaded settings
             }
             $editor = $Shipper->ui();
         }
     }
     asort($installed);
     $countrydata = Lookup::countries();
     $countries = $regionmap = $postcodes = array();
     $postcodedata = Lookup::postcodes();
     foreach ($countrydata as $code => $country) {
         $countries[$code] = $country['name'];
         if (!isset($regionmap[$country['region']])) {
             $regionmap[$country['region']] = array();
         }
         $regionmap[$country['region']][] = $code;
         if (isset($postcodedata[$code])) {
             if (!isset($postcodes[$code])) {
                 $postcodes[$code] = array();
             }
             $postcodes[$code] = true;
         }
     }
     unset($countrydata);
     unset($postcodedata);
     $lookup = array('regions' => array_merge(array('*' => __('Anywhere', 'Shopp')), Lookup::regions()), 'regionmap' => $regionmap, 'countries' => $countries, 'areas' => Lookup::country_areas(), 'zones' => Lookup::country_zones(), 'postcodes' => $postcodes);
     $ShippingTemplates = new TemplateShippingUI();
     add_action('shopp_shipping_module_settings', array($Shipping, 'templates'));
     include $this->ui('shiprates.php');
 }
Пример #5
0
 /**
  * Formats a numeric amount to a percentage using a specified format
  *
  * Uses a format configuration array to specify how the amount needs to be
  * formatted.  When no format is specified, the currency format setting
  * is used only paying attention to the decimal precision, decimal symbol and
  * thousands separator.  If no setting is available, a default configuration
  * is used (precision: 1) (decimal separator: .) (thousands separator: ,)
  *
  * @author Jonathan Davis
  * @since 1.0
  *
  * @param float $amount The amount to format
  * @param array $format A specific format for the number
  * @return string The formatted percentage
  **/
 public static function percentage($amount, $format = array())
 {
     $format = Shopp::currency_format($format);
     extract($format, EXTR_SKIP);
     $float = Shopp::floatval($amount, true, $format);
     $percent = Shopp::numeric_format($float, $precision, $decimals, $thousands, $grouping);
     if (false !== strpos($percent, $decimals)) {
         // Only remove trailing 0's after the decimal
         $percent = rtrim($percent, '0');
         $percent = rtrim($percent, $decimals);
     }
     return "{$percent}%";
 }
Пример #6
0
 /**
  * match_rule ()
  * Determines if the value of a given subject matches the rule based
  * on the specified operation */
 static function match_rule($subject, $op, $value, $property = false)
 {
     switch ($op) {
         // String or Numeric operations
         case "Is equal to":
             if ($property && ShoppPromo::$values[$property] == 'price') {
                 return Shopp::floatval($subject) != 0 && Shopp::floatval($value) != 0 && Shopp::floatval($subject) == Shopp::floatval($value);
             } else {
                 if (is_array($subject)) {
                     return in_array($value, $subject);
                 }
                 return "{$subject}" === "{$value}";
             }
             break;
         case "Is not equal to":
             if (is_array($subject)) {
                 return !in_array($value, $subject);
             }
             return "{$subject}" !== "{$value}" || Shopp::floatval($subject) != 0 && Shopp::floatval($value) != 0 && Shopp::floatval($subject) != Shopp::floatval($value);
             break;
             // String operations
         // String operations
         case "Contains":
             if (is_array($subject)) {
                 foreach ($subject as $s) {
                     if (stripos($s, $value) !== false) {
                         return true;
                     }
                 }
                 return false;
             }
             return stripos($subject, $value) !== false;
             break;
         case "Does not contain":
             if (is_array($subject)) {
                 foreach ($subject as $s) {
                     if (stripos($s, $value) !== false) {
                         return false;
                     }
                 }
                 return true;
             }
             return stripos($subject, $value) === false;
             break;
         case "Begins with":
             if (is_array($subject)) {
                 foreach ($subject as $s) {
                     if (stripos($s, $value) === 0) {
                         return true;
                     }
                 }
                 return false;
             }
             return stripos($subject, $value) === 0;
             break;
         case "Ends with":
             if (is_array($subject)) {
                 foreach ($subject as $s) {
                     if (stripos($s, $value) === strlen($s) - strlen($value)) {
                         return true;
                     }
                 }
                 return false;
             }
             return stripos($subject, $value) === strlen($subject) - strlen($value);
             break;
             // Numeric operations
         // Numeric operations
         case "Is greater than":
             return Shopp::floatval($subject, false) > Shopp::floatval($value, false);
             break;
         case "Is greater than or equal to":
             return Shopp::floatval($subject, false) >= Shopp::floatval($value, false);
             break;
         case "Is less than":
             return Shopp::floatval($subject, false) < Shopp::floatval($value, false);
             break;
         case "Is less than or equal to":
             return Shopp::floatval($subject, false) <= Shopp::floatval($value, false);
             break;
     }
     return false;
 }
Пример #7
0
 public function column_rate($Item)
 {
     extract($Item);
     $rate = Shopp::percentage(Shopp::floatval($rate), array('precision' => 4));
     $location = $this->countries[$country];
     $label = "{$rate} &mdash; {$location}";
     $edit_link = wp_nonce_url(add_query_arg('id', $id), 'shopp_edit_taxrate');
     $delete_link = wp_nonce_url(add_query_arg('delete', $id), 'shopp_delete_taxrate');
     echo '<a class="row-title edit" href="' . esc_url($edit_link) . '" title="' . Shopp::__('Edit') . ' &quot;' . esc_attr($label) . '&quot;">' . esc_html($label) . '</a>';
     echo $this->row_actions(array('edit' => '<a class="edit" href="' . $edit_link . '">' . __('Edit') . '</a>', 'delete' => '<a class="delete" href="' . $delete_link . '">' . __('Delete') . '</a>'));
 }
Пример #8
0
 /**
  * Interface processor for the order manager
  *
  * @author Jonathan Davis
  * @return void
  **/
 public function manager()
 {
     global $Shopp, $Notes;
     global $is_IIS;
     if (!current_user_can('shopp_orders')) {
         wp_die(__('You do not have sufficient permissions to access this page.', 'Shopp'));
     }
     $Purchase = ShoppPurchase();
     $Purchase->Customer = new ShoppCustomer($Purchase->customer);
     $Gateway = $Purchase->gateway();
     if (!empty($_POST["send-note"])) {
         $user = wp_get_current_user();
         shopp_add_order_event($Purchase->id, 'note', array('note' => stripslashes($_POST['note']), 'user' => $user->ID));
         $Purchase->load_events();
     }
     // Handle Order note processing
     if (!empty($_POST['note'])) {
         $this->addnote($Purchase->id, stripslashes($_POST['note']), !empty($_POST['send-note']));
     }
     if (!empty($_POST['delete-note'])) {
         $noteid = key($_POST['delete-note']);
         $Note = new ShoppMetaObject(array('id' => $noteid, 'type' => 'order_note'));
         $Note->delete();
     }
     if (!empty($_POST['edit-note'])) {
         $noteid = key($_POST['note-editor']);
         $Note = new ShoppMetaObject(array('id' => $noteid, 'type' => 'order_note'));
         $Note->value->message = stripslashes($_POST['note-editor'][$noteid]);
         $Note->save();
     }
     $Notes = new ObjectMeta($Purchase->id, 'purchase', 'order_note');
     if (isset($_POST['submit-shipments']) && isset($_POST['shipment']) && !empty($_POST['shipment'])) {
         $shipments = $_POST['shipment'];
         foreach ((array) $shipments as $shipment) {
             shopp_add_order_event($Purchase->id, 'shipped', array('tracking' => $shipment['tracking'], 'carrier' => $shipment['carrier']));
         }
         $updated = __('Shipping notice sent.', 'Shopp');
         // Save shipping carrier default preference for the user
         $userid = get_current_user_id();
         $setting = 'shopp_shipping_carrier';
         if (!get_user_meta($userid, $setting, true)) {
             add_user_meta($userid, $setting, $shipment['carrier']);
         } else {
             update_user_meta($userid, $setting, $shipment['carrier']);
         }
         unset($_POST['ship-notice']);
         $Purchase->load_events();
     }
     if (isset($_POST['order-action']) && 'refund' == $_POST['order-action']) {
         if (!current_user_can('shopp_refund')) {
             wp_die(__('You do not have sufficient permissions to carry out this action.', 'Shopp'));
         }
         $user = wp_get_current_user();
         $reason = (int) $_POST['reason'];
         $amount = Shopp::floatval($_POST['amount']);
         $Purchase->load_events();
         if (!empty($_POST['message'])) {
             $message = $_POST['message'];
             $Purchase->message['note'] = $message;
         }
         if ($amount <= $Purchase->captured - $Purchase->refunded) {
             if (!Shopp::str_true($_POST['send'])) {
                 // Force the order status
                 shopp_add_order_event($Purchase->id, 'notice', array('user' => $user->ID, 'kind' => 'refunded', 'notice' => __('Marked Refunded', 'Shopp')));
                 shopp_add_order_event($Purchase->id, 'refunded', array('txnid' => $Purchase->txnid, 'gateway' => $Gateway->module, 'amount' => $amount));
                 shopp_add_order_event($Purchase->id, 'voided', array('txnorigin' => $Purchase->txnid, 'txnid' => time(), 'gateway' => $Gateway->module));
             } else {
                 shopp_add_order_event($Purchase->id, 'refund', array('txnid' => $Purchase->txnid, 'gateway' => $Gateway->module, 'amount' => $amount, 'reason' => $reason, 'user' => $user->ID));
             }
             if (!empty($_POST['message'])) {
                 $this->addnote($Purchase->id, $_POST['message']);
             }
             $Purchase->load_events();
         } else {
             $this->notice(Shopp::__('Refund failed. Cannot refund more than the current balance.'), 'error');
         }
     }
     if (isset($_POST['order-action']) && 'cancel' == $_POST['order-action']) {
         if (!current_user_can('shopp_void')) {
             wp_die(__('You do not have sufficient permissions to carry out this action.', 'Shopp'));
         }
         // unset($_POST['refund-order']);
         $user = wp_get_current_user();
         $reason = (int) $_POST['reason'];
         $message = '';
         if (!empty($_POST['message'])) {
             $message = $_POST['message'];
             $Purchase->message['note'] = $message;
         } else {
             $message = 0;
         }
         if (!Shopp::str_true($_POST['send'])) {
             // Force the order status
             shopp_add_order_event($Purchase->id, 'notice', array('user' => $user->ID, 'kind' => 'cancelled', 'notice' => __('Marked Cancelled', 'Shopp')));
             shopp_add_order_event($Purchase->id, 'voided', array('txnorigin' => $Purchase->txnid, 'txnid' => time(), 'gateway' => $Gateway->module));
         } else {
             shopp_add_order_event($Purchase->id, 'void', array('txnid' => $Purchase->txnid, 'gateway' => $Gateway->module, 'reason' => $reason, 'user' => $user->ID, 'note' => $message));
         }
         if (!empty($_POST['message'])) {
             $this->addnote($Purchase->id, $_POST['message']);
         }
         $Purchase->load_events();
     }
     if (isset($_POST['billing']) && is_array($_POST['billing'])) {
         $Purchase->updates($_POST['billing']);
         $Purchase->save();
     }
     if (isset($_POST['shipping']) && is_array($_POST['shipping'])) {
         $shipping = array();
         foreach ($_POST['shipping'] as $name => $value) {
             $shipping["ship{$name}"] = $value;
         }
         $Purchase->updates($shipping);
         $Purchase->shipname = $shipping['shipfirstname'] . ' ' . $shipping['shiplastname'];
         $Purchase->save();
     }
     if (isset($_POST['order-action']) && 'update-customer' == $_POST['order-action'] && !empty($_POST['customer'])) {
         $Purchase->updates($_POST['customer']);
         $Purchase->save();
     }
     if (isset($_POST['cancel-edit-customer'])) {
         unset($_POST['order-action'], $_POST['edit-customer'], $_POST['select-customer']);
     }
     if (isset($_POST['order-action']) && 'new-customer' == $_POST['order-action'] && !empty($_POST['customer']) && !isset($_POST['cancel-edit-customer'])) {
         $Customer = new ShoppCustomer();
         $Customer->updates($_POST['customer']);
         $Customer->password = wp_generate_password(12, true);
         if ('wordpress' == shopp_setting('account_system')) {
             $Customer->create_wpuser();
         } else {
             unset($_POST['loginname']);
         }
         $Customer->save();
         if ((int) $Customer->id > 0) {
             $Purchase->copydata($Customer);
             $Purchase->save();
         } else {
             $this->notice(__('An unknown error occured. The customer could not be created.', 'Shopp'), 'error');
         }
     }
     if (isset($_GET['order-action']) && 'change-customer' == $_GET['order-action'] && !empty($_GET['customerid'])) {
         $Customer = new ShoppCustomer((int) $_GET['customerid']);
         if ((int) $Customer->id > 0) {
             $Purchase->copydata($Customer);
             $Purchase->customer = $Customer->id;
             $Purchase->save();
         } else {
             $this->notice(__('The selected customer was not found.', 'Shopp'), 'error');
         }
     }
     if (isset($_POST['save-item']) && !empty($_POST['lineid'])) {
         // Create a cart representation of the order to recalculate order totals
         $Cart = new ShoppCart();
         foreach ($Purchase->purchased as $OrderItem) {
             $CartItem = new Item($OrderItem);
             $Cart->contents[$OrderItem->id] = $CartItem;
         }
         $purchasedid = (int) $_POST['lineid'];
         $Purchased = $Purchase->purchased[$purchasedid];
         if ($Purchased->id) {
             $override_total = Shopp::floatval($_POST['total']) != $Purchased->total;
             // Override total
             $Item = $Cart->contents[$purchasedid];
             $Item->quantity($_POST['quantity']);
             $Item->unitprice = Shopp::floatval($_POST['unitprice']);
             $Item->retotal();
             $Purchased->quantity = $Item->quantity;
             $Purchased->unitprice = $Item->unitprice;
             $Purchased->unittax = $Item->unittax;
             $Purchased->total = $Item->total;
             if ($override_total) {
                 $Purchased->total = Shopp::floatval($_POST['total']);
             }
             $Purchased->save();
         }
         $Cart->retotal = true;
         $Cart->totals();
         $Purchase->copydata($Cart->Totals);
         $Purchase->save();
     }
     if (isset($_POST['charge']) && $Gateway && $Gateway->captures) {
         if (!current_user_can('shopp_capture')) {
             wp_die(__('You do not have sufficient permissions to carry out this action.', 'Shopp'));
         }
         $user = wp_get_current_user();
         shopp_add_order_event($Purchase->id, 'capture', array('txnid' => $Purchase->txnid, 'gateway' => $Purchase->gateway, 'amount' => $Purchase->capturable(), 'user' => $user->ID));
         $Purchase->load_events();
     }
     $base = shopp_setting('base_operations');
     $targets = shopp_setting('target_markets');
     $countries = array('' => '&nbsp;');
     $countrydata = Lookup::countries();
     foreach ($countrydata as $iso => $c) {
         if ($base['country'] == $iso) {
             $base_region = $c['region'];
         }
         $countries[$iso] = $c['name'];
     }
     $Purchase->_countries = $countries;
     $regions = Lookup::country_zones();
     $Purchase->_billing_states = array_merge(array('' => '&nbsp;'), (array) $regions[$Purchase->country]);
     $Purchase->_shipping_states = array_merge(array('' => '&nbsp;'), (array) $regions[$Purchase->shipcountry]);
     // Setup shipping carriers menu and JS data
     $carriers_menu = $carriers_json = array();
     $shipping_carriers = (array) shopp_setting('shipping_carriers');
     // The store-preferred shipping carriers
     $shipcarriers = Lookup::shipcarriers();
     // The full list of available shipping carriers
     $notrack = Shopp::__('No Tracking');
     // No tracking label
     $default = get_user_meta(get_current_user_id(), 'shopp_shipping_carrier', true);
     if (isset($shipcarriers[$default])) {
         $carriers_menu[$default] = $shipcarriers[$default]->name;
         $carriers_json[$default] = array($shipcarriers[$default]->name, $shipcarriers[$default]->trackpattern);
     } else {
         $carriers_menu['NOTRACKING'] = $notrack;
         $carriers_json['NOTRACKING'] = array($notrack, false);
     }
     $serviceareas = array('*', $base['country']);
     foreach ($shipcarriers as $code => $carrier) {
         if ($code == $default) {
             continue;
         }
         if (!empty($shipping_carriers) && !in_array($code, $shipping_carriers)) {
             continue;
         }
         if (!in_array($carrier->areas, $serviceareas)) {
             continue;
         }
         $carriers_menu[$code] = $carrier->name;
         $carriers_json[$code] = array($carrier->name, $carrier->trackpattern);
     }
     if (isset($shipcarriers[$default])) {
         $carriers_menu['NOTRACKING'] = $notrack;
         $carriers_json['NOTRACKING'] = array($notrack, false);
     }
     if (empty($statusLabels)) {
         $statusLabels = array('');
     }
     include $this->ui('order.php');
 }
Пример #9
0
 /**
  * Matches subject and value using equal to
  *
  * @author Jonathan Davis
  * @since 1.3
  *
  * @param mixed $subject The subject data to compare
  * @param mixed $value The value to match against
  * @param string $type The data type matching (string or float)
  * @return boolean True for a match, false for no match
  **/
 private function isequalto($subject, $value, $type = 'string')
 {
     if ('float' == $type) {
         $subject = Shopp::floatval($subject);
         $value = Shopp::floatval($value);
         return $subject != 0 && $value != 0 && $subject == $value;
     }
     if (is_array($subject)) {
         return in_array($value, $subject);
     }
     return "{$subject}" === "{$value}";
 }
Пример #10
0
/**
 * shopp_product_variant_set_saleprice - set the sale price of a variant
 *
 * @api
 * @since 1.2
 *
 * @param int/Price $variant (required) The priceline id to set the sale price on, or the Price object to change.  If Price object is specified, the object will be returned, but not saved to the database.
 * @param bool $flag (optional default:false) true for on, false for off. Turns on or off the sale flag on the variant.  If false, price is ignored.
 * @param float $price the price to be set
 * @param string $context (optional default:variant) enforces the priceline is a 'product','variant', or 'addon'
 * @return bool/Price false on failure, true if Price saved, else the modified Price object.
 **/
function shopp_product_variant_set_saleprice($variant = false, $flag = false, $price = 0.0, $context = 'variant')
{
    $context = 'variant' == $context ? 'variation' : $context;
    $save = true;
    if (is_object($variant) && is_a($variant, 'ShoppPrice')) {
        $Price = $variant;
        $save = false;
    } else {
        if (false == $variant) {
            shopp_debug(__FUNCTION__ . " failed: Variant id required.");
            return false;
        }
        $Price = new ShoppPrice($variant);
        if (empty($Price->id) || $Price->context != $context) {
            shopp_debug(__FUNCTION__ . " failed: No such {$context} with id {$variant}.");
        }
    }
    $Price->sale = "off";
    if ($flag) {
        $Price->sale = "on";
        if (shopp_setting_enabled('tax_inclusive') && isset($Price->tax) && Shopp::str_true($Price->tax)) {
            $Product = new ShoppProduct($Price->product);
            $taxrate = shopp_taxrate(null, true, $Product);
            $price = Shopp::floatval($price / (1 + $taxrate));
        }
        $Price->saleprice = $price;
    }
    if ($save) {
        return $Price->save();
    }
    return $Price;
}
Пример #11
0
 /**
  * Handles saving updated category information from the category editor
  *
  * @author Jonathan Davis
  * @since 1.0
  * @return void
  **/
 public function save($Category)
 {
     $Shopp = Shopp::object();
     check_admin_referer('shopp-save-category');
     if (!current_user_can('shopp_categories')) {
         wp_die(__('You do not have sufficient permissions to access this page.'));
     }
     shopp_set_formsettings();
     // Save workflow setting
     if (empty($Category->meta)) {
         $Category->load_meta();
     }
     if (isset($_POST['content'])) {
         $_POST['description'] = $_POST['content'];
     }
     $Category->name = $_POST['name'];
     $Category->description = $_POST['description'];
     $Category->parent = $_POST['parent'];
     $Category->prices = array();
     // Variation price templates
     if (!empty($_POST['price']) && is_array($_POST['price'])) {
         foreach ($_POST['price'] as &$pricing) {
             $pricing['price'] = Shopp::floatval($pricing['price'], false);
             $pricing['saleprice'] = Shopp::floatval($pricing['saleprice'], false);
             $pricing['shipfee'] = Shopp::floatval($pricing['shipfee'], false);
             $pricing['dimensions'] = array_map(array('Shopp', 'floatval'), $pricing['dimensions']);
         }
     }
     $_POST['prices'] = isset($_POST['price']) ? $_POST['price'] : array();
     if (empty($_POST['specs'])) {
         $Category->specs = array();
     }
     /* @todo Move the rest of category meta inputs to [meta] inputs eventually */
     if (isset($_POST['meta']) && isset($_POST['meta']['options'])) {
         // Moves the meta options input to 'options' index for compatibility
         $_POST['options'] = $_POST['meta']['options'];
     }
     if (empty($_POST['meta']['options']) || count($_POST['meta']['options']['v']) == 1 && !isset($_POST['meta']['options']['v'][1]['options'])) {
         $_POST['options'] = $Category->options = array();
         $_POST['prices'] = $Category->prices = array();
     }
     $metaprops = array('spectemplate', 'facetedmenus', 'variations', 'pricerange', 'priceranges', 'specs', 'options', 'prices');
     $metadata = array_filter_keys($_POST, $metaprops);
     // Update existing entries
     $updates = array();
     foreach ($Category->meta as $id => $MetaObject) {
         $name = $MetaObject->name;
         if (isset($metadata[$name])) {
             $MetaObject->value = stripslashes_deep($metadata[$name]);
             $updates[] = $name;
         }
     }
     // Create any new missing meta entries
     $new = array_diff(array_keys($metadata), $updates);
     // Determine new entries from the exsting updates
     foreach ($new as $name) {
         if (!isset($metadata[$name])) {
             continue;
         }
         $Meta = new MetaObject();
         $Meta->name = $name;
         $Meta->value = stripslashes_deep($metadata[$name]);
         $Category->meta[] = $Meta;
     }
     $Category->save();
     if (!empty($_POST['deleteImages'])) {
         $deletes = array();
         if (strpos($_POST['deleteImages'], ",")) {
             $deletes = explode(',', $_POST['deleteImages']);
         } else {
             $deletes = array($_POST['deleteImages']);
         }
         $Category->delete_images($deletes);
     }
     if (!empty($_POST['images']) && is_array($_POST['images'])) {
         $Category->link_images($_POST['images']);
         $Category->save_imageorder($_POST['images']);
         if (!empty($_POST['imagedetails']) && is_array($_POST['imagedetails'])) {
             foreach ($_POST['imagedetails'] as $i => $data) {
                 $Image = new CategoryImage($data['id']);
                 $Image->title = $data['title'];
                 $Image->alt = $data['alt'];
                 $Image->save();
             }
         }
     }
     do_action_ref_array('shopp_category_saved', array($Category));
     $this->notice(Shopp::__('%s category saved.', '<strong>' . $Category->name . '</strong>'));
 }
Пример #12
0
 /**
  * Formats tax rates to a precision beyond the currency format
  *
  * @author Jonathan Davis
  * @since 1.3
  *
  * @param scalar $amount An amount to convert to a float
  * @return float The float amount
  **/
 private static function float($amount)
 {
     $base = shopp_setting('base_operations');
     $format = $base['currency']['format'];
     $format['precision'] = 6;
     return Shopp::floatval($amount, true, $format);
 }
Пример #13
0
 public function refund()
 {
     if ('refund' != $this->form('order-action')) {
         return;
     }
     if (!current_user_can('shopp_refund')) {
         wp_die(Shopp::__('You do not have sufficient permissions to carry out this action.'));
     }
     extract($this->references);
     $user = wp_get_current_user();
     $reason = (int) $_POST['reason'];
     $amount = Shopp::floatval($_POST['amount']);
     if ($this->form('message')) {
         $Purchase->message['note'] = $this->form('message');
     }
     if (Shopp::str_true($this->form('send'))) {
         // Submit the refund request to the payment gateway
         shopp_add_order_event($Purchase->id, 'refund', array('txnid' => $Purchase->txnid, 'gateway' => $Gateway->module, 'amount' => $amount, 'reason' => $reason, 'user' => $user->ID));
     } else {
         // Force the order status to be refunded (without talking to the gateway)
         // Email a refund notice to the customer
         shopp_add_order_event($Purchase->id, 'notice', array('user' => $user->ID, 'kind' => 'refunded', 'notice' => Shopp::__('Marked Refunded')));
         // Log the refund event
         shopp_add_order_event($Purchase->id, 'refunded', array('txnid' => $Purchase->txnid, 'amount' => $amount, 'gateway' => $Gateway->module));
         // Cancel the order
         shopp_add_order_event($Purchase->id, 'voided', array('gateway' => $Gateway->module, 'txnorigin' => $Purchase->txnid, 'txnid' => current_time('timestamp')));
         $this->notice(Shopp::__('Order marked refunded.'));
     }
 }
Пример #14
0
 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);
     }
 }
Пример #15
0
 /**
  * Adds a specified quantity to the line item
  *
  * @author Jonathan Davis
  * @since 1.1
  *
  * @return void
  **/
 public function add($qty)
 {
     if ($this->type == 'Donation' && Shopp::str_true($this->donation['var'])) {
         $qty = Shopp::floatval($qty);
         $this->quantity = $this->unitprice;
     }
     $this->quantity($this->quantity + $qty);
 }
Пример #16
0
 /**
  * Handles saving updates from the product editor
  *
  * Saves all product related information which includes core product data
  * and supporting elements such as images, digital downloads, tags,
  * assigned categories, specs and pricing variations.
  *
  * @author Jonathan Davis
  * @since 1.0
  *
  * @param Product $Product
  * @return void
  **/
 public function save(ShoppProduct $Product)
 {
     check_admin_referer('shopp-save-product');
     if (!current_user_can('shopp_products')) {
         wp_die(__('You do not have sufficient permissions to access this page.'));
     }
     ShoppSettings()->saveform();
     // Save workflow setting
     $status = $Product->status;
     // Set publish date
     if ('publish' == $_POST['status']) {
         $publishing = isset($_POST['publish']) ? $_POST['publish'] : array();
         $fields = array('month' => '', 'date' => '', 'year' => '', 'hour' => '', 'minute' => '', 'meridiem' => '');
         $publishdate = join('', array_merge($fields, $publishing));
         if (!empty($publishdate)) {
             $publish =& $_POST['publish'];
             if ($publish['meridiem'] == "PM" && $publish['hour'] < 12) {
                 $publish['hour'] += 12;
             }
             $publish = mktime($publish['hour'], $publish['minute'], 0, $publish['month'], $publish['date'], $publish['year']);
             $Product->status = 'future';
             unset($_POST['status']);
         } else {
             unset($_POST['publish']);
             // Auto set the publish date if not set (or more accurately, if set to an irrelevant timestamp)
             if ($Product->publish <= 86400) {
                 $Product->publish = null;
             }
         }
     } else {
         unset($_POST['publish']);
         $Product->publish = 0;
     }
     // Set a unique product slug
     if (empty($Product->slug)) {
         $Product->slug = sanitize_title($_POST['name']);
     }
     $Product->slug = wp_unique_post_slug($Product->slug, $Product->id, $Product->status, ShoppProduct::posttype(), 0);
     $Product->featured = 'off';
     if (isset($_POST['content'])) {
         $_POST['description'] = $_POST['content'];
     }
     $Product->updates($_POST, array('meta', 'categories', 'prices', 'tags'));
     do_action('shopp_pre_product_save');
     $Product->save();
     // Remove deleted images
     if (!empty($_POST['deleteImages'])) {
         $deletes = array();
         if (strpos($_POST['deleteImages'], ",") !== false) {
             $deletes = explode(',', $_POST['deleteImages']);
         } else {
             $deletes = array($_POST['deleteImages']);
         }
         $Product->delete_images($deletes);
     }
     // Update image data
     if (!empty($_POST['images']) && is_array($_POST['images'])) {
         $Product->link_images($_POST['images']);
         $Product->save_imageorder($_POST['images']);
         if (!empty($_POST['imagedetails'])) {
             $Product->update_images($_POST['imagedetails']);
         }
     }
     // Update Prices
     if (!empty($_POST['price']) && is_array($_POST['price'])) {
         // Delete prices that were marked for removal
         if (!empty($_POST['deletePrices'])) {
             $deletes = array();
             if (strpos($_POST['deletePrices'], ",")) {
                 $deletes = explode(',', $_POST['deletePrices']);
             } else {
                 $deletes = array($_POST['deletePrices']);
             }
             foreach ($deletes as $option) {
                 $Price = new ShoppPrice($option);
                 $Price->delete();
             }
         }
         $Product->resum();
         // Save prices that there are updates for
         foreach ($_POST['price'] as $i => $priceline) {
             if (empty($priceline['id'])) {
                 $Price = new ShoppPrice();
                 $priceline['product'] = $Product->id;
             } else {
                 $Price = new ShoppPrice($priceline['id']);
             }
             $priceline['sortorder'] = array_search($i, $_POST['sortorder']) + 1;
             $priceline['shipfee'] = Shopp::floatval($priceline['shipfee']);
             if (isset($priceline['recurring']['trialprice'])) {
                 $priceline['recurring']['trialprice'] = Shopp::floatval($priceline['recurring']['trialprice']);
             }
             if ($Price->stock != $priceline['stocked']) {
                 $priceline['stock'] = (int) $priceline['stocked'];
                 do_action('shopp_stock_product', $priceline['stock'], $Price, $Price->stock, $Price->stocklevel);
             } else {
                 unset($priceline['stocked']);
             }
             $Price->updates($priceline);
             $Price->save();
             // Save 'price' meta records after saving the price record
             if (isset($priceline['dimensions']) && is_array($priceline['dimensions'])) {
                 $priceline['dimensions'] = array_map(array('Shopp', 'floatval'), $priceline['dimensions']);
             }
             $settings = array('donation', 'recurring', 'membership', 'dimensions');
             $priceline['settings'] = array();
             foreach ($settings as $setting) {
                 if (!isset($priceline[$setting])) {
                     continue;
                 }
                 $priceline['settings'][$setting] = $priceline[$setting];
             }
             if (!empty($priceline['settings'])) {
                 shopp_set_meta($Price->id, 'price', 'settings', $priceline['settings']);
             }
             if (!empty($priceline['options'])) {
                 shopp_set_meta($Price->id, 'price', 'options', $priceline['options']);
             }
             $Product->sumprice($Price);
             if (!empty($priceline['download'])) {
                 $Price->attach_download($priceline['download']);
             }
             if (!empty($priceline['downloadpath'])) {
                 // Attach file specified by URI/path
                 if (!empty($Price->download->id) || empty($Price->download) && $Price->load_download()) {
                     $File = $Price->download;
                 } else {
                     $File = new ProductDownload();
                 }
                 $stored = false;
                 $tmpfile = sanitize_path($priceline['downloadpath']);
                 $File->storage = false;
                 $Engine = $File->engine();
                 // Set engine from storage settings
                 $File->parent = $Price->id;
                 $File->context = "price";
                 $File->type = "download";
                 $File->name = !empty($priceline['downloadfile']) ? $priceline['downloadfile'] : basename($tmpfile);
                 $File->filename = $File->name;
                 if ($File->found($tmpfile)) {
                     $File->uri = $tmpfile;
                     $stored = true;
                 } else {
                     $stored = $File->store($tmpfile, 'file');
                 }
                 if ($stored) {
                     $File->readmeta();
                     $File->save();
                 }
             }
             // END attach file by path/uri
         }
         // END foreach()
         unset($Price);
     }
     // END if (!empty($_POST['price']))
     $Product->load_sold($Product->id);
     // Refresh accurate product sales stats
     $Product->sumup();
     // Update taxonomies after pricing summary is generated
     // Summary table entry is needed for ProductTaxonomy::recount() to
     // count properly based on aggregate product inventory, see #2968
     foreach (get_object_taxonomies(Product::$posttype) as $taxonomy) {
         $tags = '';
         $taxonomy_obj = get_taxonomy($taxonomy);
         if (isset($_POST['tax_input']) && isset($_POST['tax_input'][$taxonomy])) {
             $tags = $_POST['tax_input'][$taxonomy];
             if (is_array($tags)) {
                 // array = hierarchical, string = non-hierarchical.
                 $tags = array_filter($tags);
             }
         }
         if (current_user_can($taxonomy_obj->cap->assign_terms)) {
             wp_set_post_terms($Product->id, $tags, $taxonomy);
         }
     }
     // Ensure taxonomy counts are updated on status changes, see #2968
     if ($status != $_POST['status']) {
         $Post = new StdClass();
         $Post->ID = $Product->id;
         $Post->post_type = ShoppProduct::$posttype;
         wp_transition_post_status($_POST['status'], $Product->status, $Post);
     }
     if (!empty($_POST['meta']['options'])) {
         $_POST['meta']['options'] = stripslashes_deep($_POST['meta']['options']);
     } else {
         $_POST['meta']['options'] = false;
     }
     // No variation options at all, delete all variation-pricelines
     if (!empty($Product->prices) && is_array($Product->prices) && (empty($_POST['meta']['options']['v']) || empty($_POST['meta']['options']['a']))) {
         foreach ($Product->prices as $priceline) {
             // Skip if not tied to variation options
             if ($priceline->optionkey == 0) {
                 continue;
             }
             if (empty($_POST['meta']['options']['v']) && $priceline->context == "variation" || empty($_POST['meta']['options']['a']) && $priceline->context == "addon") {
                 $Price = new ShoppPrice($priceline->id);
                 $Price->delete();
             }
         }
     }
     // Handle product spec/detail data
     if (!empty($_POST['details']) || !empty($_POST['deletedSpecs'])) {
         // Delete specs queued for removal
         $ids = array();
         $deletes = array();
         if (!empty($_POST['deletedSpecs'])) {
             if (strpos($_POST['deleteImages'], ",") !== false) {
                 $deletes = explode(',', $_POST['deleteImages']);
             } else {
                 $deletes = array($_POST['deletedSpecs']);
             }
             $ids = db::escape($_POST['deletedSpecs']);
             $Spec = new Spec();
             db::query("DELETE FROM {$Spec->_table} WHERE id IN ({$ids})");
         }
         if (is_array($_POST['details'])) {
             foreach ($_POST['details'] as $i => $spec) {
                 if (in_array($spec['id'], $deletes)) {
                     continue;
                 }
                 if (isset($spec['new'])) {
                     $Spec = new Spec();
                     $spec['id'] = '';
                     $spec['parent'] = $Product->id;
                 } else {
                     $Spec = new Spec($spec['id']);
                 }
                 $spec['sortorder'] = array_search($i, $_POST['details-sortorder']) + 1;
                 $Spec->updates($spec);
                 $Spec->save();
             }
         }
     }
     // Save any meta data
     if (isset($_POST['meta']) && is_array($_POST['meta'])) {
         foreach ($_POST['meta'] as $name => $value) {
             if (isset($Product->meta[$name])) {
                 $Meta = $Product->meta[$name];
                 if (is_array($Meta)) {
                     $Meta = reset($Product->meta[$name]);
                 }
             } else {
                 $Meta = new ShoppMetaObject(array('parent' => $Product->id, 'context' => 'product', 'type' => 'meta', 'name' => $name));
             }
             $Meta->parent = $Product->id;
             $Meta->name = $name;
             $Meta->value = $value;
             $Meta->save();
         }
     }
     $Product->load_data();
     // Reload data so everything is fresh for shopp_product_saved
     do_action_ref_array('shopp_product_saved', array(&$Product));
     unset($Product);
 }
Пример #17
0
}
if (count($rates) == 0 && $edit === false) {
    ?>
				<tr id="no-taxrates"><td colspan="5"><?php 
    _e('No tax rates, yet.', 'Shopp');
    ?>
</td></tr>
			<?php 
}
$hidden = get_hidden_columns('shopp_page_shopp-settings-taxrates');
$even = false;
foreach ($rates as $index => $taxrate) {
    $defaults = array('rate' => 0, 'country' => false, 'zone' => false, 'rules' => array(), 'locals' => array(), 'haslocals' => false);
    $taxrate = array_merge($defaults, $taxrate);
    extract($taxrate);
    $rate = Shopp::percentage(Shopp::floatval($rate), array('precision' => 4));
    $location = $countries[$country];
    if (isset($zone) && !empty($zone)) {
        $location = $zones[$country][$zone] . ", {$location}";
    }
    $editurl = wp_nonce_url(add_query_arg(array('id' => $index), $this->url));
    $deleteurl = wp_nonce_url(add_query_arg(array('delete' => $index), $this->url), 'shopp_delete_taxrate');
    $classes = array();
    if (!$even) {
        $classes[] = 'alternate';
    }
    $even = !$even;
    if ($edit !== false && $edit === $index) {
        $conditions = array();
        foreach ($rules as $ruleid => $rule) {
            $condition_template_data = array('${id}' => $edit, '${ruleid}' => $ruleid, '${property_menu}' => menuoptions($propertymenu, $rule['p'], true), '${rulevalue}' => esc_attr($rule['v']));
Пример #18
0
 public function screen()
 {
     $shipcarriers = Lookup::shipcarriers();
     $serviceareas = array('*', ShoppBaseLocale()->code());
     foreach ($shipcarriers as $c => $record) {
         if (!in_array($record->areas, $serviceareas)) {
             continue;
         }
         $carriers[$c] = $record->name;
     }
     unset($shipcarriers);
     $shipping_carriers = shopp_setting('shipping_carriers');
     if (empty($shipping_carriers)) {
         $shipping_carriers = array_keys($carriers);
     }
     $imperial = 'imperial' == ShoppBaseLocale()->units();
     $weights = $imperial ? array('oz' => Shopp::__('ounces (oz)'), 'lb' => Shopp::__('pounds (lbs)')) : array('g' => Shopp::__('gram (g)'), 'kg' => Shopp::__('kilogram (kg)'));
     $weightsmenu = menuoptions($weights, shopp_setting('weight_unit'), true);
     $dimensions = $imperial ? array('in' => Shopp::__('inches (in)'), 'ft' => Shopp::__('feet (ft)')) : array('cm' => Shopp::__('centimeters (cm)'), 'm' => Shopp::__('meters (m)'));
     $dimsmenu = menuoptions($dimensions, shopp_setting('dimension_unit'), true);
     $rates = shopp_setting('shipping_rates');
     if (!empty($rates)) {
         ksort($rates);
     }
     $Shopp = Shopp::object();
     $Shipping = $Shopp->Shipping;
     $Shipping->settings();
     // Load all installed shipping modules for settings UIs
     $methods = $Shopp->Shipping->methods;
     $edit = false;
     if (isset($_REQUEST['id'])) {
         $edit = (int) $_REQUEST['id'];
     }
     $active = shopp_setting('active_shipping');
     if (!$active) {
         $active = array();
     }
     if (isset($_POST['module'])) {
         $setting = false;
         $module = isset($_POST['module']) ? $_POST['module'] : false;
         $id = isset($_POST['id']) ? $_POST['id'] : false;
         if ($id == $module) {
             if (isset($_POST['settings'])) {
                 shopp_set_formsettings();
             }
             /** Save shipping service settings **/
             $active[$module] = true;
             shopp_set_setting('active_shipping', $active);
             $updated = __('Shipping settings saved.', 'Shopp');
             // Cancel editing if saving
             if (isset($_POST['save'])) {
                 unset($_REQUEST['id']);
             }
             $Errors = ShoppErrors();
             do_action('shopp_verify_shipping_services');
             if ($Errors->exist()) {
                 // Get all addon related errors
                 $failures = $Errors->level(SHOPP_ADDON_ERR);
                 if (!empty($failures)) {
                     $updated = __('Shipping settings saved but there were errors: ', 'Shopp');
                     foreach ($failures as $error) {
                         $updated .= '<p>' . $error->message(true, true) . '</p>';
                     }
                 }
             }
         } else {
             /** Save shipping calculator settings **/
             $setting = $_POST['id'];
             if (empty($setting)) {
                 // Determine next available setting ID
                 $index = 0;
                 if (is_array($active[$module])) {
                     $index = count($active[$module]);
                 }
                 $setting = "{$module}-{$index}";
             }
             // Cancel editing if saving
             if (isset($_POST['save'])) {
                 unset($_REQUEST['id']);
             }
             $setting_module = $setting;
             $id = 0;
             if (false !== strpos($setting, '-')) {
                 list($setting_module, $id) = explode('-', $setting);
             }
             // Prevent fishy stuff from happening
             if ($module != $setting_module) {
                 $module = false;
             }
             // Save shipping calculator settings
             $Shipper = $Shipping->get($module);
             if ($Shipper && isset($_POST[$module])) {
                 $Shipper->setting($id);
                 $_POST[$module]['label'] = stripslashes($_POST[$module]['label']);
                 // Sterilize $values
                 foreach ($_POST[$module]['table'] as $i => &$row) {
                     if (isset($row['rate'])) {
                         $row['rate'] = Shopp::floatval($row['rate']);
                     }
                     if (!isset($row['tiers'])) {
                         continue;
                     }
                     foreach ($row['tiers'] as &$tier) {
                         if (isset($tier['rate'])) {
                             $tier['rate'] = Shopp::floatval($tier['rate']);
                         }
                     }
                 }
                 // Delivery estimates: ensure max equals or exceeds min
                 ShippingFramework::sensibleestimates($_POST[$module]['mindelivery'], $_POST[$module]['maxdelivery']);
                 shopp_set_setting($Shipper->setting, $_POST[$module]);
                 if (!array_key_exists($module, $active)) {
                     $active[$module] = array();
                 }
                 $active[$module][(int) $id] = true;
                 shopp_set_setting('active_shipping', $active);
                 $this->notice(Shopp::__('Shipping settings saved.'));
             }
         }
     }
     $postcodes = ShoppLookup::postcodes();
     foreach ($postcodes as &$postcode) {
         $postcode = !empty($postcode);
     }
     $lookup = array('regions' => array_merge(array('*' => Shopp::__('Anywhere')), ShoppLookup::regions()), 'regionmap' => ShoppLookup::regions('id'), 'countries' => ShoppLookup::countries(), 'areas' => ShoppLookup::country_areas(), 'zones' => ShoppLookup::country_zones(), 'postcodes' => $postcodes);
     $ShippingTemplates = new TemplateShippingUI();
     add_action('shopp_shipping_module_settings', array($Shipping, 'templates'));
     $Table = $this->table;
     $Table->prepare_items();
     include $this->ui('shipping.php');
 }
Пример #19
0
 /**
  * Parse price matching queries into a processing object
  *
  * @author Jonathan Davis
  * @since 1.1
  *
  * @param string $query A search query string
  * @return object The price matching object
  **/
 static function PriceMatching($query)
 {
     $pricematch = self::_pricematch_regex();
     preg_match_all("/{$pricematch}/", $query, $matches, PREG_SET_ORDER);
     if (empty($matches)) {
         return false;
     }
     $_->op = $matches[0][0][0];
     $_->op = in_array($_->op, array("<", ">")) ? $_->op : '';
     $_->min = Shopp::floatval($matches[0][1]);
     $_->max = Shopp::floatval($matches[0][4]);
     $_->target = $_->min;
     if ($_->max > 0) {
         $_->op = "-";
     }
     // Range matching
     // Roundabout price match
     if (empty($_->op) && empty($_->max)) {
         $_->min = $_->target - $_->target / 2;
         $_->max = $_->target + $_->target / 2;
     }
     return $_;
 }
Пример #20
0
 public function tablerate_row($row = 0, array $attrs = array(), array $table = array())
 {
     $unit = isset($attrs['unit']) ? $attrs['unit'] : array('', '');
     // Handle adding rate tiers
     if (isset($_POST['addtier'])) {
         list($inrow, $tier) = explode(',', $_POST['addtier']);
         if ($row == $inrow) {
             $tier++;
             // Stats to guess next numbers
             if (isset($table['tiers']) && !empty($table['tiers'])) {
                 $max = $mean = $sum = $deltas = $avedev = array('t' => 0, 'r' => 0);
                 $c = 0;
                 foreach ($table['tiers'] as $index => $t) {
                     if ($t['threshold'] == 0) {
                         continue;
                     }
                     $sum['t'] += $t['threshold'];
                     $sum['r'] += Shopp::floatval($t['rate']);
                     $c++;
                     $max['t'] = max($max['t'], $t['threshold']);
                     $max['r'] = max($max['r'], Shopp::floatval($t['rate']));
                     if ($index + 1 == $tier) {
                         break;
                     }
                 }
                 $mean['t'] = $sum['t'] / $c;
                 $mean['r'] = $sum['r'] / $c;
                 foreach ($table['tiers'] as $index => $t) {
                     if ($t['threshold'] == 0) {
                         continue;
                     }
                     $deltas['t'] += abs($t['threshold'] - $mean['t']);
                     $deltas['r'] += abs(Shopp::floatval($t['rate']) - $mean['r']);
                     if ($index + 1 == $tier) {
                         break;
                     }
                 }
                 $avedev['t'] = max(round($deltas['t'] / $c, 0), 1);
                 $avedev['r'] = max(round($deltas['r'] / $c, 5), 1);
             }
             $newtier = array('threshold' => $max['t'] + $avedev['t'], 'rate' => $max['r'] + $avedev['r']);
             if ($tier == $c) {
                 $table['tiers'][] = $newtier;
             } else {
                 array_splice($table['tiers'], $tier, 0, array($newtier));
             }
         }
     }
     if ($this->template) {
         $unit = array('${unit}', '${unitabbr}');
     }
     // Handle deleting a rate tier
     if (isset($_POST['deletetier'])) {
         list($inrow, $tier) = explode(',', $_POST['deletetier']);
         if ($row == $inrow && $tier !== 0) {
             array_splice($table['tiers'], $tier, 1);
         }
     }
     $_ = array();
     $_[] = '<thead>';
     $_[] = '<tr>';
     $_[] = '<th scope="col">' . __('Destination', 'Shopp') . '</th>';
     $_[] = '<th scope="col">' . __('Postal Code', 'Shopp') . '</th>';
     $_[] = '<th scope="col">' . sprintf(__('Rates by %s', 'Shopp'), "{$unit[0]}" . (isset($unit[1]) && !empty($unit[1]) ? " ({$unit[1]})" : '')) . '</th>';
     $_[] = '<th class="delete control" scope="col"><div>&nbsp;</div></th>';
     $_[] = '</tr>';
     $_[] = '</thead>';
     $_[] = '<tbody>';
     $_[] = '<tr>';
     if (!$this->template) {
         $_[] = $this->location_fields($row, $table);
     }
     $_[] = '<td>';
     $_[] = '<table class="panel">';
     if (!$this->template) {
         if (empty($table) || empty($table['tiers'])) {
             $_[] = $this->tablerate_row_tier($row, 0, $attrs);
         } else {
             foreach ($table['tiers'] as $tier => $setting) {
                 $_[] = $this->tablerate_row_tier($row, $tier, $attrs, $setting);
             }
         }
     }
     $_[] = '</table>';
     $_[] = '</td>';
     $_[] = '<td class="delete control">';
     $_[] = ShoppUI::button('delete', 'deleterow', array('class' => 'delete' . ($row == 0 ? ' hidden' : ''), 'value' => $row));
     $_[] = '</td>';
     $_[] = '</tr>';
     $_[] = '</tbody>';
     return join('', $_);
 }
Пример #21
0
 /**
  * Formats tax rates to a precision beyond the currency format
  *
  * @author Jonathan Davis
  * @since 1.3
  *
  * @param scalar $amount An amount to convert to a float
  * @return float The float amount
  **/
 private static function float($amount)
 {
     $format = ShoppBaseCurrency()->settings();
     $format['precision'] = 6;
     // Override the precision to 6 digits
     return Shopp::floatval($amount, true, $format);
 }