update Piwik to version 2.16 (fixes #91)

This commit is contained in:
oliver 2016-04-10 18:55:57 +02:00
commit 47263617c5
51 changed files with 418860 additions and 226988 deletions

View file

@ -0,0 +1,74 @@
<?php
/**
* 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\Plugins\Contents;
use Piwik\Archive;
use Piwik\DataTable;
use Piwik\DataTable\Row;
use Piwik\Metrics;
use Piwik\Piwik;
use Piwik\Plugins\Contents\Archiver;
/**
* API for plugin Contents
*
* @method static \Piwik\Plugins\Contents\API getInstance()
*/
class API extends \Piwik\Plugin\API
{
public function getContentNames($idSite, $period, $date, $segment = false, $idSubtable = false)
{
return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, false, $idSubtable);
}
public function getContentPieces($idSite, $period, $date, $segment = false, $idSubtable = false)
{
return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, false, $idSubtable);
}
private function getDataTable($name, $idSite, $period, $date, $segment, $expanded, $idSubtable)
{
Piwik::checkUserHasViewAccess($idSite);
$recordName = Dimensions::getRecordNameForAction($name);
$dataTable = Archive::getDataTableFromArchive($recordName, $idSite, $period, $date, $segment, $expanded, $idSubtable);
if (empty($idSubtable)) {
$dataTable->filter('AddSegmentValue', array(function ($label) {
if ($label === Archiver::CONTENT_PIECE_NOT_SET) {
return false;
}
return $label;
}));
}
$this->filterDataTable($dataTable);
return $dataTable;
}
/**
* @param DataTable $dataTable
*/
private function filterDataTable($dataTable)
{
$dataTable->queueFilter('ReplaceColumnNames');
$dataTable->queueFilter('ReplaceSummaryRowLabel');
$dataTable->filter(function (DataTable $table) {
$row = $table->getRowFromLabel(Archiver::CONTENT_PIECE_NOT_SET);
if ($row) {
$row->setColumn('label', Piwik::translate('General_NotDefined', Piwik::translate('Contents_ContentPiece')));
}
foreach ($table->getRows() as $row) {
if ($row->getMetadata('contentTarget') === Archiver::CONTENT_TARGET_NOT_SET) {
$row->setMetadata('contentTarget', '');
}
}
});
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* 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\Plugins\Contents\Actions;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker;
/**
* A content is composed of a name, an actual piece of content, and optionally a target.
*/
class ActionContent extends Action
{
public function __construct(Request $request)
{
parent::__construct(Action::TYPE_CONTENT, $request);
$url = $request->getParam('url');
$this->setActionUrl($url);
}
public static function shouldHandle(Request $request)
{
$name = $request->getParam('c_n');
return !empty($name);
}
protected function getActionsToLookup()
{
return array(
'idaction_url' => array($this->getActionUrl(), $this->getActionType())
);
}
// Do not track this Event URL as Entry/Exit Page URL (leave the existing entry/exit)
public function getIdActionUrlForEntryAndExitIds()
{
return false;
}
// Do not track this Event Name as Entry/Exit Page Title (leave the existing entry/exit)
public function getIdActionNameForEntryAndExitIds()
{
return false;
}
}

View file

@ -0,0 +1,320 @@
<?php
/**
* 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\Plugins\Contents;
use Piwik\DataTable;
use Piwik\Metrics;
use Piwik\Plugins\Actions\ArchivingHelper;
use Piwik\RankingQuery;
/**
* Processing reports for Contents
*/
class Archiver extends \Piwik\Plugin\Archiver
{
const CONTENTS_PIECE_NAME_RECORD_NAME = 'Contents_piece_name';
const CONTENTS_NAME_PIECE_RECORD_NAME = 'Contents_name_piece';
const CONTENT_TARGET_NOT_SET = 'Piwik_ContentTargetNotSet';
const CONTENT_PIECE_NOT_SET = 'Piwik_ContentPieceNotSet';
/**
* @var DataArray[]
*/
protected $arrays = array();
protected $metadata = array();
public function __construct($processor)
{
parent::__construct($processor);
$this->columnToSortByBeforeTruncation = Metrics::INDEX_NB_VISITS;
$this->maximumRowsInDataTable = ArchivingHelper::$maximumRowsInDataTableLevelZero;
$this->maximumRowsInSubDataTable = ArchivingHelper::$maximumRowsInSubDataTable;
}
private function getRecordToDimensions()
{
return array(
self::CONTENTS_PIECE_NAME_RECORD_NAME => array('contentPiece', 'contentName'),
self::CONTENTS_NAME_PIECE_RECORD_NAME => array('contentName', 'contentPiece')
);
}
public function aggregateMultipleReports()
{
$dataTableToSum = $this->getRecordNames();
$columnsAggregationOperation = null;
$this->getProcessor()->aggregateDataTableRecords(
$dataTableToSum,
$this->maximumRowsInDataTable,
$this->maximumRowsInSubDataTable,
$this->columnToSortByBeforeTruncation,
$columnsAggregationOperation,
$columnsToRenameAfterAggregation = null,
$countRowsRecursive = array());
}
private function getRecordNames()
{
$mapping = $this->getRecordToDimensions();
return array_keys($mapping);
}
public function aggregateDayReport()
{
$this->aggregateDayImpressions();
$this->aggregateDayInteractions();
$this->insertDayReports();
}
private function aggregateDayImpressions()
{
$select = "
log_action_content_piece.name as contentPiece,
log_action_content_target.name as contentTarget,
log_action_content_name.name as contentName,
count(distinct log_link_visit_action.idvisit) as `" . Metrics::INDEX_NB_VISITS . "`,
count(distinct log_link_visit_action.idvisitor) as `" . Metrics::INDEX_NB_UNIQ_VISITORS . "`,
count(*) as `" . Metrics::INDEX_CONTENT_NB_IMPRESSIONS . "`
";
$from = array(
"log_link_visit_action",
array(
"table" => "log_action",
"tableAlias" => "log_action_content_piece",
"joinOn" => "log_link_visit_action.idaction_content_piece = log_action_content_piece.idaction"
),
array(
"table" => "log_action",
"tableAlias" => "log_action_content_target",
"joinOn" => "log_link_visit_action.idaction_content_target = log_action_content_target.idaction"
),
array(
"table" => "log_action",
"tableAlias" => "log_action_content_name",
"joinOn" => "log_link_visit_action.idaction_content_name = log_action_content_name.idaction"
)
);
$where = "log_link_visit_action.server_time >= ?
AND log_link_visit_action.server_time <= ?
AND log_link_visit_action.idsite = ?
AND log_link_visit_action.idaction_content_name IS NOT NULL
AND log_link_visit_action.idaction_content_interaction IS NULL";
$groupBy = "log_action_content_piece.idaction,
log_action_content_target.idaction,
log_action_content_name.idaction";
$orderBy = "`" . Metrics::INDEX_NB_VISITS . "` DESC";
$rankingQueryLimit = ArchivingHelper::getRankingQueryLimit();
$rankingQuery = null;
if ($rankingQueryLimit > 0) {
$rankingQuery = new RankingQuery($rankingQueryLimit);
$rankingQuery->setOthersLabel(DataTable::LABEL_SUMMARY_ROW);
$rankingQuery->addLabelColumn(array('contentPiece', 'contentTarget', 'contentName'));
$rankingQuery->addColumn(array(Metrics::INDEX_NB_UNIQ_VISITORS));
$rankingQuery->addColumn(array(Metrics::INDEX_CONTENT_NB_IMPRESSIONS, Metrics::INDEX_NB_VISITS), 'sum');
}
$resultSet = $this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, $rankingQuery);
while ($row = $resultSet->fetch()) {
$this->aggregateImpressionRow($row);
}
}
private function aggregateDayInteractions()
{
$select = "
log_action_content_name.name as contentName,
log_action_content_interaction.name as contentInteraction,
log_action_content_piece.name as contentPiece,
count(*) as `" . Metrics::INDEX_CONTENT_NB_INTERACTIONS . "`
";
$from = array(
"log_link_visit_action",
array(
"table" => "log_action",
"tableAlias" => "log_action_content_piece",
"joinOn" => "log_link_visit_action.idaction_content_piece = log_action_content_piece.idaction"
),
array(
"table" => "log_action",
"tableAlias" => "log_action_content_interaction",
"joinOn" => "log_link_visit_action.idaction_content_interaction = log_action_content_interaction.idaction"
),
array(
"table" => "log_action",
"tableAlias" => "log_action_content_name",
"joinOn" => "log_link_visit_action.idaction_content_name = log_action_content_name.idaction"
)
);
$where = "log_link_visit_action.server_time >= ?
AND log_link_visit_action.server_time <= ?
AND log_link_visit_action.idsite = ?
AND log_link_visit_action.idaction_content_name IS NOT NULL
AND log_link_visit_action.idaction_content_interaction IS NOT NULL";
$groupBy = "log_action_content_piece.idaction,
log_action_content_interaction.idaction,
log_action_content_name.idaction";
$orderBy = "`" . Metrics::INDEX_CONTENT_NB_INTERACTIONS . "` DESC";
$rankingQueryLimit = ArchivingHelper::getRankingQueryLimit();
$rankingQuery = null;
if ($rankingQueryLimit > 0) {
$rankingQuery = new RankingQuery($rankingQueryLimit);
$rankingQuery->setOthersLabel(DataTable::LABEL_SUMMARY_ROW);
$rankingQuery->addLabelColumn(array('contentPiece', 'contentInteraction', 'contentName'));
$rankingQuery->addColumn(array(Metrics::INDEX_CONTENT_NB_INTERACTIONS), 'sum');
}
$resultSet = $this->archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, $rankingQuery);
while ($row = $resultSet->fetch()) {
$this->aggregateInteractionRow($row);
}
}
private function archiveDayQueryProcess($select, $from, $where, $groupBy, $orderBy, RankingQuery $rankingQuery)
{
// get query with segmentation
$query = $this->getLogAggregator()->generateQuery($select, $from, $where, $groupBy, $orderBy);
// apply ranking query
if ($rankingQuery) {
$query['sql'] = $rankingQuery->generateRankingQuery($query['sql']);
}
// get result
$resultSet = $this->getLogAggregator()->getDb()->query($query['sql'], $query['bind']);
if ($resultSet === false) {
return;
}
return $resultSet;
}
/**
* Records the daily datatables
*/
private function insertDayReports()
{
foreach ($this->arrays as $recordName => $dataArray) {
$dataTable = $dataArray->asDataTable();
foreach ($dataTable->getRows() as $row) {
$label = $row->getColumn('label');
if (!empty($this->metadata[$label])) {
foreach ($this->metadata[$label] as $name => $value) {
$row->addMetadata($name, $value);
}
}
}
$blob = $dataTable->getSerialized(
$this->maximumRowsInDataTable,
$this->maximumRowsInSubDataTable,
$this->columnToSortByBeforeTruncation);
$this->getProcessor()->insertBlobRecord($recordName, $blob);
}
}
/**
* @param string $name
* @return DataArray
*/
private function getDataArray($name)
{
if (empty($this->arrays[$name])) {
$this->arrays[$name] = new DataArray();
}
return $this->arrays[$name];
}
private function aggregateImpressionRow($row)
{
foreach ($this->getRecordToDimensions() as $record => $dimensions) {
$dataArray = $this->getDataArray($record);
$mainDimension = $dimensions[0];
$mainLabel = $row[$mainDimension];
// content piece is optional
if ($mainDimension == 'contentPiece'
&& empty($mainLabel)) {
$mainLabel = self::CONTENT_PIECE_NOT_SET;
}
$dataArray->sumMetricsImpressions($mainLabel, $row);
$this->rememberMetadataForRow($row, $mainLabel);
$subDimension = $dimensions[1];
$subLabel = $row[$subDimension];
if (empty($subLabel)) {
continue;
}
// content piece is optional
if ($subDimension == 'contentPiece'
&& empty($subLabel)) {
$subLabel = self::CONTENT_PIECE_NOT_SET;
}
$dataArray->sumMetricsContentsImpressionPivot($mainLabel, $subLabel, $row);
}
}
private function aggregateInteractionRow($row)
{
foreach ($this->getRecordToDimensions() as $record => $dimensions) {
$dataArray = $this->getDataArray($record);
$mainDimension = $dimensions[0];
$mainLabel = $row[$mainDimension];
$dataArray->sumMetricsInteractions($mainLabel, $row);
$subDimension = $dimensions[1];
$subLabel = $row[$subDimension];
if (empty($subLabel)) {
continue;
}
$dataArray->sumMetricsContentsInteractionPivot($mainLabel, $subLabel, $row);
}
}
private function rememberMetadataForRow($row, $mainLabel)
{
$this->metadata[$mainLabel] = array();
$target = $row['contentTarget'];
if (empty($target)) {
$target = Archiver::CONTENT_TARGET_NOT_SET;
}
// there can be many different targets
$this->metadata[$mainLabel]['contentTarget'] = $target;
}
}

