PostModel::modifyPost()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 35
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 8
dl 0
loc 35
rs 9.8666
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace App\Models;
4
5
use Core\Constant;
6
use Core\Container;
7
use Core\Model;
8
use Core\Traits\StringFunctions;
9
use Exception;
10
11
class PostModel extends Model
12
{
13
    use StringFunctions;
14
15
    private $postsTbl;
16
    private $categoriesTbl;
17
    private $usersTbl;
18
    private $postTagTbl;
19
20
    //does our query need the tags table to be joined ?
21
    private $queryWithTags = false;
22
23
    public function __construct(Container $container)
24
    {
25
        parent::__construct($container);
26
        $this->postsTbl = $this->getTablePrefix("posts");
27
        $this->categoriesTbl = $this->getTablePrefix("categories");
28
        $this->usersTbl = $this->getTablePrefix("users");
29
        $this->postTagTbl = $this->getTablePrefix("posts_has_tags");
30
    }
31
32
    /**
33
     * the base Select SQL to get the information from the post table and joined tables
34
     * @param bool $withTags
35
     * @return string
36
     */
37
    private function basePostSelect(): string
38
    {
39
        $sql = "SELECT idposts, title, post_image,article,$this->postsTbl.last_update, posts_slug, categories_idcategories, category_name, published, on_front_page, categories_slug, username as author, idusers
40
                FROM $this->postsTbl 
41
                LEFT JOIN $this->categoriesTbl ON $this->postsTbl.categories_idcategories = $this->categoriesTbl.idcategories 
42
                LEFT JOIN $this->usersTbl ON $this->postsTbl.author_iduser = $this->usersTbl.idusers";
43
        if ($this->queryWithTags) {
44
            $sql .= " LEFT JOIN $this->postTagTbl ON $this->postsTbl.idposts = $this->postTagTbl.post_idposts";
45
        }
46
        return $sql;
47
    }
48
49
    /**
50
     * add the excerpt to a post list
51
     * @param array $posts
52
     * @return array
53
     * @throws \ErrorException
54
     */
55
    private function addExcerpt(array $posts): array
56
    {
57
        $sendResults = [];
58
        //we create the excerpt for the text and add it to the object
59
        foreach ($posts as $post) {
60
            $post->{'excerpt'} = $this->getExcerpt($post->article);
61
            $sendResults[] = $post;
62
        }
63
        return $sendResults;
64
    }
65
66
    /**
67
     * get all posts, no restriction
68
     */
69
    private function getAllPosts(int $offset, int $limit)
70
    {
71
        $sql = $this->basePostSelect();
72
        $sql .= " ORDER BY $this->postsTbl.creation_date DESC";
73
        $sql .= " LIMIT :limit OFFSET :offset";
74
        $this->query($sql);
75
        $this->bind(":limit", $limit);
76
        $this->bind(":offset", $offset);
77
        $this->execute();
78
        $results = $this->fetchAll();
79
        return $this->addExcerpt($results);
80
    }
81
82
    /**
83
     * get all the posts with details. Only selecting posts that are published
84
     * @param int $offset where to start (for pagination)
85
     * @param int $limit the number of posts
86
     * @param bool $isFrontPage extract only front page posts
87
     * @param array $select list of select limiters
88
     * @return array list of posts
89
     * @throws \ErrorException
90
     */
91
    private function getAllPublishedPosts(
92
        int $offset,
93
        int $limit,
94
        bool $isFrontPage = false,
95
        array $select = []
96
    ): array {
97
        $sql = $this->basePostSelect();
98
        $sql .= " WHERE published = 1";
99
        if ($isFrontPage) {
100
            $sql .= " AND on_front_page = 1";
101
        }
102
        //if we have a limiting parameter
103
        if ($select != null) {
104
            foreach ($select as $col => $val) {
105
                if (!$this->isAlphaNum($col)) {
106
                    throw new Exception("Invalid column name");
107
                }
108
                $sql .= " AND $col = :$col";
109
            }
110
        }
111
        $sql .= " ORDER BY $this->postsTbl.creation_date DESC";
112
        $sql .= " LIMIT :limit OFFSET :offset";
113
        $this->query($sql);
114
        if ($select != null) {
115
            foreach ($select as $col => $val) {
116
                $this->bind(":" . $col, $val);
117
            }
118
        }
119
        $this->bind(":limit", $limit);
120
        $this->bind(":offset", $offset);
121
        $this->execute();
122
        $results = $this->fetchAll();
123
        return $this->addExcerpt($results);
124
    }
125
126
    /**
127
     * Count the number of published posts
128
     * @param array $select list of select limiters
129
     * @param bool $published
130
     * @return int number of posts
131
     * @throws Exception
132
     */
133
    private function countNumberPosts(array $select = [], $published = true): int
134
    {
135
        $sql = "SELECT COUNT(*) FROM $this->postsTbl";
136
        if ($this->queryWithTags) {
137
            $sql .= " LEFT JOIN $this->postTagTbl ON $this->postsTbl.idposts = $this->postTagTbl.post_idposts";
138
        }
139
        if ($published) {
140
            $sql .= " WHERE published = 1";
141
        }
142
        if ($select != null) {
143
            foreach ($select as $col => $val) {
144
                if (!$this->isAlphaNum($col)) {
145
                    throw new Exception("Invalid column name");
146
                }
147
                $sql .= " AND $col = :$col";
148
            }
149
        }
150
        $this->query($sql);
151
        if ($select != null) {
152
            foreach ($select as $col => $val) {
153
                $this->bind(":" . $col, $val);
154
            }
155
        }
156
        $this->execute();
157
        return $this->stmt->fetchColumn();
158
    }
159
160
    /**
161
     * get the total number of posts
162
     * @return int
163
     * @throws Exception
164
     */
165
    public function totalNumberPosts(): int
166
    {
167
        return $this->countNumberPosts();
168
    }
169
170
    /**
171
     * get the total number of posts + unpublished
172
     * @return int
173
     * @throws Exception
174
     */
175
    public function totalNumberFullPosts(): int
176
    {
177
        return $this->countNumberPosts([], false);
178
    }
179
180
    /**
181
     * get the total number of posts in a category
182
     * @param int $categoryId
183
     * @return int
184
     * @throws Exception
185
     */
186
    public function totalNumberPostsInCategory(int $categoryId): int
187
    {
188
        return $this->countNumberPosts(["categories_idcategories" => $categoryId]);
189
    }
190
191
    /**
192
     * get the total number of posts by an author
193
     * @param int $authorId
194
     * @return int
195
     * @throws Exception
196
     */
197
    public function totalNumberPostsByAuthor(int $authorId): int
198
    {
199
        return $this->countNumberPosts(["author_iduser" => $authorId]);
200
    }
201
202
    /**
203
     * get the total number of posts with tag
204
     * @param int $tagId
205
     * @return int
206
     * @throws Exception
207
     */
208
    public function totalNumberPostsByTag(int $tagId): int
209
    {
210
        $this->queryWithTags = true;
211
        return $this->countNumberPosts(["tag_idtags" => $tagId]);
212
    }
213
214
    /**
215
     * get the list of front posts
216
     * @param int $offset
217
     * @param int $limit
218
     * @return array
219
     * @throws \ErrorException
220
     */
221
    public function getFrontPosts(int $offset = 0, int $limit = Constant::FRONT_PAGE_POSTS): array
222
    {
223
        return $this->getAllPublishedPosts($offset, $limit, true);
224
    }
225
226
    /**
227
     * get the list of all the posts.
228
     * @param int $offset
229
     * @param array $select array of limiters [$key => $val] will convert to "where $key = $val"
230
     * @param int $limit
231
     * @return array
232
     * @throws \ErrorException
233
     */
234
    public function getPosts(int $offset = 0, array $select = [], int $limit = Constant::POSTS_PER_PAGE): array
235
    {
236
        return $this->getAllPublishedPosts($offset, $limit, false, $select);
237
    }
238
239
    /**
240
     *gets all the posts
241
     * @param int $offset
242
     * @param int $limit
243
     * @return array
244
     */
245
    public function getFullPosts(int $offset = 0, int $limit = Constant::POSTS_PER_PAGE): array
246
    {
247
        return $this->getAllPosts($offset, $limit);
248
    }
249
250
251
    /**
252
     * get all the posts from a certain category
253
     * @param int $categoryId the id of the category
254
     * @param int $offset the offset for pagination
255
     * @param int $limit the limit to display
256
     * @return array list of posts in set category
257
     * @throws Exception
258
     */
259
    public function getPostsInCategory(int $categoryId, int $offset = 0, int $limit = Constant::POSTS_PER_PAGE): array
260
    {
261
        return $this->getPosts($offset, ["categories_idcategories" => $categoryId], $limit);
262
    }
263
264
    /**
265
     * get all the posts with a specific author
266
     * @param int $authorId
267
     * @param int $offset
268
     * @param int $limit
269
     * @return array
270
     * @throws \ErrorException
271
     */
272
    public function getPostsWithAuthor(int $authorId, int $offset = 0, int $limit = Constant::POSTS_PER_PAGE): array
273
    {
274
        return $this->getPosts($offset, ["author_iduser" => $authorId], $limit);
275
    }
276
277
    /**
278
     * get all the posts with a certain tag
279
     * @param int $tagId
280
     * @param int $offset
281
     * @param int $limit
282
     * @return array
283
     * @throws \ErrorException
284
     */
285
    public function getPostsWithTag(int $tagId, int $offset = 0, int $limit = Constant::POSTS_PER_PAGE): array
286
    {
287
        $this->queryWithTags = true;
288
        return $this->getPosts($offset, ["tag_idtags" => $tagId], $limit);
289
    }
290
291
    /**
292
     * get a single post from it's ID
293
     * @param int $postId the post ID to get
294
     * @return array the single post details
295
     * @throws Exception
296
     */
297
    public function getSinglePost(int $postId)
298
    {
299
        $sql = $this->basePostSelect();
300
        $sql .= " WHERE idposts = :postId;";
301
        $this->query($sql);
302
        $this->bind(":postId", $postId, \PDO::PARAM_INT);
303
        $this->execute();
304
305
        return $this->fetch();
306
    }
307
308
    /**
309
     * Create a new post
310
     * @param string $title
311
     * @param string $postImage
312
     * @param int $idCategory
313
     * @param string $article
314
     * @param int $idUser
315
     * @param int $published
316
     * @param int $onFrontPage
317
     * @param string $postSlug
318
     * @return int the id of created post
319
     * @throws Exception
320
     */
321
    public function newPost(
322
        string $title,
323
        string $postImage,
324
        int $idCategory,
325
        string $article,
326
        int $idUser,
327
        int $published,
328
        int $onFrontPage,
329
        string $postSlug
330
    ): int {
331
        $sql = "
332
          INSERT INTO $this->postsTbl (title, post_image, categories_idcategories, article, author_iduser, creation_date, last_update, published, on_front_page, posts_slug)
333
          VALUES (:title, :post_image, :categories_idcategories, :article, :author_iduser, NOW(), NOW(), :published, :on_front_page, :posts_slug)
334
        ";
335
        $this->query($sql);
336
        $this->bind(':title', $title);
337
        $this->bind(':post_image', $postImage);
338
        $this->bind(':categories_idcategories', $idCategory);
339
        $this->bind(':article', $article);
340
        $this->bind(':author_iduser', $idUser);
341
        $this->bind(':published', $published);
342
        $this->bind(':on_front_page', $onFrontPage);
343
        $this->bind(':posts_slug', $postSlug);
344
345
        $this->execute();
346
347
        return (int)$this->dbh->lastInsertId();
348
    }
349
350
    /**
351
     * Update a post with new values
352
     * @param int $postId
353
     * @param string $title
354
     * @param string $postImage
355
     * @param int $idCategory
356
     * @param string $article
357
     * @param int $published
358
     * @param int $onFrontPage
359
     * @param string $postSlug
360
     * @return bool success
361
     * @throws Exception
362
     */
363
    public function modifyPost(
364
        int $postId,
365
        string $title,
366
        string $postImage,
367
        int $idCategory,
368
        string $article,
369
        int $published,
370
        int $onFrontPage,
371
        string $postSlug
372
    ): bool {
373
        $sql = "
374
            UPDATE $this->postsTbl 
375
            SET 
376
                title = :title,
377
                post_image = :postImage,
378
                categories_idcategories = :idCategory,
379
                article = :article,
380
                last_update = NOW(),
381
                published = :published,
382
                on_front_page = :onFrontPage,
383
                posts_slug = :postSlug
384
            WHERE
385
              idposts = :postId
386
        ;";
387
        $this->query($sql);
388
        $this->bind(":title", $title);
389
        $this->bind(":postImage", $postImage);
390
        $this->bind(":idCategory", $idCategory);
391
        $this->bind(":article", $article);
392
        $this->bind(":published", $published);
393
        $this->bind(":onFrontPage", $onFrontPage);
394
        $this->bind(":postSlug", $postSlug);
395
        $this->bind(":postId", $postId);
396
397
        return $this->finalExecute();
398
    }
399
400
    /**
401
     * Removes a post from the DataBase
402
     * @param int $postId
403
     * @return bool
404
     * @throws Exception
405
     */
406
    public function deletePost(int $postId): bool
407
    {
408
        $sql = "
409
        DELETE FROM $this->postsTbl 
410
        WHERE idposts = :postId
411
        ";
412
        $this->query($sql);
413
        $this->bind(":postId", $postId);
414
        return $this->finalExecute();
415
    }
416
417
418
    /**
419
     * get the post title from ID
420
     * @param int $postId
421
     * @return string
422
     * @throws Exception
423
     */
424
    public function getTitleFromId(int $postId): string
425
    {
426
        $sql = "SELECT title from $this->postsTbl WHERE idposts = :postId";
427
        $this->query($sql);
428
        $this->bind(":postId", $postId);
429
        $this->execute();
430
        return $this->stmt->fetchColumn();
431
    }
432
433
434
    /**
435
     * Set or unset the published state of a post
436
     * @param bool $state
437
     * @param int $postId
438
     * @return bool
439
     * @throws Exception
440
     */
441
    public function setPublished(bool $state, int $postId):bool
442
    {
443
        $sql = "
444
            UPDATE $this->postsTbl 
445
            SET
446
              last_update = NOW(),
447
              published = :published
448
            WHERE
449
              idposts = :postId
450
        ";
451
        $this->query($sql);
452
        $this->bind(":postId", $postId);
453
        $this->bind(":published", $state);
454
455
        return $this->finalExecute();
456
    }
457
458
    /**
459
     * set or unset the on front page state of a post
460
     * @param bool $state
461
     * @param int $postId
462
     * @return bool
463
     * @throws Exception
464
     */
465
    public function setOnFrontPage(bool $state, int $postId):bool
466
    {
467
        $sql = "
468
            UPDATE $this->postsTbl 
469
            SET
470
              last_update = NOW(),
471
              on_front_page = :onFrontPage
472
            WHERE
473
              idposts = :postId
474
        ";
475
        $this->query($sql);
476
        $this->bind(":postId", $postId);
477
        $this->bind(":onFrontPage", $state);
478
479
        return $this->finalExecute();
480
    }
481
482
    /**
483
     *
484
     * @param string $postSlug
485
     * @return bool
486
     * @throws Exception
487
     */
488
    public function isPostSlugUnique(string $postSlug): bool
489
    {
490
        return $this->isSlugUnique($postSlug, "posts_slug", "posts");
491
    }
492
493
    /**
494
     * Get the post slug from an ID
495
     * @param int $postId
496
     * @return string
497
     * @throws \ReflectionException
498
     */
499
    public function getPostSlugFromId(int $postId)
500
    {
501
        return $this->getSlugFromId($postId, "idposts", "posts_slug");
502
    }
503
504
505
    /**
506
     * get the ID from the slug
507
     * @param string $postSlug
508
     * @return int
509
     * @throws Exception
510
     */
511
    public function getPostIdFromSlug(string $postSlug)
512
    {
513
        return $this->getIdFromSlug($postSlug, "idposts", "posts_slug");
514
    }
515
}