Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
48.15% covered (danger)
48.15%
13 / 27
71.43% covered (warning)
71.43%
5 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ContainmentSet
48.15% covered (danger)
48.15%
13 / 27
71.43% covered (warning)
71.43%
5 / 7
36.56
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
 add
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addArray
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addFromUserOption
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 addTitleIDsFromUserOption
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 addOnWiki
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 contains
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace MediaWiki\Extension\Notifications;
4
5use BadMethodCallException;
6use MediaWiki\MediaWikiServices;
7use MediaWiki\Preferences\MultiUsernameFilter;
8use MediaWiki\User\User;
9use WANObjectCache;
10
11/**
12 * Utilizes ContainmentList interface to provide a fluent interface to whitelist/blacklist
13 * from multiple sources like global variables, wiki pages, etc.
14 *
15 * Initialize:
16 *   $cache = ObjectCache::getLocalClusterInstance();
17 *   $set = new ContainmentSet;
18 *   $set->addArray( $wgSomeGlobalParameter );
19 *   $set->addOnWiki( NS_USER, 'Foo/bar-baz', $cache, 'some_user_specific_cache_key' );
20 *
21 * Usage:
22 *   if ( $set->contains( 'SomeUser' ) ) {
23 *       ...
24 *   }
25 */
26class ContainmentSet {
27    /**
28     * @var ContainmentList[]
29     */
30    protected $lists = [];
31
32    /**
33     * @var User
34     */
35    protected $recipient;
36
37    /**
38     * @param User $recipient
39     */
40    public function __construct( User $recipient ) {
41        $this->recipient = $recipient;
42    }
43
44    /**
45     * Add an ContainmentList to the set of lists checked by self::contains()
46     *
47     * @param ContainmentList $list
48     */
49    public function add( ContainmentList $list ) {
50        $this->lists[] = $list;
51    }
52
53    /**
54     * Add a php array to the set of lists checked by self::contains()
55     *
56     * @param array $list
57     */
58    public function addArray( array $list ) {
59        $this->add( new ArrayList( $list ) );
60    }
61
62    /**
63     * Add a list from a user preference to the set of lists checked by self::contains().
64     *
65     * @param string $preferenceName
66     */
67    public function addFromUserOption( string $preferenceName ) {
68        $userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
69        $preference = $userOptionsLookup->getOption( $this->recipient, $preferenceName, [] );
70        if ( $preference ) {
71            $ids = MultiUsernameFilter::splitIds( $preference );
72            $names = MediaWikiServices::getInstance()
73                ->getCentralIdLookup()
74                ->namesFromCentralIds( $ids, $this->recipient );
75            $this->addArray( $names );
76        }
77    }
78
79    /**
80     * Add a list of title IDs from a user preference to the set of lists
81     * checked by self::contains().
82     *
83     * @param string $preferenceName
84     */
85    public function addTitleIDsFromUserOption( string $preferenceName ): void {
86        $userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
87        $preference = $userOptionsLookup->getOption( $this->recipient, $preferenceName, [] );
88        if ( !is_string( $preference ) ) {
89            // We expect the preference data to be saved as a string via the
90            // preferences form; if the user modified their data so it's no
91            // longer a string, ignore it.
92            return;
93        }
94        $titleIDs = preg_split( '/\n/', $preference, -1, PREG_SPLIT_NO_EMPTY );
95        $this->addArray( $titleIDs );
96    }
97
98    /**
99     * Add a list from a wiki page to the set of lists checked by self::contains().  Data
100     * from wiki pages is cached via the BagOStuff.  Caching is disabled when passing a null
101     * $cache object.
102     *
103     * @param int $namespace An NS_* constant representing the mediawiki namespace of the page containing the list.
104     * @param string $title The title of the page containing the list.
105     * @param WANObjectCache|null $cache An object to cache the page with or null for no cache.
106     * @param string $cacheKeyPrefix A prefix to be combined with the pages latest revision id and used as a cache key.
107     */
108    public function addOnWiki(
109        $namespace, $title, WANObjectCache $cache = null, $cacheKeyPrefix = ''
110    ) {
111        $list = new OnWikiList( $namespace, $title );
112        if ( $cache ) {
113            if ( $cacheKeyPrefix === '' ) {
114                throw new BadMethodCallException( 'Cache requires providing a cache key prefix.' );
115            }
116            $list = new CachedList( $cache, $cacheKeyPrefix, $list );
117        }
118        $this->add( $list );
119    }
120
121    /**
122     * Test the wrapped lists for existence of $value
123     *
124     * @param mixed $value The value to look for
125     * @return bool True when the set contains the provided value
126     */
127    public function contains( $value ) {
128        foreach ( $this->lists as $list ) {
129            // Use strict comparison to prevent the number 0 from matching all strings (T177825)
130            if ( in_array( $value, $list->getValues(), true ) ) {
131                return true;
132            }
133        }
134
135        return false;
136    }
137}