Completed
Push — master ( ebbe5a...17152c )
by Scott
02:43
created

ProductsQuery::applyCustomOrder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 0
1
<?php namespace Bedard\Shop\Classes;
2
3
use Bedard\Shop\Models\Category;
4
use Bedard\Shop\Models\Product;
5
6
class ProductsQuery
7
{
8
    /**
9
     * @var \Bedard\Shop\Models\Category    The category to query products for.
10
     */
11
    protected $category;
12
13
    /**
14
     * @var array   Query parameters.
15
     */
16
    protected $params;
17
18
    /**
19
     * @var \October\Rain\Databse\Builder   Products query.
20
     */
21
    public $query;
22
23
    /**
24
     * Construct.
25
     *
26
     * @param \Bedard\Shop\Models\Category  $category
27
     * @param array                         $params
28
     */
29
    public function __construct(Category $category, array $params = [])
30
    {
31
        $this->category = $category;
32
        $this->params = $params;
33
34
        $this->buildQuery();
35
    }
36
37
    /**
38
     * Build up the products query.
39
     *
40
     * @return void
41
     */
42
    protected function buildQuery()
43
    {
44
        $this->query = Product::isEnabled()->joinPrice();
45
46
        $this->applyWhereStatements();
47
        $this->applyPagination();
48
        $this->applyOrderByStatements();
49
    }
50
51
    /**
52
     * Apply a custom sort order to a products query.
53
     *
54
     * @return void
55
     */
56
    protected function applyCustomOrder()
57
    {
58
        $this->query
59
            ->join('bedard_shop_category_product', function ($join) {
60
                $join->on('bedard_shop_products.id', '=', 'bedard_shop_category_product.product_id')
61
                    ->where('bedard_shop_category_product.category_id', '=', $this->category->id);
62
            })
63
            ->orderBy('bedard_shop_category_product.sort_order');
64
    }
65
66
    /**
67
     * Apply an order by statement to the products query.
68
     *
69
     * @return void
70
     */
71
    protected function applyOrderByStatements()
72
    {
73
        if (array_key_exists('products_sort_column', $this->params) &&
74
            array_key_exists('products_sort_direction', $this->params)) {
75
            $this->query->orderBy($this->params['products_sort_column'], $this->params['products_sort_direction']);
76
        } elseif ($this->category->isCustomSorted()) {
77
            $this->applyCustomOrder();
78
        } else {
79
            $this->query->orderBy($this->category->product_sort_column, $this->category->product_sort_direction);
80
        }
81
    }
82
83
    /**
84
     * Paginate the results.
85
     *
86
     * @return void
87
     */
88
    protected function applyPagination()
89
    {
90
        if (array_key_exists('page', $this->params) && $this->category->isPaginated()) {
91
            $resultsPerPage = $this->category->resultsPerPage();
92
            $resultsToSkip = ($this->params['page'] - 1) * $resultsPerPage;
93
94
            $this->query
95
                ->offset($resultsToSkip)
96
                ->limit($resultsPerPage);
97
        }
98
    }
99
100
    /**
101
     * Apply filters to a products query.
102
     *
103
     * @return void
104
     */
105
    protected function applyProductFilters()
106
    {
107
        $this->query->where(function ($q) {
108
            foreach ($this->category->filters as $filter) {
109
                $right = $filter->getRightClause();
110
                $q->where($filter->left, $filter->comparator, $right);
111
            }
112
        });
113
    }
114
115
    /**
116
     * Restrict our query to products that should be visible in our category.
117
     *
118
     * @return void
119
     */
120
    protected function applyWhereStatements()
121
    {
122
        // if the category is filtered, grab our products from those
123
        if ($this->category->isFiltered()) {
124
            $this->applyProductFilters();
125
        }
126
127
        // otherwise grab all products appearing in our category
128
        else {
129
            $this->query->appearingInCategory($this->category->id);
130
        }
131
    }
132
}
133