Issues (97)

app/Models/Post.php (10 issues)

1
<?php
2
3
namespace App\Models;
4
5
use App\Services\Markdowner;
6
use Carbon\Carbon;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\SoftDeletes;
9
use Spatie\Feed\Feedable;
10
use Spatie\Feed\FeedItem;
11
12
class Post extends Model implements Feedable
13
{
14
    use SoftDeletes;
15
16
    /**
17
     * The database table used by the model.
18
     *
19
     * @var string
20
     */
21
    protected $table = 'posts';
22
23
    /**
24
     * The attributes that are not mass assignable.
25
     *
26
     * @var array
27
     */
28
    protected $guarded = [
29
        'id',
30
    ];
31
32
    /**
33
     * Define the date field.
34
     *
35
     * @var array
36
     */
37
    protected $dates = [
38
        'published_at',
39
        'updated_at',
40
        'deleted_at',
41
    ];
42
43
    /**
44
     * Fillable fields for a Profile.
45
     *
46
     * @var array
47
     */
48
    protected $fillable = [
49
        'title',
50
        'subtitle',
51
        'content_raw',
52
        'content_html',
53
        'post_image',
54
        'meta_description',
55
        'author',
56
        'layout',
57
        'slug',
58
        'is_draft',
59
        'published_at',
60
    ];
61
62
    /**
63
     * Typecasting is awesome.
64
     *
65
     * @var array
66
     */
67
    protected $casts = [
68
        'slug'              => 'string',
69
        'title'             => 'string',
70
        'subtitle'          => 'string',
71
        'content_raw'       => 'string',
72
        'content_html'      => 'string',
73
        'post_image'        => 'string',
74
        'meta_description'  => 'string',
75
        'author'            => 'string',
76
        'layout'            => 'string',
77
        'is_draft'          => 'boolean',
78
        'published_at'      => 'datetime:Y-m-d',
79
    ];
80
81
    /**
82
     * The attributes that should be hidden for arrays.
83
     *
84
     * @var array
85
     */
86
    protected $hidden = [
87
        'layout',
88
    ];
89
90
    /**
91
     * The many-to-many relationship between pages and tags.
92
     *
93
     * @return BelongsToMany
0 ignored issues
show
The type App\Models\BelongsToMany was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
94
     */
95
    public function tags()
96
    {
97
        return $this->belongsToMany('App\Models\Tag', 'post_tag_pivot');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->belongsToM...Tag', 'post_tag_pivot') returns the type Illuminate\Database\Eloq...Relations\BelongsToMany which is incompatible with the documented return type App\Models\BelongsToMany.
Loading history...
98
    }
99
100
    /**
101
     * Set the title attribute and automatically the slug.
102
     *
103
     * @param string $value
104
     */
105
    public function setTitleAttribute($value)
106
    {
107
        $this->attributes['title'] = $value;
108
109
        if (!$this->exists) {
110
            $this->setUniqueSlug($value, '');
111
        }
112
    }
113
114
    /**
115
     * Recursive routine to set a unique slug.
116
     *
117
     * @param string $title
118
     * @param mixed  $extra
119
     */
120
    protected function setUniqueSlug($title, $extra)
121
    {
122
        $slug = str_slug($title.'-'.$extra);
0 ignored issues
show
Deprecated Code introduced by
The function str_slug() has been deprecated: Str::slug() should be used directly instead. Will be removed in Laravel 6.0. ( Ignorable by Annotation )

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

122
        $slug = /** @scrutinizer ignore-deprecated */ str_slug($title.'-'.$extra);

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...
123
124
        if (static::whereSlug($slug)->exists()) {
125
            $this->setUniqueSlug($title, $extra + 1);
126
127
            return;
128
        }
129
130
        $this->attributes['slug'] = $slug;
131
    }
132
133
    /**
134
     * Set the HTML content automatically when the raw content is set.
135
     *
136
     * @param string $value
137
     */
138
    public function setContentRawAttribute($value)
139
    {
140
        $markdown = new Markdowner();
141
142
        $this->attributes['content_raw'] = $value;
143
        $this->attributes['content_html'] = $markdown->toHTML($value);
144
    }
145
146
    /**
147
     * Sync tag relation adding new tags as needed.
148
     *
149
     * @param array $tags
150
     */
151
    public function syncTags(array $tags)
152
    {
153
        Tag::addNeededTags($tags);
154
155
        if (count($tags)) {
156
            $this->tags()->sync(
157
                Tag::whereIn('tag', $tags)->pluck('id')->all()
158
            );
159
160
            return;
161
        }
162
163
        $this->tags()->detach();
164
    }
165
166
    /**
167
     * Return the date portion of published_at.
168
     */
169
    public function getPublishDateAttribute($value)
0 ignored issues
show
The parameter $value 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

169
    public function getPublishDateAttribute(/** @scrutinizer ignore-unused */ $value)

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...
170
    {
171
        return $this->published_at;
172
    }
173
174
    /**
175
     * Alias for content_raw.
176
     */
177
    public function getContentAttribute($value)
0 ignored issues
show
The parameter $value 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

177
    public function getContentAttribute(/** @scrutinizer ignore-unused */ $value)

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...
178
    {
179
        return $this->content_raw;
180
    }
181
182
    /**
183
     * Return URL to page.
184
     *
185
     * @param Tag $tag
186
     *
187
     * @return string
188
     */
189
    public function url(Tag $tag = null)
190
    {
191
        $url = url('/'.$this->slug);
192
        if ($tag) {
193
            $url .= '?tag='.urlencode($tag->tag);
194
        }
195
196
        return $url;
197
    }
198
199
    /**
200
     * Return array of tag links.
201
     *
202
     * @param string $base
203
     *
204
     * @return array
205
     */
206
    public function tagLinks($base = '/?tag=%TAG%')
207
    {
208
        $tags = $this->tags()->pluck('tag')->all();
209
        $return = [];
210
211
        foreach ($tags as $tag) {
212
            $url = str_replace('%TAG%', urlencode($tag), $base);
213
            $return[] = '<a class="badge" href="'.$url.'">'.e($tag).'</a>';
214
        }
215
216
        return $return;
217
    }
218
219
    /**
220
     * Return next post after this one or null.
221
     *
222
     * @param Tag $tag
223
     *
224
     * @return Post
225
     */
226
    public function newerPost(Tag $tag = null)
227
    {
228
        $query = static::where('published_at', '>', $this->published_at)
229
                            ->where('published_at', '<=', Carbon::now())
230
                            ->where('is_draft', 0)
231
                            ->orderBy('published_at', 'asc');
232
        if ($tag) {
233
            $query = $query->whereHas('tags', function ($q) use ($tag) {
234
                $q->where('tag', '=', $tag->tag);
235
            });
236
        }
237
238
        return $query->first();
239
    }
240
241
    /**
242
     * Return older post before this one or null.
243
     *
244
     * @param Tag $tag
245
     *
246
     * @return Post
247
     */
248
    public function olderPost(Tag $tag = null)
249
    {
250
        $query = static::where('published_at', '<', $this->published_at)
251
                            ->where('is_draft', 0)
252
                            ->orderBy('published_at', 'desc');
253
        if ($tag) {
254
            $query = $query->whereHas('tags', function ($q) use ($tag) {
255
                $q->where('tag', '=', $tag->tag);
256
            });
257
        }
258
259
        return $query->first();
260
    }
261
262
    /**
263
     * Model RSS feed items to return.
264
     *
265
     * @return FeedItem
266
     */
267
    public function toFeedItem()
268
    {
269
        return FeedItem::create([
270
            'id'        => $this->id,
271
            'title'     => $this->title,
272
            'summary'   => $this->content_html,
273
            'updated'   => $this->updated_at,
274
            'link'      => $this->slug,
275
            'author'    => $this->author,
276
        ]);
277
    }
278
279
    /**
280
     * Get the feed items.
281
     *
282
     * @return collection
0 ignored issues
show
The type App\Models\collection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
283
     */
284
    public static function getFeedItems()
285
    {
286
        return self::allPublishedPosts()->get();
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::allPublishedPosts()->get() returns the type Illuminate\Database\Eloquent\Collection which is incompatible with the documented return type App\Models\collection.
Loading history...
287
    }
288
289
    /**
290
     * Scope a query to get only published posts with tags.
291
     *
292
     * @return collection
293
     */
294
    public function scopeAllPublishedPosts($query)
295
    {
296
        return $query->with('tags')
297
            ->publishedTimePast()
298
            ->isNotDraft()
299
            ->orderBy('published_at', 'desc');
300
    }
301
302
    /**
303
     * Scope a query to get by slug.
304
     *
305
     * @param string $slug
306
     *
307
     * @return collection
308
     */
309
    public function scopeBySlug($query, $slug)
310
    {
311
        $query->whereSlug($slug);
312
    }
313
314
    /**
315
     * Scope a query to show posts not marked as drafts.
316
     *
317
     * @return collection
318
     */
319
    public function scopeIsNotDraft($query)
320
    {
321
        $query->where('is_draft', 0);
322
    }
323
324
    /**
325
     * Scope a query to show posts that the have past the published date and time.
326
     *
327
     * @return collection
328
     */
329
    public function scopePublishedTimePast($query)
330
    {
331
        return $query->where('published_at', '<=', Carbon::now());
332
    }
333
334
    /**
335
     * Scope a query to all posts authors.
336
     *
337
     * @param \Illuminate\Database\Eloquent\Builder $query
338
     *
339
     * @return \Illuminate\Database\Eloquent\Builder
340
     */
341
    public function scopeAuthors($query)
342
    {
343
        return $query->select('author')
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->select('a...rderBy('author', 'asc') also could return the type Illuminate\Database\Query\Builder which is incompatible with the documented return type Illuminate\Database\Eloquent\Builder.
Loading history...
344
                        ->distinct()
345
                        ->orderBy('author', 'asc');
346
    }
347
348
    /**
349
     * Scope a query to only authors with published posts.
350
     *
351
     * @param \Illuminate\Database\Eloquent\Builder $query
352
     *
353
     * @return \Illuminate\Database\Eloquent\Builder
354
     */
355
    public function scopeActiveAuthors($query)
356
    {
357
        return $query->select('author')
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->select('a...rderBy('author', 'asc') also could return the type Illuminate\Database\Query\Builder which is incompatible with the documented return type Illuminate\Database\Eloquent\Builder.
Loading history...
358
                        ->publishedTimePast()
359
                        ->isNotDraft()
360
                        ->distinct()
361
                        ->orderBy('author', 'asc');
362
    }
363
364
    /**
365
     * Scope a query to only authors with published posts.
366
     *
367
     * @param \Illuminate\Database\Eloquent\Builder $query
368
     *
369
     * @return \Illuminate\Database\Eloquent\Builder
370
     */
371
    public function scopePostsByAuthors($query, $author)
372
    {
373
        return $query->with('tags')
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->with('tag...'published_at', 'desc') also could return the type Illuminate\Database\Query\Builder which is incompatible with the documented return type Illuminate\Database\Eloquent\Builder.
Loading history...
374
            ->where('author', $author)
375
            ->publishedTimePast()
376
            ->isNotDraft()
377
            ->orderBy('published_at', 'desc');
378
    }
379
}
380