api_stats::execute()   C
last analyzed

Complexity

Conditions 10
Paths 216

Size

Total Lines 60
Code Lines 42

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 60
rs 5.7981
cc 10
eloc 42
nc 216
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* zKillboard
3
 * Copyright (C) 2012-2015 EVE-KILL Team and EVSCO.
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Affero General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Affero General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Affero General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
class api_stats implements apiEndpoint
20
{
21
	public function getDescription()
22
	{
23
		return array("type" => "description", "message" =>
24
				"Shows stats for an entity"
25
			);
26
	}
27
28
	public function getAcceptedParameters()
29
	{
30
		return array("type" => "parameters", "parameters" =>
31
			array(
32
				"characterID" => "Get stats for a certain characterID.",
33
				"corporationID" => "Get stats for a certain corporationID.",
34
				"allianceID" => "Get stats for a certain allianceID.",
35
				"factionID" => "Get stats for a certain factionID.",
36
				"shipTypeID" => "Get stats for a certain ship.",
37
				"groupID" => "Get stats for a certain group of ships.",
38
				"solarSystemID" => "Get stats for a certain solarsystem",
39
				"regionID" => "Get stats for a certain region.",
40
				"recent" => "Show recent or all time stats."
41
			)
42
		);
43
	}
44
45
	public function execute($parameters)
46
	{
47
		// Map calls to the internal names.
48
		$mapping = array(
49
			"factionID" => "faction", 
50
			"allianceID" => "alli", 
51
			"corporationID" => "corp",
52
			"characterID" => "pilot",
53
			"groupID" => "group",
54
			"shipTypeID" => "ship",
55
			"solarSystemID" => "system",
56
			"regionID" => "region"
57
		);
58
59
		$allowed_types = array(
60
			"factionID", 
61
			"allianceID", 
62
			"corporationID",
63
			"characterID",
64
			"groupID",
65
			"shipTypeID",
66
			"solarSystemID",
67
			"regionID"
68
		);
69
70
		$statsTable = isset($parameters["recent"]) ? "zz_stats_recent" : "zz_stats";
71
72
		foreach($parameters as $key => $value)
73
			if(!in_array($key, $allowed_types))
74
				unset($parameters[$key]);
75
76
		foreach($parameters as $key => $value)
77
		{
78
			$flag = $key;
79
			$id = $value[0];
80
		}
81
82
		$type = isset($flag) ? $mapping[$flag] : null;
83
84
		if(!$type)
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
85
			return array(
86
				"type" => "error",
87
				"message" => "Please use a valid type."
88
			);
89
90
		$stat_totals  = Db::queryRow('SELECT SUM(destroyed) AS countDestroyed, SUM(lost) AS countLost, SUM(pointsDestroyed) AS pointsDestroyed, SUM(pointsLost) AS pointsLost, SUM(iskDestroyed) AS iskDestroyed, SUM(iskLost) AS iskLost FROM ' . $statsTable . ' WHERE type = :type AND typeID = :id', array(':type' => $type, ':id' => $id));
0 ignored issues
show
Bug introduced by
The variable $id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
91
		$stat_details = Db::query('SELECT groupID, destroyed AS countDestroyed, lost AS countLost, pointsDestroyed, pointsLost, iskDestroyed, iskLost FROM ' . $statsTable . ' WHERE type = :type AND typeID = :id', array(':type' => $type, ':id' => $id));
92
93
		$output = array();
94
		$output["totals"] = $stat_totals;
95
		foreach($stat_details as $detail)
96
			$output["groups"][array_shift($detail)] = $detail;
97
98
		$characterID = isset($parameters["characterID"][0]) ? $parameters["characterID"][0] : NULL;
99
		$corporationID = isset($parameters["corporationID"][0]) ? $parameters["corporationID"][0] : Info::getCharacterAffiliations($characterID)["corporationID"];
100
		$verified = (bool) Db::queryField("SELECT count(*) AS count FROM zz_api_characters WHERE ((characterID = :characterID AND isDirector = 'F') OR (corporationID = :corporationID AND isDirector = 'T')) AND errorCode = 0", "count", array(":characterID" => $characterID, ":corporationID" => $corporationID), 0);
101
		$output["apiVerified"] = $verified;
102
103
		return $output;
104
	}
105
}
106