294 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			294 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * CBaseListView class file.
 | |
|  *
 | |
|  * @author Qiang Xue <qiang.xue@gmail.com>
 | |
|  * @link http://www.yiiframework.com/
 | |
|  * @copyright 2008-2013 Yii Software LLC
 | |
|  * @license http://www.yiiframework.com/license/
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * CBaseListView is the base class for {@link CListView} and {@link CGridView}.
 | |
|  *
 | |
|  * CBaseListView implements the common features needed by a view wiget for rendering multiple models.
 | |
|  *
 | |
|  * @author Qiang Xue <qiang.xue@gmail.com>
 | |
|  * @package zii.widgets
 | |
|  * @since 1.1
 | |
|  */
 | |
| abstract class CBaseListView extends CWidget
 | |
| {
 | |
| 	/**
 | |
| 	 * @var IDataProvider the data provider for the view.
 | |
| 	 */
 | |
| 	public $dataProvider;
 | |
| 	/**
 | |
| 	 * @var string the tag name for the view container. Defaults to 'div'.
 | |
| 	 */
 | |
| 	public $tagName='div';
 | |
| 	/**
 | |
| 	 * @var array the HTML options for the view container tag.
 | |
| 	 */
 | |
| 	public $htmlOptions=array();
 | |
| 	/**
 | |
| 	 * @var boolean whether to enable sorting. Note that if the {@link IDataProvider::sort} property
 | |
| 	 * of {@link dataProvider} is false, this will be treated as false as well. When sorting is enabled,
 | |
| 	 * sortable columns will have their headers clickable to trigger sorting along that column.
 | |
| 	 * Defaults to true.
 | |
| 	 * @see sortableAttributes
 | |
| 	 */
 | |
| 	public $enableSorting=true;
 | |
| 	/**
 | |
| 	 * @var boolean whether to enable pagination. Note that if the {@link IDataProvider::pagination} property
 | |
| 	 * of {@link dataProvider} is false, this will be treated as false as well. When pagination is enabled,
 | |
| 	 * a pager will be displayed in the view so that it can trigger pagination of the data display.
 | |
| 	 * Defaults to true.
 | |
| 	 */
 | |
| 	public $enablePagination=true;
 | |
| 	/**
 | |
| 	 * @var array|string the configuration for the pager. Defaults to <code>array('class'=>'CLinkPager')</code>.
 | |
| 	 * String value will be treated as the class name of the pager (<code>'ClassName'</code> value is similar
 | |
| 	 * to the <code>array('class'=>'ClassName')</code> value). See {@link CBasePager} and {@link CLinkPager}
 | |
| 	 * for more details about pager configuration array values.
 | |
| 	 * @see enablePagination
 | |
| 	 */
 | |
| 	public $pager=array('class'=>'CLinkPager');
 | |
| 	/**
 | |
| 	 * @var string the template to be used to control the layout of various sections in the view.
 | |
| 	 * These tokens are recognized: {summary}, {items} and {pager}. They will be replaced with the
 | |
| 	 * summary text, the items, and the pager.
 | |
| 	 */
 | |
| 	public $template="{summary}\n{items}\n{pager}";
 | |
| 	/**
 | |
| 	 * @var string the summary text template for the view. These tokens are recognized and will be replaced
 | |
| 	 * with the corresponding values:
 | |
| 	 * <ul>
 | |
| 	 *   <li>{start}: the starting row number (1-based) currently being displayed</li>
 | |
| 	 *   <li>{end}: the ending row number (1-based) currently being displayed</li>
 | |
| 	 *   <li>{count}: the total number of rows</li>
 | |
| 	 *   <li>{page}: the page number (1-based) current being displayed, available since version 1.1.3</li>
 | |
| 	 *   <li>{pages}: the total number of pages, available since version 1.1.3</li>
 | |
| 	 * </ul>
 | |
| 	 */
 | |
| 	public $summaryText;
 | |
| 	/**
 | |
| 	 * @var string the message to be displayed when {@link dataProvider} does not have any data.
 | |
| 	 */
 | |
| 	public $emptyText;
 | |
| 	/**
 | |
| 	 * @var string the HTML tag name for the container of the {@link emptyText} property.
 | |
| 	 */
 | |
| 	public $emptyTagName='span';
 | |
| 	/**
 | |
| 	 * @var string the CSS class name for the container of all data item display. Defaults to 'items'.
 | |
| 	 */
 | |
| 	public $itemsCssClass='items';
 | |
| 	/**
 | |
| 	 * @var string the CSS class name for the summary text container. Defaults to 'summary'.
 | |
| 	 */
 | |
| 	public $summaryCssClass='summary';
 | |
| 	/**
 | |
| 	 * @var string the CSS class name for the pager container. Defaults to 'pager'.
 | |
| 	 */
 | |
| 	public $pagerCssClass='pager';
 | |
| 	/**
 | |
| 	 * @var string the CSS class name that will be assigned to the widget container element
 | |
| 	 * when the widget is updating its content via AJAX. Defaults to 'loading'.
 | |
| 	 * @since 1.1.1
 | |
| 	 */
 | |
| 	public $loadingCssClass='loading';
 | |
| 
 | |
| 	/**
 | |
| 	 * Initializes the view.
 | |
| 	 * This method will initialize required property values and instantiate {@link columns} objects.
 | |
| 	 */
 | |
| 	public function init()
 | |
| 	{
 | |
| 		if($this->dataProvider===null)
 | |
| 			throw new CException(Yii::t('zii','The "dataProvider" property cannot be empty.'));
 | |
| 
 | |
| 		$this->dataProvider->getData();
 | |
| 
 | |
| 		if(isset($this->htmlOptions['id']))
 | |
| 			$this->id=$this->htmlOptions['id'];
 | |
| 		else
 | |
| 			$this->htmlOptions['id']=$this->id;
 | |
| 
 | |
| 		if($this->enableSorting && $this->dataProvider->getSort()===false)
 | |
| 			$this->enableSorting=false;
 | |
| 		if($this->enablePagination && $this->dataProvider->getPagination()===false)
 | |
| 			$this->enablePagination=false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Renders the view.
 | |
| 	 * This is the main entry of the whole view rendering.
 | |
| 	 * Child classes should mainly override {@link renderContent} method.
 | |
| 	 */
 | |
| 	public function run()
 | |
| 	{
 | |
| 		$this->registerClientScript();
 | |
| 
 | |
| 		echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
 | |
| 
 | |
| 		$this->renderContent();
 | |
| 		$this->renderKeys();
 | |
| 
 | |
| 		echo CHtml::closeTag($this->tagName);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Renders the main content of the view.
 | |
| 	 * The content is divided into sections, such as summary, items, pager.
 | |
| 	 * Each section is rendered by a method named as "renderXyz", where "Xyz" is the section name.
 | |
| 	 * The rendering results will replace the corresponding placeholders in {@link template}.
 | |
| 	 */
 | |
| 	public function renderContent()
 | |
| 	{
 | |
| 		ob_start();
 | |
| 		echo preg_replace_callback("/{(\w+)}/",array($this,'renderSection'),$this->template);
 | |
| 		ob_end_flush();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Renders a section.
 | |
| 	 * This method is invoked by {@link renderContent} for every placeholder found in {@link template}.
 | |
| 	 * It should return the rendering result that would replace the placeholder.
 | |
| 	 * @param array $matches the matches, where $matches[0] represents the whole placeholder,
 | |
| 	 * while $matches[1] contains the name of the matched placeholder.
 | |
| 	 * @return string the rendering result of the section
 | |
| 	 */
 | |
| 	protected function renderSection($matches)
 | |
| 	{
 | |
| 		$method='render'.$matches[1];
 | |
| 		if(method_exists($this,$method))
 | |
| 		{
 | |
| 			$this->$method();
 | |
| 			$html=ob_get_contents();
 | |
| 			ob_clean();
 | |
| 			return $html;
 | |
| 		}
 | |
| 		else
 | |
| 			return $matches[0];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Renders the empty message when there is no data.
 | |
| 	 */
 | |
| 	public function renderEmptyText()
 | |
| 	{
 | |
| 		$emptyText=$this->emptyText===null ? Yii::t('zii','No results found.') : $this->emptyText;
 | |
| 		echo CHtml::tag($this->emptyTagName, array('class'=>'empty'), $emptyText);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Renders the key values of the data in a hidden tag.
 | |
| 	 */
 | |
| 	public function renderKeys()
 | |
| 	{
 | |
| 		echo CHtml::openTag('div',array(
 | |
| 			'class'=>'keys',
 | |
| 			'style'=>'display:none',
 | |
| 			'title'=>Yii::app()->getRequest()->getUrl(),
 | |
| 		));
 | |
| 		foreach($this->dataProvider->getKeys() as $key)
 | |
| 			echo "<span>".CHtml::encode($key)."</span>";
 | |
| 		echo "</div>\n";
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Renders the summary text.
 | |
| 	 */
 | |
| 	public function renderSummary()
 | |
| 	{
 | |
| 		if(($count=$this->dataProvider->getItemCount())<=0)
 | |
| 			return;
 | |
| 
 | |
| 		echo '<div class="'.$this->summaryCssClass.'">';
 | |
| 		if($this->enablePagination)
 | |
| 		{
 | |
| 			$pagination=$this->dataProvider->getPagination();
 | |
| 			$total=$this->dataProvider->getTotalItemCount();
 | |
| 			$start=$pagination->currentPage*$pagination->pageSize+1;
 | |
| 			$end=$start+$count-1;
 | |
| 			if($end>$total)
 | |
| 			{
 | |
| 				$end=$total;
 | |
| 				$start=$end-$count+1;
 | |
| 			}
 | |
| 			if(($summaryText=$this->summaryText)===null)
 | |
| 				$summaryText=Yii::t('zii','Displaying {start}-{end} of 1 result.|Displaying {start}-{end} of {count} results.',$total);
 | |
| 			echo strtr($summaryText,array(
 | |
| 				'{start}'=>$start,
 | |
| 				'{end}'=>$end,
 | |
| 				'{count}'=>$total,
 | |
| 				'{page}'=>$pagination->currentPage+1,
 | |
| 				'{pages}'=>$pagination->pageCount,
 | |
| 			));
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			if(($summaryText=$this->summaryText)===null)
 | |
| 				$summaryText=Yii::t('zii','Total 1 result.|Total {count} results.',$count);
 | |
| 			echo strtr($summaryText,array(
 | |
| 				'{count}'=>$count,
 | |
| 				'{start}'=>1,
 | |
| 				'{end}'=>$count,
 | |
| 				'{page}'=>1,
 | |
| 				'{pages}'=>1,
 | |
| 			));
 | |
| 		}
 | |
| 		echo '</div>';
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Renders the pager.
 | |
| 	 */
 | |
| 	public function renderPager()
 | |
| 	{
 | |
| 		if(!$this->enablePagination)
 | |
| 			return;
 | |
| 
 | |
| 		$pager=array();
 | |
| 		$class='CLinkPager';
 | |
| 		if(is_string($this->pager))
 | |
| 			$class=$this->pager;
 | |
| 		elseif(is_array($this->pager))
 | |
| 		{
 | |
| 			$pager=$this->pager;
 | |
| 			if(isset($pager['class']))
 | |
| 			{
 | |
| 				$class=$pager['class'];
 | |
| 				unset($pager['class']);
 | |
| 			}
 | |
| 		}
 | |
| 		$pager['pages']=$this->dataProvider->getPagination();
 | |
| 
 | |
| 		if($pager['pages']->getPageCount()>1)
 | |
| 		{
 | |
| 			echo '<div class="'.$this->pagerCssClass.'">';
 | |
| 			$this->widget($class,$pager);
 | |
| 			echo '</div>';
 | |
| 		}
 | |
| 		else
 | |
| 			$this->widget($class,$pager);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Registers necessary client scripts.
 | |
| 	 * This method is invoked by {@link run}.
 | |
| 	 * Child classes may override this method to register customized client scripts.
 | |
| 	 */
 | |
| 	public function registerClientScript()
 | |
| 	{
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Renders the data items for the view.
 | |
| 	 * Each item is corresponding to a single data model instance.
 | |
| 	 * Child classes should override this method to provide the actual item rendering logic.
 | |
| 	 */
 | |
| 	abstract public function renderItems();
 | |
| }
 |