Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 85
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialListObjectsByType
0.00% covered (danger)
0.00%
0 / 85
0.00% covered (danger)
0.00%
0 / 9
272
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDescription
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isListed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 userCanExecute
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getParameters
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
42
 execute
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
6
 getHeaderTitle
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getHeaderForm
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 1
2
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
11namespace MediaWiki\Extension\WikiLambda\Special;
12
13use MediaWiki\Extension\WikiLambda\Fields\HTMLZTypeSelectField;
14use MediaWiki\Extension\WikiLambda\Pagers\BasicZObjectPager;
15use MediaWiki\Extension\WikiLambda\Registry\ZLangRegistry;
16use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry;
17use MediaWiki\Extension\WikiLambda\ZObjectStore;
18use MediaWiki\Extension\WikiLambda\ZObjectUtils;
19use MediaWiki\HTMLForm\HTMLForm;
20use MediaWiki\Language\LanguageFallback;
21use MediaWiki\SpecialPage\SpecialPage;
22use MediaWiki\User\User;
23
24class SpecialListObjectsByType extends SpecialPage {
25
26    private ZLangRegistry $langRegistry;
27
28    /**
29     * @param ZObjectStore $zObjectStore
30     * @param LanguageFallback $languageFallback
31     */
32    public function __construct(
33        private readonly ZObjectStore $zObjectStore,
34        private readonly LanguageFallback $languageFallback
35    ) {
36        parent::__construct( 'ListObjectsByType' );
37
38        $this->langRegistry = ZLangRegistry::singleton();
39    }
40
41    /**
42     * @inheritDoc
43     */
44    protected function getGroupName() {
45        // Triggers use of message specialpages-group-wikilambda
46        return 'wikilambda';
47    }
48
49    /**
50     * @inheritDoc
51     */
52    public function getDescription() {
53        return $this->msg( 'wikilambda-special-objectsbytype' );
54    }
55
56    /** @inheritDoc */
57    public function isListed() {
58        // No usage allowed on client-mode wikis.
59        return $this->getConfig()->get( 'WikiLambdaEnableRepoMode' );
60    }
61
62    /**
63     * @inheritDoc
64     *
65     * @param User $user
66     * @return bool
67     */
68    public function userCanExecute( User $user ) {
69        if ( !$this->getConfig()->get( 'WikiLambdaEnableRepoMode' ) ) {
70            // No usage allowed on client-mode wikis.
71            return false;
72        }
73        return parent::userCanExecute( $user );
74    }
75
76    /**
77     * Get and validate SpecialPage parameters from subpage and url
78     *
79     * @param string $subpage
80     * @return array - type ZID, orderby, bool excludePreDefined
81     */
82    private function getParameters( $subpage ) {
83        // Get type from subpage; overwrite with value from Request.
84        // * requestType can be empty string or valid/invalid string
85        // * subpage can be empty string or NULL or valid/invalid string
86        // Default: Z8/Function
87        $requestType = $this->getRequest()->getText( 'type' );
88        if ( $requestType && ZObjectUtils::isValidZObjectReference( $requestType ) ) {
89            $type = $requestType;
90        } else {
91            $type = $subpage && ZObjectUtils::isValidZObjectReference( $subpage ) ?
92                $subpage :
93                ZTypeRegistry::Z_FUNCTION;
94        }
95
96        // Get orderby from Request.
97        // * can be empty string or valid/invalid string (name, latest, oldest)
98        // Default: 'name'
99        $requestOrderby = $this->getRequest()->getText( 'orderby' );
100        $orderby = in_array( $requestOrderby, BasicZObjectPager::ORDER_BY_OPTIONS ) ?
101            $requestOrderby :
102            BasicZObjectPager::ORDER_BY_NAME;
103
104        $excludePreDefined = $this->getRequest()->getBool( 'excludePreDefined' );
105
106        return [ $type, $orderby, $excludePreDefined ];
107    }
108
109    /**
110     * @inheritDoc
111     */
112    public function execute( $subpage ) {
113        if ( !$this->userCanExecute( $this->getUser() ) ) {
114            $this->displayRestrictionError();
115        }
116
117        // Get and validate page parameters
118        [ $type, $orderby, $excludePreDefined ] = $this->getParameters( $subpage );
119
120        // Set headers
121        $this->setHeaders();
122        $this->outputHeader( 'wikilambda-special-objectsbytype-summary' );
123
124        // Set output
125        $output = $this->getOutput();
126        $output->enableOOUI();
127        $output->addModuleStyles( [ 'mediawiki.special' ] );
128
129        $this->addHelpLink( 'Help:Wikifunctions/Objects by type' );
130
131        // Get list of fallback language Zids
132        $languageZids = $this->langRegistry->getListOfFallbackLanguageZids(
133            $this->languageFallback,
134            $this->getLanguage()->getCode()
135        );
136
137        // Build BasicZObjectPager for the given filters
138        $filters = [ 'type' => $type ];
139        $pager = new BasicZObjectPager(
140            $this->getContext(),
141            $this->zObjectStore,
142            $languageZids,
143            $orderby,
144            $excludePreDefined,
145            $filters
146        );
147
148        // Add the header form
149        $output->addHTML( $this->getHeaderForm( $type, $orderby ) );
150
151        // Add the top pagination controls
152        $output->addHTML( $pager->getNavigationBar() );
153        // Add the item list body
154        $output->addWikiTextAsInterface( $pager->getBody() );
155        // Add the bottom pagination controls
156        $output->addHTML( $pager->getNavigationBar() );
157
158        // Add bottom pagination controls
159        $output->addWikiTextAsInterface( $pager->getBottomLinks() );
160    }
161
162    /**
163     * Render the header for listing ZObjects by a specific type.
164     *
165     * @param string $typeZid - The type Zid of ZObjects being listed.
166     * @return string - The text for the header.
167     */
168    private function getHeaderTitle( $typeZid ) {
169        $typeLabel = $this->zObjectStore->fetchZObjectLabel( $typeZid, $this->getLanguage()->getCode() );
170        return $this->msg( 'wikilambda-special-objectsbytype-listheader' )
171            ->rawParams( htmlspecialchars( $typeLabel ?? $typeZid ), htmlspecialchars( $typeZid ) )
172            ->text();
173    }
174
175    /**
176     * Build the form to place at the head of the Special page,
177     * with a selector field for ZTypes and another for ZLanguages.
178     *
179     * @param string $typeZid
180     * @param string $orderby
181     * @return string
182     */
183    public function getHeaderForm( string $typeZid, string $orderby ) {
184        $formHeader = $this->getHeaderTitle( $typeZid );
185        $formDescriptor = [
186            'type' => [
187                'label' => $this->msg( 'wikilambda-special-objectsbytype-form-type' )->text(),
188                'class' => HTMLZTypeSelectField::class,
189                'name' => 'type',
190                'default' => $typeZid
191            ],
192            'orderby' => [
193                'label' => $this->msg( 'wikilambda-special-objectsbytype-form-orderby' )->text(),
194                'type' => 'select',
195                'name' => 'orderby',
196                'options' => [
197                    $this->msg( 'wikilambda-special-objectsbytype-form-orderby-name' )
198                        ->escaped() => BasicZObjectPager::ORDER_BY_NAME,
199                    $this->msg( 'wikilambda-special-objectsbytype-form-orderby-latest' )
200                        ->escaped() => BasicZObjectPager::ORDER_BY_LATEST,
201                    $this->msg( 'wikilambda-special-objectsbytype-form-orderby-oldest' )
202                        ->escaped() => BasicZObjectPager::ORDER_BY_OLDEST
203                ],
204                'default' => $orderby
205            ],
206            'excludePreDefined' => [
207                'type' => 'check',
208                'label' => $this->msg( 'wikilambda-special-objectsbytype-form-excludepredefined' )->text(),
209                'name' => 'excludePreDefined',
210                'default' => false
211            ]
212        ];
213
214        $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
215            ->setWrapperLegend( $formHeader )
216            ->setCollapsibleOptions( false )
217            ->setMethod( 'get' );
218        return $htmlForm->prepareForm()->getHTML( false );
219    }
220}