|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace AppBundle\Controller; |
|
4
|
|
|
|
|
5
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; |
|
6
|
|
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
|
7
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
8
|
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
|
9
|
|
|
|
|
10
|
|
|
class AutomatedEditsController extends Controller |
|
11
|
|
|
{ |
|
12
|
|
|
/** |
|
13
|
|
|
* @Route("/autoedits", name="autoedits") |
|
14
|
|
|
* @Route("/automatededits", name="autoeditsLong") |
|
15
|
|
|
* @Route("/autoedits/index.php", name="autoeditsIndexPhp") |
|
16
|
|
|
* @Route("/automatededits/index.php", name="autoeditsLongIndexPhp") |
|
17
|
|
|
*/ |
|
18
|
|
|
|
|
19
|
|
|
public function indexAction(Request $request) |
|
20
|
|
|
{ |
|
21
|
|
|
// Pull the labs helper and check if enabled |
|
22
|
|
|
$lh = $this->get("app.labs_helper"); |
|
23
|
|
|
$lh->checkEnabled("autoedits"); |
|
24
|
|
|
|
|
25
|
|
|
// Pull the values out of the query string. These values default to |
|
26
|
|
|
// empty strings. |
|
27
|
|
|
$projectQuery = $request->query->get('project'); |
|
28
|
|
|
$username = $request->query->get('username'); |
|
29
|
|
|
$startDate = $request->query->get('start'); |
|
30
|
|
|
$endDate = $request->query->get("end"); |
|
31
|
|
|
|
|
32
|
|
|
// Redirect if the values are set. |
|
33
|
|
View Code Duplication |
if ($projectQuery != "" && $username != "" && $startDate != "" && $endDate != "") { |
|
|
|
|
|
|
34
|
|
|
// Redirect ot the route fully |
|
35
|
|
|
return $this->redirectToRoute( |
|
36
|
|
|
"autoeditsResult", |
|
37
|
|
|
[ |
|
38
|
|
|
'project'=>$projectQuery, |
|
39
|
|
|
'username'=>$username, |
|
40
|
|
|
'start' => $startDate, |
|
41
|
|
|
'end' => $endDate, |
|
42
|
|
|
] |
|
43
|
|
|
); |
|
44
|
|
|
} elseif ($projectQuery != "" && $username != "" && $endDate != "") { |
|
45
|
|
|
// Redirect if we have the username, enddate and project |
|
46
|
|
|
return $this->redirectToRoute( |
|
47
|
|
|
"autoeditsResult", |
|
48
|
|
|
[ |
|
49
|
|
|
'project'=>$projectQuery, |
|
50
|
|
|
'username'=>$username, |
|
51
|
|
|
'end' => $endDate, |
|
52
|
|
|
] |
|
53
|
|
|
); |
|
54
|
|
|
} elseif ($projectQuery != "" && $username != "" && $startDate != "") { |
|
55
|
|
|
// Redirect if we have the username, stardate and project |
|
56
|
|
|
return $this->redirectToRoute( |
|
57
|
|
|
"autoeditsResult", |
|
58
|
|
|
[ |
|
59
|
|
|
'project' => $projectQuery, |
|
60
|
|
|
'username'=>$username, |
|
61
|
|
|
'start' => $startDate, |
|
62
|
|
|
] |
|
63
|
|
|
); |
|
64
|
|
|
} elseif ($projectQuery != "" && $username != "") { |
|
65
|
|
|
// Redirect if we have the username and project |
|
66
|
|
|
return $this->redirectToRoute( |
|
67
|
|
|
"autoeditsResult", |
|
68
|
|
|
[ |
|
69
|
|
|
'project' => $projectQuery, |
|
70
|
|
|
'username'=>$username, |
|
71
|
|
|
] |
|
72
|
|
|
); |
|
73
|
|
|
} elseif ($projectQuery != "") { |
|
74
|
|
|
// Redirect if we have the project name |
|
75
|
|
|
return $this->redirectToRoute( |
|
76
|
|
|
"autoeditsResult", |
|
77
|
|
|
[ |
|
78
|
|
|
'project'=>$projectQuery |
|
79
|
|
|
] |
|
80
|
|
|
); |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
// set default wiki so we can populate the namespace selector |
|
84
|
|
|
if (!$projectQuery) { |
|
85
|
|
|
$projectQuery = $this->container->getParameter('default_project'); |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
/** @var ApiHelper */ |
|
89
|
|
|
$api = $this->get("app.api_helper"); |
|
90
|
|
|
|
|
91
|
|
|
return $this->render('autoEdits/index.html.twig', [ |
|
92
|
|
|
'xtPageTitle' => 'tool_autoedits', |
|
93
|
|
|
'xtSubtitle' => 'tool_autoedits_desc', |
|
94
|
|
|
'xtPage' => 'autoedits', |
|
95
|
|
|
'project' => $projectQuery, |
|
96
|
|
|
'namespaces' => $api->namespaces($projectQuery), |
|
97
|
|
|
]); |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
|
|
/** |
|
101
|
|
|
* @Route("/autoedits/{project}/{username}/{start}/{end}", name="autoeditsResult") |
|
102
|
|
|
*/ |
|
103
|
|
|
public function resultAction($project, $username, $start = null, $end = null) |
|
104
|
|
|
{ |
|
105
|
|
|
// Pull the labs helper and check if enabled |
|
106
|
|
|
$lh = $this->get("app.labs_helper"); |
|
107
|
|
|
$lh->checkEnabled("autoedits"); |
|
108
|
|
|
|
|
109
|
|
|
// Pull information about the project from the Labs Helper |
|
110
|
|
|
$dbValues = $lh->databasePrepare($project, "AutomatedEdits"); |
|
111
|
|
|
|
|
112
|
|
|
$dbName = $dbValues["dbName"]; |
|
113
|
|
|
$wikiName = $dbValues["wikiName"]; |
|
114
|
|
|
$url = $dbValues["url"]; |
|
115
|
|
|
|
|
116
|
|
|
// Grab our database connection |
|
117
|
|
|
$dbh = $this->get('doctrine')->getManager("replicas")->getConnection(); |
|
118
|
|
|
|
|
119
|
|
|
// Variable parsing. |
|
120
|
|
|
// Username needs to be uppercase first (yay Mediawiki), |
|
121
|
|
|
// and we also need to handle undefined dates. |
|
122
|
|
|
$username = ucfirst($username); |
|
123
|
|
|
|
|
124
|
|
|
if ($start == null) { |
|
125
|
|
|
$start = date("Y-m-d", strtotime("-1 month")); |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
if ($end == null) { |
|
129
|
|
|
$end = date("Y-m-d"); |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
// Validating the dates. If the dates are invalid, we'll redirect |
|
133
|
|
|
// to the project and username view. |
|
134
|
|
View Code Duplication |
if (strtotime($start) === false || strtotime($end) === false) { |
|
|
|
|
|
|
135
|
|
|
// Make sure to add the flash notice first. |
|
136
|
|
|
$this->addFlash("notice", ["invalid_date"]); |
|
|
|
|
|
|
137
|
|
|
|
|
138
|
|
|
// Then redirect us! |
|
139
|
|
|
return $this->redirectToRoute( |
|
140
|
|
|
"autoeditsResult", |
|
141
|
|
|
[ |
|
142
|
|
|
"project" => $project, |
|
143
|
|
|
"username" => $username, |
|
144
|
|
|
] |
|
145
|
|
|
); |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
// Now, load the semi-automated edit types. |
|
149
|
|
|
$AEBTypes = []; |
|
|
|
|
|
|
150
|
|
|
$AEBTypes = $this->getParameter("automated_tools"); |
|
151
|
|
|
|
|
152
|
|
|
// Create a collection of queries that we're going to run. |
|
153
|
|
|
$queries = []; |
|
154
|
|
|
|
|
155
|
|
|
$rev = $lh->getTable("revision", $dbName); |
|
156
|
|
|
$arc = $lh->getTable("archive", $dbName); |
|
157
|
|
|
|
|
158
|
|
|
$cond_begin = ( $start ) ? " AND rev_timestamp > :start " : null; |
|
159
|
|
|
$cond_end = ( $end ) ? " AND rev_timestamp < :end ": null; |
|
160
|
|
|
|
|
161
|
|
|
foreach ($AEBTypes as $toolname => $check) { |
|
162
|
|
|
$toolname = $dbh->quote($toolname, \PDO::PARAM_STR); |
|
163
|
|
|
$check = $dbh->quote($check, \PDO::PARAM_STR); |
|
164
|
|
|
|
|
165
|
|
|
$queries[] .= " |
|
166
|
|
|
SELECT $toolname as toolname, count(*) as count |
|
167
|
|
|
FROM $rev |
|
168
|
|
|
WHERE rev_user_text = :username |
|
169
|
|
|
AND rev_comment REGEXP $check |
|
170
|
|
|
$cond_begin |
|
171
|
|
|
$cond_end |
|
172
|
|
|
"; |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
// Next, add two simple queries for the live and deleted edits. |
|
176
|
|
|
$queries[] = " |
|
177
|
|
|
SELECT 'live' as toolname ,count(*) as count |
|
178
|
|
|
from $rev |
|
179
|
|
|
WHERE rev_user_text = :username |
|
180
|
|
|
$cond_begin |
|
181
|
|
|
$cond_end |
|
182
|
|
|
"; |
|
183
|
|
|
|
|
184
|
|
|
$cond_begin = str_replace("rev_timestamp", "ar_timestamp", $cond_begin); |
|
185
|
|
|
$cond_end = str_replace("rev_timestamp", "ar_timestamp", $cond_end); |
|
186
|
|
|
|
|
187
|
|
|
$queries[] = " |
|
188
|
|
|
SELECT 'deleted' as toolname, count(*) as count |
|
189
|
|
|
from $arc |
|
190
|
|
|
WHERE ar_user_text = :username |
|
191
|
|
|
$cond_begin |
|
192
|
|
|
$cond_end |
|
193
|
|
|
"; |
|
194
|
|
|
|
|
195
|
|
|
// Create a big query and execute. |
|
196
|
|
|
$stmt = implode(" UNION ", $queries); |
|
197
|
|
|
|
|
198
|
|
|
$sth = $dbh->prepare($stmt); |
|
199
|
|
|
|
|
200
|
|
|
$sth->bindParam("username", $username); |
|
201
|
|
|
$sth->bindParam("start", $start); |
|
202
|
|
|
$sth->bindParam("end", $end); |
|
203
|
|
|
|
|
204
|
|
|
$sth->execute(); |
|
205
|
|
|
|
|
206
|
|
|
// handling results |
|
207
|
|
|
$results = []; |
|
208
|
|
|
$total_semi = 0; |
|
209
|
|
|
$total = 0; |
|
210
|
|
|
|
|
211
|
|
|
while ($row = $sth->fetch()) { |
|
212
|
|
|
// Different variables need to get set if the tool is |
|
213
|
|
|
// the live edits or deleted edits. |
|
214
|
|
|
// If it is neither and greater than 0, |
|
215
|
|
|
// add them to the array we're rendering and to our running total |
|
216
|
|
|
if ($row["toolname"] == "live") { |
|
217
|
|
|
$total += $row["count"]; |
|
218
|
|
|
} elseif ($row["toolname"] == "deleted") { |
|
219
|
|
|
$total += $row["count"]; |
|
220
|
|
|
} elseif ($row["count"] > 0) { |
|
221
|
|
|
$results[$row["toolname"]] = $row["count"]; |
|
222
|
|
|
$total_semi = $total_semi+$row["count"]; |
|
223
|
|
|
} |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
// Sort the array and do some simple math. |
|
227
|
|
|
arsort($results); |
|
228
|
|
|
|
|
229
|
|
|
if ($total != 0) { |
|
230
|
|
|
$total_pct = ($total_semi / $total) * 100; |
|
231
|
|
|
} else { |
|
232
|
|
|
$total_pct = 0; |
|
233
|
|
|
} |
|
234
|
|
|
|
|
235
|
|
|
|
|
236
|
|
|
// Render the view with all variables set. |
|
237
|
|
|
return $this->render('autoEdits/result.html.twig', [ |
|
238
|
|
|
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..'), |
|
239
|
|
|
//"xtPageTitle" => "autoedits", |
|
|
|
|
|
|
240
|
|
|
'xtPage' => "autoedits", |
|
241
|
|
|
"username" => $username, |
|
242
|
|
|
"url" => $url, |
|
243
|
|
|
"wikiName" => $wikiName, |
|
244
|
|
|
"semi_automated" => $results, |
|
245
|
|
|
"start" => date("Y-m-d", strtotime($start)), |
|
246
|
|
|
"end" => date("Y-m-d", strtotime($end)), |
|
247
|
|
|
"total_semi" => $total_semi, |
|
248
|
|
|
"total" => $total, |
|
249
|
|
|
"total_pct" => $total_pct, |
|
250
|
|
|
|
|
251
|
|
|
]); |
|
252
|
|
|
} |
|
253
|
|
|
} |
|
254
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.