Skip to content
Extraits de code Groupes Projets
Fixture.php 28,6 ko
Newer Older
 * Piwik - free/libre analytics platform
 *
 * @link http://piwik.org
 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 */
namespace Piwik\Tests;

use Piwik\Access;
use Piwik\Common;
use Piwik\Config;
use Piwik\DataAccess\ArchiveTableCreator;
use Piwik\DataTable\Manager as DataTableManager;
mattab's avatar
mattab a validé
use Piwik\Db;
use Piwik\DbHelper;
use Piwik\Log;
use Piwik\Option;
use Piwik\Piwik;
use Piwik\Plugins\LanguagesManager\API as APILanguageManager;
use Piwik\Plugins\MobileMessaging\MobileMessaging;
use Piwik\Plugins\ScheduledReports\API as APIScheduledReports;
use Piwik\Plugins\ScheduledReports\ScheduledReports;
use Piwik\Plugins\SitesManager\API as APISitesManager;
use Piwik\Plugins\UserCountry\LocationProvider;
use Piwik\Plugins\UsersManager\API as APIUsersManager;
use Piwik\Plugins\UsersManager\UsersManager;
use Piwik\Site;
diosmosis's avatar
diosmosis a validé
use Piwik\Tracker\Cache;
use Piwik\Translate;
use PHPUnit_Framework_Assert;
use Piwik_TestingEnvironment;
use FakeAccess;
use PiwikTracker;
use Piwik_LocalTracker;
use Piwik\Updater;
use Piwik\Plugins\CoreUpdater\CoreUpdater;
use Exception;
 * Base type for all system test fixtures. System test fixtures
 * add visit and related data to the database before a test is run. Different
 * tests can use the same fixtures.
 * This class defines a set of helper methods for fixture types. The helper
 * methods are public, but ideally they should only be used by fixture types.
 * NOTE: YOU SHOULD NOT CREATE A NEW FIXTURE UNLESS THERE IS NO WAY TO MODIFY
 * AN EXISTING FIXTURE TO HANDLE YOUR USE CASE.
 * Related TODO: we should try and reduce the amount of existing fixtures by
 *                merging some together.
 */
diosmosis's avatar
diosmosis a validé
class Fixture extends PHPUnit_Framework_Assert
    const IMAGES_GENERATED_ONLY_FOR_OS = 'linux';
    const IMAGES_GENERATED_FOR_PHP = '5.5';
    const IMAGES_GENERATED_FOR_GD = '2.1.1';
    const DEFAULT_SITE_NAME = 'Piwik test';
    const ADMIN_USER_LOGIN = 'superUserLogin';
    const ADMIN_USER_PASSWORD = 'superUserPass';
diosmosis's avatar
diosmosis a validé

    public $dbName = false;
    public $createConfig = true;
    public $dropDatabaseInSetUp = true;
diosmosis's avatar
diosmosis a validé
    public $dropDatabaseInTearDown = true;
    public $loadTranslations = true;
    public $createSuperUser = true;
    public $removeExistingSuperUser = true;
