Test Setup Failed
Push — master ( 44694a...146201 )
by Matthieu
22:45 queued 15:03
created

API::getCountryCodeMapping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 12
ccs 0
cts 5
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Piwik - free/libre analytics platform
4
 *
5
 * @link http://piwik.org
6
 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7
 *
8
 */
9
namespace Piwik\Plugins\UserCountry;
10
11
use Exception;
12
use Piwik\Archive;
13
use Piwik\Container\StaticContainer;
14
use Piwik\DataTable;
15
use Piwik\Metrics;
16
use Piwik\Piwik;
17
use Piwik\Plugins\UserCountry\LocationProvider;
18
use Piwik\Tracker\Visit;
19
20
/**
21
 * @see plugins/UserCountry/functions.php
22
 */
23
require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/functions.php';
24
25
/**
26
 * The UserCountry API lets you access reports about your visitors' Countries and Continents.
27
 * @method static \Piwik\Plugins\UserCountry\API getInstance()
28
 */
29
class API extends \Piwik\Plugin\API
30
{
31
    public function getCountry($idSite, $period, $date, $segment = false)
32
    {
33
        $dataTable = $this->getDataTable(Archiver::COUNTRY_RECORD_NAME, $idSite, $period, $date, $segment);
34
35
        // apply filter on the whole datatable in order the inline search to work (searches are done on "beautiful" label)
36
        $dataTable->filter('AddSegmentValue');
37
        $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'code'));
38
        $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'logo', __NAMESPACE__ . '\getFlagFromCode'));
39
        $dataTable->filter('ColumnCallbackReplace', array('label', __NAMESPACE__ . '\countryTranslate'));
40
41
        $dataTable->queueFilter('ColumnCallbackAddMetadata', array(array(), 'logoWidth', function () { return 16; }));
42
        $dataTable->queueFilter('ColumnCallbackAddMetadata', array(array(), 'logoHeight', function () { return 11; }));
43
44
        return $dataTable;
45
    }
46
47 View Code Duplication
    public function getContinent($idSite, $period, $date, $segment = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
48
    {
49
        $dataTable = $this->getDataTable(Archiver::COUNTRY_RECORD_NAME, $idSite, $period, $date, $segment);
50
51
        $getContinent = array('Piwik\Common', 'getContinent');
52
        $dataTable->filter('GroupBy', array('label', $getContinent));
53
54
        $dataTable->filter('ColumnCallbackReplace', array('label', __NAMESPACE__ . '\continentTranslate'));
55
        $dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'code'));
56
57
        return $dataTable;
58
    }
59
60
    /**
61
     * Returns visit information for every region with at least one visit.
62
     *
63
     * @param int|string $idSite
64
     * @param string $period
65
     * @param string $date
66
     * @param string|bool $segment
67
     * @return DataTable
68
     */
69
    public function getRegion($idSite, $period, $date, $segment = false)
70
    {
71
        $dataTable = $this->getDataTable(Archiver::REGION_RECORD_NAME, $idSite, $period, $date, $segment);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->getDataTable(\Piw...riod, $date, $segment); of type Piwik\DataTable|Piwik\DataTable\Map adds the type Piwik\DataTable\Map to the return on line 102 which is incompatible with the return type documented by Piwik\Plugins\UserCountry\API::getRegion of type Piwik\DataTable.
Loading history...
72
73
        $segments = array('regionCode', 'countryCode');
74
        $dataTable->filter('AddSegmentByLabel', array($segments, Archiver::LOCATION_SEPARATOR));
75
76
        $separator = Archiver::LOCATION_SEPARATOR;
77
        $unk = Visit::UNKNOWN_CODE;
78
79
        // split the label and put the elements into the 'region' and 'country' metadata fields
80
        $dataTable->filter('ColumnCallbackAddMetadata',
81
            array('label', 'region', __NAMESPACE__ . '\getElementFromStringArray', array($separator, 0, $unk)));
82
        $dataTable->filter('ColumnCallbackAddMetadata',
83
            array('label', 'country', __NAMESPACE__ . '\getElementFromStringArray', array($separator, 1, $unk)));
84
85
        // add country name metadata
86
        $dataTable->filter('MetadataCallbackAddMetadata',
87
            array('country', 'country_name', __NAMESPACE__ . '\CountryTranslate', $applyToSummaryRow = false));
88
89
        // get the region name of each row and put it into the 'region_name' metadata
90
        $dataTable->filter('ColumnCallbackAddMetadata',
91
            array('label', 'region_name', __NAMESPACE__ . '\getRegionName', $params = null,
92
                  $applyToSummaryRow = false));
93
94
        // add the country flag as a url to the 'logo' metadata field
95
        $dataTable->filter('MetadataCallbackAddMetadata', array('country', 'logo', __NAMESPACE__ . '\getFlagFromCode'));
96
97
        // prettify the region label
98
        $dataTable->filter('ColumnCallbackReplace', array('label', __NAMESPACE__ . '\getPrettyRegionName'));
99
100
        $dataTable->queueFilter('ReplaceSummaryRowLabel');
101
102
        return $dataTable;
103
    }
