Completed
Push — master ( d5937b...92bdc6 )
by Denis
10s
created

TemplateHelper::getApplicationRootPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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