Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redefine when revenue information is displayed on All Websites Dashboard #22886

Open
wants to merge 6 commits into
base: 5.x-dev
Choose a base branch
from
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ This is the Developer Changelog for Matomo platform developers. All changes in o

The Product Changelog at **[matomo.org/changelog](https://matomo.org/changelog)** lets you see more details about any Matomo release, such as the list of new guides and FAQs, security fixes, and links to all closed issues.

## Matomo 5.3.0

### Breaking Changes

* When requesting goals for multiple sites at once using `Goals.getGoals`, the result will no longer be indexed by `idgoal` anymore. Requesting the goals for a single site will still return them indexed by `idgoal`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* When requesting goals for multiple sites at once using `Goals.getGoals`, the result will no longer be indexed by `idgoal` anymore. Requesting the goals for a single site will still return them indexed by `idgoal`.
* When requesting goals for multiple sites at once using `Goals.getGoals`, the result will no longer be indexed by `idgoal`. Requesting the goals for a single site will still return them indexed by `idgoal`.


## Matomo 5.2.0

### Breaking Changes
Expand Down
18 changes: 15 additions & 3 deletions plugins/Goals/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,17 @@ public function getGoal($idSite, $idGoal)
* @param string|array $idSite Array or Comma separated list of website IDs to request the goals for
* @param bool $orderByName
*
* @return array Array of Goal attributes
* @return array Array of Goal attributes,
* indexed by "idgoal" when requesting a single site,
* no specific index when requesting multiple sites
*/
public function getGoals($idSite, bool $orderByName = false): array
{
if (is_array($idSite)) {
$idSite = array_map('intval', $idSite);
$idSite = implode(',', $idSite);
}

$cacheId = self::getCacheId($idSite);
$cache = $this->getGoalsInfoStaticCache();
if (!$cache->contains($cacheId)) {
Expand All @@ -101,10 +108,15 @@ public function getGoals($idSite, bool $orderByName = false): array
Piwik::checkUserHasViewAccess($idSite);

$goals = $this->getModel()->getActiveGoals($idSite);
$cleanedGoals = [];
$indexByIdGoal = 1 === count($idSite);

$cleanedGoals = array();
foreach ($goals as &$goal) {
$cleanedGoals[$goal['idgoal']] = $this->formatGoal($goal);
if ($indexByIdGoal) {
$cleanedGoals[$goal['idgoal']] = $this->formatGoal($goal);
} else {
$cleanedGoals[] = $this->formatGoal($goal);
}
Comment on lines +112 to +119
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't quite understand why you would want this different behavior if there is a single goal or multiple? What's the problem with always setting the array index as the ID goal?

}

$cache->save($cacheId, $cleanedGoals);
Expand Down
40 changes: 37 additions & 3 deletions plugins/Goals/tests/Integration/APITest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,23 @@ class APITest extends IntegrationTestCase
*/
private $api;

private $idSite = 1;
/**
* @var int
*/
private $idSite;

/**
* @var int
*/
private $idSiteTwo;

public function setUp(): void
{
parent::setUp();
$this->api = API::getInstance();

Fixture::createWebsite('2014-01-01 00:00:00');
Fixture::createWebsite('2014-01-01 00:00:00');
$this->idSite = Fixture::createWebsite('2014-01-01 00:00:00');
$this->idSiteTwo = Fixture::createWebsite('2014-01-01 00:00:00');
}

/**
Expand Down Expand Up @@ -262,6 +270,32 @@ public function testGetGoalShouldReturnExistingGoal()
), $goal);
}

/**
* @param string|array $idSite
*
* @dataProvider getTestDataForMultipleSites
*/
public function testGetGoalsShouldReturnGoalsForMultipleSites($idSite): void
{
$idGoal = $this->api->addGoal($this->idSite, 'Goal Site One', 'url', 'http://site.one', 'exact');
$idGoalTwo = $this->api->addGoal($this->idSiteTwo, 'Goal Site Two', 'url', 'http://site.two', 'exact');
$goals = $this->api->getGoals($idSite);

$this->assertEqualsCanonicalizing(
[
$this->api->getGoal($this->idSite, $idGoal),
$this->api->getGoal($this->idSiteTwo, $idGoalTwo)
],
$goals
);
}

public function getTestDataForMultipleSites(): iterable
{
yield 'comma separated string' => ['1,2'];
yield 'array' => [[1, 2]];
}

private function assertHasGoals()
{
$goals = $this->getGoals();
Expand Down
34 changes: 33 additions & 1 deletion plugins/MultiSites/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use Piwik\Piwik;
use Piwik\Plugins\FeatureFlags\FeatureFlagManager;
use Piwik\Plugins\MultiSites\FeatureFlags\ImprovedAllWebsitesDashboard;
use Piwik\Plugins\Goals\API as GoalsAPI;
use Piwik\Plugins\SitesManager\API as SitesManagerAPI;
use Piwik\Translation\Translator;
use Piwik\View;

Expand Down Expand Up @@ -65,7 +67,7 @@ public function getSitesInfo($isWidgetized = false)
}

$view->isWidgetized = $isWidgetized;
$view->displayRevenueColumn = Common::isGoalPluginEnabled();
$view->displayRevenueColumn = $this->shouldDisplayRevenueColumn();
$view->limit = Config::getInstance()->General['all_websites_website_per_page'];
$view->show_sparklines = Config::getInstance()->General['show_multisites_sparklines'];

Expand Down Expand Up @@ -104,4 +106,34 @@ public function getEvolutionGraph($columns = false)
$view->requestConfig->totals = 0;
return $this->renderView($view);
}

private function shouldDisplayRevenueColumn(): bool
{
if (!Common::isGoalPluginEnabled()) {
return false;
}

if (!$this->featureFlagManager->isFeatureActive(ImprovedAllWebsitesDashboard::class)) {
return true;
}

$sites = SitesManagerAPI::getInstance()->getSitesWithAtLeastViewAccess();

foreach ($sites as $site) {
if ($site['ecommerce']) {
return true;
}
}

$idSites = array_column($sites, 'idsite');
$goals = GoalsAPI::getInstance()->getGoals($idSites);

foreach ($goals as $goal) {
if (0.0 < $goal['revenue'] || true === (bool) $goal['event_value_as_revenue']) {
return true;
}
}

return false;
}
}
124 changes: 86 additions & 38 deletions plugins/MultiSites/tests/Fixtures/ManySitesWithVisits.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Piwik\Plugins\MultiSites\tests\Fixtures;

use Piwik\Date;
use Piwik\Plugins\Goals\API as GoalsAPI;
use Piwik\Tests\Framework\Fixture;

/**
Expand All @@ -20,66 +21,113 @@
class ManySitesWithVisits extends Fixture
{
public $dateTime = '2013-01-23 01:23:45';
public $idSite = 1;

public $idSiteEcommerce;
public $idSiteGoalDefaultValue;
public $idSiteGoalEventValue;
public $idSiteGoalWithoutValue;

public $idGoalDefaultValue;
public $idGoalEventValue;
public $idGoalWithoutValue;

public function setUp(): void
{
$this->setUpWebsite();
$this->trackFirstVisit($this->idSite);
$this->trackSecondVisit($this->idSite);
$this->trackFirstVisit($siteId = 2);
$this->trackSecondVisit($siteId = 3);
$this->trackSecondVisit($siteId = 3);
$this->trackSecondVisit($siteId = 4);
$this->setUpWebsites();
$this->setUpGoals();

$this->trackVisitsForSite($this->idSiteEcommerce, 6);
$this->trackVisitsForSite($this->idSiteGoalDefaultValue, 3);
$this->trackVisitsForSite($this->idSiteGoalEventValue, 2);
$this->trackVisitsForSite($this->idSiteGoalWithoutValue, 1);
}

public function tearDown(): void
{
// empty
}

private function setUpWebsite()
private function setUpGoals(): void
{
for ($i = 1; $i <= 15; $i++) {
if (!self::siteCreated($i)) {
$idSite = self::createWebsite($this->dateTime, $ecommerce = 1, 'Site ' . $i);
$this->assertSame($i, $idSite);
}
}
$goalsApi = GoalsAPI::getInstance();

$this->idGoalDefaultValue = $goalsApi->addGoal(
$this->idSiteGoalDefaultValue,
'Goal With Value',
'manually',
'',
'',
false,
50.0
);

$this->idGoalEventValue = $goalsApi->addGoal(
$this->idSiteGoalEventValue,
'Goal Event Value',
'event_action',
'track value',
'exact',
false,
false,
false,
'',
true
);

$this->idGoalWithoutValue = $goalsApi->addGoal(
$this->idSiteGoalWithoutValue,
'Goal Without Value',
'manually',
'',
''
);
}

protected function trackFirstVisit($idSite)
private function setUpWebsites(): void
{
$t = self::getTracker($idSite, $this->dateTime, $defaultInit = true);

$t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.1)->getDatetime());
$t->setUrl('http://example.com/');
self::checkResponse($t->doTrackPageView('Viewing homepage'));
$this->idSiteEcommerce = self::createWebsite($this->dateTime, 1, 'Site Ecommerce');
$this->idSiteGoalDefaultValue = self::createWebsite($this->dateTime, 0, 'Site Goal Default Value');
$this->idSiteGoalEventValue = self::createWebsite($this->dateTime, 0, 'Site Goal Event Value');
$this->idSiteGoalWithoutValue = self::createWebsite($this->dateTime, 0, 'Site Goal Without Value');

$t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.2)->getDatetime());
$t->setUrl('http://example.com/sub/page');
self::checkResponse($t->doTrackPageView('Second page view'));
// create 11 empty websites
for ($i = 5; $i <= 15; $i++) {
$idSite = self::createWebsite($this->dateTime, 0, 'Site ' . $i);

$t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.25)->getDatetime());
$t->addEcommerceItem($sku = 'SKU_ID', $name = 'Test item!', $category = 'Test & Category', $price = 777, $quantity = 33);
self::checkResponse($t->doTrackEcommerceOrder('TestingOrder', $grandTotal = 33 * 77));
self::assertSame($i, $idSite);
}
}

protected function trackSecondVisit($idSite)
private function trackVisitsForSite(int $idSite, int $visitCount): void
{
$t = self::getTracker($idSite, $this->dateTime, $defaultInit = true);
$t->setIp('56.11.55.73');
for ($visit = 1; $visit <= $visitCount; $visit++) {
$visitDate = Date::factory($this->dateTime)->addHour($visit);
$tracker = self::getTracker($idSite, $visitDate->getDatetime());
$tracker->setUrl('http://example.com/');

self::checkResponse($tracker->doTrackPageView('Viewing homepage'));

$tracker->setForceVisitDateTime($visitDate->addHour(0.25)->getDatetime());

$t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.1)->getDatetime());
$t->setUrl('http://example.com/sub/page');
self::checkResponse($t->doTrackPageView('Viewing homepage'));
switch ($idSite) {
case $this->idSiteEcommerce:
$tracker->addEcommerceItem('SKU_ID', 'Test item!', 'Test & Category', 299.95, $visit);
self::checkResponse($tracker->doTrackEcommerceOrder('Order ' . $visit, 299.95 * $visit));
break;

$t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.2)->getDatetime());
$t->setUrl('http://example.com/?search=this is a site search query');
self::checkResponse($t->doTrackPageView('Site search query'));
case $this->idSiteGoalDefaultValue:
self::checkResponse($tracker->doTrackGoal($this->idGoalDefaultValue));
break;

$t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.3)->getDatetime());
$t->addEcommerceItem($sku = 'SKU_ID2', $name = 'A durable item', $category = 'Best seller', $price = 321);
self::checkResponse($t->doTrackEcommerceCartUpdate($grandTotal = 33 * 77));
case $this->idSiteGoalEventValue:
self::checkResponse($tracker->doTrackEvent('value event', 'track value', false, 1337.0));
break;

case $this->idSiteGoalWithoutValue:
self::checkResponse($tracker->doTrackGoal($this->idGoalWithoutValue));
break;
}
}
}
}
Loading
Loading