Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.48% covered (success)
93.48%
43 / 46
66.67% covered (warning)
66.67%
6 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
AbstractZObjectPager
93.48% covered (success)
93.48%
43 / 46
66.67% covered (warning)
66.67%
6 / 9
18.09
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getZObjectStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTypeFilter
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQueryInfo
95.65% covered (success)
95.65%
22 / 23
0.00% covered (danger)
0.00%
0 / 1
2
 getIndexField
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
5
 getDefaultDirections
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
5
 getEmptyBody
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getBottomLinks
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 formatRow
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * WikiLambda AbstractZObjectPager extends AlphabeticPager
4 *
5 * @file
6 * @ingroup Extensions
7 * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt
8 * @license MIT
9 */
10
11namespace MediaWiki\Extension\WikiLambda\Pagers;
12
13use MediaWiki\Context\IContextSource;
14use MediaWiki\Extension\WikiLambda\ZObjectStore;
15use MediaWiki\Pager\AlphabeticPager;
16use Wikimedia\Rdbms\RawSQLValue;
17use Wikimedia\Rdbms\Subquery;
18
19abstract class AbstractZObjectPager extends AlphabeticPager {
20
21    public const ORDER_BY_NAME = 'name';
22    public const ORDER_BY_OLDEST = 'oldest';
23    public const ORDER_BY_LATEST = 'latest';
24    public const ORDER_BY_OPTIONS = [ self::ORDER_BY_NAME, self::ORDER_BY_OLDEST, self::ORDER_BY_LATEST ];
25
26    /**
27     * @param IContextSource|null $context Context.
28     * @param ZObjectStore $zObjectStore
29     * @param array $languageZids
30     * @param string $orderby
31     * @param bool $excludePreDefined
32     */
33    public function __construct(
34        $context,
35        private readonly ZObjectStore $zObjectStore,
36        private readonly array $languageZids,
37        private readonly string $orderby = self::ORDER_BY_NAME,
38        private readonly bool $excludePreDefined = false
39    ) {
40        parent::__construct( $context );
41    }
42
43    /**
44     * Get the ZObjectStore object
45     *
46     * @return ZObjectStore
47     */
48    public function getZObjectStore() {
49        return $this->zObjectStore;
50    }
51
52    /**
53     * The type zid to restrict the listing to, or null for no restriction.
54     * Subclasses that list a single type should override this so that the
55     * type filter is pushed down into the preferred-labels ranking rather
56     * than applied over its results (T430853).
57     *
58     * @return string|null
59     */
60    protected function getTypeFilter(): ?string {
61        return null;
62    }
63
64    /**
65     * Provides all parameters needed for the main paged query. It returns
66     * an associative array with the following elements:
67     *    tables => Table(s) for passing to Database::select()
68     *    fields => Field(s) for passing to Database::select(), may be *
69     *    conds => WHERE conditions
70     *    options => option array
71     *    join_conds => JOIN conditions
72     *
73     * For Wikilambda ZObjects:
74     * * Fetches from labels table
75     * * Uses the normalised primary label for alphabetic pagination
76     *
77     * @return array
78     */
79    public function getQueryInfo() {
80        // Returns table with unique zids and the most preferred primary label,
81        // restricted to the pager's type (if any) before ranking
82        $subquery = $this->zObjectStore
83            ->getPreferredLabelsQuery( $this->languageZids, $this->getTypeFilter() )
84            ->getSQL();
85
86        $tables = [ 'preferred_labels' => new Subquery( $subquery ) ];
87        $fields = [
88            'page_id',
89            'wlzl_zobject_zid',
90            'wlzl_label',
91            'wlzl_label_normalised',
92            'wlzl_language',
93            'wlzl_label_primary'
94        ];
95        $conds = [];
96        if ( $this->excludePreDefined ) {
97            $conds[] = ( new RawSQLValue( 'LENGTH( wlzl_zobject_zid ) > 5' ) )->toSQL();
98        }
99
100        $queryInfo = [
101            'tables' => $tables,
102            'fields' => $fields,
103            'conds' => $conds,
104            'join_conds' => [],
105            'options' => []
106        ];
107
108        return $queryInfo;
109    }
110
111    /**
112     * Return the name of the field that is used for alphabetic sorting.
113     *
114     * @return string
115     */
116    public function getIndexField() {
117        switch ( $this->orderby ) {
118            case self::ORDER_BY_NAME:
119                return 'wlzl_label_normalised';
120            case self::ORDER_BY_LATEST:
121            case self::ORDER_BY_OLDEST:
122            default:
123                return 'page_id';
124        }
125    }
126
127    /**
128     * Return the direction or order results in
129     *
130     * @return bool
131     */
132    public function getDefaultDirections() {
133        switch ( $this->orderby ) {
134            case self::ORDER_BY_LATEST:
135                return self::DIR_DESCENDING;
136            case self::ORDER_BY_NAME:
137            case self::ORDER_BY_OLDEST:
138            default:
139                return self::DIR_ASCENDING;
140        }
141    }
142
143    /**
144     * @return string
145     */
146    public function getEmptyBody() {
147        return $this->msg( 'wikilambda-special-list-empty' )->parse();
148    }
149
150    /**
151     * @return string
152     */
153    public function getBottomLinks() {
154        $wikitext = "\n== " . $this->msg( 'wikilambda-special-list-all-pages' )->text() . " ==\n";
155
156        $wikitext .= "\n* [[Special:ListObjectsByType|" .
157            $this->msg( 'wikilambda-special-objectsbytype-link' )->text() . "]]\n";
158
159        $wikitext .= "\n* [[Special:ListDuplicateObjectNames|" .
160            $this->msg( 'wikilambda-special-listduplicateobjectlabels-link' )->text() . "]]\n";
161
162        $wikitext .= "\n* [[Special:ListMissingLabels|" .
163            $this->msg( 'wikilambda-special-missinglabels' )->text() . "]]\n";
164
165        $wikitext .= "\n* [[Special:ListFunctionsByTests|" .
166            $this->msg( 'wikilambda-special-functionsbytests' )->text() . "]]\n";
167
168        return $wikitext;
169    }
170
171    /**
172     * Process each row returned from the query.
173     * This is where we build up the list of ZObjects.
174     *
175     * @param \stdClass $row
176     * @return string
177     */
178    public function formatRow( $row ) {
179        $zid = $row->wlzl_zobject_zid;
180        $label = wfEscapeWikiText( $row->wlzl_label );
181        return "# [[$zid|$label]] ($zid)\n";
182    }
183}