Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 135
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Hooks
0.00% covered (danger)
0.00%
0 / 135
0.00% covered (danger)
0.00%
0 / 3
552
0.00% covered (danger)
0.00%
0 / 1
 getFooterShortcuts
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 1
110
 getFooterShortcutsPrivilegedUsers
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 onSkinTemplateNavigation__Universal
0.00% covered (danger)
0.00%
0 / 86
0.00% covered (danger)
0.00%
0 / 1
110
1<?php
2/**
3 * Cologne Blue: A nicer-looking alternative to Standard.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 */
22
23namespace MediaWiki\Extension\CologneBlue;
24
25// phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName
26
27use MediaWiki\Hook\SkinTemplateNavigation__UniversalHook;
28use MediaWiki\SpecialPage\SpecialPage;
29use MediaWiki\Title\Title;
30use Skin;
31use SkinTemplate;
32
33/**
34 * @ingroup Skins
35 */
36class Hooks implements SkinTemplateNavigation__UniversalHook {
37    /**
38     * Construct menu for the Cologne Blue footer
39     * from the existing data given to the
40     * SkinTemplateNavigationUniversal hook
41     * @param Skin $skin
42     * @param array $content_nav as constructed in SkinTemplateNavigationUniversal hook
43     * @return array
44     */
45    private static function getFooterShortcuts( $skin, $content_nav ) {
46        $footerShortcuts = [];
47        $actions = $content_nav['actions'];
48        $namespaces = $content_nav['namespaces'];
49        $prefix = 'cb-';
50
51        foreach ( [ 'edit', 'viewsource' ] as $key ) {
52            if ( isset( $actions[$key] ) ) {
53                $footerShortcuts[$prefix . $key] = array_merge( [], $actions[$key] );
54            }
55        }
56
57        foreach ( [ 'watch', 'unwatch', 'talk', 'history' ] as $key ) {
58            if ( isset( $namespaces[$key] ) ) {
59                $footerShortcuts[$prefix . $key] = array_merge( [], $namespaces[$key], [
60                    // disable ID construction
61                    'context' => null,
62                ] );
63            }
64        }
65
66        $out = $skin->getOutput();
67        $title = $out->getTitle();
68        $thispage = $title->getPrefixedDBkey();
69
70        if ( $out->isArticleRelated() ) {
71            $footerShortcuts['cb-whatlinkshere'] = [
72                'href' => SpecialPage::getTitleFor( 'Whatlinkshere', $thispage )->getLocalURL(),
73                'text' => $skin->msg( 'whatlinkshere' )->text(),
74                'title' => $skin->msg( "tooltip-t-whatlinkshere" )->escaped(),
75            ];
76            $footerShortcuts['cb-info'] = [
77                'text' => $skin->msg( 'pageinfo-toolboxlink' )->text(),
78                'title' => $skin->msg( "tooltip-info" )->escaped(),
79                'href' => $title->getLocalURL( "action=info" ),
80            ];
81
82            if ( $title->exists() || $title->inNamespace( NS_CATEGORY ) ) {
83                $footerShortcuts['recentchangeslinked'] = [
84                    'href' => SpecialPage::getTitleFor( 'Recentchangeslinked',
85                        $title->getPrefixedDBkey()
86                    )->getLocalURL(),
87                ];
88            }
89        }
90
91        $user = $skin->getRelevantUser();
92        if ( $user ) {
93            $rootUser = $user->getName();
94            if ( $skin->showEmailUser( $user ) ) {
95                // $this->msg( 'tool-link-emailuser', $rootUser )->text()
96                $footerShortcuts['emailuser'] = [
97                    'text' => $skin->msg( 'tool-link-emailuser', $rootUser )->text(),
98                    'href' => Skin::makeSpecialUrlSubpage( 'Emailuser', $rootUser ),
99                ];
100            }
101        }
102
103        return $footerShortcuts;
104    }
105
106    /**
107     * Construct menu for the Cologne Blue footer
108     * for privileged users from the existing data given to the
109     * SkinTemplateNavigationUniversal hook
110     * @param Skin $skin
111     * @param array $content_nav as constructed in SkinTemplateNavigationUniversal hook
112     * @return array
113     */
114    private static function getFooterShortcutsPrivilegedUsers( $skin, $content_nav ) {
115        $element = [];
116        $keys = [ 'delete', 'undelete', 'protect', 'unprotect', 'move' ];
117        foreach ( $keys as $key ) {
118            if ( isset( $content_nav['actions'][$key] ) ) {
119                $element['cb-' . $key] = array_merge( [], $content_nav['actions'][$key], [
120                    'title' => $skin->msg( "tooltip-ca-$key" )->escaped(),
121                ] );
122            }
123        }
124        return $element;
125    }
126
127    /**
128     * Adds CologneBlue-specific items to the sidebar: qbedit, qbpageoptions and qbmyoptions menus.
129     *
130     * @param SkinTemplate $skin
131     * @param array &$content_navigation
132     */
133    public function onSkinTemplateNavigation__Universal( $skin, &$content_navigation ): void {
134        if ( $skin->getSkinName() !== 'cologneblue' ) {
135            return;
136        }
137        // "This page" and "Edit" menus
138        // We need to do some massaging here... we reuse all of the items,
139        // except for $...['views']['view'], as $...['namespaces']['main'] and
140        // $...['namespaces']['talk'] together serve the same purpose. We also
141        // don't use $...['variants'], these are displayed in the top menu.
142        $qbpageoptions = $content_navigation['namespaces'];
143        if ( isset( $content_navigation['views']['history'] ) ) {
144            $qbpageoptions['history'] = $content_navigation['views']['history'];
145        }
146        if ( isset( $content_navigation['actions']['watch'] ) ) {
147            $qbpageoptions['watch'] = $content_navigation['actions']['watch'];
148        } elseif ( isset( $content_navigation['actions']['unwatch'] ) ) {
149            $qbpageoptions['unwatch'] = $content_navigation['actions']['unwatch'];
150        }
151
152        unset( $content_navigation['actions']['watch'] );
153        unset( $content_navigation['actions']['unwatch'] );
154
155        $views = $content_navigation['views'] ?? [];
156
157        $qbEditLinks = [];
158        if ( isset( $views['edit'] ) ) {
159            $qbEditLinks['edit'] = $views['edit'];
160        }
161
162        if ( isset( $views['addsection'] ) ) {
163            $qbEditLinks['addsection'] = $views['addsection'];
164        }
165        $qbedit = array_merge(
166            $qbEditLinks,
167            $content_navigation['actions']
168        );
169
170        $content_navigation['namespaces'] = $qbpageoptions;
171        $content_navigation['actions'] = $qbedit;
172        $out = $skin->getOutput();
173        $toolbox = $out->getProperty( 'cb-toolbox' );
174
175        // Clone language menu for footer display
176        $languages = $skin->getLanguages();
177        if ( count( $languages ) > 0 ) {
178            $content_navigation['cb-footer-languages'] = array_map( static function ( $lang ) {
179                return array_merge( [], $lang, [
180                    // disable ID generation.
181                    'id' => false,
182                ] );
183            }, $languages );
184        }
185
186        $content_navigation['cb-footer-shortcuts'] = self::getFooterShortcuts(
187            $skin, $content_navigation
188        );
189        $content_navigation['cb-footer-shortcuts-privileged'] =
190            self::getFooterShortcutsPrivilegedUsers( $skin, $content_navigation );
191
192        $mainpage = [
193            'text' => $skin->msg( 'mainpage' )->escaped(),
194            'href' => Title::newMainPage()->getLocalURL(),
195        ];
196
197        $about = [
198            'text' => $skin->msg( 'about' )->escaped(),
199            'href' => Skin::makeInternalOrExternalUrl(
200                $skin->msg( 'aboutpage' )->inContentLanguage()->text()
201            )
202        ];
203
204        $syslinks = [
205            'cb-mainpage' => $mainpage,
206            'cb-about' => $about,
207            'cb-help' => [
208                'text' => $skin->msg( 'help' )->escaped(),
209                'href' => Skin::makeInternalOrExternalUrl(
210                    $skin->msg( 'helppage' )->inContentLanguage()->text()
211                ),
212            ],
213            'cb-faq' => [
214                'text' => $skin->msg( 'faq' )->escaped(),
215                'href' => Skin::makeInternalOrExternalUrl(
216                    $skin->msg( 'faqpage' )->inContentLanguage()->text()
217                )
218            ],
219        ];
220
221        if ( $skin->getUser()->isAnon() ) {
222            $syslinks['cb-create-account'] = [
223                'text' => $skin->msg( 'pt-createaccount' )->escaped(),
224                'href' => Title::newFromText( 'Special:CreateAccount' )->getLocalURL(),
225            ];
226            $syslinks['cb-login'] = [
227                'text' => $skin->msg( 'pt-login' )->escaped(),
228                'href' => Title::newFromText( 'Special:UserLogin' )->getLocalURL(),
229            ];
230        } else {
231            $syslinks['cb-logout'] = [
232                'text' => $skin->msg( 'pt-userlogout' )->escaped(),
233                'data-mw' => 'interface',
234                'href' => Title::newFromText( 'Special:UserLogout' )->getLocalURL(),
235            ];
236        }
237
238        $content_navigation['cb-syslinks'] = $syslinks;
239        $content_navigation['cb-footer-syslinks'] = [
240            'cb-mainpage-footer' => $mainpage,
241            'cb-about-footer' => $about,
242        ];
243
244        // Removes logout, login and create account from the personal menus tool
245        // for Cologne Blue for historic reasons.
246        $qbmyoptions = $content_navigation['user-menu'] ?? [];
247        foreach ( [ 'logout', 'createaccount', 'login' ] as $key ) {
248            unset( $qbmyoptions[$key] );
249        }
250        $content_navigation['user-menu'] = $qbmyoptions;
251    }
252}