Passed
Pull Request — Showing-Posts (#54)
by Stone
04:55 queued 02:28
created

PostModel::modifyPost()   A

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