function apply($filePath) { if (!file_exists($filePath)) { eZDebug::writeError("File {$filePath} does not exists", 'eZClassTemplate::apply'); return false; } $text = file_get_contents($filePath); $tempFile = dirname($filePath) . '#' . basename($filePath) . '#'; $fd = fopen($tempFile, 'wb'); if (!$fd) { eZDebug::writeError("Failed to open temporary file {$tempFile}", 'eZClassTemplate::apply'); return false; } $createTag = 'code-template::create-block:'; $createTagLen = strlen($createTag); $error = false; $ok = true; $offset = 0; $len = strlen($text); while ($offset < $len) { $createPos = strpos($text, $createTag, $offset); if ($createPos !== false) { $endPos = strpos($text, "\n", $createPos + $createTagLen); if ($endPos === false) { $createText = substr($text, $createPos + $createTagLen); $end = $len; } else { $start = $createPos + $createTagLen; $createText = substr($text, $start, $endPos - $start); $end = $endPos + 1; } // Figure out how much the comments should be indented // This just makes the code seem more natural $indentText = ''; $subText = substr($text, $offset, $createPos - $offset); $startOfLine = strrpos($subText, "\n"); if ($startOfLine !== false) { if (preg_match('#^([ \\t]+)#', substr($subText, $startOfLine + 1), $matches)) { $indentText = $matches[1]; } } unset($subText); // Figure out template name and parameters $createText = trim($createText); $elements = explode(',', $createText); if (count($elements) < 1) { eZDebug::writeError("No template name found in file {$filePath} at offset {$offset}", 'eZClassTemplate::apply'); $offset = $end; $error = true; continue; } $templateName = trim($elements[0]); $templateFile = $this->templateFile($templateName); if ($templateFile === false) { eZDebug::writeError("No template file for template {$templateName} used in file {$filePath} at offset {$offset}", 'eZClassTemplate::apply'); $offset = $end; $error = true; continue; } if (!file_exists($templateFile)) { eZDebug::writeError("Template file {$templateFile} for template {$templateName} does not exist", 'eZClassTemplate::apply'); $offset = $end; $error = true; continue; } $parameters = array_splice($elements, 1); foreach ($parameters as $key => $parameter) { $parameters[$key] = trim($parameter); } // Load the template file and split it into the blocks // available blocks in the file $templateText = file_get_contents($templateFile); $tagSplit = '#(<(?:START|END):code-template::(?:[a-zA-Z]+[a-zA-Z0-9_-]*)>)#'; $tagRegexp = '#<(START|END):code-template::([a-zA-Z]+[a-zA-Z0-9_-]*)>#'; $split = preg_split($tagSplit, $templateText, -1, PREG_SPLIT_DELIM_CAPTURE); $currentBlocks = array(); $currentTag = false; for ($i = 0; $i < count($split); ++$i) { $part = $split[$i]; if ($i % 2 == 1) { // The tag element if ($currentTag === false) { preg_match($tagRegexp, trim($part), $matches); $currentTag = $matches[2]; if ($matches[1] == 'END') { eZDebug::writeError("Tag {$currentTag} was finished before it was started, skipping it", 'eZClassTemplate::apply'); $currentTag = false; $error = true; } else { if (count($currentBlocks) > 0) { $blocks[] = array('blocks' => $currentBlocks); } $currentBlocks = array(); } } else { preg_match($tagRegexp, trim($part), $matches); $tag = $matches[2]; if ($matches[1] == 'END') { if ($tag == $currentTag) { if (count($currentBlocks) > 0) { $blocks[] = array('tag' => $currentTag, 'blocks' => $currentBlocks); } $currentTag = false; $currentBlocks = array(); } else { eZDebug::writeError("End tag {$tag} does not match start tag {$currentTag}, skipping it", 'eZClassTemplate::apply'); $error = true; } } else { eZDebug::writeError("Start tag {$tag} found while {$currentTag} is active, skipping it", 'eZClassTemplate::apply'); $error = true; } } } else { // Plain text $currentBlocks[] = $part; } } if ($currentTag === false) { if (count($currentBlocks) > 0) { $blocks[] = array('blocks' => $currentBlocks); } } else { if (count($currentBlocks) > 0) { $blocks[] = array('tag' => $currentTag, 'blocks' => $currentBlocks); } } // Build new code with blocks to include $resultText = ''; foreach ($blocks as $block) { if (isset($block['tag'])) { if (in_array($block['tag'], $parameters)) { $resultText .= implode('', $block['blocks']); } } else { $resultText .= implode('', $block['blocks']); } } // Remove any end-of-line whitespaces unless keep-whitespace is used if (!in_array('keep-whitespace', $parameters)) { $resultText = preg_replace('#[ \\t]+$#m', '', $resultText); } // Output text before the template-block fwrite($fd, substr($text, $offset, $createPos - $offset)); fwrite($fd, substr($text, $createPos, $end - $createPos)); $offset = $end; // Remove any existing auto-generated code $autogenRegexp = '#^[ \\t]*// code-template::auto-generated:START.+[ \\t]*// code-template::auto-generated:END\\n#ms'; $postText = substr($text, $offset); $postText = preg_replace($autogenRegexp, '', $postText); $text = substr($text, 0, $offset) . $postText; unset($postText); // Output the template code with markers fwrite($fd, "{$indentText}// code-template::auto-generated:START {$templateName}\n" . "{$indentText}// This code is automatically generated from {$templateFile}\n" . "{$indentText}// DO NOT EDIT THIS CODE DIRECTLY, CHANGE THE TEMPLATE FILE INSTEAD\n" . "\n"); fwrite($fd, $resultText); fwrite($fd, "\n{$indentText}// This code is automatically generated from {$templateFile}\n" . "{$indentText}// code-template::auto-generated:END\n"); } else { fwrite($fd, substr($text, $offset)); break; } } fclose($fd); if (!$error) { $backupFile = $filePath . eZSys::backupFilename(); // Make a backup and make the temporary file the real one if (file_exists($backupFile)) { unlink($backupFile); } rename($filePath, $backupFile); rename($tempFile, $filePath); return true; } unlink($tempFile); return false; }
function save($fileName = false, $suffix = false, $useOverride = false, $onlyModified = false, $useRootDir = true, $resetArrays = false, $encapsulateInPHP = true) { $lineSeparator = eZSys::lineSeparator(); $pathArray = array(); $dirArray = array(); if ($fileName === false) { $fileName = $this->FileName; } if ($useRootDir === true) { $pathArray[] = $this->RootDir; $dirArray[] = $this->RootDir; } else { if (is_string($useRootDir)) { $pathArray[] = $useRootDir; $dirArray[] = $useRootDir; } } if ($useOverride) { $pathArray[] = 'override'; $dirArray[] = 'override'; } if ($useOverride === 'append') { $fileName .= '.append'; } if ($suffix !== false) { $fileName .= $suffix; } /* Try to guess which filename would fit better: 'xxx.apend' or 'xxx.append.php'. * We choose 'xxx.append.php' in all cases except when * 'xxx.append' exists already and 'xxx.append.php' does not exist. */ if (strstr($fileName, '.append')) { $fnAppend = preg_replace('#\\.php$#', '', $fileName); $fnAppendPhp = $fnAppend . '.php'; $fpAppend = eZDir::path(array_merge($pathArray, array($fnAppend))); $fpAppendPhp = eZDir::path(array_merge($pathArray, array($fnAppendPhp))); $fileName = file_exists($fpAppend) && !file_exists($fpAppendPhp) ? $fnAppend : $fnAppendPhp; } $originalFileName = $fileName; $backupFileName = $originalFileName . eZSys::backupFilename(); $fileName .= '.tmp'; $dirPath = eZDir::path($dirArray); if (!file_exists($dirPath)) { eZDir::mkdir($dirPath, octdec('777'), true); } $filePath = eZDir::path(array_merge($pathArray, array($fileName))); $originalFilePath = eZDir::path(array_merge($pathArray, array($originalFileName))); $backupFilePath = eZDir::path(array_merge($pathArray, array($backupFileName))); $fp = @fopen($filePath, "w+"); if (!$fp) { eZDebug::writeError("Failed opening file '{$filePath}' for writing", __METHOD__); return false; } $writeOK = true; $written = 0; $charset = $this->Codec ? $this->Codec->RequestedOutputCharsetCode : $this->Charset; if ($encapsulateInPHP) { $written = fwrite($fp, "<?php /* #?ini charset=\"{$charset}\"?{$lineSeparator}{$lineSeparator}"); } else { $written = fwrite($fp, "#?ini charset=\"{$charset}\"?{$lineSeparator}{$lineSeparator}"); } if ($written === false) { $writeOK = false; } $i = 0; if ($writeOK) { foreach (array_keys($this->BlockValues) as $blockName) { if ($onlyModified) { $groupHasModified = false; if (isset($this->ModifiedBlockValues[$blockName])) { foreach ($this->ModifiedBlockValues[$blockName] as $modifiedValue) { if ($modifiedValue) { $groupHasModified = true; } } } if (!$groupHasModified) { continue; } } $written = 0; if ($i > 0) { $written = fwrite($fp, "{$lineSeparator}"); } if ($written === false) { $writeOK = false; break; } $written = fwrite($fp, "[{$blockName}]{$lineSeparator}"); if ($written === false) { $writeOK = false; break; } foreach (array_keys($this->BlockValues[$blockName]) as $blockVariable) { if ($onlyModified) { if (!isset($this->ModifiedBlockValues[$blockName][$blockVariable]) or !$this->ModifiedBlockValues[$blockName][$blockVariable]) { continue; } } $varKey = $blockVariable; $varValue = $this->BlockValues[$blockName][$blockVariable]; if (is_array($varValue)) { if (count($varValue) > 0) { $customResetArray = (isset($this->BlockValues[$blockName]['ResetArrays']) and $this->BlockValues[$blockName]['ResetArrays'] == 'false') ? true : false; if ($resetArrays and !$customResetArray) { $written = fwrite($fp, "{$varKey}" . "[]{$lineSeparator}"); } foreach ($varValue as $varArrayKey => $varArrayValue) { if (is_string($varArrayKey)) { $written = fwrite($fp, "{$varKey}" . "[{$varArrayKey}]={$varArrayValue}{$lineSeparator}"); } else { if ($varArrayValue == NULL) { $written = fwrite($fp, "{$varKey}" . "[]{$lineSeparator}"); } else { $written = fwrite($fp, "{$varKey}" . "[]={$varArrayValue}{$lineSeparator}"); } } if ($written === false) { break; } } } else { $written = fwrite($fp, "{$varKey}" . "[]{$lineSeparator}"); } } else { $written = fwrite($fp, "{$varKey}={$varValue}{$lineSeparator}"); } if ($written === false) { $writeOK = false; break; } } if (!$writeOK) { break; } ++$i; } } if ($writeOK) { if ($encapsulateInPHP) { $written = fwrite($fp, "*/ ?>"); if ($written === false) { $writeOK = false; } } } @fclose($fp); if (!$writeOK) { unlink($filePath); return false; } chmod($filePath, self::$filePermission); if (file_exists($backupFilePath)) { unlink($backupFilePath); } if (file_exists($originalFilePath)) { if (!rename($originalFilePath, $backupFilePath)) { return false; } } if (!rename($filePath, $originalFilePath)) { rename($backupFilePath, $originalFilePath); return false; } return true; }
function apply( $filePath, $checkOnly = false ) { if ( !file_exists( $filePath ) ) { eZDebug::writeError( "File $filePath does not exist", __METHOD__ ); return self::STATUS_FAILED; } $text = file_get_contents( $filePath ); $tempFile = dirname( $filePath ) . '/#' . basename( $filePath ) . '#'; $fd = fopen( $tempFile, 'wb' ); if ( !$fd ) { eZDebug::writeError( "Failed to open temporary file $tempFile", __METHOD__ ); return self::STATUS_FAILED; } $createTag = 'code-template::create-block:'; $createTagLen = strlen( $createTag ); $error = false; $ok = true; $offset = 0; $len = strlen( $text ); while ( $offset < $len ) { $createPos = strpos( $text, $createTag, $offset ); if ( $createPos !== false ) { $endPos = strpos( $text, "\n", $createPos + $createTagLen ); if ( $endPos === false ) { $createText = substr( $text, $createPos + $createTagLen ); $end = $len; } else { $start = $createPos + $createTagLen; $createText = substr( $text, $start, $endPos - $start ); $end = $endPos + 1; } // Figure out how much the comments should be indented // This just makes the code seem more natural $indentText = ''; $subText = substr( $text, $offset, $createPos - $offset ); $startOfLine = strrpos( $subText, "\n" ); if ( $startOfLine !== false ) { if ( preg_match( '#^([ \t]+)#', substr( $subText, $startOfLine + 1 ), $matches ) ) { $indentText = $matches[1]; } } unset( $subText ); // Figure out template name and parameters $createText = trim( $createText ); $elements = explode( ',', $createText ); if ( count( $elements ) < 1 ) { eZDebug::writeError( "No template name found in file $filePath at offset $offset", __METHOD__ ); $offset = $end; $error = true; continue; } $templateName = trim( $elements[0] ); $templateFile = $this->templateFile( $templateName ); if ( $templateFile === false ) { eZDebug::writeError( "No template file for template $templateName used in file $filePath at offset $offset", __METHOD__ ); $offset = $end; $error = true; continue; } if ( !file_exists( $templateFile ) ) { eZDebug::writeError( "Template file $templateFile for template $templateName does not exist", __METHOD__ ); $offset = $end; $error = true; continue; } $parameters = array_splice( $elements, 1 ); foreach ( $parameters as $key => $parameter ) { $parameters[$key] = trim( $parameter ); } if ( !file_exists( $templateFile ) ) { eZDebug::writeError( "Template file $templateFile was not found while workin on $filePath at offset $offset", __METHOD__ ); $offset = $end; $error = true; continue; } // Load the template file and split it into the blocks // available blocks in the file $templateText = file_get_contents( $templateFile ); $tagSplit = '#((?:<|/\*)(?:START|END):code-template::(?:[a-zA-Z]+[a-zA-Z0-9_|&-]*)(?:>|\*/)[\n]?)#'; $tagRegexp = '#(?:<|/\*)(START|END):code-template::([a-zA-Z]+[a-zA-Z0-9_|&-]*)[\n]?(?:>|\*/)#'; $split = preg_split( $tagSplit, $templateText, -1, PREG_SPLIT_DELIM_CAPTURE ); $currentBlocks = array(); $blocks = array(); $currentTag = false; for ( $i = 0; $i < count( $split ); ++$i ) { $part = $split[$i]; if ( ( $i % 2 ) == 1 ) { // The tag element if ( $currentTag === false ) { preg_match( $tagRegexp, trim( $part ), $matches ); $currentTag = $matches[2]; if ( $matches[1] == 'END' ) { eZDebug::writeError( "Tag $currentTag was finished before it was started, skipping it", __METHOD__ ); $currentTag = false; $error = true; } else { if ( count( $currentBlocks ) > 0 ) $blocks[] = array( 'blocks' => $currentBlocks ); $currentBlocks = array(); } } else { preg_match( $tagRegexp, trim( $part ), $matches ); $tag = $matches[2]; if ( $matches[1] == 'END' ) { if ( $tag == $currentTag ) { if ( count( $currentBlocks ) > 0 ) $blocks[] = array( 'tag' => $currentTag, 'blocks' => $currentBlocks ); $currentTag = false; $currentBlocks = array(); } else { eZDebug::writeError( "End tag $tag does not match start tag $currentTag, skipping it", __METHOD__ ); $error = true; } } else { eZDebug::writeError( "Start tag $tag found while $currentTag is active, skipping it", __METHOD__ ); $error = true; } } } else { // Plain text $currentBlocks[] = $part; } } if ( $currentTag === false ) { if ( count( $currentBlocks ) > 0 ) $blocks[] = array( 'blocks' => $currentBlocks ); } else { if ( count( $currentBlocks ) > 0 ) $blocks[] = array( 'tag' => $currentTag, 'blocks' => $currentBlocks ); } // Build new code with blocks to include $resultText = ''; foreach ( $blocks as $block ) { if ( isset( $block['tag'] ) ) { $tagText = $block['tag']; if ( strpos( $tagText, '&' ) !== false ) { $tags = explode( '&', $tagText ); // Check if all tags are present in parameters (and match) if ( count( array_intersect( $parameters, $tags ) ) == count( $tags ) ) { $resultText .= implode( '', $block['blocks'] ); } } else if ( strpos( $tagText, '|' ) !== false ) { $tags = explode( '|', $tagText ); // Check if at least one tag is present in parameters (or match) if ( count( array_intersect( $parameters, $tags ) ) == count( $tags ) ) { $resultText .= implode( '', $block['blocks'] ); } } else { if ( in_array( $tagText, $parameters ) ) { $resultText .= implode( '', $block['blocks'] ); } } } else { $resultText .= implode( '', $block['blocks'] ); } } // Remove any end-of-line whitespaces unless keep-whitespace is used if ( !in_array( 'keep-whitespace', $parameters ) ) $resultText = preg_replace( '#[ \t]+$#m', '', $resultText ); // Output text before the template-block fwrite( $fd, substr( $text, $offset, $createPos - $offset ) ); fwrite( $fd, substr( $text, $createPos, $end - $createPos ) ); $offset = $end; // Remove any existing auto-generated code $autogenRegexp = '#^[ \t]*// code-template::auto-generated:START ' . $templateName . '.+[ \t]*// code-template::auto-generated:END ' . $templateName . '\n#ms'; $postText = substr( $text, $offset ); $postText = preg_replace( $autogenRegexp, '', $postText ); $text = substr( $text, 0, $offset ) . $postText; unset( $postText ); // Output the template code with markers fwrite( $fd, ( "$indentText// code-template::auto-generated:START $templateName\n" . "$indentText// This code is automatically generated from $templateFile\n" . "$indentText// DO NOT EDIT THIS CODE DIRECTLY, CHANGE THE TEMPLATE FILE INSTEAD\n" . "\n" ) ); fwrite( $fd, $resultText ); fwrite( $fd, ( "\n$indentText// This code is automatically generated from $templateFile\n" . "$indentText// code-template::auto-generated:END $templateName\n" ) ); } else { fwrite( $fd, substr( $text, $offset ) ); break; } } fclose( $fd ); if ( !$error ) { $originalMD5 = md5_file( $filePath ); $updatedMD5 = md5_file( $tempFile ); if ( $originalMD5 == $updatedMD5 ) { unlink( $tempFile ); return self::STATUS_NO_CHANGE; } else if ( $checkOnly ) { unlink( $tempFile ); return self::STATUS_OK; } else { $backupFile = $filePath . eZSys::backupFilename(); // Make a backup and make the temporary file the real one if ( file_exists( $backupFile ) ) unlink( $backupFile ); rename( $filePath, $backupFile ); rename( $tempFile, $filePath ); return self::STATUS_OK; } } unlink( $tempFile ); return self::STATUS_FAILED; }