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

PostModel::getPostSlugFromId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
}