Exponential 6.0.13 Exponential Enterprise Open Source CMS - PHP Class Reference

ezcodetemplate.php
Go to the documentation of this file.
1 <?php
17 class eZCodeTemplate
18 {
20 const STATUS_FAILED = 0;
21
23 const STATUS_OK = 1;
24
26 const STATUS_NO_CHANGE = 2;
27
31 public function __construct()
32 {
33 $ini = eZINI::instance( 'codetemplate.ini' );
34 $this->Templates = array();
35 $templates = $ini->variable( 'Files', 'Templates' );
36 foreach ( $templates as $key => $template )
37 {
38 $this->Templates[$key] = array( 'filepath' => $template );
39 }
40
41 // The default limit has to be increased to avoid PREG_BACKTRACK_LIMIT_ERROR
42 // when calling preg_*() functions.
43 ini_set( "pcre.backtrack_limit", 1e6);
44 }
45
54 function apply( $filePath, $checkOnly = false )
55 {
56 if ( !file_exists( $filePath ) )
57 {
58 eZDebug::writeError( "File $filePath does not exist", __METHOD__ );
59 return self::STATUS_FAILED;
60 }
61
62 $text = file_get_contents( $filePath );
63 $tempFile = dirname( $filePath ) . '/#' . basename( $filePath ) . '#';
64 $fd = fopen( $tempFile, 'wb' );
65 if ( !$fd )
66 {
67 eZDebug::writeError( "Failed to open temporary file $tempFile", __METHOD__ );
68 return self::STATUS_FAILED;
69 }
70
71 $createTag = 'code-template::create-block:';
72 $createTagLen = strlen( $createTag );
73
74 $error = false;
75
76 $ok = true;
77 $offset = 0;
78 $len = strlen( $text );
79 while ( $offset < $len )
80 {
81 $createPos = strpos( $text, $createTag, $offset );
82 if ( $createPos !== false )
83 {
84 $endPos = strpos( $text, "\n", $createPos + $createTagLen );
85 if ( $endPos === false )
86 {
87 $createText = substr( $text, $createPos + $createTagLen );
88 $end = $len;
89 }
90 else
91 {
92 $start = $createPos + $createTagLen;
93 $createText = substr( $text, $start, $endPos - $start );
94 $end = $endPos + 1;
95 }
96
97 // Figure out how much the comments should be indented
98 // This just makes the code seem more natural
99 $indentText = '';
100 $subText = substr( $text, $offset, $createPos - $offset );
101 $startOfLine = strrpos( $subText, "\n" );
102 if ( $startOfLine !== false )
103 {
104 if ( preg_match( '#^([ \t]+)#', substr( $subText, $startOfLine + 1 ), $matches ) )
105 {
106 $indentText = $matches[1];
107 }
108 }
109 unset( $subText );
110
111 // Figure out template name and parameters
112 $createText = trim( $createText );
113 $elements = explode( ',', $createText );
114 if ( count( $elements ) < 1 )
115 {
116 eZDebug::writeError( "No template name found in file $filePath at offset $offset", __METHOD__ );
117 $offset = $end;
118 $error = true;
119 continue;
120 }
121
122 $templateName = trim( $elements[0] );
123
124 $templateFile = $this->templateFile( $templateName );
125 if ( $templateFile === false )
126 {
127 eZDebug::writeError( "No template file for template $templateName used in file $filePath at offset $offset", __METHOD__ );
128 $offset = $end;
129 $error = true;
130 continue;
131 }
132
133 if ( !file_exists( $templateFile ) )
134 {
135 eZDebug::writeError( "Template file $templateFile for template $templateName does not exist", __METHOD__ );
136 $offset = $end;
137 $error = true;
138 continue;
139 }
140
141 $parameters = array_splice( $elements, 1 );
142 foreach ( $parameters as $key => $parameter )
143 {
144 $parameters[$key] = trim( $parameter );
145 }
146
147 if ( !file_exists( $templateFile ) )
148 {
149 eZDebug::writeError( "Template file $templateFile was not found while workin on $filePath at offset $offset", __METHOD__ );
150 $offset = $end;
151 $error = true;
152 continue;
153 }
154
155 // Load the template file and split it into the blocks
156 // available blocks in the file
157 $templateText = file_get_contents( $templateFile );
158
159 $tagSplit = '#((?:<|/\*)(?:START|END):code-template::(?:[a-zA-Z]+[a-zA-Z0-9_|&-]*)(?:>|\*/)[\n]?)#';
160 $tagRegexp = '#(?:<|/\*)(START|END):code-template::([a-zA-Z]+[a-zA-Z0-9_|&-]*)[\n]?(?:>|\*/)#';
161
162 $split = preg_split( $tagSplit, $templateText, -1, PREG_SPLIT_DELIM_CAPTURE );
163
164 $currentBlocks = array();
165 $blocks = array();
166 $currentTag = false;
167 for ( $i = 0; $i < count( $split ); ++$i )
168 {
169 $part = $split[$i];
170 if ( ( $i % 2 ) == 1 )
171 {
172 // The tag element
173 if ( $currentTag === false )
174 {
175 preg_match( $tagRegexp, trim( $part ), $matches );
176 $currentTag = $matches[2];
177 if ( $matches[1] == 'END' )
178 {
179 eZDebug::writeError( "Tag $currentTag was finished before it was started, skipping it", __METHOD__ );
180 $currentTag = false;
181 $error = true;
182 }
183 else
184 {
185 if ( count( $currentBlocks ) > 0 )
186 $blocks[] = array( 'blocks' => $currentBlocks );
187 $currentBlocks = array();
188 }
189 }
190 else
191 {
192 preg_match( $tagRegexp, trim( $part ), $matches );
193 $tag = $matches[2];
194 if ( $matches[1] == 'END' )
195 {
196 if ( $tag == $currentTag )
197 {
198 if ( count( $currentBlocks ) > 0 )
199 $blocks[] = array( 'tag' => $currentTag,
200 'blocks' => $currentBlocks );
201 $currentTag = false;
202 $currentBlocks = array();
203 }
204 else
205 {
206 eZDebug::writeError( "End tag $tag does not match start tag $currentTag, skipping it", __METHOD__ );
207 $error = true;
208 }
209 }
210 else
211 {
212 eZDebug::writeError( "Start tag $tag found while $currentTag is active, skipping it", __METHOD__ );
213 $error = true;
214 }
215 }
216 }
217 else
218 {
219 // Plain text
220 $currentBlocks[] = $part;
221 }
222 }
223 if ( $currentTag === false )
224 {
225 if ( count( $currentBlocks ) > 0 )
226 $blocks[] = array( 'blocks' => $currentBlocks );
227 }
228 else
229 {
230 if ( count( $currentBlocks ) > 0 )
231 $blocks[] = array( 'tag' => $currentTag,
232 'blocks' => $currentBlocks );
233 }
234
235 // Build new code with blocks to include
236 $resultText = '';
237 foreach ( $blocks as $block )
238 {
239 if ( isset( $block['tag'] ) )
240 {
241 $tagText = $block['tag'];
242 if ( strpos( $tagText, '&' ) !== false )
243 {
244 $tags = explode( '&', $tagText );
245 // Check if all tags are present in parameters (and match)
246 if ( count( array_intersect( $parameters, $tags ) ) == count( $tags ) )
247 {
248 $resultText .= implode( '', $block['blocks'] );
249 }
250 }
251 else if ( strpos( $tagText, '|' ) !== false )
252 {
253 $tags = explode( '|', $tagText );
254 // Check if at least one tag is present in parameters (or match)
255 if ( count( array_intersect( $parameters, $tags ) ) == count( $tags ) )
256 {
257 $resultText .= implode( '', $block['blocks'] );
258 }
259 }
260 else
261 {
262 if ( in_array( $tagText, $parameters ) )
263 {
264 $resultText .= implode( '', $block['blocks'] );
265 }
266 }
267 }
268 else
269 {
270 $resultText .= implode( '', $block['blocks'] );
271 }
272 }
273
274 // Remove any end-of-line whitespaces unless keep-whitespace is used
275 if ( !in_array( 'keep-whitespace', $parameters ) )
276 $resultText = preg_replace( '#[ \t]+$#m', '', $resultText );
277
278 // Output text before the template-block
279 fwrite( $fd, substr( $text, $offset, $createPos - $offset ) );
280 fwrite( $fd, substr( $text, $createPos, $end - $createPos ) );
281
282 $offset = $end;
283
284 // Remove any existing auto-generated code
285 $autogenRegexp = '#^[ \t]*// code-template::auto-generated:START ' . $templateName . '.+[ \t]*// code-template::auto-generated:END ' . $templateName . '\n#ms';
286 $postText = substr( $text, $offset );
287 $postText = preg_replace( $autogenRegexp, '', $postText );
288 $text = substr( $text, 0, $offset ) . $postText;
289 unset( $postText );
290
291 // Output the template code with markers
292 fwrite( $fd, ( "$indentText// code-template::auto-generated:START $templateName\n" .
293 "$indentText// This code is automatically generated from $templateFile\n" .
294 "$indentText// DO NOT EDIT THIS CODE DIRECTLY, CHANGE THE TEMPLATE FILE INSTEAD\n" .
295 "\n" ) );
296
297 fwrite( $fd, $resultText );
298 fwrite( $fd, ( "\n$indentText// This code is automatically generated from $templateFile\n" .
299 "$indentText// code-template::auto-generated:END $templateName\n" ) );
300
301 }
302 else
303 {
304 fwrite( $fd, substr( $text, $offset ) );
305 break;
306 }
307 }
308
309 fclose( $fd );
310 if ( !$error )
311 {
312 $originalMD5 = md5_file( $filePath );
313 $updatedMD5 = md5_file( $tempFile );
314 if ( $originalMD5 === $updatedMD5 )
315 {
316 unlink( $tempFile );
317 return self::STATUS_NO_CHANGE;
318 }
319 else if ( $checkOnly )
320 {
321 unlink( $tempFile );
322 return self::STATUS_OK;
323 }
324 else
325 {
326 $backupFile = $filePath . eZSys::backupFilename();
327 // Make a backup and make the temporary file the real one
328 if ( file_exists( $backupFile ) )
329 unlink( $backupFile );
330 rename( $filePath, $backupFile );
331 rename( $tempFile, $filePath );
332 return self::STATUS_OK;
333 }
334 }
335 unlink( $tempFile );
336 return self::STATUS_FAILED;
337 }
338
343 function templateFile( $templateName )
344 {
345 if ( isset( $this->Templates[$templateName] ) )
346 {
347 return $this->Templates[$templateName]['filepath'];
348 }
349 return false;
350 }
351
358 function allCodeFiles()
359 {
360 $ini = eZINI::instance( 'codetemplate.ini' );
361 return $ini->variable( 'Files', 'PHPFiles' );
362 }
363
365 public $Templates;
366 }
367
368 ?>
eZCodeTemplate
Replaces or generates blocks of code according to a template file.
Definition: ezcodetemplate.php:18
eZCodeTemplate\STATUS_FAILED
const STATUS_FAILED
There are errors in the template code.
Definition: ezcodetemplate.php:20
eZCodeTemplate\$Templates
$Templates
Definition: ezcodetemplate.php:365
eZCodeTemplate\apply
apply( $filePath, $checkOnly=false)
Definition: ezcodetemplate.php:54
eZCodeTemplate\allCodeFiles
allCodeFiles()
Definition: ezcodetemplate.php:358
eZCodeTemplate\STATUS_NO_CHANGE
const STATUS_NO_CHANGE
Code file was updated, but no new elements has been added.
Definition: ezcodetemplate.php:26
eZCodeTemplate\__construct
__construct()
Definition: ezcodetemplate.php:31
eZCodeTemplate\templateFile
templateFile( $templateName)
Definition: ezcodetemplate.php:343
eZCodeTemplate\STATUS_OK
const STATUS_OK
Code files was succesfully updated.
Definition: ezcodetemplate.php:23
eZDebug\writeError
static writeError( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:545
eZSys\backupFilename
static backupFilename()
Definition: ezsys.php:473
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.