Completed
Push — master ( 3c661d...2a57f9 )
by Will
26s queued 12s
created

src/Page/ProductCategory.php (1 issue)

1
<?php
2
3
namespace SilverShop\Page;
4
5
use Page;
6
use SilverShop\Extension\ProductVariationsExtension;
7
use SilverStripe\i18n\i18nEntityProvider;
8
use SilverStripe\ORM\DataList;
9
10
/**
11
 * Product Category provides a way to hierartically categorise products.
12
 *
13
 * It contains functions for versioning child products
14
 *
15
 * @package shop
16
 */
17
class ProductCategory extends Page implements i18nEntityProvider
18
{
19
    private static $belongs_many_many = [
20
        'Products' => Product::class,
21
    ];
22
23
    private static $singular_name = 'Category';
24
25
    private static $plural_name = 'Categories';
26
27
    private static $icon = 'silvershop/core: client/dist/images/icons/folder.gif';
28
29
    private static $table_name = 'SilverShop_ProductCategory';
30
31
    private static $default_child = 'Product';
32
33
    private static $include_child_groups = true;
34
35
    private static $page_length = 12;
36
37
    private static $must_have_price = true;
38
39
    private static $sort_options = [
40
        'Alphabetical' => 'URLSegment',
41
        'Price' => 'BasePrice',
42
    ];
43
44
    /**
45
     * Retrieve a set of products, based on the given parameters. Checks get query for sorting and pagination.
46
     *
47
     * @param bool $recursive include sub-categories
48
     *
49
     * @return DataList
50
     */
51
    public function ProductsShowable($recursive = true)
52
    {
53
        // Figure out the categories to check
54
        $groupids = array($this->ID);
55
        if (!empty($recursive) && self::config()->include_child_groups) {
56
            $groupids += $this->AllChildCategoryIDs();
57
        }
58
        $products = Product::get()->filterAny(
59
            [
60
            'ParentID' => $groupids,
61
            'ProductCategories.ID' => $groupids
62
            ]
63
        );
64
        if (self::config()->must_have_price) {
65
            if (Product::has_extension(ProductVariationsExtension::class)) {
66
                $products = $products->filterAny(
67
                    [
68
                    'BasePrice:GreaterThan' => 0,
69
                    'Variations.Price:GreaterThan' => 0
70
                    ]
71
                );
72
            } else {
73
                $products = $products->filter('BasePrice:GreaterThan', 0);
74
            }
75
        }
76
77
        $this->extend('updateProductsShowable', $products);
78
79
        return $products;
80
    }
81
82
    /**
83
     * Loop down each level of children to get all ids.
84
     */
85
    public function AllChildCategoryIDs()
86
    {
87
        $ids = [$this->ID];
88
        $allids = [];
89
        do {
90
            $ids = ProductCategory::get()
91
                ->filter('ParentID', $ids)
92
                ->getIDList();
93
            $allids += $ids;
94
        } while (!empty($ids));
95
96
        return $allids;
97
    }
98
99
    /**
100
     * Return children ProductCategory pages of this category.
101
     *
102
     * @param bool $recursive
103
     *
104
     * @return DataList
105
     */
106
    public function ChildCategories($recursive = false)
107
    {
108
        $ids = array($this->ID);
109
        if ($recursive) {
110
            $ids += $this->AllChildCategoryIDs();
111
        }
112
113
        return ProductCategory::get()->filter('ParentID', $ids);
114
    }
115
116
    /**
117
     * Recursively generate a product menu, starting from the topmost category.
118
     *
119
     * @return DataList
120
     */
121
    public function GroupsMenu()
122
    {
123
        if ($this->Parent() instanceof ProductCategory) {
124
            return $this->Parent()->GroupsMenu();
125
        }
126
        return ProductCategory::get()
127
            ->filter('ParentID', $this->ID);
128
    }
129
130
    /**
131
     * Override the nested title defaults, to show deeper nesting in the CMS.
132
     *
133
     * @param integer $level     nesting level
134
     * @param string  $separator seperate nesting with this string
135
     */
136
    public function NestedTitle($level = 10, $separator = ' > ', $field = 'MenuTitle')
137
    {
138
        $item = $this;
139
        while ($item && $level > 0) {
140
            $parts[] = $item->{$field};
141
            $item = $item->Parent;
142
            $level--;
143
        }
144
        return implode($separator, array_reverse($parts));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $parts does not seem to be defined for all execution paths leading up to this point.
Loading history...
145
    }
146
147
    public function provideI18nEntities()
148
    {
149
        $entities = parent::provideI18nEntities();
150
151
        // add the sort option keys
152
        foreach ($this->config()->sort_options as $key => $value) {
153
            $entities[__CLASS__ . '.' . $key] = array(
154
                $key,
155
                "Sort by the '$value' field",
156
            );
157
        }
158
159
        return $entities;
160
    }
161
}
162