Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
CNBannerPager
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 7
650
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 getNavigationBar
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 getQueryInfo
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
 getIndexField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 formatRow
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
90
 getBody
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
56
 getDefaultQuery
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3// FIXME Unused? See T161907
4// It's not unused, see Special:CentralNoticeBanners.  Probably needs to be
5// merged with TemplatePager.
6
7use MediaWiki\HTMLForm\Field\HTMLInfoField;
8use MediaWiki\Pager\ReverseChronologicalPager;
9use Wikimedia\Rdbms\IExpression;
10use Wikimedia\Rdbms\LikeValue;
11
12class CNBannerPager extends ReverseChronologicalPager {
13
14    /**
15     * @param SpecialCentralNoticeBanners $hostSpecialPage the page on which we appear
16     * @param string|null $formSection 'Section' attribute to apply to the banner elements generated
17     * @param array[] $prependPrototypes HTMLFormFields to add to the results before every banner entry
18     * @param array[] $appendPrototypes HTMLFormFields to add to the results after every banner entry
19     * @param string $bannerFilter Space separated strings to filter banner titles on
20     * @param bool $editable True if the form is to be created with editable elements
21     */
22    public function __construct(
23        private readonly SpecialCentralNoticeBanners $hostSpecialPage,
24        private readonly ?string $formSection = null,
25        private readonly array $prependPrototypes = [],
26        private readonly array $appendPrototypes = [],
27        private readonly string $bannerFilter = '',
28        private readonly bool $editable = false,
29    ) {
30        // Set database before parent constructor to avoid setting it there
31        $this->mDb = CNDatabase::getReplicaDb();
32
33        parent::__construct();
34
35        // Override paging defaults
36        [ $this->mLimit, $this->mOffset ] = $this->mRequest->getLimitOffsetForUser(
37            $this->getUser(),
38            20,
39            ''
40        );
41        $this->mLimitsShown = [ 20, 50, 100 ];
42    }
43
44    /**
45     * @inheritDoc
46     * @suppress PhanTypeMismatchDimAssignment
47     */
48    public function getNavigationBar() {
49        if ( $this->mNavigationBar !== null ) {
50            return $this->mNavigationBar;
51        }
52
53        // Sets mNavigation bar with the default text which we will then wrap
54        parent::getNavigationBar();
55
56        // @phan-suppress-next-line PhanTypeMismatchPropertyProbablyReal
57        $this->mNavigationBar = [
58            'class' => HTMLBannerPagerNavigation::class,
59            'value' => $this->mNavigationBar
60        ];
61
62        if ( $this->formSection ) {
63            // @phan-suppress-next-line PhanTypeMismatchPropertyProbablyReal
64            $this->mNavigationBar['section'] = $this->formSection;
65        }
66
67        // @phan-suppress-next-line PhanTypeMismatchReturnProbablyReal
68        return $this->mNavigationBar;
69    }
70
71    /**
72     * Set the database query to retrieve all the banners in the database
73     *
74     * @return array of query settings
75     */
76    public function getQueryInfo() {
77        // When the filter comes in it is space delimited, so break that...
78        $likeArray = preg_split( '/\s/', $this->bannerFilter );
79
80        // ...and then insert all the wildcards between search terms
81        if ( !$likeArray ) {
82            $likeArray = [ $this->mDb->anyString() ];
83        } else {
84            $anyStringToken = $this->mDb->anyString();
85            $tempArray = [ $anyStringToken ];
86            foreach ( $likeArray as $likePart ) {
87                $tempArray[] = $likePart;
88                $tempArray[] = $anyStringToken;
89            }
90            $likeArray = $tempArray;
91        }
92
93        return [
94            'tables' => [ 'templates' => 'cn_templates' ],
95            'fields' => [ 'templates.tmp_name', 'templates.tmp_id', 'templates.tmp_is_template' ],
96            'conds' => [ $this->mDb->expr( 'templates.tmp_name', IExpression::LIKE, new LikeValue( ...$likeArray ) ) ],
97        ];
98    }
99
100    /**
101     * Sort the banner list by tmp_id (generally equals reverse chronological)
102     *
103     * @return string
104     */
105    public function getIndexField() {
106        return 'templates.tmp_id';
107    }
108
109    /**
110     * Generate the contents of the table pager; intended to be consumed by the HTMLForm
111     *
112     * @param stdClass $row database row
113     *
114     * @return array HTMLFormElement classes
115     * @suppress PhanParamSignatureMismatch
116     */
117    public function formatRow( $row ) {
118        $retval = [];
119
120        $bannerId = $row->tmp_id;
121        $bannerName = $row->tmp_name;
122
123        // Add the prepend prototypes
124        foreach ( $this->prependPrototypes as $prototypeName => $prototypeValues ) {
125            $retval[ "{$prototypeName}-{$bannerName}" ] = $prototypeValues;
126            if ( array_key_exists( 'id', $prototypeValues ) ) {
127                $retval[ "{$prototypeName}-{$bannerId}" ][ 'id' ] .= "-$bannerName";
128            }
129        }
130
131        // Now do the banner
132        $rowText = BannerRenderer::linkToBanner( $bannerName );
133        if ( (bool)$row->tmp_is_template ) {
134            $rowText = implode( ' ', [
135                $rowText, $this->msg( "centralnotice-banner-template-info" )->escaped()
136            ] );
137        }
138        $retval["cn-banner-list-element-$bannerId"] = [
139            'class' => HTMLInfoField::class,
140            'default' => $rowText . " (" . BannerRenderer::getPreviewLink( $bannerName ) . ")",
141            'raw' => true,
142        ];
143        if ( $this->formSection ) {
144            $retval["cn-banner-list-element-$bannerId"]['section'] = $this->formSection;
145        }
146
147        // Append prototypes
148        foreach ( $this->appendPrototypes as $prototypeName => $prototypeValues ) {
149            $retval[ $prototypeName . "-$bannerId" ] = $prototypeValues;
150            if ( array_key_exists( 'id', $prototypeValues ) ) {
151                $retval[ $prototypeName . "-$bannerId" ][ 'id' ] .= "-$bannerId";
152            }
153        }
154
155        // Set the disabled attribute
156        if ( !$this->editable ) {
157            foreach ( $retval as &$prototypeValues ) {
158                $prototypeValues['disabled'] = true;
159            }
160        }
161
162        return $retval;
163    }
164
165    /**
166     * Get the formatted result list. Calls getStartBody(), formatRow() and
167     * getEndBody(), concatenates the results and returns them.
168     *
169     * @return array
170     * @suppress PhanParamSignatureMismatch
171     */
172    public function getBody() {
173        if ( !$this->mQueryDone ) {
174            $this->doQuery();
175        }
176
177        if ( $this->mResult->numRows() ) {
178            # Do any special query batches before display
179            $this->doBatchLookups();
180        }
181
182        # Don't use any extra rows returned by the query
183        $numRows = min( $this->mResult->numRows(), $this->mLimit );
184
185        $retval = [];
186
187        if ( $numRows ) {
188            if ( $this->mIsBackwards ) {
189                for ( $i = $numRows - 1; $i >= 0; $i-- ) {
190                    $this->mResult->seek( $i );
191                    $row = $this->mResult->fetchObject();
192                    $retval += $this->formatRow( $row );
193                }
194            } else {
195                $this->mResult->seek( 0 );
196                for ( $i = 0; $i < $numRows; $i++ ) {
197                    $row = $this->mResult->fetchObject();
198                    $retval += $this->formatRow( $row );
199                }
200            }
201        } else {
202            // TODO: empty value
203        }
204        return $retval;
205    }
206
207    /**
208     * @inheritDoc
209     */
210    public function getDefaultQuery() {
211        parent::getDefaultQuery();
212        $filterQuery = $this->hostSpecialPage->getFilterUrlParamAsArray();
213        $this->mDefaultQuery = array_merge( $this->mDefaultQuery, $filterQuery );
214        return $this->mDefaultQuery;
215    }
216}