Passed
Push — 1.0 ( 9ae6a9...0c6842 )
by Morven
08:45 queued 10s
created

CatalogueExtension::generateURLSegment()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 5
eloc 11
c 1
b 0
f 1
nc 4
nop 1
dl 0
loc 21
rs 9.6111
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
23
class CatalogueExtension extends DataExtension
24
{
25
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
26
        "URLSegment" => "Varchar",
27
        "MetaDescription" => "Text",
28
        "ExtraMeta" => "HTMLFragment(['whitelist' => ['meta', 'link']])"
29
    ];
30
31
    private static $casting = [
0 ignored issues
show
introduced by
The private property $casting is not used, and could be removed.
Loading history...
32
        'MetaTags' => 'HTMLFragment'
33
    ];
34
35
    public function updateRelativeLink(&$link, $action)
36
    {
37
        $parent = $this->owner->Parent();
38
39
        if ($parent && $parent->exists()) {
40
            $link = Controller::join_links(
41
                $parent->RelativeLink(),
42
                $this->owner->URLSegment,
43
                $action
44
            );
45
        } else {
46
            $link = Controller::join_links(
47
                $this->owner->URLSegment,
48
                $action
49
            );
50
        }
51
    }
52
53
    /**
54
     * Returns true if this is the currently active page being used to handle this request.
55
     *
56
     * @return bool
57
     */
58
    public function isCurrent()
59
    {
60
        $currentPage = Director::get_current_page();
61
62
        if ($currentPage instanceof ContentController) {
63
            $currentPage = $currentPage->data();
64
        }
65
        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...
66
            return $currentPage === $this->owner || $currentPage->ID === $this->owner->ID;
67
        }
68
        return false;
69
    }
70
71
    /**
72
     * Check if this page is in the currently active section (e.g. it is either current or one of its children is
73
     * currently being viewed).
74
     *
75
     * @return bool
76
     */
77
    public function isSection()
78
    {
79
        $is_curr = $this->isCurrent();
80
        $curr = Director::get_current_page();
81
82
        return $is_curr || (
83
            ($curr instanceof CatalogueCategory || $curr instanceof CatalogueProduct) && in_array($this->owner->ID, $curr->getAncestors()->column())
84
        );
85
    }
86
87
88
    /**
89
     * Return "link", "current" or section depending on if this page is the current page, or not on the current page but
90
     * in the current section.
91
     *
92
     * @return string
93
     */
94
    public function LinkingMode()
95
    {
96
        if ($this->isCurrent()) {
97
            return 'current';
98
        } elseif ($this->isSection()) {
99
            return 'section';
100
        } else {
101
            return 'link';
102
        }
103
    }
104
105
    /**
106
     * Return "link" or "section" depending on if this is the current section.
107
     *
108
     * @return string
109
     */
110
    public function LinkOrSection()
111
    {
112
        return $this->isSection() ? 'section' : 'link';
113
    }
114
115
    public function updateCMSFields(FieldList $fields)
116
    {
117
        // Add CMS requirements for URL Segment Field
118
        Requirements::javascript('silverstripe/cms: client/dist/js/bundle.js');
119
        Requirements::css('silverstripe/cms: client/dist/styles/bundle.css');
120
        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

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

285
    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...
286
    {
287
        return !$this->getOwner()->Disabled;
288
    }
289
}
290