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, 1065 insertions, 953 deletions
diff --git a/core/Piwik.php b/core/Piwik.php
index 67fd9a24c4..af7c5f083c 100644
--- a/core/Piwik.php
+++ b/core/Piwik.php
@@ -10,279 +10,69 @@
* @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 )
- {
- return;
- }
- $directoryList = '';
- foreach($resultCheck as $dir => $bool)
- {
- $realpath = Piwik_Common::realpath($dir);
- if(!empty($realpath) && $bool === false)
+ if( array_search(false, $resultCheck) !== false )
+ {
+ $directoryList = '';
+ foreach($resultCheck as $dir => $bool)
{
- $directoryList .= "<code>chmod 777 $realpath</code><br />";
+ $realpath = Piwik_Common::realpath($dir);
+ if(!empty($realpath) && $bool === false)
+ {
+ $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',
@@ -290,9 +80,9 @@ class Piwik
'/tmp/templates_c',
'/tmp/cache',
'/tmp/latest',
- );
+ );
}
-
+
$resultCheck = array();
foreach($directoriesToCheck as $directoryToCheck)
{
@@ -300,12 +90,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
@@ -316,167 +106,28 @@ class Piwik
}
return $resultCheck;
}
-
+
/**
- * 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
- *
- * Note: for IIS 7 and above
- */
- 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).
+ * Returns the Javascript code to be inserted on every page to track
*
- * @return array(bool, string, ...) Return code (true/false), followed by zero or more error messages
+ * @param int $idSite
+ * @param string $piwikUrl http://path/to/piwik/directory/
+ * @param string $actionName
+ * @return string
*/
- 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;
+ 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;
}
-/*
- * PHP environment settings
- */
-
/**
* Set maximum script execution time.
*
@@ -489,46 +140,15 @@ 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'))
{
- // 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 substr($memory, 0, strlen($memory) - 1);
}
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();
@@ -540,12 +160,7 @@ 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;
@@ -555,25 +170,22 @@ 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
@@ -582,54 +194,46 @@ 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
- */
-
+
/**
- * Get total number of queries
+ * 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.
*
- * @return int number of queries
+ * @param numeric $i1
+ * @param numeric $i2
+ * @return numeric The result of the division or zero
*/
+ 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'))
@@ -639,20 +243,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)
{
@@ -660,23 +264,24 @@ 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)
{
@@ -701,9 +306,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;
@@ -716,63 +321,44 @@ 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');
}
- /**
- * Print memory leak
- *
- * @param string $prefix
- * @param string $suffix
- */
- static public function printMemoryLeak($prefix = '', $suffix = '<br />')
+ 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;
@@ -784,7 +370,7 @@ class Piwik
{
$memory = memory_get_usage();
}
-
+
if($memory !== false)
{
$usage = round( $memory / 1024 / 1024, 2);
@@ -799,220 +385,385 @@ class Piwik
Piwik::log("Memory usage function not found.");
}
}
-
-/*
- * 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 )
+
+ static public function getPrettySizeFromBytes($size)
{
- if ( is_numeric($i1) && is_numeric($i2) && floatval($i2) != 0)
+ $bytes = array('','K','M','G','T');
+ foreach($bytes as $val)
{
- return $i1 / $i2;
+ if($size > 1024)
+ {
+ $size = $size / 1024;
+ }
+ else
+ {
+ break;
+ }
}
- return 0;
+ return round($size, 1)." ".$val;
}
/**
- * Safely compute a percentage. Return 0 to avoid division by zero.
+ * Returns true if PHP was invoked as CGI or command-line interface (shell)
*
- * @param numeric $dividend
- * @param numeric $divisor
- * @param int $precision
- * @return numeric
+ * @deprecated deprecated in 0.4.4
+ * @see Piwik_Common::isPhpCliMode()
+ * @return bool true if PHP invoked as a CGI or from CLI
*/
- static public function getPercentageSafe($dividend, $divisor, $precision = 0)
+ static public function isPhpCliMode()
{
- if($divisor == 0)
- {
- return 0;
- }
- return round(100 * $dividend / $divisor, $precision);
+ return Piwik_Common::isPhpCliMode();
}
-
- /**
- * Get currency symbol for a site
- *
- * @param int $idSite
- * @return string
- */
- static public function getCurrency($idSite)
+
+ static public function getCurrency()
{
- static $symbols = null;
- if(is_null($symbols))
+ static $symbol = null;
+ if(is_null($symbol))
{
- $symbols = Piwik_SitesManager_API::getInstance()->getCurrencySymbols();
+ $symbol = trim(Zend_Registry::get('config')->General->default_currency);
}
- $site = new Piwik_Site($idSite);
- return $symbols[$site->getCurrency()];
+ return $symbol;
}
- /**
- * Pretty format monetary value for a site
- *
- * @param numeric $value
- * @param int $idSite
- * @return string
- */
- static public function getPrettyMoney($value, $idSite)
+ static public function getPrettyMoney($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);
+ $symbol = self::getCurrency();
+ return sprintf("$symbol%.2f", $value);
}
-
- /**
- * Pretty format a memory size value
- *
- * @param numeric $size in bytes
- * @return string
- */
- static public function getPrettySizeFromBytes($size)
+
+ static public function getPercentageSafe($dividend, $divisor, $precision = 0)
{
- $bytes = array('','K','M','G','T');
- foreach($bytes as $val)
+ if($divisor == 0)
{
- if($size > 1024)
- {
- $size = $size / 1024;
- }
- else
- {
- break;
- }
+ return 0;
}
- return round($size, 1)." ".$val;
+ return round(100 * $dividend / $divisor, $precision);
}
-
- /**
- * 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(Piwik_Translate('General_DaysHours'), $days, $hours);
+ return sprintf("%d days %d hours", $days, $hours);
}
elseif($hours > 0)
{
- $return = sprintf(Piwik_Translate('General_HoursMinutes'), $hours, $minutes);
+ return sprintf("%d hours %d min", $hours, $minutes);
}
elseif($minutes > 0)
{
- $return = sprintf(Piwik_Translate('General_MinutesSeconds'), $minutes, $seconds);
+ return sprintf("%d&nbsp;min&nbsp;%ds", $minutes, $seconds);
}
else
{
- $return = sprintf(Piwik_Translate('General_Seconds'), $seconds);
+ return sprintf("%ds", $seconds);
}
- return str_replace(' ', '&nbsp;', $return);
- }
-
- /**
- * 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 = "''")
- {
- $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;
}
-
- /**
- * Generate a title for image tags
- *
- * @return string
- */
+
static public function getRandomTitle()
{
- 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',
- );
- $id = abs(intval(md5(Piwik_Url::getCurrentHost())));
+ $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;
}
-
-/*
- * Access
- */
-
- /**
- * Get current user login
- *
- * @return string
- */
+
+ static public function getTableCreateSql( $tableName )
+ {
+ $tables = Piwik::getTablesCreateSql();
+
+ if(!isset($tables[$tableName]))
+ {
+ throw new Exception("The table '$tableName' SQL creation code couldn't be found.");
+ }
+
+ return $tables[$tableName];
+ }
+
+ static public function getTablesCreateSql()
+ {
+ $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
+ ",
+ );
+ return $tables;
+ }
+
static public function getCurrentUserLogin()
{
return Zend_Registry::get('access')->getLogin();
}
-
+
+ static public function getCurrentUserTokenAuth()
+ {
+ return Zend_Registry::get('access')->getTokenAuth();
+ }
+
/**
- * Get current user's token auth
+ * Returns the plugin currently being used to display the page
*
- * @return string
+ * @return Piwik_Plugin
*/
- static public function getCurrentUserTokenAuth()
+ static public function getCurrentPlugin()
{
- return Zend_Registry::get('access')->getTokenAuth();
+ return Piwik_PluginsManager::getInstance()->getLoadedPlugin(Piwik::getModule());
}
-
+
/**
* 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
*/
@@ -1025,10 +776,8 @@ 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
*/
@@ -1044,10 +793,9 @@ 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()
@@ -1059,32 +807,21 @@ 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( $bool = true )
+ static public function setUserIsSuperUser()
{
- Zend_Registry::get('access')->setSuperUser($bool);
+ Zend_Registry::get('access')->setSuperUser();
}
-
- /**
- * 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{
@@ -1094,23 +831,12 @@ 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{
@@ -1120,23 +846,17 @@ 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();
}
-
- /**
- * Returns true if the user has view access to the sites
- *
- * @param mixed $idSites
- * @return bool
- */
+
+ static public function checkUserHasSomeViewAccess()
+ {
+ Zend_Registry::get('access')->checkUserHasSomeViewAccess();
+ }
+
static public function isUserHasViewAccess( $idSites )
{
try{
@@ -1146,140 +866,636 @@ 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;
+ }
/**
- * Check user has view access to the sites
+ * Returns the current module read from the URL (eg. 'API', 'UserSettings', etc.)
*
- * @param mixed $idSites
- * @throws Exception if user doesn't have view access to sites
+ * @return string
*/
- static public function checkUserHasViewAccess( $idSites )
+ static public function getModule()
{
- Zend_Registry::get('access')->checkUserHasViewAccess( $idSites );
+ return Piwik_Common::getRequestVar('module', '', 'string');
}
-
+
/**
- * Returns true if the user has view access to any sites
+ * Returns the current action read from the URL
*
- * @return bool
+ * @return string
*/
- static public function isUserHasSomeViewAccess()
+ static public function getAction()
{
- try{
- self::checkUserHasSomeViewAccess();
- return true;
- } catch( Exception $e){
- return false;
+ return Piwik_Common::getRequestVar('action', '', 'string');
+ }
+
+ /**
+ * returns false if the URL to redirect to is already this URL
+ */
+ static public function redirectToModule( $newModule, $newAction = '' )
+ {
+ $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;
}
/**
- * Check user has view access to any sites
- *
- * @throws Exception if user doesn't have view access to any sites
+ * Get "best" available transport method for sendHttpRequest() calls.
*/
- static public function checkUserHasSomeViewAccess()
+ static public function getTransportMethod()
{
- Zend_Registry::get('access')->checkUserHasSomeViewAccess();
+ $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;
+ }
+ }
+ }
+ return $method;
}
-/*
- * Current module, action, plugin
- */
-
/**
- * 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.
+ * Sends http request ensuring the request will fail before $timeout seconds
*
- * @return string
+ * 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
*/
- static public function getLoginPluginName()
+ static public function sendHttpRequest($aUrl, $timeout, $userAgent = null, $destinationPath = null, $followDepth = 0)
{
- return Zend_Registry::get('auth')->getName();
+ // 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);
+ }
+
+ 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);
}
/**
- * Returns the plugin currently being used to display the page
- *
- * @return Piwik_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
*/
- static public function getCurrentPlugin()
+ static public function fetchRemoteFile($url, $pathDestination, $tries = 0)
{
- return Piwik_PluginsManager::getInstance()->getLoadedPlugin(Piwik::getModule());
+ return self::sendHttpRequest($url, 10, 'Update', $pathDestination, $tries);
}
/**
- * Returns the current module read from the URL (eg. 'API', 'UserSettings', etc.)
+ * Recursively delete a directory
*
- * @return string
+ * @param string $dir Directory name
+ * @param boolean $deleteRootToo Delete specified top-level directory as well
*/
- static public function getModule()
+ static public function unlinkRecursive($dir, $deleteRootToo)
{
- return Piwik_Common::getRequestVar('module', '', 'string');
+ 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
+ */
+ 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;
}
/**
- * Returns the current action read from the URL
+ * Recursively find pathnames that match a pattern
+ * @see glob()
*
- * @return string
+ * @param string $sDir directory
+ * @param string $sPattern pattern
+ * @param int $nFlags glob() flags
+ * @return array
*/
- static public function getAction()
+ public static function globr($sDir, $sPattern, $nFlags = NULL)
{
- return Piwik_Common::getRequestVar('action', '', 'string');
+ 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;
}
/**
- * Redirect to module (and action)
+ * API was simplified in 0.2.27, but we maintain backward compatibility
+ * when calling Piwik::prefixTable
*
- * @param string $newModule
- * @param string $newAction
- * @return bool false if the URL to redirect to is already this URL
+ * @deprecated as of 0.2.27
*/
- static public function redirectToModule( $newModule, $newAction = '', $parameters = array() )
+ static public function prefixTable( $table )
{
- $newUrl = 'index.php' . Piwik_Url::getCurrentQueryStringWithParametersModified(
- array('module' => $newModule, 'action' => $newAction)
- + $parameters
- );
- Piwik_Url::redirectToUrl($newUrl);
+ return Piwik_Common::prefixTable($table);
}
-
-/*
- * Global database object
- */
-
+
/**
- * Create database object and connect to database
+ * Names of all the prefixed tables in piwik
+ * Doesn't use the DB
*/
- static public function createDatabaseObject( $dbInfos = null )
+ 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))
{
- $adapter = $dbInfos['adapter'];
- $db = Piwik_Db_Adapter::factory($adapter, $dbInfos);
+ 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
}
Zend_Registry::set('db', $db);
}
-
- /**
- * Disconnect from database
- */
+
static public function disconnectDatabase()
{
Zend_Registry::get('db')->closeConnection();
}
+
+ /**
+ * Returns the MySQL database server version
+ *
+ * @deprecated 0.4.4
+ */
+ static public function getMysqlVersion()
+ {
+ return Piwik_FetchOne("SELECT VERSION()");
+ }
/**
* Checks the database server version against the required minimum
@@ -1304,30 +1520,23 @@ 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)
@@ -1335,15 +1544,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;
@@ -1351,7 +1560,7 @@ class Piwik
}
}
}
-
+
foreach($aLoggers as $loggerType =>$logger)
{
if($logger->getWritersCount() == 0)
@@ -1361,16 +1570,7 @@ 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);
@@ -1378,181 +1578,93 @@ class Piwik
$config->init();
}
-/*
- * Global access object
- */
-
- /**
- * Create access object
- */
static public function createAccessObject()
{
Zend_Registry::set('access', new Piwik_Access());
}
-
-/*
- * 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 dropTables( $doNotDelete = array() )
{
- return (preg_match('/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z]{2,4}$/', $email) > 0);
- }
-
- /**
- * 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 checkValidLoginString( $userLogin )
- {
- $loginMinimumLength = 3;
- $loginMaximumLength = 100;
- $l = strlen($userLogin);
- if(!($l >= $loginMinimumLength
- && $l <= $loginMaximumLength
- && (preg_match('/^[A-Za-z0-9_.-]*$/', $userLogin) > 0))
- )
+ $tablesAlreadyInstalled = self::getTablesInstalled();
+ $db = Zend_Registry::get('db');
+
+ $doNotDeletePattern = '/('.implode('|',$doNotDelete).')/';
+
+ foreach($tablesAlreadyInstalled as $tableName)
{
- throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidLoginFormat', array($loginMinimumLength, $loginMaximumLength)));
- }
+
+ if( count($doNotDelete) == 0
+ || (!in_array($tableName,$doNotDelete)
+ && !preg_match($doNotDeletePattern,$tableName)
+ )
+ )
+ {
+ $db->query("DROP TABLE `$tableName`");
+ }
+ }
}
-
-/*
- * Date / Timezone
- */
-
+
/**
- * Returns true if the current php version supports timezone manipulation
- * (most likely if php >= 5.2)
- *
+ * Returns true if the email is a valid email
+ *
+ * @param string email
* @return bool
*/
- static public function isTimezoneSupportEnabled()
- {
- 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' );
- }
-
-/*
- * Database and table definition methods
- */
-
- /**
- * Is the schema available?
- *
- * @return bool True if schema is available; false otherwise
- */
- static public function isAvailable()
- {
- return Piwik_Db_Schema::getInstance()->isAvailable();
- }
-
- /**
- * 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);
- }
-
- /**
- * 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 )
+ static public function isValidEmailString( $email )
{
- Piwik_Db_Schema::getInstance()->createDatabase($dbName);
+ return (preg_match('/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z]{2,4}$/', $email) > 0);
}
-
+
/**
- * Drop database
+ * Creates an entry in the User table for the "anonymous" user.
*/
- static public function dropDatabase()
+ static public function createAnonymousUser()
{
- Piwik_Db_Schema::getInstance()->dropDatabase();
+ // 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 );" );
}
-
- /**
- * Create all tables
- */
+
static public function createTables()
{
- Piwik_Db_Schema::getInstance()->createTables();
- }
+ $db = Zend_Registry::get('db');
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
- /**
- * Creates an entry in the User table for the "anonymous" user.
- */
- static public function createAnonymousUser()
- {
- Piwik_Db_Schema::getInstance()->createAnonymousUser();
- }
+ $tablesAlreadyInstalled = self::getTablesInstalled();
+ $tablesToCreate = self::getTablesCreateSql();
+ unset($tablesToCreate['archive_blob']);
+ unset($tablesToCreate['archive_numeric']);
- /**
- * Truncate all tables
- */
- static public function truncateAllTables()
- {
- Piwik_Db_Schema::getInstance()->truncateAllTables();
+ foreach($tablesToCreate as $tableName => $tableSql)
+ {
+ $tableName = $prefixTables . $tableName;
+ if(!in_array($tableName, $tablesAlreadyInstalled))
+ {
+ $db->query( $tableSql );
+ }
+ }
}
-
- /**
- * Drop specific tables
- *
- * @param array $doNotDelete Names of tables to not delete
- */
- static public function dropTables( $doNotDelete = array() )
+
+ static public function truncateAllTables()
{
- Piwik_Db_Schema::getInstance()->dropTables($doNotDelete);
+ $tablesAlreadyInstalled = self::getTablesInstalled($forceReload = true);
+ foreach($tablesAlreadyInstalled as $table)
+ {
+ Piwik_Query("TRUNCATE `$table`");
+ }
}
-
- /**
- * Names of all the prefixed tables in piwik
- * Doesn't use the DB
- *
- * @return array Table names
- */
- static public function getTablesNames()
+
+ static public function install()
{
- return Piwik_Db_Schema::getInstance()->getTablesNames();
+ Piwik_Common::mkdir(Zend_Registry::get('config')->smarty->compile_dir);
}
-
- /**
- * 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)
+
+ static public function uninstall()
{
- return Piwik_Db_Schema::getInstance()->getTablesInstalled($forceReload, $idSite);
+ $db = Zend_Registry::get('db');
+ $db->query( "DROP TABLE IF EXISTS ". implode(", ", self::getTablesNames()) );
}
}