CatalogueExtension   A
last analyzed

Complexity

Total Complexity 39

Size/Duplication

Total Lines 284
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 1
Metric Value
eloc 126
c 7
b 0
f 1
dl 0
loc 284
rs 9.28
wmc 39

11 Methods

Rating   Name   Duplication   Size   Complexity  
A updateExportFields() 0 11 2
A updateRelativeLink() 0 14 3
A LinkingMode() 0 8 3
A alterCanIncludeInGoogleSitemap() 0 3 1
A LinkOrSection() 0 3 2
A isCurrent() 0 11 5
A generateURLSegment() 0 21 5
A isSection() 0 7 4
A onBeforeWrite() 0 7 3
A getControllerName() 0 32 6
B updateCMSFields() 0 82 5
1
<?php
2
3
namespace SilverCommerce\CatalogueFrontend\Extensions;
4
5
use SilverStripe\View\HTML;
6
use SilverStripe\Core\ClassInfo;
7
use SilverStripe\Dev\Deprecation;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Control\Director;
10
use SilverStripe\ORM\DataExtension;
11
use SilverStripe\View\Requirements;
12
use SilverStripe\CMS\Model\SiteTree;
13
use SilverStripe\Control\Controller;
14
use SilverStripe\Forms\TextareaField;
15
use SilverStripe\Forms\ToggleCompositeField;
16
use SilverStripe\View\Parsers\URLSegmentFilter;
17
use SilverStripe\CMS\Controllers\ContentController;
18
use SilverStripe\CMS\Forms\SiteTreeURLSegmentField;
19
use SilverCommerce\CatalogueAdmin\Model\CatalogueProduct;
20
use SilverCommerce\CatalogueAdmin\Model\CatalogueCategory;
21
use SilverCommerce\CatalogueFrontend\Control\CatalogueController;
22
use SilverStripe\Core\Manifest\ModuleLoader;
23
24
class CatalogueExtension extends DataExtension
25
{
26
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
27
        "URLSegment" => "Varchar",
28
        "MetaDescription" => "Text",
29
        "ExtraMeta" => "HTMLFragment(['whitelist' => ['meta', 'link']])"
30
    ];
31
32
    private static $casting = [
0 ignored issues
show
introduced by
The private property $casting is not used, and could be removed.
Loading history...
33
        'MetaTags' => 'HTMLFragment'
34
    ];
35
36
    /**
37
     * Add extra fields to export (including SEO )
38
     *
39
     * @return array
40
     */
41
    public function updateExportFields(&$fields)
42
    {
43
        $fields['URLSegment'] = 'URLSegment';
44
        $fields['MetaDescription'] = 'MetaDescription';
45
        $fields['ExtraMeta'] = 'ExtraMeta';
46
        
47
        $manifest = ModuleLoader::inst()->getManifest();
48
        
49
        // If SEO module installed, add extra SEO subject field
50
        if ($manifest->moduleExists('hubertusanton/silverstripe-seo')) {
51
            $fields['SEOPageSubject'] = 'SEOPageSubject';
52
        }
53
    }
54
55
    public function updateRelativeLink(&$link, $action)
56
    {
57
        $parent = $this->owner->Parent();
58
59
        if ($parent && $parent->exists()) {
60
            $link = Controller::join_links(
61
                $parent->RelativeLink(),
62
                $this->owner->URLSegment,
63
                $action
64
            );
65
        } else {
66
            $link = Controller::join_links(
67
                $this->owner->URLSegment,
68
                $action
69
            );
70
        }
71
    }
72
73
    /**
74
     * Returns true if this is the currently active page being used to handle this request.
75
     *
76
     * @return bool
77
     */
78
    public function isCurrent()
79
    {
80
        $currentPage = Director::get_current_page();
81
82
        if ($currentPage instanceof ContentController) {
83
            $currentPage = $currentPage->data();
84
        }
85
        if ($currentPage instanceof CatalogueCategory || $currentPage instanceof CatalogueProduct) {
0 ignored issues
show
introduced by
$currentPage is never a sub-type of SilverCommerce\Catalogue...\Model\CatalogueProduct.
Loading history...
86
            return $currentPage === $this->owner || $currentPage->ID === $this->owner->ID;
87
        }
88
        return false;
89
    }
