PageRenderTime 25ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/analytics/plugins/UserCountry/Controller.php

https://gitlab.com/yasminmostfa/thomas-site
PHP | 372 lines | 225 code | 45 blank | 102 comment | 31 complexity | b57147c18111eca0abd0b5687656fa29 MD5 | raw file
  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. use Exception;
  11. use Piwik\Common;
  12. use Piwik\DataTable\Renderer\Json;
  13. use Piwik\Http;
  14. use Piwik\IP;
  15. use Piwik\Piwik;
  16. use Piwik\Plugins\UserCountry\LocationProvider\GeoIp\ServerBased;
  17. use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
  18. use Piwik\Plugins\UserCountry\LocationProvider;
  19. use Piwik\Plugins\UserCountry\LocationProvider\DefaultProvider;
  20. use Piwik\Plugins\UserCountry\LocationProvider\GeoIp\Pecl;
  21. use Piwik\View;
  22. /**
  23. *
  24. */
  25. class Controller extends \Piwik\Plugin\ControllerAdmin
  26. {
  27. public function index()
  28. {
  29. $view = new View('@UserCountry/index');
  30. $view->urlSparklineCountries = $this->getUrlSparkline('getLastDistinctCountriesGraph');
  31. $view->numberDistinctCountries = $this->getNumberOfDistinctCountries(true);
  32. $view->dataTableCountry = $this->renderReport('getCountry');
  33. $view->dataTableContinent = $this->renderReport('getContinent');
  34. $view->dataTableRegion = $this->renderReport('getRegion');
  35. $view->dataTableCity = $this->renderReport('getCity');
  36. return $view->render();
  37. }
  38. public function adminIndex()
  39. {
  40. $this->dieIfGeolocationAdminIsDisabled();
  41. Piwik::checkUserHasSuperUserAccess();
  42. $view = new View('@UserCountry/adminIndex');
  43. $allProviderInfo = LocationProvider::getAllProviderInfo($newline = '<br/>', $includeExtra = true);
  44. $view->locationProviders = $allProviderInfo;
  45. $view->currentProviderId = LocationProvider::getCurrentProviderId();
  46. $view->thisIP = IP::getIpFromHeader();
  47. $geoIPDatabasesInstalled = GeoIp::isDatabaseInstalled();
  48. $view->geoIPDatabasesInstalled = $geoIPDatabasesInstalled;
  49. // check if there is a working provider (that isn't the default one)
  50. $isThereWorkingProvider = false;
  51. foreach ($allProviderInfo as $id => $provider) {
  52. if ($id != DefaultProvider::ID
  53. && $provider['status'] == LocationProvider::INSTALLED
  54. ) {
  55. $isThereWorkingProvider = true;
  56. break;
  57. }
  58. }
  59. $view->isThereWorkingProvider = $isThereWorkingProvider;
  60. // if using either the Apache or PECL module, they are working and there are no databases
  61. // in misc, then the databases are located outside of Piwik, so we cannot update them
  62. $view->showGeoIPUpdateSection = true;
  63. $currentProviderId = LocationProvider::getCurrentProviderId();
  64. if (!$geoIPDatabasesInstalled
  65. && ($currentProviderId == ServerBased::ID
  66. || $currentProviderId == Pecl::ID)
  67. && $allProviderInfo[$currentProviderId]['status'] == LocationProvider::INSTALLED
  68. ) {
  69. $view->showGeoIPUpdateSection = false;
  70. }
  71. $this->setUpdaterManageVars($view);
  72. $this->setBasicVariablesView($view);
  73. $this->setBasicVariablesAdminView($view);
  74. return $view->render();
  75. }
  76. /**
  77. * Starts or continues download of GeoLiteCity.dat.
  78. *
  79. * To avoid a server/PHP timeout & to show progress of the download to the user, we
  80. * use the HTTP Range header to download one chunk of the file at a time. After each
  81. * chunk, it is the browser's responsibility to call the method again to continue the download.
  82. *
  83. * Input:
  84. * 'continue' query param - if set to 1, will assume we are currently downloading & use
  85. * Range: HTTP header to get another chunk of the file.
  86. *
  87. * Output (in JSON):
  88. * 'current_size' - Current size of the partially downloaded file on disk.
  89. * 'expected_file_size' - The expected finished file size as returned by the HTTP server.
  90. * 'next_screen' - When the download finishes, this is the next screen that should be shown.
  91. * 'error' - When an error occurs, the message is returned in this property.
  92. */
  93. public function downloadFreeGeoIPDB()
  94. {
  95. $this->dieIfGeolocationAdminIsDisabled();
  96. Piwik::checkUserHasSuperUserAccess();
  97. if ($_SERVER["REQUEST_METHOD"] == "POST") {
  98. $this->checkTokenInUrl();
  99. Json::sendHeaderJSON();
  100. $outputPath = GeoIp::getPathForGeoIpDatabase('GeoIPCity.dat') . '.gz';
  101. try {
  102. $result = Http::downloadChunk(
  103. $url = GeoIp::GEO_LITE_URL,
  104. $outputPath,
  105. $continue = Common::getRequestVar('continue', true, 'int')
  106. );
  107. // if the file is done
  108. if ($result['current_size'] >= $result['expected_file_size']) {
  109. GeoIPAutoUpdater::unzipDownloadedFile($outputPath, $unlink = true);
  110. // setup the auto updater
  111. GeoIPAutoUpdater::setUpdaterOptions(array(
  112. 'loc_db' => GeoIp::GEO_LITE_URL,
  113. 'period' => GeoIPAutoUpdater::SCHEDULE_PERIOD_MONTHLY,
  114. ));
  115. // make sure to echo out the geoip updater management screen
  116. $result['next_screen'] = $this->getGeoIpUpdaterManageScreen();
  117. }
  118. return json_encode($result);
  119. } catch (Exception $ex) {
  120. return json_encode(array('error' => $ex->getMessage()));
  121. }
  122. }
  123. }
  124. /**
  125. * Renders and returns the HTML that manages the GeoIP auto-updater.
  126. *
  127. * @return string
  128. */
  129. private function getGeoIpUpdaterManageScreen()
  130. {
  131. $view = new View('@UserCountry/getGeoIpUpdaterManageScreen');
  132. $view->geoIPDatabasesInstalled = true;
  133. $this->setUpdaterManageVars($view);
  134. return $view->render();
  135. }
  136. /**
  137. * Sets some variables needed by the _updaterManage.twig template.
  138. *
  139. * @param View $view
  140. */
  141. private function setUpdaterManageVars($view)
  142. {
  143. $urls = GeoIPAutoUpdater::getConfiguredUrls();
  144. $view->geoIPLocUrl = $urls['loc'];
  145. $view->geoIPIspUrl = $urls['isp'];
  146. $view->geoIPOrgUrl = $urls['org'];
  147. $view->geoIPUpdatePeriod = GeoIPAutoUpdater::getSchedulePeriod();
  148. $view->geoLiteUrl = GeoIp::GEO_LITE_URL;
  149. $lastRunTime = GeoIPAutoUpdater::getLastRunTime();
  150. if ($lastRunTime !== false) {
  151. $view->lastTimeUpdaterRun = '<strong><em>' . $lastRunTime->toString() . '</em></strong>';
  152. }
  153. $view->nextRunTime = GeoIPAutoUpdater::getNextRunTime();
  154. }
  155. /**
  156. * Sets the URLs used to download new versions of the installed GeoIP databases.
  157. *
  158. * Input (query params):
  159. * 'loc_db' - URL for a GeoIP location database.
  160. * 'isp_db' - URL for a GeoIP ISP database (optional).
  161. * 'org_db' - URL for a GeoIP Org database (optional).
  162. * 'period' - 'weekly' or 'monthly'. Determines how often update is run.
  163. *
  164. * Output (json):
  165. * 'error' - if an error occurs its message is set as the resulting JSON object's
  166. * 'error' property.
  167. */
  168. public function updateGeoIPLinks()
  169. {
  170. $this->dieIfGeolocationAdminIsDisabled();
  171. Piwik::checkUserHasSuperUserAccess();
  172. if ($_SERVER["REQUEST_METHOD"] == "POST") {
  173. Json::sendHeaderJSON();
  174. try {
  175. $this->checkTokenInUrl();
  176. GeoIPAutoUpdater::setUpdaterOptionsFromUrl();
  177. // if there is a updater URL for a database, but its missing from the misc dir, tell
  178. // the browser so it can download it next
  179. $info = $this->getNextMissingDbUrlInfo();
  180. if ($info !== false) {
  181. return json_encode($info);
  182. } else {
  183. $view = new View("@UserCountry/_updaterNextRunTime");
  184. $view->nextRunTime = GeoIPAutoUpdater::getNextRunTime();
  185. $nextRunTimeHtml = $view->render();
  186. return json_encode(array('nextRunTime' => $nextRunTimeHtml));
  187. }
  188. } catch (Exception $ex) {
  189. return json_encode(array('error' => $ex->getMessage()));
  190. }
  191. }
  192. }
  193. /**
  194. * Starts or continues a download for a missing GeoIP database. A database is missing if
  195. * it has an update URL configured, but the actual database is not available in the misc
  196. * directory.
  197. *
  198. * Input:
  199. * 'url' - The URL to download the database from.
  200. * 'continue' - 1 if we're continuing a download, 0 if we're starting one.
  201. *
  202. * Output:
  203. * 'error' - If an error occurs this describes the error.
  204. * 'to_download' - The URL of a missing database that should be downloaded next (if any).
  205. * 'to_download_label' - The label to use w/ the progress bar that describes what we're
  206. * downloading.
  207. * 'current_size' - Size of the current file on disk.
  208. * 'expected_file_size' - Size of the completely downloaded file.
  209. */
  210. public function downloadMissingGeoIpDb()
  211. {
  212. $this->dieIfGeolocationAdminIsDisabled();
  213. Piwik::checkUserHasSuperUserAccess();
  214. if ($_SERVER["REQUEST_METHOD"] == "POST") {
  215. try {
  216. $this->checkTokenInUrl();
  217. Json::sendHeaderJSON();
  218. // based on the database type (provided by the 'key' query param) determine the
  219. // url & output file name
  220. $key = Common::getRequestVar('key', null, 'string');
  221. $url = GeoIPAutoUpdater::getConfiguredUrl($key);
  222. $ext = GeoIPAutoUpdater::getGeoIPUrlExtension($url);
  223. $filename = GeoIp::$dbNames[$key][0] . '.' . $ext;
  224. if (substr($filename, 0, 15) == 'GeoLiteCity.dat') {
  225. $filename = 'GeoIPCity.dat' . substr($filename, 15);
  226. }
  227. $outputPath = GeoIp::getPathForGeoIpDatabase($filename);
  228. // download part of the file
  229. $result = Http::downloadChunk(
  230. $url, $outputPath, Common::getRequestVar('continue', true, 'int'));
  231. // if the file is done
  232. if ($result['current_size'] >= $result['expected_file_size']) {
  233. GeoIPAutoUpdater::unzipDownloadedFile($outputPath, $unlink = true);
  234. $info = $this->getNextMissingDbUrlInfo();
  235. if ($info !== false) {
  236. return json_encode($info);
  237. }
  238. }
  239. return json_encode($result);
  240. } catch (Exception $ex) {
  241. return json_encode(array('error' => $ex->getMessage()));
  242. }
  243. }
  244. }
  245. /**
  246. * Sets the current LocationProvider type.
  247. *
  248. * Input:
  249. * Requires the 'id' query parameter to be set to the desired LocationProvider's ID.
  250. *
  251. * Output:
  252. * Nothing.
  253. */
  254. public function setCurrentLocationProvider()
  255. {
  256. $this->dieIfGeolocationAdminIsDisabled();
  257. Piwik::checkUserHasSuperUserAccess();
  258. if ($_SERVER["REQUEST_METHOD"] == "POST") {
  259. $this->checkTokenInUrl();
  260. $providerId = Common::getRequestVar('id');
  261. $provider = LocationProvider::setCurrentProvider($providerId);
  262. if ($provider === false) {
  263. throw new Exception("Invalid provider ID: '$providerId'.");
  264. }
  265. return 1;
  266. }
  267. }
  268. /**
  269. * Echo's a pretty formatted location using a specific LocationProvider.
  270. *
  271. * Input:
  272. * The 'id' query parameter must be set to the ID of the LocationProvider to use.
  273. *
  274. * Output:
  275. * The pretty formatted location that was obtained. Will be HTML.
  276. */
  277. public function getLocationUsingProvider()
  278. {
  279. $providerId = Common::getRequestVar('id');
  280. $provider = LocationProvider::getProviderById($providerId);
  281. if (empty($provider)) {
  282. throw new Exception("Invalid provider ID: '$providerId'.");
  283. }
  284. $location = $provider->getLocation(array('ip' => IP::getIpFromHeader(),
  285. 'lang' => Common::getBrowserLanguage(),
  286. 'disable_fallbacks' => true));
  287. $location = LocationProvider::prettyFormatLocation(
  288. $location, $newline = '<br/>', $includeExtra = true);
  289. return $location;
  290. }
  291. public function getNumberOfDistinctCountries()
  292. {
  293. return $this->getNumericValue('UserCountry.getNumberOfDistinctCountries');
  294. }
  295. public function getLastDistinctCountriesGraph()
  296. {
  297. $view = $this->getLastUnitGraph('UserCountry', __FUNCTION__, "UserCountry.getNumberOfDistinctCountries");
  298. $view->config->columns_to_display = array('UserCountry_distinctCountries');
  299. return $this->renderView($view);
  300. }
  301. /**
  302. * Gets information for the first missing GeoIP database (if any).
  303. *
  304. * @return bool
  305. */
  306. private function getNextMissingDbUrlInfo()
  307. {
  308. $missingDbs = GeoIPAutoUpdater::getMissingDatabases();
  309. if (!empty($missingDbs)) {
  310. $missingDbKey = $missingDbs[0];
  311. $missingDbName = GeoIp::$dbNames[$missingDbKey][0];
  312. $url = GeoIPAutoUpdater::getConfiguredUrl($missingDbKey);
  313. $link = '<a href="' . $url . '">' . $missingDbName . '</a>';
  314. return array(
  315. 'to_download' => $missingDbKey,
  316. 'to_download_label' => Piwik::translate('UserCountry_DownloadingDb', $link) . '...',
  317. );
  318. }
  319. return false;
  320. }
  321. private function dieIfGeolocationAdminIsDisabled()
  322. {
  323. if (!UserCountry::isGeoLocationAdminEnabled()) {
  324. throw new \Exception('Geo location setting page has been disabled.');
  325. }
  326. }
  327. }