Passed
Push — master ( 439f76...690eba )
by Alexander
01:40
created

Html::convertToString()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 12
rs 10
1
<?php
2
3
namespace alkemann\h2l\response;
4
5
use alkemann\h2l\Message;
6
use alkemann\h2l\Response;
7
use alkemann\h2l\util\Http;
8
9
/**
10
 * Class Html
11
 *
12
 * Content should be either a rendered HTML string or an object that when cast to string renders the HTML.
13
 * Also a slim templateing system is provided. You can use this by sending an array as content, but the 
14
 * array must follow some strict rules. The first value (no key), should be the template string. Any key/value
15
 * pair added to this array will be applied as replacements in the template in the following manner:
16
 *
17
 *  - The content key must be a unique string name, like `city`
18
 *  - The place in the template must be prefixed with `{:` and end with `}`, i.e. `{:city}
19
 *
20
 * Example:
21
 *
22
 * ```php
23
 *  Router::add('|city/(?<city>\w+)|', function(Request $request): Html {
24
 *      $template = <<<TEM
25
 *  <html>
26
 *      <head>
27
 *          <title>{:name}</title>
28
 *      </head>
29
 *      <body>
30
 *          <h1>City {:name}</h1>
31
 *          <p>On {:street}</p>
32
 *      </body>
33
 *  </html>
34
 *  TEM;
35
 *
36
 *  $data = [
37
 *      $template,
38
 *      'name' => $r->param('city'),
39
 *      'street' => 'Mainstreet',
40
 *  ];
41
 *  return new Html($data, 200);
42
 *
43
 *  }
44
 * ```
45
 *
46
 * Going to localhost/city/Oslo, will render as:
47
 *
48
 * ```
49
 *  <html>
50
 *      <head>
51
 *          <title>Oslo</title>
52
 *      </head>
53
 *      <body>
54
 *          <h1>City Oslo</h1>
55
 *          <p>On Mainstreet</p>
56
 *      </body>
57
 *  </html>
58
 * ```
59
 *
60
 * @package alkemann\h2l
61
 */
62
class Html extends Response
63
{
64
    /**
65
     * @param string|mixed $content HTML. Objects will be cast, arrays will render template
66
     * @param int $code HTTP code to respond with, defaults to `200`
67
     * @param array $config inject config/overrides like `header_func`
68
     */
69
    public function __construct($content = null, int $code = Http::CODE_OK, array $config = [])
70
    {
71
        if (is_string($content) === false) {
72
            $content = $this->convertToString($content, $config);
73
        }
74
        $this->config = $config;
75
        $this->message = (new Message())
76
            ->withCode($code)
77
            ->withHeaders([
78
                'Content-Type' => Http::CONTENT_HTML
79
            ])
80
            ->withBody($content)
0 ignored issues
show
Bug introduced by
It seems like $content can also be of type null; however, parameter $body of alkemann\h2l\Message::withBody() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

80
            ->withBody(/** @scrutinizer ignore-type */ $content)
Loading history...
81
        ;
82
    }
83
84
    private function convertToString($content, array $config = []): string
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed. ( Ignorable by Annotation )

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

84
    private function convertToString($content, /** @scrutinizer ignore-unused */ array $config = []): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
85
    {
86
        if (is_array($content) == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
87
            return (string) $content;
88
        }
89
        reset($content);
90
        $template = array_shift($content);
91
        $replace = [];
92
        foreach ($content as $name => $value) {
93
            $replace["{:$name}"] = $value;
94
        }
95
        return strtr($template, $replace);
96
    }
97
98
    /**
99
     * Set header and return a string rendered and ready to be echo'ed as response
100
     *
101
     * Header 'Content-type:' will be set using `header` or an injeced 'header_func' through constructor
102
     */
103
    public function render(): string
104
    {
105
        $this->setHeaders();
106
        return $this->message->body();
107
    }
108
}
109