Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

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