Test Setup Failed
Branch master (0141d3)
by Mathieu
07:06 queued 04:12
created

AbstractSection::setSectionType()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
rs 9.4285
cc 3
eloc 11
nc 3
nop 1
1
<?php
2
3
namespace Charcoal\Cms;
4
5
use \InvalidArgumentException;
6
7
// Module `charcoal-core` dependencies
8
use \Charcoal\Model\Collection;
9
10
// Module `charcoal-translation` dependencies
11
use \Charcoal\Translation\TranslationString;
12
13
// Module `charcoal-base` dependencies
14
use \Charcoal\Object\Content;
15
use \Charcoal\Object\CategorizableInterface;
16
use \Charcoal\Object\CategorizableTrait;
17
use \Charcoal\Object\HierarchicalInterface;
18
use \Charcoal\Object\HierarchicalTrait;
19
use \Charcoal\Object\RoutableInterface;
20
use \Charcoal\Object\RoutableTrait;
21
22
// Intra-module (`charcoal-cms`) dependencies
23
use \Charcoal\Cms\MetatagInterface;
24
use \Charcoal\Cms\SearchableInterface;
25
use \Charcoal\Cms\SectionInterface;
26
27
/**
28
 * A Section is a unique, reachable page.
29
 *
30
 * ## Types of sections
31
 * There can be different types of ection. 4 exists in the CMS module:
32
 * - `blocks`
33
 * - `content`
34
 * - `empty`
35
 * - `external`
36
 *
37
 * ## External implementations
38
 * Sections imlpement the following _Interface_ / _Trait_:
39
 * - From the `Charcoal\Object` namespace (in `charcoal-base`)
40
 *   - `Categorizable`
41
 *   - `Hierarchical`
42
 *   - `Routable`
43
 * - From the local `Charcoal\Cms` namespace
44
 *   - `Metatag`
45
 *   - `Searchable`
46
 *
47
 */
48
abstract class AbstractSection extends Content implements
49
    CategorizableInterface,
50
    HierarchicalInterface,
51
    MetatagInterface,
52
    RoutableInterface,
53
    SearchableInterface,
54
    SectionInterface
55
{
56
    use CategorizableTrait;
57
    use HierarchicalTrait;
58
    use MetatagTrait;
59
    use RoutableTrait;
60
    use SearchableTrait;
61
62
    const TYPE_BLOCKS = 'charcoal/cms/section/blocks';
63
    const TYPE_CONTENT = 'charcoal/cms/section/content';
64
    const TYPE_EMPTY = 'charcoal/cms/section/empty';
65
    const TYPE_EXTERNAL = 'charcoal/cms/section/external';
66
    const DEFAULT_TYPE = self::TYPE_CONTENT;
67
68
    /**
69
     * @var string $sectionType
70
     */
71
    private $sectionType = self::DEFAULT_TYPE;
72
73
    /**
74
     * @var TranslationString $title
75
     */
76
    private $title;
77
    /**
78
     * @var TranslationString $subtitle
79
     */
80
    private $subtitle;
81
    /**
82
     * @var TranslationString $content
83
     */
84
    private $content;
85
86
    /**
87
     * @var TranslationString $image
88
     */
89
    private $image;
90
91
    /**
92
     * @var mixed $templateIdent
93
     */
94
    private $templateIdent;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
95
    /**
96
     * @var array $templateOptions
97
     */
98
    private $templateOptions = [];
99
100
    /**
101
     * @var array $attachments
102
     */
103
    private $attachments;
104
105
    /**
106
     * @param string $sectionType The section type.
107
     * @throws InvalidArgumentException If the section type is not a string or not a valid section type.
108
     * @return SectionInterface Chainable
109
     */
110
    public function setSectionType($sectionType)
111
    {
112
        if (!is_string($sectionType)) {
113
            throw new InvalidArgumentException('Section type must be a string');
114
        }
115
        $validTypes = [
116
            self::TYPE_CONTENT,
117
            self::TYPE_EMPTY,
118
            self::TYPE_EXTERNAL
119
        ];
120
        if (!in_array($sectionType, $validTypes)) {
121
            throw new InvalidArgumentException('Section type is not valid');
122
        }
123
124
        $this->sectionType = $sectionType;
125
        return $this;
126
    }
127
128
    /**
129
     * @return string
130
     */
131
    public function sectionType()
132
    {
133
        return $this->sectionType;
134
    }
135
136
    /**
137
     * @param mixed $title The section title (localized).
138
     * @return TranslationString
139
     */
140
    public function setTitle($title)
141
    {
142
        $this->title = new TranslationString($title);
143
        return $this;
144
    }
145
146
    /**
147
     * @return TranslationString
148
     */
149
    public function title()
150
    {
151
        return $this->title;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->title; (Charcoal\Translation\TranslationString) is incompatible with the return type declared by the interface Charcoal\Cms\SectionInterface::title of type Charcoal\Cms\TranslationString.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
152
    }
153
154
    /**
155
     * @param mixed $subtitle The section subtitle (localized).
156
     * @return Section Chainable
157
     */
158
    public function setSubtitle($subtitle)
159
    {
160
        $this->subtitle = new TranslationString($subtitle);
161
        return $this;
162
    }
163
164
    /**
165
     * @return TranslationString
166
     */
167
    public function subtitle()
168
    {
169
        return $this->subtitle;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->subtitle; (Charcoal\Translation\TranslationString) is incompatible with the return type declared by the interface Charcoal\Cms\SectionInterface::subtitle of type Charcoal\Cms\TranslationString.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
170
    }
171
172
    /**
173
     * @param mixed $content The section content (localized).
174
     * @return Section Chainable
175
     */
176
    public function setContent($content)
177
    {
178
        $this->content = new TranslationString($content);
179
        return $this;
180
    }
181
182
    /**
183
     * @return TranslationString
184
     */
185
    public function content()
186
    {
187
        return $this->content;
188
    }
189
190
    /**
191
     * @param mixed $image The section main image (localized).
192
     * @return Section Chainable
193
     */
194
    public function setImage($image)
195
    {
196
        $this->image = new TranslationString($image);
197
        return $this;
198
    }
199
200
    /**
201
     * @return TranslationString
202
     */
203
    public function image()
204
    {
205
        return $this->image;
206
    }
207
208
    /**
209
     * @param mixed $template The section template (ident).
210
     * @return SectionInterface Chainable
211
     */
212
    public function setTemplateIdent($template)
213
    {
214
        $this->templateIdent = $template;
215
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Charcoal\Cms\AbstractSection) is incompatible with the return type of the parent method Charcoal\Model\AbstractModel::setTemplateIdent of type Charcoal\View\ViewableTrait.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
216
    }
