All pastes #620779 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-07-15 19:05 UTC
rendered paste body
<?php

/**
 * Zula Framework View
 * A simple tag replacement engine that also allows for PHP code
 *
 * @License: http://www.gnu.org/copyleft/gpl.html GNU/GPL 2
 * @Author Alex Cartwright
 * @Date 2007-03-11
 */

	class View {

		/**
		 * Full absolute path to the view file
		 * @var string
		 */
		protected $view_path = '';
		
		/**
		 * The module this is for (for locale)
		 * @var string
		 */
		protected $module = '';		

		/**
		 * Holds the raw view contents
		 * @var string
		 */
		protected $raw_contents = '';
		
		/**
		 * Holds a modified version of the view contents
		 * @var string
		 */
		protected $final_contents = null;
		
		/**
		 * Assigned tags that will replace tags with different content
		 * @var array
		 */
		protected $assigned_tags = array();		
		
		
		/**
		 * Constructor function
		 * Attempts to load the view file and sets which module this is for
		 *
		 * @param string $view_file
		 * [@param string $module]
		 */
		public function __construct( $view_file, $module='' ) {
			$this->module = $module;
			$this->view_path = trim( $view_file );
			if ( !file_exists( $this->view_path ) ) {	
				$new_path = Zula::get_dir( 'views' ).'/'.$view_file;
				if ( !file_exists( $new_path ) ) {
					Error::report( 'View file could not be loaded', 'view file is missing or not readable ('.$new_path.')', Error::_WARNING );
				}
				$this->view_path = $new_path;
			}					
		}		
		
		/**
		 * Returns every tag that is assigned to the view file
		 *
		 * @return array
		 */
		public function get_assigned_tags() {
			return $this->assigned_tags;
		}		
		
		/**
		 * Assigns a new tag to use that will get replaced		
		 *
		 * @param array $tags		 
		 * [@param bool $overwrite] If a tag already exists, should it be overwriten or appended?
		 * [@param bool $uppercase] Toggle if to set the tags to upper case
		 * [@param bool $allow_html] should HTML be allowed in the tag value?
		 * @return bool
		 */
		public function assign( $tags, $overwrite=true, $uppercase=true, $allow_html=false ) {
			if ( !is_array( $tags ) ) {
				return false;
			}
			foreach( $tags as $tag=>$val ) {
				if ( $allow_html == false ) {
					$val = $this->clean_tag_value( $val );
				}
				if ( $uppercase == true ) {
					$tag = strtoupper( $tag );
				}
				$tags[ $this->clean_tag( $tag ) ] = $val;				
			}
			if ( empty( $this->assigned_tags ) ) {
				$this->assigned_tags = $tags;		
				return true;
			} else if ( $overwrite == false ) {
				/**
				 * Patch that allows tags that have been assigned more than once
				 * to be appended onto the end, instead of overwriting the old tag
				 */
				foreach( $tags as $key=>$val ) {
					if ( !is_array( $val ) && isset( $this->assigned_tags[ $key ] ) ) {
						$this->assigned_tags[ $key ] .= $val;
					} else if ( isset( $this->assigned_tags[ $key ] ) ) {
						$this->assigned_tags[ $key ] = array_merge( $this->assigned_tags, $val );
					} else {
						$this->assigned_tags[ $key ] = $val;
					}
				}
				return true;
			} else {
				$this->assigned_tags = array_merge( $this->assigned_tags, $tags );
				return true;
			}
		}
		
		/**
		 * Assigns a new tag but do allow HTML
		 *
		 * @param array $tags
		 * [@param bool $uppercase] Toggle if to set the tags to upper case
		 * [@param bool $overwrite] If a tag already exists, should it be overwriten or appended?
		 * @return bool
		 */
		public function assign_html( $tags, $uppercase=true, $overwrite=true ) {
			return $this->assign( $tags, $uppercase, $overwrite, true );
		}
		
		/**
		 * Cleans up a tag to make it Alphanumeric and a few others only
		 *
		 * @param string $tag
		 * @return string
		 */
		public function clean_tag( $tag ) {
			return preg_replace( '/[^A-Za-z0-9_\- ]/', '', $tag );
		}
		
		/**
		 * Cleans up a tag value by recursingly removing HTML
		 *
		 * @param mixed $value
		 * @return mixed
		 */
		public function clean_tag_value( $value ) {
			if ( is_array( $value ) ) {
				foreach( $value as $key=>$val ) {
					if ( is_array( $val ) ) {
						$value[ $this->clean_tag( $key ) ] = $this->clean_tag_value( $val );
					} else {
						$value[ $this->clean_tag( $key ) ] = htmlspecialchars( strip_tags($val) );
					}
				}
				return $value;
			} else {
				return htmlspecialchars( strip_tags($value) );
			}
		}
		
		/**
		 * Checks if a tag has been assigned to this view file
		 *
		 * @return bool
		 */
		public function is_assigned( $val ) {
			return isset( $this->assigned_tags[ $val ] );
		}
		
		/**
		 * This is the actual Tag Replacement method
		 * First it assigns the default tags that need to be used and then prepars the Tags that
		 * will be used in the PHP 'Jail' class. All of the Tags for PHP use are convertd to lowercase
		 *
		 * After all PHP is run it gets the output from the class and goes about replacing the normal
		 * {TAGS} in the view file. All language tags are also found and assigned, they appear at the start
		 * of the assigned tags array
		 *
		 * @return string
		 */
		public function get_output() {			
			$this->assign_default_tags();			
			# Prepare the tags for the PHP class			 
			$php_tags = array();
			foreach( $this->assigned_tags as $tag=>$val ) {
				$php_tags[ strtolower( $tag ) ] = $val;
			}
			$tmp_view = new View_OB( $php_tags, $this->view_path );
			$tmp_view_content = $tmp_view->get_output(); # Return content of the parsed PHP view file
			
			# Gather all language tags and merge them into the final tag array
			$language_tags = $this->language_tags( $tmp_view_content );
			$this->assigned_tags = array_merge( $language_tags, $this->assigned_tags );	
			
			preg_match_all( '@{(.*?)}@', $tmp_view_content, $template_tags );
			if ( empty( $template_tags[0] ) ) {
				$this->final_contents = $tmp_view_content;
				return $this->final_contents;
			}
			foreach( $template_tags[0] as $key=>$tag ) {				
				if ( substr( $tag, 0, 4 ) == '{L_[' ) {
					# Replace the langauge tags without splitting the tag into .. tokens?
					$tmp_view_content = $this->replace_tag( $template_tags[1][ $key ], $tmp_view_content );
				} else {
					$tag_tokens = explode( '.', $template_tags[1][ $key ] );
					if ( count( $tag_tokens ) <= 1 ) {
						$tmp_view_content = $this->replace_tag( $template_tags[1][ $key ], $tmp_view_content );
					} else {
						# Tag is in the format of {FOO.BAR.CAR}
						$tmp_view_content = $this->replace_tag( $tag_tokens, $tmp_view_content );
					}
				}
			}
			$this->final_contents = $tmp_view_content;
			return $this->final_contents;
		}
		
		/**
		 * Replaces a tag in a string, but also checks if that tag is assigned first.
		 * This function allows for an array as the tag, in the case it will then
		 * ... 'Follow' the assigned tags array down the tree until it finds the value
		 * it needs. 
		 *
		 * @param string $tag
		 * @param string $content
		 * @return string
		 */
		private function replace_tag( $tag, $content ) {
			if ( is_array( $tag ) ) {
				#Zula::debug_print( $tag );
				$str_tag = implode( '.', $tag );
				foreach( $tag as $key=>$val ) {
					if ( !isset( $tmp_tag_value ) && isset( $this->assigned_tags[ $val ] ) ) {
						$tmp_tag_value = $this->assigned_tags[ $val ];						
					} else if ( isset( $tmp_tag_value ) ) {
						$val = strtolower( $val );
						if ( isset( $tmp_tag_value[ $val ] ) ) {
							$tmp_tag_value = $tmp_tag_value[ $val ];
						} else {
							Error::report( 'view tag "'.$str_tag.'" could not be replaced for view "'.$this->view_path.'"', 'tag has no assigned value', Error::_WARNING );
							return $content;
						}
					} else {
						Error::report( 'view tag "'.$str_tag.'" could not be replaced for view "'.$this->view_path.'"', 'tag has no assigned value', Error::_WARNING );
						return $content;
					}
				}
				$value = $tmp_tag_value;
				$tag = $str_tag;
			} else if ( $this->is_assigned( $tag ) ) {
				$value = $this->assigned_tags[ $tag ];				
			} else {
				Error::report( 'view tag "'.$tag.'" could not be replaced for view "'.$this->view_path.'"', 'tag has no assigned value', Error::_WARNING );
				return $content;
			}
			if ( is_array( $value ) ) {
				Error::report( 'view tag "'.$tag.'" has invalid assigned value', 'tag wants to get replaced with an array', Error::_WARNING );
				return $content;
			} else {
				return str_replace( '{'.$tag.'}', $value, $content );
			}
		}
		
		/**
		 * Provides the Zula Framework with Language Support for View Files
		 * It searches the view file via reg-ex to find all tags that in the format
		 * of {L_[Phrase]} and fills a new array which each of the new tags and langauge string
		 * It also updates the text domain to the current module, if we have one set.
		 * then resets it back afterwards
		 *
		 * @param string $content
		 * @return array
		 */
		private function language_tags( $content ) {
			/*locale = Registry::get( 'locale' );*/
			if ( !empty( $this->module ) ) {
				/*$locale->update_text_domain( 'messages', Zula::get_dir( 'controllers' ).'/'.$this->module.'/locale' ); */
			}
			preg_match_all( '@{L_\[(.[^\]]*)]}@', $content, $tags);			
			if ( !empty( $tags[0] ) ) {	
				$language_tags = array();
				foreach( $tags[0] as $key=>$tag ) {
					$tag = trim( $tag, '{} ' );					
					#$value = $tags[1][ $key ];
					/*$value = $locale->translate( $tags[1][ $key ] );*/
					/*$language_tags[ $tag ] = $value;*/				
				}
				/*$locale->update_text_domain();*/
				return $language_tags;				
			} else {
				return array();
			}
		}
		
		/**
		 * Provides some common, default tags that can be used in every view file
		 * 
		 * @return bool
		 */
		private function assign_default_tags() {
			$settings = Registry::get( 'settings' );
			$default_tags = array(								
									'TCM_DIR_THEME' 		=> Zula::get_dir( 'themes', true ),
									'TCM_DIR_BASE' 			=> Zula::get_base_dir(),
									'TCM_META_KEYWORDS' 	=> $settings->get( 'meta/keywords' ),
									'TCM_META_DESCRIPTION' 	=> $settings->get( 'meta/description' ),
									'TCM_URL_ADMIN' 		=> Router::make_url( null, null, null, 'admin' ),
									'TCM_SITE_TITLE' 		=> $settings->get( 'config/title' ),
									);
			return $this->assign( $default_tags );
		}		
		
	}

?>