View file

@ -0,0 +1,57 @@
<?php
/**
* 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\Plugins\Contents\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugins\Actions\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
class ContentInteraction extends ActionDimension
{
protected $columnName = 'idaction_content_interaction';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('contentInteraction');
$segment->setName('Contents_Interaction');
$segment->setAcceptedValues('The type of interaction with the content. For instance "click" or "submit".');
$this->addSegment($segment);
}
public function getName()
{
return Piwik::translate('Contents_Interaction');
}
public function getActionId()
{
return Action::TYPE_CONTENT_INTERACTION;
}
public function onLookupAction(Request $request, Action $action)
{
$interaction = $request->getParam('c_i');
if (empty($interaction)) {
return false;
}
$interaction = trim($interaction);
if (strlen($interaction) > 0) {
return $interaction;
}
return false;
}
}

View file

@ -0,0 +1,57 @@
<?php
/**
* 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\Plugins\Contents\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugins\Actions\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
class ContentName extends ActionDimension
{
protected $columnName = 'idaction_content_name';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('contentName');
$segment->setName('Contents_ContentName');
$segment->setAcceptedValues('The name of a content block, for instance "Ad Sale"');
$this->addSegment($segment);
}
public function getName()
{
return Piwik::translate('Contents_ContentName');
}
public function getActionId()
{
return Action::TYPE_CONTENT_NAME;
}
public function onLookupAction(Request $request, Action $action)
{
$contentName = $request->getParam('c_n');
if (empty($contentName)) {
return false;
}
$contentName = trim($contentName);
if (strlen($contentName) > 0) {
return $contentName;
}
return false;
}
}

View file

@ -0,0 +1,57 @@
<?php
/**
* 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\Plugins\Contents\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugins\Actions\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
class ContentPiece extends ActionDimension
{
protected $columnName = 'idaction_content_piece';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('contentPiece');
$segment->setName('Contents_ContentPiece');
$segment->setAcceptedValues('The actual content. For instance "ad.jpg" or "My text ad"');
$this->addSegment($segment);
}
public function getName()
{
return Piwik::translate('Contents_ContentPiece');
}
public function getActionId()
{
return Action::TYPE_CONTENT_PIECE;
}
public function onLookupAction(Request $request, Action $action)
{
$contentPiece = $request->getParam('c_p');
if (empty($contentPiece)) {
return false;
}
$contentPiece = trim($contentPiece);
if (strlen($contentPiece) > 0) {
return $contentPiece;
}
return false;
}
}

View file

@ -0,0 +1,52 @@
<?php
/**
* 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\Plugins\Contents\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugins\Actions\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
class ContentTarget extends ActionDimension
{
protected $columnName = 'idaction_content_target';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
protected function configureSegments()
{
$segment = new Segment();
$segment->setSegment('contentTarget');
$segment->setName('Contents_ContentTarget');
$segment->setAcceptedValues('For instance the URL of a landing page: "http://landingpage.example.com"');
$this->addSegment($segment);
}
public function getName()
{
return Piwik::translate('Contents_ContentTarget');
}
public function getActionId()
{
return Action::TYPE_CONTENT_TARGET;
}
public function onLookupAction(Request $request, Action $action)
{
$contentTarget = $request->getParam('c_t');
$contentTarget = trim($contentTarget);
if (strlen($contentTarget) > 0) {
return $contentTarget;
}
return false;
}
}

View file

@ -0,0 +1,57 @@
<?php
/**
* 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\Plugins\Contents\Columns\Metrics;
use Piwik\DataTable\Row;
use Piwik\Metrics\Formatter;
use Piwik\Piwik;
use Piwik\Plugin\ProcessedMetric;
/**
* The content interaction rate. Calculated as:
*
* nb_interactions / nb_impressions
*
* nb_interactions & nb_impressions are calculated by the Contents archiver.
*/
class InteractionRate extends ProcessedMetric
{
public function getName()
{
return 'interaction_rate';
}
public function getTranslatedName()
{
return Piwik::translate('Contents_InteractionRate');
}
public function getDocumentation()
{
return Piwik::translate('Contents_InteractionRateMetricDocumentation');
}
public function compute(Row $row)
{
$interactions = $this->getMetric($row, 'nb_interactions');
$impressions = $this->getMetric($row, 'nb_impressions');
return Piwik::getQuotientSafe($interactions, $impressions, $precision = 4);
}
public function format($value, Formatter $formatter)
{
return $formatter->getPrettyPercentFromQuotient($value);
}
public function getDependentMetrics()
{
return array('nb_interactions', 'nb_impressions');
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
* 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\Plugins\Contents;
use Piwik\Piwik;
class Contents extends \Piwik\Plugin
{
/**
* @see Piwik\Plugin::registerEvents
*/
public function registerEvents()
{
return array(
'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations',
'Metrics.getDefaultMetricDocumentationTranslations' => 'addMetricDocumentationTranslations',
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
);
}
public function addMetricTranslations(&$translations)
{
$translations['nb_impressions'] = 'Contents_Impressions';
$translations['nb_interactions'] = 'Contents_Interactions';
$translations['interaction_rate'] = 'Contents_InteractionRate';
}
public function getJsFiles(&$jsFiles)
{
$jsFiles[] = "plugins/Contents/javascripts/contentsDataTable.js";
}
public function getStylesheetFiles(&$stylesheets)
{
$stylesheets[] = "plugins/Contents/stylesheets/datatable.less";
}
public function addMetricDocumentationTranslations(&$translations)
{
$translations['nb_impressions'] = Piwik::translate('Contents_ImpressionsMetricDocumentation');
$translations['nb_interactions'] = Piwik::translate('Contents_InteractionsMetricDocumentation');
}
}

View file

@ -0,0 +1,51 @@
<?php
/**
* 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\Plugins\Contents;
use Piwik\Plugin\Report;
use Piwik\View;
class Controller extends \Piwik\Plugin\Controller
{
public function index()
{
$reportsView = new View\ReportsByDimension('Contents');
/** @var \Piwik\Plugin\Report[] $reports */
$contentNames = Report::factory($this->pluginName, 'getContentNames');
$contentPieces = Report::factory($this->pluginName, 'getContentPieces');
$reports = array($contentNames, $contentPieces);
foreach($reports as $report) {
$reportsView->addReport(
$report->getCategory(),
$report->getName(),
'Contents.' . Report::PREFIX_ACTION_IN_MENU . ucfirst($report->getAction())
);
}
return $reportsView->render();
}
public function menuGetContentNames()
{
$report = Report::factory($this->pluginName, 'getContentNames');
return View::singleReport($report->getName(), $report->render());
}
public function menuGetContentPieces()
{
$report = Report::factory($this->pluginName, 'getContentPieces');
return View::singleReport($report->getName(), $report->render());
}
}

