Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'core/Piwik.php')
-rw-r--r--core/Piwik.php2018
1 files changed, 953 insertions, 1065 deletions
diff --git a/core/Piwik.php b/core/Piwik.php
index af7c5f083c..67fd9a24c4 100644
--- a/core/Piwik.php
+++ b/core/Piwik.php
@@ -10,69 +10,279 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see core/Translate.php
*/
require_once PIWIK_INCLUDE_PATH . '/core/Translate.php';
/**
+ * @see mysqli_set_charset
+ * @see parse_ini_file
+ */
+require_once PIWIK_INCLUDE_PATH . '/libs/upgradephp/common.php';
+
+/**
* Main piwik helper class.
* Contains static functions you can call from the plugins.
- *
+ *
* @package Piwik
*/
class Piwik
{
const CLASSES_PREFIX = "Piwik_";
-
+
public static $idPeriods = array(
'day' => 1,
'week' => 2,
'month' => 3,
'year' => 4,
);
-
+
+/*
+ * Prefix/unprefix class name
+ */
+
+ /**
+ * Prefix class name (if needed)
+ *
+ * @param string $class
+ * @return string
+ */
+ static public function prefixClass( $class )
+ {
+ if(substr_count($class, Piwik::CLASSES_PREFIX) > 0)
+ {
+ return $class;
+ }
+ return Piwik::CLASSES_PREFIX.$class;
+ }
+
+ /**
+ * Unprefix class name (if needed)
+ *
+ * @param string $class
+ * @return string
+ */
+ static public function unprefixClass( $class )
+ {
+ $lenPrefix = strlen(Piwik::CLASSES_PREFIX);
+ if(substr($class, 0, $lenPrefix) == Piwik::CLASSES_PREFIX)
+ {
+ return substr($class, $lenPrefix);
+ }
+ return $class;
+ }
+
+/*
+ * Installation / Uninstallation
+ */
+
+ /**
+ * Installation helper
+ */
+ static public function install()
+ {
+ Piwik_Common::mkdir(Zend_Registry::get('config')->smarty->compile_dir);
+ }
+
+ /**
+ * Uninstallation helper
+ */
+ static public function uninstall()
+ {
+ Piwik_Db_Schema::getInstance()->dropTables();
+ }
+
+ /**
+ * Returns true if Piwik is installed
+ *
+ * @since 0.6.3
+ *
+ * @return bool True if installed; false otherwise
+ */
+ static public function isInstalled()
+ {
+ return Piwik_Db_Schema::getInstance()->hasTables();
+ }
+
+/*
+ * File and directory operations
+ */
+
+ /**
+ * Copy recursively from $source to $target.
+ *
+ * @param string $source eg. './tmp/latest'
+ * @param string $target eg. '.'
+ * @param bool $excludePhp
+ */
+ static public function copyRecursive($source, $target, $excludePhp=false )
+ {
+ if ( is_dir( $source ) )
+ {
+ @mkdir( $target );
+ $d = dir( $source );
+ while ( false !== ( $entry = $d->read() ) )
+ {
+ if ( $entry == '.' || $entry == '..' )
+ {
+ continue;
+ }
+
+ $sourcePath = $source . '/' . $entry;
+ if ( is_dir( $sourcePath ) )
+ {
+ self::copyRecursive( $sourcePath, $target . '/' . $entry, $excludePhp );
+ continue;
+ }
+ $destPath = $target . '/' . $entry;
+ self::copy($sourcePath, $destPath, $excludePhp);
+ }
+ $d->close();
+ }
+ else
+ {
+ self::copy($source, $target, $excludePhp);
+ }
+ }
+
+ /**
+ * Copy individual file from $source to $target.
+ *
+ * @param string $source eg. './tmp/latest/index.php'
+ * @param string $target eg. './index.php'
+ * @param bool $excludePhp
+ * @return bool
+ */
+ static public function copy($source, $dest, $excludePhp=false)
+ {
+ static $phpExtensions = array('php', 'tpl');
+
+ if($excludePhp)
+ {
+ $path_parts = pathinfo($source);
+ if(in_array($path_parts['extension'], $phpExtensions))
+ {
+ return true;
+ }
+ }
+
+ if(!@copy( $source, $dest ))
+ {
+ @chmod($dest, 0755);
+ if(!@copy( $source, $dest ))
+ {
+ throw new Exception("
+ Error while copying file to <code>$dest</code>. <br />
+ Please check that the web server has enough permission to overwrite this file. <br />
+ For example, on a linux server, if your apache user is www-data you can try to execute:<br />
+ <code>chown -R www-data:www-data ".Piwik_Common::getPathToPiwikRoot()."</code><br />
+ <code>chmod -R 0755 ".Piwik_Common::getPathToPiwikRoot()."</code><br />
+ ");
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Recursively delete a directory
+ *
+ * @param string $dir Directory name
+ * @param boolean $deleteRootToo Delete specified top-level directory as well
+ */
+ static public function unlinkRecursive($dir, $deleteRootToo)
+ {
+ if(!$dh = @opendir($dir))
+ {
+ return;
+ }
+ while (false !== ($obj = readdir($dh)))
+ {
+ if($obj == '.' || $obj == '..')
+ {
+ continue;
+ }
+
+ if (!@unlink($dir . '/' . $obj))
+ {
+ self::unlinkRecursive($dir.'/'.$obj, true);
+ }
+ }
+ closedir($dh);
+ if ($deleteRootToo)
+ {
+ @rmdir($dir);
+ }
+ return;
+ }
+
+ /**
+ * Recursively find pathnames that match a pattern
+ * @see glob()
+ *
+ * @param string $sDir directory
+ * @param string $sPattern pattern
+ * @param int $nFlags glob() flags
+ * @return array
+ */
+ public static function globr($sDir, $sPattern, $nFlags = NULL)
+ {
+ if(($aFiles = glob("$sDir/$sPattern", $nFlags)) == false)
+ {
+ $aFiles = array();
+ }
+ if(($aDirs = glob("$sDir/*", GLOB_ONLYDIR)) != false)
+ {
+ foreach ($aDirs as $sSubDir)
+ {
+ $aSubFiles = self::globr($sSubDir, $sPattern, $nFlags);
+ $aFiles = array_merge($aFiles, $aSubFiles);
+ }
+ }
+ return $aFiles;
+ }
+
/**
* Checks that the directories Piwik needs write access are actually writable
* Displays a nice error page if permissions are missing on some directories
+ *
+ * @param array $directoriesToCheck Array of directory names to check
*/
static public function checkDirectoriesWritableOrDie( $directoriesToCheck = null )
{
$resultCheck = Piwik::checkDirectoriesWritable( $directoriesToCheck );
- if( array_search(false, $resultCheck) !== false )
- {
- $directoryList = '';
- foreach($resultCheck as $dir => $bool)
+ if( array_search(false, $resultCheck) === false )
+ {
+ return;
+ }
+ $directoryList = '';
+ foreach($resultCheck as $dir => $bool)
+ {
+ $realpath = Piwik_Common::realpath($dir);
+ if(!empty($realpath) && $bool === false)
{
- $realpath = Piwik_Common::realpath($dir);
- if(!empty($realpath) && $bool === false)
- {
- $directoryList .= "<code>chmod 777 $realpath</code><br>";
- }
+ $directoryList .= "<code>chmod 777 $realpath</code><br />";
}
- $directoryList .= '';
- $directoryMessage = "<p><b>Piwik couldn't write to some directories</b>.</p> <p>Try to Execute the following commands on your Linux server:</P>";
- $directoryMessage .= $directoryList;
- $directoryMessage .= "<p>If this doesn't work, you can try to create the directories with your FTP software, and set the CHMOD to 777 (with your FTP software, right click on the directories, permissions).";
- $directoryMessage .= "<p>After applying the modifications, you can <a href='index.php'>refresh the page</a>.";
- $directoryMessage .= "<p>If you need more help, try <a href='misc/redirectToUrl.php?url=http://piwik.org'>Piwik.org</a>.";
-
- Piwik_ExitWithMessage($directoryMessage, false, true);
}
+ $directoryList .= '';
+ $directoryMessage = "<p><b>Piwik couldn't write to some directories</b>.</p> <p>Try to Execute the following commands on your Linux server:</P>";
+ $directoryMessage .= $directoryList;
+ $directoryMessage .= "<p>If this doesn't work, you can try to create the directories with your FTP software, and set the CHMOD to 777 (with your FTP software, right click on the directories, permissions).";
+ $directoryMessage .= "<p>After applying the modifications, you can <a href='index.php'>refresh the page</a>.";
+ $directoryMessage .= "<p>If you need more help, try <a href='misc/redirectToUrl.php?url=http://piwik.org'>Piwik.org</a>.";
+
+ Piwik_ExitWithMessage($directoryMessage, false, true);
}
-
+
/**
* Checks if directories are writable and create them if they do not exist.
- *
+ *
* @param array $directoriesToCheck array of directories to check - if not given default Piwik directories that needs write permission are checked
* @return array direcory name => true|false (is writable)
*/
static public function checkDirectoriesWritable($directoriesToCheck = null)
{
- if( $directoriesToCheck == null )
+ if( $directoriesToCheck == null )
{
$directoriesToCheck = array(
'/config',
@@ -80,9 +290,9 @@ class Piwik
'/tmp/templates_c',
'/tmp/cache',
'/tmp/latest',
- );
+ );
}
-
+
$resultCheck = array();
foreach($directoriesToCheck as $directoryToCheck)
{
@@ -90,12 +300,12 @@ class Piwik
{
$directoryToCheck = PIWIK_USER_PATH . $directoryToCheck;
}
-
+
if(!file_exists($directoryToCheck))
{
Piwik_Common::mkdir($directoryToCheck, 0755, false);
}
-
+
$directory = Piwik_Common::realpath($directoryToCheck);
$resultCheck[$directory] = false;
if($directory !== false // realpath() returns FALSE on failure
@@ -106,29 +316,168 @@ class Piwik
}
return $resultCheck;
}
-
+
/**
- * Returns the Javascript code to be inserted on every page to track
+ * Generate .htaccess files at runtime to avoid permission problems.
+ */
+ static public function createHtAccessFiles()
+ {
+ // deny access to these folders
+ $directoriesToProtect = array(
+ '/config',
+ '/core',
+ '/lang',
+ );
+ foreach($directoriesToProtect as $directoryToProtect)
+ {
+ Piwik_Common::createHtAccess(PIWIK_INCLUDE_PATH . $directoryToProtect);
+ }
+
+ // more selective allow/deny filters
+ $allowAny = "<Files \"*\">\nAllow from all\nSatisfy any\n</Files>\n";
+ $allowStaticAssets = "<Files ~ \"\\.(test\.php|gif|ico|jpg|png|js|css|swf)$\">\nSatisfy any\nAllow from all\n</Files>\n";
+ $denyDirectPhp = "<Files ~ \"\\.(php|php4|php5|inc|tpl)$\">\nDeny from all\n</Files>\n";
+ $directoriesToProtect = array(
+ '/js' => $allowAny,
+ '/libs' => $denyDirectPhp . $allowStaticAssets,
+ '/plugins' => $denyDirectPhp . $allowStaticAssets,
+ '/themes' => $denyDirectPhp . $allowStaticAssets,
+ );
+ foreach($directoriesToProtect as $directoryToProtect => $content)
+ {
+ Piwik_Common::createHtAccess(PIWIK_INCLUDE_PATH . $directoryToProtect, $content);
+ }
+ }
+
+ /**
+ * Generate web.config files at runtime
*
- * @param int $idSite
- * @param string $piwikUrl http://path/to/piwik/directory/
- * @param string $actionName
- * @return string
+ * Note: for IIS 7 and above
*/
- static public function getJavascriptCode($idSite, $piwikUrl, $actionName = "''")
- {
- $jsTag = file_get_contents( PIWIK_INCLUDE_PATH . "/core/Tracker/javascriptTag.tpl");
- $jsTag = nl2br(htmlentities($jsTag));
- $piwikUrl = preg_match('~^(http|https)://(.*)$~', $piwikUrl, $matches);
- $piwikUrl = $matches[2];
- $jsTag = str_replace('{$actionName}', $actionName, $jsTag);
- $jsTag = str_replace('{$idSite}', $idSite, $jsTag);
- $jsTag = str_replace('{$piwikUrl}', $piwikUrl, $jsTag);
- $jsTag = str_replace('{$hrefTitle}', Piwik::getRandomTitle(), $jsTag);
- return $jsTag;
+ static public function createWebConfigFiles()
+ {
+ @file_put_contents(PIWIK_INCLUDE_PATH . '/web.config',
+'<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <system.webServer>
+ <security>
+ <requestFiltering>
+ <hiddenSegments>
+ <add segment="config" />
+ <add segment="core" />
+ <add segment="lang" />
+ </hiddenSegments>
+ <fileExtensions>
+ <add fileExtension=".tpl" allowed="false" />
+ </fileExtensions>
+ </requestFiltering>
+ </security>
+ <directoryBrowse enabled="false" />
+ <defaultDocument>
+ <files>
+ <remove value="index.php" />
+ <add value="index.php" />
+ </files>
+ </defaultDocument>
+ </system.webServer>
+</configuration>');
+
+ // deny direct access to .php files
+ $directoriesToProtect = array(
+ '/libs',
+ '/plugins',
+ );
+ foreach($directoriesToProtect as $directoryToProtect)
+ {
+ @file_put_contents(PIWIK_INCLUDE_PATH . $directoryToProtect . '/web.config',
+'<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <system.webServer>
+ <security>
+ <requestFiltering>
+ <denyUrlSequences>
+ <add sequence=".php" />
+ </denyUrlSequences>
+ </requestFiltering>
+ </security>
+ </system.webServer>
+</configuration>');
+ }
}
/**
+ * Get file integrity information (in PIWIK_INCLUDE_PATH).
+ *
+ * @return array(bool, string, ...) Return code (true/false), followed by zero or more error messages
+ */
+ static public function getFileIntegrityInformation()
+ {
+ $exclude = array(
+ 'robots.txt',
+ );
+ $messages = array();
+ $messages[] = true;
+
+ // ignore dev environments
+ if(file_exists(PIWIK_INCLUDE_PATH . '/.svn'))
+ {
+ $messages[] = Piwik_Translate('General_WarningFileIntegritySkipped');
+ return $messages;
+ }
+
+ $manifest = PIWIK_INCLUDE_PATH . '/config/manifest.inc.php';
+ if(!file_exists($manifest))
+ {
+ $messages[] = Piwik_Translate('General_WarningFileIntegrityNoManifest');
+ return $messages;
+ }
+
+ require_once $manifest;
+
+ $files = Manifest::$files;
+
+ $hasMd5file = function_exists('md5_file');
+ foreach($files as $path => $props)
+ {
+ if(in_array($path, $exclude))
+ {
+ continue;
+ }
+
+ $file = PIWIK_INCLUDE_PATH . '/' . $path;
+
+ if(!file_exists($file))
+ {
+ $messages[] = Piwik_Translate('General_ExceptionMissingFile', $file);
+ }
+ else if(filesize($file) != $props[0])
+ {
+ $messages[] = Piwik_Translate('General_ExceptionFilesizeMismatch', array($file, $props[0], filesize($file)));
+ }
+ else if($hasMd5file && (@md5_file($file) !== $props[1]))
+ {
+ $messages[] = Piwik_Translate('General_ExceptionFileIntegrity', $file);
+ }
+ }
+
+ if(count($messages) > 1)
+ {
+ $messages[0] = false;
+ }
+
+ if(!$hasMd5file)
+ {
+ $messages[] = Piwik_Translate('General_WarningFileIntegrityNoMd5file');
+ }
+
+ return $messages;
+ }
+
+/*
+ * PHP environment settings
+ */
+
+ /**
* Set maximum script execution time.
*
* @param int max execution time in seconds (0 = no limit)
@@ -140,15 +489,46 @@ class Piwik
@set_time_limit($executionTime);
}
+ /**
+ * Get php memory_limit
+ *
+ * Prior to PHP 5.2.1, or on Windows, --enable-memory-limit is not a
+ * compile-time default, so ini_get('memory_limit') may return false.
+ *
+ * @see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
+ * @return int memory limit in megabytes
+ */
static public function getMemoryLimitValue()
{
if($memory = ini_get('memory_limit'))
{
- return substr($memory, 0, strlen($memory) - 1);
+ // handle shorthand byte options (case-insensitive)
+ $shorthandByteOption = substr($memory, -1);
+ switch($shorthandByteOption)
+ {
+ case 'G':
+ case 'g':
+ return substr($memory, 0, -1) * 1024;
+ case 'M':
+ case 'm':
+ return substr($memory, 0, -1);
+ case 'K':
+ case 'k':
+ return substr($memory, 0, -1) / 1024;
+ }
+ return $memory / 1048576;
}
return false;
}
-
+
+ /**
+ * Set PHP memory limit
+ *
+ * Note: system settings may prevent scripts from overriding the master value
+ *
+ * @param int $minimumMemoryLimit
+ * @return bool true if set; false otherwise
+ */
static public function setMemoryLimit($minimumMemoryLimit)
{
$currentValue = self::getMemoryLimitValue();
@@ -160,7 +540,12 @@ class Piwik
}
return false;
}
-
+
+ /**
+ * Raise PHP memory limit if below the minimum required
+ *
+ * @return bool true if set; false otherwise
+ */
static public function raiseMemoryLimitIfNecessary()
{
$minimumMemoryLimit = Zend_Registry::get('config')->General->minimum_memory_limit;
@@ -170,22 +555,25 @@ class Piwik
{
return self::setMemoryLimit($minimumMemoryLimit);
}
-
+
return false;
}
-
+
+/*
+ * Logging and error handling
+ */
+
static public function log($message = '')
{
Zend_Registry::get('logger_message')->logEvent($message);
- Zend_Registry::get('logger_message')->logEvent( "<br>" . PHP_EOL);
+ Zend_Registry::get('logger_message')->logEvent( "<br />" . PHP_EOL);
}
-
-
+
static public function error($message = '')
{
trigger_error($message, E_USER_ERROR);
}
-
+
/**
* Display the message in a nice red font with a nice icon
* ... and dies
@@ -194,46 +582,54 @@ class Piwik
{
$output = "<style>a{color:red;}</style>\n".
"<div style='color:red;font-family:Georgia;font-size:120%'>".
- "<p><img src='themes/default/images/error_medium.png' style='vertical-align:middle; float:left;padding:20 20 20 20'>".
+ "<p><img src='themes/default/images/error_medium.png' style='vertical-align:middle; float:left;padding:20 20 20 20' />".
$message.
"</p></div>";
print(Piwik_Log_Formatter_ScreenFormatter::getFormattedString($output));
exit;
}
-
+
+/*
+ * Profiling
+ */
+
/**
- * Computes the division of i1 by i2. If either i1 or i2 are not number, or if i2 has a value of zero
- * we return 0 to avoid the division by zero.
+ * Get total number of queries
*
- * @param numeric $i1
- * @param numeric $i2
- * @return numeric The result of the division or zero
+ * @return int number of queries
*/
- static public function secureDiv( $i1, $i2 )
- {
- if ( is_numeric($i1) && is_numeric($i2) && floatval($i2) != 0)
- {
- return $i1 / $i2;
- }
- return 0;
- }
static public function getQueryCount()
{
$profiler = Zend_Registry::get('db')->getProfiler();
return $profiler->getTotalNumQueries();
}
+
+ /**
+ * Get total elapsed time (in seconds)
+ *
+ * @return int elapsed time
+ */
static public function getDbElapsedSecs()
{
$profiler = Zend_Registry::get('db')->getProfiler();
return $profiler->getTotalElapsedSecs();
}
+
+ /**
+ * Print number of queries and elapsed time
+ */
static public function printQueryCount()
{
$totalTime = self::getDbElapsedSecs();
$queryCount = self::getQueryCount();
Piwik::log("Total queries = $queryCount (total sql time = ".round($totalTime,2)."s)");
}
-
+
+ /**
+ * Print profiling report for the tracker
+ *
+ * @param Piwik_Tracker_Db $db Tracker database object (or null)
+ */
static public function printSqlProfilingReportTracker( $db = null )
{
if(!function_exists('maxSumMsFirst'))
@@ -243,20 +639,20 @@ class Piwik
return $a['sum_time_ms'] < $b['sum_time_ms'];
}
}
-
+
if(is_null($db))
{
$db = Piwik_Tracker::getDatabase();
}
$tableName = Piwik_Common::prefixTable('log_profiling');
-
+
$all = $db->fetchAll('SELECT * FROM '.$tableName );
- if($all === false)
+ if($all === false)
{
return;
}
uasort($all, 'maxSumMsFirst');
-
+
$infoIndexedByQuery = array();
foreach($all as $infoQuery)
{
@@ -264,24 +660,23 @@ class Piwik
$count = $infoQuery['count'];
$sum_time_ms = $infoQuery['sum_time_ms'];
$infoIndexedByQuery[$query] = array('count' => $count, 'sumTimeMs' => $sum_time_ms);
- }
+ }
Piwik::getSqlProfilingQueryBreakdownOutput($infoIndexedByQuery);
}
/**
- * Outputs SQL Profiling reports
+ * Outputs SQL Profiling reports
* It is automatically called when enabling the SQL profiling in the config file enable_sql_profiler
- *
*/
static function printSqlProfilingReportZend()
{
$profiler = Zend_Registry::get('db')->getProfiler();
-
+
if(!$profiler->getEnabled())
{
throw new Exception("To display the profiler you should enable enable_sql_profiler on your config/config.ini.php file");
}
-
+
$infoIndexedByQuery = array();
foreach($profiler->getQueryProfiles() as $query)
{
@@ -306,9 +701,9 @@ class Piwik
}
}
uasort( $infoIndexedByQuery, 'sortTimeDesc');
-
- Piwik::log('<hr><b>SQL Profiler</b>');
- Piwik::log('<hr><b>Summary</b>');
+
+ Piwik::log('<hr /><b>SQL Profiler</b>');
+ Piwik::log('<hr /><b>Summary</b>');
$totalTime = $profiler->getTotalElapsedSecs();
$queryCount = $profiler->getTotalNumQueries();
$longestTime = 0;
@@ -321,44 +716,63 @@ class Piwik
}
$str = 'Executed ' . $queryCount . ' queries in ' . round($totalTime,3) . ' seconds' . "\n";
$str .= '(Average query length: ' . round($totalTime / $queryCount,3) . ' seconds)' . "\n";
- $str .= '<br>Queries per second: ' . round($queryCount / $totalTime,1) . "\n";
- $str .= '<br>Longest query length: ' . round($longestTime,3) . " seconds (<code>$longestQuery</code>) \n";
+ $str .= '<br />Queries per second: ' . round($queryCount / $totalTime,1) . "\n";
+ $str .= '<br />Longest query length: ' . round($longestTime,3) . " seconds (<code>$longestQuery</code>) \n";
Piwik::log($str);
Piwik::getSqlProfilingQueryBreakdownOutput($infoIndexedByQuery);
}
-
+
+ /**
+ * Log a breakdown by query
+ *
+ * @param array $infoIndexedByQuery
+ */
static private function getSqlProfilingQueryBreakdownOutput( $infoIndexedByQuery )
{
- Piwik::log('<hr><b>Breakdown by query</b>');
+ Piwik::log('<hr /><b>Breakdown by query</b>');
$output = '';
- foreach($infoIndexedByQuery as $query => $queryInfo)
+ foreach($infoIndexedByQuery as $query => $queryInfo)
{
$timeMs = round($queryInfo['sumTimeMs'],1);
$count = $queryInfo['count'];
$avgTimeString = '';
- if($count > 1)
+ if($count > 1)
{
$avgTimeMs = $timeMs / $count;
- $avgTimeString = " (average = <b>". round($avgTimeMs,1) . "ms</b>)";
+ $avgTimeString = " (average = <b>". round($avgTimeMs,1) . "ms</b>)";
}
$query = preg_replace('/([\t\n\r ]+)/', ' ', $query);
$output .= "Executed <b>$count</b> time". ($count==1?'':'s') ." in <b>".$timeMs."ms</b> $avgTimeString <pre>\t$query</pre>";
}
Piwik::log($output);
}
-
+
+ /**
+ * Print timer
+ */
static public function printTimer()
{
echo Zend_Registry::get('timer');
}
- static public function printMemoryLeak($prefix = '', $suffix = '<br>')
+ /**
+ * Print memory leak
+ *
+ * @param string $prefix
+ * @param string $suffix
+ */
+ static public function printMemoryLeak($prefix = '', $suffix = '<br />')
{
echo $prefix;
echo Zend_Registry::get('timer')->getMemoryLeak();
echo $suffix;
}
-
+
+ /**
+ * Print memory usage
+ *
+ * @param string $prefixString
+ */
static public function printMemoryUsage( $prefixString = null )
{
$memory = false;
@@ -370,7 +784,7 @@ class Piwik
{
$memory = memory_get_usage();
}
-
+
if($memory !== false)
{
$usage = round( $memory / 1024 / 1024, 2);
@@ -385,385 +799,220 @@ class Piwik
Piwik::log("Memory usage function not found.");
}
}
-
- static public function getPrettySizeFromBytes($size)
+
+/*
+ * Amounts, Percentages, Currency, Time, Math Operations, and Pretty Printing
+ */
+
+ /**
+ * Computes the division of i1 by i2. If either i1 or i2 are not number, or if i2 has a value of zero
+ * we return 0 to avoid the division by zero.
+ *
+ * @param numeric $i1
+ * @param numeric $i2
+ * @return numeric The result of the division or zero
+ */
+ static public function secureDiv( $i1, $i2 )
{
- $bytes = array('','K','M','G','T');
- foreach($bytes as $val)
+ if ( is_numeric($i1) && is_numeric($i2) && floatval($i2) != 0)
{
- if($size > 1024)
- {
- $size = $size / 1024;
- }
- else
- {
- break;
- }
+ return $i1 / $i2;
}
- return round($size, 1)." ".$val;
+ return 0;
}
/**
- * Returns true if PHP was invoked as CGI or command-line interface (shell)
+ * Safely compute a percentage. Return 0 to avoid division by zero.
*
- * @deprecated deprecated in 0.4.4
- * @see Piwik_Common::isPhpCliMode()
- * @return bool true if PHP invoked as a CGI or from CLI
+ * @param numeric $dividend
+ * @param numeric $divisor
+ * @param int $precision
+ * @return numeric
*/
- static public function isPhpCliMode()
+ static public function getPercentageSafe($dividend, $divisor, $precision = 0)
{
- return Piwik_Common::isPhpCliMode();
+ if($divisor == 0)
+ {
+ return 0;
+ }
+ return round(100 * $dividend / $divisor, $precision);
}
-
- static public function getCurrency()
+
+ /**
+ * Get currency symbol for a site
+ *
+ * @param int $idSite
+ * @return string
+ */
+ static public function getCurrency($idSite)
{
- static $symbol = null;
- if(is_null($symbol))
+ static $symbols = null;
+ if(is_null($symbols))
{
- $symbol = trim(Zend_Registry::get('config')->General->default_currency);
+ $symbols = Piwik_SitesManager_API::getInstance()->getCurrencySymbols();
}
- return $symbol;
+ $site = new Piwik_Site($idSite);
+ return $symbols[$site->getCurrency()];
}
- static public function getPrettyMoney($value)
+ /**
+ * Pretty format monetary value for a site
+ *
+ * @param numeric $value
+ * @param int $idSite
+ * @return string
+ */
+ static public function getPrettyMoney($value, $idSite)
{
- $symbol = self::getCurrency();
- return sprintf("$symbol%.2f", $value);
+ $currencyBefore = self::getCurrency($idSite);
+ $currencyAfter = '';
+
+ // manually put the currency symbol after the amount for euro
+ // (maybe more currencies prefer this notation?)
+ if(in_array($currencyBefore,array('€')))
+ {
+ $currencyAfter = '&nbsp;'.$currencyBefore;
+ $currencyBefore = '';
+ }
+ return sprintf("$currencyBefore&nbsp;%s$currencyAfter", $value);
}
-
- static public function getPercentageSafe($dividend, $divisor, $precision = 0)
+
+ /**
+ * Pretty format a memory size value
+ *
+ * @param numeric $size in bytes
+ * @return string
+ */
+ static public function getPrettySizeFromBytes($size)
{
- if($divisor == 0)
+ $bytes = array('','K','M','G','T');
+ foreach($bytes as $val)
{
- return 0;
+ if($size > 1024)
+ {
+ $size = $size / 1024;
+ }
+ else
+ {
+ break;
+ }
}
- return round(100 * $dividend / $divisor, $precision);
+ return round($size, 1)." ".$val;
}
-
+
+ /**
+ * Pretty format a time
+ *
+ * @param numeric $numberOfSeconds
+ * @return string
+ */
static public function getPrettyTimeFromSeconds($numberOfSeconds)
{
$numberOfSeconds = (double)$numberOfSeconds;
$days = floor($numberOfSeconds / 86400);
-
+
$minusDays = $numberOfSeconds - $days * 86400;
$hours = floor($minusDays / 3600);
-
+
$minusDaysAndHours = $minusDays - $hours * 3600;
$minutes = floor($minusDaysAndHours / 60 );
-
+
$seconds = $minusDaysAndHours - $minutes * 60;
-
+
if($days > 0)
{
- return sprintf("%d days %d hours", $days, $hours);
+ $return = sprintf(Piwik_Translate('General_DaysHours'), $days, $hours);
}
elseif($hours > 0)
{
- return sprintf("%d hours %d min", $hours, $minutes);
+ $return = sprintf(Piwik_Translate('General_HoursMinutes'), $hours, $minutes);
}
elseif($minutes > 0)
{
- return sprintf("%d&nbsp;min&nbsp;%ds", $minutes, $seconds);
+ $return = sprintf(Piwik_Translate('General_MinutesSeconds'), $minutes, $seconds);
}
else
{
- return sprintf("%ds", $seconds);
+ $return = sprintf(Piwik_Translate('General_Seconds'), $seconds);
}
+ return str_replace(' ', '&nbsp;', $return);
}
-
- static public function getRandomTitle()
- {
- $titles = array( 'Web analytics',
- 'Analytics',
- 'Web analytics api',
- 'Open source analytics',
- 'Open source web analytics',
- 'Google Analytics alternative',
- 'open source Google Analytics',
- 'Free analytics',
- 'Analytics software',
- 'Free web analytics',
- 'Free web statistics',
- 'Web 2.0 analytics',
- 'Statistics web 2.0',
- );
- $id = abs(intval(md5(substr(Piwik_Url::getCurrentHost(),7))));
- $title = $titles[ $id % count($titles)];
- return $title;
- }
-
- static public function getTableCreateSql( $tableName )
+
+ /**
+ * Returns the Javascript code to be inserted on every page to track
+ *
+ * @param int $idSite
+ * @param string $piwikUrl http://path/to/piwik/directory/
+ * @param string $actionName
+ * @return string
+ */
+ static public function getJavascriptCode($idSite, $piwikUrl, $actionName = "''")
{
- $tables = Piwik::getTablesCreateSql();
-
- if(!isset($tables[$tableName]))
- {
- throw new Exception("The table '$tableName' SQL creation code couldn't be found.");
- }
-
- return $tables[$tableName];
+ $jsTag = file_get_contents( PIWIK_INCLUDE_PATH . "/core/Tracker/javascriptTag.tpl");
+ $jsTag = nl2br(htmlentities($jsTag));
+ $piwikUrl = preg_match('~^(http|https)://(.*)$~', $piwikUrl, $matches);
+ $piwikUrl = $matches[2];
+ $jsTag = str_replace('{$actionName}', $actionName, $jsTag);
+ $jsTag = str_replace('{$idSite}', $idSite, $jsTag);
+ $jsTag = str_replace('{$piwikUrl}', $piwikUrl, $jsTag);
+ $jsTag = str_replace('{$hrefTitle}', Piwik::getRandomTitle(), $jsTag);
+ return $jsTag;
}
-
- static public function getTablesCreateSql()
+
+ /**
+ * Generate a title for image tags
+ *
+ * @return string
+ */
+ static public function getRandomTitle()
{
- $config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
- $tables = array(
- 'user' => "CREATE TABLE {$prefixTables}user (
- login VARCHAR(100) NOT NULL,
- password CHAR(32) NOT NULL,
- alias VARCHAR(45) NOT NULL,
- email VARCHAR(100) NOT NULL,
- token_auth CHAR(32) NOT NULL,
- date_registered TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
- PRIMARY KEY(login),
- UNIQUE INDEX uniq_keytoken(token_auth)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'access' => "CREATE TABLE {$prefixTables}access (
- login VARCHAR(100) NOT NULL,
- idsite INTEGER UNSIGNED NOT NULL,
- access VARCHAR(10) NULL,
- PRIMARY KEY(login, idsite)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'site' => "CREATE TABLE {$prefixTables}site (
- idsite INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
- name VARCHAR(90) NOT NULL,
- main_url VARCHAR(255) NOT NULL,
- ts_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
- PRIMARY KEY(idsite)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'site_url' => "CREATE TABLE {$prefixTables}site_url (
- idsite INTEGER(10) UNSIGNED NOT NULL,
- url VARCHAR(255) NOT NULL,
- PRIMARY KEY(idsite, url)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'goal' => " CREATE TABLE `{$prefixTables}goal` (
- `idsite` int(11) NOT NULL,
- `idgoal` int(11) NOT NULL,
- `name` varchar(50) NOT NULL,
- `match_attribute` varchar(20) NOT NULL,
- `pattern` varchar(255) NOT NULL,
- `pattern_type` varchar(10) NOT NULL,
- `case_sensitive` tinyint(4) NOT NULL,
- `revenue` float NOT NULL,
- `deleted` tinyint(4) NOT NULL default '0',
- PRIMARY KEY (`idsite`,`idgoal`)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'logger_message' => "CREATE TABLE {$prefixTables}logger_message (
- idlogger_message INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- timestamp TIMESTAMP NULL,
- message TEXT NULL,
- PRIMARY KEY(idlogger_message)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'logger_api_call' => "CREATE TABLE {$prefixTables}logger_api_call (
- idlogger_api_call INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- class_name VARCHAR(255) NULL,
- method_name VARCHAR(255) NULL,
- parameter_names_default_values TEXT NULL,
- parameter_values TEXT NULL,
- execution_time FLOAT NULL,
- caller_ip BIGINT UNSIGNED NULL,
- timestamp TIMESTAMP NULL,
- returned_value TEXT NULL,
- PRIMARY KEY(idlogger_api_call)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'logger_error' => "CREATE TABLE {$prefixTables}logger_error (
- idlogger_error INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- timestamp TIMESTAMP NULL,
- message TEXT NULL,
- errno INTEGER UNSIGNED NULL,
- errline INTEGER UNSIGNED NULL,
- errfile VARCHAR(255) NULL,
- backtrace TEXT NULL,
- PRIMARY KEY(idlogger_error)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'logger_exception' => "CREATE TABLE {$prefixTables}logger_exception (
- idlogger_exception INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- timestamp TIMESTAMP NULL,
- message TEXT NULL,
- errno INTEGER UNSIGNED NULL,
- errline INTEGER UNSIGNED NULL,
- errfile VARCHAR(255) NULL,
- backtrace TEXT NULL,
- PRIMARY KEY(idlogger_exception)
- ) DEFAULT CHARSET=utf8
- ",
-
-
- 'log_action' => "CREATE TABLE {$prefixTables}log_action (
- idaction INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
- name VARCHAR(255) NOT NULL,
- hash INTEGER(10) UNSIGNED NOT NULL,
- type TINYINT UNSIGNED NULL,
- PRIMARY KEY(idaction),
- INDEX index_type_hash (type, hash)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'log_visit' => "CREATE TABLE {$prefixTables}log_visit (
- idvisit INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
- idsite INTEGER(10) UNSIGNED NOT NULL,
- visitor_localtime TIME NOT NULL,
- visitor_idcookie CHAR(32) NOT NULL,
- visitor_returning TINYINT(1) NOT NULL,
- visit_first_action_time DATETIME NOT NULL,
- visit_last_action_time DATETIME NOT NULL,
- visit_server_date DATE NOT NULL,
- visit_exit_idaction_url INTEGER(11) NOT NULL,
- visit_entry_idaction_url INTEGER(11) NOT NULL,
- visit_total_actions SMALLINT(5) UNSIGNED NOT NULL,
- visit_total_time SMALLINT(5) UNSIGNED NOT NULL,
- visit_goal_converted TINYINT(1) NOT NULL,
- referer_type INTEGER UNSIGNED NULL,
- referer_name VARCHAR(70) NULL,
- referer_url TEXT NOT NULL,
- referer_keyword VARCHAR(255) NULL,
- config_md5config CHAR(32) NOT NULL,
- config_os CHAR(3) NOT NULL,
- config_browser_name VARCHAR(10) NOT NULL,
- config_browser_version VARCHAR(20) NOT NULL,
- config_resolution VARCHAR(9) NOT NULL,
- config_pdf TINYINT(1) NOT NULL,
- config_flash TINYINT(1) NOT NULL,
- config_java TINYINT(1) NOT NULL,
- config_director TINYINT(1) NOT NULL,
- config_quicktime TINYINT(1) NOT NULL,
- config_realplayer TINYINT(1) NOT NULL,
- config_windowsmedia TINYINT(1) NOT NULL,
- config_gears TINYINT(1) NOT NULL,
- config_silverlight TINYINT(1) NOT NULL,
- config_cookie TINYINT(1) NOT NULL,
- location_ip BIGINT UNSIGNED NOT NULL,
- location_browser_lang VARCHAR(20) NOT NULL,
- location_country CHAR(3) NOT NULL,
- location_continent CHAR(3) NOT NULL,
- PRIMARY KEY(idvisit),
- INDEX index_idsite_date (idsite, visit_server_date)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'log_conversion' => "CREATE TABLE `{$prefixTables}log_conversion` (
- `idvisit` int(10) unsigned NOT NULL,
- `idsite` int(10) unsigned NOT NULL,
- `visitor_idcookie` char(32) NOT NULL,
- `server_time` datetime NOT NULL,
- `visit_server_date` date NOT NULL,
- `idaction_url` int(11) default NULL,
- `idlink_va` int(11) default NULL,
- `referer_idvisit` int(10) unsigned default NULL,
- `referer_visit_server_date` date default NULL,
- `referer_type` int(10) unsigned default NULL,
- `referer_name` varchar(70) default NULL,
- `referer_keyword` varchar(255) default NULL,
- `visitor_returning` tinyint(1) NOT NULL,
- `location_country` char(3) NOT NULL,
- `location_continent` char(3) NOT NULL,
- `url` text NOT NULL,
- `idgoal` int(10) unsigned NOT NULL,
- `revenue` float default NULL,
- PRIMARY KEY (`idvisit`,`idgoal`),
- KEY `index_idsite_date` (`idsite`,`visit_server_date`)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'log_link_visit_action' => "CREATE TABLE {$prefixTables}log_link_visit_action (
- idlink_va INTEGER(11) NOT NULL AUTO_INCREMENT,
- idvisit INTEGER(10) UNSIGNED NOT NULL,
- idaction_url INTEGER(10) UNSIGNED NOT NULL,
- idaction_url_ref INTEGER(10) UNSIGNED NOT NULL,
- idaction_name INTEGER(10) UNSIGNED,
- time_spent_ref_action INTEGER(10) UNSIGNED NOT NULL,
- PRIMARY KEY(idlink_va),
- INDEX index_idvisit(idvisit)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'log_profiling' => "CREATE TABLE {$prefixTables}log_profiling (
- query TEXT NOT NULL,
- count INTEGER UNSIGNED NULL,
- sum_time_ms FLOAT NULL,
- UNIQUE INDEX query(query(100))
- ) DEFAULT CHARSET=utf8
- ",
-
- 'option' => "CREATE TABLE `{$prefixTables}option` (
- option_name VARCHAR( 64 ) NOT NULL ,
- option_value LONGTEXT NOT NULL ,
- autoload TINYINT NOT NULL DEFAULT '1',
- PRIMARY KEY ( option_name )
- ) DEFAULT CHARSET=utf8
- ",
-
- 'archive_numeric' => "CREATE TABLE {$prefixTables}archive_numeric (
- idarchive INTEGER UNSIGNED NOT NULL,
- name VARCHAR(255) NOT NULL,
- idsite INTEGER UNSIGNED NULL,
- date1 DATE NULL,
- date2 DATE NULL,
- period TINYINT UNSIGNED NULL,
- ts_archived DATETIME NULL,
- value FLOAT NULL,
- PRIMARY KEY(idarchive, name),
- KEY `index_all` (`idsite`,`date1`,`date2`,`name`,`ts_archived`)
- ) DEFAULT CHARSET=utf8
- ",
- 'archive_blob' => "CREATE TABLE {$prefixTables}archive_blob (
- idarchive INTEGER UNSIGNED NOT NULL,
- name VARCHAR(255) NOT NULL,
- idsite INTEGER UNSIGNED NULL,
- date1 DATE NULL,
- date2 DATE NULL,
- period TINYINT UNSIGNED NULL,
- ts_archived DATETIME NULL,
- value MEDIUMBLOB NULL,
- PRIMARY KEY(idarchive, name),
- KEY `index_all` (`idsite`,`date1`,`date2`,`name`,`ts_archived`)
- ) DEFAULT CHARSET=utf8
- ",
+ static $titles = array(
+ 'Web analytics',
+ 'Analytics',
+ 'Real time web analytics',
+ 'Real time analytics',
+ 'Open source analytics',
+ 'Open source web analytics',
+ 'Google Analytics alternative',
+ 'Open source Google Analytics',
+ 'Free analytics',
+ 'Analytics software',
+ 'Free web analytics',
+ 'Free web statistics',
);
- return $tables;
+ $id = abs(intval(md5(Piwik_Url::getCurrentHost())));
+ $title = $titles[ $id % count($titles)];
+ return $title;
}
-
+
+/*
+ * Access
+ */
+
+ /**
+ * Get current user login
+ *
+ * @return string
+ */
static public function getCurrentUserLogin()
{
return Zend_Registry::get('access')->getLogin();
}
-
- static public function getCurrentUserTokenAuth()
- {
- return Zend_Registry::get('access')->getTokenAuth();
- }
-
+
/**
- * Returns the plugin currently being used to display the page
+ * Get current user's token auth
*
- * @return Piwik_Plugin
+ * @return string
*/
- static public function getCurrentPlugin()
+ static public function getCurrentUserTokenAuth()
{
- return Piwik_PluginsManager::getInstance()->getLoadedPlugin(Piwik::getModule());
+ return Zend_Registry::get('access')->getTokenAuth();
}
-
+
/**
* Returns true if the current user is either the super user, or the user $theUser
* Used when modifying user preference: this usually requires super user or being the user itself.
- *
+ *
* @param string $theUser
* @return bool
*/
@@ -776,8 +1025,10 @@ class Piwik
return false;
}
}
-
+
/**
+ * Check that current user is either the specified user or the superuser
+ *
* @param string $theUser
* @throws exception if the user is neither the super user nor the user $theUser
*/
@@ -793,9 +1044,10 @@ class Piwik
throw new Piwik_Access_NoAccessException("The user has to be either the Super User or the user '$theUser' itself.");
}
}
-
+
/**
* Returns true if the current user is the Super User
+ *
* @return bool
*/
static public function isUserIsSuperUser()
@@ -807,21 +1059,32 @@ class Piwik
return false;
}
}
-
+
/**
* Helper method user to set the current as Super User.
* This should be used with great care as this gives the user all permissions.
*/
- static public function setUserIsSuperUser()
+ static public function setUserIsSuperUser( $bool = true )
{
- Zend_Registry::get('access')->setSuperUser();
+ Zend_Registry::get('access')->setSuperUser($bool);
}
-
+
+ /**
+ * Check that user is the superuser
+ *
+ * @throws Exception if not the superuser
+ */
static public function checkUserIsSuperUser()
{
Zend_Registry::get('access')->checkUserIsSuperUser();
}
-
+
+ /**
+ * Returns true if the user has admin access to the sites
+ *
+ * @param mixed $idSites
+ * @return bool
+ */
static public function isUserHasAdminAccess( $idSites )
{
try{
@@ -831,12 +1094,23 @@ class Piwik
return false;
}
}
-
+
+ /**
+ * Check user has admin access to the sites
+ *
+ * @param mixed $idSites
+ * @throws Exception if user doesn't have admin access to the sites
+ */
static public function checkUserHasAdminAccess( $idSites )
{
Zend_Registry::get('access')->checkUserHasAdminAccess( $idSites );
}
-
+
+ /**
+ * Returns true if the user has admin access to any sites
+ *
+ * @return bool
+ */
static public function isUserHasSomeAdminAccess()
{
try{
@@ -846,17 +1120,23 @@ class Piwik
return false;
}
}
-
+
+ /**
+ * Check user has admin access to any sites
+ *
+ * @throws Exception if user doesn't have admin access to any sites
+ */
static public function checkUserHasSomeAdminAccess()
{
Zend_Registry::get('access')->checkUserHasSomeAdminAccess();
}
-
- static public function checkUserHasSomeViewAccess()
- {
- Zend_Registry::get('access')->checkUserHasSomeViewAccess();
- }
-
+
+ /**
+ * Returns true if the user has view access to the sites
+ *
+ * @param mixed $idSites
+ * @return bool
+ */
static public function isUserHasViewAccess( $idSites )
{
try{
@@ -866,635 +1146,139 @@ class Piwik
return false;
}
}
-
- static public function checkUserHasViewAccess( $idSites )
- {
- Zend_Registry::get('access')->checkUserHasViewAccess( $idSites );
- }
-
- static public function prefixClass( $class )
- {
- if(substr_count($class, Piwik::CLASSES_PREFIX) > 0)
- {
- return $class;
- }
- return Piwik::CLASSES_PREFIX.$class;
- }
- static public function unprefixClass( $class )
- {
- $lenPrefix = strlen(Piwik::CLASSES_PREFIX);
- if(substr($class, 0, $lenPrefix) == Piwik::CLASSES_PREFIX)
- {
- return substr($class, $lenPrefix);
- }
- return $class;
- }
/**
- * Returns the current module read from the URL (eg. 'API', 'UserSettings', etc.)
- *
- * @return string
- */
- static public function getModule()
- {
- return Piwik_Common::getRequestVar('module', '', 'string');
- }
-
- /**
- * Returns the current action read from the URL
+ * Check user has view access to the sites
*
- * @return string
+ * @param mixed $idSites
+ * @throws Exception if user doesn't have view access to sites
*/
- static public function getAction()
- {
- return Piwik_Common::getRequestVar('action', '', 'string');
- }
-
- /**
- * returns false if the URL to redirect to is already this URL
- */
- static public function redirectToModule( $newModule, $newAction = '' )
+ static public function checkUserHasViewAccess( $idSites )
{
- $currentModule = self::getModule();
- $currentAction = self::getAction();
-
- if($currentModule != $newModule
- || $currentAction != $newAction )
- {
-
- $newUrl = 'index.php' . Piwik_Url::getCurrentQueryStringWithParametersModified(
- array('module' => $newModule, 'action' => $newAction)
- );
-
- Piwik_Url::redirectToUrl($newUrl);
- }
- return false;
+ Zend_Registry::get('access')->checkUserHasViewAccess( $idSites );
}
/**
- * Get "best" available transport method for sendHttpRequest() calls.
+ * Returns true if the user has view access to any sites
+ *
+ * @return bool
*/
- static public function getTransportMethod()
+ static public function isUserHasSomeViewAccess()
{
- $method = 'curl';
- if(!extension_loaded('curl'))
- {
- $method = 'stream';
- if(@ini_get('allow_url_fopen') != '1')
- {
- $method = 'socket';
- if(preg_match('/(^|,|\s)fsockopen($|,|\s)/', @ini_get('disable_functions')))
- {
- return null;
- }
- }
+ try{
+ self::checkUserHasSomeViewAccess();
+ return true;
+ } catch( Exception $e){
+ return false;
}
- return $method;
}
/**
- * Sends http request ensuring the request will fail before $timeout seconds
+ * Check user has view access to any sites
*
- * If no $destinationPath is specified, the trimmed response (without header) is returned as a string.
- * If a $destinationPath is specified, the response (without header) is saved to a file.
- *
- * @param string $aUrl
- * @param int $timeout
- * @param string $userAgent
- * @param string $destinationPath
- * @param int $followDepth
- * @return true (or string) on success; false on HTTP response error code (1xx or 4xx); throws exception on all other errors
+ * @throws Exception if user doesn't have view access to any sites
*/
- static public function sendHttpRequest($aUrl, $timeout, $userAgent = null, $destinationPath = null, $followDepth = 0)
+ static public function checkUserHasSomeViewAccess()
{
- // create output file
- $file = null;
- if($destinationPath)
- {
- if (($file = @fopen($destinationPath, 'wb')) === false || !is_resource($file))
- {
- throw new Exception('Error while creating the file: ' . $destinationPath);
- }
- }
-
- return self::sendHttpRequestBy(self::getTransportMethod(), $aUrl, $timeout, $userAgent, $destinationPath, $file, $followDepth);
+ Zend_Registry::get('access')->checkUserHasSomeViewAccess();
}
- static public function sendHttpRequestBy($method = 'socket', $aUrl, $timeout, $userAgent = null, $destinationPath = null, $file = null, $followDepth = 0)
- {
- if ($followDepth > 3)
- {
- throw new Exception('Too many redirects ('.$followDepth.')');
- }
-
- $contentLength = 0;
-
- if($method == 'socket')
- {
- // initialization
- $url = @parse_url($aUrl);
- if($url === false || !isset($url['scheme']))
- {
- throw new Exception('Malformed URL: '.$aUrl);
- }
-
- if($url['scheme'] != 'http')
- {
- throw new Exception('Invalid protocol/scheme: '.$url['scheme']);
- }
- $host = $url['host'];
- $port = isset($url['port)']) ? $url['port'] : 80;
- $path = isset($url['path']) ? $url['path'] : '/';
- if(isset($url['query']))
- {
- $path .= '?'.$url['query'];
- }
- $errno = null;
- $errstr = null;
-
- // connection attempt
- if (($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout)) === false || !is_resource($fsock))
- {
- if(is_resource($file)) { @fclose($file); }
- throw new Exception("Error while connecting to: $host. Please try again later. $errstr");
- }
-
- // send HTTP request header
- fwrite($fsock,
- "GET $path HTTP/1.0\r\n"
- ."Host: $host".($port != 80 ? ':'.$port : '')."\r\n"
- ."User-Agent: Piwik/".Piwik_Version::VERSION.($userAgent ? " $userAgent" : '')."\r\n"
- .'Referer: http://'.Piwik_Common::getIpString()."/\r\n"
- ."Connection: close\r\n"
- ."\r\n"
- );
-
- $streamMetaData = array('timed_out' => false);
- @stream_set_blocking($fsock, true);
- @stream_set_timeout($fsock, $timeout);
-
- // process header
- $status = null;
- $expectRedirect = false;
- $fileLength = 0;
-
- while (!feof($fsock))
- {
- $line = fgets($fsock, 4096);
-
- $streamMetaData = @stream_get_meta_data($fsock);
- if($streamMetaData['timed_out'])
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($fsock);
- throw new Exception('Timed out waiting for server response');
- }
-
- // a blank line marks the end of the server response header
- if(rtrim($line, "\r\n") == '')
- {
- break;
- }
-
- // parse first line of server response header
- if(!$status)
- {
- // expect first line to be HTTP response status line, e.g., HTTP/1.1 200 OK
- if(!preg_match('~^HTTP/(\d\.\d)\s+(\d+)(\s*.*)?~', $line, $m))
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($fsock);
- throw new Exception('Expected server response code. Got '.rtrim($line, "\r\n"));
- }
-
- $status = (integer) $m[2];
-
- // Informational 1xx or Client Error 4xx
- if ($status < 200 || $status >= 400)
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($s);
- return false;
- }
-
- continue;
- }
-
- // handle redirect
- if(preg_match('/^Location:\s*(.+)/', rtrim($line, "\r\n"), $m))
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($s);
- // Successful 2xx vs Redirect 3xx
- if($status < 300)
- {
- throw new Exception('Unexpected redirect to Location: '.rtrim($line).' for status code '.$status);
- }
- return self::sendHttpRequest(trim($m[1]), $pathDestination, $tries+1);
- }
-
- // save expected content length for later verification
- if(preg_match('/^Content-Length:\s*(\d+)/', $line, $m))
- {
- $contentLength = (integer) $m[1];
- }
- }
-
- if(feof($fsock))
- {
- throw new Exception('Unexpected end of transmission');
- }
-
- // process content/body
- $response = '';
-
- while (!feof($fsock))
- {
- $line = fread($fsock, 8192);
-
- $streamMetaData = @stream_get_meta_data($fsock);
- if($streamMetaData['timed_out'])
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($fsock);
- throw new Exception('Timed out waiting for server response');
- }
-
- if(is_resource($file))
- {
- // save to file
- $fileLength += fwrite($file, $line);
- }
- else
- {
- // concatenate to response string
- $response .= $line;
- }
- }
-
- // determine success or failure
- @fclose(@$fsock);
- }
- else if($method == 'stream')
- {
- $response = false;
-
- // we make sure the request takes less than a few seconds to fail
- // we create a stream_context (works in php >= 5.2.1)
- // we also set the socket_timeout (for php < 5.2.1)
- $default_socket_timeout = @ini_get('default_socket_timeout');
- @ini_set('default_socket_timeout', $timeout);
-
- $ctx = null;
- if(function_exists('stream_context_create')) {
- $stream_options = array(
- 'http' => array(
- 'header' => 'User-Agent: Piwik/'.Piwik_Version::VERSION.($userAgent ? " $userAgent" : '')."\r\n"
- .'Referer: http://'.Piwik_Common::getIpString()."/\r\n",
- 'max_redirects' => 3, // PHP 5.1.0
- 'timeout' => $timeout, // PHP 5.2.1
- )
- );
- $ctx = stream_context_create($stream_options);
- }
-
- $response = @file_get_contents($aUrl, 0, $ctx);
- if(is_resource($file))
- {
- // save to file
- fwrite($file, $response);
- }
-
- // restore the socket_timeout value
- if(!empty($default_socket_timeout))
- {
- @ini_set('default_socket_timeout', $default_socket_timeout);
- }
- }
- else if($method == 'curl')
- {
- $ch = @curl_init();
-
- $curl_options = array(
- CURLOPT_URL => $aUrl,
- CURLOPT_HEADER => false,
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_TIMEOUT => $timeout,
- CURLOPT_BINARYTRANSFER => is_resource($file),
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_MAXREDIRS => 3,
- CURLOPT_USERAGENT => 'Piwik/'.Piwik_Version::VERSION.($userAgent ? " $userAgent" : ''),
- CURLOPT_REFERER => 'http://'.Piwik_Common::getIpString(),
- );
- @curl_setopt_array($ch, $curl_options);
-
- $response = @curl_exec($ch);
- if(is_resource($file))
- {
- // save to file
- fwrite($file, $response);
- }
-
- @curl_close($ch);
- unset($ch);
- }
- else
- {
- throw new Exception('Invalid request method: '.$method);
- }
-
- if(is_resource($file))
- {
- fflush($file);
- @fclose($file);
- if($contentLength && (($fileLength != $contentLength) || (filesize($destinationPath) != $contentLength)))
- {
- throw new Exception('File size error: '.$destinationPath.'; expected '.$contentLength.' bytes; received '.$fileLength.' bytes');
- }
- return true;
- }
-
- if($contentLength && strlen($response) != $contentLength)
- {
- throw new Exception('Content length error: expected '.$contentLength.' bytes; received '.$fileLength.' bytes');
- }
- return trim($response);
- }
+/*
+ * Current module, action, plugin
+ */
/**
- * Fetch the file at $url in the destination $pathDestination
- * @param string $url
- * @param string $pathDestination
- * @param int $tries
- * @return true on success, throws Exception on failure
+ * Returns the name of the Login plugin currently being used.
+ * Must be used since it is not allowed to hardcode 'Login' in URLs
+ * in case another Login plugin is being used.
+ *
+ * @return string
*/
- static public function fetchRemoteFile($url, $pathDestination, $tries = 0)
+ static public function getLoginPluginName()
{
- return self::sendHttpRequest($url, 10, 'Update', $pathDestination, $tries);
+ return Zend_Registry::get('auth')->getName();
}
/**
- * Recursively delete a directory
+ * Returns the plugin currently being used to display the page
*
- * @param string $dir Directory name
- * @param boolean $deleteRootToo Delete specified top-level directory as well
- */
- static public function unlinkRecursive($dir, $deleteRootToo)
- {
- if(!$dh = @opendir($dir))
- {
- return;
- }
- while (false !== ($obj = readdir($dh)))
- {
- if($obj == '.' || $obj == '..')
- {
- continue;
- }
-
- if (!@unlink($dir . '/' . $obj))
- {
- self::unlinkRecursive($dir.'/'.$obj, true);
- }
- }
- closedir($dh);
- if ($deleteRootToo)
- {
- @rmdir($dir);
- }
- return;
- }
-
- /**
- * Copy recursively from $source to $target.
- *
- * @param string $source eg. './tmp/latest'
- * @param string $target eg. '.'
- * @param bool $excludePhp
+ * @return Piwik_Plugin
*/
- static public function copyRecursive($source, $target, $excludePhp=false )
+ static public function getCurrentPlugin()
{
- if ( is_dir( $source ) )
- {
- @mkdir( $target );
- $d = dir( $source );
- while ( false !== ( $entry = $d->read() ) )
- {
- if ( $entry == '.' || $entry == '..' )
- {
- continue;
- }
-
- $sourcePath = $source . '/' . $entry;
- if ( is_dir( $sourcePath ) )
- {
- self::copyRecursive( $sourcePath, $target . '/' . $entry, $excludePhp );
- continue;
- }
- $destPath = $target . '/' . $entry;
- self::copy($sourcePath, $destPath, $excludePhp);
- }
- $d->close();
- }
- else
- {
- self::copy($source, $target, $excludePhp);
- }
+ return Piwik_PluginsManager::getInstance()->getLoadedPlugin(Piwik::getModule());
}
-
+
/**
- * Copy individual file from $source to $target.
- *
- * @param string $source eg. './tmp/latest/index.php'
- * @param string $target eg. './index.php'
- * @param bool $excludePhp
- * @return bool
+ * Returns the current module read from the URL (eg. 'API', 'UserSettings', etc.)
+ *
+ * @return string
*/
- static public function copy($source, $dest, $excludePhp=false)
+ static public function getModule()
{
- static $phpExtensions = array('php', 'tpl');
-
- if($excludePhp)
- {
- $path_parts = pathinfo($source);
- if(in_array($path_parts['extension'], $phpExtensions))
- {
- return true;
- }
- }
-
- if(!@copy( $source, $dest ))
- {
- @chmod($dest, 0755);
- if(!@copy( $source, $dest ))
- {
- throw new Exception("
- Error while copying file to <code>$dest</code>. <br />
- Please check that the web server has enough permission to overwrite this file. <br/>
- For example, on a linux server, if your apache user is www-data you can try to execute:<br>
- <code>chown -R www-data:www-data ".Piwik_Common::getPathToPiwikRoot()."</code><br>
- <code>chmod -R 0755 ".Piwik_Common::getPathToPiwikRoot()."</code><br>
- ");
- }
- }
- return true;
+ return Piwik_Common::getRequestVar('module', '', 'string');
}
/**
- * Recursively find pathnames that match a pattern
- * @see glob()
+ * Returns the current action read from the URL
*
- * @param string $sDir directory
- * @param string $sPattern pattern
- * @param int $nFlags glob() flags
- * @return array
+ * @return string
*/
- public static function globr($sDir, $sPattern, $nFlags = NULL)
+ static public function getAction()
{
- if(($aFiles = glob("$sDir/$sPattern", $nFlags)) == false)
- {
- $aFiles = array();
- }
- if(($aDirs = glob("$sDir/*", GLOB_ONLYDIR)) != false)
- {
- foreach ($aDirs as $sSubDir)
- {
- $aSubFiles = self::globr($sSubDir, $sPattern, $nFlags);
- $aFiles = array_merge($aFiles, $aSubFiles);
- }
- }
- return $aFiles;
+ return Piwik_Common::getRequestVar('action', '', 'string');
}
/**
- * API was simplified in 0.2.27, but we maintain backward compatibility
- * when calling Piwik::prefixTable
+ * Redirect to module (and action)
*
- * @deprecated as of 0.2.27
+ * @param string $newModule
+ * @param string $newAction
+ * @return bool false if the URL to redirect to is already this URL
*/
- static public function prefixTable( $table )
+ static public function redirectToModule( $newModule, $newAction = '', $parameters = array() )
{
- return Piwik_Common::prefixTable($table);
+ $newUrl = 'index.php' . Piwik_Url::getCurrentQueryStringWithParametersModified(
+ array('module' => $newModule, 'action' => $newAction)
+ + $parameters
+ );
+ Piwik_Url::redirectToUrl($newUrl);
}
-
+
+/*
+ * Global database object
+ */
+
/**
- * Names of all the prefixed tables in piwik
- * Doesn't use the DB
+ * Create database object and connect to database
*/
- static public function getTablesNames()
- {
- $aTables = array_keys(self::getTablesCreateSql());
- $config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
- $return = array();
- foreach($aTables as $table)
- {
- $return[] = $prefixTables.$table;
- }
- return $return;
- }
-
- static $tablesInstalled = null;
-
- static public function getTablesInstalled($forceReload = true, $idSite = null)
- {
- if(is_null(self::$tablesInstalled)
- || $forceReload === true)
- {
- $db = Zend_Registry::get('db');
- $config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
-
- $allTables = $db->fetchCol("SHOW TABLES");
-
- // all the tables to be installed
- $allMyTables = self::getTablesNames();
-
- // we get the intersection between all the tables in the DB and the tables to be installed
- $tablesInstalled = array_intersect($allMyTables, $allTables);
-
- // at this point we have only the piwik tables which is good
- // but we still miss the piwik generated tables (using the class Piwik_TablePartitioning)
- $idSiteInSql = "no";
- if(!is_null($idSite))
- {
- $idSiteInSql = $idSite;
- }
- $allArchiveNumeric = $db->fetchCol("/* SHARDING_ID_SITE = ".$idSiteInSql." */
- SHOW TABLES LIKE '".$prefixTables."archive_numeric%'");
- $allArchiveBlob = $db->fetchCol("/* SHARDING_ID_SITE = ".$idSiteInSql." */
- SHOW TABLES LIKE '".$prefixTables."archive_blob%'");
-
- $allTablesReallyInstalled = array_merge($tablesInstalled, $allArchiveNumeric, $allArchiveBlob);
-
- self::$tablesInstalled = $allTablesReallyInstalled;
- }
- return self::$tablesInstalled;
- }
-
- static public function createDatabase( $dbName = null )
- {
- if(is_null($dbName))
- {
- $dbName = Zend_Registry::get('config')->database->dbname;
- }
- Piwik_Exec("CREATE DATABASE IF NOT EXISTS ".$dbName);
- }
-
- static public function dropDatabase()
- {
- $dbName = Zend_Registry::get('config')->database->dbname;
- Piwik_Exec("DROP DATABASE IF EXISTS " . $dbName);
- }
-
static public function createDatabaseObject( $dbInfos = null )
{
$config = Zend_Registry::get('config');
-
+
if(is_null($dbInfos))
{
$dbInfos = $config->database->toArray();
}
-
+
$dbInfos['profiler'] = $config->Debug->enable_sql_profiler;
-
+
$db = null;
Piwik_PostEvent('Reporting.createDatabase', $db);
if(is_null($db))
{
- if($dbInfos['port'][0] == '/')
- {
- $dbInfos['unix_socket'] = $dbInfos['port'];
- unset($dbInfos['host']);
- unset($dbInfos['port']);
- }
-
- // not used by Zend Framework
- unset($dbInfos['tables_prefix']);
- unset($dbInfos['adapter']);
-
- $db = Piwik_Db::factory($config->database->adapter, $dbInfos);
- $db->getConnection();
-
- Zend_Db_Table::setDefaultAdapter($db);
- $db->resetConfig(); // we don't want this information to appear in the logs
+ $adapter = $dbInfos['adapter'];
+ $db = Piwik_Db_Adapter::factory($adapter, $dbInfos);
}
Zend_Registry::set('db', $db);
}
-
- static public function disconnectDatabase()
- {
- Zend_Registry::get('db')->closeConnection();
- }
-
+
/**
- * Returns the MySQL database server version
- *
- * @deprecated 0.4.4
+ * Disconnect from database
*/
- static public function getMysqlVersion()
+ static public function disconnectDatabase()
{
- return Piwik_FetchOne("SELECT VERSION()");
+ Zend_Registry::get('db')->closeConnection();
}
/**
@@ -1520,23 +1304,30 @@ class Piwik
return Zend_Registry::get('db')->isConnectionUTF8();
}
+/*
+ * Global log object
+ */
+
+ /**
+ * Create log object
+ */
static public function createLogObject()
{
$configAPI = Zend_Registry::get('config')->log;
-
+
$aLoggers = array(
'logger_api_call' => new Piwik_Log_APICall,
'logger_exception' => new Piwik_Log_Exception,
'logger_error' => new Piwik_Log_Error,
'logger_message' => new Piwik_Log_Message,
- );
-
+ );
+
foreach($configAPI as $loggerType => $aRecordTo)
{
if(isset($aLoggers[$loggerType]))
{
$logger = $aLoggers[$loggerType];
-
+
foreach($aRecordTo as $recordTo)
{
switch($recordTo)
@@ -1544,15 +1335,15 @@ class Piwik
case 'screen':
$logger->addWriteToScreen();
break;
-
+
case 'database':
$logger->addWriteToDatabase();
break;
-
+
case 'file':
- $logger->addWriteToFile();
+ $logger->addWriteToFile();
break;
-
+
default:
throw new Exception("'$recordTo' is not a valid Log type. Valid logger types are: screen, database, file.");
break;
@@ -1560,7 +1351,7 @@ class Piwik
}
}
}
-
+
foreach($aLoggers as $loggerType =>$logger)
{
if($logger->getWritersCount() == 0)
@@ -1570,7 +1361,16 @@ class Piwik
Zend_Registry::set($loggerType, $logger);
}
}
-
+
+/*
+ * Global config object
+ */
+
+ /**
+ * Create configuration object
+ *
+ * @param string $pathConfigFile
+ */
static public function createConfigObject( $pathConfigFile = null )
{
$config = new Piwik_Config($pathConfigFile);
@@ -1578,93 +1378,181 @@ class Piwik
$config->init();
}
+/*
+ * Global access object
+ */
+
+ /**
+ * Create access object
+ */
static public function createAccessObject()
{
Zend_Registry::set('access', new Piwik_Access());
}
-
- static public function dropTables( $doNotDelete = array() )
- {
- $tablesAlreadyInstalled = self::getTablesInstalled();
- $db = Zend_Registry::get('db');
-
- $doNotDeletePattern = '/('.implode('|',$doNotDelete).')/';
-
- foreach($tablesAlreadyInstalled as $tableName)
- {
-
- if( count($doNotDelete) == 0
- || (!in_array($tableName,$doNotDelete)
- && !preg_match($doNotDeletePattern,$tableName)
- )
- )
- {
- $db->query("DROP TABLE `$tableName`");
- }
- }
- }
-
+
+/*
+ * User input validation
+ */
+
/**
* Returns true if the email is a valid email
- *
+ *
* @param string email
* @return bool
*/
- static public function isValidEmailString( $email )
+ static public function isValidEmailString( $email )
{
return (preg_match('/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z]{2,4}$/', $email) > 0);
}
-
+
/**
- * Creates an entry in the User table for the "anonymous" user.
+ * Returns true if the login is valid.
+ * Warning: does not check if the login already exists! You must use UsersManager_API->userExists as well.
+ *
+ * @param string $login
+ * @return bool or throws exception
*/
- static public function createAnonymousUser()
+ static public function checkValidLoginString( $userLogin )
+ {
+ $loginMinimumLength = 3;
+ $loginMaximumLength = 100;
+ $l = strlen($userLogin);
+ if(!($l >= $loginMinimumLength
+ && $l <= $loginMaximumLength
+ && (preg_match('/^[A-Za-z0-9_.-]*$/', $userLogin) > 0))
+ )
+ {
+ throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidLoginFormat', array($loginMinimumLength, $loginMaximumLength)));
+ }
+ }
+
+/*
+ * Date / Timezone
+ */
+
+ /**
+ * Returns true if the current php version supports timezone manipulation
+ * (most likely if php >= 5.2)
+ *
+ * @return bool
+ */
+ static public function isTimezoneSupportEnabled()
{
- // The anonymous user is the user that is assigned by default
- // note that the token_auth value is anonymous, which is assigned by default as well in the Login plugin
- $db = Zend_Registry::get('db');
- $db->query("INSERT INTO ". Piwik::prefixTable("user") . "
- VALUES ( 'anonymous', '', 'anonymous', 'anonymous@example.org', 'anonymous', CURRENT_TIMESTAMP );" );
+ return
+ function_exists( 'date_create' ) &&
+ function_exists( 'date_default_timezone_set' ) &&
+ function_exists( 'timezone_identifiers_list' ) &&
+ function_exists( 'timezone_open' ) &&
+ function_exists( 'timezone_offset_get' );
}
-
- static public function createTables()
+
+/*
+ * Database and table definition methods
+ */
+
+ /**
+ * Is the schema available?
+ *
+ * @return bool True if schema is available; false otherwise
+ */
+ static public function isAvailable()
{
- $db = Zend_Registry::get('db');
- $config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
+ return Piwik_Db_Schema::getInstance()->isAvailable();
+ }
- $tablesAlreadyInstalled = self::getTablesInstalled();
- $tablesToCreate = self::getTablesCreateSql();
- unset($tablesToCreate['archive_blob']);
- unset($tablesToCreate['archive_numeric']);
+ /**
+ * Get the SQL to create a specific Piwik table
+ *
+ * @param string $tableName
+ * @return string SQL
+ */
+ static public function getTableCreateSql( $tableName )
+ {
+ return Piwik_Db_Schema::getInstance()->getTableCreateSql($tableName);
+ }
- foreach($tablesToCreate as $tableName => $tableSql)
- {
- $tableName = $prefixTables . $tableName;
- if(!in_array($tableName, $tablesAlreadyInstalled))
- {
- $db->query( $tableSql );
- }
- }
+ /**
+ * Get the SQL to create Piwik tables
+ *
+ * @return array of strings containing SQL
+ */
+ static public function getTablesCreateSql()
+ {
+ return Piwik_Db_Schema::getInstance()->getTablesCreateSql();
+ }
+
+ /**
+ * Create database
+ *
+ * @param string $dbName
+ */
+ static public function createDatabase( $dbName = null )
+ {
+ Piwik_Db_Schema::getInstance()->createDatabase($dbName);
}
-
+
+ /**
+ * Drop database
+ */
+ static public function dropDatabase()
+ {
+ Piwik_Db_Schema::getInstance()->dropDatabase();
+ }
+
+ /**
+ * Create all tables
+ */
+ static public function createTables()
+ {
+ Piwik_Db_Schema::getInstance()->createTables();
+ }
+
+ /**
+ * Creates an entry in the User table for the "anonymous" user.
+ */
+ static public function createAnonymousUser()
+ {
+ Piwik_Db_Schema::getInstance()->createAnonymousUser();
+ }
+
+ /**
+ * Truncate all tables
+ */
static public function truncateAllTables()
{
- $tablesAlreadyInstalled = self::getTablesInstalled($forceReload = true);
- foreach($tablesAlreadyInstalled as $table)
- {
- Piwik_Query("TRUNCATE `$table`");
- }
+ Piwik_Db_Schema::getInstance()->truncateAllTables();
}
-
- static public function install()
+
+ /**
+ * Drop specific tables
+ *
+ * @param array $doNotDelete Names of tables to not delete
+ */
+ static public function dropTables( $doNotDelete = array() )
{
- Piwik_Common::mkdir(Zend_Registry::get('config')->smarty->compile_dir);
+ Piwik_Db_Schema::getInstance()->dropTables($doNotDelete);
}
-
- static public function uninstall()
+
+ /**
+ * Names of all the prefixed tables in piwik
+ * Doesn't use the DB
+ *
+ * @return array Table names
+ */
+ static public function getTablesNames()
+ {
+ return Piwik_Db_Schema::getInstance()->getTablesNames();
+ }
+
+ /**
+ * Get list of tables installed
+ *
+ * @param bool $forceReload Invalidate cache
+ * @param string $idSite
+ * @return array Tables installed
+ */
+ static public function getTablesInstalled($forceReload = true, $idSite = null)
{
- $db = Zend_Registry::get('db');
- $db->query( "DROP TABLE IF EXISTS ". implode(", ", self::getTablesNames()) );
+ return Piwik_Db_Schema::getInstance()->getTablesInstalled($forceReload, $idSite);
}
}