|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Definition of eZPHPCreator class 00004 // 00005 // Created on: <28-Nov-2002 08:28:23 amos> 00006 // 00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00008 // SOFTWARE NAME: eZ Publish 00009 // SOFTWARE RELEASE: 4.0.x 00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS 00011 // SOFTWARE LICENSE: GNU General Public License v2.0 00012 // NOTICE: > 00013 // This program is free software; you can redistribute it and/or 00014 // modify it under the terms of version 2.0 of the GNU General 00015 // Public License as published by the Free Software Foundation. 00016 // 00017 // This program is distributed in the hope that it will be useful, 00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 // GNU General Public License for more details. 00021 // 00022 // You should have received a copy of version 2.0 of the GNU General 00023 // Public License along with this program; if not, write to the Free 00024 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00025 // MA 02110-1301, USA. 00026 // 00027 // 00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00029 // 00030 00031 /*! \file ezphpcreator.php 00032 */ 00033 00034 /*! 00035 \class eZPHPCreator ezphpcreator.php 00036 \ingroup eZUtils 00037 \brief eZPHPCreator provides a simple interface for creating and executing PHP code. 00038 00039 To create PHP code you must create an instance of this class, 00040 add any number of elements you choose with 00041 addDefine(), addVariable(), addVariableUnset(), addVariableUnsetList(), 00042 addSpace(), addText(), addMethodCall(), addCodePiece(), addComment() and 00043 addInclude(). 00044 After that you call store() to write all changes to disk. 00045 00046 \code 00047 $php = new eZPHPCreator( 'cache', 'code.php' ); 00048 00049 $php->addComment( 'Auto generated' ); 00050 $php->addInclude( 'inc.php' ); 00051 $php->addVariable( 'count', 10 ); 00052 00053 $php->store(); 00054 \endcode 00055 00056 To restore PHP code you must create an instance of this class, 00057 check if you can restore it with canRestore() then restore variables with restore(). 00058 The class will include PHP file and run all code, once the file is done it will 00059 catch any variables you require and return it to you. 00060 00061 \code 00062 $php = new eZPHPCreator( 'cache', 'code.php' ); 00063 00064 if ( $php->canRestore() ) 00065 { 00066 $variables = $php->restore( array( 'max_count' => 'count' ) ); 00067 print( "Max count was " . $variables['max_count'] ); 00068 } 00069 00070 $php->close(); 00071 \endcode 00072 00073 */ 00074 00075 class eZPHPCreator 00076 { 00077 const VARIABLE = 1; 00078 const SPACE = 2; 00079 const TEXT = 3; 00080 const METHOD_CALL = 4; 00081 const CODE_PIECE = 5; 00082 const EOL_COMMENT = 6; 00083 const INCLUDE_STATEMENT = 7; 00084 const VARIABLE_UNSET = 8; 00085 const DEFINE = 9; 00086 const VARIABLE_UNSET_LIST = 10; 00087 const RAW_VARIABLE = 11; 00088 00089 const VARIABLE_ASSIGNMENT = 1; 00090 const VARIABLE_APPEND_TEXT = 2; 00091 const VARIABLE_APPEND_ELEMENT = 3; 00092 00093 const INCLUDE_ONCE_STATEMENT = 1; 00094 const INCLUDE_ALWAYS_STATEMENT = 2; 00095 00096 const METHOD_CALL_PARAMETER_VALUE = 1; 00097 const METHOD_CALL_PARAMETER_VARIABLE = 2; 00098 00099 /*! 00100 Initializes the creator with the directory path \a $dir and filename \a $file. 00101 */ 00102 function eZPHPCreator( $dir, $file, $prefix = '', $options = array() ) 00103 { 00104 $this->PHPDir = $dir; 00105 $this->PHPFile = $file; 00106 $this->FilePrefix = $prefix; 00107 $this->FileResource = false; 00108 $this->Elements = array(); 00109 $this->TextChunks = array(); 00110 $this->TemporaryCounter = 0; 00111 if ( isset( $options['spacing'] ) and ( $options['spacing'] == 'disabled') ) 00112 { 00113 $this->Spacing = false; 00114 } 00115 else 00116 { 00117 $this->Spacing = true; 00118 } 00119 00120 if ( isset( $options['clustering'] ) ) 00121 { 00122 $this->ClusteringEnabled = true; 00123 $this->ClusterFileScope = $options['clustering']; 00124 } 00125 else 00126 { 00127 $this->ClusteringEnabled = false; 00128 } 00129 $this->ClusterHandler = null; 00130 } 00131 00132 //@{ 00133 00134 /*! 00135 Adds a new define statement to the code with the name \a $name and value \a $value. 00136 The parameter \a $caseSensitive determines if the define should be made case sensitive or not. 00137 00138 Example: 00139 \code 00140 $php->addDefine( 'MY_CONSTANT', 5 ); 00141 \endcode 00142 00143 Would result in the PHP code. 00144 00145 \code 00146 define( 'MY_CONSTANT', 5 ); 00147 \endcode 00148 00149 \param $parameters Optional parameters, can be any of the following: 00150 - \a spacing, The number of spaces to place before each code line, default is \c 0. 00151 00152 \note \a $name must start with a letter or underscore, followed by any number of letters, numbers, or underscores. 00153 See http://php.net/manual/en/language.constants.php for more information. 00154 \sa http://php.net/manual/en/function.define.php 00155 */ 00156 function addDefine( $name, $value, $caseSensitive = true, $parameters = array() ) 00157 { 00158 $element = array( eZPHPCreator::DEFINE, 00159 $name, 00160 $value, 00161 $caseSensitive, 00162 $parameters ); 00163 $this->Elements[] = $element; 00164 } 00165 00166 /*! 00167 Adds a new raw variable tothe code with the name \a $name and value \a $value. 00168 00169 Example: 00170 \code 00171 $php->addVariable( 'TransLationRoot', $cache['root'] ); 00172 \endcode 00173 00174 This function makes use of PHP's var_export() function which is optimized 00175 for this task. 00176 */ 00177 function addRawVariable( $name, $value ) 00178 { 00179 $element = array( eZPHPCreator::RAW_VARIABLE, $name, $value ); 00180 $this->Elements[] = $element; 00181 } 00182 00183 /*! 00184 Adds a new variable to the code with the name \a $name and value \a $value. 00185 00186 Example: 00187 \code 00188 $php->addVariable( 'offset', 5 ); 00189 $php->addVariable( 'text', 'some more text', eZPHPCreator::VARIABLE_APPEND_TEXT ); 00190 $php->addVariable( 'array', 42, eZPHPCreator::VARIABLE_APPEND_ELEMENT ); 00191 \endcode 00192 00193 Would result in the PHP code. 00194 00195 \code 00196 $offset = 5; 00197 $text .= 'some more text'; 00198 $array[] = 42; 00199 \endcode 00200 00201 \param $assignmentType Controls the way the value is assigned, choose one of the following: 00202 - \b eZPHPCreator::VARIABLE_ASSIGNMENT, assign using \c = (default) 00203 - \b eZPHPCreator::VARIABLE_APPEND_TEXT, append using text concat operator \c . 00204 - \b eZPHPCreator::VARIABLE_APPEND_ELEMENT, append element to array using append operator \c [] 00205 \param $parameters Optional parameters, can be any of the following: 00206 - \a spacing, The number of spaces to place before each code line, default is \c 0. 00207 - \a full-tree, Whether to displays array values as one large expression (\c true) or 00208 split it up into multiple variables (\c false) 00209 00210 */ 00211 function addVariable( $name, $value, $assignmentType = eZPHPCreator::VARIABLE_ASSIGNMENT, 00212 $parameters = array() ) 00213 { 00214 $element = array( eZPHPCreator::VARIABLE, 00215 $name, 00216 $value, 00217 $assignmentType, 00218 $parameters ); 00219 $this->Elements[] = $element; 00220 } 00221 00222 /*! 00223 Adds code to unset a variable with the name \a $name. 00224 00225 Example: 00226 \code 00227 $php->addVariableUnset( 'offset' ); 00228 \endcode 00229 00230 Would result in the PHP code. 00231 00232 \code 00233 unset( $offset ); 00234 \endcode 00235 00236 \param $parameters Optional parameters, can be any of the following: 00237 - \a spacing, The number of spaces to place before each code line, default is \c 0. 00238 00239 \sa http://php.net/manual/en/function.unset.php 00240 */ 00241 function addVariableUnset( $name, 00242 $parameters = array() ) 00243 { 00244 $element = array( eZPHPCreator::VARIABLE_UNSET, 00245 $name, 00246 $parameters ); 00247 $this->Elements[] = $element; 00248 } 00249 00250 /*! 00251 Adds code to unset a list of variables with name from \a $list. 00252 00253 Example: 00254 \code 00255 $php->addVariableUnsetList( array ( 'var1', 'var2' ) ); 00256 \endcode 00257 00258 Would result in the PHP code. 00259 00260 \code 00261 unset( $var1, $var2 ); 00262 \endcode 00263 00264 \param $parameters Optional parameters, can be any of the following: 00265 - \a spacing, The number of spaces to place before each code line, default is \c 0. 00266 00267 \sa http://php.net/manual/en/function.unset.php 00268 */ 00269 function addVariableUnsetList( $list, 00270 $parameters = array() ) 00271 { 00272 $element = array( eZPHPCreator::VARIABLE_UNSET_LIST, 00273 $list, 00274 $parameters ); 00275 $this->Elements[] = $element; 00276 } 00277 00278 /*! 00279 Adds some space to the code in form of newlines. The number of lines 00280 is controlled with \a $lines which is \c 1 by default. 00281 You can use this to get more readable PHP code. 00282 00283 Example: 00284 \code 00285 $php->addSpace( 1 ); 00286 \endcode 00287 */ 00288 function addSpace( $lines = 1 ) 00289 { 00290 $element = array( eZPHPCreator::SPACE, 00291 $lines ); 00292 $this->Elements[] = $element; 00293 } 00294 00295 /*! 00296 Adds some plain text to the code. The text will be placed 00297 outside of PHP start and end markers and will in principle 00298 work as printing the text. 00299 00300 Example: 00301 \code 00302 $php->addText( 'Print me!' ); 00303 \endcode 00304 */ 00305 function addText( $text ) 00306 { 00307 $element = array( eZPHPCreator::TEXT, 00308 $text ); 00309 $this->Elements[] = $element; 00310 } 00311 00312 /*! 00313 Adds code to call the method \a $methodName on the object named \a $objectName, 00314 \a $methodParameters should be an array with parameter entries where each entry contains: 00315 - \a 0, The parameter value 00316 - \a 1 (\em optional), The type of parameter, is one of: 00317 - \b eZPHPCreator::METHOD_CALL_PARAMETER_VALUE, Use value directly (default if this entry is missing) 00318 - \b eZPHPCreator::METHOD_CALL_PARAMETER_VARIABLE, Use value as the name of the variable. 00319 00320 Optionally the \a $returnValue parameter can be used to decide what should be done 00321 with the return value of the method call. It can either be \c false which means 00322 to do nothing or an array with the following entries. 00323 - \a 0, The name of the variable to assign the value to 00324 - \a 1 (\em optional), The type of assignment, uses the same value as addVariable(). 00325 00326 \param $parameters Optional parameters, can be any of the following: 00327 - \a spacing, The number of spaces to place before each code line, default is \c 0. 00328 00329 Example: 00330 \code 00331 $php->addMethodCall( 'node', 'name', array(), array( 'name' ) ); 00332 $php->addMethodCall( 'php', 'addMethodCall', 00333 array( array( 'node' ), array( 'name' ) ) ); 00334 \endcode 00335 00336 Would result in the PHP code. 00337 00338 \code 00339 $name = $node->name(); 00340 $php->addMethodCall( 'node', 'name' ); 00341 \endcode 00342 */ 00343 function addMethodCall( $objectName, $methodName, $methodParameters, $returnValue = false, $parameters = array() ) 00344 { 00345 $element = array( eZPHPCreator::METHOD_CALL, 00346 $objectName, 00347 $methodName, 00348 $methodParameters, 00349 $returnValue, 00350 $parameters ); 00351 $this->Elements[] = $element; 00352 } 00353 00354 /*! 00355 Adds custom PHP code to the file, you should only use this a last resort if any 00356 of the other \em add functions done give you the required result. 00357 00358 \param $code Contains the code as text, the text will not be modified (except for spacing). 00359 This means that each expression must be ended with a newline even if it's just one. 00360 \param $parameters Optional parameters, can be any of the following: 00361 - \a spacing, The number of spaces to place before each code line, default is \c 0. 00362 00363 Example: 00364 \code 00365 $php->addCodePiece( "if ( \$value > 2 )\n{\n \$value = 2;\n}\n" ); 00366 \endcode 00367 00368 Would result in the PHP code. 00369 00370 \code 00371 if ( $value > 2 ) 00372 { 00373 $value = 2; 00374 } 00375 \endcode 00376 00377 */ 00378 function addCodePiece( $code, $parameters = array() ) 00379 { 00380 $element = array( eZPHPCreator::CODE_PIECE, 00381 $code, 00382 $parameters ); 00383 $this->Elements[] = $element; 00384 } 00385 00386 /*! 00387 Adds a comment to the code, the comment will be display using multiple end-of-line 00388 comments (//), one for each newline in the text \a $comment. 00389 00390 \param $eol Whether to add a newline at the last comment line 00391 \param $whitespaceHandling Whether to remove trailing whitespace from each line 00392 \param $parameters Optional parameters, can be any of the following: 00393 - \a spacing, The number of spaces to place before each code line, default is \c 0. 00394 00395 Example: 00396 \code 00397 $php->addComment( "This file is auto generated\nDo not edit!" ); 00398 \endcode 00399 00400 Would result in the PHP code. 00401 00402 \code 00403 // This file is auto generated 00404 // Do not edit! 00405 \endcode 00406 00407 */ 00408 function addComment( $comment, $eol = true, $whitespaceHandling = true, $parameters = array() ) 00409 { 00410 $element = array( eZPHPCreator::EOL_COMMENT, 00411 $comment, 00412 array_merge( $parameters, 00413 array( 'eol' => $eol, 00414 'whitespace-handling' => $whitespaceHandling ) ) ); 00415 $this->Elements[] = $element; 00416 } 00417 00418 /*! 00419 Adds an include statement to the code, the file to include is \a $file. 00420 00421 \param $type What type of include statement to use, can be one of the following: 00422 - \b eZPHPCreator::INCLUDE_ONCE_STATEMENT, use \em include_once() 00423 - \b eZPHPCreator::INCLUDE_ALWAYS_STATEMENT, use \em include() 00424 \param $parameters Optional parameters, can be any of the following: 00425 - \a spacing, The number of spaces to place before each code line, default is \c 0. 00426 00427 Example: 00428 \code 00429 $php->addInclude( 'lib/ezutils/classes/ezphpcreator.php' ); 00430 \endcode 00431 00432 Would result in the PHP code. 00433 00434 \code 00435 //include_once( 'lib/ezutils/classes/ezphpcreator.php' ); 00436 \endcode 00437 00438 */ 00439 function addInclude( $file, $type = eZPHPCreator::INCLUDE_ONCE_STATEMENT, $parameters = array() ) 00440 { 00441 $element = array( eZPHPCreator::INCLUDE_STATEMENT, 00442 $file, 00443 $type, 00444 $parameters ); 00445 $this->Elements[] = $element; 00446 } 00447 00448 //@} 00449 00450 /*! 00451 \static 00452 Creates a variable statement with an assignment type and returns it. 00453 \param $variableName The name of the variable 00454 \param $assignmentType What kind of assignment to use, is one of the following; 00455 - \b eZPHPCreator::VARIABLE_ASSIGNMENT, assign using \c = 00456 - \b eZPHPCreator::VARIABLE_APPEND_TEXT, append to text using \c . 00457 - \b eZPHPCreator::VARIABLE_APPEND_ELEMENT, append to array using \c [] 00458 \param $variableParameters Optional parameters for the statement 00459 */ 00460 static function variableNameText( $variableName, $assignmentType, $variableParameters = array() ) 00461 { 00462 $text = '$' . $variableName; 00463 if ( $assignmentType == eZPHPCreator::VARIABLE_ASSIGNMENT ) 00464 { 00465 $text .= ' = '; 00466 } 00467 else if ( $assignmentType == eZPHPCreator::VARIABLE_APPEND_TEXT ) 00468 { 00469 $text .= ' .= '; 00470 } 00471 else if ( $assignmentType == eZPHPCreator::VARIABLE_APPEND_ELEMENT ) 00472 { 00473 $text .= '[] = '; 00474 } 00475 return $text; 00476 } 00477 00478 /*! 00479 Creates a text representation of the value \a $value which can 00480 be placed in files and be read back by a PHP parser as it was. 00481 The type of the values determines the output, it can be one of the following. 00482 - boolean, becomes \c true or \c false 00483 - null, becomes \c null 00484 - string, adds \ (backslash) to backslashes, double quotes, dollar signs and newlines. 00485 Then wraps the whole string in " (double quotes). 00486 - numeric, displays the value as-is. 00487 - array, expands all value recursively using this function 00488 - object, creates a representation of an object creation if the object has \c serializeData implemented. 00489 00490 \param $column Determines the starting column in which the text will be placed. 00491 This is used for expanding arrays and objects which can span multiple lines. 00492 \param $iteration The current iteration, starts at 0 and increases with 1 for each recursive call 00493 \param $maxIterations The maximum number of iterations to allow, if the iteration 00494 exceeds this the array or object will be split into multiple variables. 00495 Can be set to \c false to the array or object as-is. 00496 00497 \note This function can be called statically if \a $maxIterations is set to \c false 00498 */ 00499 function thisVariableText( $value, $column = 0, $iteration = 0, $maxIterations = 2 ) 00500 { 00501 if ( isset( $this->Spacing ) and !$this->Spacing ) 00502 { 00503 return var_export( $value, true ); 00504 } 00505 00506 if ( is_bool( $value ) ) 00507 $text = ( $value ? 'true' : 'false' ); 00508 else if ( is_null( $value ) ) 00509 $text = 'null'; 00510 else if ( is_string( $value ) ) 00511 { 00512 $valueText = str_replace( array( "\\", 00513 "\"", 00514 "\$", 00515 "\n" ), 00516 array( "\\\\", 00517 "\\\"", 00518 "\\$", 00519 "\\n" ), 00520 $value ); 00521 $text = "\"$valueText\""; 00522 } 00523 else if ( is_numeric( $value ) ) 00524 $text = $value; 00525 else if ( is_object( $value ) ) 00526 { 00527 if ( $maxIterations !== false and 00528 $iteration > $maxIterations ) 00529 { 00530 $temporaryVariableName = $this->temporaryVariableName( 'obj' ); 00531 $this->writeVariable( $temporaryVariableName, $value ); 00532 $text = '$' . $temporaryVariableName; 00533 } 00534 else 00535 { 00536 $text = ''; 00537 if ( method_exists( $value, 'serializedata' ) ) 00538 { 00539 $serializeData = $value->serializeData(); 00540 $className = $serializeData['class_name']; 00541 $text = "new $className("; 00542 00543 $column += strlen( $text ); 00544 $parameters = $serializeData['parameters']; 00545 $variables = $serializeData['variables']; 00546 00547 $i = 0; 00548 foreach ( $parameters as $parameter ) 00549 { 00550 if ( $i > 0 ) 00551 { 00552 $text .= ",\n" . str_repeat( ' ', $column ); 00553 } 00554 $variableName = $variables[$parameter]; 00555 $variableValue = $value->$variableName; 00556 $keyText = " "; 00557 00558 $text .= $keyText . $this->thisVariableText( $variableValue, $column + strlen( $keyText ), $iteration + 1, $maxIterations ); 00559 00560 ++$i; 00561 } 00562 if ( $i > 0 ) 00563 $text .= ' '; 00564 00565 $text .= ')'; 00566 } 00567 } 00568 } 00569 else if ( is_array( $value ) ) 00570 { 00571 if ( $maxIterations !== false and 00572 $iteration > $maxIterations ) 00573 { 00574 $temporaryVariableName = $this->temporaryVariableName( 'arr' ); 00575 $this->writeVariable( $temporaryVariableName, $value ); 00576 $text = '$' . $temporaryVariableName; 00577 } 00578 else 00579 { 00580 $text = 'array('; 00581 $column += strlen( $text ); 00582 $valueKeys = array_keys( $value ); 00583 $isIndexed = true; 00584 for ( $i = 0; $i < count( $valueKeys ); ++$i ) 00585 { 00586 if ( $i !== $valueKeys[$i] ) 00587 { 00588 $isIndexed = false; 00589 break; 00590 } 00591 } 00592 $i = 0; 00593 foreach ( $valueKeys as $key ) 00594 { 00595 if ( $i > 0 ) 00596 { 00597 $text .= ",\n" . str_repeat( ' ', $column ); 00598 } 00599 $element = $value[$key]; 00600 $keyText = ' '; 00601 if ( !$isIndexed ) 00602 { 00603 if ( is_int( $key ) ) 00604 $keyText = $key; 00605 else 00606 $keyText = "\"" . str_replace( array( "\\", 00607 "\"", 00608 "\n" ), 00609 array( "\\\\", 00610 "\\\"", 00611 "\\n" ), 00612 $key ) . "\""; 00613 $keyText = " $keyText => "; 00614 } 00615 00616 $text .= $keyText . $this->thisVariableText( $element, $column + strlen( $keyText ), $iteration + 1, $maxIterations ); 00617 00618 ++$i; 00619 } 00620 if ( $i > 0 ) 00621 $text .= ' '; 00622 $text .= ')'; 00623 } 00624 } 00625 else 00626 $text = 'null'; 00627 return $text; 00628 } 00629 00630 static function variableText( $value, $column = 0, $iteration = 0, $maxIterations = false ) 00631 { 00632 // the last parameter will always be ignored 00633 $maxIterations = false; 00634 00635 if ( is_bool( $value ) ) 00636 $text = ( $value ? 'true' : 'false' ); 00637 else if ( is_null( $value ) ) 00638 $text = 'null'; 00639 else if ( is_string( $value ) ) 00640 { 00641 $valueText = str_replace( array( "\\", 00642 "\"", 00643 "\$", 00644 "\n" ), 00645 array( "\\\\", 00646 "\\\"", 00647 "\\$", 00648 "\\n" ), 00649 $value ); 00650 $text = "\"$valueText\""; 00651 } 00652 else if ( is_numeric( $value ) ) 00653 $text = $value; 00654 else if ( is_object( $value ) ) 00655 { 00656 $text = ''; 00657 if ( method_exists( $value, 'serializedata' ) ) 00658 { 00659 $serializeData = $value->serializeData(); 00660 $className = $serializeData['class_name']; 00661 $text = "new $className("; 00662 00663 $column += strlen( $text ); 00664 $parameters = $serializeData['parameters']; 00665 $variables = $serializeData['variables']; 00666 00667 $i = 0; 00668 foreach ( $parameters as $parameter ) 00669 { 00670 if ( $i > 0 ) 00671 { 00672 $text .= ",\n" . str_repeat( ' ', $column ); 00673 } 00674 $variableName = $variables[$parameter]; 00675 $variableValue = $value->$variableName; 00676 $keyText = " "; 00677 00678 $text .= $keyText . eZPHPCreator::variableText( $variableValue, $column + strlen( $keyText ), $iteration + 1 ); 00679 ++$i; 00680 } 00681 if ( $i > 0 ) 00682 $text .= ' '; 00683 00684 $text .= ')'; 00685 } 00686 } 00687 else if ( is_array( $value ) ) 00688 { 00689 $text = 'array('; 00690 $column += strlen( $text ); 00691 $valueKeys = array_keys( $value ); 00692 $isIndexed = true; 00693 for ( $i = 0; $i < count( $valueKeys ); ++$i ) 00694 { 00695 if ( $i !== $valueKeys[$i] ) 00696 { 00697 $isIndexed = false; 00698 break; 00699 } 00700 } 00701 $i = 0; 00702 foreach ( $valueKeys as $key ) 00703 { 00704 if ( $i > 0 ) 00705 { 00706 $text .= ",\n" . str_repeat( ' ', $column ); 00707 } 00708 $element = $value[$key]; 00709 $keyText = ' '; 00710 if ( !$isIndexed ) 00711 { 00712 if ( is_int( $key ) ) 00713 $keyText = $key; 00714 else 00715 $keyText = "\"" . str_replace( array( "\\", 00716 "\"", 00717 "\n" ), 00718 array( "\\\\", 00719 "\\\"", 00720 "\\n" ), 00721 $key ) . "\""; 00722 $keyText = " $keyText => "; 00723 } 00724 00725 $text .= $keyText . eZPHPCreator::variableText( $element, $column + strlen( $keyText ), $iteration + 1 ); 00726 00727 ++$i; 00728 } 00729 if ( $i > 0 ) 00730 $text .= ' '; 00731 $text .= ')'; 00732 } 00733 else 00734 $text = 'null'; 00735 return $text; 00736 } 00737 00738 /*! 00739 \static 00740 Splits \a $text into multiple lines using \a $splitString for splitting. 00741 For each line it will prepend the string \a $spacingString n times as specified by \a $spacing. 00742 00743 It will try to be smart and not do anything when \a $spacing is set to \c 0. 00744 00745 \param $skipEmptyLines If \c true it will not prepend the string for empty lines. 00746 \param $spacing Must be a positive number, \c 0 means to not prepend anything. 00747 */ 00748 static function prependSpacing( $text, $spacing, $skipEmptyLines = true, $spacingString = " ", $splitString = "\n" ) 00749 { 00750 if ( $spacing == 0 ) 00751 return $text; 00752 $textArray = explode( $splitString, $text ); 00753 $newTextArray = array(); 00754 foreach ( $textArray as $text ) 00755 { 00756 if ( trim( $text ) != '' ) 00757 $textLine = str_repeat( $spacingString, $spacing ) . $text; 00758 else 00759 $textLine = $text; 00760 $newTextArray[] = $textLine; 00761 } 00762 return implode( $splitString, $newTextArray ); 00763 } 00764 00765 //@{ 00766 00767 /*! 00768 Opens the file for writing and sets correct file permissions. 00769 \return The current file resource or \c false if it failed to open the file. 00770 \note The file name and path is supplied to the constructor of this class. 00771 \note Multiple calls to this method will only open the file once. 00772 */ 00773 function open( $atomic = false ) 00774 { 00775 if ( $this->ClusteringEnabled ) 00776 return true; 00777 00778 if ( !$this->FileResource ) 00779 { 00780 if ( !file_exists( $this->PHPDir ) ) 00781 { 00782 //include_once( 'lib/ezfile/classes/ezdir.php' ); 00783 eZDir::mkdir( $this->PHPDir, false, true ); 00784 } 00785 $path = $this->PHPDir . '/' . $this->PHPFile; 00786 $oldumask = umask( 0 ); 00787 $pathExisted = file_exists( $path ); 00788 if ( $atomic ) 00789 { 00790 $this->isAtomic = true; 00791 $this->requestedFilename = $path; 00792 $uniqid = md5( uniqid( "ezp". getmypid(), true ) ); 00793 $path .= ".$uniqid"; 00794 $this->tmpFilename = $path; 00795 } 00796 $ini = eZINI::instance(); 00797 $perm = octdec( $ini->variable( 'FileSettings', 'StorageFilePermissions' ) ); 00798 $this->FileResource = @fopen( $this->FilePrefix . $path, "w" ); 00799 if ( !$this->FileResource ) 00800 eZDebug::writeError( "Could not open file '$path' for writing, perhaps wrong permissions" ); 00801 if ( $this->FileResource and 00802 !$pathExisted ) 00803 chmod( $path, $perm ); 00804 umask( $oldumask ); 00805 } 00806 return $this->FileResource; 00807 } 00808 00809 /*! 00810 Closes the currently open file if any. 00811 */ 00812 function close() 00813 { 00814 if ( $this->ClusteringEnabled ) 00815 { 00816 $this->ClusterHandler = null; 00817 return; 00818 } 00819 00820 if ( $this->FileResource ) 00821 { 00822 fclose( $this->FileResource ); 00823 00824 if ( $this->isAtomic ) 00825 { 00826 //include_once( 'lib/ezfile/classes/ezfile.php' ); 00827 eZFile::rename( $this->tmpFilename, $this->requestedFilename ); 00828 } 00829 $this->FileResource = false; 00830 } 00831 } 00832 00833 /*! 00834 \return \c true if the file and path already exists. 00835 \note The file name and path is supplied to the constructor of this class. 00836 */ 00837 function exists() 00838 { 00839 $path = $this->PHPDir . '/' . $this->PHPFile; 00840 if ( !$this->ClusteringEnabled ) 00841 return file_exists( $path ); 00842 00843 if ( !$this->ClusterHandler ) 00844 { 00845 require_once( 'kernel/classes/ezclusterfilehandler.php' ); 00846 $this->ClusterHandler = eZClusterFileHandler::instance(); 00847 } 00848 return $this->ClusterHandler->fileExists( $path ); 00849 } 00850 00851 /*! 00852 \return \c true if file exists and can be restored. 00853 \param $timestamp The timestamp to check the modification time of the file against, 00854 if the modification time is larger or equal to \a $timestamp 00855 the file can be restored. Otherwise the file is considered too old. 00856 \note The file name and path is supplied to the constructor of this class. 00857 */ 00858 function canRestore( $timestamp = false ) 00859 { 00860 $path = $this->PHPDir . '/' . $this->PHPFile; 00861 00862 if ( $this->ClusteringEnabled ) 00863 { 00864 if ( !$this->ClusterHandler ) 00865 { 00866 require_once( 'kernel/classes/ezclusterfilehandler.php' ); 00867 $this->ClusterHandler = eZClusterFileHandler::instance( $path ); 00868 } 00869 $canRestore= $this->ClusterHandler->exists(); 00870 00871 if ( $timestamp !== false and $canRestore ) 00872 { 00873 $cacheModifierTime = $this->ClusterHandler->mtime(); 00874 $canRestore = ( $cacheModifierTime >= $timestamp ); 00875 } 00876 00877 return $canRestore; 00878 } 00879 00880 $canRestore = file_exists( $path ); 00881 if ( $timestamp !== false and 00882 $canRestore ) 00883 { 00884 $cacheModifierTime = filemtime( $path ); 00885 $canRestore = ( $cacheModifierTime >= $timestamp ); 00886 } 00887 00888 return $canRestore; 00889 } 00890 00891 /*! 00892 Tries to restore the PHP file and fetch the defined variables in \a $variableDefinitions. 00893 This basically means including the file using include(). 00894 00895 \param $variableDefinitions Associative array with the return variable name being the key 00896 matched variable as value. 00897 00898 \return An associatve array with the variables that were found according to \a $variableDefinitions. 00899 00900 Example: 00901 \code 00902 $values = $php->restore( array( 'MyValue' => 'node' ) ); 00903 print( $values['MyValue'] ); 00904 \endcode 00905 00906 \note The file name and path is supplied to the constructor of this class. 00907 */ 00908 function restore( $variableDefinitions ) 00909 { 00910 $returnVariables = array(); 00911 $path = $this->PHPDir . '/' . $this->PHPFile; 00912 00913 if ( !$this->ClusteringEnabled ) 00914 { 00915 $returnVariables = $this->_restoreCall( $path, false, $variableDefinitions ); 00916 } 00917 else 00918 { 00919 if ( !$this->ClusterHandler ) 00920 { 00921 require_once( 'kernel/classes/ezclusterfilehandler.php' ); 00922 $this->ClusterHandler = eZClusterFileHandler::instance( $path ); 00923 } 00924 $returnVariables = $this->ClusterHandler->processFile( array( $this, '_restoreCall' ), null, $variableDefinitions ); 00925 } 00926 return $returnVariables; 00927 } 00928 00929 /*! 00930 \private 00931 Processes the PHP file and returns the specified data. 00932 */ 00933 function _restoreCall( $path, $mtime, $variableDefinitions ) 00934 { 00935 $returnVariables = array(); 00936 include( $path ); 00937 foreach ( $variableDefinitions as $variableReturnName => $variableName ) 00938 { 00939 $variableRequired = true; 00940 $variableDefault = false; 00941 if ( is_array( $variableName ) ) 00942 { 00943 $variableDefinition = $variableName; 00944 $variableName = $variableDefinition['name']; 00945 $variableRequired = $variableDefinition['required']; 00946 if ( isset( $variableDefinition['default'] ) ) 00947 $variableDefault = $variableDefinition['default']; 00948 } 00949 if ( isset( $$variableName ) ) 00950 { 00951 $returnVariables[$variableReturnName] = $$variableName; 00952 } 00953 else if ( $variableRequired ) 00954 { 00955 eZDebug::writeError( "Variable '$variableName' is not present in cache '$path'", 00956 'eZPHPCreator::restore' ); 00957 } 00958 else 00959 { 00960 $returnVariables[$variableReturnName] = $variableDefault; 00961 } 00962 } 00963 return $returnVariables; 00964 } 00965 00966 /*! 00967 Stores the PHP cache, returns false if the cache file could not be created. 00968 */ 00969 function store( $atomic = false ) 00970 { 00971 if ( $this->open( $atomic ) ) 00972 { 00973 $this->write( "<?php\n" ); 00974 00975 $this->writeElements(); 00976 00977 $this->write( "?>\n" ); 00978 00979 $this->writeChunks(); 00980 $this->flushChunks(); 00981 $this->close(); 00982 00983 if ( !$this->ClusteringEnabled ) 00984 { 00985 $perm = octdec( eZINI::instance()->variable( 'FileSettings', 'StorageFilePermissions' ) ); 00986 chmod( eZDir::path( array( $this->PHPDir, $this->PHPFile ) ), $perm ); 00987 } 00988 00989 // Write log message to storage.log 00990 //include_once( 'lib/ezfile/classes/ezlog.php' ); 00991 eZLog::writeStorageLog( $this->PHPFile, $this->PHPDir . '/' ); 00992 return true; 00993 } 00994 else 00995 { 00996 eZDebug::writeError( "Failed to open file '" . $this->PHPDir . '/' . $this->PHPFile . "'", 00997 'eZPHPCreator::store' ); 00998 return false; 00999 } 01000 } 01001 01002 /*! 01003 Creates a text string out of all elements and returns it. 01004 \note Calling this multiple times will resulting text processing each time. 01005 */ 01006 function fetch( $addPHPMarkers = true ) 01007 { 01008 if ( $addPHPMarkers ) 01009 $this->write( "<?php\n" ); 01010 $this->writeElements(); 01011 if ( $addPHPMarkers ) 01012 $this->write( "?>\n" ); 01013 01014 $text = implode( '', $this->TextChunks ); 01015 01016 $this->flushChunks(); 01017 01018 return $text; 01019 } 01020 01021 //@} 01022 01023 /*! 01024 \private 01025 */ 01026 function writeChunks() 01027 { 01028 $count = count( $this->TextChunks ); 01029 01030 if ( $this->ClusteringEnabled ) 01031 { 01032 $text = ''; 01033 for ( $i = 0; $i < $count; ++$i ) 01034 $text .= $this->TextChunks[$i]; 01035 01036 $filePath = $this->FilePrefix . $this->PHPDir . '/' . $this->PHPFile; 01037 01038 if ( !$this->ClusterHandler ) 01039 { 01040 require_once( 'kernel/classes/ezclusterfilehandler.php' ); 01041 $this->ClusterHandler = eZClusterFileHandler::instance(); 01042 } 01043 $this->ClusterHandler->fileStoreContents( $filePath, $text, $this->ClusterFileScope, 'php' ); 01044 01045 return; 01046 } 01047 01048 for ( $i = 0; $i < $count; ++$i ) 01049 { 01050 $text = $this->TextChunks[$i]; 01051 fwrite( $this->FileResource, $text ); 01052 } 01053 } 01054 01055 /*! 01056 \private 01057 */ 01058 function flushChunks() 01059 { 01060 $this->TextChunks = array(); 01061 } 01062 01063 /*! 01064 \private 01065 */ 01066 function write( $text ) 01067 { 01068 $this->TextChunks[] = $text; 01069 } 01070 01071 /*! 01072 \private 01073 */ 01074 function writeElements() 01075 { 01076 $count = count( $this->Elements ); 01077 foreach( $this->Elements as $element ) 01078 { 01079 if ( $element[0] == eZPHPCreator::DEFINE ) 01080 { 01081 $this->writeDefine( $element ); 01082 } 01083 else if ( $element[0] == eZPHPCreator::RAW_VARIABLE ) 01084 { 01085 $this->writeRawVariable( $element[1], $element[2] ); 01086 } 01087 else if ( $element[0] == eZPHPCreator::VARIABLE ) 01088 { 01089 $this->writeVariable( $element[1], $element[2], $element[3], $element[4] ); 01090 } 01091 else if ( $element[0] == eZPHPCreator::VARIABLE_UNSET ) 01092 { 01093 $this->writeVariableUnset( $element ); 01094 } 01095 else if ( $element[0] == eZPHPCreator::VARIABLE_UNSET_LIST ) 01096 { 01097 $this->writeVariableUnsetList( $element ); 01098 } 01099 else if ( $element[0] == eZPHPCreator::SPACE ) 01100 { 01101 $this->writeSpace( $element ); 01102 } 01103 else if ( $element[0] == eZPHPCreator::TEXT ) 01104 { 01105 $this->writeText( $element ); 01106 } 01107 else if ( $element[0] == eZPHPCreator::METHOD_CALL ) 01108 { 01109 $this->writeMethodCall( $element ); 01110 } 01111 else if ( $element[0] == eZPHPCreator::CODE_PIECE ) 01112 { 01113 $this->writeCodePiece( $element ); 01114 } 01115 else if ( $element[0] == eZPHPCreator::EOL_COMMENT ) 01116 { 01117 $this->writeComment( $element ); 01118 } 01119 else if ( $element[0] == eZPHPCreator::INCLUDE_STATEMENT ) 01120 { 01121 $this->writeInclude( $element ); 01122 } 01123 } 01124 } 01125 01126 /*! 01127 \private 01128 */ 01129 function writeDefine( $element ) 01130 { 01131 $name = $element[1]; 01132 $value = $element[2]; 01133 $caseSensitive = $element[3]; 01134 $parameters = $element[4]; 01135 $text = ''; 01136 if ( $this->Spacing ) 01137 { 01138 $spacing = 0; 01139 if ( isset( $parameters['spacing'] ) ) 01140 $spacing = $parameters['spacing']; 01141 $text = str_repeat( ' ', $spacing ); 01142 } 01143 $nameText = $this->thisVariableText( $name, 0 ); 01144 $valueText = $this->thisVariableText( $value, 0 ); 01145 $text .= "define( $nameText, $valueText"; 01146 if ( !$caseSensitive ) 01147 $text .= ", true"; 01148 $text .= " );\n"; 01149 $this->write( $text ); 01150 } 01151 01152 /*! 01153 \private 01154 */ 01155 function writeInclude( $element ) 01156 { 01157 $includeFile = $element[1]; 01158 $includeType = $element[2]; 01159 $parameters = $element[3]; 01160 if ( $includeType == eZPHPCreator::INCLUDE_ONCE_STATEMENT ) 01161 $includeName = 'include_once'; 01162 else if ( $includeType == eZPHPCreator::INCLUDE_ALWAYS_STATEMENT ) 01163 $includeName = 'include'; 01164 $includeFileText = $this->thisVariableText( $includeFile, 0 ); 01165 $text = "$includeName( $includeFileText );\n"; 01166 if ( $this->Spacing ) 01167 { 01168 $spacing = 0; 01169 if ( isset( $parameters['spacing'] ) ) 01170 $spacing = $parameters['spacing']; 01171 $text = str_repeat( ' ', $spacing ) . $text; 01172 } 01173 $this->write( $text ); 01174 } 01175 01176 /*! 01177 \private 01178 */ 01179 function writeComment( $element ) 01180 { 01181 $elementAttributes = $element[2]; 01182 $spacing = 0; 01183 if ( isset( $elementAttributes['spacing'] ) and $this->Spacing ) 01184 $spacing = $elementAttributes['spacing']; 01185 $whitespaceHandling = $elementAttributes['whitespace-handling']; 01186 $eol = $elementAttributes['eol']; 01187 $newCommentArray = array(); 01188 $commentArray = preg_split( "/\r\n|\r|\n/", $element[1] ); 01189 foreach ( $commentArray as $comment ) 01190 { 01191 $textLine = '// ' . $comment; 01192 if ( $whitespaceHandling ) 01193 { 01194 $textLine = rtrim( $textLine ); 01195 $textLine = str_replace( "\t", ' ', $textLine ); 01196 } 01197 $textLine = str_repeat( ' ', $spacing ) . $textLine; 01198 $newCommentArray[] = $textLine; 01199 } 01200 $text = implode( "\n", $newCommentArray ); 01201 if ( $eol ) 01202 $text .= "\n"; 01203 $this->write( $text ); 01204 } 01205 01206 /*! 01207 \private 01208 */ 01209 function writeSpace( $element ) 01210 { 01211 $text = str_repeat( "\n", $element[1] ); 01212 $this->write( $text ); 01213 } 01214 01215 /*! 01216 \private 01217 */ 01218 function writeCodePiece( $element ) 01219 { 01220 $code = $element[1]; 01221 $parameters = $element[2]; 01222 $spacing = 0; 01223 if ( isset( $parameters['spacing'] ) and $this->Spacing ) 01224 $spacing = $parameters['spacing']; 01225 $text = eZPHPCreator::prependSpacing( $code, $spacing ); 01226 $this->write( $text ); 01227 } 01228 01229 /*! 01230 \private 01231 */ 01232 function writeText( $element ) 01233 { 01234 $text = $element[1]; 01235 $this->write( "\n?>" ); 01236 $this->write( $text ); 01237 $this->write( "<?php\n" ); 01238 } 01239 01240 /*! 01241 \private 01242 */ 01243 function writeMethodCall( $element ) 01244 { 01245 $objectName = $element[1]; 01246 $methodName = $element[2]; 01247 $methodParameters = $element[3]; 01248 $returnValue = $element[4]; 01249 $parameters = $element[5]; 01250 $text = ''; 01251 $spacing = 0; 01252 if ( isset( $parameters['spacing'] ) and $this->Spacing ) 01253 $spacing = $parameters['spacing']; 01254 if ( is_array( $returnValue ) ) 01255 { 01256 $variableName = $returnValue[0]; 01257 $assignmentType = eZPHPCreator::VARIABLE_ASSIGNMENT; 01258 if ( isset( $variableValue[1] ) ) 01259 $assignmentType = $variableValue[1]; 01260 $text = $this->variableNameText( $variableName, $assignmentType ); 01261 } 01262 $text .= '$' . $objectName . '->' . $methodName . '('; 01263 $column = strlen( $text ); 01264 $i = 0; 01265 foreach ( $methodParameters as $parameterData ) 01266 { 01267 if ( $i > 0 ) 01268 $text .= ",\n" . str_repeat( ' ', $column ); 01269 $parameterType = eZPHPCreator::METHOD_CALL_PARAMETER_VALUE; 01270 $parameterValue = $parameterData[0]; 01271 if ( isset( $parameterData[1] ) ) 01272 $parameterType = $parameterData[1]; 01273 if ( $parameterType == eZPHPCreator::METHOD_CALL_PARAMETER_VALUE ) 01274 $text .= ' ' . $this->thisVariableText( $parameterValue, $column + 1 ); 01275 else if ( $parameterType == eZPHPCreator::METHOD_CALL_PARAMETER_VARIABLE ) 01276 $text .= ' $' . $parameterValue; 01277 ++$i; 01278 } 01279 if ( $i > 0 ) 01280 $text .= ' '; 01281 $text .= ");\n"; 01282 $text = eZPHPCreator::prependSpacing( $text, $spacing ); 01283 $this->write( $text ); 01284 } 01285 01286 /*! 01287 \private 01288 */ 01289 function writeVariableUnset( $element ) 01290 { 01291 $variableName = $element[1]; 01292 $parameters = $element[2]; 01293 $spacing = 0; 01294 if ( isset( $parameters['spacing'] ) and $this->Spacing ) 01295 $spacing = $parameters['spacing']; 01296 $text = "unset( \$$variableName );\n"; 01297 $text = eZPHPCreator::prependSpacing( $text, $spacing ); 01298 $this->write( $text ); 01299 } 01300 01301 /*! 01302 \private 01303 */ 01304 function writeVariableUnsetList( $element ) 01305 { 01306 $variableNames = $element[1]; 01307 01308 if ( count( $variableNames ) ) 01309 { 01310 $parameters = $element[2]; 01311 $spacing = 0; 01312 if ( isset( $parameters['spacing'] ) and $this->Spacing ) 01313 $spacing = $parameters['spacing']; 01314 $text = 'unset( '; 01315 array_walk( $variableNames, create_function( '&$variableName,$key', '$variableName = "\$" . $variableName;') ); 01316 $text .= join( ', ', $variableNames ); 01317 $text .= " );\n"; 01318 $text = eZPHPCreator::prependSpacing( $text, $spacing ); 01319 $this->write( $text ); 01320 } 01321 } 01322 01323 /*! 01324 \private 01325 */ 01326 function writeRawVariable( $variableName, $variableValue ) 01327 { 01328 $this->write( "\${$variableName} = ". var_export( $variableValue, true). ";\n" ); 01329 } 01330 01331 /*! 01332 \private 01333 */ 01334 function writeVariable( $variableName, $variableValue, $assignmentType = eZPHPCreator::VARIABLE_ASSIGNMENT, 01335 $variableParameters = array() ) 01336 { 01337 $variableParameters = array_merge( array( 'full-tree' => false, 01338 'spacing' => 0 ), 01339 $variableParameters ); 01340 $fullTree = $variableParameters['full-tree']; 01341 $spacing = $this->Spacing ? $variableParameters['spacing'] : 0; 01342 $text = $this->variableNameText( $variableName, $assignmentType, $variableParameters ); 01343 $maxIterations = 2; 01344 if ( $fullTree ) 01345 $maxIterations = false; 01346 $text .= $this->thisVariableText( $variableValue, strlen( $text ), 0, $maxIterations ); 01347 $text .= ";\n"; 01348 $text = eZPHPCreator::prependSpacing( $text, $spacing ); 01349 $this->write( $text ); 01350 } 01351 01352 /*! 01353 \private 01354 */ 01355 function temporaryVariableName( $prefix ) 01356 { 01357 $variableName = $prefix . '_' . $this->TemporaryCounter; 01358 ++$this->TemporaryCounter; 01359 return $variableName; 01360 } 01361 01362 /// \privatesection 01363 public $PHPDir; 01364 public $PHPFile; 01365 public $FileResource; 01366 public $Elements; 01367 public $TextChunks; 01368 public $isAtomic; 01369 public $tmpFilename; 01370 public $requestedFilename; 01371 public $Spacing = true; 01372 public $ClusteringEnabled = false; 01373 public $ClusterFileScope = false; 01374 } 01375 ?>