BaseListView.php 9.8 KB

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