update Piwik to version 2.16 (fixes #91)

This commit is contained in:
oliver 2016-04-10 18:55:57 +02:00
commit d885a4baa9
5833 changed files with 418860 additions and 226988 deletions

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -11,20 +11,25 @@ namespace Piwik\Plugins\SitesManager;
use Exception;
use Piwik\Access;
use Piwik\Common;
use Piwik\Container\StaticContainer;
use Piwik\Date;
use Piwik\Db;
use Piwik\IP;
use Piwik\MetricsFormatter;
use Piwik\Metrics\Formatter;
use Piwik\Network\IPUtils;
use Piwik\Option;
use Piwik\Piwik;
use Piwik\Measurable\MeasurableSettings;
use Piwik\ProxyHttp;
use Piwik\Scheduler\Scheduler;
use Piwik\SettingsPiwik;
use Piwik\SettingsServer;
use Piwik\Site;
use Piwik\TaskScheduler;
use Piwik\Tracker;
use Piwik\Tracker\Cache;
use Piwik\Tracker\TrackerCodeGenerator;
use Piwik\Measurable\Type;
use Piwik\Url;
use Piwik\UrlHelper;
use Piwik\ProxyHttp;
/**
* The SitesManager API gives you full control on Websites in Piwik (create, update and delete), and many methods to retrieve websites based on various attributes.
@ -39,7 +44,7 @@ use Piwik\ProxyHttp;
* Some methods will affect all websites globally: "setGlobalExcludedIps" will set the list of IPs to be excluded on all websites,
* "setGlobalExcludedQueryParameters" will set the list of URL parameters to remove from URLs for all websites.
* The existing values can be fetched via "getExcludedIpsGlobal" and "getExcludedQueryParametersGlobal".
* See also the documentation about <a href='http://piwik.org/docs/manage-websites/' target='_blank'>Managing Websites</a> in Piwik.
* See also the documentation about <a href='http://piwik.org/docs/manage-websites/' rel='noreferrer' target='_blank'>Managing Websites</a> in Piwik.
* @method static \Piwik\Plugins\SitesManager\API getInstance()
*/
class API extends \Piwik\Plugin\API
@ -69,27 +74,35 @@ class API extends \Piwik\Plugin\API
* @param bool $customCampaignNameQueryParam
* @param bool $customCampaignKeywordParam
* @param bool $doNotTrack
* @internal param $
* @param bool $disableCookies
* @return string The Javascript tag ready to be included on the HTML pages
*/
public function getJavascriptTag($idSite, $piwikUrl = '', $mergeSubdomains = false, $groupPageTitlesByDomain = false,
$mergeAliasUrls = false, $visitorCustomVariables = false, $pageCustomVariables = false,
$customCampaignNameQueryParam = false, $customCampaignKeywordParam = false,
$doNotTrack = false)
$doNotTrack = false, $disableCookies = false)
{
Piwik::checkUserHasViewAccess($idSite);
if (empty($piwikUrl)) {
$piwikUrl = SettingsPiwik::getPiwikUrl();
}
$piwikUrl = Common::sanitizeInputValues($piwikUrl);
$htmlEncoded = Piwik::getJavascriptCode($idSite, $piwikUrl, $mergeSubdomains, $groupPageTitlesByDomain,
$mergeAliasUrls, $visitorCustomVariables, $pageCustomVariables,
$customCampaignNameQueryParam, $customCampaignKeywordParam,
$doNotTrack);
$htmlEncoded = str_replace(array('<br>', '<br />', '<br/>'), '', $htmlEncoded);
return $htmlEncoded;
// Revert the automatic encoding
// TODO remove that when https://github.com/piwik/piwik/issues/4231 is fixed
$piwikUrl = Common::unsanitizeInputValue($piwikUrl);
$visitorCustomVariables = Common::unsanitizeInputValues($visitorCustomVariables);
$pageCustomVariables = Common::unsanitizeInputValues($pageCustomVariables);
$customCampaignNameQueryParam = Common::unsanitizeInputValue($customCampaignNameQueryParam);
$customCampaignKeywordParam = Common::unsanitizeInputValue($customCampaignKeywordParam);
$generator = new TrackerCodeGenerator();
$code = $generator->generate($idSite, $piwikUrl, $mergeSubdomains, $groupPageTitlesByDomain,
$mergeAliasUrls, $visitorCustomVariables, $pageCustomVariables,
$customCampaignNameQueryParam, $customCampaignKeywordParam,
$doNotTrack, $disableCookies);
$code = str_replace(array('<br>', '<br />', '<br/>'), '', $code);
return $code;
}
/**
@ -103,14 +116,14 @@ class API extends \Piwik\Plugin\API
*/
public function getImageTrackingCode($idSite, $piwikUrl = '', $actionName = false, $idGoal = false, $revenue = false)
{
$urlParams = array('idSite' => $idSite, 'rec' => 1);
$urlParams = array('idsite' => $idSite, 'rec' => 1);
if ($actionName !== false) {
$urlParams['action_name'] = urlencode(Common::unsanitizeInputValue($actionName));
}
if ($idGoal !== false) {
$urlParams['idGoal'] = $idGoal;
$urlParams['idgoal'] = $idGoal;
if ($revenue !== false) {
$urlParams['revenue'] = $revenue;
}
@ -139,14 +152,12 @@ class API extends \Piwik\Plugin\API
* @param string $group Group name
* @return array of sites
*/
public function getSitesFromGroup($group)
public function getSitesFromGroup($group = '')
{
Piwik::checkUserHasSuperUserAccess();
$group = trim($group);
$sites = Db::get()->fetchAll("SELECT *
FROM " . Common::prefixTable("site") . "
WHERE `group` = ?", $group);
$group = trim($group);
$sites = $this->getModel()->getSitesFromGroup($group);
Site::setSitesFromArray($sites);
return $sites;
@ -161,12 +172,10 @@ class API extends \Piwik\Plugin\API
public function getSitesGroups()
{
Piwik::checkUserHasSuperUserAccess();
$groups = Db::get()->fetchAll("SELECT DISTINCT `group` FROM " . Common::prefixTable("site"));
$cleanedGroups = array();
foreach ($groups as $group) {
$cleanedGroups[] = $group['group'];
}
$cleanedGroups = array_map('trim', $cleanedGroups);
$groups = $this->getModel()->getSitesGroups();
$cleanedGroups = array_map('trim', $groups);
return $cleanedGroups;
}
@ -180,32 +189,17 @@ class API extends \Piwik\Plugin\API
public function getSiteFromId($idSite)
{
Piwik::checkUserHasViewAccess($idSite);
$site = Db::get()->fetchRow("SELECT *
FROM " . Common::prefixTable("site") . "
WHERE idsite = ?", $idSite);
Site::setSitesFromArray(array($site));
$site = $this->getModel()->getSiteFromId($idSite);
Site::setSiteFromArray($idSite, $site);
return $site;
}
/**
* Returns the list of alias URLs registered for the given idSite.
* The website ID must be valid when calling this method!
*
* @param int $idSite
* @return array list of alias URLs
*/
private function getAliasSiteUrlsFromId($idSite)
private function getModel()
{
$db = Db::get();
$result = $db->fetchAll("SELECT url
FROM " . Common::prefixTable("site_url") . "
WHERE idsite = ?", $idSite);
$urls = array();
foreach ($result as $url) {
$urls[] = $url['url'];
}
return $urls;
return new Model();
}
/**
@ -218,25 +212,12 @@ class API extends \Piwik\Plugin\API
public function getSiteUrlsFromId($idSite)
{
Piwik::checkUserHasViewAccess($idSite);
$site = new Site($idSite);
$urls = $this->getAliasSiteUrlsFromId($idSite);
return array_merge(array($site->getMainUrl()), $urls);
return $this->getModel()->getSiteUrlsFromId($idSite);
}
/**
* Returns the list of all the website IDs registered.
* Caller must check access.
*
* @return array The list of website IDs
*/
private function getSitesId()
{
$result = Db::fetchAll("SELECT idsite FROM " . Common::prefixTable('site'));
$idSites = array();
foreach ($result as $idSite) {
$idSites[] = $idSite['idsite'];
}
return $idSites;
return $this->getModel()->getSitesId();
}
/**
@ -247,12 +228,15 @@ class API extends \Piwik\Plugin\API
public function getAllSites()
{
Piwik::checkUserHasSuperUserAccess();
$sites = Db::get()->fetchAll("SELECT * FROM " . Common::prefixTable("site") . " ORDER BY idsite ASC");
$sites = $this->getModel()->getAllSites();
$return = array();
foreach ($sites as $site) {
$return[$site['idsite']] = $site;
}
Site::setSitesFromArray($return);
return $return;
}
@ -266,7 +250,7 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSuperUserAccess();
try {
return API::getInstance()->getSitesId();
return $this->getSitesId();
} catch (Exception $e) {
// can be called before Piwik tables are created so return empty
return array();
@ -279,6 +263,7 @@ class API extends \Piwik\Plugin\API
*
* @param bool|int $timestamp
* @return array The list of website IDs
* @deprecated since 2.15 This method will be removed in Piwik 3.0, there is no replacement.
*/
public function getSitesIdWithVisits($timestamp = false)
{
@ -286,24 +271,16 @@ class API extends \Piwik\Plugin\API
if (empty($timestamp)) $timestamp = time();
$time = Date::factory((int)$timestamp)->getDatetime();
$result = Db::fetchAll("
SELECT
idsite
FROM
" . Common::prefixTable('site') . " s
WHERE EXISTS (
SELECT 1
FROM " . Common::prefixTable('log_visit') . " v
WHERE v.idsite = s.idsite
AND visit_last_action_time > ?
AND visit_last_action_time <= ?
LIMIT 1)
", array($time, $now = Date::now()->addHour(1)->getDatetime()));
$time = Date::factory((int)$timestamp)->getDatetime();
$now = Date::now()->addHour(1)->getDatetime();
$result = $this->getModel()->getSitesWithVisits($time, $now);
$idSites = array();
foreach ($result as $idSite) {
$idSites[] = $idSite['idsite'];
}
return $idSites;
}
@ -311,12 +288,29 @@ class API extends \Piwik\Plugin\API
* Returns the list of websites with the 'admin' access for the current user.
* For the superUser it returns all the websites in the database.
*
* @param bool $fetchAliasUrls
* @param false|string $pattern
* @param false|int $limit
* @return array for each site, an array of information (idsite, name, main_url, etc.)
*/
public function getSitesWithAdminAccess()
public function getSitesWithAdminAccess($fetchAliasUrls = false, $pattern = false, $limit = false)
{
$sitesId = $this->getSitesIdWithAdminAccess();
return $this->getSitesFromIds($sitesId);
if ($pattern === false) {
$sites = $this->getSitesFromIds($sitesId, $limit);
} else {
$sites = $this->getModel()->getPatternMatchSites($sitesId, $pattern, $limit);
Site::setSitesFromArray($sites);
}
if ($fetchAliasUrls) {
foreach ($sites as &$site) {
$site['alias_urls'] = $this->getSiteUrlsFromId($site['idsite']);
}
}
return $sites;
}
/**
@ -377,7 +371,10 @@ class API extends \Piwik\Plugin\API
*/
public function getSitesIdWithAtLeastViewAccess($_restrictSitesToLogin = false)
{
if (Piwik::hasUserSuperUserAccess() && !TaskScheduler::isTaskBeingExecuted()) {
/** @var Scheduler $scheduler */
$scheduler = StaticContainer::getContainer()->get('Piwik\Scheduler\Scheduler');
if (Piwik::hasUserSuperUserAccess() && !$scheduler->isRunningTask()) {
return Access::getInstance()->getSitesIdWithAtLeastViewAccess();
}
@ -386,7 +383,7 @@ class API extends \Piwik\Plugin\API
// but during scheduled task execution, we sometimes want to restrict sites to
// a different login than the superuser.
&& (Piwik::hasUserSuperUserAccessOrIsTheUser($_restrictSitesToLogin)
|| TaskScheduler::isTaskBeingExecuted())
|| $scheduler->isRunningTask())
) {
if (Piwik::hasTheUserSuperUserAccess($_restrictSitesToLogin)) {
@ -394,10 +391,12 @@ class API extends \Piwik\Plugin\API
}
$accessRaw = Access::getInstance()->getRawSitesWithSomeViewAccess($_restrictSitesToLogin);
$sitesId = array();
$sitesId = array();
foreach ($accessRaw as $access) {
$sitesId[] = $access['idsite'];
}
return $sitesId;
} else {
return Access::getInstance()->getSitesIdWithAtLeastViewAccess();
@ -414,32 +413,28 @@ class API extends \Piwik\Plugin\API
*/
private function getSitesFromIds($idSites, $limit = false)
{
if (count($idSites) === 0) {
return array();
}
if ($limit) {
$limit = "LIMIT " . (int)$limit;
}
$db = Db::get();
$sites = $db->fetchAll("SELECT *
FROM " . Common::prefixTable("site") . "
WHERE idsite IN (" . implode(", ", $idSites) . ")
ORDER BY idsite ASC $limit");
$sites = $this->getModel()->getSitesFromIds($idSites, $limit);
Site::setSitesFromArray($sites);
return $sites;
}
protected function getNormalizedUrls($url)
{
if (strpos($url, 'www.') !== false) {
$urlBis = str_replace('www.', '', $url);
} else {
$urlBis = str_replace('://', '://www.', $url);
}
return array($url, $urlBis);
// if found, remove scheme and www. from URL
$hostname = str_replace('www.', '', $url);
$hostname = str_replace('http://', '', $hostname);
$hostname = str_replace('https://', '', $hostname);
// return all variations of the URL
return array(
$url,
"http://" . $hostname,
"http://www." . $hostname,
"https://" . $hostname,
"https://www." . $hostname
);
}
/**
@ -451,29 +446,13 @@ class API extends \Piwik\Plugin\API
public function getSitesIdFromSiteUrl($url)
{
$url = $this->removeTrailingSlash($url);
list($url, $urlBis) = $this->getNormalizedUrls($url);
$normalisedUrls = $this->getNormalizedUrls($url);
if (Piwik::hasUserSuperUserAccess()) {
$ids = Db::get()->fetchAll(
'SELECT idsite
FROM ' . Common::prefixTable('site') . '
WHERE (main_url = ? OR main_url = ?) ' .
'UNION
SELECT idsite
FROM ' . Common::prefixTable('site_url') . '
WHERE (url = ? OR url = ?) ', array($url, $urlBis, $url, $urlBis));
$ids = $this->getModel()->getAllSitesIdFromSiteUrl($normalisedUrls);
} else {
$login = Piwik::getCurrentUserLogin();
$ids = Db::get()->fetchAll(
'SELECT idsite
FROM ' . Common::prefixTable('site') . '
WHERE (main_url = ? OR main_url = ?)' .
'AND idsite IN (' . Access::getSqlAccessSite('idsite') . ') ' .
'UNION
SELECT idsite
FROM ' . Common::prefixTable('site_url') . '
WHERE (url = ? OR url = ?)' .
'AND idsite IN (' . Access::getSqlAccessSite('idsite') . ')',
array($url, $urlBis, $login, $url, $urlBis, $login));
$ids = $this->getModel()->getSitesIdFromSiteUrlHavingAccess($login, $normalisedUrls);
}
return $ids;
@ -489,18 +468,17 @@ class API extends \Piwik\Plugin\API
public function getSitesIdFromTimezones($timezones)
{
Piwik::checkUserHasSuperUserAccess();
$timezones = Piwik::getArrayFromApiParameter($timezones);
$timezones = array_unique($timezones);
$ids = Db::get()->fetchAll(
'SELECT idsite
FROM ' . Common::prefixTable('site') . '
WHERE timezone IN (' . Common::getSqlStringFieldsArray($timezones) . ')
ORDER BY idsite ASC',
$timezones);
$ids = $this->getModel()->getSitesFromTimezones($timezones);
$return = array();
foreach ($ids as $id) {
$return[] = $id['idsite'];
}
return $return;
}
@ -526,8 +504,10 @@ class API extends \Piwik\Plugin\API
* @param null|string $excludedUserAgents
* @param int $keepURLFragments If 1, URL fragments will be kept when tracking. If 2, they
* will be removed. If 0, the default global behavior will be used.
* @param array|null $settings JSON serialized settings eg {settingName: settingValue, ...}
* @see getKeepURLFragmentsGlobal.
* @param string $type The website type, defaults to "website" if not set.
* @param bool|null $excludeUnknownUrls Track only URL matching one of website URLs
*
* @return int the website ID created
*/
@ -545,7 +525,9 @@ class API extends \Piwik\Plugin\API
$startDate = null,
$excludedUserAgents = null,
$keepURLFragments = null,
$type = null)
$type = null,
$settings = null,
$excludeUnknownUrls = null)
{
Piwik::checkUserHasSuperUserAccess();
@ -570,47 +552,53 @@ class API extends \Piwik\Plugin\API
}
$this->checkValidCurrency($currency);
$db = Db::get();
$url = $urls[0];
$url = $urls[0];
$urls = array_slice($urls, 1);
$bind = array('name' => $siteName,
'main_url' => $url,
);
'main_url' => $url);
$bind['exclude_unknown_urls'] = (int)$excludeUnknownUrls;
$bind['excluded_ips'] = $this->checkAndReturnExcludedIps($excludedIps);
$bind['excluded_parameters'] = $this->checkAndReturnCommaSeparatedStringList($excludedQueryParameters);
$bind['excluded_parameters'] = $this->checkAndReturnCommaSeparatedStringList($excludedQueryParameters);
$bind['excluded_user_agents'] = $this->checkAndReturnCommaSeparatedStringList($excludedUserAgents);
$bind['keep_url_fragment'] = $keepURLFragments;
$bind['timezone'] = $timezone;
$bind['currency'] = $currency;
$bind['ecommerce'] = (int)$ecommerce;
$bind['keep_url_fragment'] = $keepURLFragments;
$bind['timezone'] = $timezone;
$bind['currency'] = $currency;
$bind['ecommerce'] = (int)$ecommerce;
$bind['sitesearch'] = $siteSearch;
$bind['sitesearch_keyword_parameters'] = $searchKeywordParameters;
$bind['sitesearch_keyword_parameters'] = $searchKeywordParameters;
$bind['sitesearch_category_parameters'] = $searchCategoryParameters;
$bind['ts_created'] = !is_null($startDate)
? Date::factory($startDate)->getDatetime()
: Date::now()->getDatetime();
if (is_null($startDate)) {
$bind['ts_created'] = Date::now()->getDatetime();
} else {
$bind['ts_created'] = Date::factory($startDate)->getDatetime();
}
$bind['type'] = $this->checkAndReturnType($type);
if (!empty($group)
&& Piwik::hasUserSuperUserAccess()
) {
if (!empty($group) && Piwik::hasUserSuperUserAccess()) {
$bind['group'] = trim($group);
} else {
$bind['group'] = "";
}
$db->insert(Common::prefixTable("site"), $bind);
if (!empty($settings)) {
$this->validateMeasurableSettings(0, $bind['type'], $settings);
}
$idSite = $db->lastInsertId();
$idSite = $this->getModel()->createSite($bind);
$this->insertSiteUrls($idSite, $urls);
// we reload the access list which doesn't yet take in consideration this new website
Access::getInstance()->reloadAccess();
if (!empty($settings)) {
$this->updateMeasurableSettings($idSite, $settings);
}
$this->postUpdateWebsite($idSite);
/**
@ -620,13 +608,45 @@ class API extends \Piwik\Plugin\API
*/
Piwik::postEvent('SitesManager.addSite.end', array($idSite));
return (int)$idSite;
return (int) $idSite;
}
private function validateMeasurableSettings($idSite, $idType, $settings)
{
$measurableSettings = new MeasurableSettings($idSite, $idType);
foreach ($measurableSettings->getSettingsForCurrentUser() as $measurableSetting) {
$name = $measurableSetting->getName();
if (!empty($settings[$name])) {
$measurableSetting->setValue($settings[$name]);
}
}
}
private function updateMeasurableSettings($idSite, $settings)
{
$idType = Site::getTypeFor($idSite);
$measurableSettings = new MeasurableSettings($idSite, $idType);
foreach ($measurableSettings->getSettingsForCurrentUser() as $measurableSetting) {
$name = $measurableSetting->getName();
if (!empty($settings[$name])) {
$measurableSetting->setValue($settings[$name]);
}
// we do not clear existing settings if the value is missing.
// There can be so many settings added by random plugins one would always clear some settings.
}
$measurableSettings->save();
}
private function postUpdateWebsite($idSite)
{
Site::clearCache();
Cache::regenerateCacheWebsiteAttributes($idSite);
Cache::clearCacheGeneral();
SiteUrls::clearSitesCache();
}
/**
@ -641,7 +661,7 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSuperUserAccess();
$idSites = API::getInstance()->getSitesId();
$idSites = $this->getSitesId();
if (!in_array($idSite, $idSites)) {
throw new Exception("website id = $idSite not found");
}
@ -650,27 +670,15 @@ class API extends \Piwik\Plugin\API
throw new Exception(Piwik::translate("SitesManager_ExceptionDeleteSite"));
}
$db = Db::get();
$db->query("DELETE FROM " . Common::prefixTable("site") . "
WHERE idsite = ?", $idSite);
$db->query("DELETE FROM " . Common::prefixTable("site_url") . "
WHERE idsite = ?", $idSite);
$db->query("DELETE FROM " . Common::prefixTable("access") . "
WHERE idsite = ?", $idSite);
// we do not delete logs here on purpose (you can run these queries on the log_ tables to delete all data)
Cache::deleteCacheWebsiteAttributes($idSite);
$this->getModel()->deleteSite($idSite);
/**
* Triggered after a site has been deleted.
*
*
* Plugins can use this event to remove site specific values or settings, such as removing all
* goals that belong to a specific website. If you store any data related to a website you
* should clean up that information here.
*
*
* @param int $idSite The ID of the site being deleted.
*/
Piwik::postEvent('SitesManager.deleteSite.end', array($idSite));
@ -713,12 +721,14 @@ class API extends \Piwik\Plugin\API
private function checkAndReturnType($type)
{
if(empty($type)) {
if (empty($type)) {
$type = Site::DEFAULT_SITE_TYPE;
}
if(!is_string($type)) {
if (!is_string($type)) {
throw new Exception("Invalid website type $type");
}
return $type;
}
@ -735,14 +745,17 @@ class API extends \Piwik\Plugin\API
if (empty($excludedIps)) {
return '';
}
$ips = explode(',', $excludedIps);
$ips = array_map('trim', $ips);
$ips = array_filter($ips, 'strlen');
foreach ($ips as $ip) {
if (!$this->isValidIp($ip)) {
throw new Exception(Piwik::translate('SitesManager_ExceptionInvalidIPFormat', array($ip, "1.2.3.4, 1.2.3.*, or 1.2.3.4/5")));
}
}
$ips = implode(',', $ips);
return $ips;
}
@ -787,7 +800,7 @@ class API extends \Piwik\Plugin\API
$urls = $this->cleanParameterUrls($urls);
$this->checkUrls($urls);
$this->deleteSiteAliasUrls($idSite);
$this->getModel()->deleteSiteAliasUrls($idSite);
$this->insertSiteUrls($idSite, $urls);
$this->postUpdateWebsite($idSite);
@ -802,12 +815,12 @@ class API extends \Piwik\Plugin\API
*/
public function getIpsForRange($ipRange)
{
$range = IP::getIpsForRange($ipRange);
if ($range === false) {
$range = IPUtils::getIPRangeBounds($ipRange);
if ($range === null) {
return false;
}
return array(IP::N2P($range[0]), IP::N2P($range[1]));
return array(IPUtils::binaryToStringIP($range[0]), IPUtils::binaryToStringIP($range[1]));
}
/**
@ -1078,6 +1091,8 @@ class API extends \Piwik\Plugin\API
* @param int|null $keepURLFragments If 1, URL fragments will be kept when tracking. If 2, they
* will be removed. If 0, the default global behavior will be used.
* @param string $type The Website type, default value is "website"
* @param array|null $settings JSON serialized settings eg {settingName: settingValue, ...}
* @param bool|null $excludeUnknownUrls Track only URL matching one of website URLs
* @throws Exception
* @see getKeepURLFragmentsGlobal. If null, the existing value will
* not be modified.
@ -1099,11 +1114,14 @@ class API extends \Piwik\Plugin\API
$startDate = null,
$excludedUserAgents = null,
$keepURLFragments = null,
$type = null)
$type = null,
$settings = null,
$excludeUnknownUrls = null)
{
Piwik::checkUserHasAdminAccess($idSite);
$idSites = API::getInstance()->getSitesId();
$idSites = $this->getSitesId();
if (!in_array($idSite, $idSites)) {
throw new Exception("website id = $idSite not found");
}
@ -1145,6 +1163,7 @@ class API extends \Piwik\Plugin\API
if (!is_null($startDate)) {
$bind['ts_created'] = Date::factory($startDate)->getDatetime();
}
$bind['exclude_unknown_urls'] = (int)$excludeUnknownUrls;
$bind['excluded_ips'] = $this->checkAndReturnExcludedIps($excludedIps);
$bind['excluded_parameters'] = $this->checkAndReturnCommaSeparatedStringList($excludedQueryParameters);
$bind['excluded_user_agents'] = $this->checkAndReturnCommaSeparatedStringList($excludedUserAgents);
@ -1160,20 +1179,28 @@ class API extends \Piwik\Plugin\API
list($searchKeywordParameters, $searchCategoryParameters) = $this->checkSiteSearchParameters($searchKeywordParameters, $searchCategoryParameters);
$bind['sitesearch_keyword_parameters'] = $searchKeywordParameters;
$bind['sitesearch_category_parameters'] = $searchCategoryParameters;
$bind['type'] = $this->checkAndReturnType($type);
$db = Db::get();
$db->update(Common::prefixTable("site"),
$bind,
"idsite = $idSite"
);
if (!is_null($type)) {
$bind['type'] = $this->checkAndReturnType($type);
}
if (!empty($settings)) {
$this->validateMeasurableSettings($idSite, Site::getTypeFor($idSite), $settings);
}
$this->getModel()->updateSite($bind, $idSite);
if (!empty($settings)) {
$this->updateMeasurableSettings($idSite, $settings);
}
// we now update the main + alias URLs
$this->deleteSiteAliasUrls($idSite);
$this->getModel()->deleteSiteAliasUrls($idSite);
if (count($urls) > 1) {
$this->addSiteAliasUrls($idSite, array_slice($urls, 1));
}
$this->postUpdateWebsite($idSite);
}
@ -1185,19 +1212,14 @@ class API extends \Piwik\Plugin\API
*
* @ignore
*/
public function updateSiteCreatedTime($idSites, $minDate)
public function updateSiteCreatedTime($idSites, Date $minDate)
{
$idSites = Site::getIdSitesFromIdSitesString($idSites);
Piwik::checkUserHasAdminAccess($idSites);
// Update piwik_site.ts_created
$query = "UPDATE " . Common::prefixTable("site") .
" SET ts_created = ?" .
" WHERE idsite IN ( " . implode(",", $idSites) . " )
AND ts_created > ?";
$minDateSql = $minDate->subDay(1)->getDatetime();
$bind = array($minDateSql, $minDateSql);
Db::query($query, $bind);
$this->getModel()->updateSiteCreatedTime($idSites, $minDateSql);
}
private function checkAndReturnCommaSeparatedStringList($parameters)
@ -1221,7 +1243,7 @@ class API extends \Piwik\Plugin\API
*/
public function getCurrencyList()
{
$currencies = MetricsFormatter::getCurrencyList();
$currencies = Site::getCurrencyList();
return array_map(function ($a) {
return $a[1] . " (" . $a[0] . ")";
}, $currencies);
@ -1234,12 +1256,23 @@ class API extends \Piwik\Plugin\API
*/
public function getCurrencySymbols()
{
$currencies = MetricsFormatter::getCurrencyList();
$currencies = Site::getCurrencyList();
return array_map(function ($a) {
return $a[0];
}, $currencies);
}
/**
* Return true if Timezone support is enabled on server
*
* @return bool
*/
public function isTimezoneSupportEnabled()
{
Piwik::checkUserHasSomeViewAccess();
return SettingsServer::isTimezoneSupportEnabled();
}
/**
* Returns the list of timezones supported.
* Used for addSite and updateSite
@ -1297,6 +1330,8 @@ class API extends \Piwik\Plugin\API
$return = array();
foreach ($GmtOffsets as $offset) {
$offset = Common::forceDotAsSeparatorForDecimalPoint($offset);
if ($offset > 0) {
$offset = '+' . $offset;
} elseif ($offset == 0) {
@ -1317,12 +1352,8 @@ class API extends \Piwik\Plugin\API
public function getUniqueSiteTimezones()
{
Piwik::checkUserHasSuperUserAccess();
$results = Db::fetchAll("SELECT distinct timezone FROM " . Common::prefixTable('site'));
$timezones = array();
foreach ($results as $result) {
$timezones[] = $result['timezone'];
}
return $timezones;
return $this->getModel()->getUniqueSiteTimezones();
}
/**
@ -1332,14 +1363,9 @@ class API extends \Piwik\Plugin\API
private function insertSiteUrls($idSite, $urls)
{
if (count($urls) != 0) {
$db = Db::get();
foreach ($urls as $url) {
try {
$db->insert(Common::prefixTable("site_url"), array(
'idsite' => $idSite,
'url' => $url
)
);
$this->getModel()->insertSiteUrl($idSite, $url);
} catch(Exception $e) {
// See bug #4149
}
@ -1347,16 +1373,6 @@ class API extends \Piwik\Plugin\API
}
}
/**
* Delete all the alias URLs for the given idSite.
*/
private function deleteSiteAliasUrls($idsite)
{
$db = Db::get();
$db->query("DELETE FROM " . Common::prefixTable("site_url") . "
WHERE idsite = ?", $idsite);
}
/**
* Remove the final slash in the URLs if found
*
@ -1371,6 +1387,7 @@ class API extends \Piwik\Plugin\API
) {
$url = substr($url, 0, strlen($url) - 1);
}
return $url;
}
@ -1394,7 +1411,7 @@ class API extends \Piwik\Plugin\API
*/
private function isValidIp($ip)
{
return IP::getIpsForRange($ip) !== false;
return IPUtils::getIPRangeBounds($ip) !== null;
}
/**
@ -1425,6 +1442,7 @@ class API extends \Piwik\Plugin\API
if (empty($searchKeywordParameters)) {
$searchKeywordParameters = '';
}
if (empty($searchCategoryParameters)) {
$searchCategoryParameters = '';
}
@ -1460,17 +1478,22 @@ class API extends \Piwik\Plugin\API
if (!is_array($urls)) {
$urls = array($urls);
}
$urls = array_filter($urls);
$urls = array_filter($urls);
$urls = array_map('urldecode', $urls);
foreach ($urls as &$url) {
$url = $this->removeTrailingSlash($url);
if (strpos($url, 'http') !== 0) {
$scheme = parse_url($url, PHP_URL_SCHEME);
if (empty($scheme)
&& strpos($url, '://') === false
) {
$url = 'http://' . $url;
}
$url = trim($url);
$url = Common::sanitizeInputValue($url);
}
$urls = array_unique($urls);
return $urls;
}
@ -1503,40 +1526,45 @@ class API extends \Piwik\Plugin\API
return true;
}
public function getPatternMatchSites($pattern)
/**
* Find websites matching the given pattern.
*
* Any website will be returned that matches the pattern in the name, URL or group.
* To limit the number of returned sites you can either specify `filter_limit` as usual or `limit` which is
* faster.
*
* @param string $pattern
* @param int|false $limit
* @return array
*/
public function getPatternMatchSites($pattern, $limit = false)
{
$ids = $this->getSitesIdWithAtLeastViewAccess();
if (empty($ids)) {
return array();
}
$ids_str = '';
foreach ($ids as $id_val) {
$ids_str .= $id_val . ' , ';
}
$ids_str .= $id_val;
$sites = $this->getModel()->getPatternMatchSites($ids, $pattern, $limit);
$db = Db::get();
$bind = array('%' . $pattern . '%', 'http%' . $pattern . '%', '%' . $pattern . '%');
// Also match the idsite
$where = '';
if (is_numeric($pattern)) {
$bind[] = $pattern;
$where = 'OR s.idsite = ?';
}
$sites = $db->fetchAll("SELECT idsite, name, main_url, `group`
FROM " . Common::prefixTable('site') . " s
WHERE ( s.name like ?
OR s.main_url like ?
OR s.`group` like ?
$where )
AND idsite in ($ids_str)
LIMIT " . SettingsPiwik::getWebsitesCountToDisplay(),
$bind);
return $sites;
}
/**
* Returns the number of websites to display per page.
*
* For example this is used in the All Websites Dashboard, in the Website Selector etc. If multiple websites are
* shown somewhere, one should request this method to detect how many websites should be shown per page when
* using paging. To use paging is always recommended since some installations have thousands of websites.
*
* @return int
*/
public function getNumWebsitesToDisplayPerPage()
{
Piwik::checkUserHasSomeViewAccess();
return SettingsPiwik::getWebsitesCountToDisplay();
}
/**
* Utility function that throws if a value is not valid for the 'keep_url_fragment'
* column of the piwik_site table.