ContentController::saveContent()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 0
cts 0
cp 0
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 3
nop 2
crap 12
1
<?php
2
namespace Chp\TextContent;
3
4 1
include_once(__DIR__ . '/../../app/config/text-content.php');
5
6
/**
7
 * Text content controller
8
 * Made by Rasmus Berg (c) 2014-2017
9
 *
10
 * @property  object  $di         Anax-MVC class handler
11
 * @property  object  $request    Anax-MVC $_POST, $_GET and $_SERVER handler class
12
 * @property  object  $response   Anax-MVC Php Header class
13
 * @property  object  $url        Anax-MVC url-handler class
14
 * @property  object  $theme      Anax-MVC theme-handler class
15
 * @property  object  $views      Anax-MVC views-handler class
16
 * @property  object  $textFilter Anax-MVC textformat-handler class
17
 * @property  object  $db         PDO database class
18
 */
19
class ContentController implements \Anax\DI\IInjectionAware
20
{
21
  use \Anax\DI\TInjectable;
22
  
23
  /**
24
   * Properties
25
   */
26
  private $content;
27
  private $valid;
28
  private $contentPerPage; // Limit contents on list page
29
  private $urlPrefix;
30
  private $miniLength;
31
  
32
  /**
33
   * Initialize the controller
34
   *
35
   * @return    void
36
   */
37 7
  public function initialize(){
38
    if(!is_object($this->di))
39
      throw new \Anax\Exception\InternalServerErrorException('"$this->di" is not valid!');
40
    
41
    $this->content = new \Chp\TextContent\Content();
42
    $this->content->setDI($this->di);
43
    $this->valid = new \Chp\TextContent\ValidContent();
44
    $this->valid->setDI($this->di);
45
    $this->valid->initialize();
46
    
47 7
    $this->contentPerPage = CHP_TC_CONTENTPERPAGE;
48 7
    $this->urlPrefix      = CHP_TC_URLPREFIX;
49 7
    $this->miniLength     = CHP_TC_MINILENGTH;
50 7
  }
51
  
52
  /**
53
   * Index content - use listAction 
54
   *
55
   * @return		void
56
   */
57
  public function indexAction(){
58
    $this->listAction();
59
  }
60
  
61
  /**
62
   * Setup content (If it allready exist it will restore database to begining)
63
   *
64
   * @return    void
65
   */
66
  public function setupAction(){
67
    $toDo   = "Restore or setup";
68
    $toWhat = "content database tables";
69
    $title  = "{$toDo} {$toWhat}";
70
    $form   = $this->confirmForm($this->url->create("{$this->urlPrefix}content/"));
71
    $status = $form->check();
72
73
    if($status === true){
74
    
75
      $this->db->dropTableIfExists('content')->execute();
76
77
      $this->db->createTable(
78
        'content',
79
        [
80
          'id'        => ['integer', 'primary key', 'not null', 'auto_increment'],
81
          'slug'      => ['char(80)'],
82
          'url'       => ['char(80)'],
83
          'type'      => ['char(80)'],
84
          'title'     => ['varchar(80)'],
85
          'ingress'   => ['text'],
86
          'text'      => ['text'],
87
          'filters'   => ['char(80)'],
88
          'author'    => ['integer', 'not null'],
89
          'published' => ['datetime'],
90
          'created'   => ['datetime'],
91
          'updated'   => ['datetime'],
92
          'deleted'   => ['datetime']
93
        ]
94
      )->execute();
95
      
96
      $this->db->insert(
97
        'content',
98
        ['slug', 'url', 'type', 'title', 'ingress', 'text', 'filters', 'author', 'published', 'created']
99
      );
100
101
      $now = date('Y-m-d H:i:s');
102
103
      $this->db->execute([
104
        'welcome_to_your_new_blog',
105
        NULL,
106
        'blog-post',
107
        'Welcome to your new blog',
108
        'This is example-blogg to show your new blog system!',
109
        'You can start blog by visit [url=' . $this->url->create("{$this->urlPrefix}content/add/") . ']Add content[/url]',
110
        'bbcode',
111
        3,
112
        $now,
113
        $now
114
      ]);
115
      
116
      $this->db->execute([
117
        'welcome_to_your_new_page',
118
        'example-page',
119
        'page',
120
        'Welcome to your new page',
121
        'This is example-page to show your new page system!',
122
        'You can start makeing pages by visit [url=' . $this->url->create("{$this->urlPrefix}content/add/") . ']Add content[/url]',
123
        'bbcode',
124
        3,
125
        $now,
126
        $now
127
      ]);
128
      
129
      $this->db->dropTableIfExists('content_tags')->execute();
130
      
131
      $this->db->createTable(
132
        'content_tags',
133
        [
134
          'idContent' => ['integer', 'not null'],
135
          'tag'       => ['varchar(150)', 'not null'],
136
          'slug'      => ['varchar(150)', 'not null']
137
        ]
138
      )->execute();
139
      
140
      $this->db->insert(
141
        'content_tags',
142
        ['idContent', 'tag', 'slug']
143
      );
144
      
145
      $this->db->execute([
146
        1,
147
        'New blog',
148
        'new_blog'
149
      ]);
150
151
      $this->db->execute([
152
        1,
153
        'Blog information',
154
        'blog_information'
155
      ]);
156
      
157
      $this->views->add('text-content/action-finish', [
158
          'title'   => $title,
159
          'msg'     => "Content and content tags database tables " . strtolower($toDo). " was successful!"
160
      ], 'main');
161
      
162
    }
163
    else{      
164
      $this->views->add('text-content/action', [
165
          'title'   => $title,
166
          'toDo'    => strtolower($toDo),
167
          'toWhat'  => $toWhat,
168
          'form'    => $form->getHTML(['novalidate' => true])
169
      ], 'main');
170
    }
171
    
172
    $this->theme->setTitle($title);
173
  }
174
  
175
  /**
176
   *  List content (by type)
177
   *
178
   * @param     string  $type	  Type to list
179
   * @param     int     $page   Page that paging is on
180
   * @return		void
181
   */
182
  public function listAction($type = null, $published = false, $page = null){
183
    $type      = ($this->valid->checkType($type)) ? $type : null;
184
    $title     = "All Content {$type} listed";
185
    $published = boolval($published);
186
187
    $form   = $this->listForm($type, $published);
188
    $form->check();
189
190
    if(!is_null($type))
191
      $contents = $this->content->getAllContentOfType($type, $page, $this->contentPerPage, $published);
192
    else
193
      $contents = $this->content->getAllContent($page, $this->contentPerPage, $published);
194
195
    $contents = $this->prepareListContent($contents);
196
197
    $this->theme->setTitle($title);
198
    $this->views->add('text-content/list', [
199
      'title'     => $title,
200
      'form'      => $form->getHTML(array('novalidate' => true)),
201
      'contents' 	=> $contents,
202
      'addUrl'	  => $this->url->create("{$this->urlPrefix}content/add/"),
203
      'setupUrl'  => $this->url->create("{$this->urlPrefix}content/setup/")
204
    ]);
205
  }
206
  
207
  /**
208
   * Add content to database
209
   *
210
   * @return    void
211
   */
212
  public function addAction(){
213
    $action = "Add";
214
    $title = "{$action} content";
215
    
216
    $form = $this->contentForm();
217
    $form->check();
218
    
219
    $this->theme->setTitle($title);
220
    
221
    $this->views->add('text-content/post', [
222
        'title'  => $title,
223
        'action' => $action,
224
        'form'   => $form->getHTML(array('novalidate' => true))
225
    ]);
226
  }
227
  
228
  /**
229
   * Edit content in database
230
   *
231
   * @param     int   $id   Index for content to edit
232
   * @return    void
233
   */
234
  public function editAction($id = null){
235
    $action = "Edit";
236
    $title  = "{$action} content";
237
    $url    = $this->url->create("{$this->urlPrefix}content/");
238
    
239
    if(is_null($id) || !is_numeric($id))
240
      $this->response->redirect($url);
241
    
242
    $content = $this->content->getContentById($id, false);
243
    
244
    if(is_null($content->id))
245
      $this->response->redirect($url);
246
    
247
    $form = $this->contentForm($content);
248
    $form->check();
249
    
250
    $this->theme->setTitle($title);
251
    
252
    $this->views->add('text-content/post', [
253
        'title'  => $title,
254
        'action' => $action,
255
        'form'   => $form->getHTML(array('novalidate' => true))
256
    ]);
257
  }
258
	
259
  /**
260
   * Remove content
261
   *
262
   * @param   int     $id       Index to content to remove
263
   * @return  string  $error    Database-error msg
264
   */
265
  public function removeAction($id = null){
266
    $action = "Delete";
267
    $title = "Delete content";
268
    $url = $this->url->create("{$this->urlPrefix}content/");
269
270
    if(is_null($id) || !is_numeric($id))
271
      $this->response->redirect($url);
272
273
    $content = $this->content->find($id);
274
275
    if(is_null($content->id))
276
      $this->response->redirect($url);
277
278
    $form = $this->confirmForm($url);
279
    $status = $form->Check();
280
281
    if ($status === true) {
282
      $now = date('Y-m-d H:i:s');
283
284
      $content->deleted = $now;
285
      $content->save();
286
287
      $this->response->redirect($url);
288
    }
289
290
    $this->theme->setTitle($title);
291
    $this->views->add('text-content/action', [
292
      'title'  => $title,
293
      'toDo'    => strtolower($action),
294
      'toWhat'  => strtolower($this->valid->getTypeTitle($content->type)),
295
      'which'   => htmlspecialchars($content->title, ENT_QUOTES),
296
      'form'    => $form->getHTML(['novalidate' => true]),
297
    ], 'main');
298
  }
299
  
300
  /**
301
   * Prepare form to add or edit content
302
   *
303
   * @param   string                $type       Selected content-type
304
   * @param   boolean               $published  If content should be published already
305
   * @return  \Mos\HTMLForm\CForm   $form       CForm object
306
   */
307
  private function listForm($type = null, $published = false){
308
    
309
    $type_options      = array_merge([0 => "Select a type of content"], $this->valid->getTypes());
310
    
311
    $form = new \Mos\HTMLForm\CForm([], [
312
        'type' => [
313
          'type'        => 'select',
314
          'label'       => 'Type of content:',
315
          'options'     => $type_options,
316
          'value'       => (isset($type)) ? $type : ''
317
        ],
318
        'published' => [
319
          'type'        => 'checkbox',
320
          'label'       => 'Published',
321
          'checked'     => $published,
322
          'value'       => 1
323
        ],
324
        'submit' => [
325
          'value' 		=> 'Filter',
326
          'type'      => 'submit',
327
          'callback'  => function ($form) {
328
            $published = ($this->request->getPost('published')) ? 1 : 0;
329
            $type      = $form->Value('type');
330
            
331
            $this->response->redirect($this->url->create("{$this->urlPrefix}content/list/{$type}/{$published}"));
332
          }
333
        ]
334
    ]);
335
    
336
    return $form;
337
  }
338
  
339
  /**
340
   * Prepare form to add or edit content
341
   *
342
   * @param   object                $values     Content values to add form elements
343
   * @return  \Mos\HTMLForm\CForm   $form       CForm object
344
   */
345
  private function contentForm($values = null){
346
    if(isset($values) && is_object($values)){
347
      $valArr = get_object_vars($values);
348
      extract($valArr);
349
    }
350
    
351
    $slug = (isset($slug)) ? $slug : NULL;
352
    
353
    $type_options = $this->valid->getTypes();
354
    
355
    $form = new \Mos\HTMLForm\CForm([], [
356
        'id'      => [
357
          'type'        => 'hidden',
358
          'value'       => (isset($id)) ? $id : 0
359
        ],
360
        'title' => [
361
          'type'        => 'text',
362
          'label'       => 'Title: (Between ' . $this->miniLength . ' to 80 chars)',
363
          'maxlength'   => 80,
364
          'required'    => true,
365
          'value'       => (isset($title)) ? $title : '',
366
          'validation'  => [
367
                              'custom_test' => array(
368
                                'message' => 'Minmum length is ' . $this->miniLength . ' chars.', 
369
                                'test'    => array($this, 'minimumLength')
370
                              )
371
                           ]
372
        ],
373
        'url' => [
374
          'type'        => 'text',
375
          'label'       => 'Url:',
376
          'maxlength'   => 80,
377
          'value'       => (isset($url)) ? $url : '',
378
          'required'    => false, 
379
          'validation'  => [
380
                              'custom_test' => array(
381
                                'message' => 'Url is not in accepted-format for url:s (accepted characters is \'a-z0-9-_()\').', 
382
                                'test'    => array($this, 'validateSlug')
383
                              )
384
                           ]
385
        ],
386
        'ingress' => [
387
          'type'        => 'textarea',
388
          'label'       => 'Ingress: (minimum 3 chars)',
389
          'value'       => (isset($ingress)) ? $ingress : '',
390
          'required'    => true,
391
          'validation'  => [
392
                              'custom_test' => array(
393
                                'message' => 'Minmum length is ' . $this->miniLength . ' chars.', 
394
                                'test'    => array($this, 'minimumLength')
395
                              )
396
                           ]
397
        ],
398
        'text' => [
399
          'type'        => 'textarea',
400
        	'label'       => 'Text: (minimum ' . $this->miniLength . ' chars)',
401
          'value'       => (isset($text)) ? $text : '',
402
          'required'    => true,
403
          'validation'  => [
404
                            'custom_test' => array(
405
                              'message' => 'Minmum length is ' . $this->miniLength . ' chars.', 
406
                              'test'    => array($this, 'minimumLength')
407
                            )
408
                           ]
409
        ],
410
        'type' => [
411
          'type'        => 'select',
412
          'label'       => 'Type of content:',
413
          'options'     => $type_options,
414
          'value'       => (isset($type)) ? $type : '',
415
          'required'    => true,
416
          'validation'  => [
417
                              'not_empty',
418
                              'custom_test' => array(
419
                                'message' => 'You need to select a existing type.', 
420
                                'test'    => array($this, 'checkType')
421
                              )
422
                           ]
423
        ],
424
        'tags' => [
425
          'type'        => 'text',
426
          'label'       => 'Tags: (Seperate by \',\')',
427
          'value'       => (isset($tags)) ? $tags : '',
428
          'required'    => false
429
        ],
430
        'filters' => [
431
          'type'        => 'checkbox-multiple',
432
          'label'       => 'Text filter:',
433
          'values'      => $this->valid->getFilters(),
434
          'checked'     => (isset($filters)) ? explode(',', $filters) : array(),
435
          'validation'  => [
436
                              'custom_test' => array(
437
                                'message' => 'You need to select a existing type.', 
438
                                'test'    => array($this, 'checkFilter')
439
                              )
440
                           ]
441
        ],
442
        'published' => [
443
          'type'        => 'datetime',
444
          'label'       => 'Published: (YYYY-MM-DD HH:MM:SS)',
445
          'value'       => (isset($published)) ? $published : '',
446
          'validation'  => [
447
                              'custom_test' => array(
448
                                'message' => 'It need to be in a correct date and time with format: YYYY-MM-DD HH:MM:SS.', 
449
                                'test'    => array($this, 'checkDatetime')
450
                              )
451
                           ]
452
        ],
453
        'publishedNow' => [
454
          'type'        => 'checkbox',
455
          'label'       => 'Publish now:',
456
          'checked'     => (!isset($published) && !isset($id)),
457
          'value'       => 'yes'
458
        ],
459
        'submit' => [
460
          'value' 		=> 'Save',
461
          'type'      => 'submit',
462
          'callback'  => function ($form) use($slug) {
463
            return $this->saveContent($form, $slug);
464
          }
465
        ]
466
    ]);
467
    
468
    return $form;
469
  }
470
  
471
  /**
472
   * Prepare confirmation form
473
   *
474
   * @param   string                $returnUrl       Return url
475
   * @return  \Mos\HTMLForm\CForm   $form            Form-object
476
   */
477
  public function confirmForm($returnUrl = null){
478
    $returnUrl = (isset($returnUrl)) ? $returnUrl : $this->request->getBaseUrl();
479
    
480
    $form = new \Mos\HTMLForm\CForm([], [
481
        'submit' => [
482
          'type'     => 'submit',
483
          'value'    => 'Yes',
484
          'callback' => function() {
485
            return true;
486
          }
487
        ],
488
        'submit-no' => [
489
          'type'     => "submit",
490
          'value'    => 'No',
491
          'callback' => function() use($returnUrl) {
492
            $this->response->redirect($returnUrl);
493
          }
494
        ]
495
      ]
496
    );
497
		
498
    // Check the status of the form
499
    return $form;
500
  }
501
  
502
  /**
503
   * Save content to database
504
   *
505
   * @param   \Mos\HTMLForm\CForm   $form       Form object
506
   * @param   string                $oldSlug    Old slug for content to compare
507
   * @return  boolean               false/true  If saving fail, return false
508
   */
509
  private function saveContent($form, $oldSlug = null){
510
    // Prepare content for saving
511
    $content = $this->prepareSaveContent($form, $oldSlug);
512
    
513
    // Save content
514
    $content = $this->content->save($content);
515
    
516
    // Saving fail
517
    if(!$this->content->id)
518
      return false;
519
    // Save tags for content to database
520
    else if($content['id'] != 0)
521
      $this->saveTags($form->Value('tags'), $this->content->id);
522
    
523
    $this->response->redirect($this->url->create("{$this->urlPrefix}content/"));
524
    return true;
525
  }
526
527
  /**
528
   * Save tags for content to database
529
   *
530
   * @param   string   $tags     Tags for content
531
   * @param   int      $id       Content index
532
   */
533
  private function saveTags($tags, $id){
534
    $this->db->delete(
535
      'content_tags',
536
      'idContent = ?'
537
    )->execute([$id]);
538
    
539
    $this->db->insert(
540
      'content_tags',
541
      ['idContent', 'tag', 'slug']
542
    );
543
    
544
    if(isset($tags) && !is_null($tags)){
545
      $tagsArr = explode(",", $tags);
546
      
547
      foreach($tagsArr as $tag){
548
        $tag = trim($tag);
549
        $this->db->execute([
550
          $id,
551
          $tag,
552
          $this->valid->slugify($tag)
553
        ]);
554
      }
555
    }
556
  }
557
  
558
  /**
559
   * Prepare contents for show in list view
560
   *
561
   * @param   object   $contents    Object with content objects
562
   * @return  array                 $results    Array with prepare content objects
563
   */
564
  public function prepareListContent($contents){
565
    $results = array();
566
    
567
    foreach($contents AS $key => $content){
568
      $available = $this->valid->checkIfAvailable($content->published);
569
      $results[$key] = (object)[];
570
      
571
      foreach($content as $key2 => $value){
572
        $results[$key]->{$key2} = $value;
573
      }
574
      
575
      $results[$key]->typeTxt      = $this->valid->getTypeTitle($content->type);
576
      $results[$key]->title        = htmlspecialchars($content->title, ENT_QUOTES);
577
      $results[$key]->editUrl      = $this->url->create("{$this->urlPrefix}content/edit/{$content->id}");
578
      $results[$key]->removeUrl    = $this->url->create("{$this->urlPrefix}content/remove/{$content->id}");
579
      $results[$key]->showUrl      = $this->valid->getUrlToContent($content);
580
      $results[$key]->available    = ((!$available) ? "not-" : null) . "published";
581
      $results[$key]->publishedTxt  = ($available) ? $contents[$key]->published : "Not published yet";
582
    }
583
    
584
    return $results;
585
  }
586
  
587
  /**
588
   * Prepare save of content to database
589
   *
590
   * @param   \Mos\HTMLForm\CForm   $form     Form object
591
   * @param   string                $oldSlug  Old slug for content to compare
592
   * @return  array                 $content  Prepare content array
593
   */  
594 1
  public function prepareSaveContent($form, $oldSlug = null){
595
    $now = date('Y-m-d H:i:s');
596
    
597
    // Prepare new slug
598
    $newSlug = $this->prepareNewSlug($form->Value('title'), $form->Value('type'), $oldSlug);
599
    
600
    $content = array(
601
      'title'     => $form->Value('title'),
602
      'slug'      => $newSlug,
603
      'url'       => $form->Value('url'),
604
      'ingress'   => $form->Value('ingress'),
605
      'text'      => $form->Value('text'),
606
      'type'      => $form->Value('type'),
607
      'filters'   => ($form->Value('filters')) ? implode(",", $form->Value('filters')) : '',
608
      'published' => ($form->Value('publishedNow') && $form->Value('publishedNow') == 'yes') ? $now : $form->Value('published')
609
    );
610
    
611
    $id = ($form->Value('id')) ? intval($form->Value('id')) : 0;
612
    
613
    if($id != 0){
614 1
      $content['updated'] = $now;
615 1
      $content['id']      = $id;
616
    }
617
    else{
618 1
      $content['created'] = $now;
619 1
      $content['author']  = 0;//$this->user->getUserId();
620 1
    }
621
    
622
    return $content;
623
  }
624
  
625
  /**
626
   * Prepare new slug for content by title
627
   *
628
   * @param   string    $title      Content title to make slug by
629
   * @param   string    $type       Content type
630
   * @param   string    $oldSlug    Old slug for content to compare
631
   * @return  string    $newSlug    New unique slug for content
632
   */
633
  public function prepareNewSlug($title, $type, $oldSlug = null){
634
    $newSlug = $this->valid->slugify($title);
635
    
636
    if($oldSlug != $newSlug && isset($newSlug))
637
      $newSlug = $this->content->makeSlugToContent($newSlug, $type);
638
    
639
    return $newSlug;
640
  }
641
  
642
  /**
643
   * Validate minimum length
644
   *
645
   * @param   string    $text       Text to validate
646
   * @return  boolean   True/False  Validate status
647
   */
648
  public function minimumLength($text = null){
649
    return $this->valid->minimumLength($text);
650
  }
651
  
652
  /**
653
   * Validate slug
654
   *
655
   * @param   string    $slug       Slug to validate
656
   * @return  boolean   True/False  Validate status
657
   */
658
  public function validateSlug($slug = null){
659
    return $this->valid->validateSlug($slug);
660
  }
661
  
662
  /**
663
   * Validate type
664
   *
665
   * @param   string    $type   Type to validate
666
   * @return  boolean   True/False  Validate status
667
   */
668
  public function checkType($type = null){
669
    return $this->valid->checkType($type);
670
  }
671
  
672
  /**
673
   * Validate filter
674
   *
675
   * @param   string    $filter   Filter to validate
676
   * @return  boolean   True/False  Validate status
677
   */
678 1
  public function checkFilter($filter = null){
679
    return $this->valid->checkFilter($filter);
680 1
  }
681
  
682
  /**
683
   * Validate date time
684
   *
685
   * @param   string    $datetime   Date time to validate
686
   * @return  boolean   True/False  Validate status
687
   */
688
  public function checkDatetime($datetime = null){
689
    return $this->valid->checkDatetime($datetime);
690
  }
691
}