Passed
Push — Showing-Posts ( 88eaaf...37107c )
by Stone
01:53
created

PostModel::countNumberPosts()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 10
nop 1
dl 0
loc 23
rs 8.8333
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 the posts with details. Only selecting posts that are published
68
     * @param int $offset where to start (for pagination)
69
     * @param int $limit the number of posts
70
     * @param bool $isFrontPage extract only front page posts
71
     * @param array $select list of select limiters
72
     * @param bool $withTags
73
     * @return array list of posts
74
     * @throws \ErrorException
75
     */
76
    private function getAllPublishedPosts(
77
        int $offset,
78
        int $limit,
79
        bool $isFrontPage = false,
80
        array $select = []
81
    ): array {
82
        $sql = $this->basePostSelect();
83
        $sql .= " WHERE published = 1";
84
        if ($isFrontPage) {
85
            $sql .= " AND on_front_page = 1";
86
        }
87
        //if we have a limiting parameter
88
        if ($select != null) {
89
            foreach ($select as $col => $val) {
90
                if (!$this->isAlphaNum($col)) {
91
                    throw new Exception("Invalid column name");
92
                }
93
                $sql .= " AND $col = :$col";
94
            }
95
        }
96
        $sql .= " ORDER BY $this->postsTbl.creation_date DESC";
97
        $sql .= " LIMIT :limit OFFSET :offset";
98
        $this->query($sql);
99
        if ($select != null) {
100
            foreach ($select as $col => $val) {
101
                $this->bind(":" . $col, $val);
102
            }
103
        }
104
        $this->bind(":limit", $limit);
105
        $this->bind(":offset", $offset);
106
        $this->execute();
107
        $results = $this->fetchAll();
108
        return $this->addExcerpt($results);
109
    }
110
111
    /**
112
     * Count the number of published posts
113
     * @param array $select list of select limiters
114
     * @param bool $withTags
115
     * @return int number of posts
116
     * @throws Exception
117
     */
118
    private function countNumberPosts(array $select = []): int
119
    {
120
        $sql = "SELECT COUNT(*) FROM $this->postsTbl";
121
        if ($this->queryWithTags) {
122
            $sql .= " LEFT JOIN $this->postTagTbl ON $this->postsTbl.idposts = $this->postTagTbl.post_idposts";
123
        }
124
        $sql .= " WHERE published = 1";
125
        if ($select != null) {
126
            foreach ($select as $col => $val) {
127
                if (!$this->isAlphaNum($col)) {
128
                    throw new Exception("Invalid column name");
129
                }
130
                $sql .= " AND $col = :$col";
131
            }
132
        }
133
        $this->query($sql);
134
        if ($select != null) {
135
            foreach ($select as $col => $val) {
136
                $this->bind(":" . $col, $val);
137
            }
138
        }
139
        $this->execute();
140
        return $this->stmt->fetchColumn();
141
    }
142
143
    /**
144
     * get the total number of posts
145
     * @return int
146
     * @throws Exception
147
     */
148
    public function totalNumberPosts(): int
149
    {
150
        return $this->countNumberPosts();
151
    }
152
153
    /**
154
     * get the total number of posts in a category
155
     * @param int $categoryId
156
     * @return int
157
     * @throws Exception
158
     */
159
    public function totalNumberPostsInCategory(int $categoryId): int
160
    {
161
        return $this->countNumberPosts(["categories_idcategories" => $categoryId]);
162
    }
163
164
    /**
165
     * get the total number of posts by an author
166
     * @param int $authorId
167
     * @return int
168
     * @throws Exception
169
     */
170
    public function totalNumberPostsByAuthor(int $authorId): int
171
    {
172
        return $this->countNumberPosts(["author_iduser" => $authorId]);
173
    }
174
175
    /**
176
     * get the total number of posts with tag
177
     * @param int $tagId
178
     * @return int
179
     * @throws Exception
180
     */
181
    public function totalNumberPostsByTag(int $tagId): int
182
    {
183
        $this->queryWithTags = true;
184
        return $this->countNumberPosts(["tag_idtags" => $tagId]);
185
    }
186
187
    /**
188
     * get the list of front posts
189
     * @param int $offset
190
     * @param int $limit
191
     * @return array
192
     * @throws \ErrorException
193
     */
194
    public function getFrontPosts(int $offset = 0, int $limit = Constant::FRONT_PAGE_POSTS): array
195
    {
196
        return $this->getAllPublishedPosts($offset, $limit, true);
197
    }
198
199
    /**
200
     * get the list of all the posts.
201
     * @param int $offset
202
     * @param array $select array of limiters [$key => $val] will convert to "where $key = $val"
203
     * @param int $limit
204
     * @return array
205
     * @throws \ErrorException
206
     */
207
    public function getPosts(int $offset = 0, array $select = [], int $limit = Constant::POSTS_PER_PAGE): array
208
    {
209
        return $this->getAllPublishedPosts($offset, $limit, false, $select);
210
    }