104
105
    /**
106
     * Returns visit information for every city with at least one visit.
107
     *
108
     * @param int|string $idSite
109
     * @param string $period
110
     * @param string $date
111
     * @param string|bool $segment
112
     * @return DataTable
113
     */
114
    public function getCity($idSite, $period, $date, $segment = false)
115
    {
116
        $dataTable = $this->getDataTable(Archiver::CITY_RECORD_NAME, $idSite, $period, $date, $segment);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->getDataTable(\Piw...riod, $date, $segment); of type Piwik\DataTable|Piwik\DataTable\Map adds the type Piwik\DataTable\Map to the return on line 165 which is incompatible with the return type documented by Piwik\Plugins\UserCountry\API::getCity of type Piwik\DataTable.
Loading history...
117
118
        $segments = array('city', 'regionCode', 'countryCode');
119
        $dataTable->filter('AddSegmentByLabel', array($segments, Archiver::LOCATION_SEPARATOR));
120
121
        $separator = Archiver::LOCATION_SEPARATOR;
122
        $unk = Visit::UNKNOWN_CODE;
123
124
        // split the label and put the elements into the 'city_name', 'region', 'country',
125
        // 'lat' & 'long' metadata fields
126
        $strUnknown = Piwik::translate('General_Unknown');
127
        $dataTable->filter('ColumnCallbackAddMetadata',
128
            array('label', 'city_name', __NAMESPACE__ . '\getElementFromStringArray',
129
                  array($separator, 0, $strUnknown)));
130
        $dataTable->filter('MetadataCallbackAddMetadata',
131
            array('city_name', 'city', function ($city) use ($strUnknown) {
132
                if ($city == $strUnknown) {
133
                    return "xx";
134
                } else {
135
                    return false;
136
                }
137
            }));
138
        $dataTable->filter('ColumnCallbackAddMetadata',
139
            array('label', 'region', __NAMESPACE__ . '\getElementFromStringArray', array($separator, 1, $unk)));
140
        $dataTable->filter('ColumnCallbackAddMetadata',
141
            array('label', 'country', __NAMESPACE__ . '\getElementFromStringArray', array($separator, 2, $unk)));
142
143
        // backwards compatibility: for reports that have lat|long in label
144
        $dataTable->filter('ColumnCallbackAddMetadata',
145
            array('label', 'lat', __NAMESPACE__ . '\getElementFromStringArray', array($separator, 3, false)));
146
        $dataTable->filter('ColumnCallbackAddMetadata',
147
            array('label', 'long', __NAMESPACE__ . '\getElementFromStringArray', array($separator, 4, false)));
148
149
        // add country name & region name metadata
150
        $dataTable->filter('MetadataCallbackAddMetadata',
151
            array('country', 'country_name', __NAMESPACE__ . '\countryTranslate', $applyToSummaryRow = false));
152
153
        $getRegionName = '\\Piwik\\Plugins\\UserCountry\\LocationProvider\\GeoIp::getRegionNameFromCodes';
154
        $dataTable->filter('MetadataCallbackAddMetadata', array(
155
                                                               array('country', 'region'), 'region_name', $getRegionName, $applyToSummaryRow = false));
156
157
        // add the country flag as a url to the 'logo' metadata field
158
        $dataTable->filter('MetadataCallbackAddMetadata', array('country', 'logo', __NAMESPACE__ . '\getFlagFromCode'));
159
160
        // prettify the label
161
        $dataTable->filter('ColumnCallbackReplace', array('label', __NAMESPACE__ . '\getPrettyCityName'));
162
163
        $dataTable->queueFilter('ReplaceSummaryRowLabel');
164
165
        return $dataTable;
166
    }