View file

@ -0,0 +1,76 @@
<?php
/**
* 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\Plugins\Contents;
use Piwik\Metrics;
/**
* The DataArray is a data structure used to aggregate datasets,
* ie. sum arrays made of rows made of columns,
* data from the logs is stored in a DataArray before being converted in a DataTable
*
*/
class DataArray extends \Piwik\DataArray
{
public function sumMetricsImpressions($label, $row)
{
if (!isset($this->data[$label])) {
$this->data[$label] = self::makeEmptyContentsRow();
}
$this->doSumContentsImpressionMetrics($row, $this->data[$label]);
}
public function sumMetricsInteractions($label, $row)
{
if (!isset($this->data[$label])) {
return; // do igonre interactions that do not have an impression
}
$this->doSumContentsInteractionMetrics($row, $this->data[$label]);
}
protected static function makeEmptyContentsRow()
{
return array(
Metrics::INDEX_NB_UNIQ_VISITORS => 0,
Metrics::INDEX_NB_VISITS => 0,
Metrics::INDEX_CONTENT_NB_IMPRESSIONS => 0,
Metrics::INDEX_CONTENT_NB_INTERACTIONS => 0
);
}
protected function doSumContentsImpressionMetrics($newRowToAdd, &$oldRowToUpdate)
{
$oldRowToUpdate[Metrics::INDEX_NB_VISITS] += $newRowToAdd[Metrics::INDEX_NB_VISITS];
$oldRowToUpdate[Metrics::INDEX_NB_UNIQ_VISITORS] += $newRowToAdd[Metrics::INDEX_NB_UNIQ_VISITORS];
$oldRowToUpdate[Metrics::INDEX_CONTENT_NB_IMPRESSIONS] += $newRowToAdd[Metrics::INDEX_CONTENT_NB_IMPRESSIONS];
}
protected function doSumContentsInteractionMetrics($newRowToAdd, &$oldRowToUpdate)
{
$oldRowToUpdate[Metrics::INDEX_CONTENT_NB_INTERACTIONS] += $newRowToAdd[Metrics::INDEX_CONTENT_NB_INTERACTIONS];
}
public function sumMetricsContentsImpressionPivot($parentLabel, $label, $row)
{
if (!isset($this->dataTwoLevels[$parentLabel][$label])) {
$this->dataTwoLevels[$parentLabel][$label] = $this->makeEmptyContentsRow();
}
$this->doSumContentsImpressionMetrics($row, $this->dataTwoLevels[$parentLabel][$label]);
}
public function sumMetricsContentsInteractionPivot($parentLabel, $label, $row)
{
if (!isset($this->dataTwoLevels[$parentLabel][$label])) {
return; // do igonre interactions that do not have an impression
}
$this->doSumContentsInteractionMetrics($row, $this->dataTwoLevels[$parentLabel][$label]);
}
}

