Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
87.69% |
57 / 65 |
|
55.56% |
5 / 9 |
CRAP | |
0.00% |
0 / 1 |
CampaignStore | |
87.69% |
57 / 65 |
|
55.56% |
5 / 9 |
18.60 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getSelectFields | |
81.82% |
9 / 11 |
|
0.00% |
0 / 1 |
3.05 | |||
getSelectTables | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
getJoinConds | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
2.15 | |||
newRecordFromRow | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
4 | |||
newSelectQueryBuilder | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
upsertCampaign | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
3 | |||
deleteCampaignByPageId | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
getCampaignByDBKey | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\MediaUploader\Campaign; |
4 | |
5 | use FormatJson; |
6 | use IDBAccessObject; |
7 | use stdClass; |
8 | use Title; |
9 | use Wikimedia\Rdbms\IConnectionProvider; |
10 | |
11 | /** |
12 | * Provides access to the mu_campaign database table. |
13 | */ |
14 | class CampaignStore implements IDBAccessObject { |
15 | |
16 | // Constants controlling how much information from the DB should be retrieved. |
17 | /** @var int Only the id, enabled and validity fields */ |
18 | public const SELECT_MINIMAL = 0; |
19 | /** @var int The content of the campaign */ |
20 | public const SELECT_CONTENT = 1; |
21 | /** @var int The title of the corresponding page */ |
22 | public const SELECT_TITLE = 2; |
23 | |
24 | private IConnectionProvider $dbProvider; |
25 | |
26 | /** |
27 | * @internal only for use by ServiceWiring |
28 | */ |
29 | public function __construct( IConnectionProvider $dbProvider ) { |
30 | $this->dbProvider = $dbProvider; |
31 | } |
32 | |
33 | /** |
34 | * Returns an array of all fields in the mu_campaign table. |
35 | * |
36 | * @param int $selectFlags Bitfield of self::SELECT_* constants |
37 | * |
38 | * @return string[] |
39 | */ |
40 | public function getSelectFields( |
41 | int $selectFlags = self::SELECT_MINIMAL |
42 | ): array { |
43 | $fields = [ |
44 | 'campaign_page_id', |
45 | 'campaign_enabled', |
46 | 'campaign_validity', |
47 | ]; |
48 | if ( self::SELECT_CONTENT & $selectFlags ) { |
49 | $fields[] = 'campaign_content'; |
50 | } |
51 | if ( self::SELECT_TITLE & $selectFlags ) { |
52 | $fields[] = 'page_title'; |
53 | $fields[] = 'page_namespace'; |
54 | } |
55 | |
56 | return $fields; |
57 | } |
58 | |
59 | /** |
60 | * Returns an array of tables for SELECT queries. |
61 | * |
62 | * @param int $selectFlags Bitfield of self::SELECT_* constants |
63 | * |
64 | * @return string[] |
65 | */ |
66 | public function getSelectTables( |
67 | int $selectFlags = self::SELECT_MINIMAL |
68 | ): array { |
69 | $tables = [ 'mu_campaign' ]; |
70 | if ( self::SELECT_TITLE & $selectFlags ) { |
71 | $tables[] = 'page'; |
72 | } |
73 | |
74 | return $tables; |
75 | } |
76 | |
77 | /** |
78 | * Returns an array of join conditions for SELECT queries. |
79 | * |
80 | * @param int $selectFlags Bitfield of self::SELECT_* constants |
81 | * |
82 | * @return array |
83 | */ |
84 | public function getJoinConds( |
85 | int $selectFlags = self::SELECT_MINIMAL |
86 | ): array { |
87 | if ( self::SELECT_TITLE & $selectFlags ) { |
88 | return [ 'page' => [ 'JOIN', 'campaign_page_id = page_id' ] ]; |
89 | } |
90 | return []; |
91 | } |
92 | |
93 | /** |
94 | * Constructs a new CampaignRecord from a DB row. |
95 | * |
96 | * @param stdClass $row |
97 | * @param int $selectFlags Bitfield of self::SELECT_* constants used to |
98 | * retrieve the row from the DB. |
99 | * |
100 | * @return CampaignRecord |
101 | */ |
102 | public function newRecordFromRow( |
103 | stdClass $row, |
104 | int $selectFlags |
105 | ): CampaignRecord { |
106 | $content = null; |
107 | if ( self::SELECT_CONTENT & $selectFlags && $row->campaign_content ) { |
108 | $content = FormatJson::parse( |
109 | $row->campaign_content, |
110 | FormatJson::FORCE_ASSOC |
111 | )->getValue(); |
112 | } |
113 | |
114 | $title = null; |
115 | if ( self::SELECT_TITLE & $selectFlags ) { |
116 | // Performance hack: in case any code down the line decides to obtain |
117 | // the page ID from the Title object, we set that info artificially on |
118 | // the DB row, as we know it from the mu_campaign table. |
119 | $row->page_id = $row->campaign_page_id; |
120 | $title = Title::newFromRow( $row ); |
121 | } |
122 | |
123 | return new CampaignRecord( |
124 | $row->campaign_page_id, |
125 | (bool)$row->campaign_enabled, |
126 | $row->campaign_validity, |
127 | $content, |
128 | $title |
129 | ); |
130 | } |
131 | |
132 | /** |
133 | * Constructs a new CampaignSelectQueryBuilder. |
134 | * |
135 | * @return CampaignSelectQueryBuilder |
136 | */ |
137 | public function newSelectQueryBuilder(): CampaignSelectQueryBuilder { |
138 | $db = $this->dbProvider->getReplicaDatabase(); |
139 | $queryBuilder = new CampaignSelectQueryBuilder( $db, $this ); |
140 | return $queryBuilder; |
141 | } |
142 | |
143 | /** |
144 | * Insert or update an existing row in the database. |
145 | * |
146 | * @param CampaignRecord $record |
147 | */ |
148 | public function upsertCampaign( CampaignRecord $record ): void { |
149 | $db = $this->dbProvider->getPrimaryDatabase(); |
150 | $content = $record->getContent(); |
151 | if ( $content !== null ) { |
152 | $content = FormatJson::encode( $content ); |
153 | } |
154 | |
155 | $set = [ |
156 | 'campaign_enabled' => $record->isEnabled() ? 1 : 0, |
157 | 'campaign_validity' => $record->getValidity(), |
158 | 'campaign_content' => $content, |
159 | ]; |
160 | $db->upsert( |
161 | 'mu_campaign', |
162 | $set + [ 'campaign_page_id' => $record->getPageId() ], |
163 | 'campaign_page_id', |
164 | $set, |
165 | __METHOD__ |
166 | ); |
167 | } |
168 | |
169 | /** |
170 | * Delete a campaign row in the DB by its page id (PK). |
171 | * |
172 | * @param int $pageId |
173 | */ |
174 | public function deleteCampaignByPageId( int $pageId ): void { |
175 | $db = $this->dbProvider->getPrimaryDatabase(); |
176 | $db->delete( |
177 | 'mu_campaign', |
178 | [ 'campaign_page_id' => $pageId ], |
179 | __METHOD__ |
180 | ); |
181 | } |
182 | |
183 | /** |
184 | * Convenience function to retrieve a record for a given DB key. |
185 | * |
186 | * @param string $dbKey |
187 | * @param int $selectFlags Bitfield of self::SELECT_* constants used to |
188 | * retrieve the row from the DB. SELECT_TITLE is always included |
189 | * regardless of this parameter. |
190 | * |
191 | * @return CampaignRecord|null |
192 | */ |
193 | public function getCampaignByDBKey( |
194 | string $dbKey, |
195 | int $selectFlags = self::SELECT_TITLE |
196 | ): ?CampaignRecord { |
197 | $selectFlags |= self::SELECT_TITLE; |
198 | return $this->newSelectQueryBuilder() |
199 | ->where( [ 'page_title' => $dbKey ] ) |
200 | ->fetchCampaignRecord( $selectFlags ); |
201 | } |
202 | } |