217
218
    /**
219
     * @return mixed
220
     */
221
    public function templateIdent()
222
    {
223
        return $this->templateIdent;
224
    }
225
226
    /**
227
     * @param array $templateOptions Extra template options, if any.
228
     * @return SectionInterface Chainable
229
     */
230
    public function setTemplateOptions(array $templateOptions)
231
    {
232
        $this->templateOptions = $templateOptions;
233
        return $this;
234
    }
235
236
    /**
237
     * @return array
238
     */
239
    public function templateOptions()
240
    {
241
        return $this->templateOptions;
242
    }
243
244
    /**
245
     * @param string $type Optional type.
246
     * @return array
247
     */
248
    public function attachments($type = null)
249
    {
250
        if (!$this->attachments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->attachments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
251
            $this->attachments = $this->loadAttachments();
252
        }
253
        if ($type) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
254
            // Return only the attachments of a certain type.
255
            return $this->attachments[$type];
256
        } else {
257
            // Return all attachments, grouped by types.
258
            return $this->attachments;
259
        }
260
    }
261
262
    /**
263
     * @return array
264
     */
265
    public function loadAttachments()
266
    {
267
        return [];
268
    }
269
270
    /**
271
     * HierarchicalTrait > loadChildren
272
     *
273
     * @return array
274
     */
275
    public function loadChildren()
276
    {
277
        $source = clone($this->source());
278
        $source->reset();
279
        $source->setFilters([
280
            [
281
                'property'=>'master',
282
                'val'=>$this->id()
283
            ],
284
            [
285
                'property'=>'active',
286
                'val'=>1
287
            ]
288
        ]);
289
        $source->setOrders([
290
            [
291
                'property'=>'position',
292
                'mode'=>'asc'
293
            ]
294
        ]);
295
        $children = $source->loadItems();
296
        return $children;
297
    }
298
299
    /**
300
     * MetatagTrait > canonicalUrl
301
     *
302
     * @return string
303
     * @todo
304
     */
305
    public function canonicalUrl()
306
    {
307
        return '';
308
    }
309
310
    /**
311
     * @return TranslationString
312
     */
313
    public function defaultMetaTitle()
314
    {
315
        return $this->title();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->title(); (Charcoal\Translation\TranslationString) is incompatible with the return type declared by the interface Charcoal\Cms\MetatagInterface::defaultMetaTitle of type Charcoal\Cms\TranslationString.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
316
    }
317
318
    /**
319
     * @return TranslationString
320
     */
321
    public function defaultMetaDescription()
322
    {
323
        return $this->content();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->content(); (Charcoal\Translation\TranslationString) is incompatible with the return type declared by the interface Charcoal\Cms\MetatagInte...:defaultMetaDescription of type Charcoal\Cms\TranslationString.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
324
    }
325
326
    /**
327
     * @return TranslationString
328
     */
329
    public function defaultMetaImage()
330
    {
331
        return $this->image();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->image(); (Charcoal\Translation\TranslationString) is incompatible with the return type declared by the interface Charcoal\Cms\MetatagInterface::defaultMetaImage of type Charcoal\Cms\TranslationString.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
332
    }
333
}
334