View file

@ -0,0 +1,33 @@
<?php
/**
* 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\Plugins\Contents;
class Dimensions
{
public static function getRecordNameForAction($apiMethod)
{
$apiToRecord = array(
'getContentNames' => Archiver::CONTENTS_NAME_PIECE_RECORD_NAME,
'getContentPieces' => Archiver::CONTENTS_PIECE_NAME_RECORD_NAME
);
return $apiToRecord[$apiMethod];
}
public static function getSubtableLabelForApiMethod($apiMethod)
{
$labelToMethod = array(
'getContentNames' => 'Contents_ContentPiece',
'getContentPieces' => 'Contents_ContentName'
);
return $labelToMethod[$apiMethod];
}
}

View file

@ -0,0 +1,24 @@
<?php
/**
* 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\Plugins\Contents;
use Piwik\Menu\MenuReporting;
/**
* This class allows you to add, remove or rename menu items.
* To configure a menu (such as Admin Menu, Reporting Menu, User Menu...) simply call the corresponding methods as
* described in the API-Reference http://developer.piwik.org/api-reference/Piwik/Menu/MenuAbstract
*/
class Menu extends \Piwik\Plugin\Menu
{
public function configureReportingMenu(MenuReporting $menu)
{
$menu->addActionsItem('Contents_Contents', array('module' => 'Contents', 'action' => 'index'), $orderId = 40);
}
}

