diff options
10 files changed, 679 insertions, 242 deletions
diff --git a/core/DataAccess/RawLogFetcher.php b/core/DataAccess/RawLogFetcher.php index ec1f7d14ce..0a867e24a3 100644 --- a/core/DataAccess/RawLogFetcher.php +++ b/core/DataAccess/RawLogFetcher.php @@ -22,7 +22,7 @@ class RawLogFetcher * @param array $fields * @param int $fromId * @param int $limit - * @return array + * @return array[] */ public function getVisitsWithDatesLimit($from, $to, $fields = array(), $fromId = 0, $limit = 1000) { diff --git a/core/DataAccess/RawLogUpdater.php b/core/DataAccess/RawLogUpdater.php index 7d54fbbfe2..a19ce52e94 100644 --- a/core/DataAccess/RawLogUpdater.php +++ b/core/DataAccess/RawLogUpdater.php @@ -21,7 +21,7 @@ class RawLogUpdater { $sql = "UPDATE " . Common::prefixTable('log_visit') . " SET " . $this->getColumnSetExpressions(array_keys($values)) - . "WHERE idvisit = ?"; + . " WHERE idvisit = ?"; $this->update($sql, $values, $idVisit); } @@ -32,11 +32,9 @@ class RawLogUpdater */ public function updateConversions(array $values, $idVisit) { - $sql = array( - "UPDATE " . Common::prefixTable('log_conversion'), - "SET " . $this->getColumnSetExpressions(array_keys($values)), - "WHERE idvisit = ?" - ); + $sql = "UPDATE " . Common::prefixTable('log_conversion') + . " SET " . $this->getColumnSetExpressions(array_keys($values)) + . " WHERE idvisit = ?"; $this->update($sql, $values, $idVisit); } diff --git a/plugins/UserCountry/Commands/AttributeHistoricalDataWithLocations.php b/plugins/UserCountry/Commands/AttributeHistoricalDataWithLocations.php index bf1d2aabc2..dc2221573f 100644 --- a/plugins/UserCountry/Commands/AttributeHistoricalDataWithLocations.php +++ b/plugins/UserCountry/Commands/AttributeHistoricalDataWithLocations.php @@ -14,6 +14,7 @@ use Piwik\Plugin\ConsoleCommand; use Piwik\Plugins\UserCountry\VisitorGeolocator; use Piwik\Plugins\UserCountry\LocationProvider; use Piwik\DataAccess\RawLogFetcher; +use Piwik\Timer; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -22,18 +23,24 @@ use Symfony\Component\Console\Output\OutputInterface; class AttributeHistoricalDataWithLocations extends ConsoleCommand { const DATES_RANGE_ARGUMENT = 'dates-range'; - const PERCENT_STEP_ARGUMENT = 'percent-step'; - const PERCENT_STEP_ARGUMENT_DEFAULT = 5; - const PROVIDER_ARGUMENT = 'provider'; - - const SEGMENT_LIMIT_OPTION = 'segmentLimit'; - + const SEGMENT_LIMIT_OPTION = 'segment-limit'; const SEGMENT_LIMIT_OPTION_DEFAULT = 1000; /** + * @var string[] + */ + private static $logVisitFieldsToUpdate = array( + 'location_country' => LocationProvider::COUNTRY_CODE_KEY, + 'location_region' => LocationProvider::REGION_CODE_KEY, + 'location_city' => LocationProvider::CITY_NAME_KEY, + 'location_latitude' => LocationProvider::LATITUDE_KEY, + 'location_longitude' => LocationProvider::LONGITUDE_KEY + ); + + /** * @var RawLogFetcher */ protected $fetcher; @@ -46,7 +53,7 @@ class AttributeHistoricalDataWithLocations extends ConsoleCommand /** * @var VisitorGeolocator */ - protected $locationFetcher; + protected $visitorGeolocator; /** * @var int @@ -59,9 +66,9 @@ class AttributeHistoricalDataWithLocations extends ConsoleCommand private $amountOfVisits; /** - * @var int + * @var Timer */ - private $start; + private $timer; /** * @var int @@ -69,54 +76,29 @@ class AttributeHistoricalDataWithLocations extends ConsoleCommand private $percentStep; /** - * @var array + * @var int */ - private $percentConfirmed = array(); + private $processedPercent = 0; - /** - * @var array - */ - protected $logVisitFieldsToUpdate = array( - 'location_country' => LocationProvider::COUNTRY_CODE_KEY, - 'location_region' => LocationProvider::REGION_CODE_KEY, - 'location_city' => LocationProvider::CITY_NAME_KEY, - 'location_latitude' => LocationProvider::LATITUDE_KEY, - 'location_longitude' => LocationProvider::LONGITUDE_KEY - ); + public function __construct(RawLogFetcher $fetcher = null, RawLogUpdater $updater = null) + { + parent::__construct(); + + $this->fetcher = $fetcher ?: new RawLogFetcher(); + $this->updater = $updater ?: new RawLogUpdater(); + } protected function configure() { $this->setName('usercountry:attribute'); - $this->addArgument( - self::DATES_RANGE_ARGUMENT, - InputArgument::REQUIRED, - 'Attribute visits from this dates.' - ); - - $this->addArgument( - self::PERCENT_STEP_ARGUMENT, - InputArgument::OPTIONAL, - 'How often command should write about current state.', - self::PERCENT_STEP_ARGUMENT_DEFAULT - ); - - $this->addArgument( - self::PROVIDER_ARGUMENT, - InputArgument::OPTIONAL, - 'Provider id which should be used to attribute visits. If empty then Piwik will use default provider.' - ); - - $this->addOption( - self::SEGMENT_LIMIT_OPTION, - null, - InputOption::VALUE_OPTIONAL, - 'Number of segments in single iteration.', - self::SEGMENT_LIMIT_OPTION_DEFAULT - ); - - $this->fetcher = new RawLogFetcher(); - $this->updater = new RawLogUpdater(); + $this->addArgument(self::DATES_RANGE_ARGUMENT, InputArgument::REQUIRED, 'Attribute visits in this date range. Eg, 2012-01-01,2013-01-01'); + $this->addArgument(self::PERCENT_STEP_ARGUMENT, InputArgument::OPTIONAL, + 'How often to display the command progress. A status update will be printed after N percent of visits are processed, ' + . 'where N is the value of this option.', self::PERCENT_STEP_ARGUMENT_DEFAULT); + $this->addArgument(self::PROVIDER_ARGUMENT, InputArgument::OPTIONAL, 'Provider id which should be used to attribute visits. If empty then' + . ' Piwik will use the currently configured provider. If no provider is configured, the default provider is used.'); + $this->addOption(self::SEGMENT_LIMIT_OPTION, null, InputOption::VALUE_OPTIONAL, 'Number of visits to process at a time.', self::SEGMENT_LIMIT_OPTION_DEFAULT); } /** @@ -126,96 +108,65 @@ class AttributeHistoricalDataWithLocations extends ConsoleCommand */ protected function execute(InputInterface $input, OutputInterface $output) { - $from = $this->getDateArgument($input, self::DATES_RANGE_ARGUMENT, 0); - $to = $this->getDateArgument($input, self::DATES_RANGE_ARGUMENT, 1); - $segmentLimit = $input->getOption(self::SEGMENT_LIMIT_OPTION); + list($from, $to) = $this->getDateRangeToAttribute($input); + + $this->visitorGeolocator = $this->createGeolocator($input); $this->percentStep = $this->getPercentStep($input); $this->amountOfVisits = $this->fetcher->countVisitsWithDatesLimit($from, $to); - if (!$from || !$to) { - $output->writeln( - sprintf('Invalid from [%s] or to [%s].', - $from, $to - ) - ); - - return 1; - } - - $providerId = $input->getArgument(self::PROVIDER_ARGUMENT); - $this->locationFetcher = new VisitorGeolocator(LocationProvider::getProviderById($providerId) ?: null); - $output->writeln( sprintf('Re-attribution for date range: %s to %s. %d visits to process with provider "%s".', - $from, $to, $this->amountOfVisits, $this->locationFetcher->getProvider()->getId() - ) + $from, $to, $this->amountOfVisits, $this->visitorGeolocator->getProvider()->getId()) ); - $this->start = time(); - $lastId = 0; - $visitFields = array_merge( - array('idvisit', 'location_ip'), - array_keys($this->logVisitFieldsToUpdate) - ); + $this->timer = new Timer(); - do { - $logs = $this->fetcher->getVisitsWithDatesLimit($from, $to, $visitFields, $lastId, $segmentLimit); - if (!empty($logs)) { - $lastId = $logs[count($logs) - 1]['idvisit']; - } + $this->processSpecifiedLogsInChunks($output, $from, $to, $input->getOption(self::SEGMENT_LIMIT_OPTION)); - /** - * @var array $row - */ - foreach ($logs as $row) { - if (!$this->isRowComplete($output, $row)) { - continue; - } + $output->writeln("Completed. <comment>" . $this->timer->__toString() . "</comment>"); - $idVisit = $row['idvisit']; - $ip = IPUtils::binaryToStringIP($row['location_ip']); - $values = $this->parseRowIntoValues($row, $ip); + return 0; + } - ++$this->processed; - $this->trackProgress($output); + protected function processSpecifiedLogsInChunks(OutputInterface $output, $from, $to, $segmentLimit) + { + $visitFieldsToSelect = array_merge(array('idvisit', 'location_ip'), array_keys(self::$logVisitFieldsToUpdate)); - if ($this->shouldSkipAttribution($output, $values, (string) $idVisit, $ip)) { - continue; - } + $lastId = 0; + do { + $logs = $this->fetcher->getVisitsWithDatesLimit($from, $to, $visitFieldsToSelect, $lastId, $segmentLimit); + if (!empty($logs)) { + $lastId = $logs[count($logs) - 1]['idvisit']; - if ($output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { - $output->writeln( - sprintf('Updating visit with idvisit = %s and ip = %s.', (string) $idVisit, $ip) - ); - } + $this->reattributeVisitLogs($output, $logs); + } + } while (count($logs) == $segmentLimit); + } - $this->updater->updateVisits($values, $idVisit); - $this->updater->updateConversions($values, $idVisit); + protected function reattributeVisitLogs(OutputInterface $output, $logRows) + { + foreach ($logRows as $row) { + if (!$this->isRowComplete($output, $row)) { + continue; } - } while (count($logs) == $segmentLimit); + $location = $this->getVisitLocation($row); + $valuesToUpdate = $this->getValuesToUpdate($row, $location); - $output->writeln(sprintf('Completed in %d seconds.', time() - $this->start)); + $this->onVisitProcessed($output); - return 0; - } + $idVisit = $row['idvisit']; - /** - * @param InputInterface $input - * @param string $name - * @param int $index - * @return string - */ - protected function getDateArgument(InputInterface $input, $name, $index) - { - $option = explode(',', $input->getArgument($name)); + if (empty($valuesToUpdate)) { + $this->writeIfVerbose($output, 'Nothing to update for idvisit = ' . $idVisit . '. Existing location info is same as geolocated.'); + } else { + $this->writeIfVerbose($output, 'Updating visit with idvisit = ' . $idVisit . '.'); - if (!isset($option[$index])) { - return false; + $this->updater->updateVisits($valuesToUpdate, $idVisit); + $this->updater->updateConversions($valuesToUpdate, $idVisit); + } } - - return date('Y-m-d', strtotime($option[$index])); } /** @@ -239,51 +190,52 @@ class AttributeHistoricalDataWithLocations extends ConsoleCommand } /** - * Parse row into proper values. (only if provider found difference) + * Returns location log values that are different than the values currently in a log row. * - * @param array $row - * @param string $ip - * @return array + * @param array $row The visit row. + * @param array $location The location information. + * @return array The location properties to update. */ - protected function parseRowIntoValues(array $row, $ip) + protected function getValuesToUpdate(array $row, $location) { - $location = $this->locationFetcher->getLocation(array('ip' => $ip)); - - $values = array(); - foreach ($this->logVisitFieldsToUpdate as $column => $locationKey) { + $valuesToUpdate = array(); + foreach (self::$logVisitFieldsToUpdate as $column => $locationKey) { if (empty($location[$locationKey])) { continue; } - $locationAttribute = $location[$locationKey]; + $locationPropertyValue = $location[$locationKey]; + $existingPropertyValue = $row[$column]; if ($locationKey === LocationProvider::COUNTRY_CODE_KEY) { - if (strtolower($locationAttribute) != strtolower($row[$column])) { - $values[$column] = strtolower($locationAttribute); + if (strtolower($locationPropertyValue) != strtolower($existingPropertyValue)) { + $valuesToUpdate[$column] = strtolower($locationPropertyValue); } } else { - if ($locationAttribute != $row[$column]) { - $values[$column] = $locationAttribute; + if ($locationPropertyValue != $existingPropertyValue) { + $valuesToUpdate[$column] = $locationPropertyValue; } } } - return $values; + return $valuesToUpdate; } /** * Print information about progress. * @param OutputInterface $output */ - protected function trackProgress(OutputInterface $output) + protected function onVisitProcessed(OutputInterface $output) { + ++$this->processed; + $percent = ceil($this->processed / $this->amountOfVisits * 100); - if (!in_array($percent, $this->percentConfirmed, true) && $percent % $this->percentStep === 0) { - $output->writeln( - sprintf('%d%% processed. [in %d seconds]', $percent, time() - $this->start) - ); + if ($percent > $this->processedPercent + && $percent % $this->percentStep === 0 + ) { + $output->writeln(sprintf('%d%% processed. <comment>%s</comment>', $percent, $this->timer->__toString())); - $this->percentConfirmed[] = $percent; + $this->processedPercent = $percent; } } @@ -296,19 +248,13 @@ class AttributeHistoricalDataWithLocations extends ConsoleCommand protected function isRowComplete(OutputInterface $output, array $row) { if (empty($row['idvisit'])) { - if ($output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { - $output->writeln('Empty idvisit field. Skipping...'); - } + $this->writeIfVerbose($output, 'Empty idvisit field. Skipping...'); return false; } if (empty($row['location_ip'])) { - if ($output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { - $output->writeln( - sprintf('Empty location_ip field for idvisit = %s. Skipping...', (string) $row['idvisit']) - ); - } + $this->writeIfVerbose($output, sprintf('Empty location_ip field for idvisit = %s. Skipping...', (string) $row['idvisit'])); return false; } @@ -316,26 +262,37 @@ class AttributeHistoricalDataWithLocations extends ConsoleCommand return true; } - /** - * Check if given visit should be re attributed. - * @param OutputInterface $output - * @param array $values - * @param string $idVisit - * @param string $ip - * @return bool - */ - protected function shouldSkipAttribution(OutputInterface $output, array $values, $idVisit, $ip) + private function getVisitLocation($row) { - if (empty($values)) { - if ($output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { - $output->writeln( - sprintf('Visit with idvisit = %s and ip = %s is attributed. Skipping...', $idVisit, $ip) - ); - } + $ip = IPUtils::binaryToStringIP($row['location_ip']); + $location = $this->visitorGeolocator->getLocation(array('ip' => $ip)); + return $location; + } - return true; + private function getDateRangeToAttribute(InputInterface $input) + { + $dateRangeString = $input->getArgument(self::DATES_RANGE_ARGUMENT); + + $dates = explode(',', $dateRangeString); + $dates = array_map(array('Piwik\Date', 'factory'), $dates); + + if (count($dates) != 2) { + throw new \InvalidArgumentException('Invalid date range supplied: ' . $dateRangeString); } - return false; + return $dates; + } + + private function createGeolocator(InputInterface $input) + { + $providerId = $input->getArgument(self::PROVIDER_ARGUMENT); + return new VisitorGeolocator(LocationProvider::getProviderById($providerId) ?: null); + } + + private function writeIfVerbose(OutputInterface $output, $message) + { + if ($output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { + $output->writeln($message); + } } -} +}
\ No newline at end of file diff --git a/plugins/UserCountry/tests/System/AttributeHistoricalDataWithLocationsTest.php b/plugins/UserCountry/tests/System/AttributeHistoricalDataWithLocationsTest.php index 844d42f9e5..ec35e4657c 100644 --- a/plugins/UserCountry/tests/System/AttributeHistoricalDataWithLocationsTest.php +++ b/plugins/UserCountry/tests/System/AttributeHistoricalDataWithLocationsTest.php @@ -10,10 +10,12 @@ namespace Piwik\Plugins\UserCountry\Test\Integration; use Piwik\Common; use Piwik\Db; +use Piwik\Network\IPUtils; use Piwik\Piwik; use Piwik\Plugins\UserCountry\Commands\AttributeHistoricalDataWithLocations; use Piwik\Tests\Fixtures\ManyVisitsWithGeoIP; use Piwik\Tests\Framework\TestCase\IntegrationTestCase; +use Piwik\Translate; use Symfony\Component\Console\Application; use Symfony\Component\Console\Tester\CommandTester; @@ -55,6 +57,8 @@ class AttributeHistoricalDataWithLocationsTest extends IntegrationTestCase Db::query($sql); } + + self::$fixture->setLocationProvider('GeoIPCity.dat'); } /** @@ -66,11 +70,13 @@ class AttributeHistoricalDataWithLocationsTest extends IntegrationTestCase $this->executeCommand(null); } + /** + * @expectedException \Exception + * @expectedExceptionMessage General_ExceptionInvalidDateFormat + */ public function testExecute_ShouldReturnMessage_IfDatesAreInvalid() { - $this->assertEquals( - 'Invalid from [1970-01-01] or to [].' . "\n", $this->executeCommand('test') - ); + $this->executeCommand('test'); } public function testExecute_ShouldReturnEmptyWorkingProcessLogs_IfThereIsNoData() @@ -90,7 +96,7 @@ class AttributeHistoricalDataWithLocationsTest extends IntegrationTestCase $result ); - $this->assertRegExp('/100% processed. \[in [(0-9)+] seconds\]/', $result); + $this->assertRegExp('/100% processed. Time elapsed: [0-9.]+s/', $result); $queryParams = array( 'idSite' => self::$fixture->idSite, diff --git a/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getCity_month.xml b/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getCity_month.xml index 23c40113d8..4618daf140 100644 --- a/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getCity_month.xml +++ b/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getCity_month.xml @@ -1,34 +1,166 @@ <?xml version="1.0" encoding="utf-8" ?> <result> <row> - <label>Unknown</label> - <nb_visits>35</nb_visits> - <nb_actions>61</nb_actions> + <label>General_Unknown</label> + <nb_visits>22</nb_visits> + <nb_actions>39</nb_actions> <max_actions>3</max_actions> - <sum_visit_length>21437</sum_visit_length> - <bounce_count>18</bounce_count> + <sum_visit_length>13871</sum_visit_length> + <bounce_count>11</bounce_count> <goals> <row idgoal='1'> - <nb_conversions>35</nb_conversions> - <nb_visits_converted>35</nb_visits_converted> - <revenue>175</revenue> + <nb_conversions>22</nb_conversions> + <nb_visits_converted>22</nb_visits_converted> + <revenue>110</revenue> </row> <row idgoal='2'> - <nb_conversions>17</nb_conversions> - <nb_visits_converted>17</nb_visits_converted> - <revenue>85</revenue> + <nb_conversions>11</nb_conversions> + <nb_visits_converted>11</nb_visits_converted> + <revenue>55</revenue> </row> </goals> - <nb_conversions>52</nb_conversions> - <revenue>260</revenue> - <sum_daily_nb_uniq_visitors>18</sum_daily_nb_uniq_visitors> - <sum_daily_nb_users>1</sum_daily_nb_users> - <city_name>Unknown</city_name> + <nb_conversions>33</nb_conversions> + <revenue>165</revenue> + <sum_daily_nb_uniq_visitors>11</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <city_name>General_Unknown</city_name> <city>xx</city> <region>xx</region> <country>xx</country> - <country_name>Unknown</country_name> - <region_name>Unknown</region_name> + <country_name>General_Unknown</country_name> + <region_name>General_Unknown</region_name> <logo>plugins/UserCountry/images/flags/xx.png</logo> </row> + <row> + <label>Vancouver, British Columbia, UserCountry_country_ca</label> + <nb_visits>6</nb_visits> + <nb_actions>10</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>3783</sum_visit_length> + <bounce_count>3</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>6</nb_conversions> + <nb_visits_converted>6</nb_visits_converted> + <revenue>30</revenue> + </row> + <row idgoal='2'> + <nb_conversions>3</nb_conversions> + <nb_visits_converted>3</nb_visits_converted> + <revenue>15</revenue> + </row> + </goals> + <nb_conversions>9</nb_conversions> + <revenue>45</revenue> + <sum_daily_nb_uniq_visitors>3</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <lat>49.25</lat> + <long>-123.133</long> + <segment>city==Vancouver;regionCode==BC;countryCode==ca</segment> + <city_name>Vancouver</city_name> + <region>BC</region> + <country>ca</country> + <country_name>UserCountry_country_ca</country_name> + <region_name>British Columbia</region_name> + <logo>plugins/UserCountry/images/flags/ca.png</logo> + </row> + <row> + <label>Besançon, Franche-Comte, UserCountry_country_fr</label> + <nb_visits>3</nb_visits> + <nb_actions>5</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>2</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>3</nb_conversions> + <nb_visits_converted>3</nb_visits_converted> + <revenue>15</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>4</nb_conversions> + <revenue>20</revenue> + <sum_daily_nb_uniq_visitors>2</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>1</sum_daily_nb_users> + <lat>47.249</lat> + <long>6.018</long> + <segment>city==Besan%C3%A7on;regionCode==A6;countryCode==fr</segment> + <city_name>Besançon</city_name> + <region>A6</region> + <country>fr</country> + <country_name>UserCountry_country_fr</country_name> + <region_name>Franche-Comte</region_name> + <logo>plugins/UserCountry/images/flags/fr.png</logo> + </row> + <row> + <label>Lhasa, General_Unknown, UserCountry_country_ti</label> + <nb_visits>2</nb_visits> + <nb_actions>3</nb_actions> + <max_actions>2</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>1</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>3</nb_conversions> + <revenue>15</revenue> + <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <lat>29.65</lat> + <long>91.1</long> + <segment>city==Lhasa;regionCode==1;countryCode==ti</segment> + <city_name>Lhasa</city_name> + <region>1</region> + <country>ti</country> + <country_name>UserCountry_country_ti</country_name> + <region_name>General_Unknown</region_name> + <logo>plugins/UserCountry/images/flags/ti.png</logo> + </row> + <row> + <label>Rome, Lazio, UserCountry_country_it</label> + <nb_visits>2</nb_visits> + <nb_actions>4</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>1</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>3</nb_conversions> + <revenue>15</revenue> + <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <lat>41.9</lat> + <long>12.483</long> + <segment>city==Rome;regionCode==07;countryCode==it</segment> + <city_name>Rome</city_name> + <region>07</region> + <country>it</country> + <country_name>UserCountry_country_it</country_name> + <region_name>Lazio</region_name> + <logo>plugins/UserCountry/images/flags/it.png</logo> + </row> </result>
\ No newline at end of file diff --git a/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getContinent_month.xml b/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getContinent_month.xml index 5882ac249d..37261de820 100644 --- a/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getContinent_month.xml +++ b/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getContinent_month.xml @@ -1,28 +1,78 @@ <?xml version="1.0" encoding="utf-8" ?> <result> <row> - <label>North America</label> - <nb_visits>35</nb_visits> - <nb_actions>61</nb_actions> + <label>UserCountry_continent_asi</label> + <nb_visits>22</nb_visits> + <nb_actions>38</nb_actions> <max_actions>3</max_actions> - <sum_visit_length>21437</sum_visit_length> - <bounce_count>18</bounce_count> + <sum_visit_length>13871</sum_visit_length> + <bounce_count>11</bounce_count> <goals> <row idgoal='1'> - <nb_conversions>35</nb_conversions> - <nb_visits_converted>35</nb_visits_converted> - <revenue>175</revenue> + <nb_conversions>22</nb_conversions> + <nb_visits_converted>22</nb_visits_converted> + <revenue>110</revenue> </row> <row idgoal='2'> - <nb_conversions>17</nb_conversions> - <nb_visits_converted>17</nb_visits_converted> - <revenue>85</revenue> + <nb_conversions>11</nb_conversions> + <nb_visits_converted>11</nb_visits_converted> + <revenue>55</revenue> </row> </goals> - <nb_conversions>52</nb_conversions> - <revenue>260</revenue> - <sum_daily_nb_uniq_visitors>18</sum_daily_nb_uniq_visitors> + <nb_conversions>33</nb_conversions> + <revenue>165</revenue> + <sum_daily_nb_uniq_visitors>11</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <code>UserCountry_continent_asi</code> + </row> + <row> + <label>UserCountry_continent_amn</label> + <nb_visits>8</nb_visits> + <nb_actions>14</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>5044</sum_visit_length> + <bounce_count>4</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>8</nb_conversions> + <nb_visits_converted>8</nb_visits_converted> + <revenue>40</revenue> + </row> + <row idgoal='2'> + <nb_conversions>4</nb_conversions> + <nb_visits_converted>4</nb_visits_converted> + <revenue>20</revenue> + </row> + </goals> + <nb_conversions>12</nb_conversions> + <revenue>60</revenue> + <sum_daily_nb_uniq_visitors>4</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <code>UserCountry_continent_amn</code> + </row> + <row> + <label>UserCountry_continent_eur</label> + <nb_visits>5</nb_visits> + <nb_actions>9</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>2522</sum_visit_length> + <bounce_count>3</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>5</nb_conversions> + <nb_visits_converted>5</nb_visits_converted> + <revenue>25</revenue> + </row> + <row idgoal='2'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + </goals> + <nb_conversions>7</nb_conversions> + <revenue>35</revenue> + <sum_daily_nb_uniq_visitors>3</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>1</sum_daily_nb_users> - <code>North America</code> + <code>UserCountry_continent_eur</code> </row> </result>
\ No newline at end of file diff --git a/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getCountry_month.xml b/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getCountry_month.xml index ee389b9ac8..70c2dc42e3 100644 --- a/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getCountry_month.xml +++ b/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getCountry_month.xml @@ -1,28 +1,202 @@ <?xml version="1.0" encoding="utf-8" ?> <result> <row> - <label>United States</label> - <nb_visits>35</nb_visits> - <nb_actions>61</nb_actions> + <label>UserCountry_country_cn</label> + <nb_visits>18</nb_visits> + <nb_actions>32</nb_actions> <max_actions>3</max_actions> - <sum_visit_length>21437</sum_visit_length> - <bounce_count>18</bounce_count> + <sum_visit_length>11349</sum_visit_length> + <bounce_count>9</bounce_count> <goals> <row idgoal='1'> - <nb_conversions>35</nb_conversions> - <nb_visits_converted>35</nb_visits_converted> - <revenue>175</revenue> + <nb_conversions>18</nb_conversions> + <nb_visits_converted>18</nb_visits_converted> + <revenue>90</revenue> </row> <row idgoal='2'> - <nb_conversions>17</nb_conversions> - <nb_visits_converted>17</nb_visits_converted> - <revenue>85</revenue> + <nb_conversions>9</nb_conversions> + <nb_visits_converted>9</nb_visits_converted> + <revenue>45</revenue> </row> </goals> - <nb_conversions>52</nb_conversions> - <revenue>260</revenue> - <sum_daily_nb_uniq_visitors>18</sum_daily_nb_uniq_visitors> + <nb_conversions>27</nb_conversions> + <revenue>135</revenue> + <sum_daily_nb_uniq_visitors>9</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <code>cn</code> + <logo>plugins/UserCountry/images/flags/cn.png</logo> + <segment>countryCode==cn</segment> + <logoWidth>16</logoWidth> + <logoHeight>11</logoHeight> + </row> + <row> + <label>UserCountry_country_ca</label> + <nb_visits>6</nb_visits> + <nb_actions>10</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>3783</sum_visit_length> + <bounce_count>3</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>6</nb_conversions> + <nb_visits_converted>6</nb_visits_converted> + <revenue>30</revenue> + </row> + <row idgoal='2'> + <nb_conversions>3</nb_conversions> + <nb_visits_converted>3</nb_visits_converted> + <revenue>15</revenue> + </row> + </goals> + <nb_conversions>9</nb_conversions> + <revenue>45</revenue> + <sum_daily_nb_uniq_visitors>3</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <code>ca</code> + <logo>plugins/UserCountry/images/flags/ca.png</logo> + <segment>countryCode==ca</segment> + <logoWidth>16</logoWidth> + <logoHeight>11</logoHeight> + </row> + <row> + <label>UserCountry_country_fr</label> + <nb_visits>3</nb_visits> + <nb_actions>5</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>2</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>3</nb_conversions> + <nb_visits_converted>3</nb_visits_converted> + <revenue>15</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>4</nb_conversions> + <revenue>20</revenue> + <sum_daily_nb_uniq_visitors>2</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>1</sum_daily_nb_users> + <code>fr</code> + <logo>plugins/UserCountry/images/flags/fr.png</logo> + <segment>countryCode==fr</segment> + <logoWidth>16</logoWidth> + <logoHeight>11</logoHeight> + </row> + <row> + <label>UserCountry_country_id</label> + <nb_visits>2</nb_visits> + <nb_actions>3</nb_actions> + <max_actions>2</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>1</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>3</nb_conversions> + <revenue>15</revenue> + <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <code>id</code> + <logo>plugins/UserCountry/images/flags/id.png</logo> + <segment>countryCode==id</segment> + <logoWidth>16</logoWidth> + <logoHeight>11</logoHeight> + </row> + <row> + <label>UserCountry_country_it</label> + <nb_visits>2</nb_visits> + <nb_actions>4</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>1</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>3</nb_conversions> + <revenue>15</revenue> + <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <code>it</code> + <logo>plugins/UserCountry/images/flags/it.png</logo> + <segment>countryCode==it</segment> + <logoWidth>16</logoWidth> + <logoHeight>11</logoHeight> + </row> + <row> + <label>UserCountry_country_ti</label> + <nb_visits>2</nb_visits> + <nb_actions>3</nb_actions> + <max_actions>2</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>1</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>3</nb_conversions> + <revenue>15</revenue> + <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <code>ti</code> + <logo>plugins/UserCountry/images/flags/ti.png</logo> + <segment>countryCode==ti</segment> + <logoWidth>16</logoWidth> + <logoHeight>11</logoHeight> + </row> + <row> + <label>UserCountry_country_us</label> + <nb_visits>2</nb_visits> + <nb_actions>4</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>1</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>3</nb_conversions> + <revenue>15</revenue> + <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> <code>us</code> <logo>plugins/UserCountry/images/flags/us.png</logo> <segment>countryCode==us</segment> diff --git a/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getRegion_month.xml b/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getRegion_month.xml index bb934e5ce6..378d5e701f 100644 --- a/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getRegion_month.xml +++ b/plugins/UserCountry/tests/System/expected/test_AttributeHistoricalDataWithLocationsTest_testExecute_ShouldReturnLogAfterWorkingWithSomeData_IfThereAreData__UserCountry.getRegion_month.xml @@ -1,32 +1,152 @@ <?xml version="1.0" encoding="utf-8" ?> <result> <row> - <label>Unknown</label> - <nb_visits>35</nb_visits> - <nb_actions>61</nb_actions> + <label>General_Unknown</label> + <nb_visits>22</nb_visits> + <nb_actions>39</nb_actions> <max_actions>3</max_actions> - <sum_visit_length>21437</sum_visit_length> - <bounce_count>18</bounce_count> + <sum_visit_length>13871</sum_visit_length> + <bounce_count>11</bounce_count> <goals> <row idgoal='1'> - <nb_conversions>35</nb_conversions> - <nb_visits_converted>35</nb_visits_converted> - <revenue>175</revenue> + <nb_conversions>22</nb_conversions> + <nb_visits_converted>22</nb_visits_converted> + <revenue>110</revenue> </row> <row idgoal='2'> - <nb_conversions>17</nb_conversions> - <nb_visits_converted>17</nb_visits_converted> - <revenue>85</revenue> + <nb_conversions>11</nb_conversions> + <nb_visits_converted>11</nb_visits_converted> + <revenue>55</revenue> </row> </goals> - <nb_conversions>52</nb_conversions> - <revenue>260</revenue> - <sum_daily_nb_uniq_visitors>18</sum_daily_nb_uniq_visitors> - <sum_daily_nb_users>1</sum_daily_nb_users> + <nb_conversions>33</nb_conversions> + <revenue>165</revenue> + <sum_daily_nb_uniq_visitors>11</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> <region>xx</region> <country>xx</country> - <country_name>Unknown</country_name> - <region_name>Unknown</region_name> + <country_name>General_Unknown</country_name> + <region_name>General_Unknown</region_name> <logo>plugins/UserCountry/images/flags/xx.png</logo> </row> + <row> + <label>British Columbia, UserCountry_country_ca</label> + <nb_visits>6</nb_visits> + <nb_actions>10</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>3783</sum_visit_length> + <bounce_count>3</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>6</nb_conversions> + <nb_visits_converted>6</nb_visits_converted> + <revenue>30</revenue> + </row> + <row idgoal='2'> + <nb_conversions>3</nb_conversions> + <nb_visits_converted>3</nb_visits_converted> + <revenue>15</revenue> + </row> + </goals> + <nb_conversions>9</nb_conversions> + <revenue>45</revenue> + <sum_daily_nb_uniq_visitors>3</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <segment>regionCode==BC;countryCode==ca</segment> + <region>BC</region> + <country>ca</country> + <country_name>UserCountry_country_ca</country_name> + <region_name>British Columbia</region_name> + <logo>plugins/UserCountry/images/flags/ca.png</logo> + </row> + <row> + <label>Franche-Comte, UserCountry_country_fr</label> + <nb_visits>3</nb_visits> + <nb_actions>5</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>2</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>3</nb_conversions> + <nb_visits_converted>3</nb_visits_converted> + <revenue>15</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>4</nb_conversions> + <revenue>20</revenue> + <sum_daily_nb_uniq_visitors>2</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>1</sum_daily_nb_users> + <segment>regionCode==A6;countryCode==fr</segment> + <region>A6</region> + <country>fr</country> + <country_name>UserCountry_country_fr</country_name> + <region_name>Franche-Comte</region_name> + <logo>plugins/UserCountry/images/flags/fr.png</logo> + </row> + <row> + <label>General_Unknown, UserCountry_country_ti</label> + <nb_visits>2</nb_visits> + <nb_actions>3</nb_actions> + <max_actions>2</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>1</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>3</nb_conversions> + <revenue>15</revenue> + <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <segment>regionCode==1;countryCode==ti</segment> + <region>1</region> + <country>ti</country> + <country_name>UserCountry_country_ti</country_name> + <region_name>General_Unknown</region_name> + <logo>plugins/UserCountry/images/flags/ti.png</logo> + </row> + <row> + <label>Lazio, UserCountry_country_it</label> + <nb_visits>2</nb_visits> + <nb_actions>4</nb_actions> + <max_actions>3</max_actions> + <sum_visit_length>1261</sum_visit_length> + <bounce_count>1</bounce_count> + <goals> + <row idgoal='1'> + <nb_conversions>2</nb_conversions> + <nb_visits_converted>2</nb_visits_converted> + <revenue>10</revenue> + </row> + <row idgoal='2'> + <nb_conversions>1</nb_conversions> + <nb_visits_converted>1</nb_visits_converted> + <revenue>5</revenue> + </row> + </goals> + <nb_conversions>3</nb_conversions> + <revenue>15</revenue> + <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <sum_daily_nb_users>0</sum_daily_nb_users> + <segment>regionCode==07;countryCode==it</segment> + <region>07</region> + <country>it</country> + <country_name>UserCountry_country_it</country_name> + <region_name>Lazio</region_name> + <logo>plugins/UserCountry/images/flags/it.png</logo> + </row> </result>
\ No newline at end of file diff --git a/tests/PHPUnit/Fixtures/ManyVisitsWithGeoIP.php b/tests/PHPUnit/Fixtures/ManyVisitsWithGeoIP.php index 3abb1ee414..f460758fbc 100644 --- a/tests/PHPUnit/Fixtures/ManyVisitsWithGeoIP.php +++ b/tests/PHPUnit/Fixtures/ManyVisitsWithGeoIP.php @@ -192,7 +192,7 @@ class ManyVisitsWithGeoIP extends Fixture self::checkResponse($t->doTrackPageView('It\'s pitch black...')); } - private function setLocationProvider($file) + public function setLocationProvider($file) { GeoIp::$dbNames['loc'] = array($file); GeoIp::$geoIPDatabaseDir = 'tests/lib/geoip-files'; diff --git a/tests/PHPUnit/Framework/TestCase/SystemTestCase.php b/tests/PHPUnit/Framework/TestCase/SystemTestCase.php index fdec9cb09b..0681c151d5 100755 --- a/tests/PHPUnit/Framework/TestCase/SystemTestCase.php +++ b/tests/PHPUnit/Framework/TestCase/SystemTestCase.php @@ -566,7 +566,7 @@ abstract class SystemTestCase extends PHPUnit_Framework_TestCase } else if (is_numeric($value)) { $values[] = $value; } else if (!ctype_print($value)) { - $values[] = "x'" . bin2hex(substr($value, 1)) . "'"; + $values[] = "x'" . bin2hex($value) . "'"; } else { $values[] = "?"; $bind[] = $value; |