Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
67.92% covered (warning)
67.92%
36 / 53
62.50% covered (warning)
62.50%
5 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
MassMessageListContent
67.92% covered (warning)
67.92%
36 / 53
62.50% covered (warning)
62.50%
5 / 8
56.75
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isValid
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
7
 hasInvalidTargets
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDescription
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getTargets
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 getValidTargets
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
 getTargetStrings
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 decode
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2
3namespace MediaWiki\MassMessage\Content;
4
5use JsonContent;
6use MediaWiki\MassMessage\Lookup\DatabaseLookup;
7use MediaWiki\MassMessage\UrlHelper;
8use MediaWiki\MediaWikiServices;
9use MediaWiki\Title\Title;
10
11class MassMessageListContent extends JsonContent {
12
13    /**
14     * Description wikitext.
15     *
16     * @var string|null
17     */
18    protected $description;
19
20    /**
21     * Array of target pages.
22     *
23     * @var array[]|null
24     */
25    protected $targets;
26
27    /**
28     * Whether $description and $targets have been populated.
29     *
30     * @var bool
31     */
32    protected $decoded = false;
33
34    /**
35     * @param string $text
36     */
37    public function __construct( $text ) {
38        parent::__construct( $text, 'MassMessageListContent' );
39    }
40
41    /**
42     * Decode and validate the contents.
43     *
44     * @return bool Whether the contents are valid
45     */
46    public function isValid() {
47        // Populate $this->description and $this->targets.
48        $this->decode();
49
50        if ( !is_string( $this->description ) || !is_array( $this->targets ) ) {
51            return false;
52        }
53        foreach ( $this->getTargets() as $target ) {
54            if ( !is_array( $target )
55                || !array_key_exists( 'title', $target )
56                || Title::newFromText( $target['title'] ) === null
57            ) {
58                return false;
59            }
60        }
61        return true;
62    }
63
64    /**
65     * Whether the content object contains invalid targets.
66     *
67     * @return bool
68     */
69    public function hasInvalidTargets() {
70        return count( $this->getTargets() ) !== count( $this->getValidTargets() );
71    }
72
73    /**
74     * @return string|null
75     */
76    public function getDescription() {
77        $this->decode();
78        return $this->description;
79    }
80
81    /**
82     * @return array[]
83     */
84    public function getTargets() {
85        $this->decode();
86        if ( is_array( $this->targets ) ) {
87            return $this->targets;
88        }
89        return [];
90    }
91
92    /**
93     * Return only the targets that would be valid for delivery.
94     *
95     * @return array
96     */
97    public function getValidTargets() {
98        $targets = $this->getTargets();
99        $validTargets = [];
100        foreach ( $targets as $target ) {
101            if ( !array_key_exists( 'site', $target )
102                || ( MediaWikiServices::getInstance()->getMainConfig()->get( 'AllowGlobalMessaging' )
103                && DatabaseLookup::getDBName( $target['site'] ) !== null )
104            ) {
105                $validTargets[] = $target;
106            }
107        }
108        return $validTargets;
109    }
110
111    /**
112     * Return targets as an array of title or title@site strings.
113     *
114     * @return array
115     */
116    public function getTargetStrings() {
117        $targets = $this->getTargets();
118        $targetStrings = [];
119        foreach ( $targets as $target ) {
120            if ( array_key_exists( 'site', $target ) ) {
121                $targetStrings[] = $target['title'] . '@' . $target['site'];
122            } elseif ( strpos( $target['title'], '@' ) !== false ) {
123                // List the site if it'd otherwise be ambiguous
124                $targetStrings[] = $target['title'] . '@'
125                    . UrlHelper::getBaseUrl(
126                        MediaWikiServices::getInstance()->getMainConfig()
127                            ->get( 'CanonicalServer' )
128                    );
129            } else {
130                $targetStrings[] = $target['title'];
131            }
132        }
133        return $targetStrings;
134    }
135
136    /**
137     * Decode the JSON contents and populate $description and $targets.
138     */
139    protected function decode() {
140        if ( $this->decoded ) {
141            return;
142        }
143        $jsonParse = $this->getData();
144        $data = $jsonParse->isGood() ? $jsonParse->getValue() : null;
145        if ( $data ) {
146            $this->description = $data->description ?? null;
147            if ( isset( $data->targets ) && is_array( $data->targets ) ) {
148                $this->targets = [];
149                foreach ( $data->targets as $target ) {
150                    if ( !is_object( $target ) ) {
151                        // There is a malformed target.
152                        $this->targets = null;
153                        break;
154                    }
155                    // Convert to associative array.
156                    $this->targets[] = wfObjectToArray( $target );
157                }
158            } else {
159                $this->targets = null;
160            }
161        }
162        $this->decoded = true;
163    }
164}