Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 66 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
SpecialListObjectsByType | |
0.00% |
0 / 66 |
|
0.00% |
0 / 5 |
306 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDescription | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 36 |
|
0.00% |
0 / 1 |
56 | |||
fetchZObjects | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
56 |
1 | <?php |
2 | /** |
3 | * WikiLambda Special:ListObjectsByType page |
4 | * |
5 | * @file |
6 | * @ingroup Extensions |
7 | * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt |
8 | * @license MIT |
9 | */ |
10 | |
11 | namespace MediaWiki\Extension\WikiLambda\Special; |
12 | |
13 | use MediaWiki\Extension\WikiLambda\Registry\ZLangRegistry; |
14 | use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry; |
15 | use MediaWiki\Extension\WikiLambda\ZObjectStore; |
16 | use MediaWiki\Languages\LanguageFallback; |
17 | use MediaWiki\SpecialPage\SpecialPage; |
18 | |
19 | class SpecialListObjectsByType extends SpecialPage { |
20 | |
21 | private ZObjectStore $zObjectStore; |
22 | private LanguageFallback $languageFallback; |
23 | |
24 | /** |
25 | * @param ZObjectStore $zObjectStore |
26 | * @param LanguageFallback $languageFallback |
27 | */ |
28 | public function __construct( ZObjectStore $zObjectStore, LanguageFallback $languageFallback ) { |
29 | parent::__construct( 'ListObjectsByType' ); |
30 | $this->zObjectStore = $zObjectStore; |
31 | $this->languageFallback = $languageFallback; |
32 | } |
33 | |
34 | /** |
35 | * @inheritDoc |
36 | */ |
37 | protected function getGroupName() { |
38 | // Triggers use of message specialpages-group-wikilambda |
39 | return 'wikilambda'; |
40 | } |
41 | |
42 | /** |
43 | * @inheritDoc |
44 | */ |
45 | public function getDescription() { |
46 | return $this->msg( 'wikilambda-special-objectsbytype' ); |
47 | } |
48 | |
49 | /** |
50 | * @inheritDoc |
51 | */ |
52 | public function execute( $type ) { |
53 | $this->setHeaders(); |
54 | |
55 | $output = $this->getOutput(); |
56 | |
57 | $output->enableOOUI(); |
58 | |
59 | $output->addModuleStyles( [ 'mediawiki.special' ] ); |
60 | // TODO (T300519): Make this help page. |
61 | $this->addHelpLink( 'Help:Wikifunctions/Objects by type' ); |
62 | |
63 | $langRegistry = ZLangRegistry::singleton(); |
64 | |
65 | // Make list of fallback language Zids |
66 | $languages = array_merge( |
67 | [ $this->getLanguage()->getCode() ], |
68 | $this->languageFallback->getAll( |
69 | $this->getLanguage()->getCode(), |
70 | /* Try for en, even if it's not an explicit fallback. */ LanguageFallback::MESSAGES |
71 | ) |
72 | ); |
73 | |
74 | $languageZids = $langRegistry->getLanguageZids( $languages ); |
75 | |
76 | $typesList = $this->fetchZObjects( ZTypeRegistry::Z_TYPE, $languageZids ); |
77 | |
78 | $wikitext = ''; |
79 | if ( $type !== null && $type !== '' && isset( $typesList[$type] ) ) { |
80 | $typeLabel = $typesList[$type]; |
81 | $zobjectList = $this->fetchZObjects( $type, $languageZids ); |
82 | $wikitext .= "\n== "; |
83 | $wikitext .= $this->msg( 'wikilambda-special-objectsbytype-listheader' ) |
84 | ->rawParams( htmlspecialchars( $typeLabel ), $type ) |
85 | ->parse(); |
86 | $wikitext .= " ==\n"; |
87 | foreach ( $zobjectList as $zid => $label ) { |
88 | // Let the usual linker de-reference the label as appropriate |
89 | $wikitext .= "# [[$zid]]\n"; |
90 | } |
91 | |
92 | if ( count( $zobjectList ) === 0 ) { |
93 | $wikitext .= $this->msg( 'wikilambda-special-objectsbytype-empty' ); |
94 | } |
95 | } |
96 | $wikitext .= "\n== "; |
97 | $wikitext .= $this->msg( 'wikilambda-special-objectsbytype-typeheader' ); |
98 | $wikitext .= " ==\n"; |
99 | $wikitext .= $this->msg( 'wikilambda-special-objectsbytype-summary' ); |
100 | $wikitext .= "\n"; |
101 | foreach ( $typesList as $type => $label ) { |
102 | $wikitext .= ": [[Special:ListObjectsByType/$type|$label]] ($type)\n"; |
103 | } |
104 | |
105 | $output->addWikiTextAsInterface( $wikitext ); |
106 | } |
107 | |
108 | /** |
109 | * Use ZObjectStore to fetch all ZObjects with appropriate labels for the provided type |
110 | * |
111 | * @param string $type |
112 | * @param string[] $languageZids |
113 | * @return array |
114 | */ |
115 | private function fetchZObjects( $type, $languageZids ) { |
116 | // Don't take down the site; limit listings to 5000(!) rows regardless. |
117 | $pageLimit = 5000; |
118 | |
119 | // Paginate our DB query at 100 items per request |
120 | $queryLimit = 100; |
121 | |
122 | $continue = null; |
123 | |
124 | $zobjects = []; |
125 | |
126 | while ( $pageLimit > 0 ) { |
127 | $pageLimit -= $queryLimit; |
128 | |
129 | $res = $this->zObjectStore->searchZObjectLabels( |
130 | '', |
131 | true, |
132 | $languageZids, |
133 | $type, |
134 | null, |
135 | false, |
136 | $continue, |
137 | $queryLimit |
138 | ); |
139 | |
140 | foreach ( $res as $row ) { |
141 | // Only set the label if we don't have one already, or if |
142 | // it's the primary label of the first-requested language. |
143 | // TODO (T362238): This means that if you're asking for uk > ru > en and we only have ru and en |
144 | // labels, we'll return whichever is first, rather than your preferred ru label over en. |
145 | if ( |
146 | !isset( $zobjects[$row->wlzl_zobject_zid] ) |
147 | || ( $row->wlzl_label_primary && array_search( $row->wlzl_language, $languageZids ) === 0 ) |
148 | ) { |
149 | $zobjects[$row->wlzl_zobject_zid] = $row->wlzl_label; |
150 | } |
151 | $continue = $row->wlzl_id; |
152 | } |
153 | |
154 | if ( $res->numRows() < $queryLimit ) { |
155 | // We got fewer than our limit last time, so exit the loop. |
156 | break; |
157 | } |
158 | } |
159 | |
160 | asort( $zobjects ); |
161 | |
162 | return $zobjects; |
163 | } |
164 | } |