Test Setup Failed
Pull Request — main (#426)
by MusikAnimal
17:10 queued 11:44
created

RfXVoteCalculatorController::indexAction()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 2
nop 0
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains the code that powers the RfX Vote Calculator page of XTools.
4
 */
5
6
declare(strict_types=1);
7
8
namespace App\Controller;
9
10
use App\Model\RFX;
11
use App\Repository\PageRepository;
12
use Doctrine\DBAL\Connection;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\Routing\Annotation\Route;
15
16
/**
17
 * Controller for the RfX Vote Calculator.
18
 * @codeCoverageIgnore
19
 */
20
class RfXVoteCalculatorController extends XtoolsController
21
{
22
    /**
23
     * Get the name of the tool's index route.
24
     * @return string
25
     * @codeCoverageIgnore
26
     */
27
    public function getIndexRoute(): string
28
    {
29
        return 'RfXVoteCalculator';
30
    }
31
32
    /**
33
     * Renders the index page for RfXVoteCalculator
34
     *
35
     * @Route("/rfxvote", name="RfXVoteCalculator")
36
     * @Route("/rfxvote/index.php", name="RfXVoteCalculatorIndexPhp")
37
     * @return Response
38
     */
39
    public function indexAction(): Response
40
    {
41
        // Redirect if at minimum project, username and categories are provided.
42
        if (isset($this->params['project']) && isset($this->params['username'])) {
43
            return $this->redirectToRoute('RfXVoteResult', $this->params);
44
        }
45
46
        return $this->render(
47
            'rfxVoteCalculator/index.html.twig',
48
            [
49
                'xtPageTitle' => 'tool-rfxvote',
50
                'xtSubtitle' => 'tool-rfxvote-desc',
51
                'xtPage' => 'RfXVoteCalculator',
52
                'project' => $this->project,
53
            ]
54
        );
55
    }
56
57
    /**
58
     * Result View of RfXVoteCalculator
59
     * @Route("/rfxvote/{project}/{username}", name="RfXVoteResult")
60
     * @return Response
61
     * @codeCoverageIgnore
62
     */
63
    public function resultAction(): Response
64
    {
65
        /** @var Connection $conn */
66
        $conn = $this->getDoctrine()->getManager('replicas')->getConnection();
0 ignored issues
show
Bug introduced by
The method getConnection() does not exist on Doctrine\Persistence\ObjectManager. It seems like you code against a sub-type of said class. However, the method does not exist in Doctrine\Persistence\ObjectManagerDecorator. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

66
        $conn = $this->getDoctrine()->getManager('replicas')->/** @scrutinizer ignore-call */ getConnection();
Loading history...
67
68
        $projectRepo = $this->project->getRepository();
69
        $pageRepo = new PageRepository();
70
        $pageRepo->setContainer($this->container);
71
72
        $dbName = $this->project->getDatabaseName();
73
74
        $rfxParam = $this->getParameter('rfx');
75
76
        $namespaces = $this->project->getNamespaces();
77
78
        if (!isset($rfxParam[$this->project->getDomain()])) {
79
            $this->addFlashMessage('notice', 'invalid-project-cant-use', [$this->project->getDomain()]);
80
            return $this->redirectToRoute('RfXVoteCalculator');
81
        }
82
83
        $pageTypes = $rfxParam[$this->project->getDomain()]['pages'];
84
        $namespace = $rfxParam[$this->project->getDomain()]['rfx_namespace'] ?? 4;
85
86
        $finalData = [];
87
88
        // We should probably figure out a better way to do this...
89
        $ignoredPages = '';
90
91
        if (isset($rfxParam[$this->project->getDomain()]['excluded_title'])) {
92
            $titlesExcluded
93
                = $rfxParam[$this->project->getDomain()]['excluded_title'];
94
            foreach ($titlesExcluded as $ignoredPage) {
95
                $ignoredPages .= "AND p.page_title != \"$ignoredPage\"\r\n";
96
            }
97
        }
98
99
        if (isset($rfxParam[$this->project->getDomain()]['excluded_regex'])) {
100
            $titlesExcluded
101
                = $rfxParam[$this->project->getDomain()]['excluded_regex'];
102
            foreach ($titlesExcluded as $ignoredPage) {
103
                $ignoredPages .= "AND p.page_title NOT LIKE \"%$ignoredPage%\"\r\n";
104
            }
105
        }
106
107
        /**
108
         * Contains the total number of !votes the user made, keyed by the RfX
109
         * type and then the vote type.
110
         * @var array
111
         */
112
        $totals = [];
113
114
        foreach ($pageTypes as $type) {
115
            $type = explode(':', $type, 2)[1];
116
117
            $type = str_replace(' ', '_', $type);
118
119
            $pageTable = $projectRepo->getTableName($dbName, 'page');
120
            $revisionTable = $projectRepo->getTableName($dbName, 'revision');
121
            $username = $this->user->getUsername();
122
123
            $sql = "SELECT DISTINCT p.page_namespace, p.page_title
124
                    FROM $pageTable p
125
                    RIGHT JOIN $revisionTable r on p.page_id=r.rev_page
126
                    WHERE p.page_namespace = :namespace
127
                    AND r.rev_user_text = :username
128
                    And p.page_title LIKE \"$type/%\"
129
                    AND p.page_title NOT LIKE \"%$type/$username%\"
130
                    $ignoredPages";
131
132
            $sth = $conn->prepare($sql);
133
            $sth->bindParam('namespace', $namespace);
134
            $sth->bindParam('username', $username);
135
136
            $sth->execute();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Statement::execute() has been deprecated: Statement::execute() is deprecated, use Statement::executeQuery() or executeStatement() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

136
            /** @scrutinizer ignore-deprecated */ $sth->execute();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
137
138
            $titles = [];
139
140
            while ($row = $sth->fetch()) {
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Statement::fetch() has been deprecated: Use fetchNumeric(), fetchAssociative() or fetchOne() instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

140
            while ($row = /** @scrutinizer ignore-deprecated */ $sth->fetch()) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
141
                $titles[] = $namespaces[$row['page_namespace']] .
142
                    ':' .$row['page_title'];
143
            }
144
145
            // Chunking... it's possible to make a URI too long
146
            $titleArray = array_chunk($titles, 20);
147
148
            foreach ($titleArray as $titlesWorked) {
149
                $pageData = $pageRepo->getPagesWikitext($this->project, $titlesWorked);
150
151
                foreach ($pageData as $title => $text) {
152
                    $type = str_replace('_', ' ', $type);
153
                    $rfx = new RFX(
154
                        $text,
155
                        $rfxParam[$this->project->getDomain()]['sections'],
156
                        $namespaces[2],
157
                        $rfxParam[$this->project->getDomain()]['date_regexp'],
158
                        $username
159
                    );
160
                    $section = $rfx->getUserSectionFound();
161
162
                    if ('' == $section) {
163
                        // Skip over ones where the user didn't !vote.
164
                        continue;
165
                    }
166
167
                    if (!isset($totals[$type])) {
168
                        $totals[$type] = [];
169
                    }
170
                    if (!isset($totals[$type][$section])) {
171
                        $totals[$type][$section] = 0;
172
                    }
173
                    if (!isset($totals[$type]['total'])) {
174
                        $totals[$type]['total'] = 0;
175
                    }
176
                    $totals[$type][$section] += 1;
177
                    $totals[$type]['total'] += 1;
178
179
                    // Todo: i18n-ize this
180
                    $finalData[$type][$section][$title]['Support']
181
                        = sizeof($rfx->getSection('support'));
182
                    $finalData[$type][$section][$title]['Oppose']
183
                        = sizeof($rfx->getSection('oppose'));
184
                    $finalData[$type][$section][$title]['Neutral']
185
                        = sizeof($rfx->getSection('neutral'));
186
                    $finalData[$type][$section][$title]['Date']
187
                        = $rfx->getEnd();
188
                    $finalData[$type][$section][$title]['name']
189
                        = explode('/', $title)[1];
190
191
                    unset($rfx);
192
                }
193
            }
194
        }
195
196
        return $this->render(
197
            'rfxVoteCalculator/result.html.twig',
198
            [
199
                'xtPage' => 'RfXVoteCalculator',
200
                'xtTitle' => $this->user->getUsername(),
201
                'user' => $this->user,
202
                'project' => $this->project,
203
                'data'=> $finalData,
204
                'totals' => $totals,
205
            ]
206
        );
207
    }
208
}
209