Changeset 865739
- Timestamp:
- 02/26/2014 10:00:04 PM (12 years ago)
- Location:
- shopp/trunk
- Files:
-
- 5 added
- 68 edited
-
Shopp.php (modified) (3 diffs)
-
api/collection.php (modified) (3 diffs)
-
api/core.php (modified) (2 diffs)
-
api/theme/cart.php (modified) (4 diffs)
-
api/theme/cartitem.php (modified) (1 diff)
-
api/theme/checkout.php (modified) (1 diff)
-
api/theme/collection.php (modified) (3 diffs)
-
api/theme/customer.php (modified) (1 diff)
-
api/theme/product.php (modified) (15 diffs)
-
api/theme/purchase.php (modified) (1 diff)
-
api/theme/storefront.php (modified) (8 diffs)
-
core/flow/Admin.php (modified) (1 diff)
-
core/flow/Ajax.php (modified) (1 diff)
-
core/flow/Checkout.php (modified) (3 diffs)
-
core/flow/Dashboard.php (modified) (2 diffs)
-
core/flow/Discounter.php (modified) (2 diffs)
-
core/flow/Install.php (modified) (14 diffs)
-
core/flow/Order.php (modified) (7 diffs)
-
core/flow/Pages.php (modified) (5 diffs)
-
core/flow/Registration.php (modified) (4 diffs)
-
core/flow/Report.php (modified) (7 diffs)
-
core/flow/Resources.php (modified) (2 diffs)
-
core/flow/Setup.php (modified) (6 diffs)
-
core/flow/Storefront.php (modified) (1 diff)
-
core/flow/System.php (modified) (6 diffs)
-
core/flow/Warehouse.php (modified) (6 diffs)
-
core/library/Core.php (modified) (3 diffs)
-
core/library/DB.php (modified) (1 diff)
-
core/library/Email.php (modified) (1 diff)
-
core/library/Loader.php (modified) (1 diff)
-
core/library/Lookup.php (modified) (1 diff)
-
core/library/Shopp.php (added)
-
core/library/Support.php (modified) (5 diffs)
-
core/library/Version.php (modified) (2 diffs)
-
core/model/Asset.php (modified) (7 diffs)
-
core/model/Cart.php (modified) (5 diffs)
-
core/model/Collection.php (modified) (4 diffs)
-
core/model/Customer.php (modified) (5 diffs)
-
core/model/Discounts.php (modified) (13 diffs)
-
core/model/Gateway.php (modified) (2 diffs)
-
core/model/Item.php (modified) (7 diffs)
-
core/model/Meta.php (modified) (2 diffs)
-
core/model/Payments.php (modified) (1 diff)
-
core/model/Product.php (modified) (12 diffs)
-
core/model/Promotion.php (modified) (3 diffs)
-
core/model/Purchase.php (modified) (6 diffs)
-
core/model/Settings.php (modified) (17 diffs)
-
core/model/Shiprates.php (modified) (3 diffs)
-
core/model/Tax.php (modified) (3 diffs)
-
core/schema (added)
-
core/schema/schema-110.sql (added)
-
core/schema/schema-120.sql (added)
-
core/schema/schema.sql (added)
-
core/ui/behaviors/catalog.js (modified) (1 diff)
-
core/ui/behaviors/priceline.js (modified) (1 diff)
-
core/ui/behaviors/priceline.min.js (modified) (1 diff)
-
core/ui/categories/category.js (modified) (3 diffs)
-
core/ui/categories/category.min.js (modified) (1 diff)
-
core/ui/orders/order.php (modified) (4 diffs)
-
core/ui/orders/orders.php (modified) (3 diffs)
-
core/ui/reports/products.php (modified) (1 diff)
-
core/ui/reports/reports.php (modified) (1 diff)
-
core/ui/settings/setup.php (modified) (1 diff)
-
core/ui/styles/admin.css (modified) (2 diffs)
-
core/ui/styles/dashboard.css (modified) (1 diff)
-
gateways/PayPal/PayPalStandard.php (modified) (8 diffs)
-
license.txt (modified) (5 diffs)
-
readme.txt (modified) (5 diffs)
-
services/image.php (modified) (1 diff)
-
storage/core/FSStorage.php (modified) (3 diffs)
-
templates/email-order.php (modified) (1 diff)
-
templates/sidecart.php (modified) (1 diff)
-
templates/thanks.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
shopp/trunk/Shopp.php
r831831 r865739 4 4 * Plugin URI: http://shopplugin.com 5 5 * Description: An ecommerce framework for WordPress. 6 * Version: 1.3. 16 * Version: 1.3.2 7 7 * Author: Ingenesis Limited 8 8 * Author URI: http://ingenesis.net … … 10 10 * Tested up to: 3.5.2 11 11 * 12 * Portions created by Ingenesis Limited are Copyright © 2008-201 3by Ingenesis Limited12 * Portions created by Ingenesis Limited are Copyright © 2008-2014 by Ingenesis Limited 13 13 * 14 14 * This file is part of Shopp. … … 29 29 **/ 30 30 31 defined( 'WPINC' ) || header( 'HTTP/1.1 403' ) & exit; // Prevent direct access 31 // Prevent direct access 32 defined( 'WPINC' ) || header( 'HTTP/1.1 403' ) & exit; 32 33 34 // Start the bootloader 33 35 require 'core/library/Loader.php'; 34 36 35 /** 36 * Shopp core plugin management class 37 * 38 * @author Jonathan Davis 39 * @since 1.0 40 * @version 1.3 41 * @package shopp 42 **/ 43 class Shopp extends ShoppCore { 44 45 private static $object = false; 46 47 private function __construct () { 48 49 $this->paths(); // Determine Shopp paths 50 $this->constants(); // Setup Shopp constants 51 $this->textdomain(); // Load the translation file 52 53 // Load the Developer API 54 ShoppDeveloperAPI::load( SHOPP_PATH ); 55 56 // Initialize error system 57 ShoppErrors(); 58 59 // Initialize application control processing 60 $this->Flow = new ShoppFlow(); 61 62 // Init deprecated properties for legacy add-on module compatibility 63 $this->Shopping = ShoppShopping(); 64 $this->Settings = ShoppSettings(); 65 66 // Hooks 67 add_action('init', array($this, 'init')); 68 69 // Core WP integration 70 add_action('shopp_init', array($this, 'pages')); 71 add_action('shopp_init', array($this, 'collections')); 72 add_action('shopp_init', array($this, 'taxonomies')); 73 add_action('shopp_init', array($this, 'products'), 99); 74 add_action('shopp_init', array($this, 'rebuild'), 99); 75 76 add_filter('rewrite_rules_array', array($this, 'rewrites')); 77 add_filter('query_vars', array($this, 'queryvars')); 78 79 // Theme integration 80 add_action('widgets_init', array($this, 'widgets')); 81 82 } 83 84 /** 85 * Singleton accessor method 86 * 87 * @author Jonathan Davis 88 * @since 1.3 89 * 90 * @return Shopp Provides the running Shopp object 91 **/ 92 public static function object () { 93 if ( ! self::$object instanceof self ) 94 self::$object = new self; 95 return self::$object; 96 } 97 98 /** 99 * Boot up the core plugin 100 * 101 * @author Jonathan Davis 102 * @since 1.3 103 * 104 * @return void 105 **/ 106 public static function plugin () { 107 global $Shopp; // Provide global for backwards compatibility 108 $Shopp = Shopp::object(); 109 do_action('shopp_loaded'); 110 } 111 112 /** 113 * Initializes the Shopp runtime environment 114 * 115 * @author Jonathan Davis 116 * @since 1.0 117 * 118 * @return void 119 **/ 120 public function init () { 121 122 $this->Collections = array(); 123 $this->Order = new ShoppOrder(); 124 $this->Gateways = new GatewayModules(); 125 $this->Shipping = new ShippingModules(); 126 $this->Storage = new StorageEngines(); 127 $this->APIs = new ShoppAPIModules(); 128 129 new ShoppLogin(); 130 do_action('shopp_init'); 131 } 132 133 /** 134 * Setup configurable constants 135 * 136 * @author Jonathan Davis 137 * @since 1.3 138 * 139 * @return void 140 **/ 141 public function constants () { 142 if ( ! defined('SHOPP_VERSION') ) define( 'SHOPP_VERSION', ShoppVersion::release() ); 143 if ( ! defined('SHOPP_GATEWAY_USERAGENT') ) define( 'SHOPP_GATEWAY_USERAGENT', ShoppVersion::agent() ); 144 145 // @deprecated 146 if ( ! defined('SHOPP_HOME') ) define( 'SHOPP_HOME', ShoppSupport::HOMEPAGE ); 147 if ( ! defined('SHOPP_CUSTOMERS') ) define( 'SHOPP_CUSTOMERS', ShoppSupport::FORUMS); 148 if ( ! defined('SHOPP_DOCS') ) define( 'SHOPP_DOCS', ShoppSupport::DOCS ); 149 150 // Helper for line break output 151 if ( ! defined('BR') ) define('BR', '<br />'); 152 153 // Overrideable config macros 154 if ( ! defined('SHOPP_NOSSL') ) define('SHOPP_NOSSL', false); // Require SSL to protect transactions, overrideable for development 155 if ( ! defined('SHOPP_PREPAYMENT_DOWNLOADS') ) define('SHOPP_PREPAYMENT_DOWNLOADS', false); // Require payment capture granting access to downloads 156 if ( ! defined('SHOPP_SESSION_TIMEOUT') ) define('SHOPP_SESSION_TIMEOUT', 172800); // Sessions live for 2 days 157 if ( ! defined('SHOPP_CART_EXPIRES') ) define('SHOPP_CART_EXPIRES', 1209600); // Carts are stashed for up to 2 weeks 158 if ( ! defined('SHOPP_QUERY_DEBUG') ) define('SHOPP_QUERY_DEBUG', false); // Debugging queries is disabled by default 159 if ( ! defined('SHOPP_GATEWAY_TIMEOUT') ) define('SHOPP_GATEWAY_TIMEOUT', 10); // Gateway connections timeout after 10 seconds 160 if ( ! defined('SHOPP_SHIPPING_TIMEOUT') ) define('SHOPP_SHIPPING_TIMEOUT', 10); // Shipping provider connections timeout after 10 seconds 161 if ( ! defined('SHOPP_TEMP_PATH') ) define('SHOPP_TEMP_PATH', sys_get_temp_dir()); // Use the system defined temporary directory 162 if ( ! defined('SHOPP_ADDONS') ) define('SHOPP_ADDONS', WP_CONTENT_DIR . '/shopp-addons'); // A configurable directory to keep Shopp addons 163 if ( ! defined('SHOPP_NAMESPACE_TAXONOMIES') ) define('SHOPP_NAMESPACE_TAXONOMIES', true); // Add taxonomy namespacing for permalinks /shop/category/category-name, /shopp/tag/tag-name 164 165 } 166 167 /** 168 * Setup path related constants 169 * 170 * @author Jonathan Davis 171 * @since 1.3 172 * 173 * @return void 174 **/ 175 public function paths () { 176 177 $path = sanitize_path(dirname(__FILE__)); 178 $file = basename(__FILE__); 179 $directory = basename($path); 180 181 // Paths 182 define('SHOPP_PATH', $path ); 183 define('SHOPP_DIR', $directory ); 184 define('SHOPP_PLUGINFILE', "$directory/$file" ); 185 define('SHOPP_PLUGINURI', set_url_scheme(WP_PLUGIN_URL . "/$directory") ); 186 187 define('SHOPP_ADMIN_DIR', '/core/ui'); 188 define('SHOPP_ADMIN_PATH', SHOPP_PATH . SHOPP_ADMIN_DIR); 189 define('SHOPP_ADMIN_URI', SHOPP_PLUGINURI . SHOPP_ADMIN_DIR); 190 define('SHOPP_ICONS_URI', SHOPP_ADMIN_URI . '/icons'); 191 define('SHOPP_FLOW_PATH', SHOPP_PATH . '/core/flow'); 192 define('SHOPP_MODEL_PATH', SHOPP_PATH . '/core/model'); 193 define('SHOPP_GATEWAYS', SHOPP_PATH . '/gateways'); 194 define('SHOPP_SHIPPING', SHOPP_PATH . '/shipping'); 195 define('SHOPP_STORAGE', SHOPP_PATH . '/storage'); 196 define('SHOPP_THEME_APIS', SHOPP_PATH . '/api/theme'); 197 define('SHOPP_DBSCHEMA', SHOPP_MODEL_PATH . '/schema.sql'); 198 199 } 200 201 /** 202 * Load the text domain translation file 203 * 204 * @author Jonathan Davis 205 * @since 1.3 206 * @uses SHOPP_LANG_DIR 207 * @uses SHOPP_ADDONS 208 * @uses SHOPP_DIR 209 * 210 * @return void 211 **/ 212 public function textdomain () { 213 214 if ( ! defined('SHOPP_LANG_DIR') ) // Add configurable path for language files 215 define('SHOPP_LANG_DIR', ( is_dir(SHOPP_ADDONS . '/languages') ? SHOPP_ADDONS . '/languages' : SHOPP_DIR . '/lang' ) ); 216 217 load_textdomain(__CLASS__, SHOPP_LANG_DIR . '/' . __CLASS__ . '-' . get_locale() . '.mo'); 218 219 } 220 221 /** 222 * Sets up permalink handling for ShoppStorefront pages 223 * 224 * @author Jonathan Davis 225 * @since 1.2 226 * 227 * @return void 228 **/ 229 public function pages () { 230 231 shopp_register_page( 'ShoppCatalogPage' ); 232 shopp_register_page( 'ShoppAccountPage' ); 233 shopp_register_page( 'ShoppCartPage' ); 234 shopp_register_page( 'ShoppCheckoutPage' ); 235 shopp_register_page( 'ShoppConfirmPage' ); 236 shopp_register_page( 'ShoppThanksPage' ); 237 238 do_action( 'shopp_init_storefront_pages' ); 239 240 } 241 242 /** 243 * Register smart collections 244 * 245 * @author Jonathan Davis 246 * @since 1.3 247 * 248 * @return void 249 **/ 250 public function collections () { 251 252 shopp_register_collection( 'CatalogProducts' ); 253 shopp_register_collection( 'NewProducts' ); 254 shopp_register_collection( 'FeaturedProducts' ); 255 shopp_register_collection( 'OnSaleProducts' ); 256 shopp_register_collection( 'BestsellerProducts' ); 257 shopp_register_collection( 'SearchResults' ); 258 shopp_register_collection( 'MixProducts' ); 259 shopp_register_collection( 'TagProducts' ); 260 shopp_register_collection( 'RelatedProducts' ); 261 shopp_register_collection( 'AlsoBoughtProducts' ); 262 shopp_register_collection( 'ViewedProducts' ); 263 shopp_register_collection( 'RandomProducts' ); 264 shopp_register_collection( 'PromoProducts' ); 265 266 } 267 268 /** 269 * Register custom taxonomies 270 * 271 * @author Jonathan Davis 272 * @since 1.3 273 * 274 * @return void 275 **/ 276 public function taxonomies () { 277 ProductTaxonomy::register( 'ProductCategory' ); 278 ProductTaxonomy::register( 'ProductTag' ); 279 } 280 281 /** 282 * Register the product custom post type 283 * 284 * @author Jonathan Davis 285 * @since 1.3 286 * 287 * @return void 288 **/ 289 public function products () { 290 WPShoppObject::register( 'ShoppProduct', ShoppPages()->baseslug() ); 291 } 292 293 /** 294 * Registers theme widgets 295 * 296 * @author Jonathan Davis 297 * @since 1.0 298 * @version 1.3 299 * 300 * @return void 301 **/ 302 public function widgets () { 303 304 register_widget( 'ShoppAccountWidget' ); 305 register_widget( 'ShoppCartWidget' ); 306 register_widget( 'ShoppCategoriesWidget' ); 307 register_widget( 'ShoppFacetedMenuWidget' ); 308 register_widget( 'ShoppProductWidget' ); 309 register_widget( 'ShoppSearchWidget' ); 310 register_widget( 'ShoppCategorySectionWidget' ); 311 register_widget( 'ShoppShoppersWidget' ); 312 register_widget( 'ShoppTagCloudWidget' ); 313 314 } 315 316 /** 317 * Adds Shopp-specific mod_rewrite rule for low-resource, speedy image server and downloads request handler 318 * 319 * @author Jonathan Davis 320 * @since 1.0 321 * 322 * @param array $wp_rewrite_rules An array of existing WordPress rewrite rules 323 * @return array Rewrite rules 324 **/ 325 public function rewrites ($wp_rewrite_rules) { 326 global $is_IIS; 327 $structure = get_option('permalink_structure'); 328 if ( '' == $structure ) return $wp_rewrite_rules; 329 330 $path = str_replace('%2F', '/', urlencode(join('/', array(PLUGINDIR, SHOPP_DIR, 'services')))); 331 332 // Download URL rewrites 333 $AccountPage = ShoppPages()->get('account'); 334 $downloads = array( ShoppPages()->baseslug(), $AccountPage->slug(), 'download', '([a-f0-9]{40})', '?$' ); 335 if ( $is_IIS && 0 === strpos($structure, '/index.php/') ) array_unshift($downloads, 'index.php'); 336 $rules = array( join('/', $downloads) 337 => 'index.php?src=download&shopp_download=$matches[1]', 338 ); 339 340 // Image URL rewrite 341 $images = array( ShoppPages()->baseslug(), 'images', '(\d+)', "?\??(.*)$" ); 342 add_rewrite_rule(join('/', $images), $path . '/image.php?siid=$1&$2'); 343 344 return $rules + (array) $wp_rewrite_rules; 345 } 346 347 /** 348 * Force rebuilding rewrite rules when necessary 349 * 350 * @author Jonathan Davis 351 * @since 1.2 352 * 353 * @return void 354 **/ 355 public function rebuild () { 356 if ( ! shopp_setting_enabled('rebuild_rewrites') ) return; 357 358 flush_rewrite_rules(); 359 shopp_set_setting('rebuild_rewrites', 'off'); 360 } 361 362 /** 363 * Registers the query variables used by Shopp 364 * 365 * @author Jonathan Davis 366 * @since 1.0 367 * @version 1.2 368 * 369 * @param array $vars The current list of handled WordPress query vars 370 * @return array Augmented list of query vars including Shopp vars 371 **/ 372 public function queryvars ($vars) { 373 374 $vars[] = 's_iid'; // Shopp image id 375 $vars[] = 's_cs'; // Catalog (search) flag 376 $vars[] = 's_ff'; // Category filters 377 $vars[] = 'src'; // Shopp resource 378 $vars[] = 'shopp_page'; 379 $vars[] = 'shopp_download'; 380 381 return $vars; 382 } 383 384 /** 385 * Handles request services like the image server and script server 386 * 387 * @author Jonathan Davis 388 * @since 1.3 389 * 390 * @return boolean The service load status 391 **/ 392 public static function services () { 393 if ( WP_DEBUG ) define('SHOPP_MEMORY_PROFILE_BEFORE', memory_get_peak_usage(true) ); 394 395 // Image Server request handling 396 if ( isset($_GET['siid']) || 1 == preg_match('{^/.+?/images/\d+/.*$}', $_SERVER['REQUEST_URI']) ) 397 return require 'services/image.php'; 398 399 // Script Server request handling 400 if ( isset($_GET['sjsl']) ) 401 return require 'services/scripts.php'; 402 } 403 404 // Deprecated properties 405 406 public $Settings; // @deprecated Shopp settings registry 407 public $Flow; // @deprecated Controller routing 408 public $Catalog; // @deprecated The main catalog 409 public $Category; // @deprecated Current category 410 public $Product; // @deprecated Current product 411 public $Purchase; // @deprecated Currently requested order receipt 412 public $Shopping; // @deprecated The shopping session 413 public $Errors; // @deprecated Error system 414 public $Order; // @deprecated The current session Order 415 public $Promotions; // @deprecated Active promotions registry 416 public $Collections; // @deprecated Collections registry 417 public $Gateways; // @deprecated Gateway modules 418 public $Shipping; // @deprecated Shipping modules 419 public $APIs; // @deprecated Loaded API modules 420 public $Storage; // @deprecated Storage engine modules 421 422 } // END class Shopp 423 424 if ( Shopp::services() || Shopp::unsupported() ) return; // Prevent loading the plugin 37 // Prevent loading the plugin in special circumstances 38 if ( Shopp::services() || Shopp::unsupported() ) return; 425 39 426 40 /* Start the core */ -
shopp/trunk/api/collection.php
r821385 r865739 41 41 $slugs = SmartCollection::slugs($name); 42 42 43 add_rewrite_tag( "%$permastruct%", " $namespace/([^/]+)" );44 add_permastruct( $permastruct, ShoppPages()->baseslug() . '/%shopp_collection%', false );43 add_rewrite_tag( "%$permastruct%", "([^/]+)" ); 44 add_permastruct( $permastruct, ShoppPages()->baseslug() . "/$namespace/%shopp_collection%", false ); 45 45 46 46 add_filter( $permastruct . '_rewrite_rules', array('ProductCollection', 'pagerewrites') ); … … 56 56 add_filter( 'shopp_themeapi_storefront_' . $collection . 'collection', $apicall, 10, 3 ); 57 57 } 58 59 // Add special default permalink handling for collection URLs (only add it once) 60 global $wp_rewrite; 61 if ( ! $wp_rewrite->using_permalinks() && false === has_filter('term_link', array('SmartCollection', 'defaultlinks')) ) 62 add_filter('term_link', array('SmartCollection', 'defaultlinks'), 10, 3); 58 63 59 64 } … … 77 82 78 83 $args['rewrite']['slug'] = SHOPP_NAMESPACE_TAXONOMIES ? ShoppPages()->baseslug().'/'.$rewrite_slug : $rewrite_slug; 79 register_taxonomy($taxonomy, ShoppProduct::$posttype,$args);84 register_taxonomy($taxonomy, ShoppProduct::$posttype,$args); 80 85 } 81 86 -
shopp/trunk/api/core.php
r821385 r865739 193 193 194 194 /** 195 * Determines if the requested page is the catalog front page.195 * Determines if the requested page is the storefront catalog page 196 196 * 197 197 * @author Jonathan Davis … … 393 393 if ( false === $wp_query ) { global $wp_the_query; $wp_query = $wp_the_query; } 394 394 395 if ( empty($wp_query->tax_query) ) return false; // No taxonomy request {@see #2748} 396 395 397 $object = $wp_query->get_queried_object(); 398 396 399 $taxonomies = get_object_taxonomies(ShoppProduct::$posttype, 'names'); 397 400 -
shopp/trunk/api/theme/cart.php
r831831 r865739 119 119 public static function applycode ( $result, $options, $O ) { 120 120 121 $submit_attrs = array( 'title', 'value', 'disabled', 'tabindex', 'accesskey', 'class');121 $submit_attrs = array( 'title', 'value', 'disabled', 'tabindex', 'accesskey', 'class', 'autocomplete', 'placeholder', 'required' ); 122 122 123 123 // Skip if discounts are not available … … 149 149 public static function applygiftcard ( $result, $options, $O ) { 150 150 151 $submit_attrs = array( 'title', 'value', 'disabled', 'tabindex', 'accesskey', 'class');151 $submit_attrs = array( 'title', 'value', 'disabled', 'tabindex', 'accesskey', 'class', 'autocomplete', 'placeholder', 'required' ); 152 152 153 153 if ( ! isset($options['value']) ) $options['value'] = Shopp::__('Add Gift Card'); … … 267 267 268 268 public static function empty_button ( $result, $options, $O ) { 269 $submit_attrs = array( 'title', 'value', 'disabled', 'tabindex', 'accesskey', 'class');269 $submit_attrs = array( 'title', 'value', 'disabled', 'tabindex', 'accesskey', 'class', 'autocomplete', 'placeholder', 'required' ); 270 270 if ( ! isset($options['value']) ) $options['value'] = __('Empty Cart', 'Shopp'); 271 271 return '<input type="submit" name="empty" id="empty-button" ' . inputattrs($options,$submit_attrs) . ' />'; … … 467 467 468 468 public static function update_button ( $result, $options, $O ) { 469 $submit_attrs = array( 'title', 'value', 'disabled', 'tabindex', 'accesskey', 'class');469 $submit_attrs = array( 'title', 'value', 'disabled', 'tabindex', 'accesskey', 'class', 'autocomplete', 'placeholder', 'required' ); 470 470 if ( ! isset($options['value']) ) $options['value'] = __('Update Subtotal', 'Shopp'); 471 471 if ( isset($options['class']) ) $options['class'] .= ' update-button'; -
shopp/trunk/api/theme/cartitem.php
r821385 r865739 121 121 public static function product ( $result, $options, $O ) { 122 122 if ( isset($options['priceline']) && Shopp::str_true($options['priceline']) ) 123 return $O-> $priceline;123 return $O->priceline; 124 124 return $O->product; 125 125 } -
shopp/trunk/api/theme/checkout.php
r831831 r865739 486 486 /// Allowable attributes for textarea inputs 487 487 $textarea_attrs = array('accesskey', 'title', 'tabindex', 'class', 'disabled', 'required'); 488 $select_attrs = array( 'title', 'required', 'class', 'disabled', 'required', 'size', 'tabindex', 'accesskey');488 $select_attrs = array( 'title', 'required', 'class', 'disabled', 'required', 'size', 'tabindex', 'accesskey', 'placeholder' ); 489 489 490 490 if ( ! $name ) {// Iterator for customer info fields -
shopp/trunk/api/theme/collection.php
r831831 r865739 390 390 391 391 public static function has_images ( $result, $options, $O ) { 392 392 393 if ( ! is_a($O, 'ProductCategory') ) return false; 393 if ( empty($O->images) ) $O->load_images(); 394 reset($O->images); 395 if ( empty($O->images) ) return false; 396 return true; 394 395 if ( empty($O->images) ) { 396 $O->load_images(); 397 reset($O->images); 398 } 399 400 return ( ! empty($O->images) ); 401 397 402 } 398 403 … … 412 417 **/ 413 418 public static function image ( $result, $options, $O ) { 414 if ( !self::has_images( $result, $options, $O )) return '';419 if ( ! self::has_images( $result, $options, $O )) return ''; 415 420 return ShoppStorefrontThemeAPI::image( $result, $options, $O ); 416 421 } 417 422 418 423 public static function images ( $result, $options, $O ) { 419 if ( !isset($O->_images_loop)) {424 if ( ! isset($O->_images_loop) ) { 420 425 reset($O->images); 421 426 $O->_images_loop = true; 422 427 } else next($O->images); 423 428 424 if ( current($O->images) !== false) return true;429 if ( current($O->images) !== false ) return true; 425 430 else { 426 431 unset($O->_images_loop); … … 669 674 670 675 public static function url ( $result, $options, $O ) { 671 global $wp_rewrite; 672 673 $namespace = get_class_property( get_class($O) ,'namespace'); 674 $prettyurls = $wp_rewrite->using_permalinks(); 675 676 $url = Shopp::url( $prettyurls ? "$namespace/$O->slug" : array($O->taxonomy => $O->slug), false ); 676 $url = get_term_link($O); 677 677 if ( isset($options['page']) ) $url = $O->pagelink((int)$options['page']); 678 678 return $url; -
shopp/trunk/api/theme/customer.php
r831831 r865739 220 220 if ( array_key_exists('filetype', $options) ) $string .= $download->mime; 221 221 if ( array_key_exists('size', $options) ) $string .= readableFileSize($download->size); 222 if ( array_key_exists('date', $options) ) $string .= _d($df, mktimestamp($download->created));222 if ( array_key_exists('date', $options) ) $string .= _d($df, $download->created); 223 223 if ( array_key_exists('url', $options) ) 224 224 $string .= Shopp::url( ('' == get_option('permalink_structure') ? -
shopp/trunk/api/theme/product.php
r831831 r865739 140 140 'discounts' => 'on', 141 141 'taxes' => null, 142 'input' => null 142 'input' => null, 143 'money' => 'on', 144 'number' => 'off' 143 145 ); 144 146 $options = array_merge($defaults, $options); … … 160 162 if ( array_key_exists('sku', $options) ) $_[] = $addon->sku; 161 163 162 if ( array_key_exists('price', $options) ) 163 $_[] = money(self::_taxed((float)$addon->price, $O, $addon->tax, $taxes)); 164 if ( array_key_exists('price', $options) ) { 165 $price = Shopp::roundprice(self::_taxed((float)$addon->price, $O, $addon->tax, $taxes)); 166 if ( Shopp::str_true($money) ) $_[] = Shopp::money($price); 167 else $_[] = $price; 168 } 164 169 165 170 if ( array_key_exists('saleprice', $options) ) { 166 if ( Shopp::str_true($discounts) ) 167 $_[] = money(self::_taxed((float)$addon->promoprice, $O, $addon->tax, $taxes)); 168 else $_[] = money(self::_taxed((float)$addon->saleprice, $O, $addon->tax, $taxes)); 171 $saleprice = Shopp::str_true($discounts) ? $addon->promoprice : $addon->saleprice; 172 $saleprice = Shopp::roundprice( self::_taxed((float)$addon->promoprice, $O, $addon->tax, $taxes) ); 173 if ( Shopp::str_true($money) ) $_[] = Shopp::money($saleprice); 174 else $_[] = $saleprice; 169 175 } 170 176 … … 172 178 if ( array_key_exists('weight', $options) ) 173 179 $_[] = round($addon->weight, 3) . (false !== $weightunit ? " $weightunit" : false); 174 if ( array_key_exists('shipfee', $options) ) 175 $_[] = money(Shopp::floatval($addon->shipfee)); 180 181 if ( array_key_exists('shipfee', $options) ) { 182 $shipfee = Shopp::roundprice($addon->shipfee); 183 if ( Shopp::str_true($money) ) $_[] = Shopp::money($shipfee); 184 else $_[] = $shipfee; 185 } 186 176 187 if ( array_key_exists('sale', $options) ) 177 188 return Shopp::str_true($addon->sale); … … 425 436 unset($options['id']); 426 437 $options['index'] = 0; 438 $options['load'] = 'coverimages'; 427 439 return self::image( $result, $options, $O ); 428 440 } … … 503 515 504 516 // Populate defaults from named settings, if provided 505 $ImageSettings = ImageSettings:: __instance();517 $ImageSettings = ImageSettings::object(); 506 518 507 519 if ( ! empty($options['p_setting']) ) { … … 551 563 // Setup preview images 552 564 $previews = ''; 565 566 if ( 'transparent' == strtolower($p_bg) ) $fill = -1; 567 else $fill = $p_bg ? hexdec(ltrim($p_bg, '#')) : false; 568 569 $lowest_quality = min(ImageSetting::$qualities); 570 571 $scale = $p_fit ? array_search($p_fit, ImageAsset::$defaults['scaling']) : false; 572 $sharpen = $p_sharpen ? max($p_sharpen, ImageAsset::$defaults['sharpen']) : false; 573 $quality = $p_quality ? max($p_quality, $lowest_quality) : false; 574 553 575 foreach ( $O->images as $Image ) { 554 576 $firstPreview = false; … … 556 578 $firstPreview = $previews .= 557 579 '<li class="fill">' . 558 '<img src="' . Shopp::clearpng() . '" alt="" style="width: ' . (int) $maxwidth . 'px; height: auto;" />' .580 '<img src="' . Shopp::clearpng() . '" alt="" style="width: ' . (int) $maxwidth . 'px; height: ' . (int) $maxheight . 'px;" />' . 559 581 '</li>'; 560 582 } 561 562 $scale = $p_fit ? array_search($p_fit, ImageAsset::$defaults['scaling']) : false;563 $sharpen = $p_sharpen ? min($p_sharpen, ImageAsset::$defaults['sharpen']) : false;564 $quality = $p_quality ? min($p_quality, ImageAsset::$defaults['quality']) : false;565 566 if ( 'transparent' == strtolower($p_bg) ) $fill = -1;567 else $fill = $p_bg ? hexdec(ltrim($p_bg, '#')) : false;568 583 569 584 $scaled = $Image->scaled($width, $height, $scale); … … 575 590 $img = '<img src="' . $src . '"' . $titleattr . ' alt="' . $alt . '" width="' . (int) $scaled['width'] . '" height="' . (int) $scaled['height'] . '" />'; 576 591 577 578 592 if ( $p_link ) { 579 580 593 $hrefattr = $Image->url(); 581 594 $relattr = empty($rel) ? '' : ' rel="' . esc_attr($rel) . '"'; … … 583 596 584 597 $img = '<a href="' . $hrefattr . '" class="' . join(' ', $linkclasses) . '"' . $relattr . $titleattr . '>' . $img . '</a>'; 585 586 598 } 587 599 … … 728 740 **/ 729 741 public static function image ( $result, $options, $O ) { 730 if ( empty($O->images) ) $O->load_data( array('images') ); 742 $loadset = array('images', 'coverimages'); 743 if ( empty($options['load']) || ! in_array($options['load'], $loadset) ) 744 $options['load'] = $loading[0]; 745 746 // Load images if no images are loaded or we're loading all images after the coverimage was loaded 747 if ( empty($O->images) || 'images' == $options['load'] ) 748 $O->load_data( array($options['load']) ); 749 731 750 return ShoppStorefrontThemeAPI::image( $result, $options, $O ); 732 751 } … … 807 826 if ( isset($options['rows']) ) $rows = ' rows="' . (int)$options['rows'] . '"'; 808 827 809 $result .= '<textarea name="products[' . (int)$O->id . '][data][' . esc_attr($name) . ']" id="'.$id.'"'.$cols.$rows.inputattrs($options).'>'.esc_html($value).'</textarea>';828 $result = '<textarea name="products[' . (int)$O->id . '][data][' . esc_attr($name) . ']" id="'.$id.'"'.$cols.$rows.inputattrs($options).'>'.esc_html($value).'</textarea>'; 810 829 811 830 } else { … … 1136 1155 1137 1156 public static function summary ( $result, $options, $O ) { 1138 return apply_filters('shopp_product_summary',$O->summary); 1157 $summary = $O->summary; 1158 1159 $overflow = isset($options['overflow']) ? esc_html($options['overflow']) : '…'; 1160 1161 if ( ! empty($options['clip']) && strlen($O->summary) > (int)$options['clip'] ) 1162 $summary = substr($summary, 0, strpos(wordwrap($summary, (int)$options['clip'], "\b"), "\b")) . $overflow; 1163 1164 return apply_filters('shopp_product_summary', $summary); 1139 1165 } 1140 1166 … … 1198 1224 'promos' => 'on', 1199 1225 'discounts' => 'on', 1200 'taxes' => null 1226 'taxes' => null, 1227 'money' => 'on', 1228 'number' => 'off' 1201 1229 ); 1202 1230 $options = array_merge($defaults, $options); … … 1214 1242 if ( array_key_exists('stock', $options) ) $_[] = $variation->stock; 1215 1243 1216 if ( array_key_exists('price', $options) ) 1217 $_[] = money(self::_taxed((float)$variation->price, $O, $variation->tax, $taxes)); 1244 if ( array_key_exists('price', $options) ) { 1245 $price = Shopp::roundprice(self::_taxed((float)$variation->price, $O, $variation->tax, $taxes)); 1246 if ( Shopp::str_true($money) ) $_[] = money($price); 1247 else $_[] = $price; 1248 } 1218 1249 1219 1250 if ( array_key_exists('saleprice', $options) ) { 1220 if (Shopp::str_true($discounts) ) $_[] = money(self::_taxed((float)$variation->promoprice, $O, $variation->tax, $taxes)); 1221 else $_[] = money(self::_taxed((float)$variation->saleprice, $O, $variation->tax, $taxes)); 1251 $saleprice = Shopp::str_true($discounts) ? $variation->promoprice : $variation->saleprice; 1252 $saleprice = Shopp::roundprice( self::_taxed((float)$saleprice, $O, $variation->tax, $taxes) ); 1253 if ( Shopp::str_true($money) ) $_[] = money($saleprice); 1254 else $_[] = $saleprice; 1222 1255 } 1223 1256 … … 1225 1258 $_[] = round($variation->weight, 3) . ($weightunit ? " $weightunit" : false); 1226 1259 1227 if ( array_key_exists('shipfee', $options) ) 1228 $_[] = money(Shopp::floatval($variation->shipfee)); 1260 if ( array_key_exists('shipfee', $options) ) { 1261 $shipfee = Shopp::roundprice($variation->shipfee); 1262 if ( Shopp::str_true($money) ) $_[] = money($shipfee); 1263 else $_[] = $shipfee; 1264 } 1229 1265 1230 1266 if ( array_key_exists('sale', $options) ) -
shopp/trunk/api/theme/purchase.php
r831831 r865739 201 201 public static function data ( $result, $options, $O ) { 202 202 if ( ! is_array($O->data) ) return false; 203 203 204 $data = current($O->data); 204 205 $name = key($O->data); 205 if ( isset($options['name']) ) return esc_html($name); 206 207 if ( ! empty($options['name']) ) { 208 if ( isset($O->data[ $options['name'] ]) ) 209 $data = $O->data[ $options['name'] ]; 210 else $data = false; 211 } elseif ( isset($options['name']) ) return esc_html($name); 212 206 213 return apply_filters('shopp_purchase_order_data', $data); 207 214 } -
shopp/trunk/api/theme/storefront.php
r831831 r865739 126 126 if ( ! empty($options['setting']) ) { 127 127 $setting = $options['setting']; 128 $ImageSettings = ImageSettings:: __instance();128 $ImageSettings = ImageSettings::object(); 129 129 $settings = $ImageSettings->get($setting); 130 130 if ( $settings ) $defaults = array_merge($defaults, $settings->options()); … … 138 138 if ( isset($O->images[ $id ]) ) $Image = $O->images[ $id ]; 139 139 else { 140 shopp_debug( sprintf('No %s image exists atwith the specified database ID of %d.', get_class($O), $id) );140 shopp_debug( sprintf('No %s image exists with the specified database ID of %d.', get_class($O), $id) ); 141 141 return ''; 142 142 } … … 401 401 $options = array_merge($defaults, $options); 402 402 403 $options['style'] = ' list';403 $options['style'] = ''; 404 404 if ( Shopp::str_true($options['dropdown']) ) 405 405 $options['style'] = 'dropdown'; 406 elseif ( ! Shopp::str_true($options['hierarchy']) || !Shopp::str_true($options['wraplist']) )407 $options['style'] = ' ';406 elseif ( Shopp::str_true($options['hierarchy']) || Shopp::str_true($options['wraplist']) ) 407 $options['style'] = 'list'; 408 408 409 409 if ( ! empty($options['showsmart']) && empty($options['smart']) ) … … 485 485 $Collection->slug = $slug; 486 486 $Collection->term_group = 0; 487 $Collection->taxonomy = 'shopp_collection';487 $Collection->taxonomy = get_class_property('SmartCollection','taxon'); 488 488 $Collection->description = ''; 489 489 $Collection->parent = 0; … … 1177 1177 $smartcollection = $category->taxonomy == get_class_property( 'SmartCollection', 'taxon'); 1178 1178 1179 if ( $smartcollection ) {1180 global $wp_rewrite;1181 $termlink = $wp_rewrite->get_extra_permastruct($category->taxonomy);1182 if ( ! empty($termlink) ) $category->slug = get_class_property( 'SmartCollection', 'namespace') . '/' . $category->slug;1183 }1184 1185 1179 $categoryname = $category->name; 1180 1186 1181 $link = get_term_link($category); 1182 1187 1183 $classes = ''; 1188 1184 if ( 'list' == $args['style'] ) { 1189 1185 $classes = 'cat-item cat-item-' . $category->term_id; 1190 if ( ! empty($current_category) ) { 1191 $_current_category = get_term( $current_category, $category->taxonomy ); 1192 if ( $category->term_id == $current_category ) 1193 $classes .= ' current-cat current'; 1194 elseif ( $category->term_id == $_current_category->parent ) 1195 $classes .= ' current-cat-parent current-parent'; 1196 } 1197 } 1186 1187 $Collection = ShoppCollection(); 1188 if ( isset($Collection->slug) && $Collection->slug == $category->slug) 1189 $classes .= ' current-cat current'; 1190 1191 if ( ! empty($Collection->parent) && $Collection->parent == $category->term_id) 1192 $classes .= ' current-cat-parent current-parent'; 1193 } 1194 1198 1195 $total = isset($category->count) ? $category->count : false; 1199 1196 … … 1203 1200 extract($filtered, EXTR_OVERWRITE); 1204 1201 1205 $link = '<a href="' . esc_url( $link ) . '" title="' . esc_attr( $title ) . '" ';1202 $link = '<a href="' . esc_url( $link ) . '" title="' . esc_attr( $title ) . '" class="' . $classes . '"'; 1206 1203 $link .= '>'; 1207 1204 $link .= $categoryname . '</a>'; … … 1215 1212 if ( 'list' == $args['style'] ) { 1216 1213 $output .= "\t<li"; 1217 if ( ! empty($class ) ) $output .= ' class="' . $class . '"';1214 if ( ! empty($classes) ) $output .= ' class="' . $classes . '"'; 1218 1215 $output .= ">$link\n"; 1219 1216 } else { … … 1268 1265 $pad = str_repeat(' ', $depth * 3); 1269 1266 1267 $link = get_term_link($category); 1268 1270 1269 $cat_name = apply_filters('shopp_storefront_categorylist_option', $category->name, $category); 1271 $output .= "\t<option class=\"level-$depth\" value=\"" .$category->slug."\"";1270 $output .= "\t<option class=\"level-$depth\" value=\"" . $link . "\""; 1272 1271 if ( $category->term_id == $args['selected'] ) 1273 1272 $output .= ' selected="selected"'; 1274 1273 $output .= '>'; 1275 1274 $output .= $pad.$cat_name; 1276 if ( $args['products'] )1275 if ( $args['products'] && isset($category->count) ) 1277 1276 $output .= ' ('. $category->count .')'; 1278 1277 $output .= "</option>\n"; -
shopp/trunk/core/flow/Admin.php
r821385 r865739 492 492 add_action('after_plugin_row_' . SHOPP_PLUGINFILE, array('ShoppSupport', 'pluginsnag'), 10, 2); 493 493 494 $updates = array('load-plugins', 'load-update.php', 'load-update-core.php', 'wp_update_plugins', 'shopp_check_updates');495 foreach ( $updates as $action )496 add_action($action, array('ShoppSupport', 'updates'));497 498 494 } 499 495 -
shopp/trunk/core/flow/Ajax.php
r831831 r865739 747 747 } 748 748 749 // @todo Investigate if it is possible to inject a formatted error log message as an XSS vector 749 /** 750 * Automatic refresh of the log is possible when $_REQUEST['refresh'] is set to something other than 'off'. 751 * 752 * @todo Investigate if it is possible to inject a formatted error log message as an XSS vector 753 */ 750 754 public function logviewer () { 751 755 check_admin_referer('wp_ajax_shopp_debuglog'); ?> 752 756 <html> 753 757 <head> 754 <?php if ( ! isset( $_REQUEST['refresh'] ) && 'off' === $_REQUEST['refresh'] ): ?>758 <?php if ( isset( $_REQUEST['refresh'] ) && 'off' !== $_REQUEST['refresh'] ): ?> 755 759 <meta http-equiv="refresh" content="10"> 756 760 <?php endif; ?> -
shopp/trunk/core/flow/Checkout.php
r831831 r865739 107 107 $this->Register->shipaddress(); 108 108 109 if ( $Cart->shipped() ) do_action('shopp_update_destination'); 109 if ( $Cart->shipped() ) 110 do_action('shopp_update_destination'); 110 111 111 112 } … … 132 133 133 134 $selection = $this->form('shipmethod'); 134 if ( $selection == $Shiprates->selected()->slug ) return; 135 $selected = isset($Shiprates->selected()->slug) ? $Shiprates->selected()->slug : ''; 136 if ( $selection == $selected ) return; 135 137 136 138 // Verify shipping method exists first … … 151 153 152 154 // Special case for updating/tracking billing locale 155 $form = $this->form('billing'); 153 156 if ( ! empty($form['locale']) ) 154 157 $BillingAddress->locale = $form['locale']; 155 158 156 if ( ! $Cart->shipped() || ! empty($form['locale']) )159 if ( ! $Cart->shipped() || ! empty($form['locale']) || 'shipping' == ShoppOrder()->sameaddress ) 157 160 do_action('shopp_update_destination'); 158 161 -
shopp/trunk/core/flow/Dashboard.php
r821385 r865739 266 266 $purchasetable = ShoppDatabaseObject::tablename(ShoppPurchase::$table); 267 267 $purchasedtable = ShoppDatabaseObject::tablename(Purchased::$table); 268 $txnstatus_labels = Lookup::txnstatus_labels(); 268 269 269 270 if ( ! ( $Orders = get_transient('shopp_dashboard_orders') ) ) { … … 277 278 echo '<tbody id="orders" class="list orders">'; 278 279 $even = false; 279 foreach ($Orders as $Order) { 280 echo '<tr'.((!$even)?' class="alternate"':'').'>'; 281 $even = !$even; 280 foreach ( $Orders as $Order ) { 281 $classes = array(); 282 if ( $even = !$even ) $classes[] = 'alternate'; 283 $txnstatus = isset($txnstatus_labels[ $Order->txnstatus ]) ? $txnstatus_labels[$Order->txnstatus] : $Order->txnstatus; 284 $classes[] = strtolower(preg_replace('/[^\w]/', '_', $Order->txnstatus)); 285 286 echo '<tr class="' . join(' ',$classes) . '">'; 282 287 echo '<td><a class="row-title" href="'.add_query_arg(array('page'=>ShoppAdmin()->pagename('orders'),'id'=>$Order->id),admin_url('admin.php')).'" title="View "Order '.$Order->id.'"">'.((empty($Order->firstname) && empty($Order->lastname))?'(no contact name)':$Order->firstname.' '.$Order->lastname).'</a></td>'; 283 288 echo '<td>'.date("Y/m/d",mktimestamp($Order->created)).'</td>'; 284 echo '<td class="num ">'.$Order->items.'</td>';285 echo '<td class="num ">'.money($Order->total).'</td>';286 echo '<td class="num ">'.$statusLabels[ $Order->status ].'</td>';289 echo '<td class="num items">'.$Order->items.'</td>'; 290 echo '<td class="num total">'.money($Order->total).'</td>'; 291 echo '<td class="num status">'.$statusLabels[ $Order->status ].'</td>'; 287 292 echo '</tr>'; 288 293 } -
shopp/trunk/core/flow/Discounter.php
r821385 r865739 179 179 if ( 'new' !== $_POST['id'] ) { 180 180 $Promotion = new ShoppPromo($_POST['id']); 181 $wascatalog = ( 'Catalog' == $Promotion->target ); 181 182 } else $Promotion = new ShoppPromo(); 182 183 … … 195 196 do_action_ref_array('shopp_promo_saved', array(&$Promotion)); 196 197 197 // $Promotion->reset_discounts();198 if ( 'Catalog' == $Promotion->target ) 198 // Apply catalog promotion discounts to catalog product price lines 199 if ( 'Catalog' == $Promotion->target ) { 199 200 $Promotion->catalog(); 201 } elseif ( $wascatalog ) { 202 // Unapply catalog discounts for discounts that no longer target catalog products 203 $priceids = ShoppPromo::discounted_prices(array($Promotion->id)); 204 $Promotion->uncatalog($priceids); 205 } 200 206 201 207 // Set confirmation notice -
shopp/trunk/core/flow/Install.php
r821385 r865739 5 5 * Flow controller for installation and upgrades 6 6 * 7 * @author Jonathan Davis8 7 * @version 1.0 9 * @copyright Ingenesis Limited, January 6, 20108 * @copyright Ingenesis Limited, January 2010-2014 10 9 * @package shopp 11 * @subpackage shopp12 10 **/ 13 11 14 12 defined( 'WPINC' ) || header( 'HTTP/1.1 403' ) & exit; // Prevent direct access 15 13 16 /**17 * ShoppInstallation18 *19 * @package shopp20 * @author Jonathan Davis21 **/22 14 class ShoppInstallation extends ShoppFlowController { 23 15 … … 29 21 * 30 22 * @return void 31 * @author Jonathan Davis32 23 **/ 33 24 function __construct () { 34 add_action('shopp_activate',array($this,'activate')); 35 add_action('shopp_deactivate',array($this,'deactivate')); 36 add_action('shopp_reinstall',array($this,'install')); 37 38 add_action('shopp_setup',array($this,'setup')); 39 add_action('shopp_setup',array($this,'images')); 40 add_action('shopp_setup',array($this,'roles')); 41 add_action('shopp_setup',array($this,'maintenance')); 25 26 add_action('shopp_activate', array($this, 'activate')); 27 add_action('shopp_deactivate', array($this, 'deactivate')); 28 add_action('shopp_reinstall', array($this, 'install')); 29 30 add_action('shopp_setup', array($this, 'setup')); 31 add_action('shopp_setup', array($this, 'images')); 32 add_action('shopp_setup', array($this, 'roles')); 33 add_action('shopp_setup', array($this, 'maintenance')); 42 34 43 35 $this->errors = array( … … 89 81 90 82 shopp_set_setting('updates', false); 91 shopp_set_setting('rebuild_rewrites', 'on'); 92 83 84 add_action('init', 'flush_rewrite_rules', 99); 93 85 return true; 94 86 } … … 166 158 shopp_set_setting('maintenance', 'on'); 167 159 168 // Process any database schema changes169 $this->upschema();170 171 // @todo Remove before release172 if ( in_array($installed, array(1300,1301)) ) $installed = 1148;173 174 160 if ( $installed < 1100 ) $this->upgrade_110(); 175 161 if ( $installed < 1200 ) $this->upgrade_120(); 176 162 if ( $installed < 1300 ) $this->upgrade_130(); 163 164 $db = sDB::object(); 165 file_put_contents(SHOPP_PATH . '/shopp_queries.txt', json_encode($db->queries)); 177 166 178 167 ShoppSettings()->save('db_version', ShoppVersion::db()); … … 195 184 * @return void 196 185 **/ 197 public function upschema () { 186 public function upschema ( $filename = 'schema.sql' ) { 187 188 $path = SHOPP_PATH . '/core/schema'; 189 $schema = "$path/$filename"; 190 191 // Check for the schema definition file 192 if ( ! file_exists($schema) ) $this->error('nodbschema-upgrade'); 193 198 194 // Test to ensure Shopp can create/drop tables 199 195 $testtable = 'shopp_db_permissions_test_'.time(); … … 210 206 require(ABSPATH.'wp-admin/includes/upgrade.php'); 211 207 212 // Check for the schema definition file213 if (!file_exists(SHOPP_DBSCHEMA)) $this->error('nodbschema-upgrade');214 208 215 209 ob_start(); 216 include(SHOPP_DBSCHEMA); 217 $schema = ob_get_contents(); 218 ob_end_clean(); 210 include($schema); 211 $schema = ob_get_clean(); 219 212 220 213 // Update the table schema … … 248 241 * shopp_products 249 242 * shopp_categories 243 * shopp_export_orders 244 * shopp_export_customers 245 * shopp_delete_orders 246 * shopp_delete_customers 247 * shopp_void 248 * shopp_refund 250 249 * shopp_orders shopp-csr 251 250 * shopp_customers 251 * shopp_capture 252 252 * shopp_menu 253 253 * … … 255 255 * @since 1.1 256 256 * 257 * @return void 257 258 **/ 258 259 public function roles () { … … 268 269 269 270 $caps['shopp-csr'] = array( 271 'shopp_capture', 270 272 'shopp_customers', 271 273 'shopp_orders', … … 283 285 'shopp_delete_orders', 284 286 'shopp_delete_customers', 285 'shopp_capture',286 287 'shopp_void', 287 288 'shopp_refund' … … 299 300 300 301 $caps = apply_filters('shopp_role_caps', $caps, $shopp_roles); 302 301 303 foreach ( $shopp_roles as $role => $display ) { 302 304 if ( $wp_roles->is_role($role) ) { … … 449 451 **/ 450 452 public function upgrade_110 () { 451 452 453 $meta_table = ShoppDatabaseObject::tablename('meta'); 453 454 $setting_table = ShoppDatabaseObject::tablename('setting'); 455 $product_table = ShoppDatabaseObject::tablename('product'); 456 457 // 1.1 schema changes 458 $this->upschema('schema-110.sql'); 454 459 455 460 // Update product status from the 'published' column 456 $product_table = ShoppDatabaseObject::tablename('product');457 461 sDB::query("UPDATE $product_table SET status=CAST(published AS unsigned)"); 458 462 … … 622 626 623 627 public function upgrade_120 () { 628 // 1.2 schema changes 629 $this->upschema('schema-120.sql'); 624 630 global $wpdb; 625 631 … … 1026 1032 1027 1033 public function upgrade_130 () { 1034 // 1.3 schema changes 1035 $this->upschema(); 1028 1036 global $wpdb; 1029 1037 -
shopp/trunk/core/flow/Order.php
r831831 r865739 61 61 if ( ! defined('SHOPP_TXNLOCK_TIMEOUT')) define('SHOPP_TXNLOCK_TIMEOUT',10); 62 62 63 add_action('parse_request', array($this, 'locate')); // location updates must come before other requests63 // Request handling 64 64 add_action('parse_request', array($this, 'request')); 65 65 add_action('parse_request', array($this->Discounts, 'requests')); 66 67 68 // Address handling 69 add_action('shopp_update_destination', array($this->Billing, 'fromshipping')); 70 add_action('shopp_update_destination', array($this, 'taxlocale')); 71 66 72 67 73 // Order processing … … 102 108 // but before gateway-order specific handlers are established 103 109 add_action('shopp_init', array($this, 'txnupdates'), 20); 110 111 // Initialize/reinitalize the current location 112 add_action('shopp_init', array($this, 'locate'), 20); 113 104 114 105 115 } … … 179 189 } 180 190 181 /** It191 /** 182 192 * Update addresses throughout the system 183 193 * … … 189 199 public function locate () { 190 200 191 add_action('shopp_update_destination', array($this->Billing, 'fromshipping')); 192 add_action('shopp_update_destination', create_function('',' 193 $Order = ShoppOrder(); 194 $Order->Tax->address($Order->Billing, $Order->Shipping, $Order->Cart->shipped()); 195 ')); 196 add_filter('shopp_tax_country', array('ShoppTax', 'euvat'), 10, 3); 197 198 if ( isset($_REQUEST['shipping']) ) { 199 $request = $_REQUEST['shipping']; 200 201 $this->Billing->locate($request); 202 $this->Shipping->locate($request); 203 204 do_action_ref_array( 'shopp_update_destination', array($request) ); 205 206 } else { 207 $this->Billing->locate(); 208 $this->Shipping->locate(); 209 } 210 211 $this->Tax->address($this->Billing, $this->Shipping, $this->Cart->shipped()); 201 $request = isset($_REQUEST['shipping']) ? $_REQUEST['shipping'] : false; 202 203 $this->Billing->locate($request); 204 $this->Shipping->locate($request); 205 206 do_action_ref_array( 'shopp_update_destination', array($request) ); 207 208 } 209 210 /** 211 * Send the current taxable address to the Tax system 212 * 213 * @author Jonathan Davis 214 * @since 1.3.2 215 * 216 * @return void 217 **/ 218 public function taxlocale ( ) { 219 220 $Address = $this->Billing; 221 if ( $this->Cart->shipped() || shopp_setting_enabled('tax_destination') ) // @todo add setting for "Apply tax to the shipping address" 222 $Address = $this->Shipping; 223 224 // Locale is always tracked with the billing address even though it is may be a shipping locale 225 $locale = empty($this->Billing->locale) ? null : $this->Billing->locale; 226 227 $this->Tax->location($Address->country, $Address->state, $locale); // Update the ShoppTax working location 228 212 229 } 213 230 … … 236 253 * @return void 237 254 **/ 238 public function invoice ( $Purchase) {255 public function invoice ( ShoppPurchase $Purchase ) { 239 256 shopp_add_order_event($Purchase->id, 'invoiced', array( 240 257 'gateway' => $Purchase->gateway, // Gateway handler name (module name from @subpackage) … … 455 472 // Catch Purchase record save errors 456 473 if ( empty($Purchase->id) ) { 457 shopp_add_error( Shopp::__('The order could not be created because of a technical problem on the server. Please try again, or contact the website admin strator.') );474 shopp_add_error( Shopp::__('The order could not be created because of a technical problem on the server. Please try again, or contact the website administrator.') ); 458 475 return; 459 476 } … … 566 583 } 567 584 568 $registration = $Purchase->registration(); 569 if ( empty($registration) ) { 570 shopp_debug('No purchase registration data available for account registration processing.'); 571 return; 572 } 573 574 $this->Customer->copydata($registration['Customer']); 575 $this->Billing->copydata($registration['Billing']); 576 $this->Shipping->copydata($registration['Shipping']); 577 578 579 add_filter('shopp_validate_registration', create_function('', 'return true;') ); // Validation already conducted during the checkout process 580 add_filter('shopp_registration_redirect', create_function('', 'return false;') ); // Prevent redirection to account page after registration 585 if ( ! $this->Customer->exists() ) { 586 587 $registration = $Purchase->registration(); 588 if ( empty($registration) ) { 589 shopp_debug('No purchase registration data available for account registration processing.'); 590 return; 591 } 592 593 $this->Customer->copydata($registration['Customer']); 594 $this->Billing->copydata($registration['Billing']); 595 $this->Shipping->copydata($registration['Shipping']); 596 597 add_filter('shopp_validate_registration', create_function('', 'return true;') ); // Validation already conducted during the checkout process 598 add_filter('shopp_registration_redirect', create_function('', 'return false;') ); // Prevent redirection to account page after registration 599 600 } 581 601 582 602 ShoppRegistration::process(); -
shopp/trunk/core/flow/Pages.php
r831831 r865739 296 296 public function templates () { 297 297 $templates = parent::templates(); 298 if ( is_catalog_frontpage() )298 if ( $this->is_frontpage() ) 299 299 array_unshift($templates, 'front-page.php'); 300 300 return $templates; … … 321 321 322 322 public function styleclass ( $classes ) { 323 if ( is_catalog_frontpage() )323 if ( $this->is_frontpage() ) 324 324 $classes[] = 'home'; 325 325 $classes[] = $this->name(); … … 333 333 $stub = parent::poststub(); 334 334 $wp_query->is_post_type_archive = false; 335 // if ( is_catalog_frontpage() )336 //$wp_query->is_home = true;335 if ( $this->is_frontpage() ) 336 $wp_query->is_home = true; 337 337 338 338 return $stub; 339 339 } 340 340 341 public function is_frontpage () { 342 return self::frontid() == get_option('page_on_front'); 343 } 341 344 } 342 345 … … 392 395 if ( ! $request) $request = ShoppStorefront()->account['request']; 393 396 $templates = array( 'account-'.$request.'.php', 'account.php' ); 394 395 397 if ( 'login' == $request || ! ShoppCustomer()->loggedin() ) $templates = array( 'login-' . $request . '.php', 'login.php' ); 396 398 $context = ShoppStorefront::intemplate(); // Set account page context 399 400 $Errors = ShoppErrorStorefrontNotices(); 397 401 ob_start(); 398 if ( apply_filters( 'shopp_show_account_errors', true ) && ShoppErrors()->exist( SHOPP_AUTH_ERR) )402 if ( apply_filters( 'shopp_show_account_errors', true ) && $Errors->exist() ) 399 403 echo ShoppStorefront::errors( array( "errors-$context", 'account-errors.php', 'errors.php' ) ); 400 404 Shopp::locate_template( $templates, true ); … … 404 408 if ($widget) $content = '<!-- id="shopp" -->' . $content; 405 409 406 return apply_filters( 'shopp_account_template', $content );410 return apply_filters( 'shopp_account_template', $content, $request ); 407 411 408 412 } -
shopp/trunk/core/flow/Registration.php
r821385 r865739 36 36 'shipping' => array(), 37 37 'info' => array(), 38 'marketing' => '', 38 39 'loginname' => '', 39 40 'password' => '', … … 88 89 'phone' => $this->form('phone'), 89 90 'info' => $this->form('info'), 90 'password' => $this->form('password', true), 91 'marketing' => $this->form('marketing'), 92 'password' => $this->form('password', true), 91 93 'loginname' => $this->form('loginname', true) 92 94 ); … … 108 110 109 111 public function shipaddress () { 112 110 113 $ShippingAddress = ShoppOrder()->Shipping; 111 114 $BillingAddress = ShoppOrder()->Billing; … … 138 141 // Prevent overwriting the card data when updating the BillingAddress 139 142 $ignore = array(); 140 if ( ! empty($form['card']) && preg_replace('/[^\d]/', '',$form['card']) == substr($BillingAddress->card,-4) )143 if ( ! empty($form['card']) && preg_replace('/[^\d]/', '', $form['card']) == substr($BillingAddress->card, -4) ) 141 144 $ignore[] = 'card'; 142 145 143 $BillingAddress->updates($form, $ignore);146 $BillingAddress->updates($form, $ignore); 144 147 145 148 // Handle same address copying -
shopp/trunk/core/flow/Report.php
r831831 r865739 27 27 28 28 private $view = 'dashboard'; 29 protected $ui = 'reports'; 29 30 30 31 private $defaults = array(); // Default request options … … 45 46 shopp_enqueue_script('reports'); 46 47 47 add_filter('shopp_reports', array($this,'xreports'));48 add_action('load-'.$this->screen, array($this,'loader'));48 add_filter('shopp_reports', array(__CLASS__, 'xreports')); 49 add_action('load-'.$this->screen, array($this, 'loader')); 49 50 } 50 51 … … 144 145 static function load () { 145 146 $options = self::request(); 146 extract($options, EXTR_SKIP);147 extract($options, EXTR_SKIP); 147 148 148 149 $reports = self::reports(); … … 151 152 $report = isset($_GET['report']) ? $_GET['report'] : 'sales'; 152 153 153 $ReportClass = $reports[$report]['class']; 154 if ( empty($reports[ $report ]['class']) ) 155 return wp_die(Shopp::__('The requested report does not exist.')); 156 157 $ReportClass = $reports[ $report ]['class']; 154 158 $Report = new $ReportClass($options); 155 159 $Report->load(); … … 188 192 189 193 $Report = $this->Report; 194 $Report->pagination(); 190 195 $ListTable = ShoppUI::table_set_pagination ($this->screen, $Report->total, $Report->pages, $per_page ); 191 196 … … 223 228 224 229 $report_title = isset($reports[ $report ])? $reports[ $report ]['name'] : __('Report','Shopp'); 225 include(SHOPP_ADMIN_PATH."/reports/reports.php"); 230 231 include $this->ui('reports.php'); 232 226 233 } 227 234 … … 708 715 709 716 ?> 717 718 710 719 <table class="widefat" cellspacing="0"> 711 720 <thead> -
shopp/trunk/core/flow/Resources.php
r821385 r865739 95 95 if ( ! current_user_can('shopp_financials') || ! current_user_can('shopp_export_orders') ) exit(); 96 96 97 add_filter('shopp_reports', array('ShoppAdminReport', 'xreports')); 97 98 $reports = ShoppAdminReport::reports(); 98 99 $Report = ShoppAdminReport::load(); … … 233 234 } 234 235 235 if ( apply_filters('shopp_download_forbidden', $forbidden ) ) {236 if ( apply_filters('shopp_download_forbidden', $forbidden, $Purchased) ) { 236 237 Shopp::redirect( add_query_arg('downloads', '', Shopp::url(false, 'account') ), true, 303 ); 237 238 } -
shopp/trunk/core/flow/Setup.php
r821385 r865739 97 97 if ( ! empty($_POST['setup']) ) { 98 98 $_POST['settings']['display_welcome'] = 'off'; 99 $this->settings_save();99 shopp_set_formsettings(); 100 100 } 101 101 … … 135 135 asort($_POST['settings']['target_markets']); 136 136 137 $this->settings_save();137 shopp_set_formsettings(); 138 138 $updated = __('Shopp settings saved.', 'Shopp'); 139 139 } … … 179 179 } 180 180 181 $this->settings_save();181 shopp_set_formsettings(); 182 182 } 183 183 … … 245 245 246 246 247 $this->settings_save();247 shopp_set_formsettings(); 248 248 $updated = __('Shopp checkout settings saved.','Shopp'); 249 249 } … … 338 338 $defaults = ShoppPages()->settings(); 339 339 $_POST['settings']['storefront_pages'] = array_merge($defaults,$_POST['settings']['storefront_pages']); 340 $this->settings_save();340 shopp_set_formsettings(); 341 341 342 342 // Re-register page, collection, taxonomies and product rewrites … … 454 454 } 455 455 456 public function settings_save () {457 if (empty($_POST['settings']) || !is_array($_POST['settings'])) return false;458 foreach ($_POST['settings'] as $setting => $value)459 shopp_set_setting($setting,stripslashes_deep($value));460 }461 462 456 } -
shopp/trunk/core/flow/Storefront.php
r831831 r865739 1060 1060 if ( in_array($view, $views) ) $classes[] = $view; 1061 1061 1062 if ( 'grid' == $view ) { 1063 $boxes = shopp_setting('row_products'); 1064 if ( empty($boxes) ) $boxes = 3; 1065 $classes[] = 'shopp_grid-' . abs($boxes); 1066 } 1062 $boxes = shopp_setting('row_products'); 1063 if ( empty($boxes) ) $boxes = 3; 1064 $classes[] = 'shopp_grid-' . abs($boxes); 1067 1065 1068 1066 // Add collection slug -
shopp/trunk/core/flow/System.php
r821385 r865739 152 152 } 153 153 154 $this->settings_save();154 shopp_set_formsettings(); 155 155 $updated = __('Shipping settings saved.','Shopp'); 156 156 } … … 242 242 243 243 if ($id == $module) { 244 if (isset($_POST['settings'])) $this->settings_save();244 if (isset($_POST['settings'])) shopp_set_formsettings(); 245 245 /** Save shipping service settings **/ 246 246 $active[$module] = true; … … 440 440 if (!empty($_POST['save'])) { 441 441 check_admin_referer('shopp-settings-taxes'); 442 $this->settings_save();442 shopp_set_formsettings(); 443 443 $updated = __('Tax settings saved.','Shopp'); 444 444 } … … 686 686 $gateway = str_replace($matched[0], '', $gateway); 687 687 688 // Merge the existing gateway settings with the newly updated settings 688 689 if ( isset($Gateways->active[ $gateway ]) ) { 689 690 $Gateway = $Gateways->active[ $gateway ]; 690 $_POST['settings'][$gateway] = array_merge($Gateway->settings,$_POST['settings'][ $gateway ]); 691 // Cannot use array_merge() because it adds numeric index values instead of overwriting them 692 $_POST['settings'][ $gateway ] = (array) $_POST['settings'][ $gateway ] + (array) $Gateway->settings; 691 693 } 694 692 695 } 693 696 … … 700 703 } // END isset($_POST['gateway]) 701 704 702 $this->settings_save();705 shopp_set_formsettings(); 703 706 $updated = __('Shopp payments settings saved.','Shopp'); 704 707 } … … 880 883 } 881 884 882 883 public function settings_save () {884 if (empty($_POST['settings']) || !is_array($_POST['settings'])) return false;885 foreach ($_POST['settings'] as $setting => $value)886 shopp_set_setting($setting,stripslashes_deep($value));887 }888 889 885 public static function reindex () { 890 886 -
shopp/trunk/core/flow/Warehouse.php
r821385 r865739 21 21 public $products = array(); 22 22 public $subs = array(); 23 24 protected $ui = 'products'; 23 25 24 26 /** … … 383 385 ); 384 386 385 if ( isset($ordercols) ) {387 if ( ! empty($ordercols) ) { 386 388 unset($loading['order']); 387 389 $loading['orderby'] = $ordercols; … … 641 643 wp_die(__('You do not have sufficient permissions to access this page.')); 642 644 643 if ( empty($Shopp->Product)) {645 if ( empty($Shopp->Product) ) { 644 646 $Product = new ShoppProduct(); 645 647 $Product->status = "publish"; 646 648 } else $Product = $Shopp->Product; 647 649 648 $Product->slug = apply_filters('editable_slug', $Product->slug);650 $Product->slug = apply_filters('editable_slug', $Product->slug); 649 651 $permalink = trailingslashit(Shopp::url()); 650 652 … … 655 657 656 658 $workflows = array( 657 "continue" => __('Continue Editing','Shopp'),658 "close" => __('Products Manager','Shopp'),659 "new" => __('New Product','Shopp'),660 "next" => __('Edit Next','Shopp'),661 "previous" => __('Edit Previous','Shopp')659 'continue' => Shopp::__('Continue Editing'), 660 'close' => Shopp::__('Products Manager'), 661 'new' => Shopp::__('New Product'), 662 'next' => Shopp::__('Edit Next'), 663 'previous' => Shopp::__('Edit Previous') 662 664 ); 663 665 664 666 $taglist = array(); 665 foreach ($Product->tags as $tag) $taglist[] = $tag->name; 666 667 if ($Product->id && !empty($Product->images)) { 668 $ids = join(',',array_keys($Product->images)); 667 foreach ( $Product->tags as $tag ) 668 $taglist[] = $tag->name; 669 670 if ( $Product->id && ! empty($Product->images) ) { 671 $ids = join(',', array_keys($Product->images)); 669 672 $CoverImage = reset($Product->images); 670 673 $image_table = $CoverImage->_table; … … 673 676 674 677 $shiprates = shopp_setting('shipping_rates'); 675 if (!empty($shiprates)) ksort($shiprates); 678 if ( ! empty($shiprates) ) 679 ksort($shiprates); 676 680 677 681 $uploader = shopp_setting('uploader_pref'); 678 if ( !$uploader) $uploader = 'flash';679 680 $process = (!empty($Product->id)?$Product->id:'new');681 $_POST['action'] = add_query_arg(array_merge($_GET, array('page'=>$this->Admin->pagename('products'))),admin_url('admin.php'));682 if ( ! $uploader ) $uploader = 'flash'; 683 684 $process = empty($Product->id) ? 'new' : $Product->id; 685 $_POST['action'] = add_query_arg(array_merge($_GET, array('page' => $this->Admin->pagename('products'))), admin_url('admin.php')); 682 686 $post_type = ShoppProduct::posttype(); 683 687 684 // For inclusive taxes, add tax to base product price (so tax is part of the price)685 // This has to take place outside of ShoppProduct::pricing() so that the summary system686 // doesn't cache the results causing strange/unexpected price jumps687 // if ( shopp_setting_enabled('tax_inclusive') && ! Shopp::str_true($Product->excludetax) ) {688 // foreach ($Product->prices as &$price) {689 // if ( ! Shopp::str_true($price->tax) ) continue;690 //691 // $taxes = array();692 // $Tax = new ShoppTax();693 // $Tax->address(ShoppOrder()->Billing);694 // $Tax->rates($taxes, $Tax->item($Product));695 //696 // $price->price += ShoppTax::calculate($taxes, $price->price);697 // $price->saleprice += ShoppTax::calculate($taxes, $price->saleprice);698 // }699 // }700 701 688 do_action('add_meta_boxes', ShoppProduct::$posttype, $Product); 702 do_action('add_meta_boxes_' .ShoppProduct::$posttype, $Product);689 do_action('add_meta_boxes_' . ShoppProduct::$posttype, $Product); 703 690 704 691 do_action('do_meta_boxes', ShoppProduct::$posttype, 'normal', $Product); … … 706 693 do_action('do_meta_boxes', ShoppProduct::$posttype, 'side', $Product); 707 694 708 include (SHOPP_ADMIN_PATH."/products/editor.php");695 include $this->ui('editor.php'); 709 696 } 710 697 -
shopp/trunk/core/library/Core.php
r821385 r865739 1079 1079 'title','value'); 1080 1080 } 1081 $allowed = apply_filters( 'shopp_allowed_inputattrs', $allowed, $options ); 1081 1082 $string = ""; 1082 1083 $classes = ""; … … 2250 2251 * @return boolean True if Suhosin is dectected and has configuration issues 2251 2252 **/ 2252 function suhosin_warning () {2253 public static function suhosin_warning () { 2253 2254 2254 2255 return ( // Is Suhosin loaded or available? … … 2267 2268 } 2268 2269 2270 /** 2271 * Trim whitespace from the beggingin 2272 * 2273 * @author Jonathan Davis 2274 * @since 1.3 2275 * 2276 * @return void Description... 2277 **/ 2278 public function trim_deep ( $value ) { 2279 2280 if ( is_object($value) ) { 2281 $vars = get_object_vars( $value ); 2282 foreach ( $vars as $key => $data ) 2283 $value->{$key} = self::trim_deep( $data ); 2284 } elseif ( is_array($value) ) { 2285 $value = array_map(array(__CLASS__, 'trim_deep'), $value); 2286 } elseif ( is_string( $value ) ) { 2287 $value = trim($value); 2288 } 2289 2290 return $value; 2291 2292 } 2293 2269 2294 } // End abstract class ShoppCore 2270 2295 -
shopp/trunk/core/library/DB.php
r831831 r865739 655 655 return sDB::object(); 656 656 } 657 658 public static function instance () { 659 return sDB::object(); 660 } 657 661 658 662 } -
shopp/trunk/core/library/Email.php
r821385 r865739 83 83 84 84 static function FixSymbols ( $message ) { 85 $entities = htmlentities( $message, ENT_NOQUOTES | ENT_DISALLOWED, 'UTF-8', false ); // Translate HTML entities (special symbols) 85 if ( ! defined( 'ENT_DISALLOWED' ) ) define( 'ENT_DISALLOWED', 128 ); // ENT_DISALLOWED added in PHP 5.4 86 $entities = htmlentities( $message, ENT_NOQUOTES | ENT_DISALLOWED, 'UTF-8', false ); // Translate HTML entities (special symbols) 86 87 return htmlspecialchars_decode( $entities, ENT_NOQUOTES ); // Translate HTML tags back 87 88 } -
shopp/trunk/core/library/Loader.php
r831831 r865739 502 502 'shippingreport' => '/ui/reports/shipping.php', 503 503 'shippingsettingsui' => '/model/Shipping.php', 504 'shopp' => '/library/Shopp.php', 504 505 'shoppaccountdashboardpage' => '/flow/Pages.php', 505 506 'shoppaccountpage' => '/flow/Pages.php', -
shopp/trunk/core/library/Lookup.php
r821385 r865739 777 777 public static function payment_status_labels () { 778 778 $_ = array( 779 'PENDING' => __('Pending','Shopp'),780 'CHARGED' => __('Charged','Shopp'),781 'REFUNDED' => __('Refunded','Shopp'),782 'VOID' => __('Void','Shopp')783 ); 784 return apply_filters('shopp_payment_status_labels', $_);779 'PENDING' => Shopp::__('Pending'), 780 'CHARGED' => Shopp::__('Charged'), 781 'REFUNDED' => Shopp::__('Refunded'), 782 'VOID' => Shopp::__('Void') 783 ); 784 return apply_filters('shopp_payment_status_labels', $_); 785 785 } 786 786 787 787 public static function txnstatus_labels () { 788 788 $_ = array( 789 'review' => __('Review','Shopp'), 790 'purchase' => __('Purchase Order','Shopp'), 791 'invoiced' => __('Invoiced','Shopp'), 792 'authed' => __('Authorized','Shopp'), 793 'captured' => __('Paid','Shopp'), 794 'shipped' => __('Shipped','Shopp'), 795 'refunded' => __('Refunded','Shopp'), 796 'voided' => __('Void','Shopp'), 797 'closed' => __('Closed','Shopp') 798 ); 799 return apply_filters('shopp_txnstatus_labels',$_); 789 'review' => Shopp::__('Review'), 790 'purchase' => Shopp::__('Purchase Order'), 791 'invoiced' => Shopp::__('Invoiced'), 792 'authed' => Shopp::__('Authorized'), 793 'auth-failed' => Shopp::__('Declined'), 794 'captured' => Shopp::__('Paid'), 795 'shipped' => Shopp::__('Shipped'), 796 'refunded' => Shopp::__('Refunded'), 797 'voided' => Shopp::__('Void'), 798 'closed' => Shopp::__('Closed') 799 ); 800 return apply_filters('shopp_txnstatus_labels', $_); 800 801 } 801 802 -
shopp/trunk/core/library/Support.php
r831831 r865739 27 27 28 28 /** 29 * Checks for available updates30 *31 * @author Jonathan Davis32 * @since 1.133 *34 * @return array List of available updates35 **/36 public static function updates () {37 38 if ( ! wp_next_scheduled('shopp_check_updates') )39 wp_schedule_event(time(), 'twicedaily', 'shopp_check_updates');40 41 global $pagenow;42 if ( is_admin()43 && 'plugins.php' == $pagenow44 && isset($_GET['action'])45 && 'deactivate' == $_GET['action']) return array();46 47 $updates = new StdClass();48 if (function_exists('get_site_transient')) $plugin_updates = get_site_transient('update_plugins');49 else $plugin_updates = get_transient('update_plugins');50 51 switch ( current_filter() ) {52 case 'load-update-core.php': $timeout = 60; break; // 1 minute53 case 'load-plugins.php': // 1 hour54 case 'load-update.php': $timeout = 3600; break;55 default: $timeout = 43200; // 12 hours56 }57 58 $justchecked = isset( $plugin_updates->last_checked_shopp ) && $timeout > ( time() - $plugin_updates->last_checked_shopp );59 $changed = isset($plugin_updates->response[ SHOPP_PLUGINFILE ]);60 if ( $justchecked && ! $changed ) return;61 62 $Shopp = Shopp::object();63 $addons = array_merge(64 $Shopp->Gateways->checksums(),65 $Shopp->Shipping->checksums(),66 $Shopp->Storage->checksums()67 );68 69 $request = array('ShoppServerRequest' => 'update-check');70 /**71 * Update checks collect environment details for faster support service only,72 * none of it is linked to personally identifiable information.73 **/74 $data = array(75 'core' => ShoppVersion::release(),76 'addons' => join("-", $addons),77 'site' => get_bloginfo('url'),78 );79 80 if ( shopp_setting_enabled('support_data') ) {81 $optional = array(82 'wp' => get_bloginfo('version').(is_multisite()?' (multisite)':''),83 'mysql' => mysql_get_server_info(),84 'php' => phpversion(),85 'uploadmax' => ini_get('upload_max_filesize'),86 'postmax' => ini_get('post_max_size'),87 'memlimit' => ini_get('memory_limit'),88 'server' => $_SERVER['SERVER_SOFTWARE'],89 'agent' => $_SERVER['HTTP_USER_AGENT']90 );91 $data = array_merge($data, $optional);92 }93 94 $response = ShoppSupport::callhome($request, $data);95 96 if ($response == '-1') return; // Bad response, bail97 $response = unserialize($response);98 unset($updates->response);99 100 if ( isset($response->key) && ! Shopp::str_true($response->key) )101 delete_transient('shopp_activation');102 103 if ( isset($response->addons) ) {104 $updates->response[ SHOPP_PLUGINFILE . '/addons' ] = $response->addons;105 unset($response->addons);106 }107 108 if ( isset($response->id) )109 $updates->response[ SHOPP_PLUGINFILE ] = $response;110 111 if (isset($updates->response)) {112 shopp_set_setting('updates', $updates);113 114 // Add Shopp to the WP plugin update notification count115 if ( isset($updates->response[ SHOPP_PLUGINFILE ]) )116 $plugin_updates->response[ SHOPP_PLUGINFILE ] = $updates->response[ SHOPP_PLUGINFILE ];117 118 } else unset($plugin_updates->response[ SHOPP_PLUGINFILE ]); // No updates, remove Shopp from the plugin update count119 120 $plugin_updates->last_checked_shopp = time();121 if ( function_exists('set_site_transient') ) set_site_transient('update_plugins', $plugin_updates);122 else set_transient('update_plugins', $plugin_updates);123 124 return $updates;125 }126 127 /**128 29 * Loads the change log for an available update 129 30 * … … 161 62 if ( is_network_admin() || ! is_multisite() ) { 162 63 $wp_list_table = _get_list_table('WP_Plugins_List_Table'); 163 echo '<tr class="plugin-update-tr "><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';64 echo '<tr class="plugin-update-tr active"><th colspan="' . $wp_list_table->get_column_count() . '" class="check-column plugin-update colspanchange"><div class="update-message">'; 164 65 echo self::buykey(); 165 echo '<style type="text/css">#shopp th,#shopp td{border-bottom:0;}</style>'; 66 echo '<br class="clear" /><br /><style type="text/css">#shopp th,#shopp td{border-bottom:0;-webkit-box-shadow:none;box-shadow:none;} 67 #shopp+.plugin-update-tr .update-message {box-sizing:border-box;} #shopp+.plugin-update-tr .button {float:left; margin:20px 20px 0 0;} #shopp+.plugin-update-tr big { display:block; } #shopp+.plugin-update-tr .update-message::before {content:"";}</style>'; 166 68 echo '</div></td></tr>'; 167 69 } … … 238 140 239 141 $wp_list_table = _get_list_table('WP_Plugins_List_Table'); 240 echo '<tr class="plugin-update-tr"><t dcolspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';142 echo '<tr class="plugin-update-tr"><th colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">'; 241 143 Shopp::_emi( 242 144 'You're missing out on important updates! %1$s %2$s Buy a Shopp Support Key! %3$s', empty($updates) ? '' : join(' ', $updates), '<a href="' . ShoppSupport::STORE . '" class="button button-primary">', '</a>' … … 262 164 $url = add_query_arg('action', 'shopp_nonag', wp_nonce_url(admin_url('admin-ajax.php'), 'wp_ajax_shopp_nonag')); 263 165 $_ = array(); 264 $_[] = '<div id="shopp-activation-nag" class=" notice wp-core-ui">';166 $_[] = '<div id="shopp-activation-nag" class="update-nag">'; 265 167 266 168 $_[] = '<p class="dismiss shoppui-remove-sign alignright"></p>'; … … 276 178 277 179 public static function buykey () { 278 return Shopp::_mi(' You're missing out on **expert support**, **early access** to Shopp updates, and **one-click add-on updates**! Don't have a Shopp Support Key? %sBuy a Shopp Support Key!%s', '<a href="' . ShoppSupport::STORE . '" class="button button-primary" target="_blank">', '</a>');180 return Shopp::_mi('%s<big>Upgrade for Support</big>%s<big>You're missing out on **expert support**, **early access** to Shopp updates, and **one-click add-on updates**!</big>Don't have a Shopp Support Key? Support the project and get expert support, buy one today!', '<a href="' . ShoppSupport::STORE . '?utm_source=wpadmin-' . $_REQUEST['page'] . '&utm_medium=Shopp&utm_campaign=Plugin" class="button button-primary" target="_blank">', '</a>'); 279 181 } 280 182 -
shopp/trunk/core/library/Version.php
r831831 r865739 22 22 23 23 /** @type int PATCH The maintenance patch version number */ 24 const PATCH = 1;24 const PATCH = 2; 25 25 26 26 /** @type string PRERELEASE The prerelease designation (dev, beta, RC1) */ … … 28 28 29 29 /** @type string CODENAME The release project code name */ 30 const CODENAME = ' Deimos';30 const CODENAME = 'Phobos'; 31 31 32 32 /** @type int DB The database schema version */ -
shopp/trunk/core/model/Asset.php
r831831 r865739 261 261 $url = Shopp::url( '' != get_option('permalink_structure') ? trailingslashit($this->id) . $this->filename : $this->id, 'images' ); 262 262 263 // Get the current URI 264 $uri = $this->uri; 265 263 266 // Handle resize requests 264 267 $params = func_get_args(); … … 269 272 // Build the path to the cached copy of the file (if it exists) 270 273 $size = $this->cachefile( $request ); 271 $this->uri = "cache_{$size}_{$this->filename}"; 272 274 $uri = "cache_{$size}_{$this->filename}"; // Override the URI for the request 273 275 } 274 276 275 277 // Ask the engine if we have a direct URL 276 $direct_url = $this->engine()->direct($ this->uri);278 $direct_url = $this->engine()->direct($uri); 277 279 if ( false !== $direct_url ) return $direct_url; 278 280 279 281 if ( empty($request) ) return $url; 280 282 else return Shopp::add_query_string( $request, $url); 281 282 283 } 283 284 … … 633 634 if ( !class_exists('ListFramework') ) return; 634 635 636 /** 637 * ImageSetting 638 * 639 * Data model for handling image setting data 640 * 641 * @since 1.2 642 * @package shopp 643 **/ 635 644 class ImageSetting extends ShoppMetaObject { 636 645 637 static $qualities = array(100, 92,80,70,60);638 static $fittings = array('all', 'matte','crop','width','height');646 static $qualities = array(100, 92, 80, 70, 60); 647 static $fittings = array('all', 'matte', 'crop', 'width', 'height'); 639 648 640 649 public $width; … … 646 655 public $context = 'setting'; 647 656 public $type = 'image_setting'; 648 public $_xcols = array('width', 'height','fit','quality','sharpen','bg');649 650 public function __construct ( $id=false,$key='id') {657 public $_xcols = array('width', 'height', 'fit', 'quality', 'sharpen', 'bg'); 658 659 public function __construct ( $id = false, $key = 'id' ) { 651 660 $this->init(self::$table); 652 661 $this->load($id,$key); 653 662 } 654 663 664 /** 665 * Provides a translated list of image "fit" setting labels 666 * 667 * @since 1.2 668 * 669 * @return array List of translated settings labels 670 **/ 655 671 public function fit_menu () { 656 return array( __('All','Shopp'), 657 __('Fill','Shopp'), 658 __('Crop','Shopp'), 659 __('Width','Shopp'), 660 __('Height','Shopp') 672 return array( 673 Shopp::__('All'), 674 Shopp::__('Fill'), 675 Shopp::__('Crop'), 676 Shopp::__('Width'), 677 Shopp::__('Height') 661 678 ); 662 679 } 663 680 681 /** 682 * Provides a menu of readable image quality labels 683 * 684 * @since 1.3 685 * 686 * @return array List of quality labels 687 **/ 664 688 public function quality_menu () { 665 return array( __('Highest quality, largest file size','Shopp'), 666 __('Higher quality, larger file size','Shopp'), 667 __('Balanced quality & file size','Shopp'), 668 __('Lower quality, smaller file size','Shopp'), 669 __('Lowest quality, smallest file size','Shopp') 689 return array( 690 Shopp::__('Highest quality, largest file size'), 691 Shopp::__('Higher quality, larger file size'), 692 Shopp::__('Balanced quality & file size'), 693 Shopp::__('Lower quality, smaller file size'), 694 Shopp::__('Lowest quality, smallest file size') 670 695 ); 671 696 } 672 697 673 public function fit_value ($value) { 674 if (isset(self::$fittings[$value])) return self::$fittings[$value]; 698 /** 699 * Converts a numeric ImageSetting fit setting to a Theme API compatible option name 700 * 701 * @since 1.3 702 * 703 * @param integer $setting The numeric ImageSetting value 704 * @return string The option name 705 **/ 706 public function fit ( integer $setting ) { 707 if ( isset(self::$fittings[ $setting ]) ) 708 return self::$fittings[ $setting ]; 675 709 return self::$fittings[0]; 676 710 } 677 711 678 public function quality_value ($value) { 679 if (isset(self::$qualities[$value])) return self::$qualities[$value]; 712 /** 713 * Converts a numeric ImageSetting quality setting to a Theme API compatible option value 714 * 715 * @since 1.3 716 * 717 * @param integer $setting The numeric ImageSetting value 718 * @return integer The option value 719 **/ 720 public function quality ( integer $setting ) { 721 if ( isset(self::$qualities[ $setting ]) ) 722 return self::$qualities[ $setting ]; 680 723 return self::$qualities[2]; 681 724 } 682 725 683 public function options ($prefix='') { 726 /** 727 * Convert the ImageSetting values to a Theme API compatible array of image options 728 * 729 * @since 1.3 730 * 731 * @param string $prefix (optional) Prefix for the option keys 732 * @return array The image options 733 **/ 734 public function options ( $prefix = '' ) { 684 735 $settings = array(); 685 $properties = array('width', 'height','fit','quality','sharpen','bg');686 foreach ( $properties as $property) {736 $properties = array('width', 'height', 'fit', 'quality', 'sharpen', 'bg'); 737 foreach ( $properties as $property ) { 687 738 $value = $this->{$property}; 688 if ( 'quality' == $property) $value = $this->quality_value($this->{$property});689 if ( 'fit' == $property) $value = $this->fit_value($this->{$property});690 $settings[ $prefix.$property] = $value;739 if ( 'quality' == $property ) $value = $this->quality((int)$this->{$property}); 740 if ( 'fit' == $property ) $value = $this->fit((int)$this->{$property}); 741 $settings[ $prefix . $property ] = $value; 691 742 } 692 743 return $settings; … … 695 746 } // END class ImageSetting 696 747 748 /** 749 * Loads the collection of image settings 750 * 751 * @since 1.2 752 * @package shopp 753 **/ 697 754 class ImageSettings extends ListFramework { 698 755 699 private static $ instance;700 701 p ublicfunction __construct () {756 private static $object; 757 758 private function __construct () { 702 759 $ImageSetting = new ImageSetting(); 703 760 $table = $ImageSetting->_table; … … 706 763 "context='$ImageSetting->context'" 707 764 ); 708 $options = compact('table', 'where');765 $options = compact('table', 'where'); 709 766 $query = sDB::select($options); 710 $this->populate(sDB::query($query, 'array',array($ImageSetting,'loader'),false,'name'));767 $this->populate(sDB::query($query, 'array', array($ImageSetting, 'loader'), false, 'name')); 711 768 $this->found = sDB::found(); 712 769 } … … 735 792 * @return DB Returns a reference to the DB object 736 793 **/ 737 public static function &__instance () { 738 if (!self::$instance instanceof self) 739 self::$instance = new self; 740 return self::$instance; 741 } 742 794 public static function &object () { 795 if ( ! self::$object instanceof self ) 796 self::$object = new self; 797 return self::$object; 798 } 743 799 744 800 } // END class ImageSettings -
shopp/trunk/core/model/Cart.php
r831831 r865739 114 114 $commands = array('add', 'empty', 'update', 'remove'); 115 115 116 if ( isset($_REQUEST['empty']) ) 117 $_REQUEST['cart'] = 'empty'; 118 116 119 $request = isset($_REQUEST['cart']) ? strtolower($_REQUEST['cart']) : false; 117 120 … … 125 128 'item' => false, 126 129 'items' => array(), 127 'remove' => array() 130 'remove' => array(), 128 131 ); 129 132 $request = array_intersect_key($_REQUEST,$allowed); // Filter for allowed arguments … … 287 290 * 288 291 * @param int $quantity The quantity of the item to add to the cart 289 * @param ShoppProduct $Product Productobject to add to the cart290 * @param ShoppPrice$Price Price object to add to the cart292 * @param ShoppProduct|ShoppCartItem $Product Product object or cart item object to add to the cart 293 * @param mixed $Price Price object to add to the cart 291 294 * @param int $category The id of the category navigated to find the product 292 295 * @param array $data Any custom item data to carry through … … 294 297 **/ 295 298 public function additem ( $quantity = 1, &$Product, &$Price, $category = false, $data = array(), $addons = array() ) { 296 $NewItem = new ShoppCartItem($Product, $Price, $category, $data, $addons); 297 298 if ( ! $NewItem->valid() || ! $this->addable($NewItem) ) return false; 299 300 if ( 'ShoppCartItem' == get_class($Product) ) $NewItem = $Product; 301 else { 302 $NewItem = new ShoppCartItem($Product, $Price, $category, $data, $addons); 303 if ( ! $NewItem->valid() || ! $this->addable($NewItem) ) return false; 304 } 299 305 300 306 $id = $NewItem->fingerprint(); … … 625 631 $Discounts->credits(); 626 632 627 if ( $ Shipping->free() && $Totals->total('shipping') > 0 ) {633 if ( $Discounts->shipping() ) // If shipping discounts changed, recalculate shipping amount 628 634 $Totals->register( new OrderAmountShipping( array('id' => 'cart', 'amount' => $Shipping->calculate() ) ) ); 629 }630 635 631 636 do_action_ref_array('shopp_cart_retotal', array(&$Totals) ); -
shopp/trunk/core/model/Collection.php
r831831 r865739 70 70 'adjacent' => false, // 71 71 'product' => false, // 72 'load' => array( ), // Product data to load72 'load' => array('coverimages'), // Product data to load 73 73 'inventory' => false, // Flag for detecting inventory-based queries 74 74 'taxquery' => false, // Cross taxonomy queries … … 1467 1467 public $name = false; 1468 1468 public $loading = array(); 1469 protected $_options = array(); 1469 1470 1470 1471 public function __construct ( array $options = array() ) { 1472 1473 $this->taxonomy = self::$taxon; 1474 1475 $thisclass = get_class($this); 1476 $slugs = SmartCollection::slugs($thisclass); 1477 1478 $this->slug = $this->uri = $slugs[0]; 1479 1480 $this->name = call_user_func(array($thisclass, 'name')); 1481 $this->_options = $options; 1482 } 1483 1484 public static function name () { 1485 return Shopp::__('Collection'); 1486 } 1487 1488 public static function slugs ( string $class ) { 1489 return apply_filters( 'shopp_' . strtolower($class) . '_collection_slugs', get_class_property($class, 'slugs') ); 1490 } 1491 1492 public function load ( array $options = array() ) { 1493 $options = array_merge( $this->_options, $options ); 1494 $this->smart($options); 1471 1495 1472 1496 if ( isset($options['show']) ) … … 1476 1500 $this->loading['pagination'] = $options['pagination']; 1477 1501 1478 $this->taxonomy = self::$taxon;1479 1480 $thisclass = get_class($this);1481 $slugs = SmartCollection::slugs($thisclass);1482 1483 $this->slug = $this->uri = $slugs[0];1484 1485 $this->name = call_user_func(array($thisclass, 'name'));1486 }1487 1488 public static function name () {1489 return Shopp::__('Collection');1490 }1491 1492 public static function slugs ( string $class ) {1493 return apply_filters( 'shopp_' . strtolower($class) . '_collection_slugs', get_class_property($class, 'slugs') );1494 }1495 1496 public function load ( array $options = array() ) {1497 $this->smart($options);1498 1502 parent::load($this->loading); 1503 } 1504 1505 public static function defaultlinks ( $termlink, $term, $taxonomy ) { 1506 if ( false !== strpos($termlink, "taxonomy=" . self::$taxon) ) 1507 return home_url("?" . self::$taxon . "=$term->slug"); 1508 return $termlink; 1499 1509 } 1500 1510 … … 1755 1765 'groupby' => 'p.ID', 1756 1766 'orderby' => 'score DESC'); 1757 if ( ! empty($pricematch) ) $this->loading[ 'having'] = array($pricematch);1767 if ( ! empty($pricematch) ) $this->loading[ empty( $search )? 'where':'having' ] = array($pricematch); 1758 1768 if ( isset($options['show']) ) $this->loading['limit'] = $options['show']; 1759 1769 if ( isset($options['published']) ) $this->loading['published'] = $options['published']; -
shopp/trunk/core/model/Customer.php
r821385 r865739 287 287 extract((array)$Storefront->account); 288 288 289 if ( isset($id) )289 if ( ! empty($id) ) 290 290 $this->order($id); 291 291 … … 493 493 public function load_downloads () { 494 494 // Bail out if the downloads property is already populated or we can't load customer order data 495 if ( /*! empty($this->downloads) ||*/ ! ($purchases = shopp_customer_orders($this->id)) ) return; #Decomment before commit!495 if ( /*! empty($this->downloads) ||*/ ! ($purchases = shopp_customer_orders($this->id)) ) return; // Decomment before commit! 496 496 $this->downloads = array(); 497 497 498 498 foreach ( $purchases as $Purchase ) { 499 if ( ! in_array($Purchase->txnstatus, array('captured')) ) continue; 499 500 reset($Purchase->purchased); 500 501 $this->extract_downloads($Purchase->purchased); … … 502 503 } 503 504 504 protected function extract_downloads ($items) { 505 protected function extract_downloads ( $items ) { 506 507 $this->_filemap = array(); // Temporary property to hold the file mapping index 508 505 509 while ( list($index, $Purchased) = each($items) ) { 506 510 // Check for downloadable addons … … 514 518 // Is it a downloadable item? Do not add the same dkey twice 515 519 if ( empty($Purchased->download) ) continue; 520 521 // Load download file data 516 522 $this->downloads[ $Purchased->dkey ] = $Purchased; 517 } 523 $this->_filemap[ $Purchased->download ] = $Purchased->dkey; 524 } 525 526 $this->load_downloadfiles( array_keys($this->_filemap) ); 527 528 } 529 530 /** 531 * Loads the extra download file data for the loaded customer downloads 532 * 533 * @author Jonathan Davis 534 * @since 1.3.2 535 * 536 * @param array $downloads a list of download meta record ids to load 537 * @return void 538 **/ 539 public function load_downloadfiles ( array $downloads = array() ) { 540 541 if ( empty($downloads) ) return false; 542 543 $meta_table = ShoppDatabaseObject::tablename(ShoppMetaObject::$table); 544 sDB::query("SELECT * FROM $meta_table WHERE id IN (" . join(',', $downloads) . ")", 'array', array($this, 'download_loader')); 545 546 unset($this->_filemap); 547 } 548 549 /** 550 * Download record loader to map download file data to the loaded downloads for the customer 551 * 552 * @author Jonathan Davis 553 * @since 1.3.2 554 * 555 * @param array $records The records to map to (unused becase they are mapped to the Customer->downloads records) 556 * @param array $record The record data loaded from the query 557 * @return void 558 **/ 559 public function download_loader ( &$records, &$record ) { 560 561 // Lookup the download key 562 if ( empty($this->_filemap[ $record->id ]) ) return; 563 $dkey = $this->_filemap[ $record->id ]; 564 565 // Find the purchased download 566 if ( empty($this->downloads[ $dkey ]) ) return; 567 $Purchased = &$this->downloads[ $dkey ]; 568 569 // Unserialize the file data 570 $data = maybe_unserialize($record->value); 571 if ( is_object($data) ) $properties = get_object_vars($data); 572 else return; 573 574 // Map the file data to the purchased download record 575 foreach ( (array)$properties as $property => $value ) 576 $Purchased->$property = sDB::clean($value); 577 518 578 } 519 579 … … 743 803 } 744 804 } // END class CustomerXLSExport 745 746 /**747 * CustomerAccountPage class748 *749 * A property container for Shopp's customer account page meta750 *751 * @author Jonathan Davis752 * @since 1.1753 * @package customer754 **/755 class CustomerAccountPage {756 757 public $request = '';758 public $label = '';759 public $handler = false;760 761 public function __construct ( $request, $label, $handler ) {762 $this->request = $request;763 $this->label = $label;764 $this->handler = $handler;765 }766 767 } // END class CustomerAccountPage -
shopp/trunk/core/model/Discounts.php
r831831 r865739 29 29 private $request = false; // Current code request 30 30 private $credit = false; // Credit request types 31 32 /** 33 * Get or set the current request 34 * 35 * @author Jonathan Davis 36 * @since 1.3 37 * 38 * @param string $request The request string to set 39 * @return string The current request 40 **/ 41 public function request ( string $request = null ) { 42 43 if ( isset($request) ) $this->request = $request; 44 return $this->request; 45 46 } 47 48 public function credit ( string $request = null ) { 49 50 if ( isset($request) ) $this->credit = $request; 51 return $this->credit; 52 53 } 54 55 /** 56 * Handle parsing and routing discount code related requests 57 * 58 * @author Jonathan Davis 59 * @since 1.3 60 * 61 * @return void 62 **/ 63 public function requests () { 64 65 if ( isset($_REQUEST['discount']) && ! empty($_REQUEST['discount']) ) 66 $this->request( trim($_REQUEST['discount']) ); 67 elseif ( isset($_REQUEST['credit']) && ! empty($_REQUEST['credit']) ) 68 $this->credit( trim($_REQUEST['credit']) ); 69 70 if ( isset($_REQUEST['removecode']) && ! empty($_REQUEST['removecode']) ) 71 $this->undiscount(trim($_REQUEST['removecode'])); 72 73 } 31 private $shipping = false; // Track shipping discount changes 74 32 75 33 /** … … 116 74 } 117 75 118 public function credits () {119 $credits = array();120 121 $CartTotals = ShoppOrder()->Cart->Totals;122 123 // Wipe out any existing credit calculations124 $CartTotals->takeoff('discount', 'credit');125 $discounts = $CartTotals->total('discount'); // Resum the applied discounts (without credits)126 127 foreach ( $this as $Discount ) {128 if ( $Discount->type() != ShoppOrderDiscount::CREDIT ) continue;129 $Discount->calculate(); // Recalculate based on current total to apply an appropriate amount130 $credits[] = $Discount->amount();131 $CartTotals->register( new OrderAmountDiscount( array('id' => 'credit', 'amount' => array_sum($credits) ) ) );132 }133 134 $amount = array_sum($credits);135 136 return (float) $amount;137 }138 139 76 /** 140 77 * Match the promotions that apply to the order … … 154 91 // Match applied first 155 92 $Promotions->sort( array($this, 'sortapplied'), 'keys' ); 93 94 // Reset shipping flag to track changes 95 $this->shipping = false; 156 96 157 97 // Iterate over each promo to determine whether it applies … … 239 179 240 180 $this->add($Promo->id, $Discount); 181 $this->shipping($Discount); // Flag shipping changes 241 182 242 183 } … … 349 290 350 291 $Discount = $this->get($id); 292 $Discount->unapply(); 351 293 352 294 $_REQUEST['cart'] = true; 353 295 354 $this->remove($id); 296 $this->remove($Discount->id()); // Remove it from the discount stack if it is there 297 $this->shipping($Discount); // Flag shipping changes 355 298 356 299 if ( isset($this->codes[ $Discount->code() ]) ) { … … 371 314 **/ 372 315 private function reset ( ShoppOrderPromo $Promo ) { 373 374 $this->remove($Promo->id); // Remove it from the discount stack if it is there 375 316 $this->undiscount((int)$Promo->id); 376 317 } 377 318 … … 398 339 399 340 return false; 341 } 342 343 /** 344 * Get or set the current request 345 * 346 * @author Jonathan Davis 347 * @since 1.3 348 * 349 * @param string $request The request string to set 350 * @return string The current request 351 **/ 352 public function request ( string $request = null ) { 353 354 if ( isset($request) ) $this->request = $request; 355 return $this->request; 356 357 } 358 359 public function credit ( string $request = null ) { 360 361 if ( isset($request) ) $this->credit = $request; 362 return $this->credit; 363 364 } 365 366 /** 367 * Handle parsing and routing discount code related requests 368 * 369 * @author Jonathan Davis 370 * @since 1.3 371 * 372 * @return void 373 **/ 374 public function requests () { 375 376 if ( isset($_REQUEST['discount']) && ! empty($_REQUEST['discount']) ) 377 $this->request( trim($_REQUEST['discount']) ); 378 elseif ( isset($_REQUEST['credit']) && ! empty($_REQUEST['credit']) ) 379 $this->credit( trim($_REQUEST['credit']) ); 380 381 if ( isset($_REQUEST['removecode']) && ! empty($_REQUEST['removecode']) ) 382 $this->undiscount(trim($_REQUEST['removecode'])); 383 384 } 385 386 /** 387 * Applies credits to the order discounts register 388 * 389 * @author Jonathan Davis 390 * @since 1.3 391 * 392 * @return float The total amount credited 393 **/ 394 public function credits () { 395 $credits = array(); 396 397 $CartTotals = ShoppOrder()->Cart->Totals; 398 399 // Wipe out any existing credit calculations 400 $CartTotals->takeoff('discount', 'credit'); 401 $discounts = $CartTotals->total('discount'); // Resum the applied discounts (without credits) 402 403 foreach ( $this as $Discount ) { 404 if ( $Discount->type() != ShoppOrderDiscount::CREDIT ) continue; 405 $Discount->calculate(); // Recalculate based on current total to apply an appropriate amount 406 $credits[] = $Discount->amount(); 407 } 408 409 $amount = array_sum($credits); 410 if ( $amount > 0 ) 411 $CartTotals->register( new OrderAmountDiscount( array('id' => 'credit', 'amount' => $amount ) ) ); 412 413 return (float) $amount; 414 } 415 416 417 /** 418 * Report shipping discount changes 419 * 420 * @author Jonathan Davis 421 * @since 1.3.2 422 * 423 * @param ShoppOrderDiscount $Discount (optional) The applied or unapplied discount to check for shipping changes 424 * @return boolean True if shipping discounts changed, false otherwise 425 **/ 426 public function shipping ( ShoppOrderDiscount $Discount = null ) { 427 428 if ( isset($Discount) && ShoppOrderDiscount::SHIP_FREE == $Discount->type() ) 429 $this->shipping = true; 430 431 return $this->shipping; 400 432 } 401 433 … … 568 600 569 601 case 'discounts applied': return ShoppOrder()->Discounts->count(); 570 case 'total quantity': return $Cart-> Totals->total('quantity');571 case 'shipping amount': return $Cart-> Totals->total('shipping');572 case 'subtotal amount': return $Cart-> Totals->total('order');602 case 'total quantity': return $Cart->total('quantity'); 603 case 'shipping amount': return $Cart->total('shipping'); 604 case 'subtotal amount': return $Cart->total('order'); 573 605 case 'customer type': return ShoppOrder()->Customer->type; 574 606 case 'ship-to country': return ShoppOrder()->Shipping->country; … … 697 729 698 730 // Numeric operations 699 case 'is greater than': return (Shopp::floatval($subject, false) > Shopp::floatval($value,false));700 case 'is greater than or equal to': return (Shopp::floatval($subject, false) >= Shopp::floatval($value,false));701 case 'is less than': return (Shopp::floatval($subject, false) < Shopp::floatval($value,false));702 case ' Is less than or equal to': return (Shopp::floatval($subject,false) <= Shopp::floatval($value,false));731 case 'is greater than': return (Shopp::floatval($subject, false) > Shopp::floatval($value, false)); 732 case 'is greater than or equal to': return (Shopp::floatval($subject, false) >= Shopp::floatval($value, false)); 733 case 'is less than': return (Shopp::floatval($subject, false) < Shopp::floatval($value, false)); 734 case 'is less than or equal to': return (Shopp::floatval($subject, false) <= Shopp::floatval($value, false)); 703 735 } 704 736 … … 860 892 **/ 861 893 public function applies () { 862 $applies = ( $this->amount() > 0 || ( $this->amount() == 0 && $this->shipfree() ) );894 $applies = ( $this->amount() > 0 || ( $this->amount() == 0 && $this->shipfree() ) || count($this->items) > 0 ); 863 895 return apply_filters('shopp_discount_applies', $applies, $this ); 864 896 } … … 1087 1119 case self::PERCENT_OFF: $amount = $Item->unitprice * ($this->discount() / 100); break; 1088 1120 case self::AMOUNT_OFF: $amount = $this->discount(); break; 1089 case self::SHIP_FREE: $Item->freeshipping = true; $ amount = 0; break;1121 case self::SHIP_FREE: $Item->freeshipping = true; $this->shipping = true; $amount = 0; break; 1090 1122 case self::BOGOF: 1091 1123 list($buy, $get) = $this->discount(); … … 1120 1152 public function hasitem ( string $key ) { 1121 1153 return isset($this->items[ $key ]); 1154 } 1155 1156 /** 1157 * Unapply the discount 1158 * 1159 * This primarily involves resetting the Cart Item->freeshipping property. 1160 * 1161 * @author Jonathan Davis 1162 * @since 1.3 1163 * 1164 * @return void Description... 1165 **/ 1166 public function unapply () { 1167 $Cart = ShoppOrder()->Cart; 1168 1169 if ( self::SHIP_FREE == $this->type ) { 1170 $Shiprates = ShoppOrder()->Shiprates; 1171 foreach ( $this->items as $id => $item ) { 1172 $CartItem = $Cart->get($id); 1173 $CartItem->freeshipping = false; 1174 } 1175 } 1176 1122 1177 } 1123 1178 … … 1133 1188 class ShoppPurchaseDiscount { 1134 1189 1135 public $id = false; // The originating promotion object id1136 public $name = ''; // The name of the promotion1137 public $amount = 0.00; // The total amount of the discount1138 public $type = ShoppOrderDiscount::AMOUNT_OFF; // The discount type1139 public $target = ShoppOrderDiscount::ORDER; // The discount target1140 public $discount = false; // The calculated discount amount (float or array for BOGOFs)1141 public $code = false; // The code associated with the discount1142 public $shipfree = false; // A flag for free shipping1190 public $id = false; // The originating promotion object id 1191 public $name = ''; // The name of the promotion 1192 public $amount = 0.00; // The total amount of the discount 1193 public $type = ShoppOrderDiscount::AMOUNT_OFF; // The discount type 1194 public $target = ShoppOrderDiscount::ORDER; // The discount target 1195 public $discount = false; // The calculated discount amount (float or array for BOGOFs) 1196 public $code = false; // The code associated with the discount 1197 public $shipfree = false; // A flag for free shipping 1143 1198 1144 1199 public function __construct ( ShoppOrderDiscount $Discount ) { -
shopp/trunk/core/model/Gateway.php
r821385 r865739 345 345 public function amount ( $amount, array $format = array() ) { 346 346 347 $register = false; 348 347 349 if ( is_string($amount) ) { 350 $register = $amount; 348 351 $Cart = ShoppOrder()->Cart; 349 352 $amount = $Cart->total($amount); 353 if ( false === $amount ) $register = false; 350 354 } elseif ( ! ( is_int($amount) || is_float($amount) ) ) return $amount; 351 355 … … 358 362 extract($format); 359 363 364 if ( ! empty($register) ) // Allow targeting specific amounts for filtering 365 $amount = apply_filters("shopp_gateway_{$register}_amount", $amount); 366 360 367 $amount = apply_filters('shopp_gateway_amount', abs($amount)); 368 361 369 return number_format($amount, $precision, $decimals, $thousands); 370 } 371 372 /** 373 * Zeros out tax amounts when tax inclusive is enabled 374 * 375 * Prevents inclusive-tax unaware payment systems (such as PayPal Standard) 376 * from adding extra taxes to the order 377 * 378 * @author Jonathan Davis 379 * @since 1.3.2 380 * 381 * @param float $amount The tax amount to filter 382 * @return float The correct amount 383 **/ 384 public function notaxinclusive ( $amount ) { 385 if ( shopp_setting_enabled('tax_inclusive') ) return 0.0; 386 else return $amount; 362 387 } 363 388 -
shopp/trunk/core/model/Item.php
r831831 r865739 79 79 * @return void 80 80 **/ 81 public function __construct ( $Product, $pricing, $category = false, $data = array(), $addons = array() ) { 81 public function __construct ( ShoppProduct $Product = null, $pricing = null, $category = false, array $data = array(), array $addons = array() ) { 82 82 83 $args = func_get_args(); 83 84 if ( empty($args) ) return; … … 86 87 else $this->load($Product, $pricing, $category, $data, $addons); 87 88 88 // $this->__wakeup(); 89 // $this->rediscount(); 90 // $this->totals(); 91 92 } 93 94 // public function __wakeup () { 95 // add_action('shopp_cart_item_totals', array($this, 'rediscount')); 96 // add_action('shopp_cart_item_totals', array($this, 'totals')); 97 // } 98 99 /** 100 * load 101 * 102 * loads/constructs the Item object from parameters 103 * 104 * @author John Dillick 89 } 90 91 /** 92 * Loads or constructs the Item object from product and product pricing parameters 93 * 94 * @author John Dillick, Jonathan Davis 105 95 * @since 1.2 106 96 * … … 120 110 if ( ! isset($Product->pricekey[ $optionkey ]) ) $optionkey = $Product->optionkey($pricing, true); // deprecated prime 121 111 if ( isset($Product->pricekey[ $optionkey ]) ) $Price = $Product->pricekey[ $optionkey ]; 122 } elseif ( $pricing) {112 } elseif ( is_numeric($pricing) ) { 123 113 $Price = $Product->priceid[ $pricing ]; 114 } elseif ( is_a($pricing, 'ShoppPrice') ) { 115 $Price = $pricing; 124 116 } 125 117 … … 254 246 } 255 247 248 /** 249 * Loads or constructs item properties from a purchased product 250 * 251 * @author Jonathan Davis 252 * @since 1.3 253 * 254 * @return void 255 **/ 256 256 public function load_purchased ( $Purchased ) { 257 257 … … 281 281 // no product or no price specified 282 282 if ( ! $this->product || ! $this->priceline ) { 283 new ShoppError(__('The product could not be added to the cart because it could not be found.','Shopp'), 'cart_item_invalid',SHOPP_ERR);283 new ShoppError(__('The product could not be added to the cart because it could not be found.','Shopp'), 'cart_item_invalid', SHOPP_ERR); 284 284 return false; 285 285 } … … 287 287 // the item is not in stock 288 288 if ( ! $this->instock() ) { 289 new ShoppError(__('The product could not be added to the cart because it is not in stock.','Shopp'), 'cart_item_invalid',SHOPP_ERR);289 new ShoppError(__('The product could not be added to the cart because it is not in stock.','Shopp'), 'cart_item_invalid', SHOPP_ERR); 290 290 return false; 291 291 } … … 303 303 public function fingerprint () { 304 304 $_ = $this->product.$this->priceline; 305 if ( empty($_) ) $_ = $this->name; 306 if ( empty($_) ) $_ = mktime(); 305 307 if ( ! empty($this->addons) ) $_ .= serialize($this->addons); 306 308 if ( ! empty($this->data) ) $_ .= serialize($this->data); 307 return __CLASS__ . '_' . hash('crc32', $_);309 return __CLASS__ . '_' . hash('crc32', $_); 308 310 } 309 311 -
shopp/trunk/core/model/Meta.php
r821385 r865739 36 36 * @return void 37 37 **/ 38 function __construct ( $id=false,$key='id') {38 function __construct ( $id = false, $key = 'id' ) { 39 39 $this->init(self::$table); 40 if (!$id) return; 41 if (is_array($id)) $this->load($id); 42 else $this->load(array($key=>$id,'type'=>$this->type)); 43 44 if (!empty($this->id) && !empty($this->_xcols)) 40 if ( ! $id ) return; 41 42 if ( is_array($id) ) 43 $this->load($id); 44 else $this->load(array($key => $id, 'type' => $this->type)); 45 46 if ( ! empty($this->id) && ! empty($this->_xcols) ) 45 47 $this->expopulate(); 46 48 } … … 55 57 **/ 56 58 function expopulate () { 57 if ( !is_object($this->value)) return;59 if ( ! is_object($this->value) ) return; 58 60 $properties = $this->value; 59 61 $this->copydata($properties); -
shopp/trunk/core/model/Payments.php
r821385 r865739 134 134 $this->rewind(); 135 135 $selected = $this->key(); 136 137 if ( empty($selected) ) return false; 136 138 137 139 return $this->selected($selected); -
shopp/trunk/core/model/Product.php
r831831 r865739 16 16 17 17 class ShoppProduct extends WPShoppObject { 18 18 19 static $table = 'posts'; 19 20 static $_taxonomies = array( … … 64 65 ); 65 66 67 // Keep track of data load efforts 68 protected $_loaded = array(); 69 66 70 /** 67 71 * Product constructor … … 72 76 * @return void 73 77 **/ 74 public function __construct ( $id=false,$key='ID') {75 if ( isset($this->_map[$key])) $key = $this->_map[$key];76 $this->init(self::$table, $key);78 public function __construct ( $id = false, $key = 'ID' ) { 79 if ( isset($this->_map[ $key ]) ) $key = $this->_map[ $key ]; 80 $this->init(self::$table, $key); 77 81 $this->type = self::$posttype; 78 $this->load($id, $key);82 $this->load($id, $key); 79 83 } 80 84 … … 111 115 public static function labels () { 112 116 return apply_filters( 'shopp_product_labels', array( 113 'name' => __('Products', 'Shopp'),114 'singular_name' => __('Product', 'Shopp'),115 'edit_item' => __('Edit Product', 'Shopp'),116 'new_item' => __('New Product', 'Shopp')117 'name' => __('Products', 'Shopp'), 118 'singular_name' => __('Product', 'Shopp'), 119 'edit_item' => __('Edit Product', 'Shopp'), 120 'new_item' => __('New Product', 'Shopp') 117 121 )); 118 122 } … … 141 145 * @return void 142 146 **/ 143 public function load_data ( $options=array('prices','specs','images','categories','tags','meta','summary'),&$products=array()) {147 public function load_data ( array $options = array('prices', 'specs', 'images', 'categories', 'tags', 'meta', 'summary'), array &$products = array() ) { 144 148 // Load summary before prices to ensure summary can be overridden by fresh pricing aggregation 145 149 $loaders = array( 146 // 'name' 'callback_method'147 'summary' => 'load_summary',148 'meta' => 'load_meta',149 'prices' => 'load_prices',150 'specs' => 'load_meta',151 'images' => 'load_meta',152 'coverimages' => 'load_coverimages',153 'categories' => 'load_taxonomies',154 'tags' => 'load_taxonomies'150 // 'name' 'callback_method' 151 'summary' => 'load_summary', 152 'meta' => 'load_meta', 153 'prices' => 'load_prices', 154 'specs' => 'load_meta', 155 'images' => 'load_meta', 156 'coverimages' => 'load_coverimages', 157 'categories' => 'load_taxonomies', 158 'tags' => 'load_taxonomies' 155 159 156 160 ); 157 158 $options = array_map('strtolower',$options); 159 $load = array_flip(array_intersect($options,array_keys($loaders))); 160 $loadcalls = array_unique(array_values(array_intersect_key($loaders,$load))); 161 162 if (!empty($products) ) { 163 $ids = join(',',array_keys($products)); 161 // allow case-insensitive options 162 $options = array_map('strtolower', $options); 163 164 // prevent loading data sets already requested and processed 165 $options = array_diff($options, $this->_loaded); 166 167 // Only allow white-listed load operations 168 $load = array_flip(array_intersect($options, array_keys($loaders))); 169 170 // Convert load requests to loading callbacks while preventing duplicate calls 171 $loadcalls = array_unique(array_values(array_intersect_key($loaders, $load))); 172 173 if ( ! empty($products) ) { // Handle loading data across a collection of products 174 $ids = join(',', array_keys($products)); 164 175 $this->products = &$products; 165 } else $ids = $this->id; 176 foreach ( $products as $product ) 177 $product->_loaded = array_merge($product->_loaded, $options); 178 } else { // Handle loading data for a single product 179 $ids = $this->id; 180 $this->_loaded = array_unique(array_merge($this->_loaded, $options)); 181 } 166 182 167 183 if ( empty($ids) ) return; 168 foreach ($loadcalls as $loadmethod) { 184 185 foreach ( $loadcalls as $loadmethod ) 169 186 if ( method_exists($this, $loadmethod) ) 170 call_user_func_array(array($this,$loadmethod),array($ids)); 171 } 187 call_user_func_array(array($this, $loadmethod), array($ids)); 172 188 173 189 } … … 202 218 203 219 // Reset summary properties for correct price range and stock sums in single product (product page) loading contexts 204 if ( ! empty($this->id) && $this->id == $ids && empty($this->checksum)) {220 if (!empty($this->id) && $this->id == $ids) { 205 221 $this->load_summary($ids); 206 222 $this->resum(); … … 398 414 public function metasetloader ( &$records, &$record, $id = 'id', $property = false, $collate = true, $merge = false ) { 399 415 400 if ( isset($this->products) && !empty($this->products)) $products = &$this->products;416 if ( isset($this->products) && ! empty($this->products) ) $products = &$this->products; 401 417 else $products = array(); 402 418 … … 436 452 } 437 453 438 if ( 'images' == $property) {454 if ( 'images' == $property ) { 439 455 // Prevent double-loading images (can occur when images are specifically loaded, then all meta is generically loaded) 440 if ( isset($target->$property) && isset($target->{$property}[$record->id])) return;456 if ( isset($target->$property) && isset($target->{$property}[ $record->id ]) ) return; 441 457 $collate = 'id'; 442 } 443 444 if ('specs' == $property) { 458 // Prevent extra image queries since we already tried 459 } 460 461 if ( 'specs' == $property ) { 445 462 $property = 'specnames'; 446 463 parent::metaloader($records, $record, $products, $id, $property, $collate, $merge); … … 577 594 } 578 595 596 $price->_sale = $price->sale; // Keep a copy of the price record "sale" setting {@see issue #2797} 579 597 if ($price->promoprice < $price->price) $target->sale = $price->sale = 'on'; 580 598 … … 1110 1128 if ( ! isset($term->taxonomy) || empty($term->taxonomy) ) continue; // Skip invalid entries 1111 1129 1112 if (!isset($terms[$term->taxonomy])) $terms[$term->taxonomy] = array(); 1113 $terms[$term->taxonomy][] = (int)$term->term_id; 1130 if ( ! isset($terms[ $term->taxonomy ]) ) 1131 $terms[ $term->taxonomy ] = array(); 1132 $terms[ $term->taxonomy ][] = (int)$term->term_id; 1114 1133 } 1115 1134 foreach ($terms as $taxonomy => $termlist) … … 1117 1136 1118 1137 $metadata = array('specs','images','settings','meta'); 1119 foreach ( $metadata as $metaset) {1138 foreach ( $metadata as $metaset ) { 1120 1139 if ( ! is_array($this->$metaset) ) continue; 1121 foreach ( $this->$metaset as $metaobjects) {1140 foreach ( $this->$metaset as $metaobjects ) { 1122 1141 if ( ! is_array($metaobjects) ) $metaobjects = array($metaobjects); 1123 1142 foreach ( $metaobjects as $meta ) { … … 1130 1149 } 1131 1150 } 1151 1152 // Duplicate summary (primarily for summary settings data) 1153 $Summary = new ProductSummary($original); 1154 $Summary->product = $this->id; 1155 $Summary->save(); 1132 1156 1133 1157 // Re-summarize product pricing -
shopp/trunk/core/model/Promotion.php
r831831 r865739 132 132 133 133 $table = ShoppDatabaseObject::tablename(ShoppPrice::$table); 134 echo "SELECT id,product,discounts,FIND_IN_SET($this->id,discounts) AS offset FROM $table WHERE id IN ('" . join(',', $pricetags) . "')"; 134 135 $discounted = sDB::query("SELECT id,product,discounts,FIND_IN_SET($this->id,discounts) AS offset FROM $table WHERE id IN ('" . join(',', $pricetags) . "')", 'array'); 135 136 … … 139 140 $promos = explode(',', $pricetag->discounts); 140 141 array_splice($promos, ($pricetag->offset - 1), 1); // Remove the located promotion ID from the discounts list 142 echo "UPDATE $table SET discounts='" . join(',', $promos) . "' WHERE id=$pricetag->id"; 141 143 sDB::query("UPDATE $table SET discounts='" . join(',', $promos) . "' WHERE id=$pricetag->id"); 142 144 } … … 144 146 // Force resum on products next load 145 147 $summary = ShoppDatabaseObject::tablename('summary'); 146 sDB::query("UPDATE $summary SET modified='" . ProductSummary::$_updates . "' WHERE product IN (" . join(',', $products). ")"); 148 echo "UPDATE $summary SET modified='" . ProductSummary::RECALCULATE . "' WHERE product IN (" . join(',', $products). ")"; 149 sDB::query("UPDATE $summary SET modified='" . ProductSummary::RECALCULATE . "' WHERE product IN (" . join(',', $products). ")"); 147 150 } 148 151 -
shopp/trunk/core/model/Purchase.php
r831831 r865739 253 253 **/ 254 254 public function isrefunded () { 255 if ( empty($this->events)) $this->load_events();256 return ( $this->refunded == $this->captured);255 if ( empty($this->events) ) $this->load_events(); 256 return ( $this->refunded == $this->captured ); 257 257 } 258 258 … … 266 266 **/ 267 267 public function isvoid () { 268 if ( empty($this->events)) $this->load_events();268 if ( empty($this->events) ) $this->load_events(); 269 269 return ($this->voided > 0 && $this->voided >= $this->invoiced); 270 270 } … … 285 285 286 286 public function capturable () { 287 if ( !$this->authorized) return 0.0;287 if ( ! $this->authorized ) return 0.0; 288 288 return ($this->authorized - (float)$this->captured); 289 289 } … … 471 471 sprintf(__('Order #%s: %s', 'Shopp'), $Purchase->id, $Event->label()), // Subject 472 472 "email-merchant-$Event->name.php") // Template 473 ) );473 ), $Event); 474 474 475 475 // Event-specific hook for event specific email messages 476 $messages = apply_filters('shopp_' . $Event->name . '_order_event_emails', $messages );476 $messages = apply_filters('shopp_' . $Event->name . '_order_event_emails', $messages, $Event); 477 477 478 478 foreach ( $messages as $name => $message ) { … … 820 820 case "discount": 821 821 $meta_table = ShoppDatabaseObject::tablename(ShoppMetaObject::$table); 822 $joins[ $meta_table ] = "INNER JOIN $meta_table AS discounts ON discounts.parent = o.id ";823 $search[] = "discounts.value LIKE '%$keyword%' AND discounts.context='purchase' AND discounts.name='discounts'"; break;822 $joins[ $meta_table ] = "INNER JOIN $meta_table AS discounts ON discounts.parent = o.id AND discounts.name='discounts' AND discounts.context='purchase'"; 823 $search[] = "discounts.value LIKE '%$keyword%'"; break; 824 824 } 825 825 } … … 838 838 $offset = ($this->set * $this->limit); 839 839 840 $c = 0; $columns = array(); $purchasedcols = false; 840 $c = 0; $columns = array(); $purchasedcols = false; $discountcols = false; 841 841 foreach ( $this->selected as $column ) { 842 842 $columns[] = "$column AS col".$c++; 843 843 if ( false !== strpos($column, 'p.') ) $purchasedcols = true; 844 if ( false !== strpos($column, 'discounts') ) $discountcols = true; 844 845 } 845 846 if ( $purchasedcols ) $FROM = "FROM $purchasedtable AS p INNER JOIN $purchasetable AS o ON o.id=p.purchase"; 846 847 else $FROM = "FROM $purchasetable AS o"; 848 849 if ( $discountcols ) { 850 $meta_table = ShoppDatabaseObject::tablename(ShoppMetaObject::$table); 851 $joins[ $meta_table ] = "INNER JOIN $meta_table AS discounts ON discounts.parent = o.id AND discounts.name='discounts' AND discounts.context='purchase'"; 852 } 847 853 848 854 $joins = join(' ', $joins); -
shopp/trunk/core/model/Settings.php
r831831 r865739 35 35 * the unavailable flag is set. 36 36 * 37 * @author Jonathan Davis38 37 * @since 1.0 39 38 * @version 1.1 … … 63 62 * Update the availability status of the settings database table 64 63 * 65 * @author Jonathan Davis66 64 * @since 1.1 67 65 * … … 75 73 * Load settings from the database 76 74 * 77 * @author Jonathan Davis78 75 * @since 1.0 79 76 * … … 108 105 * Add a new setting to the registry and store it in the database 109 106 * 110 * @author Jonathan Davis111 107 * @since 1.0 112 108 * … … 131 127 * Updates the setting in the registry and the database 132 128 * 133 * @author Jonathan Davis134 129 * @since 1.0 135 130 * … … 161 156 * Save a setting to the database 162 157 * 163 * @author Jonathan Davis164 158 * @since 1.0 165 159 * … … 181 175 * Save a setting to the database if it does not already exist 182 176 * 183 * @author Jonathan Davis184 177 * @since 1.1 185 178 * … … 195 188 * Remove a setting from the registry and the database 196 189 * 197 * @author Jonathan Davis198 190 * @since 1.0 199 191 * … … 221 213 * loading it directly from the database. 222 214 * 223 * @author Jonathan Davis224 215 * @since 1.0 225 216 * … … 252 243 * Restores a serialized value to a runtime object/structure 253 244 * 254 * @author Jonathan Davis255 245 * @since 1.0 256 246 * … … 261 251 if ( ! is_string($value) ) return $value; 262 252 // Return unserialized, if serialized value 263 if ( is_serialized($value) ) {264 $restored = unserialize($value);265 if ( empty($restored) ) $restored = unserialize( stripslashes($value) );253 if ( sDB::serialized($value) ) { 254 $restored = @unserialize($value); 255 if ( empty($restored) ) $restored = @unserialize( stripslashes($value) ); 266 256 if ( false !== $restored ) return $restored; 267 257 } … … 272 262 * Provides a blank setting object template 273 263 * 274 * @author Jonathan Davis275 264 * @since 1.0 276 265 * … … 294 283 * Automatically collect and save settings from a POST form 295 284 * 296 * @author Jonathan Davis297 285 * @since 1.0 298 286 * … … 301 289 public function saveform () { 302 290 if ( empty($_POST['settings']) || ! is_array($_POST['settings']) ) return false; 303 foreach ( $_POST['settings'] as $setting => $value ) 304 $this->save($setting, stripslashes_deep($value)); 291 292 $settings = stripslashes_deep($_POST['settings']); 293 $settings = Shopp::trim_deep($settings); 294 295 foreach ( $settings as $setting => $value ) 296 $this->save($setting, $value); 297 305 298 } 306 299 … … 311 304 * also checks the legacy 312 305 * 313 * @author Jonathan Davis314 306 * @since 1.3 315 307 * … … 328 320 // Try again using the legacy table 329 321 if ( false === $version && false === $legacy ) $version = self::dbversion('legacy'); 322 elseif ( false !== $legacy ) { // No version in the legacy settings table, possible 1.0 install? 323 // Look in the old settings table for the old Shopp version setting 324 $shopp_version = sDB::query("SELECT value FROM $table WHERE name='version' ORDER BY id DESC LIMIT 1", 'object', 'col'); 325 // Use (int) 1 to indicate Shopp 1.0 installed and avoid the install process 326 if ( version_compare($shopp_version, '1.1', '<') ) $version = 1; 327 } 330 328 331 329 if ( false === $version ) ShoppSettings()->registry['db_version'] = null; … … 335 333 } 336 334 335 337 336 } // END class Settings -
shopp/trunk/core/model/Shiprates.php
r831831 r865739 257 257 258 258 foreach ( $this->shippable as $id => $free ) { 259 if ( $free ) continue;260 259 261 260 $CartItem = shopp_cart_item($id); … … 263 262 264 263 $Item = new ShoppShippableItem( $CartItem ); 264 $this->item($Item); 265 265 do_action_ref_array('shopp_calculate_item_shipping', array($id, &$Item)); 266 266 } … … 472 472 if ( ! $this->shippable ) return false; 473 473 474 $this->id = $Item->fingerprint();475 $this->quantity =$Item->quantity;476 $this->fees =$Item->shipfee;477 $this->weight =$Item->weight;478 $this->length =$Item->length;479 $this->width =$Item->width;480 $this->height =$Item->height;481 $this->shipsfree = $Item->freeshipping;474 $this->id = $Item->fingerprint(); 475 $this->quantity =& $Item->quantity; 476 $this->fees =& $Item->shipfee; 477 $this->weight =& $Item->weight; 478 $this->length =& $Item->length; 479 $this->width =& $Item->width; 480 $this->height =& $Item->height; 481 $this->shipsfree =& $Item->freeshipping; 482 482 } 483 483 -
shopp/trunk/core/model/Tax.php
r831831 r865739 218 218 * @author Jonathan Davis 219 219 * @since 1.3 220 * @deprecated Use ShoppTax->location() 220 221 * 221 222 * @param BillingAddress $Billing The billing address … … 225 226 **/ 226 227 public function address ( BillingAddress $Billing, ShippingAddress $Shipping = null, $shipped = false ) { 227 228 228 $Address = $Billing; 229 229 if ( $shipped && null !== $Shipping || shopp_setting_enabled('tax_destination') ) // @todo add setting for "Apply tax to the shipping address" … … 238 238 239 239 $this->address = array_merge(apply_filters('shopp_taxable_address', compact('country','zone','locale'))); 240 241 return $this->address; 242 } 243 244 245 246 /** 247 * Sets the taxable location (address) for matching tax rates 248 * 249 * @author Jonathan Davis 250 * @since 1.3.2 251 * 252 * @param string $country The country code 253 * @param string $state The state name or code 254 * @param string $locale (optional) The locale name 255 * @return array An associative array containing the country, zone and locale 256 **/ 257 public function location ( string $country = null, string $state = null, string $locale = null ) { 258 259 $address = apply_filters('shopp_taxable_address', array( 260 'country' => $country, 261 'zone' => $state, 262 'locale' => $locale 263 )); 264 265 $this->address = array_merge($this->address, array_filter($address)); 240 266 241 267 return $this->address; -
shopp/trunk/core/ui/behaviors/catalog.js
r821385 r865739 395 395 396 396 if (input.hasClass('email') && !input.val().match( // RFC822 & RFC5322 Email validation 397 new RegExp(/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.( aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i)))397 new RegExp(/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.([a-z][a-z0-9]+)|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i))) 398 398 error = new Array($cv.email,field); 399 399 -
shopp/trunk/core/ui/behaviors/priceline.js
r821385 r865739 501 501 _.Shipped = function (data) { 502 502 _.price(data.price,data.tax); 503 _.saleprice(data. sale,data.saleprice);503 _.saleprice(data._sale,data.saleprice); 504 504 _.shipping(data.shipping,data.dimensions,data.shipfee); 505 505 if (!tmp) _.inventory(data.inventory,data.stock,data.sku); -
shopp/trunk/core/ui/behaviors/priceline.min.js
r821385 r865739 4 4 * Licensed under the GPLv3 {@see license.txt} 5 5 */ 6 function Pricelines(){var $=jqnc(),_=this;_.idx=0;_.row=new Object();_.variations=new Array();_.addons=new Array();_.linked=new Array();_.add=function(options,data,target,attachment){if(!data){data={context:"product"}}var key,p,targetkey,index;if(data.context=="variation"){key=xorkey(options);p=new Priceline(_.idx,options,data,target,attachment);_.row[key]=p;if(attachment){targetkey=parseInt(target.optionkey.val(),10);index=$.inArray(targetkey,_.variations);if(index!=-1){if(attachment=="before"){_.variations.splice(index,0,xorkey(p.options))}else{_.variations.splice(index+1,0,xorkey(p.options))}}}else{_.variations.push(xorkey(p.options))}}if(data.context=="addon"){p=new Priceline(_.idx,options,data,target,attachment);_.row[options]=p}if(data.context=="product"){p=new Priceline(0,options,data,target,attachment);_.row[0]=p}$("#prices").val(_.idx++)};_.exists=function(key){if(_.row[key]){return true}return false};_.remove=function(row){var index=$.inArray(row,_.variations);if(index!=-1){_.variations.splice(index,1)}_.row[row].row.remove();delete _.row[row]};_.reorderVariation=function(key,options){var variation=_.row[key],index=$.inArray(key,_.variations);variation.row.appendTo("#variations-pricing");variation.setOptions(options);if(index==-1){return}_.variations.splice(index,1);_.variations.push(xorkey(variation.options))};_.reorderAddon=function(id,pricegroup){var addon=_.row[id];addon.row.appendTo(pricegroup)};_.updateVariationsUI=function(type){var i,key,row,option;for(i in _.variations){key=_.variations[i];if(!Pricelines.row[key]){delete _.variations[i];continue}row=Pricelines.row[key];row.updateTabIndex(i);if(type&&type=="tabs"){continue}row.unlinkInputs();for(option in _.linked){if($.inArray(option,_.row[key].options)!=-1){if(!_.linked[option][key]){_.linked[option].push(key)}_.row[key].linkInputs(option)}}}};_.linkVariations=function(option){if(!option){return}for(var key in _.row){if($.inArray(option.toString(),_.row[key].options)!=-1){if(!_.linked[option]){_.linked[option]=new Array()}_.linked[option].push(key);_.row[key].linkInputs(option)}}};_.unlinkVariations=function(option){if(!option){return}if(!_.linked[option]){return}for(var row in _.linked[option]){if(_.row[_.linked[option][row]]){_.row[_.linked[option][row]].unlinkInputs(option)}}_.linked.splice(option,1)};_.unlinkAll=function(){for(var key in _.row){_.row[key].unlinkInputs()}_.linked.splice(0,1)};_.updateVariationLinks=function(){if(!_.linked){return}var key,option;for(key in _.row){_.row[key].unlinkInputs()}for(option in _.linked){_.linked[option]=false;_.linkVariations(option)}};_.allLinked=function(){if(_.linked[0]){return true}return false};_.linkAll=function(){_.unlinkAll();_.linked=new Array();_.linked[0]=new Array();for(var key in _.row){if(key==0){continue}_.linked[0].push(key);_.row[key].linkInputs(0)}}}function Priceline(id,options,data,target,attachment){var $=jqnc(),_=this,tmp=template,controller=Pricelines,typeOptions="",i,fn,heading,labelText,myid,context,optionids,sortorder,optionkey,type,dataCell,pricingTable,headingsRow,inputsRow;_.id=id;_.options=options;_.data=data;_.label=false;_.links=new Array();_.inputs=new Array();_.lasttype=false;i=_.id;fn="price["+i+"]";_.row=$('<div id="row-'+i+'" class="priceline" />');if(attachment=="after"){_.row.insertAfter(target)}else{if(attachment=="before"){_.row.insertBefore(target)}else{_.row.appendTo(target)}}heading=$('<div class="pricing-label" />').appendTo(_.row);labelText=$('<label for="label-'+i+'" />').appendTo(heading);_.label=$('<input type="hidden" name="price['+i+'][label]" id="label-'+i+'" />').appendTo(heading);_.label.change(function(){labelText.text($(this).val())});if(!data.id){data.id=""}if(!data.product){data.product=product}if(!data.donation){data.donation={"var":false,min:false}}if(!data.dimensions){data.dimensions={weight:0,height:0,width:0,length:0}}$('<input type="hidden" name="'+fn+'[id]" id="priceid-'+i+'" value="'+data.id+'" /><input type="hidden" name="'+fn+'[product]" id="product-'+i+'" value="'+data.product+'" /><input type="hidden" name="'+fn+'[context]" id="context-'+i+'"/><input type="hidden" name="'+fn+'[optionkey]" id="optionkey-'+i+'" class="optionkey" /><input type="hidden" name="'+fn+'[options]" id="options-'+i+'" value="" /><input type="hidden" name="sortorder[]" id="sortorder-'+i+'" value="'+i+'" />').appendTo(heading);myid=$("#priceid-"+i);context=$("#context-"+i);optionids=$("#options-"+i);sortorder=$("#sortorder-"+i);optionkey=$("#optionkey-"+i);_.row.optionkey=optionkey;$(priceTypes).each(function(t,option){if("addon"==data.context&&"Subscription"==option.label){return}typeOptions+='<option value="'+option.value+'">'+option.label+"</option>"});type=$('<select name="price['+i+'][type]" id="type-'+i+'"></select>').html(typeOptions).appendTo(heading);if(data&&data.label){_.label.val(htmlentities(data.label)).change();type.val(data.type)}dataCell=$('<div class="pricing-ui clear" />').appendTo(_.row);pricingTable=$("<table/>").addClass("pricing-table").appendTo(dataCell);headingsRow=$("<tr/>").appendTo(pricingTable);inputsRow=$("<tr/>").appendTo(pricingTable);_.price=function(price,tax){var hd,ui;hd=$('<th><label for="price-'+i+'">'+PRICE_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><input type="text" name="'+fn+'[price]" id="price-'+i+'" value="0" size="10" class="selectall money right" /><br /><input type="hidden" name="'+fn+'[tax]" value="on" /><input type="checkbox" name="'+fn+'[tax]" id="tax-'+i+'" value="off" /><label for="tax-'+i+'"> '+NOTAX_LABEL+"</label><br /></td>").appendTo(inputsRow);_.p=$("#price-"+i).val(asMoney(new Number(price)));_.t=$("#tax-"+i).attr("checked",tax=="off"?true:false)};_.saleprice=function(toggle,saleprice){var hd,ui,dis;hd=$('<th><input type="hidden" name="'+fn+'[sale]" value="off" /><input type="checkbox" name="'+fn+'[sale]" id="sale-'+i+'" value="on" /><label for="sale-'+i+'"> '+SALE_PRICE_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><span class="status">'+NOT_ON_SALE_TEXT+'</span><span class="ui"><input type="text" name="'+fn+'[saleprice]" id="saleprice-'+i+'" size="10" class="selectall money right" /></span></td>').appendTo(inputsRow);dis=ui.find("span.status");ui=ui.find("span.ui").hide();_.sp=$("#saleprice-"+i).val(asMoney(new Number(saleprice)));_.spt=$("#sale-"+i).attr("checked",(toggle=="on"?true:false)).toggler(dis,ui,_.sp)};_.donation=function(price,tax,variable,minimum){var hd,ui,hd2,ui2;hd=$('<th><label for="price-'+i+'"> '+AMOUNT_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><input type="text" name="'+fn+'[price]" id="price-'+i+'" value="0" size="10" class="selectall money right" /><br /><input type="hidden" name="'+fn+'[tax]" value="on" /><input type="checkbox" name="'+fn+'[tax]" id="tax-'+i+'" value="off" /><label for="tax-'+i+'"> '+NOTAX_LABEL+"</label><br /></td>").appendTo(inputsRow);_.p=$("#price-"+i).val(asMoney(new Number(price)));_.t=$("#tax-"+i).attr("checked",tax=="on"?false:true);hd2=$("<th />").appendTo(headingsRow);ui2=$('<td width="80%"><input type="hidden" name="'+fn+'[donation][var]" value="off" /><input type="checkbox" name="'+fn+'[donation][var]" id="donation-var-'+i+'" value="on" /><label for="donation-var-'+i+'"> '+DONATIONS_VAR_LABEL+'</label><br /><input type="hidden" name="'+fn+'[donation][min]" value="off" /><input type="checkbox" name="'+fn+'[donation][min]" id="donation-min-'+i+'" value="on" /><label for="donation-min-'+i+'"> '+DONATIONS_MIN_LABEL+"</label><br /></td>").appendTo(inputsRow);_.dv=$("#donation-var-"+i).attr("checked",variable=="on"?true:false);_.dm=$("#donation-min-"+i).attr("checked",minimum=="on"?true:false)};_.shipping=function(toggle,dimensions,fee){var hd,ui,dis,inf,dc,dw,dl,dwd,dh,dv,nf=getCurrencyFormat();nf.precision="2";hd=$('<th><input type="hidden" name="'+fn+'[shipping]" value="off" /><input type="checkbox" name="'+fn+'[shipping]" id="shipping-'+i+'" value="on" /><label for="shipping-'+i+'"> '+SHIPPING_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><span class="status">'+FREE_SHIPPING_TEXT+'</span><span class="ui"><input type="text" name="'+fn+'[dimensions][weight]" id="weight-'+i+'" size="8" class="selectall right" /><label for="weight-'+i+'" id="weight-label-'+i+'" title="'+WEIGHT_LABEL+'"> '+WEIGHT_LABEL+((weightUnit)?" ("+weightUnit+")":"")+'</label><br /><span class="dimui"></span><input type="text" name="'+fn+'[shipfee]" id="shipfee-'+i+'" size="8" class="selectall money right" /><label for="shipfee-'+i+'" title="'+SHIPFEE_XTRA+'"> '+SHIPFEE_LABEL+"</label><br /></span></td>").appendTo(inputsRow);dis=ui.find("span.status");inf=ui.find("span.ui").hide();dui=ui.find(".dimui");if(!dimensions.weight){dimensions.weight=0}_.w=$("#weight-"+i).val(formatNumber(new Number(dimensions.weight),nf,true)).bind("change.value",function(){this.value=formatNumber(isNaN(this.value)?0:this.value,nf,true)});_.fee=$("#shipfee-"+i);_.fee.val(asMoney(new Number(fee)));_.st=hd.find("#shipping-"+i).attr("checked",(toggle=="off"?false:true)).toggler(dis,inf,_.w);if(dimensionsRequired){dv=function(e,init){var value=this.value;if(init){value=new Number(value)}this.value=formatNumber(value,nf,true)};$("#weight-label-"+i).html(" "+dimensionUnit+"<sup>3</sup>/"+weightUnit);dc=$('<div class="dimensions"><div class="inline"><input type="text" name="'+fn+'[dimensions][weight]" id="dimensions-weight-'+i+'" size="4" class="selectall right weight" />'+(weightUnit?"<label>"+weightUnit+" </label>":"")+'<br /><label for="dimensions-weight-'+i+'" title="'+WEIGHT_LABEL+'"> '+WEIGHT_LABEL+'</label></div><div class="inline"><input type="text" name="'+fn+'[dimensions][length]" id="dimensions-length-'+i+'" size="4" class="selectall right" /><label> x </label><br /><label for="dimensions-length-'+i+'" title="'+LENGTH_LABEL+'"> '+LENGTH_LABEL+'</label></div><div class="inline"><input type="text" name="'+fn+'[dimensions][width]" id="dimensions-width-'+i+'" size="4" class="selectall right" /><label> x </label><br /><label for="dimensions-width-'+i+'" title="'+WIDTH_LABEL+'"> '+WIDTH_LABEL+'</label></div><div class="inline"><input type="text" name="'+fn+'[dimensions][height]" id="dimensions-height-'+i+'" size="4" class="selectall right" /><label>'+dimensionUnit+'</label><br /><label for="dimensions-height-'+i+'" title="'+HEIGHT_LABEL+'"> '+HEIGHT_LABEL+"</label></div></div>").hide().appendTo(dui);if(!(dimensions instanceof Object)){dimensions={weight:0,length:0,width:0,height:0}}_.dw=$("#dimensions-weight-"+i).val(dimensions.weight).bind("change.value",dv).trigger("change.value",true);_.dl=$("#dimensions-length-"+i).val(dimensions.length).bind("change.value",dv).trigger("change.value",true);_.dwd=$("#dimensions-width-"+i).val(dimensions.width).bind("change.value",dv).trigger("change.value",true);_.dh=$("#dimensions-height-"+i).val(dimensions.height).bind("change.value",dv).trigger("change.value",true);function volumeWeight(){var d=0,w=0;dc.find("input").each(function(id,dims){if($(dims).hasClass("weight")){w=asNumber(dims.value)}else{if(d==0){d=asNumber(dims.value)}else{d*=asNumber(dims.value)}}});if(!isNaN(d/w)){_.w.val((d/w)).trigger("change.value")}}function toggleDimensions(){_.w.toggleClass("extoggle");dc.toggle();_.dw.focus();volumeWeight()}_.st.change(function(){if(!$(this).attr("checked")){dc.hide()}});_.dh.blur(toggleDimensions);_.w.click(toggleDimensions).attr("readonly",true);volumeWeight()}};_.inventory=function(toggle,stock,sku){var hd,ui,dis;hd=$('<th><input type="hidden" name="'+fn+'[inventory]" value="off" /><input type="checkbox" name="'+fn+'[inventory]" id="inventory-'+i+'" value="on" /><label for="inventory-'+i+'"> '+INVENTORY_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><span class="status">'+NOT_TRACKED_TEXT+'</span><span class="ui"><input type="text" name="'+fn+'[stocked]" id="stock-'+i+'" size="8" class="selectall right" /><label for="stock-'+i+'"> '+IN_STOCK_LABEL+'</label><br /><input type="text" name="'+fn+'[sku]" id="sku-'+i+'" size="8" title="'+SKU_XTRA+'" class="selectall" /><label for="sku-'+i+'" title="'+SKU_LABEL_HELP+'"> '+SKU_LABEL+"</label></span></td>").appendTo(inputsRow);dis=ui.find("span.status");ui=ui.find("span.ui").hide();if(!stock){stock=0}_.stock=$("#stock-"+i).val(stock).trigger("change.value",function(){this.value=new Number(this.value)});_.sku=$("#sku-"+i).val(sku);_.it=hd.find("#inventory-"+i).attr("checked",(toggle=="on"?true:false)).toggler(dis,ui,_.stock)};_.download=function(d){var hd,ui,hd2,fc;hd=$('<th><label for="download-'+i+'">'+PRODUCT_DOWNLOAD_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td width="31%"><input type="hidden" name="'+fn+'[downloadpath]" id="download_path-'+i+'"/><input type="hidden" name="'+fn+'[downloadfile]" id="download_file-'+i+'"/><div id="file-'+i+'" class="status">'+NO_DOWNLOAD+"</div></td>").appendTo(inputsRow);hd2=$('<td rowspan="2" class="controls" width="75"><button type="button" class="button-secondary" style="white-space: nowrap;" id="file-selector-'+i+'"><small>'+SELECT_FILE_BUTTON_TEXT+"…</small></button></td>").appendTo(headingsRow);_.file=$("#file-"+i);_.selector=$("#file-selector-"+i).FileChooser(i,_.file);if(d&&d.id){fc=d.mime.replace("/"," ");_.file.attr("class","file").html('<div class="icon shoppui-file '+fc+'"></div>'+d.name+"<br /><small>"+readableFileSize(d.size)+"</small>").click(function(){window.location.href=adminurl+"admin.php?src=download&shopp_download="+d.id})}};_.recurring=function(r){var hd,ui,hd2,ui2,ints,n,cycs='<option value="0">∞</option>',pp,ps;for(n=1;n<31;n++){ints+='<option value="'+n+'">'+n+"</option>";if(n>1){cycs+='<option value="'+n+'">'+n+"</option>"}}$(billPeriods[0]).each(function(n,option){pp+='<option value="'+option.value+'">'+option.label+"</option>"});$(billPeriods[1]).each(function(n,option){ps+='<option value="'+option.value+'">'+option.label+"</option>"});hd2=$('<th><input type="hidden" name="'+fn+'[recurring][trial]" value="off" /><input type="checkbox" name="'+fn+'[recurring][trial]" id="trial-'+i+'" /><label for="trial-'+i+'"> '+TRIAL_LABEL+"</label></th>").appendTo(headingsRow);ui2=$('<td><span class="status">'+NOTRIAL_TEXT+'</span><span class="ui"><select name="'+fn+'[recurring][trialint]" id="trialint-'+i+'">'+ints+'</select><select name="'+fn+'[recurring][trialperiod]" id="trialperiod-'+i+'" class="period">'+pp+'</select><br /><input type="text" name="'+fn+'[recurring][trialprice]" id="trialprice-'+i+'" value="0" size="10" class="selectall money right" /><label for="trialprice-'+i+'"> '+PRICE_LABEL+"</label></span></td>").appendTo(inputsRow);hd=$('<th><label for="billcycle-'+i+'"> '+BILLCYCLE_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><select name="'+fn+'[recurring][interval]" id="interval-'+i+'">'+ints+'</select><select name="'+fn+'[recurring][period]" id="period-'+i+'" class="period">'+pp+'</select><br /><select name="'+fn+'[recurring][cycles]" id="cycles-'+i+'">'+cycs+'</select><label for="cycles'+i+'"> '+TIMES_LABEL+"</label></td>").appendTo(inputsRow);dis=ui2.find("span.status");ui=ui2.find("span.ui").hide();if(!r){r={period:1,interval:"d",cycles:0,trialperiod:1,trialint:1,trialprice:0}}_.period=$("#period-"+i).val(r.period);_.interval=$("#interval-"+i).val(r.interval).change(function(){var $this=$(this),s=_.period.val();if($this.val()==1){_.period.html(ps)}else{_.period.html(pp)}_.period.val(s)}).change();_.cycles=$("#cycles-"+i).val(r.cycles);_.trialperiod=$("#trialperiod-"+i).val(r.trialperiod);_.trialint=$("#trialint-"+i).val(r.trialint).change(function(){var $this=$(this),s=_.trialperiod.val();if($this.val()==1){_.trialperiod.html(ps)}else{_.trialperiod.html(pp)}_.trialperiod.val(s)}).change();_.trialprice=$("#trialprice-"+i).val(asMoney(new Number(r.trialprice)));_.trial=hd2.find("#trial-"+i).attr("checked",(r.trial=="on"?true:false)).toggler(dis,ui,_.trialint)};_.memberlevel=function(){var hd,ui,memberships,mo;memberships=["Basic","Silver","Gold","Platinum"];$(memberships).each(function(n,option){mo+='<option value="'+option+'">'+option+"</option>"});hd=$('<th><label for="membership-'+i+'"> '+MEMBERSHIP_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><select name="'+fn+'[membership]" id="membership-'+i+'" class="membership">'+mo+"</select></td>").appendTo(inputsRow)};$.fn.toggler=function(s,ui,f){this.bind("change.value",function(){if(this.checked){s.hide();ui.show()}else{s.show();ui.hide()}if($.ua.msie){$(this).blur()}}).click(function(){if($.ua.msie){$(this).trigger("change.value")}if(this.checked){f.focus().select()}}).trigger("change.value");return $(this)};_.Shipped=function(data){_.price(data.price,data.tax);_.saleprice(data. sale,data.saleprice);_.shipping(data.shipping,data.dimensions,data.shipfee);if(!tmp){_.inventory(data.inventory,data.stock,data.sku)}};_.Virtual=function(data){_.price(data.price,data.tax);_.saleprice(data.sale,data.saleprice);if(!tmp){_.inventory(data.inventory,data.stock,data.sku)}};_.Download=function(data){_.price(data.price,data.tax);_.saleprice(data.sale,data.saleprice);if(!tmp){_.download(data.download)}};_.Donation=function(data){_.donation(data.price,data.tax,data.donation["var"],data.donation.min)};_.Subscription=function(data){_.price(data.price,data.tax);_.saleprice(data.sale,data.saleprice);_.recurring(data.recurring)};_.Membership=function(data){_.price(data.price,data.tax);_.saleprice(data.sale,data.saleprice);_.recurring();if(!tmp){_.memberlevel()}};type.bind("change.value",function(){headingsRow.empty();inputsRow.empty();var ui=type.val();if(ui=="Shipped"){_.Shipped(data)}if(ui=="Virtual"){_.Virtual(data)}if(ui=="Download"){_.Download(data)}if(ui=="Donation"){_.Donation(data)}if(ui=="Subscription"){_.Subscription(data)}if(ui=="Membership"){_.Membership(data)}inputsRow.find("input.money").bind("change.value",function(){this.value=asMoney(this.value)}).trigger("change.value");quickSelects(inputsRow)}).trigger("change.value");_.disable=function(){_.lasttype=(type.val())?type.val():false;type.val("N/A").trigger("change.value")};_.enable=function(){if(_.lasttype){type.val(_.lasttype).trigger("change.value")}};if(data&&data.context){context.val(data.context)}else{context.val("product")}_.setOptions=function(options){var update=false;if(options){if(options!=_.options){update=true}_.options=options}if(context.val()=="variation"){optionkey.val(xorkey(_.options))}if(update){_.updateLabel()}};_.updateKey=function(){optionkey.val(xorkey(_.options))};_.updateLabel=function(){var type=context.val(),string="",ids="";if(_.options){if(type=="variation"){$(_.options).each(function(index,id){if(string==""){string=$(productOptions[id]).val()}else{string+=", "+$(productOptions[id]).val()}if(ids==""){ids=id}else{ids+=","+id}})}if(type=="addon"){string=$(productAddons[_.options]).val();ids=_.options}}if(string==""){string=DEFAULT_PRICELINE_LABEL}_.label.val(htmlentities(string)).change();optionids.val(ids)};_.updateTabIndex=function(row){row=new Number(row);$.each(_.inputs,function(i,input){$(input).attr("tabindex",((row+1)*100)+i)})};_.linkInputs=function(option){_.links.push(option);$.each(_.inputs,function(i,input){if(!input){return}var type="change.linkedinputs",elem=$(input);if(elem.attr("type")=="checkbox"){type="click.linkedinputs"}$(input).bind(type,function(){var value=$(this).val(),checked=$(this).attr("checked");$.each(_.links,function(l,option){$.each(controller.linked[option],function(id,key){if(key==xorkey(_.options)){return}if(!controller.row[key]){return}if(elem.attr("type")=="checkbox"){$(controller.row[key].inputs[i]).attr("checked",checked)}else{$(controller.row[key].inputs[i]).val(value)}$(controller.row[key].inputs[i]).trigger("change.value")})})})})};_.unlinkInputs=function(option){if(option!==false){index=$.inArray(option,_.links);_.links.splice(index,1)}$.each(_.inputs,function(i,input){if(!input){return}var type="blur.linkedinputs";if($(input).attr("type")=="checkbox"){type="click.linkedinputs"}$(input).unbind(type)})};if(type.val()!="N/A"){_.inputs=new Array(type,_.p,_.t,_.spt,_.sp,_.dv,_.dm,_.st,_.w,_.dw,_.dl,_.dwd,_.dh,_.fee,_.it,_.stock,_.sku,_.period,_.interval,_.cycles,_.trialperiod,_.trialint,_.trialprice,_.trial)}_.updateKey();_.updateLabel()};6 function Pricelines(){var $=jqnc(),_=this;_.idx=0;_.row=new Object();_.variations=new Array();_.addons=new Array();_.linked=new Array();_.add=function(options,data,target,attachment){if(!data){data={context:"product"}}var key,p,targetkey,index;if(data.context=="variation"){key=xorkey(options);p=new Priceline(_.idx,options,data,target,attachment);_.row[key]=p;if(attachment){targetkey=parseInt(target.optionkey.val(),10);index=$.inArray(targetkey,_.variations);if(index!=-1){if(attachment=="before"){_.variations.splice(index,0,xorkey(p.options))}else{_.variations.splice(index+1,0,xorkey(p.options))}}}else{_.variations.push(xorkey(p.options))}}if(data.context=="addon"){p=new Priceline(_.idx,options,data,target,attachment);_.row[options]=p}if(data.context=="product"){p=new Priceline(0,options,data,target,attachment);_.row[0]=p}$("#prices").val(_.idx++)};_.exists=function(key){if(_.row[key]){return true}return false};_.remove=function(row){var index=$.inArray(row,_.variations);if(index!=-1){_.variations.splice(index,1)}_.row[row].row.remove();delete _.row[row]};_.reorderVariation=function(key,options){var variation=_.row[key],index=$.inArray(key,_.variations);variation.row.appendTo("#variations-pricing");variation.setOptions(options);if(index==-1){return}_.variations.splice(index,1);_.variations.push(xorkey(variation.options))};_.reorderAddon=function(id,pricegroup){var addon=_.row[id];addon.row.appendTo(pricegroup)};_.updateVariationsUI=function(type){var i,key,row,option;for(i in _.variations){key=_.variations[i];if(!Pricelines.row[key]){delete _.variations[i];continue}row=Pricelines.row[key];row.updateTabIndex(i);if(type&&type=="tabs"){continue}row.unlinkInputs();for(option in _.linked){if($.inArray(option,_.row[key].options)!=-1){if(!_.linked[option][key]){_.linked[option].push(key)}_.row[key].linkInputs(option)}}}};_.linkVariations=function(option){if(!option){return}for(var key in _.row){if($.inArray(option.toString(),_.row[key].options)!=-1){if(!_.linked[option]){_.linked[option]=new Array()}_.linked[option].push(key);_.row[key].linkInputs(option)}}};_.unlinkVariations=function(option){if(!option){return}if(!_.linked[option]){return}for(var row in _.linked[option]){if(_.row[_.linked[option][row]]){_.row[_.linked[option][row]].unlinkInputs(option)}}_.linked.splice(option,1)};_.unlinkAll=function(){for(var key in _.row){_.row[key].unlinkInputs()}_.linked.splice(0,1)};_.updateVariationLinks=function(){if(!_.linked){return}var key,option;for(key in _.row){_.row[key].unlinkInputs()}for(option in _.linked){_.linked[option]=false;_.linkVariations(option)}};_.allLinked=function(){if(_.linked[0]){return true}return false};_.linkAll=function(){_.unlinkAll();_.linked=new Array();_.linked[0]=new Array();for(var key in _.row){if(key==0){continue}_.linked[0].push(key);_.row[key].linkInputs(0)}}}function Priceline(id,options,data,target,attachment){var $=jqnc(),_=this,tmp=template,controller=Pricelines,typeOptions="",i,fn,heading,labelText,myid,context,optionids,sortorder,optionkey,type,dataCell,pricingTable,headingsRow,inputsRow;_.id=id;_.options=options;_.data=data;_.label=false;_.links=new Array();_.inputs=new Array();_.lasttype=false;i=_.id;fn="price["+i+"]";_.row=$('<div id="row-'+i+'" class="priceline" />');if(attachment=="after"){_.row.insertAfter(target)}else{if(attachment=="before"){_.row.insertBefore(target)}else{_.row.appendTo(target)}}heading=$('<div class="pricing-label" />').appendTo(_.row);labelText=$('<label for="label-'+i+'" />').appendTo(heading);_.label=$('<input type="hidden" name="price['+i+'][label]" id="label-'+i+'" />').appendTo(heading);_.label.change(function(){labelText.text($(this).val())});if(!data.id){data.id=""}if(!data.product){data.product=product}if(!data.donation){data.donation={"var":false,min:false}}if(!data.dimensions){data.dimensions={weight:0,height:0,width:0,length:0}}$('<input type="hidden" name="'+fn+'[id]" id="priceid-'+i+'" value="'+data.id+'" /><input type="hidden" name="'+fn+'[product]" id="product-'+i+'" value="'+data.product+'" /><input type="hidden" name="'+fn+'[context]" id="context-'+i+'"/><input type="hidden" name="'+fn+'[optionkey]" id="optionkey-'+i+'" class="optionkey" /><input type="hidden" name="'+fn+'[options]" id="options-'+i+'" value="" /><input type="hidden" name="sortorder[]" id="sortorder-'+i+'" value="'+i+'" />').appendTo(heading);myid=$("#priceid-"+i);context=$("#context-"+i);optionids=$("#options-"+i);sortorder=$("#sortorder-"+i);optionkey=$("#optionkey-"+i);_.row.optionkey=optionkey;$(priceTypes).each(function(t,option){if("addon"==data.context&&"Subscription"==option.label){return}typeOptions+='<option value="'+option.value+'">'+option.label+"</option>"});type=$('<select name="price['+i+'][type]" id="type-'+i+'"></select>').html(typeOptions).appendTo(heading);if(data&&data.label){_.label.val(htmlentities(data.label)).change();type.val(data.type)}dataCell=$('<div class="pricing-ui clear" />').appendTo(_.row);pricingTable=$("<table/>").addClass("pricing-table").appendTo(dataCell);headingsRow=$("<tr/>").appendTo(pricingTable);inputsRow=$("<tr/>").appendTo(pricingTable);_.price=function(price,tax){var hd,ui;hd=$('<th><label for="price-'+i+'">'+PRICE_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><input type="text" name="'+fn+'[price]" id="price-'+i+'" value="0" size="10" class="selectall money right" /><br /><input type="hidden" name="'+fn+'[tax]" value="on" /><input type="checkbox" name="'+fn+'[tax]" id="tax-'+i+'" value="off" /><label for="tax-'+i+'"> '+NOTAX_LABEL+"</label><br /></td>").appendTo(inputsRow);_.p=$("#price-"+i).val(asMoney(new Number(price)));_.t=$("#tax-"+i).attr("checked",tax=="off"?true:false)};_.saleprice=function(toggle,saleprice){var hd,ui,dis;hd=$('<th><input type="hidden" name="'+fn+'[sale]" value="off" /><input type="checkbox" name="'+fn+'[sale]" id="sale-'+i+'" value="on" /><label for="sale-'+i+'"> '+SALE_PRICE_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><span class="status">'+NOT_ON_SALE_TEXT+'</span><span class="ui"><input type="text" name="'+fn+'[saleprice]" id="saleprice-'+i+'" size="10" class="selectall money right" /></span></td>').appendTo(inputsRow);dis=ui.find("span.status");ui=ui.find("span.ui").hide();_.sp=$("#saleprice-"+i).val(asMoney(new Number(saleprice)));_.spt=$("#sale-"+i).attr("checked",(toggle=="on"?true:false)).toggler(dis,ui,_.sp)};_.donation=function(price,tax,variable,minimum){var hd,ui,hd2,ui2;hd=$('<th><label for="price-'+i+'"> '+AMOUNT_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><input type="text" name="'+fn+'[price]" id="price-'+i+'" value="0" size="10" class="selectall money right" /><br /><input type="hidden" name="'+fn+'[tax]" value="on" /><input type="checkbox" name="'+fn+'[tax]" id="tax-'+i+'" value="off" /><label for="tax-'+i+'"> '+NOTAX_LABEL+"</label><br /></td>").appendTo(inputsRow);_.p=$("#price-"+i).val(asMoney(new Number(price)));_.t=$("#tax-"+i).attr("checked",tax=="on"?false:true);hd2=$("<th />").appendTo(headingsRow);ui2=$('<td width="80%"><input type="hidden" name="'+fn+'[donation][var]" value="off" /><input type="checkbox" name="'+fn+'[donation][var]" id="donation-var-'+i+'" value="on" /><label for="donation-var-'+i+'"> '+DONATIONS_VAR_LABEL+'</label><br /><input type="hidden" name="'+fn+'[donation][min]" value="off" /><input type="checkbox" name="'+fn+'[donation][min]" id="donation-min-'+i+'" value="on" /><label for="donation-min-'+i+'"> '+DONATIONS_MIN_LABEL+"</label><br /></td>").appendTo(inputsRow);_.dv=$("#donation-var-"+i).attr("checked",variable=="on"?true:false);_.dm=$("#donation-min-"+i).attr("checked",minimum=="on"?true:false)};_.shipping=function(toggle,dimensions,fee){var hd,ui,dis,inf,dc,dw,dl,dwd,dh,dv,nf=getCurrencyFormat();nf.precision="2";hd=$('<th><input type="hidden" name="'+fn+'[shipping]" value="off" /><input type="checkbox" name="'+fn+'[shipping]" id="shipping-'+i+'" value="on" /><label for="shipping-'+i+'"> '+SHIPPING_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><span class="status">'+FREE_SHIPPING_TEXT+'</span><span class="ui"><input type="text" name="'+fn+'[dimensions][weight]" id="weight-'+i+'" size="8" class="selectall right" /><label for="weight-'+i+'" id="weight-label-'+i+'" title="'+WEIGHT_LABEL+'"> '+WEIGHT_LABEL+((weightUnit)?" ("+weightUnit+")":"")+'</label><br /><span class="dimui"></span><input type="text" name="'+fn+'[shipfee]" id="shipfee-'+i+'" size="8" class="selectall money right" /><label for="shipfee-'+i+'" title="'+SHIPFEE_XTRA+'"> '+SHIPFEE_LABEL+"</label><br /></span></td>").appendTo(inputsRow);dis=ui.find("span.status");inf=ui.find("span.ui").hide();dui=ui.find(".dimui");if(!dimensions.weight){dimensions.weight=0}_.w=$("#weight-"+i).val(formatNumber(new Number(dimensions.weight),nf,true)).bind("change.value",function(){this.value=formatNumber(isNaN(this.value)?0:this.value,nf,true)});_.fee=$("#shipfee-"+i);_.fee.val(asMoney(new Number(fee)));_.st=hd.find("#shipping-"+i).attr("checked",(toggle=="off"?false:true)).toggler(dis,inf,_.w);if(dimensionsRequired){dv=function(e,init){var value=this.value;if(init){value=new Number(value)}this.value=formatNumber(value,nf,true)};$("#weight-label-"+i).html(" "+dimensionUnit+"<sup>3</sup>/"+weightUnit);dc=$('<div class="dimensions"><div class="inline"><input type="text" name="'+fn+'[dimensions][weight]" id="dimensions-weight-'+i+'" size="4" class="selectall right weight" />'+(weightUnit?"<label>"+weightUnit+" </label>":"")+'<br /><label for="dimensions-weight-'+i+'" title="'+WEIGHT_LABEL+'"> '+WEIGHT_LABEL+'</label></div><div class="inline"><input type="text" name="'+fn+'[dimensions][length]" id="dimensions-length-'+i+'" size="4" class="selectall right" /><label> x </label><br /><label for="dimensions-length-'+i+'" title="'+LENGTH_LABEL+'"> '+LENGTH_LABEL+'</label></div><div class="inline"><input type="text" name="'+fn+'[dimensions][width]" id="dimensions-width-'+i+'" size="4" class="selectall right" /><label> x </label><br /><label for="dimensions-width-'+i+'" title="'+WIDTH_LABEL+'"> '+WIDTH_LABEL+'</label></div><div class="inline"><input type="text" name="'+fn+'[dimensions][height]" id="dimensions-height-'+i+'" size="4" class="selectall right" /><label>'+dimensionUnit+'</label><br /><label for="dimensions-height-'+i+'" title="'+HEIGHT_LABEL+'"> '+HEIGHT_LABEL+"</label></div></div>").hide().appendTo(dui);if(!(dimensions instanceof Object)){dimensions={weight:0,length:0,width:0,height:0}}_.dw=$("#dimensions-weight-"+i).val(dimensions.weight).bind("change.value",dv).trigger("change.value",true);_.dl=$("#dimensions-length-"+i).val(dimensions.length).bind("change.value",dv).trigger("change.value",true);_.dwd=$("#dimensions-width-"+i).val(dimensions.width).bind("change.value",dv).trigger("change.value",true);_.dh=$("#dimensions-height-"+i).val(dimensions.height).bind("change.value",dv).trigger("change.value",true);function volumeWeight(){var d=0,w=0;dc.find("input").each(function(id,dims){if($(dims).hasClass("weight")){w=asNumber(dims.value)}else{if(d==0){d=asNumber(dims.value)}else{d*=asNumber(dims.value)}}});if(!isNaN(d/w)){_.w.val((d/w)).trigger("change.value")}}function toggleDimensions(){_.w.toggleClass("extoggle");dc.toggle();_.dw.focus();volumeWeight()}_.st.change(function(){if(!$(this).attr("checked")){dc.hide()}});_.dh.blur(toggleDimensions);_.w.click(toggleDimensions).attr("readonly",true);volumeWeight()}};_.inventory=function(toggle,stock,sku){var hd,ui,dis;hd=$('<th><input type="hidden" name="'+fn+'[inventory]" value="off" /><input type="checkbox" name="'+fn+'[inventory]" id="inventory-'+i+'" value="on" /><label for="inventory-'+i+'"> '+INVENTORY_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><span class="status">'+NOT_TRACKED_TEXT+'</span><span class="ui"><input type="text" name="'+fn+'[stocked]" id="stock-'+i+'" size="8" class="selectall right" /><label for="stock-'+i+'"> '+IN_STOCK_LABEL+'</label><br /><input type="text" name="'+fn+'[sku]" id="sku-'+i+'" size="8" title="'+SKU_XTRA+'" class="selectall" /><label for="sku-'+i+'" title="'+SKU_LABEL_HELP+'"> '+SKU_LABEL+"</label></span></td>").appendTo(inputsRow);dis=ui.find("span.status");ui=ui.find("span.ui").hide();if(!stock){stock=0}_.stock=$("#stock-"+i).val(stock).trigger("change.value",function(){this.value=new Number(this.value)});_.sku=$("#sku-"+i).val(sku);_.it=hd.find("#inventory-"+i).attr("checked",(toggle=="on"?true:false)).toggler(dis,ui,_.stock)};_.download=function(d){var hd,ui,hd2,fc;hd=$('<th><label for="download-'+i+'">'+PRODUCT_DOWNLOAD_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td width="31%"><input type="hidden" name="'+fn+'[downloadpath]" id="download_path-'+i+'"/><input type="hidden" name="'+fn+'[downloadfile]" id="download_file-'+i+'"/><div id="file-'+i+'" class="status">'+NO_DOWNLOAD+"</div></td>").appendTo(inputsRow);hd2=$('<td rowspan="2" class="controls" width="75"><button type="button" class="button-secondary" style="white-space: nowrap;" id="file-selector-'+i+'"><small>'+SELECT_FILE_BUTTON_TEXT+"…</small></button></td>").appendTo(headingsRow);_.file=$("#file-"+i);_.selector=$("#file-selector-"+i).FileChooser(i,_.file);if(d&&d.id){fc=d.mime.replace("/"," ");_.file.attr("class","file").html('<div class="icon shoppui-file '+fc+'"></div>'+d.name+"<br /><small>"+readableFileSize(d.size)+"</small>").click(function(){window.location.href=adminurl+"admin.php?src=download&shopp_download="+d.id})}};_.recurring=function(r){var hd,ui,hd2,ui2,ints,n,cycs='<option value="0">∞</option>',pp,ps;for(n=1;n<31;n++){ints+='<option value="'+n+'">'+n+"</option>";if(n>1){cycs+='<option value="'+n+'">'+n+"</option>"}}$(billPeriods[0]).each(function(n,option){pp+='<option value="'+option.value+'">'+option.label+"</option>"});$(billPeriods[1]).each(function(n,option){ps+='<option value="'+option.value+'">'+option.label+"</option>"});hd2=$('<th><input type="hidden" name="'+fn+'[recurring][trial]" value="off" /><input type="checkbox" name="'+fn+'[recurring][trial]" id="trial-'+i+'" /><label for="trial-'+i+'"> '+TRIAL_LABEL+"</label></th>").appendTo(headingsRow);ui2=$('<td><span class="status">'+NOTRIAL_TEXT+'</span><span class="ui"><select name="'+fn+'[recurring][trialint]" id="trialint-'+i+'">'+ints+'</select><select name="'+fn+'[recurring][trialperiod]" id="trialperiod-'+i+'" class="period">'+pp+'</select><br /><input type="text" name="'+fn+'[recurring][trialprice]" id="trialprice-'+i+'" value="0" size="10" class="selectall money right" /><label for="trialprice-'+i+'"> '+PRICE_LABEL+"</label></span></td>").appendTo(inputsRow);hd=$('<th><label for="billcycle-'+i+'"> '+BILLCYCLE_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><select name="'+fn+'[recurring][interval]" id="interval-'+i+'">'+ints+'</select><select name="'+fn+'[recurring][period]" id="period-'+i+'" class="period">'+pp+'</select><br /><select name="'+fn+'[recurring][cycles]" id="cycles-'+i+'">'+cycs+'</select><label for="cycles'+i+'"> '+TIMES_LABEL+"</label></td>").appendTo(inputsRow);dis=ui2.find("span.status");ui=ui2.find("span.ui").hide();if(!r){r={period:1,interval:"d",cycles:0,trialperiod:1,trialint:1,trialprice:0}}_.period=$("#period-"+i).val(r.period);_.interval=$("#interval-"+i).val(r.interval).change(function(){var $this=$(this),s=_.period.val();if($this.val()==1){_.period.html(ps)}else{_.period.html(pp)}_.period.val(s)}).change();_.cycles=$("#cycles-"+i).val(r.cycles);_.trialperiod=$("#trialperiod-"+i).val(r.trialperiod);_.trialint=$("#trialint-"+i).val(r.trialint).change(function(){var $this=$(this),s=_.trialperiod.val();if($this.val()==1){_.trialperiod.html(ps)}else{_.trialperiod.html(pp)}_.trialperiod.val(s)}).change();_.trialprice=$("#trialprice-"+i).val(asMoney(new Number(r.trialprice)));_.trial=hd2.find("#trial-"+i).attr("checked",(r.trial=="on"?true:false)).toggler(dis,ui,_.trialint)};_.memberlevel=function(){var hd,ui,memberships,mo;memberships=["Basic","Silver","Gold","Platinum"];$(memberships).each(function(n,option){mo+='<option value="'+option+'">'+option+"</option>"});hd=$('<th><label for="membership-'+i+'"> '+MEMBERSHIP_LABEL+"</label></th>").appendTo(headingsRow);ui=$('<td><select name="'+fn+'[membership]" id="membership-'+i+'" class="membership">'+mo+"</select></td>").appendTo(inputsRow)};$.fn.toggler=function(s,ui,f){this.bind("change.value",function(){if(this.checked){s.hide();ui.show()}else{s.show();ui.hide()}if($.ua.msie){$(this).blur()}}).click(function(){if($.ua.msie){$(this).trigger("change.value")}if(this.checked){f.focus().select()}}).trigger("change.value");return $(this)};_.Shipped=function(data){_.price(data.price,data.tax);_.saleprice(data._sale,data.saleprice);_.shipping(data.shipping,data.dimensions,data.shipfee);if(!tmp){_.inventory(data.inventory,data.stock,data.sku)}};_.Virtual=function(data){_.price(data.price,data.tax);_.saleprice(data.sale,data.saleprice);if(!tmp){_.inventory(data.inventory,data.stock,data.sku)}};_.Download=function(data){_.price(data.price,data.tax);_.saleprice(data.sale,data.saleprice);if(!tmp){_.download(data.download)}};_.Donation=function(data){_.donation(data.price,data.tax,data.donation["var"],data.donation.min)};_.Subscription=function(data){_.price(data.price,data.tax);_.saleprice(data.sale,data.saleprice);_.recurring(data.recurring)};_.Membership=function(data){_.price(data.price,data.tax);_.saleprice(data.sale,data.saleprice);_.recurring();if(!tmp){_.memberlevel()}};type.bind("change.value",function(){headingsRow.empty();inputsRow.empty();var ui=type.val();if(ui=="Shipped"){_.Shipped(data)}if(ui=="Virtual"){_.Virtual(data)}if(ui=="Download"){_.Download(data)}if(ui=="Donation"){_.Donation(data)}if(ui=="Subscription"){_.Subscription(data)}if(ui=="Membership"){_.Membership(data)}inputsRow.find("input.money").bind("change.value",function(){this.value=asMoney(this.value)}).trigger("change.value");quickSelects(inputsRow)}).trigger("change.value");_.disable=function(){_.lasttype=(type.val())?type.val():false;type.val("N/A").trigger("change.value")};_.enable=function(){if(_.lasttype){type.val(_.lasttype).trigger("change.value")}};if(data&&data.context){context.val(data.context)}else{context.val("product")}_.setOptions=function(options){var update=false;if(options){if(options!=_.options){update=true}_.options=options}if(context.val()=="variation"){optionkey.val(xorkey(_.options))}if(update){_.updateLabel()}};_.updateKey=function(){optionkey.val(xorkey(_.options))};_.updateLabel=function(){var type=context.val(),string="",ids="";if(_.options){if(type=="variation"){$(_.options).each(function(index,id){if(string==""){string=$(productOptions[id]).val()}else{string+=", "+$(productOptions[id]).val()}if(ids==""){ids=id}else{ids+=","+id}})}if(type=="addon"){string=$(productAddons[_.options]).val();ids=_.options}}if(string==""){string=DEFAULT_PRICELINE_LABEL}_.label.val(htmlentities(string)).change();optionids.val(ids)};_.updateTabIndex=function(row){row=new Number(row);$.each(_.inputs,function(i,input){$(input).attr("tabindex",((row+1)*100)+i)})};_.linkInputs=function(option){_.links.push(option);$.each(_.inputs,function(i,input){if(!input){return}var type="change.linkedinputs",elem=$(input);if(elem.attr("type")=="checkbox"){type="click.linkedinputs"}$(input).bind(type,function(){var value=$(this).val(),checked=$(this).attr("checked");$.each(_.links,function(l,option){$.each(controller.linked[option],function(id,key){if(key==xorkey(_.options)){return}if(!controller.row[key]){return}if(elem.attr("type")=="checkbox"){$(controller.row[key].inputs[i]).attr("checked",checked)}else{$(controller.row[key].inputs[i]).val(value)}$(controller.row[key].inputs[i]).trigger("change.value")})})})})};_.unlinkInputs=function(option){if(option!==false){index=$.inArray(option,_.links);_.links.splice(index,1)}$.each(_.inputs,function(i,input){if(!input){return}var type="blur.linkedinputs";if($(input).attr("type")=="checkbox"){type="click.linkedinputs"}$(input).unbind(type)})};if(type.val()!="N/A"){_.inputs=new Array(type,_.p,_.t,_.spt,_.sp,_.dv,_.dm,_.st,_.w,_.dw,_.dl,_.dwd,_.dh,_.fee,_.it,_.stock,_.sku,_.period,_.interval,_.cycles,_.trialperiod,_.trialint,_.trialprice,_.trial)}_.updateKey();_.updateLabel()}; -
shopp/trunk/core/ui/categories/category.js
r821385 r865739 52 52 }).change(); 53 53 54 if (details) for (s in details) addDetail(details[s]);54 if (details) $.each(details, function(i, r) { addDetail(r); }); 55 55 $('#addPriceLevel').click(function() { addPriceLevel(); }); 56 56 $('#addDetail').click(function() { addDetail(); }); … … 72 72 }).change(); 73 73 74 if (priceranges) for (key in priceranges) addPriceLevel(priceranges[key]);74 if (priceranges) $.each(priceranges, function(i, r) { addPriceLevel(r); }); 75 75 76 76 if (!category) $('#title').focus(); … … 124 124 125 125 // Load up existing options 126 if (data && data.options) { 127 for (var i in data.options) menu.addOption(data.options[i]); 128 } 129 130 126 if (data && data.options) $.each(data.options, function (i,r) { menu.addOption(r); }); 131 127 $(menu.itemsElement).sortable({'axis':'y','items':'li.option','scroll':false}); 132 128 -
shopp/trunk/core/ui/categories/category.min.js
r821385 r865739 1 var Pricelines=new Pricelines(),productOptions=new Array(),optionMenus=new Array(),detailsidx=1,variationsidx=1,optionsidx=1,pricingidx=1,pricelevelsidx=1,fileUploader=false,changes=false,saving=false,flashUploader=false,template=true;jQuery(document).ready(function(){var $=jqnc(),editslug=new SlugEditor(category,"category"),imageUploads=new ImageUploads($("#image-category-id").val(),"category");postboxes.add_postbox_toggles("shopp_page_shopp-categories");$(".if-js-closed").removeClass("if-js-closed").addClass("closed");$(".postbox a.help").click(function(){$(this).colorbox({iframe:true,open:true,innerWidth:768,innerHeight:480,scrolling:false});return false});updateWorkflow();$("#category").submit(function(){this.action=this.action.substr(0,this.action.indexOf("?"))+"?"+$.param(request);return true});$("#templates, #details-template, #details-facetedmenu, #variations-template, #variations-pricing, #price-ranges").hide();$("#spectemplates-setting").change(function(){if(this.checked){$("#templates, #details-template").show()}else{$("#details-template").hide()}if(!$("#spectemplates-setting").attr("checked")&&!$("#variations-setting").attr("checked")){$("#templates").hide()}}).change();$("#faceted-setting").change(function(){if(this.checked){$("#details-menu").removeClass("options").addClass("menu");$("#details-facetedmenu, #price-ranges").show()}else{$("#details-menu").removeClass("menu").addClass("options");$("#details-facetedmenu, #price-ranges").hide()}}).change();if(details){ for(s in details){addDetail(details[s])}}$("#addPriceLevel").click(function(){addPriceLevel()});$("#addDetail").click(function(){addDetail()});$("#variations-setting").bind("toggleui",function(){if(this.checked){$("#templates, #variations-template, #variations-pricing").show()}else{$("#variations-template, #variations-pricing").hide()}if(!$("#spectemplates-setting").attr("checked")&&!$("#variations-setting").attr("checked")){$("#templates").hide()}}).click(function(){$(this).trigger("toggleui")}).trigger("toggleui");if(options){loadVariations(!(options.v)?options:options.v,prices)}$("#addVariationMenu").click(function(){addVariationOptionsMenu()});$("#pricerange-facetedmenu").change(function(){if($(this).val()=="custom"){$("#pricerange-menu, #addPriceLevel").show()}else{$("#pricerange-menu, #addPriceLevel").hide()}}).change();if(priceranges){for(key in priceranges){addPriceLevel(priceranges[key])}}if(!category){$("#title").focus()}function addPriceLevel(data){var menus=$("#pricerange-menu");var id=pricelevelsidx++;var menu=new NestedMenu(id,menus,"priceranges","",data,false,{axis:"y",scroll:false});$(menu.label).change(function(){this.value=asMoney(this.value)}).change()}function addDetail(data){var menus=$("#details-menu"),entries=$("#details-list"),addOptionButton=$("#addDetailOption"),id=detailsidx,menu=new NestedMenu(id,menus,"specs",NEW_DETAIL_DEFAULT,data,{target:entries,type:"list"});menu.items=new Array();menu.addOption=function(data){var option=new NestedMenuOption(menu.index,menu.itemsElement,menu.dataname,NEW_OPTION_DEFAULT,data,true);menu.items.push(option)};var facetedSetting=$('<li class="setting"></li>').appendTo(menu.itemsElement);var facetedMenu=$('<select name="specs['+menu.index+'][facetedmenu]"></select>').appendTo(facetedSetting);$('<option value="disabled">'+FACETED_DISABLED+"</option>").appendTo(facetedMenu);$('<option value="auto">'+FACETED_AUTO+"</option>").appendTo(facetedMenu);$('<option value="ranges">'+FACETED_RANGES+"</option>").appendTo(facetedMenu);$('<option value="custom">'+FACETED_CUSTOM+"</option>").appendTo(facetedMenu);if(data&&data.facetedmenu){facetedMenu.val(data.facetedmenu)}facetedMenu.change(function(){if($(this).val()=="disabled"||$(this).val()=="auto"){$(addOptionButton).hide();$(menu.itemsElement).find("li.option").hide()}else{$(addOptionButton).show();$(menu.itemsElement).find("li.option").show()}}).change();if(data&&data.options){for(var i in data.options){menu.addOption(data.options[i])}}$(menu.itemsElement).sortable({axis:"y",items:"li.option",scroll:false});menu.element.unbind("click",menu.click);menu.element.click(function(){menu.selected();$(addOptionButton).unbind("click").click(menu.addOption);$(facetedMenu).change()});detailsidx++}function updateWorkflow(){$("#workflow").change(function(){setting=$(this).val();request.page=adminpage;request.id=category;if(!request.id){request.id="new"}if(setting=="new"){request.id="new";request.next=setting}if(setting=="close"){delete request.id}if(setting=="previous"){$.each(worklist,function(i,entry){if(entry.id!=category){return}if(worklist[i-1]){request.next=worklist[i-1].id}else{delete request.id}})}if(setting=="next"){$.each(worklist,function(i,entry){if(entry.id!=category){return}if(worklist[i+1]){request.next=worklist[i+1].id}else{delete request.id}})}}).change()}});1 var Pricelines=new Pricelines(),productOptions=new Array(),optionMenus=new Array(),detailsidx=1,variationsidx=1,optionsidx=1,pricingidx=1,pricelevelsidx=1,fileUploader=false,changes=false,saving=false,flashUploader=false,template=true;jQuery(document).ready(function(){var $=jqnc(),editslug=new SlugEditor(category,"category"),imageUploads=new ImageUploads($("#image-category-id").val(),"category");postboxes.add_postbox_toggles("shopp_page_shopp-categories");$(".if-js-closed").removeClass("if-js-closed").addClass("closed");$(".postbox a.help").click(function(){$(this).colorbox({iframe:true,open:true,innerWidth:768,innerHeight:480,scrolling:false});return false});updateWorkflow();$("#category").submit(function(){this.action=this.action.substr(0,this.action.indexOf("?"))+"?"+$.param(request);return true});$("#templates, #details-template, #details-facetedmenu, #variations-template, #variations-pricing, #price-ranges").hide();$("#spectemplates-setting").change(function(){if(this.checked){$("#templates, #details-template").show()}else{$("#details-template").hide()}if(!$("#spectemplates-setting").attr("checked")&&!$("#variations-setting").attr("checked")){$("#templates").hide()}}).change();$("#faceted-setting").change(function(){if(this.checked){$("#details-menu").removeClass("options").addClass("menu");$("#details-facetedmenu, #price-ranges").show()}else{$("#details-menu").removeClass("menu").addClass("options");$("#details-facetedmenu, #price-ranges").hide()}}).change();if(details){$.each(details,function(i,r){addDetail(r)})}$("#addPriceLevel").click(function(){addPriceLevel()});$("#addDetail").click(function(){addDetail()});$("#variations-setting").bind("toggleui",function(){if(this.checked){$("#templates, #variations-template, #variations-pricing").show()}else{$("#variations-template, #variations-pricing").hide()}if(!$("#spectemplates-setting").attr("checked")&&!$("#variations-setting").attr("checked")){$("#templates").hide()}}).click(function(){$(this).trigger("toggleui")}).trigger("toggleui");if(options){loadVariations(!(options.v)?options:options.v,prices)}$("#addVariationMenu").click(function(){addVariationOptionsMenu()});$("#pricerange-facetedmenu").change(function(){if($(this).val()=="custom"){$("#pricerange-menu, #addPriceLevel").show()}else{$("#pricerange-menu, #addPriceLevel").hide()}}).change();if(priceranges){$.each(priceranges,function(i,r){addPriceLevel(r)})}if(!category){$("#title").focus()}function addPriceLevel(data){var menus=$("#pricerange-menu");var id=pricelevelsidx++;var menu=new NestedMenu(id,menus,"priceranges","",data,false,{axis:"y",scroll:false});$(menu.label).change(function(){this.value=asMoney(this.value)}).change()}function addDetail(data){var menus=$("#details-menu"),entries=$("#details-list"),addOptionButton=$("#addDetailOption"),id=detailsidx,menu=new NestedMenu(id,menus,"specs",NEW_DETAIL_DEFAULT,data,{target:entries,type:"list"});menu.items=new Array();menu.addOption=function(data){var option=new NestedMenuOption(menu.index,menu.itemsElement,menu.dataname,NEW_OPTION_DEFAULT,data,true);menu.items.push(option)};var facetedSetting=$('<li class="setting"></li>').appendTo(menu.itemsElement);var facetedMenu=$('<select name="specs['+menu.index+'][facetedmenu]"></select>').appendTo(facetedSetting);$('<option value="disabled">'+FACETED_DISABLED+"</option>").appendTo(facetedMenu);$('<option value="auto">'+FACETED_AUTO+"</option>").appendTo(facetedMenu);$('<option value="ranges">'+FACETED_RANGES+"</option>").appendTo(facetedMenu);$('<option value="custom">'+FACETED_CUSTOM+"</option>").appendTo(facetedMenu);if(data&&data.facetedmenu){facetedMenu.val(data.facetedmenu)}facetedMenu.change(function(){if($(this).val()=="disabled"||$(this).val()=="auto"){$(addOptionButton).hide();$(menu.itemsElement).find("li.option").hide()}else{$(addOptionButton).show();$(menu.itemsElement).find("li.option").show()}}).change();if(data&&data.options){$.each(data.options,function(i,r){menu.addOption(r)})}$(menu.itemsElement).sortable({axis:"y",items:"li.option",scroll:false});menu.element.unbind("click",menu.click);menu.element.click(function(){menu.selected();$(addOptionButton).unbind("click").click(menu.addOption);$(facetedMenu).change()});detailsidx++}function updateWorkflow(){$("#workflow").change(function(){setting=$(this).val();request.page=adminpage;request.id=category;if(!request.id){request.id="new"}if(setting=="new"){request.id="new";request.next=setting}if(setting=="close"){delete request.id}if(setting=="previous"){$.each(worklist,function(i,entry){if(entry.id!=category){return}if(worklist[i-1]){request.next=worklist[i-1].id}else{delete request.id}})}if(setting=="next"){$.each(worklist,function(i,entry){if(entry.id!=category){return}if(worklist[i+1]){request.next=worklist[i+1].id}else{delete request.id}})}}).change()}}); -
shopp/trunk/core/ui/orders/order.php
r831831 r865739 21 21 <?php endif; ?> 22 22 23 <?php if ( $Purchase->ispaid()): ?>23 <?php if ( $Purchase->ispaid() && ! $Purchase->isvoid() ): ?> 24 24 <div class="stamp paid"><div class="type"><?php _e('Paid','Shopp'); ?></div><div class="ing"> </div></div> 25 25 <?php elseif ($Purchase->isvoid()): ?> … … 114 114 <ul class="promos"> 115 115 <?php foreach ( $Purchase->discounts as $id => $Discount ): ?> 116 <li><small><a href="<?php echo esc_url( add_query_arg(array('page' => $this->Admin->pagename('discounts'), 'id' => $id), admin_url('admin.php'))); ?>"><?php echo esc_html($Discount->name); ?></a>< /small></li>116 <li><small><a href="<?php echo esc_url( add_query_arg(array('page' => $this->Admin->pagename('discounts'), 'id' => $id), admin_url('admin.php'))); ?>"><?php echo esc_html($Discount->name); ?></a><?php if ( isset($Discount->code) ) echo " - " . esc_html($Discount->code); ?></small></li> 117 117 <?php endforeach; ?> 118 118 </ul> … … 187 187 $Product->load_data( array('images') ); 188 188 $Image = reset($Product->images); 189 $image_id = apply_filters('shopp_order_item_image_id', $Image->id, $Item, $Product); 189 190 190 191 if ( ! empty($Image) ) { ?> 191 <img src="?siid=<?php echo $ Image->id ?>&<?php echo $Image->resizing(38, 0, 1) ?>" width="38" height="38" class="alignleft" />192 <img src="?siid=<?php echo $image_id ?>&<?php echo $Image->resizing(38, 0, 1) ?>" width="38" height="38" class="alignleft" /> 192 193 <?php 193 194 } … … 251 252 ?> 252 253 <td class="<?php echo esc_attr(join(' ',$classes)); ?>"> 253 <?php do_action( 'shopp_manage_order_' .$column.'_column_data', $column, $Product); ?>254 <?php do_action( 'shopp_manage_order_' . sanitize_key($column) .'_column_data', $column, $Product, $Item, $Purchase ); ?> 254 255 </td> 255 256 <?php -
shopp/trunk/core/ui/orders/orders.php
r831831 r865739 36 36 <button type="submit" id="update-button" name="update" value="order" class="button-secondary"><?php _e('Update','Shopp'); ?></button> 37 37 </div> 38 38 39 39 <div class="alignleft actions filtering"> 40 40 <select name="range" id="range"> … … 63 63 <tbody id="orders-table" class="list orders"> 64 64 <?php 65 $columns = get_column_headers(ShoppAdmin()->screen()); 65 66 $hidden = get_hidden_columns(ShoppAdmin()->screen()); 66 67 … … 94 95 do_action_ref_array('shopp_order_row_css',array(&$classes,&$Order)); 95 96 $even = !$even; 96 ?>97 ?> 97 98 <tr class="<?php echo join(' ',$classes); ?>"> 98 <th scope='row' class='check-column'><input type='checkbox' name='selected[]' value='<?php echo $Order->id; ?>' /></th> 99 <td class="order column-order<?php echo in_array('order',$hidden)?' hidden':''; ?>"><a class='row-title' href='<?php echo esc_url($viewurl); ?>' title='<?php printf(__('View Order #%d','Shopp'),$Order->id); ?>'><?php printf(__('Order #%d','Shopp'),$Order->id); ?></a></td> 100 <td class="name column-name"><a href="<?php echo esc_url($customerurl); ?>"><?php echo esc_html($customer); ?></a><?php echo !empty($Order->company)?"<br />".esc_html($Order->company):""; ?></td> 101 <td class="destination column-destination<?php echo in_array('destination',$hidden)?' hidden':''; ?>"><?php echo esc_html($location); ?></td> 102 <td class="txn column-txn<?php echo in_array('txn',$hidden)?' hidden':''; ?>"><?php echo $Order->txnid; ?><br /><?php echo esc_html($gateway); ?></td> 103 <td class="date column-date<?php echo in_array('date',$hidden)?' hidden':''; ?>"><?php echo date("Y/m/d",mktimestamp($Order->created)); ?><br /> 104 <strong><?php echo $statusLabels[$Order->status]; ?></strong></td> 105 <td class="total column-total<?php echo in_array('total',$hidden)?' hidden':''; ?>"><?php echo money($Order->total); ?><br /><span class="status"><?php echo $txnstatus; ?></span></td> 99 <?php 100 foreach ( $columns as $column => $column_title ) { 101 $classes = array($column,"column-$column"); 102 if ( in_array($column, $hidden) ) $classes[] = 'hidden'; 103 104 switch ( $column ) { 105 case 'cb': 106 ?> 107 <th scope='row' class='check-column'><input type='checkbox' name='selected[]' value='<?php echo esc_attr($Order->id); ?>' /></th> 108 <?php 109 break; 110 111 case 'order': 112 ?> 113 <td class="<?php echo esc_attr(join(' ', $classes)); ?>"> 114 <a class='row-title' href='<?php echo esc_url($viewurl); ?>' title='<?php printf(__('View Order #%d','Shopp'),$Order->id); ?>'><?php printf(__('Order #%d','Shopp'),$Order->id); ?></a> 115 </td> 116 <?php 117 break; 118 119 case 'name': 120 ?> 121 <td class="<?php echo esc_attr(join(' ', $classes)); ?>"> 122 <a href="<?php echo esc_url($customerurl); ?>"><?php echo esc_html($customer); ?></a><?php echo !empty($Order->company)?"<br />".esc_html($Order->company):""; ?> 123 </td> 124 <?php 125 break; 126 127 case 'destination': 128 ?> 129 <td class="<?php echo esc_attr(join(' ', $classes)); ?>"> 130 <?php echo esc_html($location); ?> 131 </td> 132 <?php 133 break; 134 135 case 'txn': 136 ?> 137 <td class="<?php echo esc_attr(join(' ', $classes)); ?>"> 138 <?php echo $Order->txnid; ?><br /><?php echo esc_html($gateway); ?> 139 </td> 140 <?php 141 break; 142 143 case 'date': 144 ?> 145 <td class="<?php echo esc_attr(join(' ', $classes)); ?>"> 146 <?php echo date("Y/m/d", mktimestamp($Order->created)); ?><br /> 147 <strong><?php echo $statusLabels[$Order->status]; ?></strong> 148 </td> 149 <?php 150 break; 151 152 case 'total': 153 ?> 154 <td class="<?php echo esc_attr(join(' ', $classes)); ?>"> 155 <?php echo money($Order->total); ?><br /><span class="status"><?php echo $txnstatus; ?></span> 156 </td> 157 <?php 158 break; 159 160 default: 161 ?> 162 <td class="<?php echo esc_attr(join(' ', $classes)); ?>"> 163 <?php do_action( 'shopp_manage_orders_custom_column', $column, $Order ); ?> 164 <?php do_action( 'shopp_manage_orders_' . santitize_key($column) . '_column', $column, $Order ); ?> 165 </td> 166 <?php 167 break; 168 169 170 } // end switch ( $column ) 171 172 } // end foreach ( $columns…) 173 ?> 106 174 </tr> 107 175 <?php endforeach; ?> -
shopp/trunk/core/ui/reports/products.php
r831831 r865739 42 42 $query = "SELECT CONCAT($id) AS id, 43 43 CONCAT(p.post_title,' ',pr.label) AS product, 44 COUNT(DISTINCT o.id) AS sold,44 SUM(o.quantity) AS sold, 45 45 COUNT(DISTINCT o.purchase) AS orders, 46 46 SUM(o.total) AS grossed -
shopp/trunk/core/ui/reports/reports.php
r821385 r865739 21 21 </div> 22 22 23 <?php $ListTable->pagination( 'top'); ?>23 <?php $ListTable->pagination( 'top' ); ?> 24 24 25 25 <div class="clear"></div> -
shopp/trunk/core/ui/settings/setup.php
r821385 r865739 76 76 <tr> 77 77 <th scope="row" valign="top"><label for="maintenance-toggle"><?php _e('Maintenance Mode','Shopp'); ?></label></th> 78 <td><input type="hidden" name="settings[maintenance]" value="off" /><input type="checkbox" name="settings[maintenance]" value="on" id="maintenance-toggle"<?php if ( shopp_setting_enabled('maintenance') ) echo ' checked="checked"'?> /><label for="maintenance-toggle"> <?php _e('Enable mainte ance mode','Shopp'); ?></label><br />78 <td><input type="hidden" name="settings[maintenance]" value="off" /><input type="checkbox" name="settings[maintenance]" value="on" id="maintenance-toggle"<?php if ( shopp_setting_enabled('maintenance') ) echo ' checked="checked"'?> /><label for="maintenance-toggle"> <?php _e('Enable maintenance mode','Shopp'); ?></label><br /> 79 79 <?php _e('All storefront pages will display a maintenance mode message.','Shopp'); ?></td> 80 80 </tr> -
shopp/trunk/core/ui/styles/admin.css
r831831 r865739 312 312 #lightbox div.progress { margin:40px 0 0 10px; } 313 313 314 .shopp .notice {-webkit-border-radius:3px;border-radius:3px;border:1px solid #e6db55;background-color:#ffffe0;margin: 5px 0 15px;padding: 0 0.6em; } 315 .shopp .notice p { margin:1em 0; } 314 #shopp-activation-nag { width:100%; box-sizing:border-box;} 315 #shopp-activation-nag .dismiss { color:#ccc; margin-right:8px; } 316 #shopp-activation-nag .dismiss:hover { color:#aaa; } 317 #shopp-activation-nag .button { float: left; margin: 8px 20px 0 0; button } 318 #shopp-activation-nag big { display:block; } 316 319 317 320 #wpcontent .form-table select.scrolling { height:auto; } … … 507 510 508 511 .orders.list .status { font-weight: bold; } 512 .orders.list .refunded .order, 513 .orders.list .refunded .total, 509 514 .orders.list .voided .order, 510 515 .orders.list .voided .total { text-decoration: line-through; } -
shopp/trunk/core/ui/styles/dashboard.css
r821385 r865739 29 29 #dashboard_shopp_inventory span.lowstock.warning { background: #C60; } 30 30 #dashboard_shopp_inventory span.lowstock.backorder { background: #C00; } 31 32 .orders.list .refunded td { text-decoration: line-through; } -
shopp/trunk/gateways/PayPal/PayPalStandard.php
r831831 r865739 6 6 * @copyright Ingenesis Limited, May 2009 7 7 * @package shopp 8 * @version 1.3 8 * @version 1.3.2 9 9 * @since 1.2 10 10 **/ … … 53 53 // add_filter('shopp_themeapi_cart_paypal', array($this, 'sendcart'), 10, 2); // provides shopp('cart.paypal') checkout button 54 54 add_filter( 'shopp_checkout_submit_button', array($this, 'submit'), 10, 3 ); // replace submit button with paypal image 55 56 // Prevent inclusive taxes from adding extra taxes to the order 57 add_filter( 'shopp_gateway_tax_amount', array($this, 'notaxinclusive' ) ); 55 58 56 59 // request handlers … … 347 350 $title = Shopp::__( 'Sending order to PayPal…' ); 348 351 $message = '<form id="' . $id . '" action="' . $this->url() . '" method="POST">' . 349 $this->form( $Purchase ) .350 '<h1>' . $title . '</h1>' .351 '<noscript>' .352 '<p>' . Shopp::__( 'Click the "Checkout with PayPal" button below to submit your order to PayPal for payment processing:' ) . '</p>' .353 '<p>' . join( '', $this->submit() ) . '</p>' .354 '</noscript>' .355 '</form>' .356 '<script type="text/javascript">document.getElementById("' . $id . '").submit();</script></body></html>';352 $this->form( $Purchase ) . 353 '<h1>' . $title . '</h1>' . 354 '<noscript>' . 355 '<p>' . Shopp::__( 'Click the "Checkout with PayPal" button below to submit your order to PayPal for payment processing:' ) . '</p>' . 356 '<p>' . join( '', $this->submit() ) . '</p>' . 357 '</noscript>' . 358 '</form>' . 359 '<script type="text/javascript">document.getElementById("' . $id . '").submit();</script></body></html>'; 357 360 358 361 wp_die( $message, $title, array( 'response' => 200 ) ); … … 502 505 $_['item_number_'.$id] = $id; 503 506 $_['item_name_'.$id] = apply_filters('paypal_freeorder_handling_label', 504 __('Shipping & Handling','Shopp'));507 __('Shipping & Handling','Shopp')); 505 508 $_['amount_'.$id] = $this->amount( max((float)$this->amount('shipping'), 0.01) ); 506 509 $_['quantity_'.$id] = 1; … … 534 537 $this->sale($Purchase); 535 538 elseif ( 'capture' === $event ) { 536 if ( ! $Purchase->capturable() ) return false; // Already captured 539 540 if ( ! $Purchase->capturable() ) 541 return ShoppOrder()->success(); // Already captured 542 537 543 if ( 'voided' === $Purchase->txnstatus ) 538 544 ShoppOrder()->invoice($Purchase); // Reinvoice for cancel-reversals … … 695 701 **/ 696 702 public function pdt () { 697 698 if ( empty(ShoppOrder()->inprogress) ) { 699 shopp_debug('PDT processing could not load in-progress order from session.'); 700 return Shopp::redirect( Shopp::url( false, 'thanks', false ) ); // Send back customer to thanks page and hope IPN takes care of it properly 701 } 703 $Order = ShoppOrder(); 702 704 703 705 if ( ! $this->pdtvalid() ) return; … … 708 710 $event = $Message->event(); 709 711 710 if ( ShoppOrder()->inprogress != $id ) {711 shopp_debug('PDT processing order did not match the inprogress order.');712 return Shopp::redirect( Shopp::url( false, 'thanks', false ) );713 }714 715 712 $Purchase = new ShoppPurchase($id); 716 713 717 if ( ! isset($Purchase->id) ||empty($Purchase->id) ) {714 if ( empty($Purchase->id) ) { 718 715 shopp_debug('PDT processing could not load the in progress order from the database.'); 719 716 return Shopp::redirect( Shopp::url(false, 'thanks', false ) ); 720 717 } 721 718 719 $Order->inprogress = $Purchase->id; 722 720 $this->process($event, $Purchase); 723 721 Shopp::redirect( Shopp::url( false, 'thanks', false ) ); … … 933 931 934 932 $this->labels(); // Initialize labels 935 936 933 } 937 934 -
shopp/trunk/license.txt
r821385 r865739 1 Table of Contents1 # Table of Contents 2 2 ===================================================================== 3 3 Section I : Credits and Copyrights 4 4 Section II : GNU General Public License 5 5 Section III : BSD License (see Credits) 6 Section IV : THE EMOGRIFIER LICENSE7 8 Section I: Credits9 ===================================================================== 6 Section IV : THE EMOGRIFIER LICENSE 7 ===================================================================== 8 ## Section I: Credits 9 10 10 Code contributors include (but not limited to): 11 11 Jonathan Davis - Ingenesis Limited … … 13 13 Marc Neuhaus 14 14 Timothy Hatcher 15 Tom Wu (see BSD License in Section III for license to this author's work) 16 Pelago, pelagodesign.com (see THE EMOGRIFIER LICENSE, Section IV) 15 Barry Hughes 16 Clifton Griffin 17 Ben Andersen 18 Lorenzo Caum 19 Tom Wu (see Section III: BSD License) 20 Pelago, pelagodesign.com (see Section IV: THE EMOGRIFIER LICENSE) 17 21 18 22 Copyrights: … … 22 26 source code files. 23 27 24 Section II : GNU General Public License 25 ===================================================================== 28 ===================================================================== 29 30 ## Section II: GNU General Public License 31 26 32 GNU GENERAL PUBLIC LICENSE 27 33 Version 3, 29 June 2007 … … 702 708 ===================================================================== 703 709 704 Section III : BSD License (see Credits) 705 ===================================================================== 706 * Permission is hereby granted, free of charge, to any person obtaining 707 * a copy of this software and associated documentation files (the 708 * "Software"), to deal in the Software without restriction, including 709 * without limitation the rights to use, copy, modify, merge, publish, 710 * distribute, sublicense, and/or sell copies of the Software, and to 711 * permit persons to whom the Software is furnished to do so, subject to 712 * the following conditions: 713 * 714 * The above copyright notice and this permission notice shall be 715 * included in all copies or substantial portions of the Software. 716 * 717 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 718 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 719 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 720 * 721 * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, 722 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER 723 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF 724 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT 725 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 726 * 727 * In addition, the following condition applies: 728 * 729 * All redistributions must retain an intact copy of this copyright notice 730 * and disclaimer. 731 * 710 ## Section III: BSD License 711 712 (see Section I: Credits) 713 714 Permission is hereby granted, free of charge, to any person obtaining 715 a copy of this software and associated documentation files (the 716 "Software"), to deal in the Software without restriction, including 717 without limitation the rights to use, copy, modify, merge, publish, 718 distribute, sublicense, and/or sell copies of the Software, and to 719 permit persons to whom the Software is furnished to do so, subject to 720 the following conditions: 721 722 The above copyright notice and this permission notice shall be 723 included in all copies or substantial portions of the Software. 724 725 THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 726 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 727 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 728 729 IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, 730 INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER 731 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF 732 THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT 733 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 734 735 In addition, the following condition applies: 736 737 All redistributions must retain an intact copy of this copyright notice 738 and disclaimer. 739 732 740 Address all questions regarding this license to: 733 741 … … 739 747 ===================================================================== 740 748 741 Section IV : THE EMOGRIFIER LICENSE (see Credits) 742 ===================================================================== 749 ## Section IV: THE EMOGRIFIER LICENSE 750 751 (see Section I: Credits) 743 752 744 753 Emogrifier is provided under the terms of the MIT license: -
shopp/trunk/readme.txt
r821385 r865739 21 21 Run sales, add new products, update inventory, ship orders. It’s all there, and it’s easy. Shopp consistently wins accolades for it’s WordPress-native administration tools giving it the most natural management experience you’ll find in a WordPress e-commerce solution. Get in, do your thing and get on with your real life. 22 22 23 E-commerce software shouldn’t tell you how to manage your business. You should be able tell your e-commerce software how you manage your business. Shopp lets you do just that. Create your own order processing labels and easily move orders through each step of the order ful lfillment workflow either automatically or take control of it yourself.23 E-commerce software shouldn’t tell you how to manage your business. You should be able tell your e-commerce software how you manage your business. Shopp lets you do just that. Create your own order processing labels and easily move orders through each step of the order fulfillment workflow either automatically or take control of it yourself. 24 24 25 25 Export orders to accounting systems like Intuit® QuickBooks®, or to spreadsheets like Microsoft® Excel®. Shopp remembers your last export date so its easy to do ongoing exports on a regular basis. … … 27 27 = Safe & Sound = 28 28 29 Your website will be in good -hands- bytesrunning on Shopp. Our comprehensive security builds on the solid toolkit of WordPress to let the good guys in and keep bad guys out. We use all the tricks of the trade plus a few ideas of our own to protect your store and your customers.29 Your website will be in good hands (or bytes) running on Shopp. Our comprehensive security builds on the solid toolkit of WordPress to let the good guys in and keep bad guys out. We use all the tricks of the trade plus a few ideas of our own to protect your store and your customers. 30 30 31 31 Shopp is so secure it passes PCI vulnerability scans every day and we can prove it! [See the McAfee SECURE seal on our website](https://www.mcafeesecure.com/RatingVerify?ref=shopplugin.net). … … 86 86 6. Click on any of the Shopp menus to start setting up your new Shopp store! 87 87 88 At a minimum you should setup a **Base of Operations** location to setup Shopp to work for your location. For details see our [Getting Started Guide](https://shopplugin.com t/docs/getting-started/)88 At a minimum you should setup a **Base of Operations** location to setup Shopp to work for your location. For details see our [Getting Started Guide](https://shopplugin.com/docs/getting-started/) 89 89 90 90 == Changelog == 91 91 92 = 1. 0=92 = 1.3 = 93 93 94 * Initial release 95 * Content templates 96 * Shortcodes 97 * Widgets 98 * Product Variants editor 99 * PayPal Standard 100 101 = 1.1 = 102 103 * Product addons 104 * Storefront Search Engine 105 * Tax system improvements 106 * Image & Script Servers 107 * Scriptabe email templates 108 * Cart Item discounts 109 * Passes PCI scans 110 * Offline Payments 111 * 2Checkout and Google Checkout included 112 * New Theme API tags 94 * Added reports with charting and exports 95 * Relabeled Promotions to Discounts 96 * Added icon font and other vector art 97 * Implemented PHP smart loading 98 * Improved checkout experience and templates 99 * Added schema.org support 100 * Refactored classes for better encapsulation and tidier interfaces 101 * Added direct URL support to storage engines 102 * Introduced support for `wp-content/shopp-addons/` directory 103 * Improved tax and discount calculations 104 * Added compound tax support 105 * Implemented totals register system 106 * Improved session handling 107 * Fixed slow queries 108 * Improved order management 109 * Redesigned unit tests 110 * implemented continuous integration developement 113 111 114 112 = 1.2 = … … 132 130 * Implemented unit tests 133 131 134 = 1. 3=132 = 1.1 = 135 133 136 * Added reports with charting and exports 137 * Relabeled Promotions to Discounts 138 * Added icon font and other vector art 139 * Implemented PHP smart loading 140 * Improved checkout experience and templates 141 * Added schema.org support 142 * Refactored classes for better encapsulation and tidier interfaces 143 * Added direct URL support to storage engines 144 * Introduced support for `wp-content/shopp-addons/` directory 145 * Improved tax and discount calculations 146 * Added compound tax support 147 * Implemented totals register system 148 * Improved session handling 149 * Fixed slow queries 150 * Improved order management 151 * Redesigned unit tests 152 * implemented continuous integration developement 134 * Product addons 135 * Storefront Search Engine 136 * Tax system improvements 137 * Image & Script Servers 138 * Scriptabe email templates 139 * Cart Item discounts 140 * Passes PCI scans 141 * Offline Payments 142 * 2Checkout and Google Checkout included 143 * New Theme API tags 144 145 = 1.0 = 146 147 * Initial release 148 * Content templates 149 * Shortcodes 150 * Widgets 151 * Product Variants editor 152 * PayPal Standard 153 153 154 154 155 == Frequently Asked Questions == … … 160 161 = Where can I see examples of Shopp in action? = 161 162 162 The [Showcase](https://shopplugin. com/showcase) has lots of live storefronts running Shopp.163 The [Showcase](https://shopplugin.net/blog/category/showcase/) has lots of live storefronts running Shopp. 163 164 164 165 = Do you have a product importer? = -
shopp/trunk/services/image.php
r831831 r865739 246 246 247 247 // Output the image 248 ob_clean(); // try to catch errant data in buffer248 @ob_clean(); // try to catch errant data in buffer 249 249 $this->Image->output($headers); 250 250 } -
shopp/trunk/storage/core/FSStorage.php
r821385 r865739 42 42 parent::__construct(); 43 43 $this->name = __('File system','Shopp'); 44 $this->webroot = apply_filters('shopp_fsstorage_webroot', trim(ABSPATH, '/'));44 $this->webroot = apply_filters('shopp_fsstorage_webroot', $_SERVER['DOCUMENT_ROOT']); 45 45 } 46 46 … … 281 281 * @return mixed bool | string 282 282 */ 283 public function direct ( $uri ) {283 public function direct ( $uri ) { 284 284 if ( defined('SHOPP_DIRECT_ASSET_URLS') && ! SHOPP_DIRECT_ASSET_URLS ) return false; 285 285 $path = $this->finddirect($uri); … … 298 298 * @return string | bool 299 299 */ 300 protected function finddirect($uri) { 301 $wpurl = get_option('siteurl'); 302 $webroot = explode('/', $this->webroot); 300 protected function finddirect ( $uri ) { 301 // The web server's document root 302 $webroot = $this->webroot; 303 304 // The base directory of WordPress 305 $wpdir = apply_filters( 'shopp_fsstorage_homedir', ABSPATH ); 306 307 // The base URL (home URL) of the site 308 $baseurl = untrailingslashit( apply_filters( 'shopp_fsstorage_homeurl', get_option( 'home' ) ) ); 303 309 304 310 // Obtain the storage path or bail out early if it is not accessible/is invalid 305 311 if ( ! ( $storagepath = $this->storagepath() ) ) return false; 306 else $storagedir = explode('/', trim($storagepath, '/') );307 312 308 313 // Ensure the file exists 309 if ( ! file_exists( $storagepath . "/$uri" )) return false;314 if ( ! file_exists( $storagepath . "/$uri" ) ) return false; 310 315 311 316 // Determine if the storage path is inside the webroot (they should have the same initial set of "segments") 312 for ($segment = 0; $segment < count($webroot); $segment++) 313 if ($webroot[$segment] !== $storagedir[$segment]) return false; 317 if ( 0 != strpos( $storagepath, $webroot ) ) return false; 318 319 // Is WordPress installed and accessed from within a subdirectory of webroot? Adjust $baseurl to remove the subdir if so 320 if ( $webroot !== $wpdir && false !== strpos($wpdir, $webroot) ) { 321 $path = untrailingslashit( str_replace( $webroot, '', $wpdir ) ); 322 $inpath = strrpos( $baseurl, $path ); 323 if ( $inpath ) $baseurl = substr( $baseurl, 0, $inpath ); 324 } 325 326 // Determine if the storage path is under the WordPress directory and if so use it as the canonical webroot 327 if ( false !== strpos($storagepath, $wpdir) && false === strpos($storagepath, $webroot) ) 328 $webroot = $wpdir; 314 329 315 330 // Supposing the image directory isn't the WP root, append the trailing component 316 if (count($storagedir) > count($this->webroot)) { 317 $trailing_component = join('/', array_slice($storagedir, count($webroot))); 318 $public_url = trailingslashit($wpurl) . $trailing_component; 319 } 320 else $public_url = $wpurl; 321 322 return trailingslashit($public_url) . $uri; 331 if ( $storagepath !== $webroot ) { 332 $path = str_replace( trailingslashit( $webroot ), '', $storagepath ); 333 $url = trailingslashit( $baseurl ) . $path; 334 } else $url = $baseurl; 335 336 return trailingslashit( $url ) . $uri; 323 337 } 324 338 -
shopp/trunk/templates/email-order.php
r821385 r865739 12 12 <?php shopp( 'purchase.receipt' ); ?> 13 13 <?php if ( shopp( 'purchase.notpaid' ) && shopp( 'checkout.get-offline-instructions' ) ) : ?> 14 < p><?php shopp( 'checkout.offline-instructions' ); ?></p>14 <?php shopp( 'checkout.offline-instructions' ); ?> 15 15 <?php endif; ?> 16 16 </div> -
shopp/trunk/templates/sidecart.php
r821385 r865739 23 23 </ul> 24 24 <?php else : ?> 25 <p class=" notice"><?php _e( 'Your cart is empty.', 'Shopp' ); ?></p>25 <p class="status notice"><?php _e( 'Your cart is empty.', 'Shopp' ); ?></p> 26 26 <?php endif; ?> 27 27 </div> -
shopp/trunk/templates/thanks.php
r821385 r865739 20 20 21 21 <?php if ( shopp( 'checkout.get-offline-instructions' ) ) : ?> 22 < p><?php shopp( 'checkout.offline-instructions' ); ?></p>22 <?php shopp( 'checkout.offline-instructions' ); ?> 23 23 <?php endif; ?> 24 24
Note: See TracChangeset
for help on using the changeset viewer.