Completed
Push — master ( 16471c...f4d9b9 )
by Denis
9s
created

TemplateHelper::setVariable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
/**
3
 * Whoops - php errors for cool kids
4
 * @author Filipe Dobreira <http://github.com/filp>
5
 */
6
7
namespace Whoops\Util;
8
9
use Symfony\Component\VarDumper\Caster\Caster;
10
use Symfony\Component\VarDumper\Cloner\AbstractCloner;
11
use Symfony\Component\VarDumper\Cloner\VarCloner;
12
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
13
use Whoops\Exception\Frame;
14
15
/**
16
 * Exposes useful tools for working with/in templates
17
 */
18
class TemplateHelper
19
{
20
    /**
21
     * An array of variables to be passed to all templates
22
     * @var array
23
     */
24
    private $variables = [];
25
26
    /**
27
     * @var HtmlDumper
28
     */
29
    private $htmlDumper;
30
31
    /**
32
     * @var HtmlDumperOutput
33
     */
34
    private $htmlDumperOutput;
35
36
    /**
37
     * @var AbstractCloner
38
     */
39
    private $cloner;
40
41
    /**
42
     * Escapes a string for output in an HTML document
43
     *
44
     * @param  string $raw
45
     * @return string
46
     */
47 2
    public function escape($raw)
48
    {
49 2
        $flags = ENT_QUOTES;
50
51
        // HHVM has all constants defined, but only ENT_IGNORE
52
        // works at the moment
53 2
        if (defined("ENT_SUBSTITUTE") && !defined("HHVM_VERSION")) {
54 2
            $flags |= ENT_SUBSTITUTE;
55 2
        } else {
56
            // This is for 5.3.
57
            // The documentation warns of a potential security issue,
58
            // but it seems it does not apply in our case, because
59
            // we do not blacklist anything anywhere.
60
            $flags |= ENT_IGNORE;
61
        }
62
63 2
        $raw = str_replace(chr(9), '    ', $raw);
64
        
65 2
        return htmlspecialchars($raw, $flags, "UTF-8");
66
    }
67
68
    /**
69
     * Escapes a string for output in an HTML document, but preserves
70
     * URIs within it, and converts them to clickable anchor elements.
71
     *
72
     * @param  string $raw
73
     * @return string
74
     */
75 1
    public function escapeButPreserveUris($raw)
76
    {
77 1
        $escaped = $this->escape($raw);
78 1
        return preg_replace(
79 1
            "@([A-z]+?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@",
80 1
            "<a href=\"$1\" target=\"_blank\">$1</a>", $escaped
81 1
        );
82
    }
83
84
    /**
85
     * Makes sure that the given string breaks on the delimiter.
86
     *
87
     * @param  string $delimiter
88
     * @param  string $s
89
     * @return string
90
     */
91 1
    public function breakOnDelimiter($delimiter, $s)
92
    {
93 1
        $parts = explode($delimiter, $s);
94 1
        foreach ($parts as &$part) {
95 1
            $part = '<div class="delimiter">' . $part . '</div>';
96 1
        }
97
98 1
        return implode($delimiter, $parts);
99
    }
100
101
    /**
102
     * Replace the part of the path that all files have in common.
103
     *
104
     * @param  string $path
105
     * @return string
106
     */
107
    public function shorten($path)
108
    {
109
        $dirname = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__))))));
110
        if ($dirname != "/") {
111
            $path = str_replace($dirname, '&hellip;', $path);
112
        }
113
114
        return $path;
115
    }
116
117
    private function getDumper()
118
    {
119
        if (!$this->htmlDumper && class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) {
120
            $this->htmlDumperOutput = new HtmlDumperOutput();
121
            // re-use the same var-dumper instance, so it won't re-render the global styles/scripts on each dump.
122
            $this->htmlDumper = new HtmlDumper($this->htmlDumperOutput);
123
124
            $styles = [
125
                'default' => 'color:#FFFFFF; line-height:normal; font:12px "Inconsolata", "Fira Mono", "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace !important; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: normal',
126
                'num' => 'color:#BCD42A',
127
                'const' => 'color: #4bb1b1;',
128
                'str' => 'color:#BCD42A',
129
                'note' => 'color:#ef7c61',
130
                'ref' => 'color:#A0A0A0',
131
                'public' => 'color:#FFFFFF',
132
                'protected' => 'color:#FFFFFF',
133
                'private' => 'color:#FFFFFF',
134
                'meta' => 'color:#FFFFFF',
135
                'key' => 'color:#BCD42A',
136
                'index' => 'color:#ef7c61',
137
            ];
138
            $this->htmlDumper->setStyles($styles);
139
        }
140
141
        return $this->htmlDumper;
142
    }
143
144
    /**
145
     * Format the given value into a human readable string.
146
     *
147
     * @param  mixed $value
148
     * @return string
149
     */
150
    public function dump($value)