211
212
    /**
213
     * get all the posts from a certain category
214
     * @param int $categoryId the id of the category
215
     * @param int $offset the offset for pagination
216
     * @param int $limit the limit to display
217
     * @return array list of posts in set category
218
     * @throws Exception
219
     */
220
    public function getPostsInCategory(int $categoryId, int $offset = 0, int $limit = Constant::POSTS_PER_PAGE): array
221
    {
222
        return $this->getPosts($offset, ["categories_idcategories" => $categoryId], $limit);
223
    }
224
225
    /**
226
     * get all the posts with a specific author
227
     * @param int $authorId
228
     * @param int $offset
229
     * @param int $limit
230
     * @return array
231
     * @throws \ErrorException
232
     */
233
    public function getPostsWithAuthor(int $authorId, int $offset = 0, int $limit = Constant::POSTS_PER_PAGE): array
234
    {
235
        return $this->getPosts($offset, ["author_iduser" => $authorId], $limit);
236
    }
237
238
    /**
239
     * get all the posts with a certain tag
240
     * @param int $tagId
241
     * @param int $offset
242
     * @param int $limit
243
     * @return array
244
     * @throws \ErrorException
245
     */
246
    public function getPostsWithTag(int $tagId, int $offset = 0, int $limit = Constant::POSTS_PER_PAGE): array
247
    {
248
        $this->queryWithTags = true;
249
        return $this->getPosts($offset, ["tag_idtags" => $tagId], $limit);
250
    }
251
252
    /**
253
     * get a single post from it's ID
254
     * @param int $postid the post ID to get
255
     * @return array the single post details
256
     * @throws Exception
257
     */
258
    public function getSinglePost(int $postid)
259
    {
260
        $sql = $this->basePostSelect();
261
        $sql .= " WHERE idposts = :postId;";
262
        $this->query($sql);
263
        $this->bind(":postId", $postid, \PDO::PARAM_INT);
264
        $this->execute();
265
266
        return $this->fetch();
267
    }
268
269
    /**
270
     * Create a new post
271
     * @param string $title
272
     * @param string $postImage
273
     * @param int $idCategory
274
     * @param string $article
275
     * @param int $idUser
276
     * @param int $published
277
     * @param int $onFrontPage
278
     * @param string $postSlug
279
     * @return int the id of created post
280
     * @throws Exception
281
     */
282
    public function newPost(
283
        string $title,
284
        string $postImage,
285
        int $idCategory,
286
        string $article,
287
        int $idUser,
288
        int $published,
289
        int $onFrontPage,
290
        string $postSlug
291
    ): int {
292
        $sql = "
293
          INSERT INTO $this->postsTbl (title, post_image, categories_idcategories, article, author_iduser, creation_date, last_update, published, on_front_page, posts_slug)
294
          VALUES (:title, :post_image, :categories_idcategories, :article, :author_iduser, NOW(), NOW(), :published, :on_front_page, :posts_slug)
295
        ";
296
        $this->query($sql);
297
        $this->bind(':title', $title);
298
        $this->bind(':post_image', $postImage);
299
        $this->bind(':categories_idcategories', $idCategory);
300
        $this->bind(':article', $article);
301
        $this->bind(':author_iduser', $idUser);
302
        $this->bind(':published', $published);
303
        $this->bind(':on_front_page', $onFrontPage);
304
        $this->bind(':posts_slug', $postSlug);
305
306
        $this->execute();
307
308
        return (int)$this->dbh->lastInsertId();
309
    }
310
311
    /**
312
     * Update a post with new values
313
     * @param int $postId
314
     * @param string $title
315
     * @param string $postImage
316
     * @param int $idCategory
317
     * @param string $article
318
     * @param int $published
319
     * @param int $onFrontPage
320
     * @param string $postSlug
321
     * @return bool success
322
     * @throws Exception
323
     */
324
    public function modifyPost(
325
        int $postId,
326
        string $title,
327
        string $postImage,
328
        int $idCategory,
329
        string $article,
330
        int $published,
331
        int $onFrontPage,
332
        string $postSlug
333
    ): bool {
334
        $sql = "
335
            UPDATE $this->postsTbl 
336
            SET 
337
                title = :title,
338
                post_image = :postImage,
339
                categories_idcategories = :idCategory,
340
                article = :article,
341
                last_update = NOW(),
342
                published = :published,
343
                on_front_page = :onFrontPage,
344
                posts_slug = :postSlug
345
            WHERE
346
              idposts = :postId
347
        ;";
348
        $this->query($sql);
349
        $this->bind(":title", $title);
350
        $this->bind(":postImage", $postImage);
351
        $this->bind(":idCategory", $idCategory);
352
        $this->bind(":article", $article);
353
        $this->bind(":published", $published);
354
        $this->bind(":onFrontPage", $onFrontPage);
355
        $this->bind(":postSlug", $postSlug);
356
        $this->bind(":postId", $postId);
357
358
        return $this->execute();
359
    }
360
361
362
}