diff --git a/framework/yii/widgets/DetailView.php b/framework/yii/widgets/DetailView.php index 9b062c5..d6259c9 100644 --- a/framework/yii/widgets/DetailView.php +++ b/framework/yii/widgets/DetailView.php @@ -111,7 +111,8 @@ class DetailView extends Widget $this->formatter = Yii::$app->getFormatter(); } elseif (is_array($this->formatter)) { $this->formatter = Yii::createObject($this->formatter); - } elseif (!$this->formatter instanceof Formatter) { + } + if (!$this->formatter instanceof Formatter) { throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.'); } $this->normalizeAttributes(); @@ -173,7 +174,7 @@ class DetailView extends Widget foreach ($this->attributes as $i => $attribute) { if (is_string($attribute)) { if (!preg_match('/^(\w+)(\s*:\s*(\w+))?$/', $attribute, $matches)) { - throw new InvalidConfigException('The attribute must be in the format of "Name" or "Name:Type"'); + throw new InvalidConfigException('The attribute must be specified in the format of "Name" or "Name:Type"'); } $attribute = array( 'name' => $matches[1], diff --git a/framework/yii/widgets/ListView.php b/framework/yii/widgets/ListView.php index 21aa5e2..dbcf6f5 100644 --- a/framework/yii/widgets/ListView.php +++ b/framework/yii/widgets/ListView.php @@ -8,9 +8,6 @@ namespace yii\widgets; use Yii; -use yii\base\InvalidConfigException; -use yii\base\Model; -use yii\base\Widget; use yii\helpers\ArrayHelper; use yii\helpers\Html; @@ -19,18 +16,9 @@ use yii\helpers\Html; * @author Qiang Xue * @since 2.0 */ -class ListView extends Widget +class ListView extends ListViewBase { /** - * @var array the HTML attributes for the container tag of the list view. - * The "tag" element specifies the tag name of the container element and defaults to "div". - */ - public $options = array(); - /** - * @var \yii\data\IDataProvider the data provider for the view. This property is required. - */ - public $dataProvider; - /** * @var array the HTML attributes for the container of the rendering result of each data item. * The "tag" element specifies the tag name of the container element and defaults to "div". * If "tag" is false, it means no container element will be rendered. @@ -59,129 +47,9 @@ class ListView extends Widget * @var string the HTML code to be displayed between any two consecutive items. */ public $separator = "\n"; - /** - * @var array the configuration for the pager widget. By default, [[LinkPager]] will be - * used to render the pager. You can use a different widget class by configuring the "class" element. - */ - public $pager = array(); - /** - * @var array the configuration for the sorter widget. By default, [[LinkSorter]] will be - * used to render the sorter. You can use a different widget class by configuring the "class" element. - */ - public $sorter = array(); - /** - * @var string the HTML content to be displayed as the summary of the list view. - * If you do not want to show the summary, you may set it with an empty string. - * - * The following tokens will be replaced with the corresponding values: - * - * - `{begin}`: the starting row number (1-based) currently being displayed - * - `{end}`: the ending row number (1-based) currently being displayed - * - `{count}`: the number of rows currently being displayed - * - `{totalCount}`: the total number of rows available - * - `{page}`: the page number (1-based) current being displayed - * - `{pageCount}`: the number of pages available - */ - public $summary; - /** - * @var string the HTML content to be displayed when [[dataProvider]] does not have any data. - * If you do not want to show anything when [[dataProvider]] is empty, you may set this property with an empty string. - */ - public $empty; - /** - * @var string the layout that determines how different sections of the list view should be organized. - * The following tokens will be replaced with the corresponding section contents: - * - * - `{summary}`: the summary section. See [[renderSummary()]]. - * - `{items}`: the list items. See [[renderItems()]]. - * - `{sorter}`: the sorter. See [[renderSorter()]]. - * - `{pager}`: the pager. See [[renderPager()]]. - */ - public $layout = "{summary}\n{sorter}\n{items}\n{pager}"; /** - * Initializes the view. - */ - public function init() - { - if ($this->dataProvider === null) { - throw new InvalidConfigException('The "dataProvider" property must be set.'); - } - if ($this->empty === null) { - $this->empty = '
' . Yii::t('yii', 'No results found.') . '
'; - } - } - - /** - * Runs the widget. - */ - public function run() - { - if ($this->dataProvider->getCount() > 0) { - $tag = ArrayHelper::remove($this->options, 'tag', 'div'); - $content = preg_replace_callback("/{\\w+}/", array($this, 'renderSection'), $this->layout); - echo Html::tag($tag, $content, $this->options); - } else { - echo $this->empty; - } - } - - /** - * Renders a section of the list view. - * This method is invoked for every placeholder found in [[layout]]. - * It should return the rendering result that would replace the placeholder. - * @param array $matches the matches, where $matches[0] represents the matching placeholder. - * @return string the rendering result of the section - */ - protected function renderSection($matches) - { - switch ($matches[0]) { - case '{summary}': return $this->renderSummary(); - case '{items}': return $this->renderItems(); - case '{sorter}': return $this->renderSorter(); - case '{pager}': return $this->renderPager(); - default: return $matches[0]; - } - } - - /** - * Renders the summary text. - */ - public function renderSummary() - { - $count = $this->dataProvider->getCount(); - if (($pagination = $this->dataProvider->getPagination()) !== false) { - $totalCount = $this->dataProvider->getTotalCount(); - $begin = $pagination->getPage() * $pagination->pageSize + 1; - $end = $begin + $count - 1; - if ($end > $totalCount) { - $end = $totalCount; - $begin = $end - $count + 1; - } - $page = $pagination->getPage() + 1; - $pageCount = $pagination->pageCount; - if (($summaryContent = $this->summary) === null) { - $summaryContent = '
' . Yii::t('yii', 'Total 1 result.|Showing {begin}-{end} of {totalCount} results.', $totalCount) . '
'; - } - } else { - $begin = $page = $pageCount = 1; - $end = $totalCount = $count; - if (($summaryContent = $this->summary) === null) { - $summaryContent = '
' . Yii::t('yii', 'Total 1 result.|Total {count} results.', $count) . '
'; - } - } - return strtr($summaryContent, array( - '{begin}' => $begin, - '{end}' => $end, - '{count}' => $count, - '{totalCount}' => $totalCount, - '{page}' => $page, - '{pageCount}' => $pageCount, - )); - } - - /** * Renders all data items. * @return string the rendering result */ @@ -226,36 +94,4 @@ class ListView extends Widget return $content; } } - - /** - * Renders the sorter. - * @return string the rendering result - */ - public function renderSorter() - { - $sort = $this->dataProvider->getSort(); - if ($sort === false || empty($sort->attributes) || $this->dataProvider->getCount() <= 0) { - return ''; - } - /** @var LinkSorter $class */ - $class = ArrayHelper::remove($this->sorter, 'class', LinkSorter::className()); - $this->sorter['sort'] = $sort; - return $class::widget($this->sorter); - } - - /** - * Renders the pager. - * @return string the rendering result - */ - public function renderPager() - { - $pagination = $this->dataProvider->getPagination(); - if ($pagination === false || $this->dataProvider->getCount() <= 0) { - return ''; - } - /** @var LinkPager $class */ - $class = ArrayHelper::remove($this->pager, 'class', LinkPager::className()); - $this->pager['pagination'] = $pagination; - return $class::widget($this->pager); - } } diff --git a/framework/yii/widgets/ListViewBase.php b/framework/yii/widgets/ListViewBase.php new file mode 100644 index 0000000..a29fcf0 --- /dev/null +++ b/framework/yii/widgets/ListViewBase.php @@ -0,0 +1,194 @@ + + * @since 2.0 + */ +abstract class ListViewBase extends Widget +{ + /** + * @var array the HTML attributes for the container tag of the list view. + * The "tag" element specifies the tag name of the container element and defaults to "div". + */ + public $options = array(); + /** + * @var \yii\data\IDataProvider the data provider for the view. This property is required. + */ + public $dataProvider; + /** + * @var array the configuration for the pager widget. By default, [[LinkPager]] will be + * used to render the pager. You can use a different widget class by configuring the "class" element. + */ + public $pager = array(); + /** + * @var array the configuration for the sorter widget. By default, [[LinkSorter]] will be + * used to render the sorter. You can use a different widget class by configuring the "class" element. + */ + public $sorter = array(); + /** + * @var string the HTML content to be displayed as the summary of the list view. + * If you do not want to show the summary, you may set it with an empty string. + * + * The following tokens will be replaced with the corresponding values: + * + * - `{begin}`: the starting row number (1-based) currently being displayed + * - `{end}`: the ending row number (1-based) currently being displayed + * - `{count}`: the number of rows currently being displayed + * - `{totalCount}`: the total number of rows available + * - `{page}`: the page number (1-based) current being displayed + * - `{pageCount}`: the number of pages available + */ + public $summary; + /** + * @var string|boolean the HTML content to be displayed when [[dataProvider]] does not have any data. + * If false, the list view will still be displayed (without body content though). + */ + public $empty; + /** + * @var string the layout that determines how different sections of the list view should be organized. + * The following tokens will be replaced with the corresponding section contents: + * + * - `{summary}`: the summary section. See [[renderSummary()]]. + * - `{items}`: the list items. See [[renderItems()]]. + * - `{sorter}`: the sorter. See [[renderSorter()]]. + * - `{pager}`: the pager. See [[renderPager()]]. + */ + public $layout = "{summary}\n{sorter}\n{items}\n{pager}"; + + + /** + * Renders the data items. + * @return string the rendering result. + */ + abstract public function renderItems(); + + /** + * Initializes the view. + */ + public function init() + { + if ($this->dataProvider === null) { + throw new InvalidConfigException('The "dataProvider" property must be set.'); + } + } + + /** + * Runs the widget. + */ + public function run() + { + if ($this->dataProvider->getCount() > 0 || $this->empty === false) { + $content = preg_replace_callback("/{\\w+}/", function ($matches) { + $content = $this->renderSection($matches[0]); + return $content === false ? $matches[0] : $content; + }, $this->layout); + } else { + $content = '
' . ($this->empty === null ? Yii::t('yii', 'No results found.') : $this->empty) . '
'; + } + $tag = ArrayHelper::remove($this->options, 'tag', 'div'); + echo Html::tag($tag, $content, $this->options); + } + + /** + * Renders a section of the specified name. + * If the named section is not supported, false will be returned. + * @param string $name the section name, e.g., `{summary}`, `{items}`. + * @return string|boolean the rendering result of the section, or false if the named section is not supported. + */ + protected function renderSection($name) + { + switch ($name) { + case '{summary}': + return $this->renderSummary(); + case '{items}': + return $this->renderItems(); + case '{pager}': + return $this->renderPager(); + case '{sorter}': + return $this->renderSorter(); + default: + return false; + } + } + + /** + * Renders the summary text. + */ + public function renderSummary() + { + $count = $this->dataProvider->getCount(); + if (($pagination = $this->dataProvider->getPagination()) !== false) { + $totalCount = $this->dataProvider->getTotalCount(); + $begin = $pagination->getPage() * $pagination->pageSize + 1; + $end = $begin + $count - 1; + if ($end > $totalCount) { + $end = $totalCount; + $begin = $end - $count + 1; + } + $page = $pagination->getPage() + 1; + $pageCount = $pagination->pageCount; + if (($summaryContent = $this->summary) === null) { + $summaryContent = '
' . Yii::t('yii', 'Total 1 item.|Showing {begin}-{end} of {totalCount} items.', $totalCount) . '
'; + } + } else { + $begin = $page = $pageCount = 1; + $end = $totalCount = $count; + if (($summaryContent = $this->summary) === null) { + $summaryContent = '
' . Yii::t('yii', 'Total 1 item.|Total {count} items.', $count) . '
'; + } + } + return strtr($summaryContent, array( + '{begin}' => $begin, + '{end}' => $end, + '{count}' => $count, + '{totalCount}' => $totalCount, + '{page}' => $page, + '{pageCount}' => $pageCount, + )); + } + + /** + * Renders the pager. + * @return string the rendering result + */ + public function renderPager() + { + $pagination = $this->dataProvider->getPagination(); + if ($pagination === false || $this->dataProvider->getCount() <= 0) { + return ''; + } + /** @var LinkPager $class */ + $class = ArrayHelper::remove($this->pager, 'class', LinkPager::className()); + $this->pager['pagination'] = $pagination; + return $class::widget($this->pager); + } + + /** + * Renders the sorter. + * @return string the rendering result + */ + public function renderSorter() + { + $sort = $this->dataProvider->getSort(); + if ($sort === false || empty($sort->attributes) || $this->dataProvider->getCount() <= 0) { + return ''; + } + /** @var LinkSorter $class */ + $class = ArrayHelper::remove($this->sorter, 'class', LinkSorter::className()); + $this->sorter['sort'] = $sort; + return $class::widget($this->sorter); + } +}