public function customerImage() { try { $slug = $this->inputfilter->clean($this->app->get('PARAMS.slug'), 'cmd'); $product = $this->model('products')->setState('filter.slug', $slug)->setState('filter.published_today', true)->setState('filter.publication_status', 'published')->setState('filter.inventory_status', 'in_stock')->getItem(); if (empty($product->id)) { throw new \Exception(); } } catch (\Exception $e) { $this->app->error('404', 'Invalid Product'); return; } $offset = abs((int) $this->app->get('PARAMS.skip')); $image_count = \Shop\Models\ProductReviews::forProduct($product, 'image_count'); if (empty($image_count) || $offset > $image_count - 1) { $this->app->error('404', 'Invalid image offset'); return; } $reviews = (new \Shop\Models\ProductReviews())->setState('filter.product_id', $product->id)->setState('filter.published_today', true)->setState('filter.publication_status', 'published')->setState('filter.has_image', true)->setState('list.limit', 1)->setParam('skip', $offset)->getItems(); if (empty($reviews[0])) { $this->app->error('404', 'Invalid image'); return; } $review = $reviews[0]; $next = $offset + 1 < $image_count ? $offset + 1 : null; $prev = $offset - 1 >= 0 ? $offset - 1 : null; $this->app->set('review', $review); $this->app->set('product', $product); $this->app->set('image_count', $image_count); $this->app->set('current', $offset); $this->app->set('next', $next); $this->app->set('prev', $prev); $html = $this->theme->renderView('Shop/Site/Views::product/review_image.php'); echo $html; }
// can this user make the review? ?> <?php if (\Shop\Models\ProductReviews::canUserReview($this->auth->getIdentity(), $item) === true) { $this->app->set('review_key', 0); echo $this->renderView('Shop/Site/Views::product/fragment_reviews_create.php'); ?> <hr /><?php } ?> <?php // are there reviews to display? ?> <?php if ($paginated = \Shop\Models\ProductReviews::forProduct($item)) { ?> <div class="reviews-content"> <?php foreach ($paginated->items as $key => $review) { ?> <div class="review" itemprop="review" itemscope itemtype="http://schema.org/Review"> <div class="row"> <div class="col-sm-2 col-md-2"> <div class="review-author" itemprop="author"><?php echo $review->user_name; ?> </div> <meta itemprop="datePublished" content="<?php
/** * Get a paginated list of the customer's purchased products * * @param \Users\Models\Users $user * @param \Shop\Models\Products $product * @return boolean */ public static function purchasedProducts(\Users\Models\Users $user, $options = array()) { $options = $options + array('limit' => 10, 'offset' => 0, 'keyword' => null); $limit = $options['limit']; $offset = $options['offset']; $model = (new \Shop\Models\Orders())->setState('filter.keyword', $options['keyword'])->setState('filter.user', $user->id)->setState('filter.status_excludes', \Shop\Constants\OrderStatus::cancelled)->setState('filter.financial_status', array(\Shop\Constants\OrderFinancialStatus::paid, \Shop\Constants\OrderFinancialStatus::authorized, \Shop\Constants\OrderFinancialStatus::pending)); $conditions = $model->conditions(); $pipeline = array(array('$match' => $conditions), array('$sort' => array('metadata.created.time' => -1)), array('$unwind' => '$items'), array('$project' => array('_id' => 0, 'title' => '$items.product.title', 'slug' => '$items.product.slug', 'product_id' => '$items.product_id', 'variant_id' => '$items.variant_id', 'price' => '$items.price', 'quantity' => '$items.quantity', 'attribute_title' => '$items.attribute_title', 'sku' => '$items.sku', 'model_number' => '$items.model_number', 'order_created' => '$metadata.created', 'order_id' => '$_id')), array('$match' => array('product_id' => array('$nin' => array('', null))))); if (!empty($options['keyword'])) { $key = new \MongoRegex('/' . $options['keyword'] . '/i'); $pipeline[] = array('$match' => array('$or' => array(array('title' => $key), array('sku' => $key), array('order_id' => $key)))); } if (isset($options['is_reviewed']) && is_bool($options['is_reviewed'])) { // get the product_ids that have been reviewed $reviewed_product_ids = \Shop\Models\ProductReviews::collection()->distinct('product_id', array('user_id' => $user->id)); if ($options['is_reviewed']) { // Add an $in filter to the pipeline for product_id $pipeline[] = array('$match' => array('product_id' => array('$in' => $reviewed_product_ids))); } else { // Add an $nin filter to the pipeline for product_id $pipeline[] = array('$match' => array('product_id' => array('$nin' => $reviewed_product_ids))); } } $count_pipeline = $pipeline; $count_pipeline[] = array('$group' => array('_id' => null, 'count' => array('$sum' => 1))); $pipeline[] = array('$skip' => $offset * $limit); $pipeline[] = array('$limit' => $limit); $agg = \Shop\Models\Orders::collection()->aggregate($pipeline); $result = null; //\Dsc\System::addMessage(\Dsc\Debug::dump($agg)); if (!empty($agg['ok']) && !empty($agg['result'])) { $agg_count = \Shop\Models\Orders::collection()->aggregate($count_pipeline); $total = isset($agg_count['result'][0]['count']) ? $agg_count['result'][0]['count'] : \Shop\Models\Orders::collection()->count($conditions); $result = new \Dsc\Pagination($total, $limit); $items = array(); foreach ($agg['result'] as $doc) { if (empty($doc['product_id'])) { continue; } $item = (new \Shop\Models\Products())->setState('filter.id', $doc['product_id'])->getItem(); if (!empty($item->id)) { $item->order_item = $doc; if (empty($item->order_item['variant_id'])) { $item->order_item['variant_id'] = null; } $item->order_item['image'] = $item->variantImage($item->order_item['variant_id']); $items[] = $item; } } $result->items = $items; } return $result; }
<strong>Ordered:</strong> <?php echo date('M j, Y', \Dsc\ArrayHelper::get($item, 'order_item.order_created.time')); ?> </p> <?php } ?> </div> </div> </div> </div> </div> <div class="col-xs-12 col-sm-7 col-md-7"> <?php if ($review = \Shop\Models\ProductReviews::hasUserReviewed($this->auth->getIdentity(), $item)) { ?> <div class="row"> <div class="col-sm-8"> <input itemprop="ratingValue" class="rating" data-size="xs" data-disabled="true" data-readonly="true" data-show-clear="false" data-show-caption="false" value="<?php echo (int) $review->rating; ?> " > </div> <div class="col-sm-4"> <?php switch ($review->{'publication.status'}) { case "published": echo '<span class="label label-success pull-right">Published</span>'; break; case "unpublished":
/** * Completes an order. * * Trigger this on newly-made orders to perform tasks such as: * Sending an email to the customer * Updating available product quantities. * Deduct giftcard.amount from any giftcards * Deduct credit.total from customer credit balance * * This does NOT do the following: * Enabling file downloads * Enabling subscriptions * as those would be triggered upon order fulfillment == $this->fulfill() * * Trigger a Listener event to notify observers */ public function accept() { // #. Update quantities foreach ($this->items as $item) { $found = false; $product = (new \Shop\Models\Products())->setState('filter.id', $item['product_id'])->getItem(); if (!empty($product->id) && (string) $product->id == (string) $item['product_id']) { foreach ($product->variants as $key => $variant) { if ((string) $variant['id'] == (string) $item['variant_id']) { $found = true; $product->{'variants.' . $key . '.quantity'} = $variant['quantity'] - 1; break; } } if ($found) { $product->save(); } } else { $message = 'Could not update variant quantities -- Invalid Product ID'; $message .= \Dsc\Debug::dump($item); $this->log($message); } } // #. Add an email to the Mailer if ($this->user_email) { $this->sendEmailNewOrder(); } $this->sendEmailNewOrderNotifications(); // #. Increase total spent and orders count $this->updateCustomerTotals(); // TODO #. Increase hit counts on coupons used in order, https://github.com/dioscouri/f3-shop/issues/90 // #. Decrease value of any used gift certificates $this->redeemGiftCards(); // #. Add a negative credit record for historical purposes $this->deductCredit(); // #. queue emails requesting product reviews \Shop\Models\ProductReviews::queueEmailForOrder($this); // trigger event $this->__accept_event = \Dsc\System::instance()->trigger('onShopAcceptOrder', array('order' => $this)); return $this; }