Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
CodeExtension.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Bridge\Twig\Extension;
013
014 use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
015 use Twig\Extension\AbstractExtension;
016 use Twig\TwigFilter;
017
018 /**
019 * Twig extension relate to PHP code and used by the profiler and the default exception templates.
020 *
021 * @author Fabien Potencier <fabien@symfony.com>
022 */
023 class CodeExtension extends AbstractExtension
024 {
025 private $fileLinkFormat;
026 private $rootDir;
027 private $charset;
028
029 /**
030 * @param string|FileLinkFormatter $fileLinkFormat The format for links to source files
031 * @param string $rootDir The project root directory
032 * @param string $charset The charset
033 */
034 public function __construct($fileLinkFormat, $rootDir, $charset)
035 {
036 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
037 $this->rootDir = str_replace('/', \DIRECTORY_SEPARATOR, \dirname($rootDir)).\DIRECTORY_SEPARATOR;
038 $this->charset = $charset;
039 }
040
041 /**
042 * {@inheritdoc}
043 */
044 public function getFilters()
045 {
046 return [
047 new TwigFilter('abbr_class', [$this, 'abbrClass'], ['is_safe' => ['html']]),
048 new TwigFilter('abbr_method', [$this, 'abbrMethod'], ['is_safe' => ['html']]),
049 new TwigFilter('format_args', [$this, 'formatArgs'], ['is_safe' => ['html']]),
050 new TwigFilter('format_args_as_text', [$this, 'formatArgsAsText']),
051 new TwigFilter('file_excerpt', [$this, 'fileExcerpt'], ['is_safe' => ['html']]),
052 new TwigFilter('format_file', [$this, 'formatFile'], ['is_safe' => ['html']]),
053 new TwigFilter('format_file_from_text', [$this, 'formatFileFromText'], ['is_safe' => ['html']]),
054 new TwigFilter('format_log_message', [$this, 'formatLogMessage'], ['is_safe' => ['html']]),
055 new TwigFilter('file_link', [$this, 'getFileLink']),
056 ];
057 }
058
059 public function abbrClass($class)
060 {
061 $parts = explode('\\', $class);
062 $short = array_pop($parts);
063
064 return sprintf('<abbr title="%s">%s</abbr>', $class, $short);
065 }
066
067 public function abbrMethod($method)
068 {
069 if (false !== strpos($method, '::')) {
070 list($class, $method) = explode('::', $method, 2);
071 $result = sprintf('%s::%s()', $this->abbrClass($class), $method);
072 } elseif ('Closure' === $method) {
073 $result = sprintf('<abbr title="%s">%1$s</abbr>', $method);
074 } else {
075 $result = sprintf('<abbr title="%s">%1$s</abbr>()', $method);
076 }
077
078 return $result;
079 }
080
081 /**
082 * Formats an array as a string.
083 *
084 * @param array $args The argument array
085 *
086 * @return string
087 */
088 public function formatArgs($args)
089 {
090 $result = [];
091 foreach ($args as $key => $item) {
092 if ('object' === $item[0]) {
093 $parts = explode('\\', $item[1]);
094 $short = array_pop($parts);
095 $formattedValue = sprintf('<em>object</em>(<abbr title="%s">%s</abbr>)', $item[1], $short);
096 } elseif ('array' === $item[0]) {
097 $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
098 } elseif ('null' === $item[0]) {
099 $formattedValue = '<em>null</em>';
100 } elseif ('boolean' === $item[0]) {
101 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
102 } elseif ('resource' === $item[0]) {
103 $formattedValue = '<em>resource</em>';
104 } else {
105 $formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset));
106 }
107
108 $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
109 }
110
111 return implode(', ', $result);
112 }
113
114 /**
115 * Formats an array as a string.
116 *
117 * @param array $args The argument array
118 *
119 * @return string
120 */
121 public function formatArgsAsText($args)
122 {
123 return strip_tags($this->formatArgs($args));
124 }
125
126 /**
127 * Returns an excerpt of a code file around the given line number.
128 *
129 * @param string $file A file path
130 * @param int $line The selected line number
131 * @param int $srcContext The number of displayed lines around or -1 for the whole file
132 *
133 * @return string An HTML string
134 */
135 public function fileExcerpt($file, $line, $srcContext = 3)
136 {
137 if (is_file($file) && is_readable($file)) {
138 // highlight_file could throw warnings
139 // see https://bugs.php.net/25725
140 $code = @highlight_file($file, true);
141 // remove main code/span tags
142 $code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
143 // split multiline spans
144 $code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', function ($m) {
145 return "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>';
146 }, $code);
147 $content = explode('<br />', $code);
148
149 $lines = [];
150 if (0 > $srcContext) {
151 $srcContext = \count($content);
152 }
153
154 for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) {
155 $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><a class="anchor" name="line'.$i.'"></a><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>';
156 }
157
158 return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>';
159 }
160
161 return null;
162 }
163
164 /**
165 * Formats a file path.
166 *
167 * @param string $file An absolute file path
168 * @param int $line The line number
169 * @param string $text Use this text for the link rather than the file path
170 *
171 * @return string
172 */
173 public function formatFile($file, $line, $text = null)
174 {
175 $file = trim($file);
176
177 if (null === $text) {
178 $text = str_replace('/', \DIRECTORY_SEPARATOR, $file);
179 if (0 === strpos($text, $this->rootDir)) {
180 $text = substr($text, \strlen($this->rootDir));
181 $text = explode(\DIRECTORY_SEPARATOR, $text, 2);
182 $text = sprintf('<abbr title="%s%2$s">%s</abbr>%s', $this->rootDir, $text[0], isset($text[1]) ? \DIRECTORY_SEPARATOR.$text[1] : '');
183 }
184 }
185
186 if (0 < $line) {
187 $text .= ' at line '.$line;
188 }
189
190 if (false !== $link = $this->getFileLink($file, $line)) {
191 return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', htmlspecialchars($link, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), $text);
192 }
193
194 return $text;
195 }
196
197 /**
198 * Returns the link for a given file/line pair.
199 *
200 * @param string $file An absolute file path
201 * @param int $line The line number
202 *
203 * @return string|false A link or false
204 */
205 public function getFileLink($file, $line)
206 {
207 if ($fmt = $this->fileLinkFormat) {
208 return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);
209 }
210
211 return false;
212 }
213
214 public function formatFileFromText($text)
215 {
216 return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) {
217 return 'in '.$this->formatFile($match[2], $match[3]);
218 }, $text);
219 }
220
221 /**
222 * @internal
223 */
224 public function formatLogMessage($message, array $context)
225 {
226 if ($context && false !== strpos($message, '{')) {
227 $replacements = [];
228 foreach ($context as $key => $val) {
229 if (is_scalar($val)) {
230 $replacements['{'.$key.'}'] = $val;
231 }
232 }
233
234 if ($replacements) {
235 $message = strtr($message, $replacements);
236 }
237 }
238
239 return htmlspecialchars($message, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset);
240 }
241
242 /**
243 * {@inheritdoc}
244 */
245 public function getName()
246 {
247 return 'code';
248 }
249
250 protected static function fixCodeMarkup($line)
251 {
252 // </span> ending tag from previous line
253 $opening = strpos($line, '<span');
254 $closing = strpos($line, '</span>');
255 if (false !== $closing && (false === $opening || $closing < $opening)) {
256 $line = substr_replace($line, '', $closing, 7);
257 }
258
259 // missing </span> tag at the end of line
260 $opening = strpos($line, '<span');
261 $closing = strpos($line, '</span>');
262 if (false !== $opening && (false === $closing || $closing > $opening)) {
263 $line .= '</span>';
264 }
265
266 return trim($line);
267 }
268 }
269