90
91
    /**
92
     * Check if this page is in the currently active section (e.g. it is either current or one of its children is
93
     * currently being viewed).
94
     *
95
     * @return bool
96
     */
97
    public function isSection()
98
    {
99
        $is_curr = $this->isCurrent();
100
        $curr = Director::get_current_page();
101
102
        return $is_curr || (
103
            ($curr instanceof CatalogueCategory || $curr instanceof CatalogueProduct) && in_array($this->owner->ID, $curr->getAncestors()->column())
104
        );
105
    }
106
107
108
    /**
109
     * Return "link", "current" or section depending on if this page is the current page, or not on the current page but
110
     * in the current section.
111
     *
112
     * @return string
113
     */
114
    public function LinkingMode()
115
    {
116
        if ($this->isCurrent()) {
117
            return 'current';
118
        } elseif ($this->isSection()) {
119
            return 'section';
120
        } else {
121
            return 'link';
122
        }
123
    }
124
125
    /**
126
     * Return "link" or "section" depending on if this is the current section.
127
     *
128
     * @return string
129
     */
130
    public function LinkOrSection()
131
    {
132
        return $this->isSection() ? 'section' : 'link';
133
    }
134
135
    public function updateCMSFields(FieldList $fields)
136
    {
137
        // Add CMS requirements for URL Segment Field
138
        Requirements::javascript('silverstripe/cms: client/dist/js/bundle.js');
139
        Requirements::css('silverstripe/cms: client/dist/styles/bundle.css');
140
        Requirements::add_i18n_javascript('silverstripe/cms: client/lang', false, true);
0 ignored issues
show
Deprecated Code introduced by
The function SilverStripe\View\Requir...::add_i18n_javascript() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

140
        /** @scrutinizer ignore-deprecated */ Requirements::add_i18n_javascript('silverstripe/cms: client/lang', false, true);
Loading history...
141
142
        $fields->removeByName("MetaDescription");
143
        $fields->removeByName("ExtraMeta");
144
145
        $parent = null;
146
        $parent_link = null;
147
148
        if ($this->owner instanceof CatalogueCategory) {
149
            $parent = $this
150
                ->owner
151
                ->Parent();
152
        } elseif ($this->owner instanceof CatalogueProduct) {
153
            $parent = $this
154
                ->owner
155
                ->Categories()
156
                ->first();
157
        }
158
159
        if ($parent) {
160
            $parent_link = $parent->RelativeLink();
161
        }
162
        
163
        $baseLink = Controller::join_links(
164
            Director::absoluteBaseURL(),
165
            $parent_link
166
        );
167
168
        if (substr(rtrim($baseLink), -1) != "/") {
169
            $baseLink = $baseLink . "/";
170
        }
171
172
        $fields->addFieldToTab(
173
            "Root.Main",
174
            SiteTreeURLSegmentField::create(
175
                "URLSegment",
176
                $this->owner->fieldLabel('URLSegment')
177
            )->setURLPrefix($baseLink),
178
            'Content'
179
        );
180
181
        // Add meta info fields
182
        $fields->addFieldToTab(
183
            "Root.Main",
184
            ToggleCompositeField::create(
185
                'Metadata',
186
                _t(__CLASS__.'.MetadataToggle', 'Metadata'),
187
                [
188
                    $metaFieldDesc = TextareaField::create(
189
                        "MetaDescription",
190
                        $this->owner->fieldLabel('MetaDescription')
191
                    ),
192
                    $metaFieldExtra = TextareaField::create(
193
                        "ExtraMeta",
194
                        $this->owner->fieldLabel('ExtraMeta')
195
                    )
196
                ]
197
            )->setHeadingLevel(4)
198
        );
199
200
        // Help text for MetaData on page content editor
201
        $metaFieldDesc
202
            ->setRightTitle(
203
                _t(
204
                    'SilverStripe\\CMS\\Model\\SiteTree.METADESCHELP',
205
                    "Search engines use this content for displaying search results (although it will not influence their ranking)."
206
                )
207
            )->addExtraClass('help');
208
209
        $metaFieldExtra
210
            ->setRightTitle(
211
                _t(
212
                    'SilverStripe\\CMS\\Model\\SiteTree.METAEXTRAHELP',
213
                    "HTML tags for additional meta information. For example <meta name=\"customName\" content=\"your custom content here\" />"
214
                )
215
            )
216
            ->addExtraClass('help');
217
    }
