Version 1
[yaffs-website] / web / modules / contrib / devel / kint / src / Twig / KintExtension.php
1 <?php
2
3 namespace Drupal\kint\Twig;
4
5 /**
6  * Provides the Kint debugging function within Twig templates.
7  */
8 class KintExtension extends \Twig_Extension {
9
10   /**
11    * {@inheritdoc}
12    */
13   public function getName() {
14     return 'kint';
15   }
16
17   /**
18    * {@inheritdoc}
19    */
20   public function getFunctions() {
21     return array(
22       new \Twig_SimpleFunction('kint', array($this, 'kint'), array(
23         'is_safe' => array('html'),
24         'needs_environment' => TRUE,
25         'needs_context' => TRUE,
26         'is_variadic' => TRUE,
27       )),
28     );
29   }
30
31   /**
32    * Provides Kint function to Twig templates.
33    *
34    * Handles 0, 1, or multiple arguments.
35    *
36    * Code derived from https://github.com/barelon/CgKintBundle.
37    *
38    * @param \Twig_Environment $env
39    *   The twig environment instance.
40    * @param array $context
41    *   An array of parameters passed to the template.
42    * @param array $args
43    *   An array of parameters passed the function.
44    *
45    * @return string
46    *   String representation of the input variables.
47    */
48   public function kint(\Twig_Environment $env, array $context, array $args = []) {
49     // Don't do anything unless twig_debug is enabled. This reads from the Twig
50     // environment, not Drupal Settings, so a container rebuild is necessary
51     // when toggling twig_debug on and off. We can consider injecting Settings.
52     if (!$env->isDebug()) {
53       return;
54     }
55     kint_require();
56     // Don't display where Kint was called from.
57     // @todo Can we add information about which template Kint was called from?
58     \Kint::$displayCalledFrom = FALSE;
59
60     // No arguments passed to kint(), display full Twig context.
61     if (empty($args)) {
62       $kint_variable = array();
63       foreach ($context as $key => $value) {
64         if (!$value instanceof \Twig_Template) {
65           $kint_variable[$key] = $value;
66         }
67       }
68
69       $result = @\Kint::dump($kint_variable);
70       $output = str_replace('$kint_variable', 'Twig context', $result);
71     }
72     else {
73       // Try to get the names of variables from the Twig template.
74       $parameters = $this->getTwigFunctionParameters();
75
76       // If there is only one argument, pass to Kint without too much hassle.
77       if (count($args) == 1) {
78         $kint_variable = reset($args);
79         $variable_name = reset($parameters);
80         $result = @\Kint::dump($kint_variable);
81         // Replace $kint_variable with the name of the variable in the Twig
82         // template.
83         $output = str_replace('$kint_variable', $variable_name, $result);
84       }
85       else {
86         $kint_args = [];
87         // Build an array of variable to pass to Kint.
88         // @todo Can we just call_user_func_array while still retaining the
89         //   variable names?
90         foreach ($args as $index => $arg) {
91           // Prepend a unique index to allow debugging the same variable more
92           // than once in the same Kint dump.
93           $name = !empty($parameters[$index]) ? $parameters[$index] : $index;
94           $kint_args['_index_' . $index . '_' . $name] = $arg;
95         }
96
97         $result = @\Kint::dump($kint_args);
98         // Display a comma separated list of the variables contained in this group.
99         $output = str_replace('$kint_args', implode(', ', $parameters), $result);
100         // Remove unique indexes from output.
101         $output = preg_replace('/_index_([0-9]+)_/', '', $output);
102       }
103     }
104
105     return $output;
106   }
107
108   /**
109    * Gets the twig function parameters for the current invocation.
110    *
111    * @return array
112    *   The detected twig function parameters.
113    */
114   protected function getTwigFunctionParameters() {
115     $callee = NULL;
116     $template = NULL;
117
118     $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
119
120     foreach ($backtrace as $index => $trace) {
121       if (isset($trace['object']) && $trace['object'] instanceof \Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
122         $template = $trace['object'];
123         $callee = $backtrace[$index - 1];
124         break;
125       }
126     }
127
128     $parameters = [];
129
130     /** @var \Twig_Template $template */
131     if (NULL !== $template && NULL !== $callee) {
132       $line_number = $callee['line'];
133       $debug_infos = $template->getDebugInfo();
134
135       if (isset($debug_infos[$line_number])) {
136         $source_line = $debug_infos[$line_number];
137         $source_file_name = $template->getTemplateName();
138
139         if (is_readable($source_file_name)) {
140           $source = file($source_file_name, FILE_IGNORE_NEW_LINES);
141           $line = $source[$source_line - 1];
142
143           preg_match('/kint\((.+)\)/', $line, $matches);
144           if (isset($matches[1])) {
145             $parameters = array_map('trim', explode(',', $matches[1]));
146           }
147         }
148       }
149     }
150
151     return $parameters;
152   }
153
154 }