Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.92% covered (success)
95.92%
47 / 49
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
EventTopicsStore
95.92% covered (success)
95.92%
47 / 49
50.00% covered (danger)
50.00%
2 / 4
11
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getEventTopics
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEventTopicsMulti
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
3.00
 addOrUpdateEventTopics
96.97% covered (success)
96.97%
32 / 33
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare( strict_types=1 );
4
5namespace MediaWiki\Extension\CampaignEvents\Event\Store;
6
7use MediaWiki\Extension\CampaignEvents\Database\CampaignsDatabaseHelper;
8
9/**
10 * This class abstracts access to the ce_event_topics DB table.
11 * @note This class is intended to manage event and topic relationships within the CampaignEvents extension.
12 */
13class EventTopicsStore {
14    public const SERVICE_NAME = 'CampaignEventsEventTopicsStore';
15
16    private CampaignsDatabaseHelper $dbHelper;
17    private bool $featureEnabled;
18
19    public function __construct(
20        CampaignsDatabaseHelper $dbHelper,
21        bool $featureEnabled
22    ) {
23        $this->dbHelper = $dbHelper;
24        $this->featureEnabled = $featureEnabled;
25    }
26
27    /**
28     * Retrieves all topics (ceet_topics) associated with a specific event ID.
29     *
30     * @param int $eventID
31     * @return string[] List of topics IDs
32     */
33    public function getEventTopics( int $eventID ) {
34        return $this->getEventTopicsMulti( [ $eventID ] )[$eventID];
35    }
36
37    /**
38     * Retrieves all topics associated with the given events.
39     *
40     * @param int[] $eventIDs
41     * @return array<int,string[]> Maps event ID to a list of topic IDs
42     */
43    public function getEventTopicsMulti( array $eventIDs ): array {
44        $topicsByEvent = array_fill_keys( $eventIDs, [] );
45        if ( !$this->featureEnabled ) {
46            return $topicsByEvent;
47        }
48
49        $dbr = $this->dbHelper->getDBConnection( DB_REPLICA );
50        $queryBuilder = $dbr->newSelectQueryBuilder();
51        $res = $queryBuilder->select( [ 'ceet_event_id', 'ceet_topic' ] )
52            ->from( 'ce_event_topics' )
53            ->where( [ 'ceet_event_id' => $eventIDs ] )
54            ->caller( __METHOD__ )
55            ->fetchResultSet();
56
57        foreach ( $res as $row ) {
58            $topicsByEvent[$row->ceet_event_id][] = $row->ceet_topic;
59        }
60        return $topicsByEvent;
61    }
62
63    /**
64     * Adds topics for a specific event ID.
65     *
66     * @param int $eventID The event ID to associate these topics with.
67     * @param string[] $eventTopics An array of topic IDs to add
68     */
69    public function addOrUpdateEventTopics( int $eventID, array $eventTopics ): void {
70        if ( !$this->featureEnabled ) {
71            return;
72        }
73        $dbw = $this->dbHelper->getDBConnection( DB_PRIMARY );
74
75        $queryBuilder = $dbw->newSelectQueryBuilder();
76        $currentTopicsRes = $queryBuilder->select( [ 'ceet_id', 'ceet_topic' ] )
77            ->from( 'ce_event_topics' )
78            ->where( [ 'ceet_event_id' => $eventID ] )
79            ->caller( __METHOD__ )
80            ->fetchResultSet();
81        $currentTopicsByID = [];
82        foreach ( $currentTopicsRes as $row ) {
83            $currentTopicsByID[$row->ceet_id] = $row->ceet_topic;
84        }
85
86        $rowIDsToRemove = array_keys( array_diff( $currentTopicsByID, $eventTopics ) );
87        $topicsToAdd = array_diff( $eventTopics, $currentTopicsByID );
88
89        if ( count( $rowIDsToRemove ) > 0 ) {
90            $deleteQueryBuilder = $dbw->newDeleteQueryBuilder();
91            $deleteQueryBuilder->delete( 'ce_event_topics' )
92                ->where( [ 'ceet_id' => $rowIDsToRemove ] )
93                ->caller( __METHOD__ )
94                ->execute();
95        }
96
97        if ( count( $topicsToAdd ) > 0 ) {
98            $rows = [];
99            foreach ( $topicsToAdd as $topic ) {
100                $rows[] = [
101                    'ceet_event_id' => $eventID,
102                    'ceet_topic' => $topic
103                ];
104            }
105
106            $insertQueryBuilder = $dbw->newInsertQueryBuilder();
107            $insertQueryBuilder->insertInto( 'ce_event_topics' )
108                ->ignore()
109                ->rows( $rows )
110                ->caller( __METHOD__ )
111                ->execute();
112        }
113    }
114}