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

PostModel::newPost()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 8
dl 0
loc 27
rs 9.8333
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 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
}