View file

@ -0,0 +1,18 @@
# Piwik Contents Plugin
## Description
Add your plugin description here.
## FAQ
__My question?__
My answer
## Changelog
Here goes the changelog text.
## Support
Please direct any feedback to ...

View file

@ -0,0 +1,60 @@
<?php
/**
* 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\Plugins\Contents\Reports;
use Piwik\Common;
use Piwik\Piwik;
use Piwik\Plugin\Report;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\Contents\Dimensions;
abstract class Base extends Report
{
protected function init()
{
$this->category = 'General_Actions';
}
/**
* Here you can configure how your report should be displayed. For instance whether your report supports a search
* etc. You can also change the default request config. For instance change how many rows are displayed by default.
*
* @param ViewDataTable $view
*/
public function configureView(ViewDataTable $view)
{
$view->config->datatable_js_type = 'ContentsDataTable';
$view->config->datatable_css_class = 'ContentsDataTable';
if (!empty($this->dimension)) {
$view->config->addTranslations(array('label' => $this->dimension->getName()));
}
$view->config->columns_to_display = array_merge(
array('label'),
array_keys($this->getMetrics()),
array_keys($this->getProcessedMetrics())
);
$view->requestConfig->filter_sort_column = 'nb_impressions';
if ($this->hasSubtableId()) {
$apiMethod = $view->requestConfig->getApiMethodToRequest();
$label = Dimensions::getSubtableLabelForApiMethod($apiMethod);
$view->config->addTranslation('label', Piwik::translate($label));
}
}
private function hasSubtableId()
{
$subtable = Common::getRequestVar('idSubtable', false, 'integer');
return !empty($subtable);
}
}