diosmosis's avatar
diosmosis a validé
    public $configureComponents = true;
    public $persistFixtureData = false;
    public $resetPersistedFixture = false;
    public $printToScreen = false;
    public $extraPluginsToLoad = array();
    /**
     * @return string
     */
    protected static function getPythonBinary()
    {
        if(\Piwik\SettingsServer::isWindows()) {
            return "C:\Python27\python.exe";
        }
        if(SystemTestCase::isTravisCI()) {
    /** Adds data to Piwik. Creates sites, tracks visits, imports log files, etc. */
diosmosis's avatar
diosmosis a validé
    public function setUp()
    {
        // empty
    }

    /** Does any clean up. Most of the time there will be no need to clean up. */
diosmosis's avatar
diosmosis a validé
    public function tearDown()
    {
        // empty
    }

    public function getDbName()
    {
        if ($this->dbName !== false) {
            return $this->dbName;
        }

        if ($this->persistFixtureData) {
            return str_replace("\\", "_", get_class($this));
        }

        return Config::getInstance()->database_tests['dbname'];
    }

    public function performSetUp($setupEnvironmentOnly = false)
diosmosis's avatar
diosmosis a validé
    {
        try {
            if ($this->createConfig) {
                Config::getInstance()->setTestEnvironment();
            }

            if ($this->persistFixtureData) {
                $this->dropDatabaseInSetUp = false;
                $this->dropDatabaseInTearDown = false;
                $this->overwriteExisting = false;
                $this->removeExistingSuperUser = false;

                Config::getInstance()->database_tests['dbname'] = Config::getInstance()->database['dbname'] = $this->dbName;
diosmosis's avatar
diosmosis a validé
                $this->getTestEnvironment()->dbName = $this->dbName;
            }

            if ($this->dbName === false) { // must be after test config is created
                $this->dbName = Config::getInstance()->database['dbname'];
            }
diosmosis's avatar
diosmosis a validé

            static::connectWithoutDatabase();
            if ($this->dropDatabaseInSetUp
                || $this->resetPersistedFixture
            ) {
diosmosis's avatar
diosmosis a validé
                $this->dropDatabase();
diosmosis's avatar
diosmosis a validé
            DbHelper::createDatabase($this->dbName);
            DbHelper::disconnectDatabase();

            // reconnect once we're sure the database exists
            Config::getInstance()->database['dbname'] = $this->dbName;
            Db::createDatabaseObject();

            Db::get()->query("SET wait_timeout=28800;");

diosmosis's avatar
diosmosis a validé
            DbHelper::createTables();

            \Piwik\Plugin\Manager::getInstance()->unloadPlugins();
diosmosis's avatar
diosmosis a validé
        } catch (Exception $e) {
            static::fail("TEST INITIALIZATION FAILED: " . $e->getMessage() . "\n" . $e->getTraceAsString());
        }

        include "DataFiles/SearchEngines.php";
        include "DataFiles/Socials.php";
        include "DataFiles/Languages.php";
        include "DataFiles/Countries.php";
        include "DataFiles/Currencies.php";
        include "DataFiles/LanguageToCountry.php";
        include "DataFiles/Providers.php";
        if (!$this->isFixtureSetUp()) {
            DbHelper::truncateAllTables();
        }

diosmosis's avatar
diosmosis a validé
        static::createAccessInstance();

        // We need to be SU to create websites for tests
        Access::getInstance()->setSuperUserAccess();
diosmosis's avatar
diosmosis a validé

        Cache::deleteTrackerCache();

        static::loadAllPlugins($this->getTestEnvironment(), $this->testCaseClass, $this->extraPluginsToLoad);
diosmosis's avatar
diosmosis a validé
        $_GET = $_REQUEST = array();
        $_SERVER['HTTP_REFERER'] = '';

        // Make sure translations are loaded to check messages in English
        if ($this->loadTranslations) {
            Translate::reloadLanguage('en');
            APILanguageManager::getInstance()->setLanguageForUser('superUserLogin', 'en');
        }
diosmosis's avatar
diosmosis a validé
        FakeAccess::$superUserLogin = 'superUserLogin';
diosmosis's avatar
diosmosis a validé
        \Piwik\SettingsPiwik::$cachedKnownSegmentsToArchive = null;
        \Piwik\CacheFile::$invalidateOpCacheBeforeRead = true;

diosmosis's avatar
diosmosis a validé
        if ($this->configureComponents) {
            \Piwik\Plugins\PrivacyManager\IPAnonymizer::deactivate();
            \Piwik\Plugins\PrivacyManager\DoNotTrackHeaderChecker::deactivate();
        }
diosmosis's avatar
diosmosis a validé

        if ($this->createSuperUser) {
            self::createSuperUser($this->removeExistingSuperUser);
diosmosis's avatar
diosmosis a validé
        $this->getTestEnvironment()->save();
        $this->getTestEnvironment()->executeSetupTestEnvHook();
        Piwik_TestingEnvironment::addSendMailHook();
diosmosis's avatar
diosmosis a validé

        if ($this->overwriteExisting
            || !$this->isFixtureSetUp()
        ) {
            $this->markFixtureSetUp();
            $this->log("Database {$this->dbName} marked as successfully set up.");
        } else {
            $this->log("Using existing database {$this->dbName}.");
diosmosis's avatar
diosmosis a validé
    public function getTestEnvironment()
    {
        if ($this->testEnvironment === null) {
            $this->testEnvironment = new Piwik_TestingEnvironment();

            if (getenv('PIWIK_USE_XHPROF') == 1) {
                $this->testEnvironment->useXhprof = true;
            }
diosmosis's avatar
diosmosis a validé
        }
        return $this->testEnvironment;
    }

    public function isFixtureSetUp()
    {
        $optionName = get_class($this) . '.setUpFlag';
        return Option::get($optionName) !== false;
        $optionName = get_class($this) . '.setUpFlag';
        Option::set($optionName, 1);
    }

    public function performTearDown()
    {
mattab's avatar
mattab a validé
        // Note: avoid run SQL in the *tearDown() metohds because it randomly fails on Travis CI
        // with error Error while sending QUERY packet. PID=XX
diosmosis's avatar
diosmosis a validé
        self::unloadAllPlugins();

        if ($this->dropDatabaseInTearDown) {
diosmosis's avatar
diosmosis a validé
            $this->dropDatabase();
        $this->clearInMemoryCaches();
    }

    public function clearInMemoryCaches()
    {
diosmosis's avatar
diosmosis a validé
        DataTableManager::getInstance()->deleteAll();
        Option::clearCache();
        Site::clearCache();
        Cache::deleteTrackerCache();
        Config::getInstance()->clear();
        ArchiveTableCreator::clear();
        \Piwik\Plugins\ScheduledReports\API::$cache = array();
        \Piwik\Registry::unsetInstance();
diosmosis's avatar
diosmosis a validé
        \Piwik\EventDispatcher::getInstance()->clearAllObservers();
diosmosis's avatar
diosmosis a validé

        $_GET = $_REQUEST = array();
        Translate::unloadEnglishTranslation();
diosmosis's avatar
diosmosis a validé

        Config::unsetInstance();

        \Piwik\Config::getInstance()->Plugins; // make sure Plugins exists in a config object for next tests that use Plugin\Manager
        // since Plugin\Manager uses getFromGlobalConfig which doesn't init the config object
    public static function loadAllPlugins($testEnvironment = null, $testCaseClass = false, $extraPluginsToLoad = array())
        if (empty($testEnvironment)) {
            $testEnvironment = new Piwik_TestingEnvironment();
        }

mattab's avatar
mattab a validé
        DbHelper::createTables();
diosmosis's avatar
diosmosis a validé
        $pluginsManager = \Piwik\Plugin\Manager::getInstance();
        $plugins = $testEnvironment->getCoreAndSupportedPlugins();

        // make sure the plugin that executed this method is included in the plugins to load
        $extraPlugins = array_merge($extraPluginsToLoad, array(
            \Piwik\Plugin::getPluginNameFromBacktrace(debug_backtrace()),
            \Piwik\Plugin::getPluginNameFromNamespace($testCaseClass),
            \Piwik\Plugin::getPluginNameFromNamespace(get_called_class())
        foreach ($extraPlugins as $pluginName) {
            if (empty($pluginName)) {
                continue;
            }

            if (in_array($pluginName, $plugins)) {
                continue;
            }

            $plugins[] = $pluginName;
            if ($testEnvironment) {
                $testEnvironment->pluginsToLoad = array_merge($testEnvironment->pluginsToLoad ?: array(), array($pluginName));
            }
        }

        Log::debug("Plugins to load during tests: " . implode(', ', $plugins));
diosmosis's avatar
diosmosis a validé
        $pluginsManager->loadPlugins($plugins);
    }

    public static function installAndActivatePlugins()
    {
        $pluginsManager = \Piwik\Plugin\Manager::getInstance();
diosmosis's avatar
diosmosis a validé

        // Install plugins
        $messages = $pluginsManager->installLoadedPlugins();
        if(!empty($messages)) {
            Log::info("Plugin loading messages: %s", implode(" --- ", $messages));
        }
diosmosis's avatar
diosmosis a validé

        // Activate them
        foreach($pluginsManager->getLoadedPlugins() as $plugin) {
            $name = $plugin->getPluginName();
diosmosis's avatar
diosmosis a validé
            if (!$pluginsManager->isPluginActivated($name)) {
                $pluginsManager->activatePlugin($name);
            }
        }
    }

    public static function unloadAllPlugins()
    {
        try {
            $manager = \Piwik\Plugin\Manager::getInstance();
            $plugins = $manager->getLoadedPlugins();
Christian Raue's avatar
Christian Raue a validé
            foreach ($plugins as $plugin) {
diosmosis's avatar
diosmosis a validé
            }
            \Piwik\Plugin\Manager::getInstance()->unloadPlugins();
        } catch (Exception $e) {
        }
    }
    /**
     * Creates a website, then sets its creation date to a day earlier than specified dateTime
     * Useful to create a website now, but force data to be archived back in the past.
     *
     * @param string $dateTime eg '2010-01-01 12:34:56'
     * @param int $ecommerce
     * @param string $siteName
sgiehl's avatar
sgiehl a validé
     * @param bool|string $siteUrl
     * @param int $siteSearch
     * @param null|string $searchKeywordParameters
     * @param null|string $searchCategoryParameters
     * @return int    idSite of website created
     */
    public static function createWebsite($dateTime, $ecommerce = 0, $siteName = false, $siteUrl = false,
                                         $siteSearch = 1, $searchKeywordParameters = null,
                                         $searchCategoryParameters = null, $timezone = null)
        if($siteName === false) {
            $siteName = self::DEFAULT_SITE_NAME;
        }
        $idSite = APISitesManager::getInstance()->addSite(
            $siteName,
            $siteUrl === false ? "http://piwik.net/" : $siteUrl,
            $ecommerce,
            $siteSearch, $searchKeywordParameters, $searchCategoryParameters,
            $ips = null,
            $excludedQueryParameters = null,
            $currency = null
        );

        // Manually set the website creation date to a day earlier than the earliest day we record stats for
        Db::get()->update(Common::prefixTable("site"),
diosmosis's avatar
diosmosis a validé
            array('ts_created' => Date::factory($dateTime)->subDay(1)->getDatetime()),
            "idsite = $idSite"
        );

        // Clear the memory Website cache
        Site::clearCache();
    /**
     * Returns URL to Piwik root.
     *
     * @return string
     */
    public static function getRootUrl()
    {
        $piwikUrl = Url::getCurrentUrlWithoutFileName();

        $pathBeforeRoot = 'tests';
        // Running from a plugin
        if (strpos($piwikUrl, 'plugins/') !== false) {
            $pathBeforeRoot = 'plugins';
        }

        $testsInPath = strpos($piwikUrl, $pathBeforeRoot . '/');
        if ($testsInPath !== false) {
            $piwikUrl = substr($piwikUrl, 0, $testsInPath);
        }

        // in case force_ssl=1, or assume_secure_protocol=1, is set in tests
        // we don't want to require Travis CI or devs to setup HTTPS on their local machine
        $piwikUrl = str_replace("https://", "http://", $piwikUrl);

        return $piwikUrl;
    }

    /**
     * Returns URL to the proxy script, used to ensure piwik.php
     * uses the test environment, and allows variable overwriting
     *
     * @return string
     */
    public static function getTrackerUrl()
    {
        return self::getRootUrl() . 'tests/PHPUnit/proxy/piwik.php';
    }

    /**
     * Returns a PiwikTracker object that you can then use to track pages or goals.
     *
sgiehl's avatar
sgiehl a validé
     * @param int     $idSite
     * @param string  $dateTime
     * @param boolean $defaultInit If set to true, the tracker object will have default IP, user agent, time, resolution, etc.
sgiehl's avatar
sgiehl a validé
     * @param bool    $useLocal
    public static function getTracker($idSite, $dateTime, $defaultInit = true, $useLocal = false)
        if ($useLocal) {
            require_once PIWIK_INCLUDE_PATH . '/tests/LocalTracker.php';
            $t = new Piwik_LocalTracker($idSite, self::getTrackerUrl());
        } else {
            $t = new PiwikTracker($idSite, self::getTrackerUrl());
            $t->setTokenAuth(self::getTokenAuth());
            $t->setIp('156.5.3.2');

            // Optional tracking
            $t->setUserAgent("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 (.NET CLR 3.5.30729)");
            $t->setLocalTime('12:34:06');
            $t->setResolution(1024, 768);
            $t->setBrowserHasCookies(true);
            $t->setPlugins($flash = true, $java = true, $director = false);
        }
        return $t;
    }

     * Checks that the response is a GIF image as expected.
     * Will fail the test if the response is not the expected GIF
     *
     * @param $response
     */
    public static function checkResponse($response)
    {
        $trans_gif_64 = "R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
        $expectedResponse = base64_decode($trans_gif_64);

        $url = "\n =========================== \n URL was: " . PiwikTracker::$DEBUG_LAST_REQUESTED_URL;
        self::assertEquals($expectedResponse, $response, "Expected GIF beacon, got: <br/>\n"
            . var_export($response, true)
            . "\n If you are stuck, you can enable [Tracker] debug=1; in config.ini.php to get more debug info."
    /**
     * Checks that the response from bulk tracking is a valid JSON
     * string. Will fail the test if JSON status is not success.
     *
     * @param $response
     */
    public static function checkBulkTrackingResponse($response) {
        $data = json_decode($response, true);
        if (!is_array($data) || empty($response)) {
            throw new Exception("Bulk tracking response (".$response.") is not an array: " . var_export($data, true) . "\n");
        }
        if(!isset($data['status'])) {
            throw new Exception("Returned data didn't have a status: " . var_export($data,true));
        self::assertArrayHasKey('status', $data);
mattab's avatar
mattab a validé
        self::assertEquals('success', $data['status'], "expected success, got: " . var_export($data, true));
    public static function makeLocation($city, $region, $country, $lat = null, $long = null, $isp = null)
        return array(LocationProvider::CITY_NAME_KEY    => $city,
                     LocationProvider::REGION_CODE_KEY  => $region,
                     LocationProvider::COUNTRY_CODE_KEY => $country,
                     LocationProvider::LATITUDE_KEY     => $lat,
                     LocationProvider::LONGITUDE_KEY    => $long,
                     LocationProvider::ISP_KEY          => $isp);
     * Returns the Super User token auth that can be used in tests. Can be used to
     * do bulk tracking.
     *
     * @return string
     */
    public static function getTokenAuth()
    {
        return APIUsersManager::getInstance()->getTokenAuth(
            self::ADMIN_USER_LOGIN,
            UsersManager::getPasswordHash(self::ADMIN_USER_PASSWORD)
        );
    public static function createSuperUser($removeExisting = true)
diosmosis's avatar
diosmosis a validé
        $login = self::ADMIN_USER_LOGIN;
        $password = UsersManager::getPasswordHash(self::ADMIN_USER_PASSWORD);
diosmosis's avatar
diosmosis a validé
        $token = self::getTokenAuth();

        $model = new \Piwik\Plugins\UsersManager\Model();
        if ($removeExisting) {
            $model->deleteUserOnly($login);
        }


        if (empty($user)) {
            $model->addUser($login, $password, 'hello@example.org', $login, $token, Date::now()->getDatetime());
        } else {
            $model->updateUser($login, $password, 'hello@example.org', $login, $token);
        }

        if (empty($user['superuser_access'])) {
            $model->setSuperUserAccess($login, true);
        }

        return $model->getUserByTokenAuth($token);
     * Create three MAIL and two MOBILE scheduled reports
     *
     * Reports sent by mail can contain PNG graphs when the user specifies it.
     * Depending on the system under test, generated images differ slightly.
     * Because of this discrepancy, PNG graphs are only tested if the system under test
Julien Moumné's avatar
Julien Moumné a validé
     * has the characteristics described in 'canImagesBeIncludedInScheduledReports'.
     * See tests/README.md for more detail.
     *
     * @see canImagesBeIncludedInScheduledReports
     * @param int $idSite id of website created
     */
    public static function setUpScheduledReports($idSite)
    {
        // fake access is needed so API methods can call Piwik::getCurrentUserLogin(), e.g: 'ScheduledReports.addReport'
        $pseudoMockAccess = new FakeAccess;
        FakeAccess::$superUser = true;
        Access::setSingletonInstance($pseudoMockAccess);
        $availableReportMetadata = APIScheduledReports::getReportMetadata($idSite, ScheduledReports::EMAIL_TYPE);

        $availableReportIds = array();
        foreach ($availableReportMetadata as $reportMetadata) {
            $availableReportIds[] = $reportMetadata['uniqueId'];
        }

        //@review should we also test evolution graphs?
        // set-up mail report
        APIScheduledReports::getInstance()->addReport(
            $idSite,
            'Mail Test report',
            'day', // overridden in getApiForTestingScheduledReports()
            0,
            ScheduledReports::EMAIL_TYPE,
            ReportRenderer::HTML_FORMAT, // overridden in getApiForTestingScheduledReports()
            array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY)
        );

        // set-up sms report for one website
        APIScheduledReports::getInstance()->addReport(
            $idSite,
            'SMS Test report, one website',
            'day', // overridden in getApiForTestingScheduledReports()
            0,
            MobileMessaging::MOBILE_TYPE,
            MobileMessaging::SMS_FORMAT,
            array("MultiSites_getOne"),
            array("phoneNumbers" => array())
        );

        // set-up sms report for all websites
        APIScheduledReports::getInstance()->addReport(
            $idSite,
            'SMS Test report, all websites',
            'day', // overridden in getApiForTestingScheduledReports()
            0,
            MobileMessaging::MOBILE_TYPE,
            MobileMessaging::SMS_FORMAT,
            array("MultiSites_getAll"),
            array("phoneNumbers" => array())
        );

        if (self::canImagesBeIncludedInScheduledReports()) {
            // set-up mail report with images
            APIScheduledReports::getInstance()->addReport(
                $idSite,
                'Mail Test report',
                'day', // overridden in getApiForTestingScheduledReports()
                0,
                ScheduledReports::EMAIL_TYPE,
                ReportRenderer::HTML_FORMAT, // overridden in getApiForTestingScheduledReports()
                array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_AND_GRAPHS)
            );

            // set-up mail report with one row evolution based png graph
            APIScheduledReports::getInstance()->addReport(
                $idSite,
                'Mail Test report',
                'day',
                0,
                ScheduledReports::EMAIL_TYPE,
                array('Actions_getPageTitles'),
                array(
                     ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_GRAPHS_ONLY,
                     ScheduledReports::EVOLUTION_GRAPH_PARAMETER => 'true',
mattab's avatar
mattab a validé
     * Return true if system under test has Piwik core team's most common configuration
     */
    public static function canImagesBeIncludedInScheduledReports()
    {
        $gdInfo = gd_info();
        return
            stristr(php_uname(), self::IMAGES_GENERATED_ONLY_FOR_OS) &&
mattab's avatar
mattab a validé
            strpos( phpversion(), self::IMAGES_GENERATED_FOR_PHP) !== false &&
            strpos( $gdInfo['GD Version'], self::IMAGES_GENERATED_FOR_GD) !== false;
    }

    public static $geoIpDbUrl = 'http://piwik-team.s3.amazonaws.com/GeoIP.dat.gz';
    public static $geoLiteCityDbUrl = 'http://piwik-team.s3.amazonaws.com/GeoLiteCity.dat.gz';

    public static function downloadGeoIpDbs()
    {
        $geoIpOutputDir = PIWIK_INCLUDE_PATH . '/tests/lib/geoip-files';
        self::downloadAndUnzip(self::$geoIpDbUrl, $geoIpOutputDir, 'GeoIP.dat');
        self::downloadAndUnzip(self::$geoLiteCityDbUrl, $geoIpOutputDir, 'GeoIPCity.dat');
    }

    public static function downloadAndUnzip($url, $outputDir, $filename)
    {
        $bufferSize = 1024 * 1024;

        if (!is_dir($outputDir)) {
            mkdir($outputDir);
        }

        $deflatedOut = $outputDir . '/' . $filename;
        $outfileName = $deflatedOut . '.gz';

        if (file_exists($deflatedOut)) {
            return;
        }

        $dump = fopen($url, 'rb');
        $outfile = fopen($outfileName, 'wb');
        while (!feof($dump)) {
            fwrite($outfile, fread($dump, $bufferSize), $bufferSize);
        }
        fclose($dump);
        fclose($outfile);

        // unzip the dump
        exec("gunzip -c \"" . $outfileName . "\" > \"$deflatedOut\"", $output, $return);
        if ($return !== 0) {
diosmosis's avatar
diosmosis a validé
            Log::info("gunzip failed with file that has following contents:");
            Log::info(file_get_contents($outfile));

            throw new Exception("gunzip failed($return): " . implode("\n", $output));
        }
mattab's avatar
mattab a validé

    protected static function executeLogImporter($logFile, $options)
    {
mattab's avatar
mattab a validé

        // create the command
        $cmd = $python
            . ' "' . PIWIK_INCLUDE_PATH . '/misc/log-analytics/import_logs.py" ' # script loc
            . '-ddd ' // debug
            . '--url="' . self::getRootUrl() . 'tests/PHPUnit/proxy/" ' # proxy so that piwik uses test config files
        ;

        foreach ($options as $name => $value) {
            $cmd .= $name;
            if ($value !== false) {
                $cmd .= '="' . $value . '"';
            }
            $cmd .= ' ';
        }

        $cmd .= '"' . $logFile . '" 2>&1';

        // run the command
        exec($cmd, $output, $result);
        if ($result !== 0) {
            throw new Exception("log importer failed: " . implode("\n", $output) . "\n\ncommand used: $cmd");
        }

        return $output;
    }

    public static function siteCreated($idSite)
    {
        return Db::fetchOne("SELECT COUNT(*) FROM " . Common::prefixTable('site') . " WHERE idsite = ?", array($idSite)) != 0;
    }

    public static function goalExists($idSite, $idGoal)
    {
        return Db::fetchOne("SELECT COUNT(*) FROM " . Common::prefixTable('goal') . " WHERE idgoal = ? AND idsite = ?", array($idGoal, $idSite)) != 0;
    }
diosmosis's avatar
diosmosis a validé

    /**
     * Connects to MySQL w/o specifying a database.
     */
    public static function connectWithoutDatabase()
    {
        $dbConfig = Config::getInstance()->database;
        $oldDbName = $dbConfig['dbname'];
        $dbConfig['dbname'] = null;

        Db::createDatabaseObject($dbConfig);

        $dbConfig['dbname'] = $oldDbName;
    }

    /**
     * Sets up access instance.
     */
    public static function createAccessInstance()
    {
        Access::setSingletonInstance(null);
        Access::getInstance();
        Piwik::postEvent('Request.initAuthenticationObject');
    }
diosmosis's avatar
diosmosis a validé

    public function dropDatabase($dbName = null)
diosmosis's avatar
diosmosis a validé
    {
        $dbName = $dbName ?: $this->dbName ?: Config::getInstance()->database_tests['dbname'];
diosmosis's avatar
diosmosis a validé
        $config = _parse_ini_file(PIWIK_INCLUDE_PATH . '/config/config.ini.php', true);
        $originalDbName = $config['database']['dbname'];
        if ($dbName == $originalDbName
            && $dbName != 'piwik_tests'
diosmosis's avatar
diosmosis a validé
        ) { // santity check
            throw new \Exception("Trying to drop original database '$originalDbName'. Something's wrong w/ the tests.");
diosmosis's avatar
diosmosis a validé
    }

    public function log($message)
    {
        if ($this->printToScreen) {
            echo $message . "\n";
        }
    }
diosmosis's avatar
diosmosis a validé

    // NOTE: since API_Request does sanitization, API methods do not. when calling them, we must
    // sometimes do sanitization ourselves.
    public static function makeXssContent($type, $sanitize = false)
    {
        $result = "<script>$('body').html('$type XSS!');</script>";
        if ($sanitize) {
            $result = Common::sanitizeInputValue($result);
        }
        return $result;
    }
    public static function updateDatabase($force = false)
        if ($force) {
            // remove version options to force update
            Option::deleteLike('version%');
            Option::set('version_core', '0.0');
        }

        $updater = new Updater();
        $componentsWithUpdateFile = CoreUpdater::getComponentUpdates($updater);
        if (empty($componentsWithUpdateFile)) {
            return false;
        }

        $result = CoreUpdater::updateComponents($updater, $componentsWithUpdateFile);
        if (!empty($result['coreError'])
            || !empty($result['warnings'])
            || !empty($result['errors'])
        ) {
            throw new \Exception("Failed to update database (errors or warnings found): " . print_r($result, true));
        }

        return $result;
    }
mattab's avatar
mattab a validé
}

// needed by tests that use stored segments w/ the proxy index.php
class OverrideLogin extends Access
mattab's avatar
mattab a validé
{
    public function getLogin()
    {
        return 'superUserLogin';
    }