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;
 }
Example #2
0
 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;
    }