function query() { $this->options = array_merge(array('orderby' => '(pr.stock/pr.stocked)', 'order' => 'ASC'), $this->options); extract($this->options, EXTR_SKIP); $where = array(); $where[] = "pr.inventory='on'"; $where = join(" AND ", $where); if (!in_array(strtoupper($order), array('ASC', 'DESC'))) { $order = 'DESC'; } if (!in_array(strtolower($orderby), array('inventory'))) { $orderby = '(pr.stock/pr.stocked)'; } $ordercols = "{$orderby} {$order}"; $id = "pr.product,' ',pr.id"; $product_table = WPDatabaseObject::tablename(ShoppProduct::$table); $summary_table = ShoppDatabaseObject::tablename(ProductSummary::$table); $price_table = ShoppDatabaseObject::tablename('price'); $query = "SELECT CONCAT({$id}) AS id,\n\t\t\t\t\t\t\tCONCAT(p.post_title,' ',pr.label) AS product,\n\t\t\t\t\t\t\tpr.stock AS inventory,\n\t\t\t\t\t\t\tpr.stocked AS stocked,\n\t\t\t\t\t\t\t(pr.stock/pr.stocked)*100 AS level\n\t\t\t\t\tFROM {$price_table} AS pr\n\t\t\t\t\tJOIN {$product_table} AS p ON p.ID=pr.product\n\t\t\t\t\tWHERE {$where}\n\t\t\t\t\tGROUP BY CONCAT({$id}) ORDER BY {$ordercols}"; return $query; }
public function query() { $this->options = array_merge(array('orderby' => 'orders', 'order' => 'desc'), $this->options); extract($this->options, EXTR_SKIP); $where = array(); $where[] = "o.created BETWEEN '" . sDB::mkdatetime($starts) . "' AND '" . sDB::mkdatetime($ends) . "'"; $where[] = "orders.txnstatus IN ('authed','captured')"; $where = join(" AND ", $where); if (!in_array($order, array('asc', 'desc'))) { $order = 'desc'; } if (!in_array($orderby, array('orders', 'sold', 'grossed'))) { $orderby = 'orders'; } $ordercols = "{$orderby} {$order}"; $id = "o.product,' ',o.price"; $purchase_table = ShoppDatabaseObject::tablename('purchase'); $purchased_table = ShoppDatabaseObject::tablename('purchased'); $product_table = WPDatabaseObject::tablename(ShoppProduct::$table); $price_table = ShoppDatabaseObject::tablename('price'); $query = "SELECT CONCAT({$id}) AS id,\n\t\t\t\t\t\t\tCONCAT(p.post_title,' ', IF(pr.context != 'product',pr.label,'')) AS product,\n\t\t\t\t\t\t\tpr.sku as sku,\n\t\t\t\t\t\t\tSUM(o.quantity) AS sold,\n\t\t\t\t\t\t\tCOUNT(DISTINCT o.purchase) AS orders,\n\t\t\t\t\t\t\tSUM(o.total) AS grossed\n\t\t\t\t\tFROM {$purchased_table} AS o INNER JOIN {$purchase_table} AS orders ON orders.id=o.purchase\n\t\t\t\t\tJOIN {$product_table} AS p ON p.ID=o.product\n\t\t\t\t\tJOIN {$price_table} AS pr ON pr.id=o.price\n\t\t\t\t\tWHERE {$where}\n\t\t\t\t\tGROUP BY CONCAT({$id}) ORDER BY {$ordercols}"; return $query; }
public function load() { $args = func_get_args(); if (empty($args[0])) { return false; } if (count($args) == 2) { list($id, $key) = $args; if (empty($key)) { $key = $this->_key; } $p = array($key => $id); } if (is_array($args[0])) { $p = $args[0]; } $class = get_class($this); $p['post_type'] = get_class_property($class, 'posttype'); parent::load($p); }
public function poststub() { global $wp_query; if (!$wp_query->is_main_query()) { return; } $this->filters(); $stub = new WPDatabaseObject(); $stub->init('posts'); $stub->ID = 0; $stub->post_name = ''; $stub->comment_status = 'closed'; // Force comments closed $stub->post_title = $this->title; $stub->post_content = ''; $stub->post_excerpt = ' '; // Prevent wp_trim_excerpt from calling the_content filter $stub->post_type = ShoppPages::QUERYVAR; // Setup labels $labels = new stdClass(); $labels->name = $this->title(); $stub->labels = $labels; $wp_query->queried_object = $stub; $wp_query->posts = array($stub); return $stub; }
public function loader($workflow = false) { if (!current_user_can('shopp_products')) { return; } add_screen_option('per_page', array('label' => __('Products Per Page', 'Shopp'), 'default' => 20, 'option' => 'edit_' . ShoppProduct::$posttype . '_per_page')); $per_page_option = get_current_screen()->get_option('per_page'); $defaults = array('cat' => false, 'paged' => 1, 'per_page' => $per_page_option['default'], 's' => '', 'sl' => '', 'matchcol' => '', 'view' => $this->view, 'is_inventory' => false, 'is_trash' => false, 'is_bestselling' => false, 'categories_menu' => false, 'inventory_menu' => false, 'lowstock' => 0, 'columns' => '', 'orderby' => '', 'order' => '', 'where' => array(), 'joins' => array()); $args = array_merge($defaults, $_GET); if (false !== ($user_per_page = get_user_option($per_page_option['option']))) { $args['per_page'] = $user_per_page; } extract($args, EXTR_SKIP); $url = ShoppAdminController::url($_GET); $subs = array('all' => array('label' => Shopp::__('All'), 'where' => array("p.post_status!='trash'")), 'published' => array('label' => Shopp::__('Published'), 'where' => array("p.post_status='publish'")), 'drafts' => array('label' => Shopp::__('Drafts'), 'where' => array("p.post_status='draft'")), 'onsale' => array('label' => Shopp::__('On Sale'), 'where' => array("s.sale='on' AND p.post_status != 'trash'")), 'featured' => array('label' => Shopp::__('Featured'), 'where' => array("s.featured='on' AND p.post_status != 'trash'")), 'bestselling' => array('label' => Shopp::__('Bestselling'), 'where' => array("p.post_status!='trash'", BestsellerProducts::threshold() . " < s.sold"), 'order' => 'bestselling'), 'inventory' => array('label' => Shopp::__('Inventory'), 'where' => array("s.inventory='on' AND p.post_status != 'trash'")), 'trash' => array('label' => Shopp::__('Trash'), 'where' => array("p.post_status='trash'"))); if (!shopp_setting_enabled('inventory')) { unset($subs['inventory']); } switch ($view) { case 'inventory': if (shopp_setting_enabled('inventory')) { $is_inventory = true; } else { Shopp::redirect(add_query_arg('view', null, $url), true); } break; case 'trash': $is_trash = true; break; case 'bestselling': $is_bestselling = true; break; } if ($is_inventory) { $per_page = 50; } $pagenum = absint($paged); $start = $per_page * ($pagenum - 1); $where = $subs[$this->view]['where']; if (!empty($s)) { $SearchResults = new SearchResults(array('search' => $s, 'nostock' => 'on', 'published' => 'off', 'paged' => -1)); $SearchResults->load(); $ids = array_keys($SearchResults->products); $where[] = "p.ID IN (" . join(',', $ids) . ")"; } if (!empty($cat)) { global $wpdb; $joins[$wpdb->term_relationships] = "INNER JOIN {$wpdb->term_relationships} AS tr ON (p.ID=tr.object_id)"; $joins[$wpdb->term_taxonomy] = "INNER JOIN {$wpdb->term_taxonomy} AS tt ON (tr.term_taxonomy_id=tt.term_taxonomy_id AND tt.term_id={$cat})"; if (-1 == $cat) { unset($joins[$wpdb->term_taxonomy]); $joins[$wpdb->term_relationships] = "LEFT JOIN {$wpdb->term_relationships} AS tr ON (p.ID=tr.object_id)"; $where[] = 'tr.object_id IS NULL'; } } // Detect custom taxonomies $taxonomies = array_intersect(get_object_taxonomies(ShoppProduct::$posttype), array_keys($_GET)); if (!empty($taxonomies)) { foreach ($taxonomies as $n => $taxonomy) { global $wpdb; $term = get_term_by('slug', $_GET[$taxonomy], $taxonomy); if (!empty($term->term_id)) { $joins[$wpdb->term_relationships . '_' . $n] = "INNER JOIN {$wpdb->term_relationships} AS tr{$n} ON (p.ID=tr{$n}.object_id)"; $joins[$wpdb->term_taxonomy . '_' . $n] = "INNER JOIN {$wpdb->term_taxonomy} AS tt{$n} ON (tr{$n}.term_taxonomy_id=tt{$n}.term_taxonomy_id AND tt{$n}.term_id={$term->term_id})"; } } } if (!empty($sl) && shopp_setting_enabled('inventory')) { switch ($sl) { case "ns": foreach ($where as &$w) { $w = str_replace("s.inventory='on'", "s.inventory='off'", $w); } $where[] = "s.inventory='off'"; break; case "oos": $where[] = "(s.inventory='on' AND s.stock = 0)"; break; case "ls": $ls = shopp_setting('lowstock_level'); if (empty($ls)) { $ls = '0'; } $where[] = "(s.inventory='on' AND s.lowstock != 'none')"; break; case "is": $where[] = "(s.inventory='on' AND s.stock > 0)"; } } $lowstock = shopp_setting('lowstock_level'); // Setup queries $pd = WPDatabaseObject::tablename(ShoppProduct::$table); $pt = ShoppDatabaseObject::tablename(ShoppPrice::$table); $ps = ShoppDatabaseObject::tablename(ProductSummary::$table); $orderdirs = array('asc', 'desc'); if (in_array($order, $orderdirs)) { $orderd = strtolower($order); } else { $orderd = 'asc'; } if (isset($subs[$this->view]['order'])) { $order = $subs[$this->view]['order']; } $ordercols = ''; switch ($orderby) { case 'name': $order = 'title'; if ('desc' == $orderd) { $order = 'reverse'; } break; case 'price': $order = 'lowprice'; if ('desc' == $orderd) { $order = 'highprice'; } break; case 'date': $order = 'newest'; if ('desc' == $orderd) { $order = 'oldest'; } break; case 'sold': $ordercols = 's.sold ' . $orderd; break; case 'gross': $ordercols = 's.grossed ' . $orderd; break; case 'inventory': $ordercols = 's.stock ' . $orderd; break; case 'sku': $ordercols = 'pt.sku ' . $orderd; break; } if (in_array($this->view, array('onsale', 'featured', 'inventory'))) { $joins[$ps] = "INNER JOIN {$ps} AS s ON p.ID=s.product"; } $loading = array('where' => $where, 'joins' => $joins, 'limit' => "{$start},{$per_page}", 'load' => array('categories', 'coverimages'), 'published' => false, 'order' => $order, 'nostock' => true); if (!empty($ordercols)) { unset($loading['order']); $loading['orderby'] = $ordercols; } if ($is_inventory) { // Override for inventory products $where[] = "(pt.context='product' OR pt.context='variation') AND pt.type != 'N/A'"; $loading = array('columns' => "pt.id AS stockid,IF(pt.context='variation',CONCAT(p.post_title,': ',pt.label),p.post_title) AS post_title,pt.sku AS sku,pt.stock AS stock", 'joins' => array_merge(array($pt => "LEFT JOIN {$pt} AS pt ON p.ID=pt.product"), $joins), 'where' => $where, 'groupby' => 'pt.id', 'orderby' => str_replace('s.', 'pt.', $ordercols), 'limit' => "{$start},{$per_page}", 'nostock' => true, 'published' => false); } // Override loading product meta and limiting by pagination in the workflow list if ($workflow) { unset($loading['limit']); $loading['ids'] = true; $loading['pagination'] = false; $loading['load'] = array(); } $this->products = new ProductCollection(); $this->products->load($loading); // Overpagination protection, redirect to page 1 if the requested page doesn't exist $num_pages = ceil($this->products->total / $per_page); if ($paged > 1 && $paged > $num_pages) { Shopp::redirect(add_query_arg('paged', null, $url)); } // Return a list of product keys for workflow list requests if ($workflow) { return $this->products->worklist(); } // Get sub-screen counts $subcounts = Shopp::cache_get('shopp_product_subcounts', 'shopp_admin'); if ($subcounts) { foreach ($subcounts as $name => $total) { if (isset($subs[$name])) { $subs[$name]['total'] = $total; } } } else { $subcounts = array(); foreach ($subs as $name => &$subquery) { $subquery['total'] = 0; $query = array('columns' => "count(*) AS total", 'table' => "{$pd} as p", 'joins' => array(), 'where' => array()); $query = array_merge($query, $subquery); $query['where'][] = "p.post_type='shopp_product'"; if (in_array($name, array('onsale', 'bestselling', 'featured', 'inventory'))) { $query['joins'][$ps] = "INNER JOIN {$ps} AS s ON p.ID=s.product"; } $query = sDB::select($query); $subquery['total'] = sDB::query($query, 'auto', 'col', 'total'); $subcounts[$name] = $subquery['total']; } Shopp::cache_set('shopp_product_subcounts', $subcounts, 'shopp_admin'); } $this->subs = $subs; }
function catalog() { $product_table = WPDatabaseObject::tablename(ShoppProduct::$table); $price_table = ShoppDatabaseObject::tablename(ShoppPrice::$table); // $where_notdiscounted = array("0 = FIND_IN_SET($this->id,discounts)"); $where = array(); $excludes = array(); // Go through each rule to construct an SQL query // that gets all applicable product & price ids foreach ((array) $this->rules as $rule) { if ('price' == ShoppPromo::$values[$rule['property']]) { $value = Shopp::floatval($rule['value']); } else { $value = $rule['value']; } switch ($rule['logic']) { case "Is equal to": $match = "='{$value}'"; break; case "Is not equal to": $match = "!='{$value}'"; break; case "Contains": $match = " LIKE '%{$value}%'"; break; case "Does not contain": $match = " NOT LIKE '%{$value}%'"; break; case "Begins with": $match = " LIKE '{$value}%'"; break; case "Ends with": $match = " LIKE '%{$value}'"; break; case "Is greater than": $match = "> {$value}"; break; case "Is greater than or equal to": $match = ">= {$value}"; break; case "Is less than": $match = "< {$value}"; break; case "Is less than or equal to": $match = "<= {$value}"; break; } switch ($rule['property']) { case "Name": $where[] = "p.post_title{$match}"; $joins[$product_table] = "INNER JOIN {$product_table} as p ON prc.product=p.id"; break; case "Category": $where[] = "tm.name{$match}"; if ('!' == $match[0]) { $excludes[] = "tm.name" . ltrim($match, '!'); } global $wpdb; $joins[$wpdb->term_relationships] = "INNER JOIN {$wpdb->term_relationships} AS tr ON (prc.product=tr.object_id)"; $joins[$wpdb->term_taxonomy] = "INNER JOIN {$wpdb->term_taxonomy} AS tt ON (tr.term_taxonomy_id=tt.term_taxonomy_id)"; $joins[$wpdb->terms] = "INNER JOIN {$wpdb->terms} AS tm ON (tm.term_id=tt.term_id)"; break; case "Variation": $where[] = "prc.label{$match}"; break; case "Price": $where[] = "prc.price{$match}"; break; case "Sale price": $where[] = "(prc.onsale='on' AND prc.saleprice{$match})"; break; case "Type": $where[] = "prc.type{$match}"; break; case "In stock": $where[] = "(prc.inventory='on' AND prc.stock{$match})"; break; } } $operator = 'all' == strtolower($this->search) ? ' AND ' : ' OR '; if (!empty($where)) { $where = "WHERE " . join($operator, $where); } else { $where = false; } if (!empty($joins)) { $joins = join(' ', $joins); } else { $joins = false; } // Find all the pricetags the promotion is *currently assigned* to $query = "SELECT id FROM {$price_table} WHERE 0 < FIND_IN_SET({$this->id},discounts)"; $current = sDB::query($query, 'array', 'col', 'id'); $exclude = ''; if (!empty($excludes)) { // Find all the pricetags the promotion should exclude $subquery = "SELECT prc.id FROM {$price_table} AS prc {$joins} WHERE " . join(' OR ', $excludes); $exclude = " AND prc.id NOT IN ({$subquery})"; } // Find all the pricetags the promotion is *going to apply* to $query = "SELECT prc.id,prc.product,prc.discounts FROM {$price_table} AS prc\n\t\t\t\t\t{$joins}\n\t\t\t\t\t{$where} {$exclude}"; $updates = sDB::query($query, 'array', 'col', 'id'); // Determine which records need promo added to and removed from $added = array_diff($updates, $current); $removed = array_diff($current, $updates); // Add discounts to specific rows $query = "UPDATE {$price_table}\n\t\t\t\t\tSET discounts=CONCAT(discounts,IF(discounts='','{$this->id}',',{$this->id}'))\n\t\t\t\t\tWHERE id IN (" . join(',', $added) . ")"; if (!empty($added)) { sDB::query($query); } // Remove discounts from pricetags that now don't match the conditions if (!empty($removed)) { $this->uncatalog($removed); } // Recalculate product stats for products with pricetags that have changed $Collection = new PromoProducts(array('id' => $this->id)); $Collection->load(array('load' => array('prices'), 'pagination' => false)); }