Yii Framework Forum: Layout extension - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Layout extension Rate Topic: -----

#1 User is offline   jayrulez 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 348
  • Joined: 29-July 09

Posted 07 August 2010 - 01:43 PM

Layout.php
<?php

class Layout
{
	private static $_instance;
	private static $_regions = array();
	private static $_blocks = array();
	
	public function __construct()
	{
	}
	
	public function init()
	{
	}
	
	public static function getInstance()
	{
		if(self::$_instance === null)
			self::$_instance = new self;
		return self::$_instance;
	}
	
	public static function hasRegion($regionId)
	{
		$clips = Yii::app()->controller->clips;
		if($clips->contains($regionId))
		{
			if(!empty($clips[$regionId]))
				return true;
		}
		return false;
	}
	
	public function hasRegions($regionIds=array())
	{
		foreach($regionIds as $regionId)
		{
			if(!self::hasRegion($regionId))
				return false;
		}
		return true;
	}
	
	public static function getRegionBlocks($regionId)
	{
		$blocks = array();
		
		$clips = Yii::app()->controller->clips;
		
		if($clips->contains($regionId))
		{
			foreach($clips[$regionId] as $blockId => $content)
				$blocks[$blockId] = $content;
		}
		//asort($blocks);
		return $blocks;
	}
	
	public static function renderRegion($regionId)
	{
		if(self::hasRegion($regionId))
		{
			$blocks = self::getRegionBlocks($regionId);
			
			if(is_array($blocks))
			{
				self::renderRecursive($blocks);
			}
		}
	}	
	
	public static function renderRecursive($blocks)
	{
		if(is_array($blocks))
		{
			foreach($blocks as $blockId => $content)
			{
				if(is_array($content))
					self::renderRecursive($content);
				else if(is_string($content))
				{
					echo $content;
				}
			}
		}else if(is_string($blocks))
		{
			echo $blocks;
		}
	}
	
	public static function openBodyTag()
	{
		$htmlOptions = array();
		if(self::hasRegions(array('sidebar.left','sidebar.right')))
			$htmlOptions['class'] = 'sidebars';
		else if(self::hasRegion('sidebar.left'))
			$htmlOptions['class'] = 'sidebar-left';
		else if(self::hasRegion('sidebar.right'))
			$htmlOptions['class'] = 'sidebar-right';
		return CHtml::openTag('body', $htmlOptions);
	}
	
	public static function addBlock($regionId, $blockId, $content)
	{
		$clips = Yii::app()->controller->clips;
		
		if($clips->contains($regionId))
		{
			$newClips = array();
			foreach($clips[$regionId] as $key => $clip)
			{
				$newClips[$key] = $clip;
			}
			$newClips[$blockId] = $content;
			$clips[$regionId] = $newClips;
		}else{
			$clips[$regionId] = array(
				$blockId => $content,
			);
		}
	}
	
	public static function addBlocks($regionId, $blocks = array())
	{
		if(is_array($blocks))
		{
			foreach($blocks as $blockId => $content)
			{
				self::addBlock($regionId, $blockId, $content);
			}
		}
	}
	
	public static function removeRegion($regionId)
	{
		$clips = Yii::app()->controller->clips;
		
		if($clips->contains($regionId))
			$clips->remove($regionId);
	}
	
	public static function hasBlock($regionId, $blockId)
	{
		$blocks = self::getRegionBlocks($regionId);
		return array_key_exists($blockId, $blocks);
	}
	
	public static function removeBlock($regionId, $blockId)
	{
		$clips = Yii::app()->controller->clips;
		
		if($clips->contains($regionId))
		{
			$blocks = $clips[$regionId];
			foreach($block as $key => $value)
			{
				if($key == $blockId)
					unset($blocks[$key]);
			}
			Yii::app()->controller->clips[$regionId] = $blocks;
		}
	}
}


example usage: layout file,main.php

<?php
$app = Yii::app();
Layout::addBlock('header.content','main',$this->widget('core.widgets.HeaderWidget', array(), true));
Layout::addBlock('footer.content','main',$this->widget('core.widgets.FooterWidget', array(), true));
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $app->locale->getId(); ?>" dir="<?php echo $app->locale->getOrientation(); ?>">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $app->charset; ?>" />
<meta name="language" content="<?php echo $app->locale->getId(); ?>" />
<script type="text/javascript">
	var baseUrl = '<?php echo $app->getBaseUrl(true); ?>';