167
168
    /**
169
     * Returns a simple mapping from country code to country name
170
     *
171
     * @return \string[]
172
     */
173
    public function getCountryCodeMapping()
174
    {
175
        $regionDataProvider = StaticContainer::get('Piwik\Intl\Data\Provider\RegionDataProvider');
176
177
        $countryCodeList = $regionDataProvider->getCountryList();
178
179
        array_walk($countryCodeList, function(&$item, $key) {
180
            $item = Piwik::translate('Intl_Country_'.strtoupper($key));
181
        });
182
183
        return $countryCodeList;
184
    }
185
186
    /**
187
     * Uses a location provider to find/guess the location of an IP address.
188
     *
189
     * See LocationProvider::getLocation to see the details
190
     * of the result of this function.
191
     *
192
     * @param string $ip The IP address.
193
     * @param bool|string $provider The ID of the provider to use or false to use the
194
     *                               currently configured one.
195
     * @throws Exception
196
     * @return array|false
197
     */
198
    public function getLocationFromIP($ip, $provider = false)
199
    {
200
        Piwik::checkUserHasSomeViewAccess();
201
202
        if (empty($provider)) {
203
            $provider = LocationProvider::getCurrentProviderId();
204
        }
205
206
        $oProvider = LocationProvider::getProviderById($provider);
0 ignored issues
show
Bug introduced by
It seems like $provider defined by parameter $provider on line 198 can also be of type boolean; however, Piwik\Plugins\UserCountr...ider::getProviderById() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
207
        if (empty($oProvider)) {
208
            throw new Exception("Cannot find the '$provider' provider. It is either an invalid provider "
209
                . "ID or the ID of a provider that is not working.");
210
        }
211
212
        $location = $oProvider->getLocation(array('ip' => $ip));
213
        if (empty($location)) {
214
            throw new Exception("Could not geolocate '$ip'!");
215
        }
216
        $location['ip'] = $ip;
217
        return $location;
218
    }
219
220
    /**
221
     * Set the location provider
222
     *
223
     * @param string $providerId  The ID of the provider to use  eg 'default', 'geoip_php', ...
224
     * @throws Exception if ID is invalid
225
     */
226
    public function setLocationProvider($providerId)
227
    {
228
        Piwik::checkUserHasSuperUserAccess();
229
230
        if (!UserCountry::isGeoLocationAdminEnabled()) {
231
            throw new \Exception('Setting geo location has been disabled in config.');
232
        }
233
234
        $provider = LocationProvider::setCurrentProvider($providerId);
235
        if ($provider === false) {
236
            throw new Exception("Invalid provider ID: '$providerId'.");
237
        }
238
    }
239
240 View Code Duplication
    protected function getDataTable($name, $idSite, $period, $date, $segment)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
241
    {
242
        Piwik::checkUserHasViewAccess($idSite);
243
        $archive = Archive::build($idSite, $period, $date, $segment);
244
        $dataTable = $archive->getDataTable($name);
245
        $dataTable->queueFilter('ReplaceColumnNames');
246
        return $dataTable;
247
    }
248
249
    public function getNumberOfDistinctCountries($idSite, $period, $date, $segment = false)
250
    {
251
        Piwik::checkUserHasViewAccess($idSite);
252
        $archive = Archive::build($idSite, $period, $date, $segment);
253
        return $archive->getDataTableFromNumeric(Archiver::DISTINCT_COUNTRIES_METRIC);
254
    }
255
}
256