Complex classes like PH7Tpl 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 PH7Tpl, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
34 | class PH7Tpl extends Kernel implements Templatable, GenerableFile |
||
35 | { |
||
36 | const NAME = 'PH7Tpl'; |
||
37 | const AUTHOR = 'Pierre-Henry Soria'; |
||
38 | const VERSION = '1.3.0'; |
||
39 | const LICENSE = 'Creative Commons Attribution 3.0 License - http://creativecommons.org/licenses/by/3.0/'; |
||
40 | const ERR_MSG = 'It seems you have removed the copyright notice(s) in the software. If you really want to remove them, please email: %s'; |
||
41 | const DATETIME_FORMAT = 'Y-m-d H:i:s'; |
||
42 | |||
43 | /** |
||
44 | * @internal For better compatibility with Windows, we didn't put a slash at the end of the directory constants. |
||
45 | */ |
||
46 | const COMPILE_DIR = 'pH7tpl_compile'; |
||
47 | const CACHE_DIR = 'pH7tpl_cache'; |
||
48 | const MAIN_COMPILE_DIR = 'public_main'; |
||
49 | |||
50 | const MAIN_PAGE = 'layout'; |
||
51 | const MAIN_COMPILE_PAGE = 'layout.cpl.php'; |
||
52 | const XML_SITEMAP_COMPILE_PAGE = 'mainlayout.xsl.cpl.php'; |
||
53 | const TEMPLATE_FILE_EXT = '.tpl'; |
||
54 | const COMPILE_FILE_EXT = '.cpl.php'; |
||
55 | const CACHE_FILE_EXT = '.cache.html'; |
||
56 | |||
57 | const RESERVED_WORDS = [ |
||
58 | 'auto_include', |
||
59 | 'def_main_auto_include', |
||
60 | 'else', |
||
61 | 'literal', |
||
62 | 'lang' |
||
63 | ]; |
||
64 | |||
65 | /** @var DesignModel */ |
||
66 | private $designModel; |
||
67 | |||
68 | /** @var Syntax */ |
||
69 | private $oSyntaxEngine; |
||
70 | |||
71 | /** @var string */ |
||
72 | private $sTplFile; |
||
73 | |||
74 | /** @var string */ |
||
75 | private $sTemplateDir; |
||
76 | |||
77 | /** @var string */ |
||
78 | private $sCompileDir; |
||
79 | |||
80 | /** @var string */ |
||
81 | private $sCompileDir2; |
||
82 | |||
83 | /** @var string */ |
||
84 | private $sCacheDir; |
||
85 | |||
86 | /** @var string */ |
||
87 | private $sCacheDir2; |
||
88 | |||
89 | /** @var string */ |
||
90 | private $sCode; |
||
91 | |||
92 | /** @var string */ |
||
93 | private $sTemplateDirFile; |
||
94 | |||
95 | /** @var string */ |
||
96 | private $sCompileDirFile; |
||
97 | |||
98 | /** @var string */ |
||
99 | private $sCacheDirFile; |
||
100 | |||
101 | /** @var bool */ |
||
102 | private $bCaching = false; |
||
103 | |||
104 | /** @var bool */ |
||
105 | private $bHtmlCompressor; |
||
106 | |||
107 | /** @var bool */ |
||
108 | private $bPhpCompressor; |
||
109 | |||
110 | /** @var int|null */ |
||
111 | private $mCacheExpire; |
||
112 | |||
113 | /** @var array */ |
||
114 | private $_aVars = []; |
||
115 | |||
116 | /** @var PH7Tpl */ |
||
117 | private $_oVars; |
||
118 | |||
119 | // Hack that keeps the $config variable in the template files |
||
120 | protected $config; |
||
121 | |||
122 | public function __construct(Syntax $oSyntaxEngine) |
||
123 | { |
||
124 | parent::__construct(); |
||
125 | |||
126 | $this->checkCompileDir(); |
||
127 | $this->checkCacheDir(); |
||
128 | |||
129 | /** Instance objects to the class **/ |
||
130 | $this->_oVars = $this; |
||
131 | $this->designModel = new DesignModel; |
||
132 | $this->oSyntaxEngine = new $oSyntaxEngine; |
||
133 | |||
134 | $this->bHtmlCompressor = (bool)$this->config->values['cache']['enable.static.minify']; |
||
135 | $this->bPhpCompressor = (bool)$this->config->values['cache']['enable.static.minify']; |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Get the main page file of the template. |
||
140 | * |
||
141 | * @return string The main page file. |
||
142 | */ |
||
143 | public function getMainPage() |
||
144 | { |
||
145 | return static::MAIN_PAGE . static::TEMPLATE_FILE_EXT; |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Set the directory for the template. |
||
150 | * |
||
151 | * @param string $sDir |
||
152 | * |
||
153 | * @return void |
||
154 | * |
||
155 | * @throws PH7InvalidArgumentException An explanatory message if the directory does not exist. |
||
156 | */ |
||
157 | public function setTemplateDir($sDir) |
||
158 | { |
||
159 | if (is_dir($sDir)) { |
||
160 | $this->sTemplateDir = $this->file->checkExtDir($sDir); |
||
161 | } else { |
||
162 | throw new PH7InvalidArgumentException( |
||
163 | sprintf('<strong>%s</strong> cannot find "%s" template directory.', self::NAME, $sDir) |
||
164 | ); |
||
165 | } |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Set the directory for the compilation template. |
||
170 | * |
||
171 | * @param string $sDir |
||
172 | * |
||
173 | * @return void |
||
174 | * |
||
175 | * @throws PH7InvalidArgumentException An explanatory message if the directory does not exist. |
||
176 | */ |
||
177 | public function setCompileDir($sDir) |
||
178 | { |
||
179 | if (is_dir($sDir)) { |
||
180 | $this->sCompileDir = $this->file->checkExtDir($sDir); |
||
181 | } else { |
||
182 | throw new PH7InvalidArgumentException( |
||
183 | sprintf( |
||
184 | '<strong>%s</strong> cannot find "%s" compile directory.', self::NAME, $sDir) |
||
185 | ); |
||
186 | } |
||
187 | } |
||
188 | |||
189 | /** |
||
190 | * Set the directory for the cache template. |
||
191 | * |
||
192 | * @param string $sDir |
||
193 | * |
||
194 | * @return void |
||
195 | * |
||
196 | * @throws PH7InvalidArgumentException An explanatory message if the directory does not exist. |
||
197 | */ |
||
198 | public function setCacheDir($sDir) |
||
199 | { |
||
200 | if (is_dir($sDir)) { |
||
201 | $this->sCacheDir = $this->file->checkExtDir($sDir); |
||
202 | } else { |
||
203 | throw new PH7InvalidArgumentException( |
||
204 | sprintf('<strong>%s</strong> cannot find "%s" cache directory.', self::NAME, $sDir) |
||
205 | ); |
||
206 | } |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * Enabled the cache. |
||
211 | * |
||
212 | * @param bool $bCaching |
||
213 | * |
||
214 | * @return void |
||
215 | */ |
||
216 | public function setCaching($bCaching) |
||
217 | { |
||
218 | $this->bCaching = (bool)$bCaching; |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * Check if the cache is enabled. |
||
223 | * |
||
224 | * @return bool |
||
225 | */ |
||
226 | public function isEnableCache() |
||
227 | { |
||
228 | return $this->bCaching; |
||
229 | } |
||
230 | |||
231 | /** |
||
232 | * Set the HTML Compressor. |
||
233 | * |
||
234 | * @param bool $bCompressor |
||
235 | * |
||
236 | * @return void |
||
237 | */ |
||
238 | public function setHtmlCompress($bCompressor) |
||
239 | { |
||
240 | $this->bHtmlCompressor = (bool)$bCompressor; |
||
241 | } |
||
242 | |||
243 | /** |
||
244 | * Set the PHP Compressor. |
||
245 | * |
||
246 | * @param bool $bCompressor |
||
247 | * |
||
248 | * @return void |
||
249 | */ |
||
250 | public function setPhpCompress($bCompressor) |
||
251 | { |
||
252 | $this->bPhpCompressor = (bool)$bCompressor; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * Set the time of expire cache. |
||
257 | * |
||
258 | * @param int $iLifeTime In seconds. |
||
259 | * |
||
260 | * @return void |
||
261 | */ |
||
262 | public function setCacheExpire($iLifeTime) |
||
263 | { |
||
264 | $this->mCacheExpire = (int)$iLifeTime; // 3600 seconds = 1 hour cache duration |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Adds a variable that can be used by the templates. |
||
269 | * Adds a new array index to the variable property. This |
||
270 | * new array index will be treated as a variable by the templates. |
||
271 | * |
||
272 | * @see pH7Tpl::assign() |
||
273 | * |
||
274 | * @param string $sName The variable name to use in the template |
||
275 | * @param mixed $mValue (string, object, array, integer, ...) Value Variable |
||
276 | * |
||
277 | * @return void |
||
278 | */ |
||
279 | public function __set($sName, $mValue) |
||
280 | { |
||
281 | $this->assign($sName, $mValue); |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * Retrieve an assigned variable (overload the magic __get method). |
||
286 | * |
||
287 | * @see pH7Tpl::getVar() |
||
288 | * |
||
289 | * @param string $sKey The variable name. |
||
290 | * |
||
291 | * @return mixed The variable value. |
||
292 | */ |
||
293 | public function __get($sKey) |
||
294 | { |
||
295 | return $this->getVar($sKey); |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * Allows testing with empty() and isset() to work. |
||
300 | * |
||
301 | * @param string $sKey |
||
302 | * |
||
303 | * @return bool |
||
304 | */ |
||
305 | public function __isset($sKey) |
||
306 | { |
||
307 | return isset($this->_aVars[$sKey]); |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * @param string $sTplFile Default NULL |
||
312 | * @param string $sDirPath Default NULL |
||
313 | * @param bool $bInclude Default TRUE |
||
314 | * |
||
315 | * @return string |
||
316 | * |
||
317 | * @throws TplException If the template file does no exist. |
||
318 | * @throws PH7InvalidArgumentException |
||
319 | */ |
||
320 | public function display($sTplFile = null, $sDirPath = null, $bInclude = true) |
||
321 | { |
||
322 | $this->sTplFile = $sTplFile; |
||
323 | |||
324 | if (!empty($sDirPath)) { |
||
325 | $this->setTemplateDir($sDirPath); |
||
326 | } |
||
327 | |||
328 | $this->sTemplateDirFile = $this->sTemplateDir . 'tpl' . PH7_DS . $this->sTplFile; |
||
329 | |||
330 | $this->file->createDir($this->sCompileDir); |
||
331 | |||
332 | if ($this->isMainDir($sDirPath)) { |
||
333 | $this->sCompileDir2 = $this->sCompileDir . static::MAIN_COMPILE_DIR . PH7_DS . PH7_TPL_NAME . PH7_DS; |
||
334 | } else { |
||
335 | $this->sCompileDir2 = $this->sCompileDir . $this->registry->module . '_' . md5($this->registry->path_module) . PH7_DS . PH7_TPL_MOD_NAME . PH7_DS . $this->getCurrentController(); |
||
336 | } |
||
337 | |||
338 | $this->sCompileDirFile = ($this->isMainDir($sDirPath) ? $this->sCompileDir2 . $this->file->getFileWithoutExt($this->sTplFile) . static::COMPILE_FILE_EXT : $this->sCompileDir2) . |
||
339 | str_replace($this->getCurrentController(), '', $this->file->getFileWithoutExt($this->sTplFile)) . static::COMPILE_FILE_EXT; |
||
340 | |||
341 | if (!$this->file->existFile($this->sTemplateDirFile)) { |
||
342 | throw new TplException( |
||
343 | sprintf('%s file does no exist.', $this->sTemplateDirFile) |
||
344 | ); |
||
345 | } |
||
346 | |||
347 | |||
348 | /*** If the file does not exist or if the template has been modified, recompile the makefiles ***/ |
||
349 | if ($this->file->getModifTime($this->sTemplateDirFile) > $this->file->getModifTime($this->sCompileDirFile)) { |
||
350 | $this->compile(); |
||
351 | } |
||
352 | |||
353 | if ($bInclude) { |
||
354 | $bCaching = (bool)$this->config->values['cache']['enable.html.tpl.cache']; |
||
355 | |||
356 | if ($bCaching === true && $this->isEnableCache() === true && !$this->isMainCompilePage()) { |
||
357 | $this->cache(); |
||
358 | } else { |
||
359 | // Extraction Variables |
||
360 | extract($this->_aVars); |
||
361 | require $this->sCompileDirFile; |
||
362 | } |
||
363 | } else { |
||
364 | return $this->sCompileDirFile; |
||
365 | } |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Parse an email template. |
||
370 | * |
||
371 | * @param string $sMailTplFile |
||
372 | * @param string $sEmailAddress It is used to create the privacy policy for lute against spam. |
||
373 | * |
||
374 | * @return string The contents of the template parsed. |
||
375 | * |
||
376 | * @throws TplException If the template file could not be opened. |
||
377 | */ |
||
378 | public function parseMail($sMailTplFile, $sEmailAddress) |
||
379 | { |
||
380 | /** |
||
381 | * If the template doesn't contain theme for emails, we retrieve the emails default themes. |
||
382 | */ |
||
383 | if (!is_file($sMailTplFile) && defined('PH7_TPL_NAME')) { |
||
384 | $sMailTplFile = str_replace(PH7_TPL_NAME, PH7_DEFAULT_THEME, $sMailTplFile); |
||
385 | } |
||
386 | |||
387 | if (!$sCode = $this->file->getFile($sMailTplFile)) { |
||
388 | throw new TplException( |
||
389 | sprintf('Cannot open "%s" file.', $sMailTplFile) |
||
390 | ); |
||
391 | } |
||
392 | |||
393 | /***** Other variables in file "/framework/Parse/SysVar.class.php" with syntax %var% *****/ |
||
394 | $sCode = (new SysVar)->parse($sCode); |
||
395 | |||
396 | foreach ($this->_aVars as $sKey => $sValue) { |
||
397 | /*** Variables ***/ |
||
398 | |||
399 | // We can't convert an object to a string with str_replace, which we tested the variables with is_object function |
||
400 | if (!is_object($sValue)) { |
||
401 | $sCode = str_replace('{' . $sKey . '}', $sValue, $sCode); |
||
402 | } |
||
403 | |||
404 | // Email Address |
||
405 | //$sCode = str_replace('{email}', $sEmailAddress, $sCode); |
||
406 | |||
407 | $oMailDesign = new MailLayout; |
||
408 | |||
409 | /* Headers */ |
||
410 | |||
411 | // Includes |
||
412 | $sCode = str_replace('{inc_header}', $oMailDesign->header(), $sCode); |
||
413 | $sCode = str_replace('{inc_sub_header}', $oMailDesign->subHeader(), $sCode); |
||
414 | |||
415 | /* Footers */ |
||
416 | |||
417 | // Privacy Policy Footer |
||
418 | $sCode = str_replace('{pp_footer}', $oMailDesign->privacyPolicyFooter($sEmailAddress), $sCode); |
||
419 | |||
420 | // Bottom Footer |
||
421 | $sCode = str_replace('{b_footer}', $oMailDesign->bottomFooter(), $sCode); |
||
422 | |||
423 | // Includes |
||
424 | $sCode = str_replace('{inc_sub_footer}', $oMailDesign->subFooter($sEmailAddress), $sCode); |
||
425 | $sCode = str_replace('{inc_footer}', $oMailDesign->footer(), $sCode); |
||
426 | unset($oMailDesign); |
||
427 | } |
||
428 | |||
429 | return $sCode; |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * Assign variables to the template. |
||
434 | * |
||
435 | * |
||
436 | * @example |
||
437 | * |
||
438 | * Example with a string variable: |
||
439 | * |
||
440 | * <code> |
||
441 | * === PHP === |
||
442 | * $oPh7Tpl->assign('var_name', $sName); |
||
443 | * |
||
444 | * === TPL === |
||
445 | * {var_name} |
||
446 | * </code> |
||
447 | * |
||
448 | * |
||
449 | * Example with an array variable: |
||
450 | * |
||
451 | * <code> |
||
452 | * === PHP === |
||
453 | * $oPh7Tpl->assign('arr_data_var', $aData); |
||
454 | * |
||
455 | * === TPL === |
||
456 | * {% $arr_data_var['key1'] %} |
||
457 | * </code> |
||
458 | * |
||
459 | * |
||
460 | * Example with an object variable: |
||
461 | * |
||
462 | * <code> |
||
463 | * === PHP === |
||
464 | * $oPh7Tpl->assign('obj_user_var', $oUser); |
||
465 | * |
||
466 | * === TPL === |
||
467 | * {% $obj_user_var->getUsers() %} |
||
468 | * --- OR --- |
||
469 | * {{ $obj_user_var->printUsers() }} |
||
470 | * </code> |
||
471 | * |
||
472 | * |
||
473 | * @see __set() |
||
474 | * |
||
475 | * @param string $sName Variable name |
||
476 | * @param mixed $mValue (string, object, array, integer, ...) Value Variable |
||
477 | * @param bool $bEscape Specify "true" if you want to protect your variables against XSS. |
||
478 | * @param bool $bEscapeStrip If you use escape method, you can also set this parameter to "true" to strip HTML and PHP tags from a string. |
||
479 | * |
||
480 | * @return void |
||
481 | */ |
||
482 | public function assign($sName, $mValue, $bEscape = false, $bEscapeStrip = false) |
||
483 | { |
||
484 | if ($bEscape === true) { |
||
485 | $mValue = $this->str->escape($mValue, $bEscapeStrip); |
||
486 | } |
||
487 | |||
488 | $this->_aVars[$sName] = $mValue; |
||
489 | } |
||
490 | |||
491 | /** |
||
492 | * Assign variables from array. |
||
493 | * |
||
494 | * @see assign() |
||
495 | * |
||
496 | * @param array $aVars |
||
497 | * @param bool $bEscape Specify TRUE if you want to protect your variables against XSS. |
||
498 | * @param bool $bEscapeStrip If you use escape method, you can also set this parameter to "true" to strip HTML and PHP tags from a string. |
||
499 | * |
||
500 | * @return void |
||
501 | */ |
||
502 | public function assigns(array $aVars, $bEscape = false, $bEscapeStrip = false) |
||
503 | { |
||
504 | foreach ($aVars as $sKey => $sValue) { |
||
505 | $this->assign($sKey, $sValue, $bEscape, $bEscapeStrip); // Assign a string variable |
||
506 | } |
||
507 | } |
||
508 | |||
509 | /** |
||
510 | * Get a variable we assigned with the assign() method. |
||
511 | * |
||
512 | * @see __get() |
||
513 | * |
||
514 | * @param $sVarName string Name of a variable that is to be retrieved. |
||
515 | * |
||
516 | * @return mixed Value of that variable. |
||
517 | */ |
||
518 | public function getVar($sVarName) |
||
519 | { |
||
520 | return isset($this->_aVars[$sVarName]) ? $this->_aVars[$sVarName] : ''; |
||
521 | } |
||
522 | |||
523 | /** |
||
524 | * Remove all variables from memory template. |
||
525 | * |
||
526 | * @return void |
||
527 | */ |
||
528 | public function clean() |
||
529 | { |
||
530 | unset($this->_aVars, $this->_oVars); |
||
531 | } |
||
532 | |||
533 | /** |
||
534 | * Get the reserved variables. |
||
535 | * |
||
536 | * @return array |
||
537 | */ |
||
538 | public function getReservedWords() |
||
539 | { |
||
540 | return self::RESERVED_WORDS; |
||
541 | } |
||
542 | |||
543 | /** |
||
544 | * Get the header content to put in the file. |
||
545 | * |
||
546 | * @return string |
||
547 | */ |
||
548 | final public function getHeaderContents() |
||
549 | { |
||
550 | return ' |
||
551 | namespace PH7; |
||
552 | defined(\'PH7\') or exit(\'Restricted access\'); |
||
553 | /* |
||
554 | Created on ' . gmdate(self::DATETIME_FORMAT) . ' |
||
555 | Compiled file from: ' . $this->sTemplateDirFile . ' |
||
556 | Template Engine: ' . self::NAME . ' version ' . self::VERSION . ' by ' . self::AUTHOR . ' |
||
557 | */ |
||
558 | /*************************************************************************** |
||
559 | * ' . self::SOFTWARE_NAME . ' ' . self::SOFTWARE_COMPANY . ' |
||
560 | * -------------------- |
||
561 | * @since Mon Mar 21 2011 |
||
562 | * @author SORIA Pierre-Henry |
||
563 | * @email ' . self::SOFTWARE_EMAIL . ' |
||
564 | * @link ' . self::SOFTWARE_WEBSITE . ' |
||
565 | * @copyright ' . sprintf(self::SOFTWARE_COPYRIGHT, date('Y')) . ' |
||
566 | * @license ' . self::LICENSE . ' |
||
567 | ***************************************************************************/ |
||
568 | '; |
||
569 | } |
||
570 | |||
571 | /** |
||
572 | * Set self pointer on cloned object. |
||
573 | * |
||
574 | * @clone |
||
575 | */ |
||
576 | public function __clone() |
||
577 | { |
||
578 | $this->_oVars = $this; |
||
579 | } |
||
580 | |||
581 | /** |
||
582 | * Cache system for the static contents with support for different templates and languages! |
||
583 | * |
||
584 | * @return void |
||
585 | * |
||
586 | * @throws Exception |
||
587 | * @throws \PH7\Framework\File\Permission\PermissionException |
||
588 | * @throws TplException If the cache file could not be written. |
||
589 | */ |
||
590 | protected function cache() |
||
591 | { |
||
592 | // Create cache folder |
||
593 | $this->file->createDir($this->sCacheDir); |
||
594 | |||
595 | $this->sCacheDir2 = $this->sCacheDir . PH7_TPL_NAME . PH7_DS . $this->registry->module . '_' . md5($this-> |
||
596 | registry->path_module) . PH7_DS . PH7_TPL_MOD_NAME . PH7_DS . PH7_LANG_NAME . PH7_DS . $this->getCurrentController() . PH7_DS; |
||
597 | $this->file->createDir($this->sCacheDir2); |
||
598 | $this->sCacheDirFile = $this->sCacheDir2 . str_replace(PH7_DS, '_', $this->file->getFileWithoutExt($this->sTplFile)) . static::CACHE_FILE_EXT; |
||
599 | |||
600 | if ($this->hasCacheExpired()) { |
||
601 | ob_start(); |
||
602 | |||
603 | // Extraction Variables |
||
604 | extract($this->_aVars); |
||
605 | |||
606 | require $this->sCompileDirFile; |
||
607 | $sOutput = ob_get_contents(); |
||
608 | ob_end_clean(); |
||
609 | |||
610 | if ($this->bHtmlCompressor) { |
||
611 | $sOutput = (new Compress)->parseHtml($sOutput); |
||
612 | } |
||
613 | |||
614 | if (!$this->file->putFile($this->sCacheDirFile, $sOutput)) { |
||
615 | throw new TplException( |
||
616 | sprintf('Unable to write HTML cached file "%s"', $this->sCacheDirFile) |
||
617 | ); |
||
618 | } |
||
619 | |||
620 | echo $sOutput; |
||
621 | } else { |
||
622 | readfile($this->sCacheDirFile); |
||
623 | } |
||
624 | } |
||
625 | |||
626 | /** |
||
627 | * Optimizes the code generated by pH7Tpl syntax parser. |
||
628 | * |
||
629 | * @return void |
||
630 | */ |
||
631 | protected function optimizeCode() |
||
632 | { |
||
633 | $this->sCode = preg_replace(['#[\t\r\n];?\?>#s', '#\?>[\t\r\n]+?<\?(php)?#si'], '', $this->sCode); |
||
634 | $this->sCode = preg_replace('#;{2,}#s', ';', $this->sCode); |
||
635 | } |
||
636 | |||
637 | /** |
||
638 | * Get current pH7CMS's controller. |
||
639 | * |
||
640 | * @return string The current controller |
||
641 | */ |
||
642 | protected function getCurrentController() |
||
643 | { |
||
644 | return $this->httpRequest->currentController(); |
||
645 | } |
||
646 | |||
647 | /** |
||
648 | * Compiler template. |
||
649 | * |
||
650 | * @return bool |
||
651 | * |
||
652 | * @throws TplException If the template file could not be recovered or cannot be written. |
||
653 | */ |
||
654 | final private function compile() |
||
655 | { |
||
656 | // Create compile folder |
||
657 | $this->file->createDir($this->sCompileDir2); |
||
658 | |||
659 | if (!$this->sCode = $this->file->getFile($this->sTemplateDirFile)) { |
||
660 | throw new TplException( |
||
661 | sprintf('Impossible to fetch template file "%s"', $this->sTemplateDirFile) |
||
662 | ); |
||
663 | } |
||
664 | |||
665 | // Parser the predefined variables |
||
666 | $this->sCode = (new Predefined\Variable($this->sCode))->assign()->get(); |
||
667 | |||
668 | // Parser the predefined template functions |
||
669 | $this->sCode = (new Predefined\Func($this->sCode))->assign()->get(); |
||
670 | |||
671 | // Parser the language constructs |
||
672 | $this->parse(); |
||
673 | |||
674 | $sPhpHeader = $this->getHeaderContents(); |
||
675 | |||
676 | // Check if the "$design" variable is actually part of the \PH7\Framework\Layout\Html\Design class |
||
677 | if (!$this->checkDesignInstance()) { |
||
678 | $this->setErrMsg(); |
||
679 | } |
||
680 | |||
681 | /** |
||
682 | * Skip this step if it's not layout.tpl file or if it's not the base template |
||
683 | * (because there isn't "link()" in layout.tpl of other templates as it includes the "base" one). |
||
684 | */ |
||
685 | if ($this->isMainCompilePage() && !$this->notBaseTheme()) { |
||
686 | // It is forbidden to violate the copyright! |
||
687 | // Think to me, who has spent years to develop a professional, high-quality software and done my best to help other developers! |
||
688 | if (!$this->isMarkCopyright()) { |
||
689 | $this->setErrMsg(); |
||
690 | } |
||
691 | } |
||
692 | |||
693 | if ($this->isXmlSitemapCompilePage() && !$this->isSmallMarkCopyright()) { |
||
694 | $this->setErrMsg(); |
||
695 | } |
||
696 | |||
697 | if ($this->bPhpCompressor) { |
||
698 | $this->sCode = (new Compress)->parsePhp($this->sCode); |
||
699 | } |
||
700 | |||
701 | $this->sCode = '<?php ' . $sPhpHeader . '?>' . $this->sCode; |
||
702 | |||
703 | if ($rHandle = @fopen($this->sCompileDirFile, 'wb')) { |
||
704 | fwrite($rHandle, $this->sCode); |
||
705 | fclose($rHandle); |
||
706 | return true; |
||
707 | } |
||
708 | |||
709 | throw new TplException( |
||
710 | sprintf('Could not write template compiled file "%s"', $this->sCompileDirFile) |
||
711 | ); |
||
712 | } |
||
713 | |||
714 | /** |
||
715 | * Parse the template syntax code for translating the language template to PHP. |
||
716 | * |
||
717 | * @return void |
||
718 | */ |
||
719 | private function parse() |
||
720 | { |
||
721 | $this->oSyntaxEngine->setCode($this->sCode); |
||
722 | $this->oSyntaxEngine->setShortcutsToObjects(); |
||
723 | |||
724 | /***** Parse pH7Tpl's syntax *****/ |
||
725 | $this->oSyntaxEngine->setTemplateFile($this->sTplFile); |
||
726 | $this->oSyntaxEngine->parse(); |
||
727 | |||
728 | $this->sCode = $this->oSyntaxEngine->getParsedCode(); |
||
729 | |||
730 | /***** Code optimization *****/ |
||
731 | $this->optimizeCode(); |
||
732 | } |
||
733 | |||
734 | /** |
||
735 | * Checks if the template file in the $this->sTemplateDirFile attribute is the main page (layout.tpl). |
||
736 | * |
||
737 | * @return bool |
||
738 | */ |
||
739 | private function isMainPage() |
||
740 | { |
||
741 | return preg_match('#' . $this->addSlashes(PH7_PATH_TPL . PH7_TPL_NAME . PH7_DS . $this->getMainPage()) . '#', $this->sTemplateDirFile); |
||
742 | } |
||
743 | |||
744 | /** |
||
745 | * Checks if the compile file in the $this->sCompileDirFile attribute is the main page (layout.cpl.php). |
||
746 | * |
||
747 | * @return bool |
||
748 | */ |
||
749 | final private function isMainCompilePage() |
||
750 | { |
||
751 | return preg_match( |
||
752 | '#' . $this->addSlashes($this->sCompileDir . static::MAIN_COMPILE_DIR . PH7_DS . PH7_TPL_NAME . PH7_DS . static::MAIN_COMPILE_PAGE) . '#', |
||
753 | $this->sCompileDirFile |
||
754 | ); |
||
755 | } |
||
756 | |||
757 | /** |
||
758 | * Checks if the compile file in the $this->sCompileDirFile attribute is the XML (with XSL layout) Sitemap page (mainlayout.xsl.cpl.php). |
||
759 | * |
||
760 | * @return bool |
||
761 | */ |
||
762 | final private function isXmlSitemapCompilePage() |
||
763 | { |
||
764 | return preg_match('#' . static::XML_SITEMAP_COMPILE_PAGE . '#', $this->sCompileDirFile); |
||
765 | } |
||
766 | |||
767 | /** |
||
768 | * Checks if the directory passed by the argument of the method is the main directory. |
||
769 | * |
||
770 | * @param string $sDirPath |
||
771 | * |
||
772 | * @return bool |
||
773 | */ |
||
774 | final private function isMainDir($sDirPath) |
||
775 | { |
||
776 | return !empty($sDirPath) && preg_match('#' . $this->addSlashes(PH7_PATH_TPL . PH7_TPL_NAME . PH7_DS) . '#', $sDirPath); |
||
777 | } |
||
778 | |||
779 | /** |
||
780 | * Check that the variable "$design" is actually parts of the Design class. |
||
781 | * |
||
782 | * @return bool |
||
783 | */ |
||
784 | final private function checkDesignInstance() |
||
785 | { |
||
786 | return !empty($this->_aVars['design']) && $this->_aVars['design'] instanceof Design; |
||
787 | } |
||
788 | |||
789 | /** |
||
790 | * Checks if the marks licensing, copyright has not been removed. |
||
791 | * |
||
792 | * @return bool |
||
793 | */ |
||
794 | final private function isMarkCopyright() |
||
795 | { |
||
796 | // "link()" and "softwareComment()" can never be removed |
||
797 | return $this->isKeywordFoundInCode('design->link()') && |
||
798 | $this->isKeywordFoundInCode('design->softwareComment()'); |
||
799 | } |
||
800 | |||
801 | /** |
||
802 | * Checks if the small links copyright has not been removed. |
||
803 | * |
||
804 | * @return bool |
||
805 | */ |
||
806 | final private function isSmallMarkCopyright() |
||
807 | { |
||
808 | return $this->isKeywordFoundInCode('design->smallLink()'); |
||
809 | } |
||
810 | |||
811 | /** |
||
812 | * Check if it's not the base theme. |
||
813 | * |
||
814 | * @return bool Returns TRUE if it's not the base theme, FALSE otherwise. |
||
815 | */ |
||
816 | final private function notBaseTheme() |
||
817 | { |
||
818 | return strpos($this->sTemplateDir, PH7_PATH_TPL . PH7_DEFAULT_THEME . PH7_DS) === false && |
||
819 | $this->isKeywordFoundInCode('$this->display(\'' . $this->getMainPage() . '\', PH7_PATH_TPL . PH7_DEFAULT_THEME . PH7_DS)'); |
||
820 | } |
||
821 | |||
822 | /** |
||
823 | * @return bool Returns TRUE if the cache has expired, FALSE otherwise. |
||
824 | */ |
||
825 | private function hasCacheExpired() |
||
826 | { |
||
827 | return |
||
828 | $this->file->getModifTime($this->sCompileDirFile) > $this->file->getModifTime($this->sCacheDirFile) || |
||
829 | (!empty($this->mCacheExpire) && $this->file->getModifTime($this->sCacheDirFile) < time() - $this->mCacheExpire); |
||
830 | } |
||
831 | |||
832 | /** |
||
833 | * Add slashes to avoid errors with "preg_replace()" with Windows' backslashes in directories. |
||
834 | * |
||
835 | * @param string $sStr |
||
836 | * |
||
837 | * @return string Escaped string |
||
838 | */ |
||
839 | private function addSlashes($sStr) |
||
843 | |||
844 | /** |
||
845 | * Checks if the compile directory has been defined otherwise we create a default directory. |
||
846 | * |
||
847 | * If the folder compile does not exist, it creates a folder. |
||
848 | * |
||
849 | * @return self |
||
850 | */ |
||
851 | private function checkCompileDir() |
||
857 | |||
858 | /** |
||
859 | * Checks if the cache directory has been defined otherwise we create a default directory. |
||
860 | * If the folder cache does not exist, it creates a folder. |
||
861 | * |
||
862 | * @return self |
||
863 | */ |
||
864 | private function checkCacheDir() |
||
870 | |||
871 | /** |
||
872 | * @param string $sKeyword |
||
873 | * |
||
874 | * @return bool |
||
875 | */ |
||
876 | private function isKeywordFoundInCode($sKeyword) |
||
877 | { |
||
878 | return strpos($this->sCode, $sKeyword) !== false; |
||
879 | } |
||
880 | |||
881 | /** |
||
882 | * Set the error message. |
||
883 | * |
||
884 | * @return void |
||
885 | */ |
||
886 | final private function setErrMsg() |
||
887 | { |
||
888 | $this->sCode = sprintf(static::ERR_MSG, self::SOFTWARE_EMAIL); |
||
889 | } |
||
890 | |||
891 | public function __destruct() |
||
892 | { |
||
893 | $this->clean(); |
||
894 | } |
||
895 | } |
||
896 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.