</script>
<link rel="stylesheet" type="text/css" href="<?php echo $app->getBaseUrl(); ?>/css/layout.css" />
<title><?php echo CHtml::encode($this->pageTitle); ?></title>
<!--[if lt IE 8]>
<link rel="stylesheet" type="text/css" href="<?php echo $app->getBaseUrl(); ?>/css/ie.css" />
<![endif]-->
</head>

<?php echo Layout::openBodyTag(); ?>
	<div id="page-container">
		<div id="page">
		
			<!-- header container -->
			<div id="header-container">
				<div id="header">
					<?php if(Layout::hasRegion('header.top')): ?>
						<div id="header-top">
							<?php Layout::renderRegion('header.top'); ?>
						</div>
					<?php endif; ?>
					<div id="header-content">
						<?php Layout::renderRegion('header.content'); ?>
					</div>
					<?php if(Layout::hasRegion('header.bottom')): ?>
						<div id="header-bottom">
							<?php Layout::renderRegion('header.bottom'); ?>
						</div>
					<?php endif; ?>
				</div>
			</div>
			<!-- /header-container -->
			
			<!-- content-container -->
			<div id="content-container">
				<div id="content">
					<?php if(Layout::hasRegion('content.top')): ?>
						<div id="content-top">
							<?php Layout::renderRegion('content.top'); ?>
						</div>
					<?php endif?>
					<div id="content-inner">
					
						<?php if(Layout::hasRegion('sidebar.left')): ?>
						<!-- sidebar-left -->
						<div id="sidebar-left" class="sidebar">
							<div class="sidebar-content">
								<?php Layout::renderRegion('sidebar.left'); ?>
							</div>
						</div>
						<!-- /sidebar-left -->
						<?php endif; ?>
						
						<!-- canvas -->
						<div id="canvas">
							<?php if(Layout::hasRegion('canvas.top')): ?>
							<div id="canvas-top">
								<?php Layout::renderRegion('canvas.top'); ?>
							</div>
							<?php endif; ?>
							<div id="canvas-content">
								<?php echo $content; ?>
							</div>
							<?php if(Layout::hasRegion('canvas.bottom')): ?>
							<div id="canvas-bottom">
								<?php Layout::renderRegion('canvas.bottom'); ?>
							</div>
							<?php endif; ?>
						</div>
						<!-- /canvas -->
						
						<?php if(Layout::hasRegion('sidebar.right')): ?>
						<!-- sidebar-right -->
						<div id="sidebar-right" class="sidebar">
							<div class="sidebar-content">
								<?php Layout::renderRegion('sidebar.right'); ?>
							</div>
						</div>
						<!-- /sidebar-right -->
						<?php endif; ?>
						
					</div>
					<?php if(Layout::hasRegion('content.bottom')): ?>
						<div id="content-bottom">
							<?php Layout::renderRegion('content.bottom'); ?>
						</div>
					<?php endif; ?>
				</div>
			</div>
			<!-- /content-container -->
			
			<div id="footer-container">
				<div id="footer">
					<?php if(Layout::hasRegion('footer.top')): ?>
						<div id="footer-top">
							<?php Layout::renderRegion('footer.top'); ?>
						</div>
					<?php endif; ?>
					<div id="footer-content">
						<?php Layout::renderRegion('footer.content'); ?>
					</div>
					<?php if(Layout::hasRegion('footer.bottom')): ?>
						<div id="footer-bottom">
							<?php Layout::renderRegion('footer.bottom'); ?>
						</div>
					<?php endif; ?>
				</div>
			</div>
		</div>
	</div>
</body>
</html>

php:
foreach(array('cat', 'dog', 'cow') as $animal) echo $animal."\n";

python:
[(animal, print(animal)) for animal in ['cat', 'dog', 'cow']]

ruby:
['cat', 'dog', 'cow'].each {|animal| puts animal}


You say Tomato, I say Tomato.
0

#2 User is offline   jayrulez 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 348
  • Joined: 29-July 09

Posted 19 August 2010 - 02:24 AM

