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