218
219
    /**
220
     * Find the controller name by our convention of {$ModelClass}Controller
221
     *
222
     * @return string
223
     */
224
    public function getControllerName()
225
    {
226
        //default controller for SiteTree objects
227
        $controller = CatalogueController::class;
228
229
        //go through the ancestry for this class looking for
230
        $ancestry = ClassInfo::ancestry($this->owner->ClassName);
231
232
        // loop over the array going from the deepest descendant (ie: the current class) to SiteTree
233
        while ($class = array_pop($ancestry)) {
234
            //we don't need to go any deeper than the SiteTree class
235
            if ($class == CatalogueProduct::class || $class == CatalogueCategory::class) {
236
                break;
237
            }
238
            
239
            // If we have a class of "{$ClassName}Controller" then we found our controller
240
            if (class_exists($candidate = sprintf('%sController', $class))) {
241
                $controller = $candidate;
242
                break;
243
            } elseif (class_exists($candidate = sprintf('%s_Controller', $class))) {
244
                // Support the legacy underscored filename, but raise a deprecation notice
245
                Deprecation::notice(
246
                    '5.0',
247
                    'Underscored controller class names are deprecated. Use "MyController" instead of "My_Controller".',
248
                    Deprecation::SCOPE_GLOBAL
249
                );
250
                $controller = $candidate;
251
                break;
252
            }
253
        }
254
255
        return $controller;
256
    }
257
258
    /**
259
     * Generate a URL segment based on the title provided.
260
     *
261
     * @param string $title Page title
262
     *
263
     * @return string Generated url segment
264
     */
265
    public function generateURLSegment($title)
266
    {
267
        $filter = URLSegmentFilter::create();
268
        $t = $filter->filter($title);
269
270
        // Fallback to generic name if path is empty (= no valid, convertable characters)
271
        if (!$t || $t == '-' || $t == '-1') {
272
            $t = "{$this->owner->ID}";
273
        }
274
275
        // Ensure that this object has a non-conflicting URLSegment value.
276
        $existing_cats = CatalogueCategory::get()->filter('URLSegment', $t)->count();
277
        $existing_products = CatalogueProduct::get()->filter('URLSegment', $t)->count();
278
        $existing_pages = SiteTree::get()->filter('URLSegment', $t)->count();
279
        $count = (int)$existing_cats + (int)$existing_products + (int)$existing_pages;
280
        $t = ($count) ? $t . '-' . ($count + 1) : $t;
281
282
        // Hook for extensions
283
        $this->getOwner()->extend('updateURLSegment', $t, $title);
284
285
        return $t;
286
    }
287
288
    public function onBeforeWrite()
289
    {
290
        // Only call on first creation, ir if title is changed
291
        if ($this->getOwner()->isChanged('Title') || !$this->getOwner()->URLSegment) {
292
            $this->getOwner()->URLSegment = $this
293
                ->getOwner()
294
                ->generateURLSegment($this->getOwner()->Title);
295
        }
296
    }
297
    
298
    /**
299
     * Hides disabled products from googlesitemaps
300
     * Only called if googlesitemaps module is installed
301
     *
302
     * @param [type] $can
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
303
     * @return bool
304
     */
305
    public function alterCanIncludeInGoogleSitemap(&$can)
0 ignored issues
show
Unused Code introduced by
The parameter $can is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

305
    public function alterCanIncludeInGoogleSitemap(/** @scrutinizer ignore-unused */ &$can)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
306
    {
307
        return !$this->getOwner()->Disabled;
308
    }
309
}
310