You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BaseListView.php 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\widgets;
  8. use Yii;
  9. use yii\base\InvalidConfigException;
  10. use yii\base\Widget;
  11. use yii\helpers\ArrayHelper;
  12. use yii\helpers\Html;
  13. /**
  14. * BaseListView is a base class for widgets displaying data from data provider
  15. * such as ListView and GridView.
  16. *
  17. * It provides features like sorting, paging and also filtering the data.
  18. *
  19. * @author Qiang Xue <qiang.xue@gmail.com>
  20. * @since 2.0
  21. */
  22. abstract class BaseListView extends Widget
  23. {
  24. /**
  25. * @var array the HTML attributes for the container tag of the list view.
  26. * The "tag" element specifies the tag name of the container element and defaults to "div".
  27. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
  28. */
  29. public $options = [];
  30. /**
  31. * @var \yii\data\DataProviderInterface the data provider for the view. This property is required.
  32. */
  33. public $dataProvider;
  34. /**
  35. * @var array the configuration for the pager widget. By default, [[LinkPager]] will be
  36. * used to render the pager. You can use a different widget class by configuring the "class" element.
  37. * Note that the widget must support the `pagination` property which will be populated with the `pagination` value
  38. * of [[dataProvider]].
  39. */
  40. public $pager = [];
  41. /**
  42. * @var array the configuration for the sorter widget. By default, [[LinkSorter]] will be
  43. * used to render the sorter. You can use a different widget class by configuring the "class" element.
  44. * Note that the widget must support the `sort` property which will be populated with the `sort` value
  45. * of [[dataProvider]].
  46. */
  47. public $sorter = [];
  48. /**
  49. * @var string the HTML content to be displayed as the summary of the list view.
  50. * If you do not want to show the summary, you may set it with an empty string.
  51. *
  52. * The following tokens will be replaced with the corresponding values:
  53. *
  54. * - `{begin}`: the starting row number (1-based) currently being displayed
  55. * - `{end}`: the ending row number (1-based) currently being displayed
  56. * - `{count}`: the number of rows currently being displayed
  57. * - `{totalCount}`: the total number of rows available
  58. * - `{page}`: the page number (1-based) current being displayed
  59. * - `{pageCount}`: the number of pages available
  60. */
  61. public $summary;
  62. /**
  63. * @var array the HTML attributes for the summary of the list view.
  64. * The "tag" element specifies the tag name of the summary element and defaults to "div".
  65. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
  66. */
  67. public $summaryOptions = ['class' => 'summary'];
  68. /**
  69. * @var boolean whether to show the list view if [[dataProvider]] returns no data.
  70. */
  71. public $showOnEmpty = false;
  72. /**
  73. * @var string the HTML content to be displayed when [[dataProvider]] does not have any data.
  74. */
  75. public $emptyText;
  76. /**
  77. * @var array the HTML attributes for the emptyText of the list view.
  78. * The "tag" element specifies the tag name of the emptyText element and defaults to "div".
  79. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
  80. */
  81. public $emptyTextOptions = ['class' => 'empty'];
  82. /**
  83. * @var string the layout that determines how different sections of the list view should be organized.
  84. * The following tokens will be replaced with the corresponding section contents:
  85. *
  86. * - `{summary}`: the summary section. See [[renderSummary()]].
  87. * - `{items}`: the list items. See [[renderItems()]].
  88. * - `{sorter}`: the sorter. See [[renderSorter()]].
  89. * - `{pager}`: the pager. See [[renderPager()]].
  90. */
  91. public $layout = "{summary}\n{items}\n{pager}";
  92. /**
  93. * Renders the data models.
  94. * @return string the rendering result.
  95. */
  96. abstract public function renderItems();
  97. /**
  98. * Initializes the view.
  99. */
  100. public function init()
  101. {
  102. if ($this->dataProvider === null) {
  103. throw new InvalidConfigException('The "dataProvider" property must be set.');
  104. }
  105. if ($this->emptyText === null) {
  106. $this->emptyText = Yii::t('yii', 'No results found.');
  107. }
  108. if (!isset($this->options['id'])) {
  109. $this->options['id'] = $this->getId();
  110. }
  111. }
  112. /**
  113. * Runs the widget.
  114. */
  115. public function run()
  116. {
  117. if ($this->showOnEmpty || $this->dataProvider->getCount() > 0) {
  118. $content = preg_replace_callback("/{\\w+}/", function ($matches) {
  119. $content = $this->renderSection($matches[0]);
  120. return $content === false ? $matches[0] : $content;
  121. }, $this->layout);
  122. } else {
  123. $content = $this->renderEmpty();
  124. }
  125. $tag = ArrayHelper::remove($this->options, 'tag', 'div');
  126. echo Html::tag($tag, $content, $this->options);
  127. }
  128. /**
  129. * Renders a section of the specified name.
  130. * If the named section is not supported, false will be returned.
  131. * @param string $name the section name, e.g., `{summary}`, `{items}`.
  132. * @return string|boolean the rendering result of the section, or false if the named section is not supported.
  133. */
  134. public function renderSection($name)
  135. {
  136. switch ($name) {
  137. case '{summary}':
  138. return $this->renderSummary();
  139. case '{items}':
  140. return $this->renderItems();
  141. case '{pager}':
  142. return $this->renderPager();
  143. case '{sorter}':
  144. return $this->renderSorter();
  145. default:
  146. return false;
  147. }
  148. }
  149. /**
  150. * Renders the HTML content indicating that the list view has no data.
  151. * @return string the rendering result
  152. * @see emptyText
  153. */
  154. public function renderEmpty()
  155. {
  156. $tag = ArrayHelper::remove($this->emptyTextOptions, 'tag', 'div');
  157. return Html::tag($tag, ($this->emptyText === null ? Yii::t('yii', 'No results found.') : $this->emptyText), $this->emptyTextOptions);
  158. }
  159. /**
  160. * Renders the summary text.
  161. */
  162. public function renderSummary()
  163. {
  164. $count = $this->dataProvider->getCount();
  165. if ($count <= 0) {
  166. return '';
  167. }
  168. $tag = ArrayHelper::remove($this->summaryOptions, 'tag', 'div');
  169. if (($pagination = $this->dataProvider->getPagination()) !== false) {
  170. $totalCount = $this->dataProvider->getTotalCount();
  171. $begin = $pagination->getPage() * $pagination->pageSize + 1;
  172. $end = $begin + $count - 1;
  173. if ($begin > $end) {
  174. $begin = $end;
  175. }
  176. $page = $pagination->getPage() + 1;
  177. $pageCount = $pagination->pageCount;
  178. if (($summaryContent = $this->summary) === null) {
  179. return Html::tag($tag, Yii::t('yii', 'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.', [
  180. 'begin' => $begin,
  181. 'end' => $end,
  182. 'count' => $count,
  183. 'totalCount' => $totalCount,
  184. 'page' => $page,
  185. 'pageCount' => $pageCount,
  186. ]), $this->summaryOptions);
  187. }
  188. } else {
  189. $begin = $page = $pageCount = 1;
  190. $end = $totalCount = $count;
  191. if (($summaryContent = $this->summary) === null) {
  192. return Html::tag($tag, Yii::t('yii', 'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.', [
  193. 'begin' => $begin,
  194. 'end' => $end,
  195. 'count' => $count,
  196. 'totalCount' => $totalCount,
  197. 'page' => $page,
  198. 'pageCount' => $pageCount,
  199. ]), $this->summaryOptions);
  200. }
  201. }
  202. return Yii::$app->getI18n()->format($summaryContent, [
  203. 'begin' => $begin,
  204. 'end' => $end,
  205. 'count' => $count,
  206. 'totalCount' => $totalCount,
  207. 'page' => $page,
  208. 'pageCount' => $pageCount,
  209. ], Yii::$app->language);
  210. }
  211. /**
  212. * Renders the pager.
  213. * @return string the rendering result
  214. */
  215. public function renderPager()
  216. {
  217. $pagination = $this->dataProvider->getPagination();
  218. if ($pagination === false || $this->dataProvider->getCount() <= 0) {
  219. return '';
  220. }
  221. /* @var $class LinkPager */
  222. $pager = $this->pager;
  223. $class = ArrayHelper::remove($pager, 'class', LinkPager::className());
  224. $pager['pagination'] = $pagination;
  225. $pager['view'] = $this->getView();
  226. return $class::widget($pager);
  227. }
  228. /**
  229. * Renders the sorter.
  230. * @return string the rendering result
  231. */
  232. public function renderSorter()
  233. {
  234. $sort = $this->dataProvider->getSort();
  235. if ($sort === false || empty($sort->attributes) || $this->dataProvider->getCount() <= 0) {
  236. return '';
  237. }
  238. /* @var $class LinkSorter */
  239. $sorter = $this->sorter;
  240. $class = ArrayHelper::remove($sorter, 'class', LinkSorter::className());
  241. $sorter['sort'] = $sort;
  242. $sorter['view'] = $this->getView();
  243. return $class::widget($sorter);
  244. }
  245. }