View file

@ -0,0 +1,39 @@
<?php
/**
* 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\Plugins\Contents\Reports;
use Piwik\Piwik;
use Piwik\Plugin\Report;
use Piwik\Plugins\Contents\Columns\ContentName;
use Piwik\Plugins\Contents\Columns\Metrics\InteractionRate;
use Piwik\View;
/**
* This class defines a new report.
*
* See {@link http://developer.piwik.org/api-reference/Piwik/Plugin/Report} for more information.
*/
class GetContentNames extends Base
{
protected function init()
{
parent::init();
$this->name = Piwik::translate('Contents_ContentName');
$this->dimension = null;
// TODO $this->documentation = Piwik::translate('ContentsDocumentation');
$this->dimension = new ContentName();
$this->order = 35;
$this->actionToLoadSubTables = 'getContentNames';
$this->widgetTitle = 'Contents_ContentName';
$this->metrics = array('nb_impressions', 'nb_interactions');
$this->processedMetrics = array(new InteractionRate());
}
}

View file

@ -0,0 +1,40 @@
<?php
/**
* 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\Plugins\Contents\Reports;
use Piwik\Piwik;
use Piwik\Plugin\Report;
use Piwik\Plugins\Contents\Columns\ContentPiece;
use Piwik\Plugins\Contents\Columns\Metrics\InteractionRate;
use Piwik\View;
/**
* This class defines a new report.
*
* See {@link http://developer.piwik.org/api-reference/Piwik/Plugin/Report} for more information.
*/
class GetContentPieces extends Base
{
protected function init()
{
parent::init();
$this->name = Piwik::translate('Contents_ContentPiece');
$this->dimension = null;
// TODO $this->documentation = Piwik::translate('ContentsDocumentation');
$this->dimension = new ContentPiece();
$this->order = 36;
$this->actionToLoadSubTables = 'getContentPieces';
$this->widgetTitle = 'Contents_ContentPiece';
$this->metrics = array('nb_impressions', 'nb_interactions');
$this->processedMetrics = array(new InteractionRate());
}
}

