Total Complexity | 41 |
Total Lines | 534 |
Duplicated Lines | 0 % |
Changes | 34 | ||
Bugs | 0 | Features | 0 |
Complex classes like Reports often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Reports, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class Reports extends Component |
||
19 | { |
||
20 | // Public Methods |
||
21 | // ========================================================================= |
||
22 | |||
23 | /** |
||
24 | * Returns a realtime report. |
||
25 | * |
||
26 | * @param array $request |
||
27 | * |
||
28 | * @return array |
||
29 | * @throws \yii\base\InvalidConfigException |
||
30 | */ |
||
31 | public function getRealtimeReport(array $request) |
||
32 | { |
||
33 | $view = Analytics::$plugin->getViews()->getViewById($request['viewId']); |
||
34 | |||
35 | $tableId = null; |
||
36 | |||
37 | if ($view) { |
||
38 | $tableId = 'ga:'.$view->gaViewId; |
||
39 | } |
||
40 | |||
41 | $metrics = $request['metrics']; |
||
42 | $optParams = $request['optParams']; |
||
43 | |||
44 | $cacheId = ['reports.getRealtimeReport', $tableId, $metrics, $optParams]; |
||
45 | $response = Analytics::$plugin->cache->get($cacheId); |
||
46 | |||
47 | if (!$response) { |
||
48 | $response = Analytics::$plugin->getApis()->getAnalytics()->getService()->data_realtime->get($tableId, $metrics, $optParams); |
||
49 | |||
50 | $cacheDuration = Analytics::$plugin->getSettings()->realtimeRefreshInterval; |
||
51 | Analytics::$plugin->cache->set($cacheId, $response, $cacheDuration); |
||
52 | } |
||
53 | |||
54 | return (array)$response; |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * Get e-commerce report. |
||
59 | * |
||
60 | * @param $viewId |
||
61 | * @param $period |
||
62 | * |
||
63 | * @return array |
||
64 | */ |
||
65 | public function getEcommerceReport($viewId, $period) |
||
111 | ], |
||
112 | ]; |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Returns an element report. |
||
117 | * |
||
118 | * @param int $elementId |
||
119 | * @param int|null $siteId |
||
120 | * @param string $metric |
||
121 | * |
||
122 | * @return array |
||
123 | * @throws \Exception |
||
124 | */ |
||
125 | public function getElementReport($elementId, $siteId, $metric) |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Returns an area report. |
||
186 | * |
||
187 | * @param array $request |
||
188 | * |
||
189 | * @return array |
||
190 | * @throws \yii\base\InvalidConfigException |
||
191 | */ |
||
192 | public function getAreaReport(array $request) |
||
193 | { |
||
194 | $viewId = ($request['viewId'] ?? null); |
||
195 | $period = ($request['period'] ?? null); |
||
196 | $metricString = ($request['options']['metric'] ?? null); |
||
197 | |||
198 | switch ($period) { |
||
199 | case 'year': |
||
200 | $dimensionString = 'ga:yearMonth'; |
||
201 | $startDate = date('Y-m-01', strtotime('-1 '.$period)); |
||
202 | $endDate = date('Y-m-d'); |
||
203 | break; |
||
204 | |||
205 | default: |
||
206 | $dimensionString = 'ga:date'; |
||
207 | $startDate = date('Y-m-d', strtotime('-1 '.$period)); |
||
208 | $endDate = date('Y-m-d'); |
||
209 | } |
||
210 | |||
211 | $criteria = new ReportRequestCriteria; |
||
212 | $criteria->viewId = $viewId; |
||
213 | $criteria->startDate = $startDate; |
||
214 | $criteria->endDate = $endDate; |
||
215 | $criteria->metrics = $metricString; |
||
216 | $criteria->dimensions = $dimensionString; |
||
217 | $criteria->includeEmptyRows = true; |
||
218 | |||
219 | $criteria->orderBys = [ |
||
220 | ['fieldName' => $dimensionString, 'orderType' => 'VALUE', 'sortOrder' => 'ASCENDING'] |
||
221 | ]; |
||
222 | |||
223 | $reportResponse = Analytics::$plugin->getApis()->getAnalyticsReporting()->getReport($criteria); |
||
224 | $report = $this->parseReportingReport($reportResponse); |
||
225 | |||
226 | $total = $report['totals'][0]; |
||
227 | |||
228 | $view = Analytics::$plugin->getViews()->getViewById($viewId); |
||
229 | |||
230 | return [ |
||
231 | 'view' => $view->name, |
||
232 | 'type' => 'area', |
||
233 | 'chart' => $report, |
||
234 | 'total' => $total, |
||
235 | 'metric' => Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($metricString)), |
||
236 | 'period' => $period, |
||
237 | 'periodLabel' => Craft::t('analytics', 'This '.$period) |
||
238 | ]; |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * Returns a counter report. |
||
243 | * |
||
244 | * @param array $request |
||
245 | * |
||
246 | * @return array |
||
247 | * @throws \yii\base\InvalidConfigException |
||
248 | */ |
||
249 | public function getCounterReport(array $request) |
||
250 | { |
||
251 | $viewId = ($request['viewId'] ?? null); |
||
252 | $period = ($request['period'] ?? null); |
||
253 | $metricString = ($request['options']['metric'] ?? null); |
||
254 | $startDate = date('Y-m-d', strtotime('-1 '.$period)); |
||
255 | $endDate = date('Y-m-d'); |
||
256 | |||
257 | $criteria = new ReportRequestCriteria; |
||
258 | $criteria->viewId = $viewId; |
||
259 | $criteria->startDate = $startDate; |
||
260 | $criteria->endDate = $endDate; |
||
261 | $criteria->metrics = $metricString; |
||
262 | |||
263 | |||
264 | $reportResponse = Analytics::$plugin->getApis()->getAnalyticsReporting()->getReport($criteria); |
||
265 | $report = $this->parseReportingReport($reportResponse); |
||
266 | |||
267 | $total = 0; |
||
268 | |||
269 | if (!empty($report['totals'][0])) { |
||
270 | $total = $report['totals'][0]; |
||
271 | } |
||
272 | |||
273 | $counter = [ |
||
274 | 'type' => $report['cols'][0]['type'], |
||
275 | 'value' => $total, |
||
276 | 'label' => StringHelper::toLowerCase(Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($metricString))) |
||
277 | ]; |
||
278 | |||
279 | $view = Analytics::$plugin->getViews()->getViewById($viewId); |
||
280 | |||
281 | return [ |
||
282 | 'view' => $view->name, |
||
283 | 'type' => 'counter', |
||
284 | 'counter' => $counter, |
||
285 | 'response' => $report, |
||
286 | 'metric' => Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($metricString)), |
||
287 | 'period' => $period, |
||
288 | 'periodLabel' => Craft::t('analytics', 'this '.$period) |
||
289 | ]; |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * Returns a pie report. |
||
294 | * |
||
295 | * @param array $request |
||
296 | * |
||
297 | * @return array |
||
298 | * @throws \yii\base\InvalidConfigException |
||
299 | */ |
||
300 | public function getPieReport(array $request) |
||
301 | { |
||
302 | $viewId = ($request['viewId'] ?? null); |
||
303 | $period = ($request['period'] ?? null); |
||
304 | $dimensionString = ($request['options']['dimension'] ?? null); |
||
305 | $metricString = ($request['options']['metric'] ?? null); |
||
306 | $startDate = date('Y-m-d', strtotime('-1 '.$period)); |
||
307 | $endDate = date('Y-m-d'); |
||
308 | |||
309 | $criteria = new ReportRequestCriteria; |
||
310 | $criteria->viewId = $viewId; |
||
311 | $criteria->startDate = $startDate; |
||
312 | $criteria->endDate = $endDate; |
||
313 | $criteria->metrics = $metricString; |
||
314 | $criteria->dimensions = $dimensionString; |
||
315 | |||
316 | $reportResponse = Analytics::$plugin->getApis()->getAnalyticsReporting()->getReport($criteria); |
||
317 | $report = $this->parseReportingReport($reportResponse); |
||
318 | |||
319 | $view = Analytics::$plugin->getViews()->getViewById($viewId); |
||
320 | |||
321 | return [ |
||
322 | 'view' => $view->name, |
||
323 | 'type' => 'pie', |
||
324 | 'chart' => $report, |
||
325 | 'dimension' => Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($dimensionString)), |
||
326 | 'metric' => Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($metricString)), |
||
327 | 'period' => $period, |
||
328 | 'periodLabel' => Craft::t('analytics', 'this '.$period) |
||
329 | ]; |
||
330 | } |
||
331 | |||
332 | /** |
||
333 | * Returns a table report. |
||
334 | * |
||
335 | * @param array $request |
||
336 | * |
||
337 | * @return array |
||
338 | * @throws \yii\base\InvalidConfigException |
||
339 | */ |
||
340 | public function getTableReport(array $request) |
||
341 | { |
||
342 | $viewId = ($request['viewId'] ?? null); |
||
343 | |||
344 | $period = ($request['period'] ?? null); |
||
345 | $dimensionString = ($request['options']['dimension'] ?? null); |
||
346 | $metricString = ($request['options']['metric'] ?? null); |
||
347 | |||
348 | $criteria = new ReportRequestCriteria; |
||
349 | $criteria->viewId = $viewId; |
||
350 | $criteria->dimensions = $dimensionString; |
||
351 | $criteria->metrics = $metricString; |
||
352 | $criteria->startDate = date('Y-m-d', strtotime('-1 '.$period)); |
||
353 | $criteria->endDate = date('Y-m-d'); |
||
354 | |||
355 | $reportResponse = Analytics::$plugin->getApis()->getAnalyticsReporting()->getReport($criteria); |
||
356 | $report = $this->parseReportingReport($reportResponse); |
||
357 | |||
358 | $view = Analytics::$plugin->getViews()->getViewById($viewId); |
||
359 | |||
360 | return [ |
||
361 | 'view' => $view->name, |
||
362 | 'type' => 'table', |
||
363 | 'chart' => $report, |
||
364 | 'dimension' => Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($dimensionString)), |
||
365 | 'metric' => Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($metricString)), |
||
366 | 'period' => $period, |
||
367 | 'periodLabel' => Craft::t('analytics', 'This '.$period) |
||
368 | ]; |
||
369 | } |
||
370 | |||
371 | /** |
||
372 | * Returns a geo report. |
||
373 | * |
||
374 | * @param array $request |
||
375 | * |
||
376 | * @return array |
||
377 | * @throws \yii\base\InvalidConfigException |
||
378 | */ |
||
379 | public function getGeoReport(array $request) |
||
380 | { |
||
381 | $viewId = ($request['viewId'] ?? null); |
||
382 | $period = ($request['period'] ?? null); |
||
383 | $dimensionString = ($request['options']['dimension'] ?? null); |
||
384 | $metricString = ($request['options']['metric'] ?? null); |
||
385 | |||
386 | $originDimension = $dimensionString; |
||
387 | |||
388 | if ($dimensionString === 'ga:city') { |
||
389 | $dimensionString = 'ga:latitude,ga:longitude,'.$dimensionString; |
||
390 | } |
||
391 | |||
392 | $criteria = new ReportRequestCriteria; |
||
393 | $criteria->viewId = $viewId; |
||
394 | $criteria->dimensions = $dimensionString; |
||
395 | $criteria->metrics = $metricString; |
||
396 | $criteria->startDate = date('Y-m-d', strtotime('-1 '.$period)); |
||
397 | $criteria->endDate = date('Y-m-d'); |
||
398 | |||
399 | $reportResponse = Analytics::$plugin->getApis()->getAnalyticsReporting()->getReport($criteria); |
||
400 | $report = $this->parseReportingReport($reportResponse); |
||
401 | |||
402 | $view = Analytics::$plugin->getViews()->getViewById($viewId); |
||
403 | |||
404 | return [ |
||
405 | 'view' => $view->name, |
||
406 | 'type' => 'geo', |
||
407 | 'chart' => $report, |
||
408 | 'dimensionRaw' => $originDimension, |
||
409 | 'dimension' => Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($originDimension)), |
||
410 | 'metric' => Craft::t('analytics', Analytics::$plugin->metadata->getDimMet($metricString)), |
||
411 | 'period' => $period, |
||
412 | 'periodLabel' => Craft::t('analytics', 'This '.$period) |
||
413 | ]; |
||
414 | } |
||
415 | |||
416 | // Private Methods |
||
417 | // ========================================================================= |
||
418 | |||
419 | /** |
||
420 | * @param Google_Service_AnalyticsReporting_Report $report |
||
421 | * @return array |
||
422 | */ |
||
423 | private function parseReportingReport(Google_Service_AnalyticsReporting_Report $report): array |
||
424 | { |
||
425 | $cols = $this->parseReportingReportCols($report); |
||
426 | $rows = $this->parseReportingReportRows($report); |
||
427 | $totals = $report->getData()->getTotals()[0]->getValues(); |
||
428 | |||
429 | return [ |
||
430 | 'cols' => $cols, |
||
431 | 'rows' => $rows, |
||
432 | 'totals' => $totals |
||
433 | ]; |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * @param Google_Service_AnalyticsReporting_Report $report |
||
438 | * @return array |
||
439 | */ |
||
440 | private function parseReportingReportCols(Google_Service_AnalyticsReporting_Report $report): array |
||
441 | { |
||
442 | $columnHeader = $report->getColumnHeader(); |
||
443 | $columnHeaderDimensions = $columnHeader->getDimensions(); |
||
444 | $metricHeaderEntries = $columnHeader->getMetricHeader()->getMetricHeaderEntries(); |
||
445 | |||
446 | $cols = []; |
||
447 | |||
448 | if ($columnHeaderDimensions) { |
||
449 | foreach ($columnHeaderDimensions as $columnHeaderDimension) { |
||
450 | |||
451 | $id = $columnHeaderDimension; |
||
452 | $label = Analytics::$plugin->metadata->getDimMet($columnHeaderDimension); |
||
453 | |||
454 | switch ($columnHeaderDimension) { |
||
455 | case 'ga:date': |
||
456 | case 'ga:yearMonth': |
||
457 | $type = 'date'; |
||
458 | break; |
||
459 | |||
460 | case 'ga:continent': |
||
461 | $type = 'continent'; |
||
462 | break; |
||
463 | case 'ga:subContinent': |
||
464 | $type = 'subContinent'; |
||
465 | break; |
||
466 | |||
467 | case 'ga:latitude': |
||
468 | case 'ga:longitude': |
||
469 | $type = 'float'; |
||
470 | break; |
||
471 | |||
472 | default: |
||
473 | $type = 'string'; |
||
474 | } |
||
475 | |||
476 | $col = [ |
||
477 | 'type' => $type, |
||
478 | 'label' => Craft::t('analytics', $label), |
||
479 | 'id' => $id, |
||
480 | ]; |
||
481 | |||
482 | array_push($cols, $col); |
||
483 | } |
||
484 | } |
||
485 | |||
486 | foreach ($metricHeaderEntries as $metricHeaderEntry) { |
||
487 | $label = Analytics::$plugin->metadata->getDimMet($metricHeaderEntry['name']); |
||
488 | |||
489 | $col = [ |
||
490 | 'type' => strtolower($metricHeaderEntry['type']), |
||
491 | 'label' => Craft::t('analytics', $label), |
||
492 | 'id' => $metricHeaderEntry['name'], |
||
493 | ]; |
||
494 | |||
495 | array_push($cols, $col); |
||
496 | } |
||
497 | |||
498 | return $cols; |
||
499 | } |
||
500 | |||
501 | /** |
||
502 | * @param Google_Service_AnalyticsReporting_Report $report |
||
503 | * @return array |
||
504 | */ |
||
505 | private function parseReportingReportRows(Google_Service_AnalyticsReporting_Report $report): array |
||
552 | } |
||
553 | } |
||
554 |
Let?s assume that you have a directory layout like this:
and let?s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: