Skip to content
This repository was archived by the owner on Jul 19, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 27 additions & 102 deletions Commands/MigrateSite.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@

class MigrateSite extends ConsoleCommand
{
protected static $DB_CONFIG_MAPPING = array(
'host' => 'db-host',
'username' => 'db-username',
'password' => 'db-password',
'dbname' => 'db-name',
'port' => 'db-port',
'tables_prefix' => 'db-prefix'
);

protected function configure()
{
$this->setName('migration:site');
Expand Down Expand Up @@ -59,35 +68,37 @@ protected function configure()

protected function execute(InputInterface $input, OutputInterface $output)
{
$self = $this;

// Set memory limit to off
@ini_set('memory_limit', -1);
Piwik::doAsSuperUser(function() use ($input, $output){
Piwik::doAsSuperUser(function() use ($input, $output, $self){
$settings = new MigratorSettings();
$settings->idSite = $input->getArgument('idSite');
$settings->site = $this->getSite($settings->idSite);
$settings->site = $self->getSite($settings->idSite);
$settings->dateFrom = $input->getOption('date-from') ? new \DateTime($input->getOption('date-from')) : null;
$settings->dateTo = $input->getOption('date-to') ? new \DateTime($input->getOption('date-to')) : null;
$settings->skipArchiveData = $input->getOption('skip-archive-data');
$settings->skipLogData = $input->getOption('skip-log-data');

$config = Db::getDatabaseConfig();
$localConfig = Db::getDatabaseConfig();
$startTime = microtime(true);

$this->createTargetDatabaseConfig($input, $output, $config);
$targetConfig = $self->createTargetDatabaseConfig($input, $output, $localConfig);

$tmpConfig = $config;
$sourceDb = Db::get();
try {
$targetDb = @Db\Adapter::factory($config['adapter'], $tmpConfig);
$tmpTargetConfig = $targetConfig; //The factory removes some necessary keys
$targetDb = @Db\Adapter::factory($targetConfig['adapter'], $tmpTargetConfig);
} catch (\Exception $e) {
throw new \RuntimeException('Unable to connect to the target database: ' . $e->getMessage(), 0, $e);
}

$sourceDbHelper = new DBHelper($sourceDb, Db::getDatabaseConfig());
$sourceDbHelper = new DBHelper($sourceDb, $localConfig);

$migratorFacade = new Migrator(
$sourceDbHelper,
new DBHelper($targetDb, $config),
new DBHelper($targetDb, $targetConfig),
GCHelper::getInstance(),
$settings,
new ArchiveLister($sourceDbHelper)
Expand All @@ -103,7 +114,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}


protected function getSite($idSite)
public function getSite($idSite)
{
if (!Site::getSite($idSite)) {
throw new \InvalidArgumentException('idSite is not a valid, no such site found');
Expand All @@ -115,101 +126,15 @@ protected function getSite($idSite)
);
}

private function createTargetDatabaseConfig(InputInterface $input, OutputInterface $output, &$config)
public function createTargetDatabaseConfig(InputInterface $input, OutputInterface $output, $baseConfig)
{
$notNullValidator = function ($answer) {
if (strlen(trim($answer)) == 0) {
throw new \InvalidArgumentException('This value should not be empty');
}

return $answer;
};

$dummyValidator = function ($answer) {
return $answer;
};

$config['host'] = $this->ensureOptionsIsProvided(
'db-host',
$input,
$output,
'Please provide the destination database host',
$notNullValidator,
false,
'localhost'
);

$config['username'] = $this->ensureOptionsIsProvided(
'db-username',
$input,
$output,
'Please provide the destination database username',
$notNullValidator
);

$config['password'] = $this->ensureOptionsIsProvided(
'db-password',
$input,
$output,
'Please provide the destination database password',
$dummyValidator,
false,
null,
true
);

$config['dbname'] = $this->ensureOptionsIsProvided(
'db-name',
$input,
$output,
'Please provide the destination database name',
$notNullValidator
);

$config['port'] = $input->getOption('db-port');
$config['tables_prefix'] = $input->getOption('db-prefix');
}

public function ensureOptionsIsProvided($optionName, InputInterface $input, OutputInterface $output, $question, $validator, $attempts = false, $default = null, $hidden = false)
{
if (!$input->getOption($optionName)) {
return $this->askAndValidate($output, $question, $validator, $attempts, $default, $hidden);
foreach (static::$DB_CONFIG_MAPPING as $configKey => $configParam) {
$option = $input->getOption($configParam);
if ($option) {
$baseConfig[$configKey] = $option;
};
}

return $input->getOption($optionName);
}

protected function askAndValidate(
OutputInterface $output,
$question,
$validator,
$attempts = false,
$default = null,
$hidden = false
)
{
/**
* @var $dialog DialogHelper
*/
$dialog = $this->getHelperSet()->get('dialog');
$question = '<question>' . $question . (($default) ? " [$default]" : '') . ':</question> ';

if (!$hidden) {
return $dialog->askAndValidate(
$output,
$question,
$validator,
$attempts,
$default
);
} else {
return $dialog->askHiddenResponseAndValidate(
$output,
$question,
$validator,
$attempts,
$default
);
}
return $baseConfig;
}
}
7 changes: 5 additions & 2 deletions Migrator/ActionMigrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,15 @@ public function ensureActionIsMigrated($idAction)

public function getNewId($idAction)
{
if($idAction == null || $idAction < 1){
return $idAction;
}

if ($this->ensureActionIsMigrated($idAction)) {
return $this->idMap[$idAction];
} else {
return 0;
throw new \InvalidArgumentException('Id ' . $idAction . ' not found in ' . __CLASS__);
}

}

/**
Expand Down
4 changes: 0 additions & 4 deletions Migrator/ConversionItemMigrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ protected function translateRow(&$row)
$row['idvisit'] = $this->visitMigrator->getNewId($row['idvisit']);

foreach ($this->actionsToTranslate as $translationKey) {
if ($row[$translationKey] == 0) {
continue;
}

$row[$translationKey] = $this->actionMigrator->getNewId($row[$translationKey]);
}
}
Expand Down
8 changes: 1 addition & 7 deletions Migrator/ConversionMigrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,7 @@ protected function translateRow(&$row)
$row['idlink_va'] = $this->linkVisitActionMigrator->getNewId($row['idlink_va']);
}

if ($row['idaction_url']) {
$row['idaction_url'] = $this->actionMigrator->getNewId(
$row['idaction_url']
);
} else {
$row['idaction_url'] = 0;
}
$row['idaction_url'] = $this->actionMigrator->getNewId( $row['idaction_url']);
}

/**
Expand Down
38 changes: 30 additions & 8 deletions Migrator/Migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,19 @@ private function migrateSiteConfig()

$this->siteMigrator->migrate(
$this->getBatchProvider(
'SELECT * FROM ' . $this->sourceDbHelper->prefixTable('site') . ' WHERE idsite = ' . $this->settings->idSite
'SELECT * FROM ' . $this->sourceDbHelper->prefixTable('site') . ' WHERE idsite = ' . $this->settings->idSite . ' ORDER BY idsite ASC'
)
);

$this->siteGoalMigrator->migrate(
$this->getBatchProvider(
'SELECT * FROM ' . $this->sourceDbHelper->prefixTable('goal') . ' WHERE idsite = ' . $this->settings->idSite
'SELECT * FROM ' . $this->sourceDbHelper->prefixTable('goal') . ' WHERE idsite = ' . $this->settings->idSite . ' ORDER BY idsite ASC, idgoal ASC'
)
);

$this->siteUrlMigrator->migrate(
$this->getBatchProvider(
'SELECT * FROM ' . $this->sourceDbHelper->prefixTable('site_url') . ' WHERE idsite = ' . $this->settings->idSite
'SELECT * FROM ' . $this->sourceDbHelper->prefixTable('site_url') . ' WHERE idsite = ' . $this->settings->idSite . ' ORDER BY idsite ASC, url ASC'
)
);
}
Expand All @@ -177,6 +177,8 @@ private function migrateLogVisits()
$query .= ' AND `visit_last_action_time` < \'' . $this->settings->dateTo->format('Y-m-d') . '\'';
}

$query .= ' ORDER BY idvisit ASC';

$this->visitMigrator->migrate(
$this->getBatchProvider($query)
);
Expand All @@ -186,7 +188,7 @@ private function migrateLogVisitActions()
{
Log::info('Migrating log data - link visit action');

$queries = $this->getLogVisitQueriesFor('log_link_visit_action');
$queries = $this->getLogVisitQueriesForLinkVisitAction();

if (count($queries) > 0) {
$this->visitActionMigrator->migrate($this->getBatchProvider($queries));
Expand All @@ -197,8 +199,8 @@ private function migrateLogVisitConversions()
{
Log::info('Migrating log data - conversions and conversion items');

$queries = $this->getLogVisitQueriesFor('log_conversion');
$itemQueries = $this->getLogVisitQueriesFor('log_conversion_item');
$queries = $this->getLogVisitQueriesForLogConversion();
$itemQueries = $this->getLogVisitQueriesForLogConversionItem();

if (count($queries) > 0) {
$this->conversionMigrator->migrate($this->getBatchProvider($queries));
Expand All @@ -213,7 +215,7 @@ private function migrateArchives()
$this->archiveMigrator->migrate($this->settings->idSite, $this->settings->dateFrom, $this->settings->dateTo);
}

private function getLogVisitQueriesFor($table)
private function getLogVisitQueriesFor($table, $orderBy = array())
{
$visitIdRanges = $this->visitMigrator->getIdRanges();

Expand All @@ -223,7 +225,13 @@ private function getLogVisitQueriesFor($table)


foreach ($visitIdRanges as $range) {
$queries[] = $baseQuery . ' (' . implode(', ', $range) . ')';
$newQuery = $baseQuery . ' (' . implode(', ', $range) . ')';

if (count($orderBy) != 0) {
$newQuery .= ' ORDER BY ' . implode(',', $orderBy);
}

$queries[] = $newQuery;
}

return $queries;
Expand All @@ -232,6 +240,20 @@ private function getLogVisitQueriesFor($table)
}
}

private function getLogVisitQueriesForLogConversion()
{
return $this->getLogVisitQueriesFor('log_conversion', array('idvisit', 'idgoal', 'buster'));
}

private function getLogVisitQueriesForLogConversionItem(){
return $this->getLogVisitQueriesFor('log_conversion_item', array('idvisit', 'idorder', 'idaction_sku'));
}

private function getLogVisitQueriesForLinkVisitAction()
{
return $this->getLogVisitQueriesFor('log_link_visit_action', array('idlink_va'));
}

private function getBatchProvider($query)
{
return new BatchProvider($query, $this->sourceDbHelper, $this->gcHelper, 10000);
Expand Down
54 changes: 54 additions & 0 deletions Test/Fixture/AbstractTableFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/**
* Abraxas Medien
* Developer: Adrian Tello
* Date: 01.10.15
* Time: 14:14
*/

namespace Piwik\Plugins\SiteMigration\Test\Fixture;

use Piwik\Common;
use Piwik\Db;
use Piwik\Tests\Framework\Fixture;

abstract class AbstractTableFixture extends Fixture {

public $data = array();

public function setUp()
{
parent::setUp();

$this->compatData();
$this->insertTables($this->data);
}

protected function compatData()
{
//Remove exclude_unknown_urls if using a core version lower than 2.15.0-b3
if (!file_exists(PIWIK_DOCUMENT_ROOT . '/core/Updates/2.15.0-b3.php')) {
foreach ($this->data['site']['data'] as &$row) {
unset($row['exclude_unknown_urls']);
}
}
}

protected function insertTables()
{
foreach ($this->data as $tableName => $table) {
$prefixedTable = Common::prefixTable($tableName);
foreach ($table['data'] as $row) {
$placeholders = array_map(function () { return "?"; }, $row);
$columns = array_keys($row);
foreach ($columns as &$column){
$column = '`' . $column . '`';
}

$sql = "INSERT INTO $prefixedTable (" . implode(',', $columns) . ") VALUES (" . implode(',', $placeholders) . ")";
Db::query($sql, array_values($row));
}
}
}

}
Loading