Completed
Push — prototype ( 3bfdd7...aec713 )
by Peter
07:47
created

AbstractHtml::setTitle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Webino (http://webino.sk)
4
 *
5
 * @link        https://github.com/webino for the canonical source repository
6
 * @copyright   Copyright (c) 2015-2017 Webino, s.r.o. (http://webino.sk)
7
 * @author      Peter Bačinský <[email protected]>
8
 * @license     BSD-3-Clause
9
 */
10
11
namespace WebinoHtmlLib\Html;
12
13
use WebinoBaseLib\Util\ToString;
14
15
/**
16
 * Class AbstractHtml
17
 */
18
abstract class AbstractHtml implements HtmlInterface
19
{
20
    use EscaperAwareTrait;
21
    use FormatTrait;
22
23
    /**
24
     * @var string
25
     */
26
    private $value;
27
28
    /**
29
     * @var array
30
     */
31
    private $attribs = [];
32
33
    /**
34
     * @return string
35
     */
36
    abstract protected function getTagName();
37
38
    /**
39
     * @param string|array|object $value New value;current value placeholder is `%s`
40
     * @return $this
41
     */
42
    public function setValue($value)
43
    {
44
        $this->value = strtr($this->normalizeValue($value), ['%s' => $this->value]);
0 ignored issues
show
Bug introduced by
It seems like $value defined by parameter $value on line 42 can also be of type object; however, WebinoHtmlLib\Html\AbstractHtml::normalizeValue() does only seem to accept string|array|object<Webi...Lib\Html\HtmlInterface>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
45
        return $this;
46
    }
47
48
    /**
49
     * @param string $name
50
     * @param string $value
51
     * @return $this
52
     */
53
    protected function setAttribute($name, $value)
54
    {
55
        $this->attribs[$name] = $value;
56
        return $this;
57
    }
58
59
    /**
60
     * @param $title
61
     * @return $this
62
     */
63
    public function setTitle($title)
64
    {
65
        $this->setAttribute('title', $title);
66
        return $this;
67
    }
68
69
    /**
70
     * @param string $class
71
     * @return $this
72
     */
73
    public function setClass($class)
74
    {
75
        $this->setAttribute('class', $class);
76
        return $this;
77
    }
78
79
    /**
80
     * @param array|string $style
81
     * @param string|null $value
82
     * @return $this
83
     */
84
    public function setStyle($style, $value = null)
85
    {
86
        $styleData = [];
87
88
        if (!empty($this->attribs['style'])) {
89
            call_user_func(function () use (&$styleData) {
90
                foreach (explode(';', $this->attribs['style']) as $pair) {
91
                    list($name, $value) = explode(':', $pair);
92
                    $styleData[trim($name)] = trim($value);
93
                }
94
            });
95
        }
96
97
        if (is_array($style)) {
98
            foreach ($style as $name => $value) {
99
                $styleData[$name] = $value;
100
            }
101
102
        } elseif (null !== $value) {
103
            $styleData[$style] = $value;
104
105
        } elseif (isset($styleData[$style])) {
106
            unset($styleData[$style]);
107
        }
108
109
        $stylePairs = [];
110
        foreach ($styleData as $name => $value) {
111
            $stylePairs[] = $name . ': ' . $value;
112
        }
113
114
        $this->setAttribute('style', join('; ', $stylePairs));
115
        return $this;
116
    }
117
118
    /**
119
     * @param string|array|HtmlInterface $value
120
     * @return string
121
     */
122
    private function normalizeValue($value)
123
    {
124
        if ($value instanceof HtmlInterface) {
125
            return ToString::value($value);
126
        }
127
128
        if (is_array($value)) {
129
            $newValue = '';
130
            foreach ($value as $subValue) {
131
                $newValue .= $this->normalizeValue($subValue);
132
            }
133
            return $newValue;
134
        }
135
136
        return $this->getEscaper()->escapeHtml(ToString::value($value));
137
    }
138
139
    /**
140
     * @param string $tag
141
     * @param string $attribs
142
     * @param string $value
143
     * @return string
144
     */
145
    protected function toStringInternal($tag, $attribs, $value)
146
    {
147
        return $this->doFormat(sprintf('<%s %s>%s</%s>', $tag, $attribs, $value, $tag));
148
    }
149
150
    /**
151
     * @return string
152
     */
153
    public function __toString()
154
    {
155
        $escaper = $this->getEscaper();
156
        $attribs = [];
157
158
        foreach ($this->attribs as $attrib => $value) {
159
160
            empty($value)
161
                or $attribs[] = sprintf(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
162
                    '%s="%s"',
163
                    $escaper->escapeHtml($attrib),
164
                    $escaper->escapeHtmlAttr($value)
165
                );
166
        }
167
168
        $tag = $this->getTagName();
169
        return $this->toStringInternal($tag, join(' ', $attribs), $this->value);
170
    }
171
}
172