Completed
Push — master ( c477d2...1de560 )
by Denis
7s
created

TemplateHelper::dumpArgs()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 20
ccs 0
cts 13
cp 0
rs 9.2
cc 4
eloc 11
nc 3
nop 1
crap 20
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\Cloner\VarCloner;
10
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
11
use Whoops\Exception\Frame;
12
13
/**
14
 * Exposes useful tools for working with/in templates
15
 */
16
class TemplateHelper
17
{
18
    /**
19
     * An array of variables to be passed to all templates
20
     * @var array
21
     */
22
    private $variables = array();
23
24
    /**
25
     * @var HtmlDumper
26
     */
27
    private $htmlDumper;
28
29
    /**
30
     * @var HtmlDumperOutput
31
     */
32
    private $htmlDumperOutput;
33
34
    /**
35
     * Escapes a string for output in an HTML document
36
     *
37
     * @param  string $raw
38
     * @return string
39
     */
40 2
    public function escape($raw)
41
    {
42 2
        $flags = ENT_QUOTES;
43
44
        // HHVM has all constants defined, but only ENT_IGNORE
45
        // works at the moment
46 2
        if (defined("ENT_SUBSTITUTE") && !defined("HHVM_VERSION")) {
47 2
            $flags |= ENT_SUBSTITUTE;
48 2
        } else {
49
            // This is for 5.3.
50
            // The documentation warns of a potential security issue,
51
            // but it seems it does not apply in our case, because
52
            // we do not blacklist anything anywhere.
53
            $flags |= ENT_IGNORE;
54
        }
55
56 2
        return htmlspecialchars($raw, $flags, "UTF-8");
57
    }
58
59
    /**
60
     * Escapes a string for output in an HTML document, but preserves
61
     * URIs within it, and converts them to clickable anchor elements.
62
     *
63
     * @param  string $raw
64
     * @return string
65
     */
66 1
    public function escapeButPreserveUris($raw)
67
    {
68 1
        $escaped = $this->escape($raw);
69 1
        return preg_replace(
70 1
            "@([A-z]+?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@",
71 1
            "<a href=\"$1\" target=\"_blank\">$1</a>", $escaped
72 1
        );
73
    }
74
75
    private function getDumper()
76
    {
77
        if (!$this->htmlDumper && class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) {
78
            $this->htmlDumperOutput = new HtmlDumperOutput();
79
            // re-use the same var-dumper instance, so it won't re-render the global styles/scripts on each dump.
80
            $this->htmlDumper = new HtmlDumper($this->htmlDumperOutput);
81
82
            $styles = array(
83
                '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',
84
                'num' => 'color:#BCD42A',
85
                'const' => 'color: #4bb1b1;',
86
                'str' => 'color:#BCD42A',
87
                'note' => 'color:#ef7c61',
88
                'ref' => 'color:#A0A0A0',
89
                'public' => 'color:#FFFFFF',
90
                'protected' => 'color:#FFFFFF',
91
                'private' => 'color:#FFFFFF',
92
                'meta' => 'color:#FFFFFF',
93
                'key' => 'color:#BCD42A',
94
                'index' => 'color:#ef7c61',
95
            );
96
            $this->htmlDumper->setStyles($styles);
97
        }
98
99
        return $this->htmlDumper;
100
    }
101
102
    /**
103
     * Format the given value into a human readable string.
104
     *
105
     * @param  mixed $value
106
     * @return string
107
     */
108
    public function dump($value)
109
    {
110
        $dumper = $this->getDumper();
111
112
        if ($dumper) {
113
            $cloner = new VarCloner();
114
115
            // re-use the same DumpOutput instance, so it won't re-render the global styles/scripts on each dump.
116
            $dumper->dump($cloner->cloneVar($value), $this->htmlDumperOutput);
117
118
            $output = $this->htmlDumperOutput->getOutput();
119
            $this->htmlDumperOutput->clear();
120
121
            return $output;
122
        }
123
124
        return print_r($value, true);
125
    }
126
127
    /**
128
     * Format the args of the given Frame as a human readable html string
129
     *
130
     * @param  Frame $frame
131
     * @return string the rendered html
132
     */
133
    public function dumpArgs(Frame $frame)
134
    {
135
        // we support frame args only when the optional dumper is available
136
        if (!$this->getDumper()) {
137
            return '';
138
        }
139
140
        $html = '';
141
        $numFrames = count($frame->getArgs());
142
143
        if ($numFrames > 0) {
144
            $html = '<ol class="linenums">';
145
            foreach($frame->getArgs() as $j => $frameArg) {
146
                $html .= '<li>'. $this->dump($frameArg) .'</li>';
147
            }
148
            $html .= '</ol>';
149
        }
150
151
        return $html;
152
    }
153
154
    /**
155
     * Convert a string to a slug version of itself
156
     *
157
     * @param  string $original
158
     * @return string
159
     */
160 1
    public function slug($original)
161
    {
162 1
        $slug = str_replace(" ", "-", $original);
163 1
        $slug = preg_replace('/[^\w\d\-\_]/i', '', $slug);
164 1
        return strtolower($slug);
165
    }
166
167
    /**
168
     * Given a template path, render it within its own scope. This
169
     * method also accepts an array of additional variables to be
170
     * passed to the template.
171
     *
172
     * @param string $template
173
     * @param array  $additionalVariables
174
     */
175 1
    public function render($template, array $additionalVariables = null)
176
    {
177 1
        $variables = $this->getVariables();
178
179
        // Pass the helper to the template:
180 1
        $variables["tpl"] = $this;
181
182 1
        if ($additionalVariables !== null) {
183 1
            $variables = array_replace($variables, $additionalVariables);
184 1
        }
185
186 1
        call_user_func(function () {
187 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...
188 1
            require func_get_arg(0);
189 1
        }, $template, $variables);
190 1
    }
191
192
    /**
193
     * Sets the variables to be passed to all templates rendered
194
     * by this template helper.
195
     *
196
     * @param array $variables
197
     */
198 1
    public function setVariables(array $variables)
199
    {
200 1
        $this->variables = $variables;
201 1
    }
202
203
    /**
204
     * Sets a single template variable, by its name:
205
     *
206
     * @param string $variableName
207
     * @param mixd   $variableValue
208
     */
209 1
    public function setVariable($variableName, $variableValue)
210
    {
211 1
        $this->variables[$variableName] = $variableValue;
212 1
    }
213
214
    /**
215
     * Gets a single template variable, by its name, or
216
     * $defaultValue if the variable does not exist
217
     *
218
     * @param  string $variableName
219
     * @param  mixed  $defaultValue
220
     * @return mixed
221
     */
222 1
    public function getVariable($variableName, $defaultValue = null)
223
    {
224 1
        return isset($this->variables[$variableName]) ?
225 1
            $this->variables[$variableName] : $defaultValue;
226
    }
227
228
    /**
229
     * Unsets a single template variable, by its name
230
     *
231
     * @param string $variableName
232
     */
233 1
    public function delVariable($variableName)
234
    {
235 1
        unset($this->variables[$variableName]);
236 1
    }
237
238
    /**
239
     * Returns all variables for this helper
240
     *
241
     * @return array
242
     */
243 1
    public function getVariables()
244
    {
245 1
        return $this->variables;
246
    }
247
}
248