Passed
Push — master ( c05d77...dd3b39 )
by Francis
01:11
created

libraries/Blogger.php (21 issues)

1
<?php
2
declare(strict_types=1);
3
defined('BASEPATH') OR exit('No direct script access allowed');
4
5
class Blogger {
6
7
  /**
8
   * Code Igniter Instance
9
   * @var object
10
   */
11
  private $ci;
12
  /**
13
   * Code Igniter DB Forge instance reference for simplicity.
14
   * @var object
15
   */
16
  private $dbforge;
17
  /**
18
   * Current Blog Table Name.
19
   * @var string
20
   */
21
  private $table_name;
22
  /**
23
   * String prefixed with ever blog name.
24
   * @var string
25
   */
26
  const TABLE_PREFIX = "blogger_posts";
27
  /**
28
   * Name of this package for simplicity.
29
   * @var string
30
   */
31
  const PACKAGE = "francis94c/blog";
32
  /**
33
   * Name of the dependent package for markdown.
34
   * @var string
35
   */
36
  const MARKDOWN_PACKAGE = "francis94c/ci-parsedown";
37
  /**
38
   * Blog post create action.
39
   * @var string
40
   */
41
  const CREATE = "create";
42
  /**
43
   * Blog post create and publish action.
44
   * @var string
45
   */
46
  const CREATE_AND_PUBLISH = "createAndPublish";
47
  /**
48
   * Blog post edit action.
49
   * @var string
50
   */
51
  const EDIT = "edit";
52
  /**
53
   * Blog post publish action.
54
   * @var string
55
   */
56
  const PUBLISH = "publish";
57
  /**
58
   * Blog post delete action.
59
   * @var string
60
   */
61
  const DELETE = "delete";
62
  /**
63
   * Blog post abort acction. This is an action taken internally when other
64
   * actions fail.
65
   * @var string
66
   */
67
  const ABORT = "abortAction";
68
  /**
69
   * Blog post no action.
70
   * @var string
71
   */
72
  const NO_ACTION = "no_action";
73
  /**
74
   * Constructor
75
   * @param mixed $params associative array of parameters. See README.md
76
   */
77
  function __construct($params=null) {
78
    $this->ci =& /** @scrutinizer ignore-call */ get_instance();
79
    $this->ci->load->database();
80
    $this->table_name = self::TABLE_PREFIX . (isset($params["name"]) ? "_" . $params["name"] : "");
81
    $this->ci->load->database();
82
    $this->ci->load->splint(self::PACKAGE, "*BlogManager", "bmanager");
83
    $this->ci->load->splint(self::MARKDOWN_PACKAGE, "+Parsedown", null, "parsedown");
84
    $this->ci->bmanager->setBlogName(isset($params["name"]) ? $params["name"] : null);
85
    $this->ci->load->helper("url");
86
  }
87
  /**
88
   * Installs a blog with the given table name and paramters.
89
   *
90
   * @param  string $blogName                Name of blog tabke to install.
91
   *
92
   * @param  string $adminTableName          Name of admi table to restrict post to.
93
   *
94
   * @param  string $adminIdColumnName       Name of the column to add a foreign
95
   *                                         key constarint to the blog table with.
96
   *
97
   * @param  int    $adminIdColumnConstraint The column constarint or limit of
98
   *                                         $adminIdColumnName.
99
   *
100
   * @return bool                            True on Success, False if Not.
101
   */
102
  public function install(string $blogName=null, string $adminTableName=null, string $adminIdColumnName=null, int $adminIdColumnConstraint=null): bool {
103
    $blogName = $blogName === null ? $this->table_name : self::TABLE_PREFIX . "_" . $blogName;
104
    $this->ci->load->dbforge();
105
    $this->ci->dbforge->add_field("id");
106
    $fields = array(
107
      "title" => array(
108
        "type"       => "VARCHAR",
109
        "constraint" => 70,
110
      ),
111
      "content" => array(
112
        "type" => "TEXT"
113
      ),
114
      "date_published" => array(
115
        "type" => "TIMESTAMP",
116
        "null" => true
117
      ),
118
      "published" => array(
119
        "type" => "TINYINT",
120
        "default" => 0
121
      ),
122
      "hits"      => array(
123
        "type"       => "INT",
124
        "constraint" => 7,
125
        "default"    => 0
126
      ),
127
      "slug"      => array(
128
        "type"       => "VARCHAR",
129
        "constraint" => 80,
130
        "unique"     => true
131
      )
132
    );
133
    $this->ci->dbforge->add_field($fields);
134
    $constrain = $adminTableName !== null && $adminIdColumnName !== null &&
135
    $adminIdColumnConstraint !== null;
136
    if ($constrain) {
137
      $this->ci->dbforge->add_field(
138
        "poster_id INT($adminIdColumnConstraint), FOREIGN KEY (poster_id) REFERENCES $adminTableName($adminIdColumnName)");
139
    }
140
    $this->ci->dbforge->add_field("date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP");
141
    $attributes = array('ENGINE' => 'InnoDB');
142
    if (!$this->ci->dbforge->create_table($blogName, true, $attributes)) return false;
143
    return true;
144
  }
145
  /**
146
   * Sets the name of the current blog table.
147
   *
148
   * @param string $name name of a blog table.
149
   *
150
   * @deprecated
151
   */
152
  public function setName(string $name): void {
153
    $this->table_name = self::TABLE_PREFIX . "_" . $name;
154
    $this->ci->bmanager->setBlogName($name != "" ? $name : null);
155
  }
156
  /**
157
   * Same as the deprecated setName. Sets the name of the current blog table.
158
   *
159
   * @param string $blog [description]
160
   */
161
  public function setBlog(string $blog): void {
162
    $this->table_name = self::TABLE_PREFIX . "_" . $blog;
163
    $this->ci->bmanager->setBlogName($blog != "" ? $blog : null);
164
  }
165
  /**
166
   * Gets the name of the blog.
167
   * @return string The name of the blog.
168
   */
169
  public function getName(): string {
170
    return $this->table_name;
171
  }
172
  /**
173
   * Loads/echoes the client side scripts needed for the blog to render it's
174
   * post editor and other views.
175
   *
176
   * @param  bool $w3css If true, additionally loads the W3.CSS file for additional
177
   *                     styling. Defaults internally on Blogmanager to true
178
   */
179
  private function loadScripts(bool $w3css): void {
180
    $this->ci->load->splint(self::PACKAGE, "-header_scripts", array(
181
      "w3css" => $w3css
182
    ));
183
  }
184
  /**
185
   * Returns the W3.CSS client side script loading tag.
186
   * @return string W3.CSS link tag.
187
   */
188
  public function w3css(): string {
189
    return "<link rel=\"stylesheet\" href=\"https://www.w3schools.com/w3css/4/w3.css\">";
190
  }
191
  /**
192
   * Returns the Fonts Awesome CSS link loading tag.
193
   * @return string Fonts Awesome CSS link loading tag.
194
   */
195
  public function fontsAwesome(): string {
196
    return "<link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.3.1/css/all.css\"";
197
  }
198
  /**
199
   * Echoes to the browser a 'SimpleMDE' markdown editor for editing post
200
   * contents, as part of a form.
201
   *
202
   * @param  string  $callback The URI callback that will be passed to the Code
203
   *                           Igniter form_open method when outputing the form.
204
   *                           The call back is where you should read the contents
205
   *                           of the submited form.
206
   *                           The contents of the form should be read or handled
207
   *                           by a call to the 'savePost($posterId)' function.
208
   *                           You don't need to worry about reading it your self.
209
   *
210
   * @param  int     $postId   (Optional) The ID of the post whose content should
211
   *                           be present in the editor when loaded. provide this
212
   *                           parameter when you want to edit a post.
213
   *
214
   * @param  bool    $w3css    If true, echoes the W3.CSS link tag as well.
215
   *
216
   * @return bool              True  if sucessfull without errors, false if not.
217
   */
218
  public function loadEditor(string $callback, int $postId=null, bool $w3css=true): bool {
219
    $this->loadScripts($w3css);
220
    $this->ci->load->helper("form");
221
    $data = array(
222
      "callback" => "Admin/token",
223
      "type"     => $postId === null ? "create" : "edit",
224
      "callback" => $callback
225
    );
226
    if ($postId !== null) {
227
      $data["id"] = $postId;
228
      $post = $this->getPost($postId, false);
229
      $data["title"] = $post["title"];
230
      $data["content"] = $post["content"];
231
    }
232
    $this->ci->load->splint("francis94c/blog", "-post_edit", $data);
233
    return true;
234
  }
235
  /**
236
   * Handles form data from the Editor loaded by a call to 'loadEditor'.
237
   * Traditionally, this function is to be called ath the controller function
238
   * specified by the callback URI provided to the loadEditor method.
239
   *
240
   * @param  int $posterId ID of the poster. A valid admin ID from the table
241
   *                       specified as a foreign key constraint during the
242
   *                       installation of the selected blog.
243
   *
244
   * @return string        The final action reached in processing the form
245
   *                       inputs. These are public string constants declared in
246
   *                       this file.
247
   */
248
  public function savePost(int $posterId=null): string {
249
    $action = $this->ci->security->xss_clean($this->ci->input->post("action"));
250
    switch ($action) {
251
      case "save":
252
        return $this->handleSavePost($posterId);
253
      case "publish":
254
        return $this->handlePublishPost($posterId);
255
      case "createAndPublish":
256
        if ($this->ci->bmanager->createAndPublishPost($this->ci->security->xss_clean($this->ci->input->post("title")), $this->ci->security->xss_clean($this->ci->input->post("editor")), $posterId) !== false) return self::CREATE_AND_PUBLISH;
257
        return self::ABORT;
258
      case "delete":
259
        if ($this->ci->bmanager->deletePost($this->ci->security->xss_clean($this->ci->input->post("id")))) return self::DELETE;
260
        return self::ABORT;
261
      default:
262
        return self::NO_ACTION;
263
    }
264
  }
265
  /**
266
   * [handleSavePost handles save pot actions; edit & create]
267
   *
268
   * @param  int     $posterId  Poster ID or Admin ID.
269
   *
270
   * @return string             Action taken during the pocess; Blogger::CREATE Or Blogger::EDIT
271
   */
272
  private function handleSavePost(int $posterId=null): string {
273
    $id = $this->ci->security->xss_clean($this->ci->input->post("id"));
274
    if ($id != "") {
275
      if (!$this->ci->bmanager->savePost($this->ci->input->post("id"), $this->ci->security->xss_clean($this->ci->input->post("title")), $this->ci->security->xss_clean($this->ci->input->post("editor")), $posterId)) return self::ABORT;
276
      return self::EDIT;
277
    } else {
278
      if ($this->ci->bmanager->createPost($this->ci->security->xss_clean($this->ci->input->post("title")), $this->ci->security->xss_clean($this->ci->input->post("editor")), $posterId) == 0) return self::ABORT;
279
      return self::CREATE;
280
    }
281
  }
282
  /**
283
   * [handlePublishPost handles the publishing of a post using inputs from the
284
   *  submited form.]
285
   *
286
   * @param  int    $posterId ID of the publishing Admin.
287
288
   * @return string           Action reached while processing form inputs.
289
   */
290
  private function handlePublishPost(int $posterId=null): string {
291
    $id = $this->ci->security->xss_clean($this->ci->input->post("id"));
292
    if ($id == "") return self::ABORT;
293
    if (!$this->ci->bmanager->savePost($id, $this->ci->security->xss_clean($this->ci->input->post("title")), $this->ci->security->xss_clean($this->ci->input->post("editor")), $posterId)) return self::ABORT;
294
    if (!$this->ci->bmanager->publishPost($id, true)) return self::ABORT;
295
    return self::PUBLISH;
296
  }
297
  /**
298
   * getPosts get posts from the database by the given $page starting from the
299
   * value of 1 and returns $limit number of rows.
300
   *
301
   * @param  int     $page   Page number starting from 1.
302
   *
303
   * @param  int     $limit  Number of posts to return.
304
   *
305
   * @param  bool    $filter if true, returns only published posts, if false
306
   *                         return all posts. false by default.
307
   *
308
   * @param  bool    $hits   If truem orders the returned posts by number of hits.
309
   *
310
   * @return array           Array of posts for a given page.
311
   */
312
  public function getPosts(int $page, int $limit, bool $filter=false, bool $hits=false): array {
313
    return $this->ci->bmanager->getPosts($page, $limit, $filter, $hits);
314
  }
315
  /**
316
   * [renderPosts render post items by page number, max page count, and specified
317
   * view files.]
318
   * @param  string  $view       [description]
319
   * @param  string  $empty_view [description]
320
   * @param  int     $page       [description]
321
   * @param  int     $limit      [description]
322
   * @param  boolean $filter     [description]
323
   * @param  boolean $hits       [description]
324
   * @return bool             [description]
325
   */
326
  public function renderPostItems($view=null, $callback=null, $empty_view=null, $page=1, $limit=5, $filter=false, $hits=false, $slug=true) {
327
    if ($view == null || $empty_view == null) $this->ci->load->bind("francis94c/blog", $blogger);
0 ignored issues
show
It seems like you are loosely comparing $view of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
It seems like you are loosely comparing $empty_view of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
328
    $posts = $this->getPosts($page, $limit, $filter, $hits);
329
    if (count($posts) == 0) {
330
      if ($empty_view == null) { $blogger->load->view("empty"); } else {
0 ignored issues
show
It seems like you are loosely comparing $empty_view of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
331
        $this->ci->load->view($empty_view);
332
        return true;
333
      }
334
    }
335
    $this->ci->load->helper("text");
336
    foreach ($posts as $post) {
337
      $post["callback"] = $callback != null ? trim($callback, "/") . "/" . ($slug ? $post["slug"] : $post["id"]) : "";
338
      $post["filter"] = $filter;
339
      $post["content"] = $this->ci->parsedown->text(ellipsize($post["content"], 300));
340
      if ($view == null) {$blogger->load->view("post_list_item", $post); } else {
0 ignored issues
show
It seems like you are loosely comparing $view of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
341
        $this->ci->load->view($view, $post);
342
      }
343
    }
344
    return true;
345
  }
346
  /**
347
   * [getRecentPosts description]
348
   * @param  integer $limit  [description]
349
   * @param  boolean $filter [description]
350
   * @return [type]          [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
351
   */
352
  public function getRecentPosts($limit=5, $filter=false) {
353
    return $this->ci->bmanager->getRecentPosts($limit, $filter);
354
  }
355
  /**
356
   * [renderPost description]
357
   * @param  [type] $post [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
358
   * @param  [type] $view [description]
359
   * @return [type]       [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
360
   */
361
  public function renderPost($post, $view=null) {
362
    if (!is_array($post)) $post = $this->ci->bmanager->getPost($post);
363
    if (!$post) return false;
364
    $post["content"] = $this->ci->parsedown->text($post["content"]);
365
    if ($view == null) {
366
      $this->ci->load->splint("francis94c/blog", "-post_item", $post);
367
    } else {
368
      $this->ci->load->view($view, $post);
369
    }
370
    return true;
371
  }
372
  /**
373
   * [metaOg description]
374
   * @param  [type] $post [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
375
   * @return [type]       [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
376
   */
377
  public function metaOg($post) {
378
    $data = array();
379
    $data["title"] = $post["title"];
380
    $data["description"] = substr($post["content"], 0, 154);
381
    if (isset($post["share_image"])) $data["image_link"] = $post["share_image"];
382
    $data["url"] = current_url();
1 ignored issue
show
The function current_url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

382
    $data["url"] = /** @scrutinizer ignore-call */ current_url();
Loading history...
383
    return $this->ci->load->splint(self::PACKAGE, "-meta_og", $data, true);
384
  }
385
  /**
386
   * [getPostsCount description]
387
   * @return [type] [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
388
   */
389
  public function getPostsCount() {
390
    return $this->ci->bmanager->getPostsCount();
391
  }
392
  /**
393
   * [getPost description]
394
   * @param  [type] $postId [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
395
   * @return [type]         [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
396
   */
397
  public function getPost($postId, $hit=true) {
398
    return $this->ci->bmanager->getPost($postId, $hit);
399
  }
400
  /**
401
   * [getHits description]
402
   * @param  [type] $postId [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
403
   * @return [type]         [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
404
   */
405
  public function getHits($postId) {
406
    return $this->ci->bmanager->getHits($postId);
407
  }
408
  /**
409
   * [publishPost description]
410
   * @param  [type] $postId  [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
411
   * @param  [type] $publish [description]
412
   * @return [type]          [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
413
   */
414
  public function publishPost($postId, $publish) {
415
    return $this->ci->bmanager->publishPost($postId, $publish);
416
  }
417
  /**
418
   * [deletePost description]
419
   * @param  [type] $postId [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
420
   * @return [type]         [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
421
   */
422
  public function deletePost($postId) {
423
    return $this->ci->bmanager->deletePost($postId);
424
  }
425
  /**
426
   * [searchPosts description]
427
   * @param  [type]  $words  [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
428
   * @param  [type]  $page   [description]
429
   * @param  integer $limit  [description]
430
   * @param  boolean $filter [description]
431
   * @return [type]          [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
432
   */
433
  public function searchPosts($words, $page, $limit=0, $filter=false) {
434
    return $this->ci->bmanager->searchPosts($words, $page, $limit, $filter);
435
  }
436
}
437