CBaseListView.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <?php
  2. /**
  3. * CBaseListView class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CBaseListView is the base class for {@link CListView} and {@link CGridView}.
  12. *
  13. * CBaseListView implements the common features needed by a view wiget for rendering multiple models.
  14. *
  15. * @author Qiang Xue <qiang.xue@gmail.com>
  16. * @package zii.widgets
  17. * @since 1.1
  18. */
  19. abstract class CBaseListView extends CWidget
  20. {
  21. /**
  22. * @var IDataProvider the data provider for the view.
  23. */
  24. public $dataProvider;
  25. /**
  26. * @var string the tag name for the view container. Defaults to 'div'.
  27. */
  28. public $tagName='div';
  29. /**
  30. * @var array the HTML options for the view container tag.
  31. */
  32. public $htmlOptions=array();
  33. /**
  34. * @var boolean whether to enable sorting. Note that if the {@link IDataProvider::sort} property
  35. * of {@link dataProvider} is false, this will be treated as false as well. When sorting is enabled,
  36. * sortable columns will have their headers clickable to trigger sorting along that column.
  37. * Defaults to true.
  38. * @see sortableAttributes
  39. */
  40. public $enableSorting=true;
  41. /**
  42. * @var boolean whether to enable pagination. Note that if the {@link IDataProvider::pagination} property
  43. * of {@link dataProvider} is false, this will be treated as false as well. When pagination is enabled,
  44. * a pager will be displayed in the view so that it can trigger pagination of the data display.
  45. * Defaults to true.
  46. */
  47. public $enablePagination=true;
  48. /**
  49. * @var array|string the configuration for the pager. Defaults to <code>array('class'=>'CLinkPager')</code>.
  50. * String value will be treated as the class name of the pager (<code>'ClassName'</code> value is similar
  51. * to the <code>array('class'=>'ClassName')</code> value). See {@link CBasePager} and {@link CLinkPager}
  52. * for more details about pager configuration array values.
  53. * @see enablePagination
  54. */
  55. public $pager=array('class'=>'CLinkPager');
  56. /**
  57. * @var string the template to be used to control the layout of various sections in the view.
  58. * These tokens are recognized: {summary}, {items} and {pager}. They will be replaced with the
  59. * summary text, the items, and the pager.
  60. */
  61. public $template="{summary}\n{items}\n{pager}";
  62. /**
  63. * @var string the summary text template for the view. These tokens are recognized and will be replaced
  64. * with the corresponding values:
  65. * <ul>
  66. * <li>{start}: the starting row number (1-based) currently being displayed</li>
  67. * <li>{end}: the ending row number (1-based) currently being displayed</li>
  68. * <li>{count}: the total number of rows</li>
  69. * <li>{page}: the page number (1-based) current being displayed, available since version 1.1.3</li>
  70. * <li>{pages}: the total number of pages, available since version 1.1.3</li>
  71. * </ul>
  72. */
  73. public $summaryText;
  74. /**
  75. * @var string the message to be displayed when {@link dataProvider} does not have any data.
  76. */
  77. public $emptyText;
  78. /**
  79. * @var string the HTML tag name for the container of the {@link emptyText} property.
  80. */
  81. public $emptyTagName='span';
  82. /**
  83. * @var string the CSS class name for the container of all data item display. Defaults to 'items'.
  84. */
  85. public $itemsCssClass='items';
  86. /**
  87. * @var string the CSS class name for the summary text container. Defaults to 'summary'.
  88. */
  89. public $summaryCssClass='summary';
  90. /**
  91. * @var string the CSS class name for the pager container. Defaults to 'pager'.
  92. */
  93. public $pagerCssClass='pager';
  94. /**
  95. * @var string the CSS class name that will be assigned to the widget container element
  96. * when the widget is updating its content via AJAX. Defaults to 'loading'.
  97. * @since 1.1.1
  98. */
  99. public $loadingCssClass='loading';
  100. /**
  101. * Initializes the view.
  102. * This method will initialize required property values and instantiate {@link columns} objects.
  103. */
  104. public function init()
  105. {
  106. if($this->dataProvider===null)
  107. throw new CException(Yii::t('zii','The "dataProvider" property cannot be empty.'));
  108. $this->dataProvider->getData();
  109. if(isset($this->htmlOptions['id']))
  110. $this->id=$this->htmlOptions['id'];
  111. else
  112. $this->htmlOptions['id']=$this->id;
  113. if($this->enableSorting && $this->dataProvider->getSort()===false)
  114. $this->enableSorting=false;
  115. if($this->enablePagination && $this->dataProvider->getPagination()===false)
  116. $this->enablePagination=false;
  117. }
  118. /**
  119. * Renders the view.
  120. * This is the main entry of the whole view rendering.
  121. * Child classes should mainly override {@link renderContent} method.
  122. */
  123. public function run()
  124. {
  125. $this->registerClientScript();
  126. echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
  127. $this->renderContent();
  128. $this->renderKeys();
  129. echo CHtml::closeTag($this->tagName);
  130. }
  131. /**
  132. * Renders the main content of the view.
  133. * The content is divided into sections, such as summary, items, pager.
  134. * Each section is rendered by a method named as "renderXyz", where "Xyz" is the section name.
  135. * The rendering results will replace the corresponding placeholders in {@link template}.
  136. */
  137. public function renderContent()
  138. {
  139. ob_start();
  140. echo preg_replace_callback("/{(\w+)}/",array($this,'renderSection'),$this->template);
  141. ob_end_flush();
  142. }
  143. /**
  144. * Renders a section.
  145. * This method is invoked by {@link renderContent} for every placeholder found in {@link template}.
  146. * It should return the rendering result that would replace the placeholder.
  147. * @param array $matches the matches, where $matches[0] represents the whole placeholder,
  148. * while $matches[1] contains the name of the matched placeholder.
  149. * @return string the rendering result of the section
  150. */
  151. protected function renderSection($matches)
  152. {
  153. $method='render'.$matches[1];
  154. if(method_exists($this,$method))
  155. {
  156. $this->$method();
  157. $html=ob_get_contents();
  158. ob_clean();
  159. return $html;
  160. }
  161. else
  162. return $matches[0];
  163. }
  164. /**
  165. * Renders the empty message when there is no data.
  166. */
  167. public function renderEmptyText()
  168. {
  169. $emptyText=$this->emptyText===null ? Yii::t('zii','No results found.') : $this->emptyText;
  170. echo CHtml::tag($this->emptyTagName, array('class'=>'empty'), $emptyText);
  171. }
  172. /**
  173. * Renders the key values of the data in a hidden tag.
  174. */
  175. public function renderKeys()
  176. {
  177. echo CHtml::openTag('div',array(
  178. 'class'=>'keys',
  179. 'style'=>'display:none',
  180. 'title'=>Yii::app()->getRequest()->getUrl(),
  181. ));
  182. foreach($this->dataProvider->getKeys() as $key)
  183. echo "<span>".CHtml::encode($key)."</span>";
  184. echo "</div>\n";
  185. }
  186. /**
  187. * Renders the summary text.
  188. */
  189. public function renderSummary()
  190. {
  191. if(($count=$this->dataProvider->getItemCount())<=0)
  192. return;
  193. echo '<div class="'.$this->summaryCssClass.'">';
  194. if($this->enablePagination)
  195. {
  196. $pagination=$this->dataProvider->getPagination();
  197. $total=$this->dataProvider->getTotalItemCount();
  198. $start=$pagination->currentPage*$pagination->pageSize+1;
  199. $end=$start+$count-1;
  200. if($end>$total)
  201. {
  202. $end=$total;
  203. $start=$end-$count+1;
  204. }
  205. if(($summaryText=$this->summaryText)===null)
  206. $summaryText=Yii::t('zii','Displaying {start}-{end} of 1 result.|Displaying {start}-{end} of {count} results.',$total);
  207. echo strtr($summaryText,array(
  208. '{start}'=>$start,
  209. '{end}'=>$end,
  210. '{count}'=>$total,
  211. '{page}'=>$pagination->currentPage+1,
  212. '{pages}'=>$pagination->pageCount,
  213. ));
  214. }
  215. else
  216. {
  217. if(($summaryText=$this->summaryText)===null)
  218. $summaryText=Yii::t('zii','Total 1 result.|Total {count} results.',$count);
  219. echo strtr($summaryText,array(
  220. '{count}'=>$count,
  221. '{start}'=>1,
  222. '{end}'=>$count,
  223. '{page}'=>1,
  224. '{pages}'=>1,
  225. ));
  226. }
  227. echo '</div>';
  228. }
  229. /**
  230. * Renders the pager.
  231. */
  232. public function renderPager()
  233. {
  234. if(!$this->enablePagination)
  235. return;
  236. $pager=array();
  237. $class='CLinkPager';
  238. if(is_string($this->pager))
  239. $class=$this->pager;
  240. elseif(is_array($this->pager))
  241. {
  242. $pager=$this->pager;
  243. if(isset($pager['class']))
  244. {
  245. $class=$pager['class'];
  246. unset($pager['class']);
  247. }
  248. }
  249. $pager['pages']=$this->dataProvider->getPagination();
  250. if($pager['pages']->getPageCount()>1)
  251. {
  252. echo '<div class="'.$this->pagerCssClass.'">';
  253. $this->widget($class,$pager);
  254. echo '</div>';
  255. }
  256. else
  257. $this->widget($class,$pager);
  258. }
  259. /**
  260. * Registers necessary client scripts.
  261. * This method is invoked by {@link run}.
  262. * Child classes may override this method to register customized client scripts.
  263. */
  264. public function registerClientScript()
  265. {
  266. }
  267. /**
  268. * Renders the data items for the view.
  269. * Each item is corresponding to a single data model instance.
  270. * Child classes should override this method to provide the actual item rendering logic.
  271. */
  272. abstract public function renderItems();
  273. }