151
    {
152
        $dumper = $this->getDumper();
153
154
        if ($dumper) {
155
            // re-use the same DumpOutput instance, so it won't re-render the global styles/scripts on each dump.
156
            // exclude verbose information (e.g. exception stack traces)
157
            if (class_exists('Symfony\Component\VarDumper\Caster\Caster')) {
158
                $cloneVar = $this->getCloner()->cloneVar($value, Caster::EXCLUDE_VERBOSE);
159
            // Symfony VarDumper 2.6 Caster class dont exist.
160
            } else {
161
                $cloneVar = $this->getCloner()->cloneVar($value);
162
            }
163
164
            $dumper->dump(
165
                $cloneVar,
166
                $this->htmlDumperOutput
167
            );
168
169
            $output = $this->htmlDumperOutput->getOutput();
170
            $this->htmlDumperOutput->clear();
171
172
            return $output;
173
        }
174
175
        return print_r($value, true);
176
    }
177
178
    /**
179
     * Format the args of the given Frame as a human readable html string
180
     *
181
     * @param  Frame $frame
182
     * @return string the rendered html
183
     */
184
    public function dumpArgs(Frame $frame)
185
    {
186
        // we support frame args only when the optional dumper is available
187
        if (!$this->getDumper()) {
188
            return '';
189
        }
190
191
        $html = '';
192
        $numFrames = count($frame->getArgs());
193
194
        if ($numFrames > 0) {
195
            $html = '<ol class="linenums">';
196
            foreach($frame->getArgs() as $j => $frameArg) {
197
                $html .= '<li>'. $this->dump($frameArg) .'</li>';
198
            }
199
            $html .= '</ol>';
200
        }
201
202
        return $html;
203
    }
204
205
    /**
206
     * Convert a string to a slug version of itself
207
     *
208
     * @param  string $original
209
     * @return string
210
     */
211 1
    public function slug($original)
212
    {
213 1
        $slug = str_replace(" ", "-", $original);
214 1
        $slug = preg_replace('/[^\w\d\-\_]/i', '', $slug);
215 1
        return strtolower($slug);
216
    }
217
218
    /**
219
     * Given a template path, render it within its own scope. This
220
     * method also accepts an array of additional variables to be
221
     * passed to the template.
222
     *
223
     * @param string $template
224
     * @param array  $additionalVariables
225
     */
226 1
    public function render($template, array $additionalVariables = null)
227
    {
228 1
        $variables = $this->getVariables();
229
230
        // Pass the helper to the template:
231 1
        $variables["tpl"] = $this;
232
233 1
        if ($additionalVariables !== null) {
234 1
            $variables = array_replace($variables, $additionalVariables);
235 1
        }
236
237 1
        call_user_func(function () {
238 1
            extract(func_get_arg(1));
0 ignored issues
show
Bug introduced by
func_get_arg(1) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
239 1
            require func_get_arg(0);
240 1
        }, $template, $variables);
241 1
    }
242
243
    /**
244
     * Sets the variables to be passed to all templates rendered
245
     * by this template helper.
246
     *
247
     * @param array $variables
248
     */
249 1
    public function setVariables(array $variables)
250
    {
251 1
        $this->variables = $variables;
252 1
    }
253
254
    /**
255
     * Sets a single template variable, by its name:
256
     *
257
     * @param string $variableName
258
     * @param mixd   $variableValue
259
     */
260 1
    public function setVariable($variableName, $variableValue)
261
    {
262 1
        $this->variables[$variableName] = $variableValue;
263 1
    }
264
265
    /**
266
     * Gets a single template variable, by its name, or
267
     * $defaultValue if the variable does not exist
268
     *
269
     * @param  string $variableName
270
     * @param  mixed  $defaultValue
271
     * @return mixed
272
     */
273 1
    public function getVariable($variableName, $defaultValue = null)
274
    {
275 1
        return isset($this->variables[$variableName]) ?
276 1
            $this->variables[$variableName] : $defaultValue;
277
    }
278
279
    /**
280
     * Unsets a single template variable, by its name
281
     *
282
     * @param string $variableName
283
     */
284 1
    public function delVariable($variableName)
285
    {
286 1
        unset($this->variables[$variableName]);
287 1
    }
288
289
    /**
290
     * Returns all variables for this helper
291
     *
292
     * @return array
293
     */
294 1
    public function getVariables()
295
    {
296 1
        return $this->variables;
297
    }
298
299
    /**
300
     * Set the cloner used for dumping variables.
301
     *
302
     * @param AbstractCloner $cloner
303
     */
304
    public function setCloner($cloner)
305
    {
306
        $this->cloner = $cloner;
307
    }
308
309
    /**
310
     * Get the cloner used for dumping variables.
311
     *
312
     * @return AbstractCloner
313
     */
314
    public function getCloner()
315
    {
316
        if (!$this->cloner) {
317
            $this->cloner = new VarCloner();
318
        }
319
        return $this->cloner;
320
    }
321
}
322