Updated Layout Helper. I will add documentation and examples soon.

<?php

class LayoutBlock
{
	private $_id;
	private $_content;
	private $_weight;
	private $_visible;
	private $_htmlOptions = array();
	private $_tagName;
	
	private $_defaultHtmlOptions = array(
		'class'=>'block',
	);
	
	const DEFAULT_BLOCK_TAG = 'div';
	
	public function __construct($id, $content, $weight = 0, $visible = true, $htmlOptions = array(), $tagName = self::DEFAULT_BLOCK_TAG)
	{
		$this->_id          = $id;
		$this->setContent($content);
		$this->setWeight($weight);
		$this->setVisible($visible);
		$this->setHtmlOptions($htmlOptions);
		$this->setTagName($tagName);
	}
	
	public function getId()
	{
		return $this->_id;
	}
	
	public function getContent()
	{
		return $this->_content;
	}
	
	public function getWeight()
	{
		return $this->_weight;
	}
	
	public function getVisible()
	{
		return $this->_visible;
	}
	
	public function getTagName()
	{
		return $this->_tagName;
	}
	
	public function setId($id)
	{
		if(is_string($id))
		{
			throw new CException(Util::t('The block id must be a string.'));
		}
		$this->_id = $id;
		return $this;
	}
	
	public function setContent($content)
	{
		if(!is_string($content))
		{
			throw new CException(Util::t('The block content must be a string.'));
		}
		$this->_content = $content;
		return $this;
	}
	
	public function setWeight($weight)
	{
		if(!is_numeric($weight))
		{
			throw new CException(Util::t('The block weight must be a number.'));
		}
		$this->_weight = (int)$weight;
		return $this;
	}
	
	public function setHtmlOptions($htmlOptions, $mergeOld = false)
	{
		if(!is_array($htmlOptions))
		{
			throw new CException(Util::t('The block html options must be a number.'));
		}
		if($mergeOld)
		{
			$this->_htmlOptions = CMap::mergeArray($this->_htmlOptions, $htmlOptions);
		}else{
			$this->_htmlOptions = $htmlOptions;
		}
		return $this;
	}
	
	public function setTagName($tagName)
	{
		if(!is_string($tagName))
		{
			throw new CException(Util::t('The block tag name must be a string.'));
		}
		$this->_tagName = $tagName;
		return $this;
	}
	
	public function setVisible($visible)
	{
		if(!is_bool($visible))
		{
			throw new CException(Util::t('The block visibility must be set to a boolean value.'));
		}
		$this->_visible = $visible;
		return $this;
	}
	
	public function render($return = false, $renderTag = true)
	{
		$block = $this->_content;
		if($renderTag)
		{
			$block = CHtml::openTag($this->_tagName, CMap::mergeArray($this->_defaultHtmlOptions, $this->_htmlOptions)).$block.CHtml::closeTag($this->_tagName);
		}
		if($return === true)
		{
			return $block;
		}else{
			echo $block;
		}
	}
}

class Layout
{
	private static $_instance;
	
	protected $regions;
	
	public function __construct()
	{
		$this->regions = new CMap;
	}
	
	public static function getInstance()
	{
		if(self::$_instance === null)
		{
			self::$_instance = new self;
		}
		return self::$_instance;
	}
	
	protected static function compareBlocks($blockA, $blockB)
	{
		if($blockA instanceof LayoutBlock && $blockB instanceof LayoutBlock)
		{
			if($blockA->getWeight() === $blockB->getWeight())
			{
				return 0;
			}
			return ($blockA->getWeight() <= $blockB->getWeight()) ? -1 : 1;
		}else{
			throw new CException(Util::t('Both blocks must be instances of LayoutBlock or one of it\'s children.'));
		}
	}
	
	protected static function sortBlocks($blocks)
	{		
		$blocks = $blocks->toArray();
		
		uasort($blocks, array(__CLASS__,'compareBlocks'));
		
		return new CMap($blocks);
	}
	
	public function getBlocks($regionId, $visibleOnly = true)
	{
		$instance = self::getInstance();
		
		$blocks   = new CMap;
		
		if($instance->regions->contains($regionId))
		{			
			foreach($instance->regions[$regionId] as $blockId => $block)
			{
				if($visibleOnly)
				{
					if($block->getVisible() === false)
					{
						continue;
					}
				}
				$blocks->add($blockId, $block);
			}
		}
		
		return self::sortBlocks($blocks);
	}
	
