Completed
Push — master ( edf6b0...6c806a )
by Scott
02:23
created

ProductsQuery::buildQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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