Completed
Pull Request — master (#10)
by ARCANEDEV
31:01
created

Post   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 309
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 9

Test Coverage

Coverage 19.23%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 18
c 1
b 0
f 0
lcom 4
cbo 9
dl 0
loc 309
ccs 10
cts 52
cp 0.1923
rs 10

16 Methods

Rating   Name   Duplication   Size   Complexity  
A scopePublished() 0 5 1
A scopePublishedAt() 0 5 1
A scopeLocalized() 0 4 2
A tags() 0 4 1
A updateOne() 0 13 2
A isDraft() 0 4 1
A isPublished() 0 4 1
A hasThumbnail() 0 4 1
A getShowUrl() 0 4 1
A getEditUrl() 0 4 1
A author() 0 7 1
A createOne() 0 12 1
A extractSeoAttributes() 0 9 1
A setTitleAttribute() 0 5 1
A setContentAttribute() 0 5 1
A category() 0 4 1
1
<?php namespace Arcanesoft\Blog\Models;
2
3
use Arcanedev\LaravelSeo\Traits\Seoable;
4
use Arcanesoft\Blog\Events\Posts as PostEvents;
5
use Carbon\Carbon;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Database\Eloquent\SoftDeletes;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Facades\DB;
10
use Illuminate\Support\Str;
11
12
/**
13
 * Class     Post
14
 *
15
 * @package  Arcanesoft\Blog\Models
16
 * @author   ARCANEDEV <[email protected]>
17
 *
18
 * @property  int             id
19
 * @property  int             author_id
20
 * @property  int             category_id
21
 * @property  string          locale
22
 * @property  string          title
23
 * @property  string          slug
24
 * @property  string          excerpt
25
 * @property  string|null     thumbnail
26
 * @property  string          content_raw
27
 * @property  string          content_html
28
 * @property  bool            is_draft
29
 * @property  \Carbon\Carbon  published_at
30
 * @property  \Carbon\Carbon  created_at
31
 * @property  \Carbon\Carbon  updated_at
32
 * @property  \Carbon\Carbon  deleted_at
33
 *
34
 * @property  \Arcanesoft\Contracts\Auth\Models\User  user
35
 * @property  \Arcanesoft\Blog\Models\Category        category
36
 *
37
 * @method  static  \Illuminate\Database\Eloquent\Builder  published()
38
 * @method  static  \Illuminate\Database\Eloquent\Builder  publishedAt(int $year)
39
 * @method  static  \Illuminate\Database\Eloquent\Builder  localized(string|null $locale)
40
 */
41
class Post extends AbstractModel
42
{
43
    /* -----------------------------------------------------------------
44
     |  Constants
45
     | -----------------------------------------------------------------
46
     */
47
48
    const STATUS_DRAFT     = 'draft';
49
    const STATUS_PUBLISHED = 'published';
50
51
    /* -----------------------------------------------------------------
52
     |  Traits
53
     | -----------------------------------------------------------------
54
     */
55
56
    use Presenters\PostPresenter,
57
        Seoable,
58
        SoftDeletes;
59
60
    /* -----------------------------------------------------------------
61
     |  Properties
62
     | -----------------------------------------------------------------
63
     */
64
65
    /**
66
     * The database table used by the model
67
     *
68
     * @var string
69
     */
70
    protected $table = 'posts';
71
72
    /**
73
     * The attributes that are mass assignable
74
     *
75
     * @var array
76
     */
77
    protected $fillable = [
78
        'author_id', 'category_id', 'locale', 'title', 'excerpt', 'thumbnail', 'content', 'published_at',
79
    ];
80
81
    /**
82
     * The attributes that should be mutated to dates.
83
     *
84
     * @var array
85
     */
86
    protected $dates = ['published_at', 'deleted_at'];
87
88
    /**
89
     * The attributes that should be casted to native types.
90
     *
91
     * @var array
92
     */
93
    protected $casts = [
94
        'author_id'   => 'integer',
95
        'category_id' => 'integer',
96
        'is_draft'    => 'boolean',
97
    ];
98
99
    /**
100
     * The event map for the model.
101
     *
102
     * @var array
103
     */
104
    protected $dispatchesEvents = [
105
        'creating'  => PostEvents\PostCreating::class,
106
        'created'   => PostEvents\PostCreated::class,
107
        'updating'  => PostEvents\PostUpdating::class,
108
        'updated'   => PostEvents\PostUpdated::class,
109
        'saving'    => PostEvents\PostSaving::class,
110
        'saved'     => PostEvents\PostSaved::class,
111
        'deleting'  => PostEvents\PostDeleting::class,
112
        'deleted'   => PostEvents\PostDeleted::class,
113
        'restoring' => PostEvents\PostRestoring::class,
114
        'restored'  => PostEvents\PostRestored::class,
115
    ];
116
117
    /* -----------------------------------------------------------------
118
     |  Scopes
119
     | -----------------------------------------------------------------
120
     */
121
122
    /**
123
     * Scope only published posts.
124
     *
125
     * @param  \Illuminate\Database\Eloquent\Builder  $query
126
     *
127
     * @return \Illuminate\Database\Eloquent\Builder
128
     */
129
    public function scopePublished(Builder $query)
130
    {
131
        return $query->where('is_draft', false)
132
                     ->where('published_at', '<=', Carbon::now());
133
    }
134
135
    /**
136
     * Scope only published posts.
137
     *
138
     * @param  \Illuminate\Database\Eloquent\Builder  $query
139
     * @param  int                                    $year
140
     *
141
     * @return \Illuminate\Database\Eloquent\Builder
142
     */
143
    public function scopePublishedAt(Builder $query, $year)
144
    {
145
        return $this->scopePublished($query)
146
                    ->where(DB::raw('YEAR(published_at)'), $year);
147
    }
148
149
    /**
150
     * Scope by post's locale.
151
     *
152
     * @param  \Illuminate\Database\Eloquent\Builder  $query
153
     * @param  string|null                            $locale
154
     *
155
     * @return \Illuminate\Database\Eloquent\Builder
156
     */
157
    public function scopeLocalized(Builder $query, $locale = null)
158
    {
159
        return $query->where('locale', $locale ?: config('app.locale'));
160
    }
161
162
    /* -----------------------------------------------------------------
163
     |  Relationships
164
     | -----------------------------------------------------------------
165
     */
166
167
    /**
168
     * Author relationship.
169
     *
170
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
171
     */
172
    public function author()
173
    {
174
        return $this->belongsTo(
175
            config('auth.providers.users.model', 'App\Models\User'),
176
            'author_id'
177
        );
178
    }
179
180
    /**
181
     * Category relationship.
182
     *
183
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
184
     */
185 2
    public function category()
186
    {
187 2
        return $this->belongsTo(Category::class);
188
    }
189
190
    /**
191
     * Tags relationship.
192
     *
193
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
194
     */
195
    public function tags()
196
    {
197
        return $this->belongsToMany(Tag::class, "{$this->prefix}post_tag");
198
    }
199
200
    /* -----------------------------------------------------------------
201
     |  Getters & Setters
202
     | -----------------------------------------------------------------
203
     */
204
205
    /**
206
     * Set the title attribute.
207
     *
208
     * @param  string  $title
209
     */
210 6
    public function setTitleAttribute($title)
211
    {
212 6
        $this->attributes['title'] = $title;
213 6
        $this->attributes['slug']  = Str::slug($title);
214 6
    }
215
216
    /**
217
     * Set the content attribute.
218
     *
219
     * @param  string  $content
220
     */
221 6
    public function setContentAttribute($content)
222
    {
223 6
        $this->attributes['content_raw']  = $content;
224 6
        $this->attributes['content_html'] = markdown($content);
225 6
    }
226
227
    /* -----------------------------------------------------------------
228
     |  Main Functions
229
     | -----------------------------------------------------------------
230
     */
231
232
    /**
233
     * Create a post.
234
     *
235
     * @param  array  $attributes
236
     *
237
     * @return self
238
     */
239
    public static function createOne(array $attributes)
240
    {
241
        return tap(new self($attributes), function (self $post) use ($attributes) {
242
            $post->save();
243
244
            $post->tags()->sync($attributes['tags']);
245
246
            $post->createSeo(
247
                static::extractSeoAttributes($attributes)
248
            );
249
        });
250
    }
251
252
    /**
253
     * Create a post.
254
     *
255
     * @param  array  $inputs
256
     *
257
     * @return bool|int
258
     */
259
    public function updateOne(array $inputs)
260
    {
261
        $updated = $this->setStatusAttribute($inputs['status'])
262
            ->update(Arr::except($inputs, ['author_id']));
263
264
        $this->tags()->sync($inputs['tags']);
265
266
        $seoAttributes = static::extractSeoAttributes($inputs);
267
268
        $this->hasSeo() ? $this->updateSeo($seoAttributes) : $this->createSeo($seoAttributes);
269
270
        return $updated;
271
    }
272
273
    /* -----------------------------------------------------------------
274
     |  Check Functions
275
     | -----------------------------------------------------------------
276
     */
277
278
    /**
279
     * Check if the post's status is "draft".
280
     *
281
     * @return bool
282
     */
283
    public function isDraft()
284
    {
285
        return $this->is_draft;
286
    }
287
288
    /**
289
     * Check if the post's status is "published".
290
     *
291
     * @return bool
292
     */
293
    public function isPublished()
294
    {
295
        return ! $this->isDraft();
296
    }
297
298
    /**
299
     * Check if the post has thumbnail.
300
     *
301
     * @return bool
302
     */
303
    public function hasThumbnail()
304
    {
305
        return ! is_null($this->thumbnail);
306
    }
307
308
    /* -----------------------------------------------------------------
309
     |  Other Methods
310
     | -----------------------------------------------------------------
311
     */
312
313
    /**
314
     * Extract the seo attributes.
315
     *
316
     * @param  array  $inputs
317
     *
318
     * @return array
319
     */
320
    protected static function extractSeoAttributes(array $inputs)
321
    {
322
        return [
323
            'title'       => Arr::get($inputs, 'seo_title'),
324
            'description' => Arr::get($inputs, 'seo_description'),
325
            'keywords'    => Arr::get($inputs, 'seo_keywords'),
326
            'metas'       => Arr::get($inputs, 'seo_metas', []),
327
        ];
328
    }
329
330
    /**
331
     * Get the show url.
332
     *
333
     * @return string
334
     */
335
    public function getShowUrl()
336
    {
337
        return route('admin::blog.posts.show', [$this]);
338
    }
339
340
    /**
341
     * Get the edit url.
342
     *
343
     * @return string
344
     */
345
    public function getEditUrl()
346
    {
347
        return route('admin::blog.posts.edit', [$this]);
348
    }
349
}
350