Completed
Branch master (856cc5)
by Mihail
07:21 queued 04:29
created

NativeGenerator::safe()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 21
rs 9.3142
cc 3
eloc 14
nc 4
nop 2
1
<?php
2
3
namespace Ffcms\Core\Helper\HTML\System;
4
5
use Ffcms\Core\App;
6
use Ffcms\Core\Helper\Security;
7
use Ffcms\Core\Helper\Type\Obj;
8
use Ffcms\Core\Helper\Type\Str;
9
use Ffcms\Core\Helper\Url;
10
11
abstract class NativeGenerator
12
{
13
14
    /**
15
     * Make data "safe" - all dangerous html/js/etc will be removed
16
     * @param string $data
17
     * @param bool $quotes
18
     * @return string
19
     */
20
    public static function safe($data, $quotes = false)
21
    {
22
        $purifier = null;
0 ignored issues
show
Unused Code introduced by
$purifier is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
23
        if (App::$Memory->get('object.purifier.helpers') !== null) {
24
            $purifier = App::$Memory->get('object.purifier.helpers');
25
        } else {
26
            $config = \HTMLPurifier_Config::createDefault();
27
            $config->set('Cache.SerializerPath', root . '/Private/Cache/HTMLPurifier/');
28
            $config->set('AutoFormat.AutoParagraph', false);
29
30
            // allow use target=_blank for links
31
            $def = $config->getHTMLDefinition(true);
32
            $def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');
33
34
            $purifier = new \HTMLPurifier($config);
35
            App::$Memory->set('object.purifier.helpers', $purifier);
36
        }
37
38
        $data = $purifier->purify($data);
39
        return $quotes ? $data : App::$Security->escapeQuotes($data);
40
    }
41
42
    /**
43
     * Remove all html tags from data
44
     * @param string $data
45
     * @return string
46
     */
47
    public static function nohtml($data)
48
    {
49
        return App::$Security->escapeQuotes(App::$Security->strip_tags($data));
0 ignored issues
show
Bug introduced by
It seems like \Ffcms\Core\App::$Security->strip_tags($data) targeting Ffcms\Core\Helper\Security::strip_tags() can also be of type array; however, Ffcms\Core\Helper\Security::escapeQuotes() does only seem to accept string, maybe add an additional type check?

This check looks at variables that 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...
50
    }
51
52
    /**
53
     * Build property for html element from array.
54
     * IMPORTANT: $property can be null-string (some times this happend's) - do not remove NULL!!
55
     * @param array $property
56
     * @return null|string
57
     */
58
    public static function applyProperty(array $property = null)
59
    {
60
        if (!Obj::isArray($property) || count($property) < 1) {
61
            return null;
62
        }
63
        
64
        $build = null;
65
        foreach ($property as $p => $v) {
0 ignored issues
show
Bug introduced by
The expression $property of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
66
            if ($v === null || $v === false || $v === true) {
67
                $build .= ' ' . self::nohtml($p);
68
            } else {
69
                $build .= ' ' . self::nohtml($p) . '="' . self::nohtml($v) . '"';
70
            }
71
        }
72
        return $build;
73
    }
74
75
    /**
76
     * Fast building single tag based on property's array
77
     * @param string $tagName
78
     * @param array|null $property
79
     * @return string
80
     */
81
    public static function buildSingleTag($tagName, array $property = null)
82
    {
83
        return '<' . self::nohtml($tagName) . self::applyProperty($property) . '/>';
84
    }
85
86
    /**
87
     * Fast building container type tag based on property's and value
88
     * @param string $tagName
89
     * @param array|null $property
90
     * @param null|string $value
91
     * @param bool $valueHtml
92
     * @return string
93
     */
94
    public static function buildContainerTag($tagName, array $property = null, $value = null, $valueHtml = false)
95
    {
96
        $tagName = self::nohtml($tagName);
97
        if ($valueHtml !== true) {
98
            $value = self::nohtml($value);
99
        }
100
        
101
        return '<' . $tagName . self::applyProperty($property) . '>' . $value . '</' . $tagName . '>';
102
    }
103
104
    /**
105
     * Make parts of URI safe and usable
106
     * @param string $string
107
     * @param bool $encode
108
     * @return string
109
     */
110
    public static function safeUri($string, $encode = true)
111
    {
112
        $string = Str::lowerCase($string);
113
        $string = self::nohtml($string);
114
        if ($encode === true) {
115
            $string = urlencode($string);
116
        }
117
        return $string;
118
    }
119
120
    /**
121
     * Check if uri $source is equal to current uri point with array of $aliases and active $order set
122
     * @param null $source
123
     * @param array|null $aliases
124
     * @param bool $order
125
     * @return bool
126
     */
127
    public static function isCurrentLink($source = null, array $aliases = null, $order = false)
128
    {
129
        $elementPoint = Url::buildPathway($source);
130
        $currentPoint = Url::buildPathwayFromRequest();
131
132
        // use special active element order type: controller, action
133
        switch ($order) {
134
            case 'controller':
135
                $elementPoint = Str::firstIn($elementPoint, '/');
136
                $active = Str::startsWith($elementPoint, $currentPoint);
137
                break;
138
            case 'action':
139
                $elementArray = explode('/', $elementPoint);
140
                if (!Str::contains('/', $elementPoint) || count($elementArray) < 2) {
141
                    $active = $elementPoint === $currentPoint;
142
                } else {
143
                    $elementPoint = $elementArray[0] . '/' . $elementArray[1];
144
                    $active = Str::startsWith($elementPoint, $currentPoint);
145
                }
146
                break;
147
            case 'id':
148
                $elementArray = explode('/', $elementPoint);
149
                $elementPoint = $elementArray[0] . '/' . $elementArray[1];
150
                if (null !== $elementArray[2]) {
151
                    $elementPoint .= '/' . $elementArray[2];
152
                }
153
154
                $active = Str::startsWith($elementPoint, $currentPoint);
155
                break;
156
            default:
157
                $active = $elementPoint === $currentPoint;
158
                break;
159
        }
160
161
        // check if current uri equals with aliases
162
        if (Obj::isArray($aliases) && count($aliases) > 0) {
163
            foreach ($aliases as $activeUri) {
0 ignored issues
show
Bug introduced by
The expression $aliases of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
164
                $activeUri = trim($activeUri, '/');
165
                if (Str::endsWith('*', $activeUri)) {
166
                    $activeUri = rtrim($activeUri, '*');
167
                    if (Str::startsWith($activeUri, $currentPoint)) {
168
                        $active = true;
169
                    }
170
                } else {
171
                    if ($activeUri === $currentPoint) {
172
                        $active = true;
173
                    }
174
                }
175
            }
176
        }
177
178
        return $active;
179
    }
180
181
    /**
182
     * Apply security for string to output as html
183
     * @param string|null $object
184
     * @param bool $html
185
     * @param bool $secure
186
     * @return null|string
187
     */
188
    public static function applyEscape($object = null, $html = false, $secure = false)
189
    {
190
        $object = (string)$object;
191
        if ($html !== true) {
192
            $object = self::nohtml($object);
193
        } elseif ($secure !== true) {
194
            $object = self::safe($object, true);
195
        }
196
197
        return $object;
198
    }
199
200
    /**
201
     * Convert link-binding type to classic link with security filter
202
     * @param string|array $uri
203
     * @return string
204
     */
205
    public static function convertLink($uri)
206
    {
207
        $link = App::$Alias->baseUrl . '/';
208
        if (Obj::isArray($uri)) {
209
            $link .= Url::buildPathway($uri);
0 ignored issues
show
Bug introduced by
It seems like $uri defined by parameter $uri on line 205 can also be of type string; however, Ffcms\Core\Helper\Url::buildPathway() does only seem to accept null|array, 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...
210
        } elseif (Str::startsWith('http', $uri)) {
0 ignored issues
show
Bug introduced by
It seems like $uri defined by parameter $uri on line 205 can also be of type array; however, Ffcms\Core\Helper\Type\Str::startsWith() does only seem to accept string, 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...
211
            $link = self::nohtml($uri);
0 ignored issues
show
Bug introduced by
It seems like $uri defined by parameter $uri on line 205 can also be of type array; however, Ffcms\Core\Helper\HTML\S...tiveGenerator::nohtml() does only seem to accept string, 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...
212
        } elseif (Str::startsWith('#', $uri)) { // allow pass #part
0 ignored issues
show
Bug introduced by
It seems like $uri defined by parameter $uri on line 205 can also be of type array; however, Ffcms\Core\Helper\Type\Str::startsWith() does only seem to accept string, 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...
213
            $link = self::nohtml($uri);
0 ignored issues
show
Bug introduced by
It seems like $uri defined by parameter $uri on line 205 can also be of type array; however, Ffcms\Core\Helper\HTML\S...tiveGenerator::nohtml() does only seem to accept string, 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...
214
        } else {
215
            $link .= self::nohtml(trim($uri, '/'));
216
        }
217
        return $link;
218
    }
219
220
221
}