Passed
Push — Showing-Posts ( 8d8b28...232f01 )
by Stone
02:10
created

PostModel::numberPosts()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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