Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
DynamicSidebarHooks
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 7
1260
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
 onSidebarBeforeOutput
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
272
 doUserSidebar
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 doGroupSidebar
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
 doPageCategorySidebar
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 doCategorySidebar
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
56
 printDebug
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace MediaWiki\Extension\DynamicSidebar;
4
5use Article;
6use MediaWiki\Hook\SidebarBeforeOutputHook;
7use MediaWiki\HookContainer\HookContainer;
8use MediaWiki\User\UserGroupManager;
9use Skin;
10use TextContent;
11use Title;
12use User;
13
14class DynamicSidebarHooks implements SidebarBeforeOutputHook {
15    /** @var HookContainer */
16    private $hookContainer;
17    /** @var UserGroupManager */
18    private $userGroupManager;
19
20    /**
21     * @param HookContainer $hookContainer
22     * @param UserGroupManager $userGroupManager
23     */
24    public function __construct(
25        HookContainer $hookContainer,
26        UserGroupManager $userGroupManager
27    ) {
28        $this->hookContainer = $hookContainer;
29        $this->userGroupManager = $userGroupManager;
30    }
31
32    /**
33     * Called from SidebarBeforeOutput hook. Modifies the sidebar
34     * via callbacks.
35     *
36     * @param Skin $skin
37     * @param array &$sidebar
38     */
39    public function onSidebarBeforeOutput( $skin, &$sidebar ): void {
40        $config = $skin->getConfig();
41
42        $dynamicSidebarUseGroups = $config->get( 'DynamicSidebarUseGroups' );
43        $dynamicSidebarUseUserpages = $config->get( 'DynamicSidebarUseUserpages' );
44        $dynamicSidebarUseCategories = $config->get( 'DynamicSidebarUseCategories' );
45        $dynamicSidebarUsePageCategories = $config->get( 'DynamicSidebarUsePageCategories' );
46
47        self::printDebug( "Entering onSidebarBeforeOutput" );
48        $groupSB = [];
49        $userSB = [];
50        $catSB = [];
51        $user = $skin->getUser();
52        if ( $dynamicSidebarUseGroups && isset( $sidebar['GROUP-SIDEBAR'] ) ) {
53            self::printDebug( "Using group sidebar" );
54            $skin->addToSidebarPlain(
55                $groupSB,
56                self::doGroupSidebar( $user, $this->userGroupManager, $this->hookContainer )
57            );
58        }
59        if ( $dynamicSidebarUseUserpages && isset( $sidebar['USER-SIDEBAR'] ) ) {
60            self::printDebug( "Using user sidebar" );
61            $skin->addToSidebarPlain( $userSB, self::doUserSidebar( $user ) );
62        }
63        if ( $dynamicSidebarUseCategories && isset( $sidebar['CATEGORY-SIDEBAR'] ) ) {
64            self::printDebug( "Using category sidebar" );
65            $skin->addToSidebarPlain( $catSB, self::doCategorySidebar( $user ) );
66        }
67        if ( $dynamicSidebarUsePageCategories && isset( $sidebar['CATEGORY-SIDEBAR'] ) ) {
68            self::printDebug( "Using category sidebar" );
69            $skin->addToSidebarPlain( $catSB, self::doPageCategorySidebar( $user, $skin->getTitle() ) );
70        }
71
72        $sidebar_copy = [];
73
74        foreach ( $sidebar as $sidebar_key => $sidebar_item ) {
75            if ( $sidebar_key == 'GROUP-SIDEBAR' ) {
76                // Replace the GROUP-SIDEBAR entry with the group's sidebar
77                foreach ( $groupSB as $groupSBkey => $groupSBvalue ) {
78                    $sidebar_copy[$groupSBkey] = $groupSBvalue;
79                }
80            } elseif ( $sidebar_key == 'USER-SIDEBAR' ) {
81                // Replace the USER-SIDEBAR entry with the user's sidebar
82                foreach ( $userSB as $userSBkey => $userSBvalue ) {
83                    $sidebar_copy[$userSBkey] = $userSBvalue;
84                }
85            } elseif ( $sidebar_key == 'CATEGORY-SIDEBAR' ) {
86                // Replace the CATEGORY-SIDEBAR entry with the category's sidebar
87                foreach ( $catSB as $catSBkey => $catSBvalue ) {
88                    $sidebar_copy[$catSBkey] = $catSBvalue;
89                }
90            } else {
91                // Add the original array item back
92                $sidebar_copy[$sidebar_key] = $sidebar_item;
93            }
94        }
95
96        $sidebar = $sidebar_copy;
97    }
98
99    /**
100     * Grabs the sidebar for the current user
101     * User:<username>/Sidebar
102     *
103     * @param User $user
104     * @return string|null
105     */
106    private static function doUserSidebar( User $user ) {
107        $username = $user->getName();
108
109        // does 'User:<username>/Sidebar' page exist?
110        $title = Title::makeTitle( NS_USER, $username . '/Sidebar' );
111        if ( !$title->exists() ) {
112            // Remove this sidebar if not
113            return '';
114        }
115
116        $revid = $title->getLatestRevID();
117        $a = new Article( $title, $revid );
118
119        $content = $a->getPage()->getContent();
120        return ( $content instanceof TextContent ) ? $content->getText() : null;
121    }
122
123    /**
124     * Grabs the sidebar for the current user's groups
125     *
126     * @param User $user
127     * @param UserGroupManager $userGroupManager
128     * @param HookContainer $hookContainer
129     * @return string
130     */
131    private static function doGroupSidebar(
132        User $user,
133        UserGroupManager $userGroupManager,
134        HookContainer $hookContainer
135    ) {
136        // Get group membership array.
137        $groups = $userGroupManager->getUserEffectiveGroups( $user );
138        $hookContainer->run( 'DynamicSidebarGetGroups', [ &$groups ] );
139        // Did we find any groups?
140        if ( count( $groups ) == 0 ) {
141            // Remove this sidebar if not
142            return '';
143        }
144
145        $text = '';
146        foreach ( $groups as $group ) {
147            // Form the path to the article:
148            // MediaWiki:Sidebar/<group>
149            $title = Title::makeTitle( NS_MEDIAWIKI, 'Sidebar/Group:' . $group );
150            if ( !$title->exists() ) {
151                continue;
152            }
153            $revid = $title->getLatestRevID();
154            $a = new Article( $title, $revid );
155
156            $content = $a->getPage()->getContent();
157            $text .= ( $content instanceof TextContent ) ? $content->getText() : "" . "\n";
158
159        }
160        return $text;
161    }
162
163    /**
164     * @param User $user
165     * @param Title $title
166     * @return string
167     */
168    private static function doPageCategorySidebar( User $user, Title $title ) {
169        return self::doCategorySidebar( $user, $title->getParentCategories() );
170    }
171
172    /**
173     * Grabs the sidebar for the current user's categories
174     *
175     * @param User $user
176     * @param array|null $categories
177     * @return string
178     */
179    private static function doCategorySidebar( User $user, ?array $categories = null ) {
180        self::printDebug( "User name: {$user->getName()}" );
181        if ( $categories === null ) {
182            $categories = $user->getUserPage()->getParentCategories();
183        }
184
185        // Did we find any categories?
186        if ( !is_array( $categories ) || count( $categories ) == 0 ) {
187            // Remove this sidebar if not.
188            return '';
189        }
190
191        $text = '';
192        // getParentCategories() returns categories in the form:
193        // [ParentCategory] => page
194        // We only care about the parent category
195        foreach ( $categories as $category => $unused ) {
196            // $category is in form Category:<category>
197            // We need <category>.
198            $category = explode( ":", $category );
199            $category = $category[1];
200            self::printDebug( "Checking category: $category" );
201
202            // Form the path to the article:
203            // MediaWiki:Sidebar/<category>
204            $title = Title::makeTitle( NS_MEDIAWIKI, 'Sidebar/Category:' . $category );
205            if ( !$title->exists() ) {
206                self::printDebug( "$category category page doesn't exist." );
207                continue;
208            }
209            $revid = $title->getLatestRevID();
210            $a = new Article( $title, $revid );
211            $content = $a->getPage()->getContent();
212            $text .= ( $content instanceof TextContent ) ? $content->getText() : "" . "\n";
213            self::printDebug( "$category text output is: $text" );
214        }
215        return $text;
216    }
217
218    /**
219     * Prints debugging information. $debugText is what you want to print, $debugArr
220     * will expand into arrItem::arrItem2::arrItem3::... and is appended to $debugText
221     *
222     * @param string $debugText
223     * @param array|null $debugArr
224     */
225    private static function printDebug( $debugText, ?array $debugArr = null ) {
226        if ( $debugArr !== null ) {
227            $text = $debugText . " " . implode( "::", $debugArr );
228            wfDebugLog( 'dynamic-sidebar', $text, false );
229        } else {
230            wfDebugLog( 'dynamic-sidebar', $debugText, false );
231        }
232    }
233}