BaseListView.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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|false the HTML content to be displayed when [[dataProvider]] does not have any data.
  78. * When this is set to `false` no extra HTML content will be generated.
  79. * The default value is the text "No results found." which will be translated to the current application language.
  80. * @see showOnEmpty
  81. * @see emptyTextOptions
  82. */
  83. public $emptyText;
  84. /**
  85. * @var array the HTML attributes for the emptyText of the list view.
  86. * The "tag" element specifies the tag name of the emptyText element and defaults to "div".
  87. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
  88. */
  89. public $emptyTextOptions = ['class' => 'empty'];
  90. /**
  91. * @var string the layout that determines how different sections of the list view should be organized.
  92. * The following tokens will be replaced with the corresponding section contents:
  93. *
  94. * - `{summary}`: the summary section. See [[renderSummary()]].
  95. * - `{items}`: the list items. See [[renderItems()]].
  96. * - `{sorter}`: the sorter. See [[renderSorter()]].
  97. * - `{pager}`: the pager. See [[renderPager()]].
  98. */
  99. public $layout = "{summary}\n{items}\n{pager}";
  100. /**
  101. * Renders the data models.
  102. * @return string the rendering result.
  103. */
  104. abstract public function renderItems();
  105. /**
  106. * Initializes the view.
  107. */
  108. public function init()
  109. {
  110. if ($this->dataProvider === null) {
  111. throw new InvalidConfigException('The "dataProvider" property must be set.');
  112. }
  113. if ($this->emptyText === null) {
  114. $this->emptyText = Yii::t('yii', 'No results found.');
  115. }
  116. if (!isset($this->options['id'])) {
  117. $this->options['id'] = $this->getId();
  118. }
  119. }
  120. /**
  121. * Runs the widget.
  122. */
  123. public function run()
  124. {
  125. if ($this->showOnEmpty || $this->dataProvider->getCount() > 0) {
  126. $content = preg_replace_callback("/{\\w+}/", function ($matches) {
  127. $content = $this->renderSection($matches[0]);
  128. return $content === false ? $matches[0] : $content;
  129. }, $this->layout);
  130. } else {
  131. $content = $this->renderEmpty();
  132. }
  133. $options = $this->options;
  134. $tag = ArrayHelper::remove($options, 'tag', 'div');
  135. echo Html::tag($tag, $content, $options);
  136. }
  137. /**
  138. * Renders a section of the specified name.
  139. * If the named section is not supported, false will be returned.
  140. * @param string $name the section name, e.g., `{summary}`, `{items}`.
  141. * @return string|bool the rendering result of the section, or false if the named section is not supported.
  142. */
  143. public function renderSection($name)
  144. {
  145. switch ($name) {
  146. case '{summary}':
  147. return $this->renderSummary();
  148. case '{items}':
  149. return $this->renderItems();
  150. case '{pager}':
  151. return $this->renderPager();
  152. case '{sorter}':
  153. return $this->renderSorter();
  154. default:
  155. return false;
  156. }
  157. }
  158. /**
  159. * Renders the HTML content indicating that the list view has no data.
  160. * @return string the rendering result
  161. * @see emptyText
  162. */
  163. public function renderEmpty()
  164. {
  165. if ($this->emptyText === false) {
  166. return '';
  167. }
  168. $options = $this->emptyTextOptions;
  169. $tag = ArrayHelper::remove($options, 'tag', 'div');
  170. return Html::tag($tag, $this->emptyText, $options);
  171. }
  172. /**
  173. * Renders the summary text.
  174. */
  175. public function renderSummary()
  176. {
  177. $count = $this->dataProvider->getCount();
  178. if ($count <= 0) {
  179. return '';
  180. }
  181. $summaryOptions = $this->summaryOptions;
  182. $tag = ArrayHelper::remove($summaryOptions, 'tag', 'div');
  183. if (($pagination = $this->dataProvider->getPagination()) !== false) {
  184. $totalCount = $this->dataProvider->getTotalCount();
  185. $begin = $pagination->getPage() * $pagination->pageSize + 1;
  186. $end = $begin + $count - 1;
  187. if ($begin > $end) {
  188. $begin = $end;
  189. }
  190. $page = $pagination->getPage() + 1;
  191. $pageCount = $pagination->pageCount;
  192. if (($summaryContent = $this->summary) === null) {
  193. 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}}.', [
  194. 'begin' => $begin,
  195. 'end' => $end,
  196. 'count' => $count,
  197. 'totalCount' => $totalCount,
  198. 'page' => $page,
  199. 'pageCount' => $pageCount,
  200. ]), $summaryOptions);
  201. }
  202. } else {
  203. $begin = $page = $pageCount = 1;
  204. $end = $totalCount = $count;
  205. if (($summaryContent = $this->summary) === null) {
  206. return Html::tag($tag, Yii::t('yii', 'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.', [
  207. 'begin' => $begin,
  208. 'end' => $end,
  209. 'count' => $count,
  210. 'totalCount' => $totalCount,
  211. 'page' => $page,
  212. 'pageCount' => $pageCount,
  213. ]), $summaryOptions);
  214. }
  215. }
  216. return Yii::$app->getI18n()->format($summaryContent, [
  217. 'begin' => $begin,
  218. 'end' => $end,
  219. 'count' => $count,
  220. 'totalCount' => $totalCount,
  221. 'page' => $page,
  222. 'pageCount' => $pageCount,
  223. ], Yii::$app->language);
  224. }
  225. /**
  226. * Renders the pager.
  227. * @return string the rendering result
  228. */
  229. public function renderPager()
  230. {
  231. $pagination = $this->dataProvider->getPagination();
  232. if ($pagination === false || $this->dataProvider->getCount() <= 0) {
  233. return '';
  234. }
  235. /* @var $class LinkPager */
  236. $pager = $this->pager;
  237. $class = ArrayHelper::remove($pager, 'class', LinkPager::className());
  238. $pager['pagination'] = $pagination;
  239. $pager['view'] = $this->getView();
  240. return $class::widget($pager);
  241. }
  242. /**
  243. * Renders the sorter.
  244. * @return string the rendering result
  245. */
  246. public function renderSorter()
  247. {
  248. $sort = $this->dataProvider->getSort();
  249. if ($sort === false || empty($sort->attributes) || $this->dataProvider->getCount() <= 0) {
  250. return '';
  251. }
  252. /* @var $class LinkSorter */
  253. $sorter = $this->sorter;
  254. $class = ArrayHelper::remove($sorter, 'class', LinkSorter::className());
  255. $sorter['sort'] = $sort;
  256. $sorter['view'] = $this->getView();
  257. return $class::widget($sorter);
  258. }
  259. }