Total Complexity | 55 |
Total Lines | 614 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like SmartyTask 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.
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 SmartyTask, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
50 | class SmartyTask extends Task |
||
51 | { |
||
52 | /** |
||
53 | * Smarty template engine. |
||
54 | * |
||
55 | * @var Smarty |
||
56 | */ |
||
57 | protected $context; |
||
58 | |||
59 | /** |
||
60 | * Variables that are assigned to the context on parse/compile. |
||
61 | * |
||
62 | * @var array |
||
63 | */ |
||
64 | protected $properties = []; |
||
65 | |||
66 | /** |
||
67 | * This is the control template that governs the output. |
||
68 | * It may or may not invoke the services of worker |
||
69 | * templates. |
||
70 | * |
||
71 | * @var string |
||
72 | */ |
||
73 | protected $controlTemplate; |
||
74 | |||
75 | /** |
||
76 | * This is where Smarty will look for templates |
||
77 | * using the file template loader. |
||
78 | * |
||
79 | * @var string |
||
80 | */ |
||
81 | protected $templatePath; |
||
82 | |||
83 | /** |
||
84 | * This is where texen will place all the output |
||
85 | * that is a product of the generation process. |
||
86 | * |
||
87 | * @var string |
||
88 | */ |
||
89 | protected $outputDirectory; |
||
90 | |||
91 | /** |
||
92 | * This is the file where the generated text |
||
93 | * will be placed. |
||
94 | * |
||
95 | * @var string |
||
96 | */ |
||
97 | protected $outputFile; |
||
98 | |||
99 | /** |
||
100 | * <p> |
||
101 | * These are properties that are fed into the |
||
102 | * initial context from a properties file. This |
||
103 | * is simply a convenient way to set some values |
||
104 | * that you wish to make available in the context. |
||
105 | * </p> |
||
106 | * <p> |
||
107 | * These values are not critical, like the template path |
||
108 | * or output path, but allow a convenient way to |
||
109 | * set a value that may be specific to a particular |
||
110 | * generation task. |
||
111 | * </p> |
||
112 | * <p> |
||
113 | * For example, if you are generating scripts to allow |
||
114 | * user to automatically create a database, then |
||
115 | * you might want the <code>$databaseName</code> |
||
116 | * to be placed |
||
117 | * in the initial context so that it is available |
||
118 | * in a script that might look something like the |
||
119 | * following: |
||
120 | * <code><pre> |
||
121 | * #!bin/sh |
||
122 | * |
||
123 | * echo y | mysqladmin create $databaseName |
||
124 | * </pre></code> |
||
125 | * The value of <code>$databaseName</code> isn't critical to |
||
126 | * output, and you obviously don't want to change |
||
127 | * the ant task to simply take a database name. |
||
128 | * So initial context values can be set with |
||
129 | * properties file. |
||
130 | * |
||
131 | * @var Properties |
||
132 | */ |
||
133 | protected $contextProperties; |
||
134 | |||
135 | /** |
||
136 | * Smarty compiles templates before parsing / replacing tokens in them. |
||
137 | * By default it will try ./templates_c, but you may wish to override this. |
||
138 | * |
||
139 | * @var string |
||
140 | */ |
||
141 | protected $compilePath; |
||
142 | |||
143 | /** |
||
144 | * Whether to force Smarty to recompile templates. |
||
145 | * Smarty does check file modification time, but you can set this |
||
146 | * to be *sure* that the template will be compiled (of course it will |
||
147 | * be slower if you do). |
||
148 | * |
||
149 | * @var boolean |
||
150 | */ |
||
151 | protected $forceCompile = false; |
||
152 | |||
153 | /** |
||
154 | * Smarty can use config files. |
||
155 | * This tells Smarty where to look for the config files. |
||
156 | * |
||
157 | * @var string |
||
158 | */ |
||
159 | protected $configPath; |
||
160 | |||
161 | /** |
||
162 | * Customize the left delimiter for Smarty tags. |
||
163 | * |
||
164 | * @var string |
||
165 | */ |
||
166 | protected $leftDelimiter; |
||
167 | |||
168 | /** |
||
169 | * Customize the right delimiter for Smarty tags. |
||
170 | * |
||
171 | * @var string |
||
172 | */ |
||
173 | protected $rightDelimiter; |
||
174 | |||
175 | // ----------------------------------------------------------------------- |
||
176 | // The following getters & setters are used by phing to set properties |
||
177 | // specified in the XML for the smarty task. |
||
178 | // ----------------------------------------------------------------------- |
||
179 | |||
180 | public function init() |
||
181 | { |
||
182 | if (!class_exists('Smarty\\Smarty')) { |
||
183 | throw new BuildException("To use SmartyTask, you must have the path to Smarty.class.php on your include_path or your \$PHP_CLASSPATH environment variable."); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * [REQUIRED] Set the control template for the |
||
189 | * generating process. |
||
190 | * |
||
191 | * @param string $controlTemplate |
||
192 | * @return void |
||
193 | */ |
||
194 | public function setControlTemplate($controlTemplate) |
||
195 | { |
||
196 | $this->controlTemplate = $controlTemplate; |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Get the control template for the |
||
201 | * generating process. |
||
202 | * |
||
203 | * @return string |
||
204 | */ |
||
205 | public function getControlTemplate() |
||
206 | { |
||
207 | return $this->controlTemplate; |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * [REQUIRED] Set the path where Smarty will look |
||
212 | * for templates using the file template |
||
213 | * loader. |
||
214 | * |
||
215 | * @param $templatePath |
||
216 | * @return void |
||
217 | */ |
||
218 | public function setTemplatePath($templatePath) |
||
219 | { |
||
220 | $resolvedPath = ""; |
||
221 | $tok = strtok($templatePath, ","); |
||
222 | while ($tok) { |
||
223 | // resolve relative path from basedir and leave |
||
224 | // absolute path untouched. |
||
225 | $fullPath = $this->project->resolveFile($tok); |
||
226 | $cpath = $fullPath->getCanonicalPath(); |
||
227 | if ($cpath === false) { |
||
228 | $this->log("Template directory does not exist: " . $fullPath->getAbsolutePath()); |
||
229 | } else { |
||
230 | $resolvedPath .= $cpath; |
||
231 | } |
||
232 | $tok = strtok(","); |
||
233 | if ($tok) { |
||
234 | $resolvedPath .= ","; |
||
235 | } |
||
236 | } |
||
237 | $this->templatePath = $resolvedPath; |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Get the path where Smarty will look |
||
242 | * for templates using the file template |
||
243 | * loader. |
||
244 | * |
||
245 | * @return string |
||
246 | */ |
||
247 | public function getTemplatePath() |
||
248 | { |
||
249 | return $this->templatePath; |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * [REQUIRED] Set the output directory. It will be |
||
254 | * created if it doesn't exist. |
||
255 | * |
||
256 | * @param File $outputDirectory |
||
257 | * @return void |
||
258 | * @throws \Exception |
||
259 | */ |
||
260 | public function setOutputDirectory(File $outputDirectory) |
||
261 | { |
||
262 | try { |
||
263 | if (!$outputDirectory->exists()) { |
||
264 | $this->log( |
||
265 | "Output directory does not exist, creating: " . $outputDirectory->getPath(), |
||
266 | Project::MSG_VERBOSE |
||
267 | ); |
||
268 | if (!$outputDirectory->mkdirs()) { |
||
269 | throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath()); |
||
270 | } |
||
271 | } |
||
272 | $this->outputDirectory = $outputDirectory->getCanonicalPath(); |
||
273 | } catch (IOException $ioe) { |
||
274 | throw new BuildException($ioe->getMessage()); |
||
275 | } |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Get the output directory. |
||
280 | * |
||
281 | * @return string |
||
282 | */ |
||
283 | public function getOutputDirectory() |
||
284 | { |
||
285 | return $this->outputDirectory; |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * [REQUIRED] Set the output file for the |
||
290 | * generation process. |
||
291 | * |
||
292 | * @param $outputFile |
||
293 | * @return void |
||
294 | */ |
||
295 | public function setOutputFile($outputFile) |
||
296 | { |
||
297 | $this->outputFile = $outputFile; |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Get the output file for the |
||
302 | * generation process. |
||
303 | * |
||
304 | * @return string |
||
305 | */ |
||
306 | public function getOutputFile() |
||
307 | { |
||
308 | return $this->outputFile; |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Set the path Smarty uses as a "cache" for compiled templates. |
||
313 | * |
||
314 | * @param string $compilePath |
||
315 | */ |
||
316 | public function setCompilePath($compilePath) |
||
317 | { |
||
318 | $this->compilePath = $compilePath; |
||
319 | } |
||
320 | |||
321 | /** |
||
322 | * Get the path Smarty uses for compiling templates. |
||
323 | * |
||
324 | * @return string |
||
325 | */ |
||
326 | public function getCompilePath() |
||
327 | { |
||
328 | return $this->compilePath; |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * Set whether Smarty should always recompile templates. |
||
333 | * |
||
334 | * @param boolean $force |
||
335 | * @return void |
||
336 | */ |
||
337 | public function setForceCompile($force) |
||
338 | { |
||
339 | $this->forceCompile = (bool) $force; |
||
340 | } |
||
341 | |||
342 | /** |
||
343 | * Get whether Smarty should always recompile template. |
||
344 | * |
||
345 | * @return boolean |
||
346 | */ |
||
347 | public function getForceCompile() |
||
348 | { |
||
349 | return $this->forceCompile; |
||
350 | } |
||
351 | |||
352 | /** |
||
353 | * Set where Smarty looks for config files. |
||
354 | * |
||
355 | * @param string $configPath |
||
356 | * @return void |
||
357 | */ |
||
358 | public function setConfigPath($configPath) |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * Get the path that Smarty uses for looking for config files. |
||
365 | * |
||
366 | * @return string |
||
367 | */ |
||
368 | public function getConfigPath() |
||
371 | } |
||
372 | |||
373 | /** |
||
374 | * Set Smarty template left delimiter. |
||
375 | * |
||
376 | * @param string $delim |
||
377 | * @return void |
||
378 | */ |
||
379 | public function setLeftDelimiter($delim) |
||
380 | { |
||
381 | $this->leftDelimiter = $delim; |
||
382 | } |
||
383 | |||
384 | /** |
||
385 | * Get Smarty template right delimiter |
||
386 | * |
||
387 | * @return string |
||
388 | */ |
||
389 | public function getLeftDelimiter() |
||
390 | { |
||
391 | return $this->leftDelimiter; |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * Set Smarty template right delimiter. |
||
396 | * |
||
397 | * @param string $delim |
||
398 | * @return void |
||
399 | */ |
||
400 | public function setRightDelimiter($delim) |
||
403 | } |
||
404 | |||
405 | /** |
||
406 | * Get Smarty template right delimiter |
||
407 | * |
||
408 | * @return string |
||
409 | */ |
||
410 | public function getRightDelimiter() |
||
411 | { |
||
412 | return $this->rightDelimiter; |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * Set the context properties that will be |
||
417 | * fed into the initial context be the |
||
418 | * generating process starts. |
||
419 | * |
||
420 | * @param string $file |
||
421 | * @throws BuildException |
||
422 | * @return void |
||
423 | */ |
||
424 | public function setContextProperties($file) |
||
425 | { |
||
426 | $sources = explode(",", $file); |
||
427 | $this->contextProperties = new Properties(); |
||
428 | |||
429 | // Always try to get the context properties resource |
||
430 | // from a file first. Templates may be taken from a JAR |
||
431 | // file but the context properties resource may be a |
||
432 | // resource in the filesystem. If this fails than attempt |
||
433 | // to get the context properties resource from the |
||
434 | // classpath. |
||
435 | for ($i = 0, $sourcesLength = count($sources); $i < $sourcesLength; $i++) { |
||
436 | $source = new Properties(); |
||
437 | |||
438 | try { |
||
439 | // resolve relative path from basedir and leave |
||
440 | // absolute path untouched. |
||
441 | $fullPath = $this->project->resolveFile($sources[$i]); |
||
442 | $this->log("Using contextProperties file: " . $fullPath->__toString()); |
||
443 | $source->load($fullPath); |
||
444 | } catch (\Exception $e) { |
||
445 | throw new BuildException( |
||
446 | "Context properties file " . $sources[$i] . |
||
447 | " could not be found in the file system!" |
||
448 | ); |
||
449 | } |
||
450 | |||
451 | $keys = $source->keys(); |
||
452 | |||
453 | foreach ($keys as $key) { |
||
454 | $name = $key; |
||
455 | $value = $this->project->replaceProperties($source->getProperty($name)); |
||
456 | $this->contextProperties->setProperty($name, $value); |
||
457 | } |
||
458 | } |
||
459 | } |
||
460 | |||
461 | /** |
||
462 | * Get the context properties that will be |
||
463 | * fed into the initial context be the |
||
464 | * generating process starts. |
||
465 | * |
||
466 | * @return Properties |
||
467 | */ |
||
468 | public function getContextProperties() |
||
469 | { |
||
470 | return $this->contextProperties; |
||
471 | } |
||
472 | |||
473 | // --------------------------------------------------------------- |
||
474 | // End of XML setters & getters |
||
475 | // --------------------------------------------------------------- |
||
476 | |||
477 | /** |
||
478 | * Creates a Smarty object. |
||
479 | * |
||
480 | * @return Smarty initialized (cleared) Smarty context. |
||
481 | * @throws \Exception the execute method will catch |
||
482 | * and rethrow as a <code>BuildException</code> |
||
483 | */ |
||
484 | public function initControlContext() |
||
485 | { |
||
486 | $this->context->clearAllAssign(); |
||
487 | |||
488 | return $this->context; |
||
489 | } |
||
490 | |||
491 | /** |
||
492 | * Execute the input script with Smarty |
||
493 | * |
||
494 | * @throws BuildException |
||
495 | * BuildExceptions are thrown when required attributes are missing. |
||
496 | * Exceptions thrown by Smarty are rethrown as BuildExceptions. |
||
497 | */ |
||
498 | public function main() |
||
499 | { |
||
500 | |||
501 | // Make sure the template path is set. |
||
502 | if (empty($this->templatePath)) { |
||
503 | throw new BuildException("The template path needs to be defined!"); |
||
504 | } |
||
505 | |||
506 | // Make sure the control template is set. |
||
507 | if ($this->controlTemplate === null) { |
||
508 | throw new BuildException("The control template needs to be defined!"); |
||
509 | } |
||
510 | |||
511 | // Make sure the output directory is set. |
||
512 | if ($this->outputDirectory === null) { |
||
513 | throw new BuildException("The output directory needs to be defined!"); |
||
514 | } |
||
515 | |||
516 | // Make sure there is an output file. |
||
517 | if ($this->outputFile === null) { |
||
518 | throw new BuildException("The output file needs to be defined!"); |
||
519 | } |
||
520 | |||
521 | // Setup Smarty runtime. |
||
522 | |||
523 | $this->context = new Smarty(); |
||
524 | |||
525 | if ($this->compilePath !== null) { |
||
526 | $this->log("Using compilePath: " . $this->compilePath); |
||
527 | $this->context->setCompileDir($this->compilePath); |
||
528 | } |
||
529 | |||
530 | if ($this->configPath !== null) { |
||
531 | $this->log("Using configPath: " . $this->configPath); |
||
532 | $this->context->setConfigDir($this->configPath); |
||
533 | } |
||
534 | |||
535 | if ($this->forceCompile !== null) { |
||
536 | $this->context->setForceCompile($this->forceCompile); |
||
537 | } |
||
538 | |||
539 | if ($this->leftDelimiter !== null) { |
||
540 | $this->context->setLeftDelimiter($this->leftDelimiter); |
||
541 | } |
||
542 | |||
543 | if ($this->rightDelimiter !== null) { |
||
544 | $this->context->setRightDelimiter($this->rightDelimiter); |
||
545 | } |
||
546 | |||
547 | if ($this->templatePath !== null) { |
||
548 | $this->log("Using templatePath: " . $this->templatePath); |
||
549 | $this->context->setTemplateDir($this->templatePath); |
||
550 | } |
||
551 | |||
552 | $smartyCompilePath = new File($this->context->getCompileDir()); |
||
553 | if (!$smartyCompilePath->exists()) { |
||
554 | $this->log( |
||
555 | "Compile directory does not exist, creating: " . $smartyCompilePath->getPath(), |
||
556 | Project::MSG_VERBOSE |
||
557 | ); |
||
558 | if (!$smartyCompilePath->mkdirs()) { |
||
559 | throw new BuildException("Smarty needs a place to compile templates; specify a 'compilePath' or create " . $this->context->getCompileDir()); |
||
560 | } |
||
561 | } |
||
562 | |||
563 | // Make sure the output directory exists, if it doesn't |
||
564 | // then create it. |
||
565 | $file = new File($this->outputDirectory); |
||
566 | if (!$file->exists()) { |
||
567 | $this->log("Output directory does not exist, creating: " . $file->getAbsolutePath()); |
||
568 | $file->mkdirs(); |
||
569 | } |
||
570 | |||
571 | $path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile; |
||
572 | $this->log("Generating to file " . $path); |
||
573 | |||
574 | $writer = new FileWriter($path); |
||
575 | |||
576 | // The generator and the output path should |
||
577 | // be placed in the init context here and |
||
578 | // not in the generator class itself. |
||
579 | $c = $this->initControlContext(); |
||
580 | |||
581 | // Set any variables that need to always |
||
582 | // be loaded |
||
583 | $this->populateInitialContext($c); |
||
584 | |||
585 | // Feed all the options into the initial |
||
586 | // control context so they are available |
||
587 | // in the control/worker templates. |
||
588 | if ($this->contextProperties !== null) { |
||
589 | foreach ($this->contextProperties->keys() as $property) { |
||
590 | $value = $this->contextProperties->getProperty($property); |
||
591 | |||
592 | // Special exception (from Texen) |
||
593 | // for properties ending in file.contents: |
||
594 | // in that case we dump the contents of the file |
||
595 | // as the "value" for the Property. |
||
596 | if (StringHelper::endsWith("file.contents", $property)) { |
||
597 | // pull in contents of file specified |
||
598 | |||
599 | $property = substr($property, 0, strpos($property, "file.contents") - 1); |
||
600 | |||
601 | // reset value, and then |
||
602 | // read in the contents of the file into that var |
||
603 | $value = ""; |
||
604 | $f = new File($this->project->resolveFile($value)->getCanonicalPath()); |
||
605 | if ($f->exists()) { |
||
606 | try { |
||
607 | $br = new BufferedReader(new FileReader($f)); |
||
608 | $value = $br->read(); |
||
609 | } catch (\Exception $e) { |
||
610 | throw $e; |
||
611 | } |
||
612 | } |
||
613 | } // if ends with file.contents |
||
614 | |||
615 | if (StringHelper::isBoolean($value)) { |
||
616 | $value = StringHelper::booleanValue($value); |
||
617 | } |
||
618 | |||
619 | $c->assign($property, $value); |
||
620 | } // foreach property |
||
621 | } // if contextProperties !== null |
||
622 | |||
623 | try { |
||
624 | //$c->display($this->controlTemplate); |
||
625 | $writer->write($c->fetch($this->controlTemplate)); |
||
626 | $writer->close(); |
||
627 | } catch (IOException $ioe) { |
||
628 | $writer->close(); |
||
629 | throw new BuildException("Cannot write parsed template."); |
||
630 | } |
||
631 | |||
632 | $this->cleanup(); |
||
633 | } |
||
634 | |||
635 | /** |
||
636 | * <p>Place useful objects into the initial context.</p> |
||
637 | * |
||
638 | * <p>TexenTask places <code>Date().toString()</code> into the |
||
639 | * context as <code>$now</code>. Subclasses who want to vary the |
||
640 | * objects in the context should override this method.</p> |
||
641 | * |
||
642 | * <p><code>$generator</code> is not put into the context in this |
||
643 | * method.</p> |
||
644 | * |
||
645 | * @param Smarty $context context to populate, as retrieved from |
||
646 | * {@link #initControlContext()}. |
||
647 | * @return void |
||
648 | */ |
||
649 | protected function populateInitialContext(Smarty $context) |
||
651 | } |
||
652 | |||
653 | /** |
||
654 | * A hook method called at the end of {@link #execute()} which can |
||
655 | * be overridden to perform any necessary cleanup activities (such |
||
656 | * as the release of database connections, etc.). By default, |
||
657 | * does nothing. |
||
658 | * |
||
659 | * @return void |
||
660 | * @throws \Exception Problem cleaning up. |
||
661 | */ |
||
662 | protected function cleanup() |
||
664 | } |
||
665 | } |
||
666 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.