View file

@ -0,0 +1,52 @@
/*!
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
(function ($, require) {
var exports = require('piwik/UI'),
DataTable = exports.DataTable,
dataTablePrototype = DataTable.prototype;
/**
* UI control that handles extra functionality for Actions datatables.
*
* @constructor
*/
exports.ContentsDataTable = function (element) {
DataTable.call(this, element);
};
$.extend(exports.ContentsDataTable.prototype, dataTablePrototype, {
//see dataTable::bindEventsAndApplyStyle
_init: function (domElem) {
domElem.find('table > tbody > tr').each(function (index, tr) {
var $tr = $(tr);
var $td = $tr.find('.label .value');
var text = $td.text().trim();
if (text.search('^https?:\/\/[^\/]+') !== -1) {
if (text.match(/(.jpg|.gif|.png|.svg)$/)) {
if (window.encodeURI) {
text = window.encodeURI(text);
}
$td.tooltip({
track: true,
items: 'span',
content: '<p><img style="max-width: 150px;max-height:150px;" src="' + text + '"/><br />' + text + '</p>',
tooltipClass: 'rowActionTooltip',
show: false,
hide: false
});
}
}
});
}
});
})(jQuery, require);

View file

@ -0,0 +1,9 @@
{
"Contents": {
"Impressions": "طباعة",
"Interaction": "المعاملة",
"InteractionRate": "نسبة المشاركة",
"ContentPiece": "جزء من المحتوى",
"Contents": "عنوان المحتوى"
}
}

View file

@ -0,0 +1,11 @@
{
"Contents": {
"Impressions": "Импресии",
"Interactions": "Взаимодействия",
"Interaction": "Взаимодействие",
"InteractionRate": "Честота на взаимодействие",
"ContentName": "Име на съдържанието",
"ContentTarget": "Целево съдържание",
"Contents": "Съдържание"
}
}

Some files were not shown because too many files have changed in this diff Show more