Skip to content

Commit

Permalink
Reports: Add Proof of Play MongoDB grouping
Browse files Browse the repository at this point in the history
  • Loading branch information
mgbaybay committed Sep 25, 2024
1 parent 2cb3e69 commit cbd569c
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 3 deletions.
138 changes: 136 additions & 2 deletions lib/Report/ProofOfPlay.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use Xibo\Factory\MediaFactory;
use Xibo\Factory\ReportScheduleFactory;
use Xibo\Factory\DisplayGroupFactory;
use Xibo\Factory\TagFactory;
use Xibo\Helper\ApplicationState;
use Xibo\Helper\DateFormatHelper;
use Xibo\Helper\SanitizerService;
Expand Down Expand Up @@ -75,6 +76,11 @@ class ProofOfPlay implements ReportInterface
*/
private $displayGroupFactory;

/**
* @var TagFactory
*/
private $tagFactory;

/**
* @var SanitizerService
*/
Expand All @@ -101,6 +107,7 @@ public function setFactories(ContainerInterface $container)
$this->layoutFactory = $container->get('layoutFactory');
$this->reportScheduleFactory = $container->get('reportScheduleFactory');
$this->displayGroupFactory = $container->get('displayGroupFactory');
$this->tagFactory = $container->get('tagFactory');
$this->sanitizer = $container->get('sanitizerService');

return $this;
Expand Down Expand Up @@ -470,7 +477,9 @@ public function getResults(SanitizerInterface $sanitizedParams)
$tags,
$tagsType,
$exactTags,
$operator
$operator,
$groupBy,
$displayGroupIds
);
} else {
$result = $this->getProofOfPlayReportMySql(
Expand Down Expand Up @@ -952,6 +961,8 @@ private function getBodyForTagsType($tagsType, $exclude) :string
* @param $tags string
* @param $tagsType string
* @param $exactTags mixed
* @param $groupBy string
* @param $displayGroupIds array
* @return array[array result, date periodStart, date periodEnd, int count, int totalStats]
* @throws InvalidArgumentException
* @throws \Xibo\Support\Exception\GeneralException
Expand All @@ -968,7 +979,9 @@ private function getProofOfPlayReportMongoDb(
$tags,
$tagsType,
$exactTags,
$operator
$operator,
$groupBy,
$displayGroupIds
) {
$fromDt = new UTCDateTime($filterFromDt->format('U')*1000);
$toDt = new UTCDateTime($filterToDt->format('U')*1000);
Expand Down Expand Up @@ -1196,11 +1209,21 @@ private function getProofOfPlayReportMongoDb(
$entry['widgetId'] = $row['widgetId'];
$entry['mediaId'] = $row['mediaId'];
$entry['tag'] = $row['eventName'];
$entry['displayGroupId'] = '';
$entry['displayGroup'] = '';
$entry['tagId'] = '';
$entry['tagName'] = '';

$rows[] = $entry;
}
}

if ($groupBy === 'tag') {
$rows = $this->groupByTagMongoDb($rows, $tagsType);
} else if ($groupBy === 'displayGroup') {
$rows = $this->groupByDisplayGroupMongoDb($rows, $displayGroupIds);
}

return [
'periodStart' => $filterFromDt->format(DateFormatHelper::getSystemFormat()),
'periodEnd' => $filterToDt->format(DateFormatHelper::getSystemFormat()),
Expand Down Expand Up @@ -1228,4 +1251,115 @@ private function groupByTagType(string $tagType) : string
`lktagdisplaygroup` AS taglink ON taglink.displaygroupId = displaydg.displaygroupId',
};
}

/**
* Group by display group in MongoDB
* @param array $rows
* @param array $displayIds
* @return array
* @throws NotFoundException
*/
private function groupByDisplayGroupMongoDb(array $rows, array $displayIds = []) : array
{
$data = [];

// Get the display groups
foreach ($rows as $row) {
foreach ($this->displayGroupFactory->query(null, ['displayId' => $row['displayId']]) as $dg) {

// Do we have a filter?
if (!$displayIds || in_array($dg->displayGroupId, $displayIds)) {
// Create a temporary key to group by multiple columns at once
// and save memory instead of checking each column recursively
$key = $dg->displayGroupId . '_' . $row['layoutId'] . '_' . $row['mediaId'] . '_' .
$row['tag'] . '_' . $row['widgetId'] . '_' . $row['parentCampaignId'] . '_' . $row['type'];

if (!isset($data[$key])) {
// Since we already have the display group as the grouping option, we can remove the display info
$row['display'] = null;
$row['displayId'] = null;
$row['displayGroupId'] = $dg->displayGroupId;
$row['displayGroup'] = $dg->displayGroup;

$data[$key] = $row;
} else {
$data[$key]['duration'] += $row['duration'];
$data[$key]['numberPlays'] += $row['numberPlays'];
}
}
}
}

return $data;
}

/**
* Group by tag in MongoDB
* @param array $rows
* @param string $tagsType
* @return array
*/
private function groupByTagMongoDb(array $rows, string $tagsType) : array
{
$data = [];
$tags = $this->filterByTagType($tagsType);
$type = match ($tagsType) {
'media' => 'mediaId',
'layout' => 'layoutId',
'dg' => 'displayId',
};;

foreach ($rows as $row) {
foreach ($tags as $tag) {
if ($row[$type] == $tag['entityId']) {
// Create a temporary key to group by multiple columns at once
// and save memory instead of checking each column recursively
$key = $tag['tagId'] . '_' . $row['layoutId'] . '_' . $row['mediaId'] . '_' .
$row['tag'] . '_' . $row['widgetId'] . '_' . $row['parentCampaignId'] . '_' . $row['type'];

if (!isset($data[$key])) {
// Since we already have the tags as the grouping option, we can remove the display info
$row['display'] = null;
$row['displayId'] = null;
$row['tagName'] = $tag['tag'];
$row['tagId'] = $tag['tagId'];

$data[$key] = $row;
} else {
$data[$key]['duration'] += $row['duration'];
$data[$key]['numberPlays'] += $row['numberPlays'];
}
}
}
}

return $data;
}

/**
* @param string $tagsType
* @return array
*/
private function filterByTagType(string $tagsType): array
{
$tags = [];
$filter = match ($tagsType) {
'media' => 'Media',
'layout' => 'Layout',
'dg' => 'Display',
};

// What type of tags are looking for?
foreach ($this->tagFactory->query() as $tag) {
foreach ($this->tagFactory->getAllLinks(null, ['tagId' => $tag->tagId]) as $filteredTag) {
if ($filteredTag['type'] == $filter) {
$filteredTag['tagId'] = $tag->tagId;
$filteredTag['tag'] = $tag->tag;
$tags[] = $filteredTag;
}
}
}

return $tags;
}
}
2 changes: 1 addition & 1 deletion reports/proofofplay-report-form.twig
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@
let totalNumberPlaysPage = api.column(13, { page: 'current'}).data().reduce(function (a, b) {
return a + b;
}, 0);
let totalDurationPage = api.column(13, { page: 'current'}).data().reduce(function (a, b) {
let totalDurationPage = api.column(15, { page: 'current'}).data().reduce(function (a, b) {
return a + b;
}, 0);
Expand Down

0 comments on commit cbd569c

Please sign in to comment.