Completed
Push — 0.3 ( da43ab...625b56 )
by Ben
96:17 queued 52:29
created

Page::url()   A

Complexity

Conditions 3
Paths 6

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 10
cc 3
nc 6
nop 1
crap 3
1
<?php
2
3
namespace Thinktomorrow\Chief\Pages;
4
5
use Illuminate\Support\Collection;
6
use Illuminate\Database\Eloquent\Model;
7
use Thinktomorrow\Chief\Urls\MemoizedUrlRecord;
8
use Thinktomorrow\Chief\Urls\ProvidesUrl\ProvidesUrl;
9
use Thinktomorrow\Chief\Urls\ProvidesUrl\ResolvingRoute;
10
use Thinktomorrow\Chief\Concerns\Viewable\Viewable;
11
use Thinktomorrow\Chief\Concerns\Viewable\ViewableContract;
12
use Thinktomorrow\Chief\Modules\Module;
13
use Thinktomorrow\Chief\Audit\AuditTrait;
14
use Spatie\MediaLibrary\HasMedia\HasMedia;
15
use Thinktomorrow\Chief\Concerns\Featurable;
16
use Thinktomorrow\Chief\Menu\ActsAsMenuItem;
17
use Illuminate\Database\Eloquent\SoftDeletes;
18
use Thinktomorrow\Chief\Relations\ActsAsChild;
19
use Thinktomorrow\Chief\Snippets\WithSnippets;
20
use Thinktomorrow\Chief\Relations\ActsAsParent;
21
use Thinktomorrow\Chief\Relations\ActingAsChild;
22
use Thinktomorrow\AssetLibrary\Traits\AssetTrait;
23
use Thinktomorrow\Chief\Relations\ActingAsParent;
24
use Thinktomorrow\Chief\Concerns\Morphable\Morphable;
25
use Thinktomorrow\Chief\FlatReferences\FlatReference;
26
use Thinktomorrow\Chief\Concerns\Archivable\Archivable;
27
use Dimsav\Translatable\Translatable as BaseTranslatable;
28
use Thinktomorrow\Chief\Concerns\Publishable\Publishable;
29
use Thinktomorrow\Chief\Concerns\Translatable\Translatable;
30
use Thinktomorrow\Chief\Concerns\Morphable\MorphableContract;
31
use Thinktomorrow\Chief\Concerns\Translatable\TranslatableContract;
32
use Thinktomorrow\Chief\Urls\UrlRecordNotFound;
33
34
class Page extends Model implements TranslatableContract, HasMedia, ActsAsParent, ActsAsChild, ActsAsMenuItem, MorphableContract, ViewableContract, ProvidesUrl
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 159 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
35
{
36
    use BaseTranslatable {
0 ignored issues
show
introduced by
The trait Dimsav\Translatable\Translatable requires some properties which are not provided by Thinktomorrow\Chief\Pages\Page: $translations, $useTranslationFallback, $localeKey
Loading history...
37
        getAttribute as getTranslatableAttribute;
38
    }
39
40
    use Morphable,
0 ignored issues
show
introduced by
The trait Thinktomorrow\AssetLibrary\Traits\AssetTrait requires some properties which are not provided by Thinktomorrow\Chief\Pages\Page: $assets, $pivot, $each, $locale, $mediaConversionRegistrations, $media, $type, $collection_name
Loading history...
Bug introduced by
The trait Thinktomorrow\Chief\Conc...anslatable\Translatable requires the property $translations which is not provided by Thinktomorrow\Chief\Pages\Page.
Loading history...
introduced by
The trait Thinktomorrow\Chief\Concerns\Morphable\Morphable requires some properties which are not provided by Thinktomorrow\Chief\Pages\Page: $translations, $morph_key
Loading history...
introduced by
The trait Thinktomorrow\Chief\Concerns\Viewable\Viewable requires some properties which are not provided by Thinktomorrow\Chief\Pages\Page: $content, $viewKey
Loading history...
41
        AssetTrait,
42
        Translatable,
43
        SoftDeletes,
44
        Publishable,
45
        Featurable,
46
        Archivable,
47
        AuditTrait,
48
        ActingAsParent,
49
        ActingAsChild,
50
        WithSnippets,
51
        ResolvingRoute,
52
        Viewable;
53
54
    // Explicitly mention the translation model so on inheritance the child class uses the proper default translation model
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 123 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
55
    protected $translationModel      = PageTranslation::class;
56
    protected $translationForeignKey = 'page_id';
57
    protected $translatedAttributes  = [
58
        'title', 'content', 'short', 'seo_title', 'seo_description', 'seo_keywords', 'seo_image'
59
    ];
60
61
    public $table          = "pages";
62
    protected $guarded     = [];
63
    protected $dates       = ['deleted_at', 'archived_at'];
64
    protected $with        = ['translations'];
65
66
    /** @deprecated since 0.2 */
67
    protected $pagebuilder = true;
68
69
    protected $baseViewPath;
70
    protected static $baseUrlSegment = '/';
71
72 178
    public function __construct(array $attributes = [])
73
    {
74 178
        $this->constructWithSnippets();
75
76 178
        if (!isset($this->baseViewPath)) {
77 178
            $this->baseViewPath = config('thinktomorrow.chief.base-view-paths.pages', 'pages');
78
        }
79
80 178
        parent::__construct($attributes);
81 178
    }
82
83
    /**
84
     * Parse and render any found snippets in custom
85
     * or translatable attribute values.
86
     *
87
     * @param string $value
88
     * @return mixed|null|string|string[]
89
     */
90 153
    public function getAttribute($value)
91
    {
92 153
        $value = $this->getTranslatableAttribute($value);
93
94 153
        if ($this->shouldParseWithSnippets($value)) {
95 1
            $value = $this->parseWithSnippets($value);
96
        }
97
98 153
        return $value;
99
    }
100
101
    /**
102
     * Page specific modules. We exclude text modules since they are modules in pure
103
     * technical terms and not so much as behavioural elements for the admin.
104
     *
105
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
106
     */
107 2
    public function modules()
108
    {
109 2
        return $this->hasMany(Module::class, 'page_id')->where('morph_key', '<>', 'text');
110
    }
111
112 9
    public function flatReference(): FlatReference
113
    {
114 9
        return new FlatReference(static::class, $this->id);
115
    }
116
117 67
    public function flatReferenceLabel(): string
118
    {
119 67
        if ($this->exists) {
120 54
            $status = ! $this->isPublished() ? ' [' . $this->statusAsPlainLabel().']' : null;
121
122 54
            return $this->title ? $this->title . $status : '';
0 ignored issues
show
Bug introduced by
The property title does not seem to exist on Thinktomorrow\Chief\Pages\Page. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
123
        }
124
125 17
        return '';
126
    }
127
128 5
    public function flatReferenceGroup(): string
129
    {
130 5
        $classKey = get_class($this);
131 5
        $labelSingular = property_exists($this, 'labelSingular') ? $this->labelSingular : str_singular($classKey);
0 ignored issues
show
Deprecated Code introduced by
The function str_singular() has been deprecated: Str::singular() should be used directly instead. Will be removed in Laravel 5.9. ( Ignorable by Annotation )

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

131
        $labelSingular = property_exists($this, 'labelSingular') ? $this->labelSingular : /** @scrutinizer ignore-deprecated */ str_singular($classKey);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Bug introduced by
The property labelSingular does not seem to exist on Thinktomorrow\Chief\Pages\Page. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
132
133 5
        return $labelSingular;
134
    }
135
136
    public function mediaUrls($type = null): Collection
137
    {
138
        return $this->getAllFiles($type)->map->getFileUrl();
139
    }
140
141
    public function mediaUrl($type = null): ?string
142
    {
143
        return $this->mediaUrls($type)->first();
144
    }
145
146
    public static function findPublished($id)
147
    {
148
        return static::published()->find($id);
149
    }
150
151 1
    public function scopeSortedByCreated($query)
152
    {
153 1
        $query->orderBy('created_at', 'DESC');
154 1
    }
155
156
    /** @inheritdoc */
157 47
    public function url(string $locale = null): string
158
    {
159 47
        if (!$locale) {
160 43
            $locale = app()->getLocale();
0 ignored issues
show
introduced by
The method getLocale() does not exist on Illuminate\Container\Container. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

160
            $locale = app()->/** @scrutinizer ignore-call */ getLocale();
Loading history...
161
        }
162
163
        try {
164 47
            $slug = MemoizedUrlRecord::findByModel($this, $locale)->slug;
165
166 31
            return $this->resolveUrl($locale, [$slug]);
167 18
        } catch (UrlRecordNotFound $e) {
168 18
            return '';
169
        }
170
    }
171
172 57
    public function resolveUrl(string $locale = null, $parameters = null): string
173
    {
174 57
        $routeName = config('thinktomorrow.chief.routes.name');
175
176 57
        return $this->resolveRoute($routeName, $parameters, $locale);
0 ignored issues
show
Bug introduced by
It seems like $locale can also be of type string; however, parameter $locale of Thinktomorrow\Chief\Pages\Page::resolveRoute() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

176
        return $this->resolveRoute($routeName, $parameters, /** @scrutinizer ignore-type */ $locale);
Loading history...
177
    }
178
179
    /** @inheritdoc */
180 52
    public function previewUrl(string $locale = null, bool $useFallback = true): string
181
    {
182 52
        return $this->url($locale, $useFallback).'?preview-mode';
0 ignored issues
show
Unused Code introduced by
The call to Thinktomorrow\Chief\Pages\Page::url() has too many arguments starting with $useFallback. ( Ignorable by Annotation )

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

182
        return $this->/** @scrutinizer ignore-call */ url($locale, $useFallback).'?preview-mode';

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
183
    }
184
185
186
    /** @inheritdoc */
187 51
    public static function baseUrlSegment(string $locale = null): string
188
    {
189 51
        if (!isset(static::$baseUrlSegment)) {
190
            return '/';
191
        }
192
193 51
        if (!is_array(static::$baseUrlSegment)) {
0 ignored issues
show
introduced by
The condition is_array(static::baseUrlSegment) is always false.
Loading history...
194 43
            return static::$baseUrlSegment;
195
        }
196
197
        // When an array, we try to locale the expected segment by locale
198 8
        $key = $locale ?? app()->getlocale();
199
200 8
        if (isset(static::$baseUrlSegment[$key])) {
201 8
            return static::$baseUrlSegment[$key];
202
        }
203
204
        // Fall back to last entry in case no match is found
205
        $reversedSegments = array_reverse(static::$baseUrlSegment);
206
        return reset($reversedSegments);
207
    }
208
209
    /**
210
     * @deprecated since 0.2.8: use url() instead
211
     * @return string
212
     */
213
    public function menuUrl(): string
214
    {
215
        return $this->url();
216
    }
217
218 7
    public function menuLabel(): string
219
    {
220 7
        return $this->title ?? '';
0 ignored issues
show
Bug introduced by
The property title does not seem to exist on Thinktomorrow\Chief\Pages\Page. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
221
    }
222
223
    /**
224
     * PUBLISHABLE OVERRIDES BECAUSE OF ARCHIVED STATE IS SET ELSEWHERE.
225
     * IMPROVEMENT SHOULD BE TO MANAGE THE PAGE STATES IN ONE LOCATION. eg state machine
226
     */
227 63
    public function isPublished()
228
    {
229 63
        return (!!$this->published && is_null($this->archived_at));
230
    }
231
232 62
    public function isDraft()
233
    {
234 62
        return (!$this->published && is_null($this->archived_at));
235
    }
236
237 6
    public function publish()
238
    {
239 6
        $this->published = 1;
240 6
        $this->archived_at = null;
241
242 6
        $this->save();
243 6
    }
244
245 1
    public function draft()
246
    {
247 1
        $this->published = 0;
248 1
        $this->archived_at = null;
249
250 1
        $this->save();
251 1
    }
252
253
    public function statusAsLabel()
254
    {
255
        if ($this->isPublished()) {
256
            return '<a href="'.$this->url().'" target="_blank"><em>online</em></a>';
257
        }
258
259
        if ($this->isDraft()) {
260
            return '<a href="'.$this->previewUrl().'" target="_blank" class="text-error"><em>offline</em></a>';
261
        }
262
263
        if ($this->isArchived()) {
264
            return '<span><em>gearchiveerd</em></span>';
265
        }
266
267
        return '-';
268
    }
269
270 53
    public function statusAsPlainLabel()
271
    {
272 53
        if ($this->isPublished()) {
273
            return 'online';
274
        }
275
276 53
        if ($this->isDraft()) {
277 51
            return 'offline';
278
        }
279
280 3
        if ($this->isArchived()) {
281 3
            return 'gearchiveerd';
282
        }
283
284
        return '-';
285
    }
286
287
    /**
288
     * @deprecated will no longer be used in later versions >= 0.4
289
     * @return bool
290
     */
291
    public function hasPagebuilder()
292
    {
293
        return $this->pagebuilder;
0 ignored issues
show
Deprecated Code introduced by
The property Thinktomorrow\Chief\Pages\Page::$pagebuilder has been deprecated: since 0.2 ( Ignorable by Annotation )

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

293
        return /** @scrutinizer ignore-deprecated */ $this->pagebuilder;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
294
    }
295
}
296