Complex classes like Twig_Template often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Twig_Template, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | abstract class Twig_Template implements Twig_TemplateInterface |
||
|
|||
19 | { |
||
20 | protected static $cache = array(); |
||
21 | |||
22 | protected $parent; |
||
23 | protected $parents = array(); |
||
24 | protected $env; |
||
25 | protected $blocks; |
||
26 | protected $traits; |
||
27 | |||
28 | /** |
||
29 | * Constructor. |
||
30 | * |
||
31 | * @param Twig_Environment $env A Twig_Environment instance |
||
32 | */ |
||
33 | public function __construct(Twig_Environment $env) |
||
34 | { |
||
35 | $this->env = $env; |
||
36 | $this->blocks = array(); |
||
37 | $this->traits = array(); |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * Returns the template name. |
||
42 | * |
||
43 | * @return string The template name |
||
44 | */ |
||
45 | abstract public function getTemplateName(); |
||
46 | |||
47 | /** |
||
48 | * {@inheritdoc} |
||
49 | */ |
||
50 | public function getEnvironment() |
||
54 | |||
55 | /** |
||
56 | * Returns the parent template. |
||
57 | * |
||
58 | * This method is for internal use only and should never be called |
||
59 | * directly. |
||
60 | * |
||
61 | * @return Twig_TemplateInterface|false The parent template or false if there is no parent |
||
62 | */ |
||
63 | public function getParent(array $context) |
||
64 | { |
||
65 | if (null !== $this->parent) { |
||
66 | return $this->parent; |
||
67 | } |
||
68 | |||
69 | try { |
||
70 | $parent = $this->doGetParent($context); |
||
71 | |||
72 | if (false === $parent) { |
||
73 | return false; |
||
74 | } |
||
75 | |||
76 | if ($parent instanceof Twig_Template) { |
||
77 | return $this->parents[$parent->getTemplateName()] = $parent; |
||
78 | } |
||
79 | |||
80 | if (!isset($this->parents[$parent])) { |
||
81 | $this->parents[$parent] = $this->env->loadTemplate($parent); |
||
82 | } |
||
83 | } catch (Twig_Error_Loader $e) { |
||
84 | $e->setTemplateFile(null); |
||
85 | $e->guess(); |
||
86 | |||
87 | throw $e; |
||
88 | } |
||
89 | |||
90 | return $this->parents[$parent]; |
||
91 | } |
||
92 | |||
93 | protected function doGetParent(array $context) |
||
97 | |||
98 | public function isTraitable() |
||
102 | |||
103 | /** |
||
104 | * Displays a parent block. |
||
105 | * |
||
106 | * This method is for internal use only and should never be called |
||
107 | * directly. |
||
108 | * |
||
109 | * @param string $name The block name to display from the parent |
||
110 | * @param array $context The context |
||
111 | * @param array $blocks The current set of blocks |
||
112 | */ |
||
113 | public function displayParentBlock($name, array $context, array $blocks = array()) |
||
114 | { |
||
115 | $name = (string) $name; |
||
116 | |||
117 | if (isset($this->traits[$name])) { |
||
118 | $this->traits[$name][0]->displayBlock($name, $context, $blocks, false); |
||
119 | } elseif (false !== $parent = $this->getParent($context)) { |
||
120 | $parent->displayBlock($name, $context, $blocks, false); |
||
121 | } else { |
||
122 | throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block', $name), -1, $this->getTemplateName()); |
||
123 | } |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Displays a block. |
||
128 | * |
||
129 | * This method is for internal use only and should never be called |
||
130 | * directly. |
||
131 | * |
||
132 | * @param string $name The block name to display |
||
133 | * @param array $context The context |
||
134 | * @param array $blocks The current set of blocks |
||
135 | * @param bool $useBlocks Whether to use the current set of blocks |
||
136 | */ |
||
137 | public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true) |
||
138 | { |
||
139 | $name = (string) $name; |
||
140 | |||
141 | if ($useBlocks && isset($blocks[$name])) { |
||
142 | $template = $blocks[$name][0]; |
||
143 | $block = $blocks[$name][1]; |
||
144 | } elseif (isset($this->blocks[$name])) { |
||
145 | $template = $this->blocks[$name][0]; |
||
146 | $block = $this->blocks[$name][1]; |
||
147 | } else { |
||
148 | $template = null; |
||
149 | $block = null; |
||
150 | } |
||
151 | |||
152 | if (null !== $template) { |
||
153 | try { |
||
154 | $template->$block($context, $blocks); |
||
155 | } catch (Twig_Error $e) { |
||
156 | throw $e; |
||
157 | } catch (Exception $e) { |
||
158 | throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e); |
||
159 | } |
||
160 | } elseif (false !== $parent = $this->getParent($context)) { |
||
161 | $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false); |
||
162 | } |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * Renders a parent block. |
||
167 | * |
||
168 | * This method is for internal use only and should never be called |
||
169 | * directly. |
||
170 | * |
||
171 | * @param string $name The block name to render from the parent |
||
172 | * @param array $context The context |
||
173 | * @param array $blocks The current set of blocks |
||
174 | * |
||
175 | * @return string The rendered block |
||
176 | */ |
||
177 | public function renderParentBlock($name, array $context, array $blocks = array()) |
||
178 | { |
||
179 | ob_start(); |
||
180 | $this->displayParentBlock($name, $context, $blocks); |
||
181 | |||
182 | return ob_get_clean(); |
||
183 | } |
||
184 | |||
185 | /** |
||
186 | * Renders a block. |
||
187 | * |
||
188 | * This method is for internal use only and should never be called |
||
189 | * directly. |
||
190 | * |
||
191 | * @param string $name The block name to render |
||
192 | * @param array $context The context |
||
193 | * @param array $blocks The current set of blocks |
||
194 | * @param bool $useBlocks Whether to use the current set of blocks |
||
195 | * |
||
196 | * @return string The rendered block |
||
197 | */ |
||
198 | public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true) |
||
199 | { |
||
200 | ob_start(); |
||
201 | $this->displayBlock($name, $context, $blocks, $useBlocks); |
||
202 | |||
203 | return ob_get_clean(); |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * Returns whether a block exists or not. |
||
208 | * |
||
209 | * This method is for internal use only and should never be called |
||
210 | * directly. |
||
211 | * |
||
212 | * This method does only return blocks defined in the current template |
||
213 | * or defined in "used" traits. |
||
214 | * |
||
215 | * It does not return blocks from parent templates as the parent |
||
216 | * template name can be dynamic, which is only known based on the |
||
217 | * current context. |
||
218 | * |
||
219 | * @param string $name The block name |
||
220 | * |
||
221 | * @return bool true if the block exists, false otherwise |
||
222 | */ |
||
223 | public function hasBlock($name) |
||
227 | |||
228 | /** |
||
229 | * Returns all block names. |
||
230 | * |
||
231 | * This method is for internal use only and should never be called |
||
232 | * directly. |
||
233 | * |
||
234 | * @return array An array of block names |
||
235 | * |
||
236 | * @see hasBlock |
||
237 | */ |
||
238 | public function getBlockNames() |
||
242 | |||
243 | /** |
||
244 | * Returns all blocks. |
||
245 | * |
||
246 | * This method is for internal use only and should never be called |
||
247 | * directly. |
||
248 | * |
||
249 | * @return array An array of blocks |
||
250 | * |
||
251 | * @see hasBlock |
||
252 | */ |
||
253 | public function getBlocks() |
||
257 | |||
258 | /** |
||
259 | * {@inheritdoc} |
||
260 | */ |
||
261 | public function display(array $context, array $blocks = array()) |
||
265 | |||
266 | /** |
||
267 | * {@inheritdoc} |
||
268 | */ |
||
269 | public function render(array $context) |
||
270 | { |
||
271 | $level = ob_get_level(); |
||
272 | ob_start(); |
||
273 | try { |
||
274 | $this->display($context); |
||
275 | } catch (Exception $e) { |
||
276 | while (ob_get_level() > $level) { |
||
277 | ob_end_clean(); |
||
278 | } |
||
279 | |||
280 | throw $e; |
||
281 | } |
||
282 | |||
283 | return ob_get_clean(); |
||
284 | } |
||
285 | |||
286 | protected function displayWithErrorHandling(array $context, array $blocks = array()) |
||
287 | { |
||
288 | try { |
||
289 | $this->doDisplay($context, $blocks); |
||
290 | } catch (Twig_Error $e) { |
||
291 | if (!$e->getTemplateFile()) { |
||
292 | $e->setTemplateFile($this->getTemplateName()); |
||
293 | } |
||
294 | |||
295 | // this is mostly useful for Twig_Error_Loader exceptions |
||
296 | // see Twig_Error_Loader |
||
297 | if (false === $e->getTemplateLine()) { |
||
298 | $e->setTemplateLine(-1); |
||
299 | $e->guess(); |
||
300 | } |
||
301 | |||
302 | throw $e; |
||
303 | } catch (Exception $e) { |
||
304 | throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getTemplateName(), $e); |
||
305 | } |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * Auto-generated method to display the template with the given context. |
||
310 | * |
||
311 | * @param array $context An array of parameters to pass to the template |
||
312 | * @param array $blocks An array of blocks to pass to the template |
||
313 | */ |
||
314 | abstract protected function doDisplay(array $context, array $blocks = array()); |
||
315 | |||
316 | /** |
||
317 | * Returns a variable from the context. |
||
318 | * |
||
319 | * This method is for internal use only and should never be called |
||
320 | * directly. |
||
321 | * |
||
322 | * This method should not be overridden in a sub-class as this is an |
||
323 | * implementation detail that has been introduced to optimize variable |
||
324 | * access for versions of PHP before 5.4. This is not a way to override |
||
325 | * the way to get a variable value. |
||
326 | * |
||
327 | * @param array $context The context |
||
328 | * @param string $item The variable to return from the context |
||
329 | * @param bool $ignoreStrictCheck Whether to ignore the strict variable check or not |
||
330 | * |
||
331 | * @return The content of the context variable |
||
332 | * |
||
333 | * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode |
||
334 | */ |
||
335 | final protected function getContext($context, $item, $ignoreStrictCheck = false) |
||
347 | |||
348 | /** |
||
349 | * Returns the attribute value for a given array/object. |
||
350 | * |
||
351 | * @param mixed $object The object or array from where to get the item |
||
352 | * @param mixed $item The item to get from the array or object |
||
353 | * @param array $arguments An array of arguments to pass if the item is an object method |
||
354 | * @param string $type The type of attribute (@see Twig_Template constants) |
||
355 | * @param bool $isDefinedTest Whether this is only a defined check |
||
356 | * @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not |
||
357 | * |
||
358 | * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true |
||
359 | * |
||
360 | * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false |
||
361 | */ |
||
362 | protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) |
||
491 | } |
||
492 |
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.