	public static function addBlock($regionId, $blockData)
	{
		if(isset($blockData['id']))
		{
			$instance    = self::getInstance();
			
			$blockId     = $blockData['id'];
			$content     = $blockData['content'];
			
			$weight      = isset($blockData['weight'])      ? $blockData['weight']      : 0;
			$visible     = isset($blockData['visible'])     ? $blockData['visible']     : true;
			$htmlOptions = isset($blockData['htmlOptions']) ? $blockData['htmlOptions'] : array();
			$tagName     = isset($blockData['tagName'])     ? $blockData['tagName']     : LayoutBlock::DEFAULT_BLOCK_TAG;
			
			$block       = new LayoutBlock($blockId, $content, $weight, $visible, $htmlOptions);
			
			if(!$instance->regions->contains($regionId))
			{
				$instance->regions[$regionId] = new CMap;
			}
			$instance->regions[$regionId]->add($blockId, $block);
		}else{
			throw new CException(Util::t('A block must have at least an id.'));
		}
	}
	
	public static function addBlocks($blocks = array())
	{
		foreach($blocks as $blockData)
		{
			if(isset($blockData['regionId']))
			{
				$regionId = $blockData['regionId'];
				unset($blockData['regionId']);
				self::addBlock($regionId, $blockData);
			}
		}
	}
	
	public static function getBlock($regionId, $blockId)
	{
		$instance = self::getInstance();
		if(($region = self::getRegion($regionId)) !== null)
		{
			if($region->contains($blockId))
			{
				return $region[$blockId];
			}
		}
		return null;
	}
	
	public static function hasBlock($regionId, $blockId)
	{
		return self::getBlock($regionId, $blockId) !== null;
	}
	
	public static function removeBlock($regionId, $blockId)
	{
		if(($region = self::getRegion($regionId)) !== null)
		{
			if($region->contains($blockId))
			{
				$region->remove($blockId);
			}
		}
	}
	
	public static function getRegion($regionId)
	{
		$instance = self::getInstance();
		return $instance->regions->contains($regionId) ? $instance->regions[$regionId] : null;
	}
	
	public static function hasRegion($regionId)
	{
		return self::getRegion($regionId) !== null;
	}
	
	public static function hasRegions()
	{
		$args = func_get_args();
		if(count($args))
		{
			foreach($args as $regionId)
			{
				if(!self::hasRegion($regionId))
				{
					return false;
				}
			}
			return true;
		}
		throw new CException(Util::t('No region id was specified.'));
	}
	
	public static function renderRegion($regionId, $return = false)
	{
		$regionContent = '';
		
		if(self::hasRegion($regionId))
		{
			$blocks = self::getBlocks($regionId);
			
			foreach($blocks as $block)
			{
				if($block instanceof LayoutBlock)
				{
					$regionContent .= $block->render(true);
				}
			}
		}
		
		if($return)
		{
			return $regionContent;
		}else{
			echo $regionContent;
		}
	}
	
	public static function removeRegion($regionId)
	{
		$instance = self::getInstance();
		
		if($instance->regions->contains($regionId))
		{
			$instance->regions->remove($regionId);
		}
	}
}

php:
foreach(array('cat', 'dog', 'cow') as $animal) echo $animal."\n";

python:
[(animal, print(animal)) for animal in ['cat', 'dog', 'cow']]

ruby:
['cat', 'dog', 'cow'].each {|animal| puts animal}


You say Tomato, I say Tomato.
0

#3 User is offline   sebastian dm 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 31-October 10

Posted 14 November 2010 - 11:12 AM

great work!
0

#4 User is offline   jacmoe 

  • Elite Member
  • Yii
  • Group: Moderators
  • Posts: 2,601
  • Joined: 10-October 10
  • Location:Denmark

Posted 14 November 2010 - 11:38 AM

View Postjayrulez, on 19 August 2010 - 02:24 AM, said:

Updated Layout Helper. I will add documentation and examples soon.

That would be lovely! :)
"Less noise - more signal"
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users