PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/Events/API.php

https://github.com/CodeYellowBV/piwik
PHP | 231 lines | 152 code | 23 blank | 56 comment | 10 complexity | 95df987c60452f873e49a59785dac33a MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. *
  8. */
  9. namespace Piwik\Plugins\Events;
  10. use Piwik\Archive;
  11. use Piwik\DataTable\Row;
  12. use Piwik\DataTable;
  13. use Piwik\Metrics;
  14. use Piwik\Piwik;
  15. /**
  16. * The Events API lets you request reports about your users' Custom Events.
  17. *
  18. * Events are tracked using the Javascript Tracker trackEvent() function, or using the [Tracking HTTP API](http://developer.piwik.org/api-reference/tracking-api).
  19. *
  20. * <br/>An event is defined by an event category (Videos, Music, Games...),
  21. * an event action (Play, Pause, Duration, Add Playlist, Downloaded, Clicked...),
  22. * and an optional event name (a movie name, a song title, etc.) and an optional numeric value.
  23. *
  24. * <br/>This API exposes the following Custom Events reports: `getCategory` lists the top Event Categories,
  25. * `getAction` lists the top Event Actions, `getName` lists the top Event Names.
  26. *
  27. * <br/>These Events report define the following metrics: nb_uniq_visitors, nb_visits, nb_events.
  28. * If you define values for your events, you can expect to see the following metrics: nb_events_with_value,
  29. * sum_event_value, min_event_value, max_event_value, avg_event_value
  30. *
  31. * <br/>The Events.get* reports can be used with an optional `&secondaryDimension` parameter.
  32. * Secondary dimension is the dimension used in the sub-table of the Event report you are requesting.
  33. *
  34. * <br/>Here are the possible values of `secondaryDimension`: <ul>
  35. * <li>For `Events.getCategory` you can set `secondaryDimension` to `eventAction` or `eventName`.</li>
  36. * <li>For `Events.getAction` you can set `secondaryDimension` to `eventName` or `eventCategory`.</li>
  37. * <li>For `Events.getName` you can set `secondaryDimension` to `eventAction` or `eventCategory`.</li>
  38. * </ul>
  39. *
  40. * <br/>For example, to request all Custom Events Categories, and for each, the top Event actions,
  41. * you would request: `method=Events.getCategory&secondaryDimension=eventAction&flat=1`.
  42. * You may also omit `&flat=1` in which case, to get top Event actions for one Event category,
  43. * use `method=Events.getActionFromCategoryId` passing it the `&idSubtable=` of this Event category.
  44. *
  45. * @package Events
  46. * @method static \Piwik\Plugins\Events\API getInstance()
  47. */
  48. class API extends \Piwik\Plugin\API
  49. {
  50. protected $defaultMappingApiToSecondaryDimension = array(
  51. 'getCategory' => 'eventAction',
  52. 'getAction' => 'eventName',
  53. 'getName' => 'eventAction',
  54. );
  55. protected $mappingApiToRecord = array(
  56. 'getCategory' =>
  57. array(
  58. 'eventAction' => Archiver::EVENTS_CATEGORY_ACTION_RECORD_NAME,
  59. 'eventName' => Archiver::EVENTS_CATEGORY_NAME_RECORD_NAME,
  60. ),
  61. 'getAction' =>
  62. array(
  63. 'eventName' => Archiver::EVENTS_ACTION_NAME_RECORD_NAME,
  64. 'eventCategory' => Archiver::EVENTS_ACTION_CATEGORY_RECORD_NAME,
  65. ),
  66. 'getName' =>
  67. array(
  68. 'eventAction' => Archiver::EVENTS_NAME_ACTION_RECORD_NAME,
  69. 'eventCategory' => Archiver::EVENTS_NAME_CATEGORY_RECORD_NAME,
  70. ),
  71. 'getActionFromCategoryId' => Archiver::EVENTS_CATEGORY_ACTION_RECORD_NAME,
  72. 'getNameFromCategoryId' => Archiver::EVENTS_CATEGORY_NAME_RECORD_NAME,
  73. 'getCategoryFromActionId' => Archiver::EVENTS_ACTION_CATEGORY_RECORD_NAME,
  74. 'getNameFromActionId' => Archiver::EVENTS_ACTION_NAME_RECORD_NAME,
  75. 'getActionFromNameId' => Archiver::EVENTS_NAME_ACTION_RECORD_NAME,
  76. 'getCategoryFromNameId' => Archiver::EVENTS_NAME_CATEGORY_RECORD_NAME,
  77. );
  78. /**
  79. * @ignore
  80. */
  81. public function getActionToLoadSubtables($apiMethod, $secondaryDimension = false)
  82. {
  83. $recordName = $this->getRecordNameForAction($apiMethod, $secondaryDimension);
  84. $apiMethod = array_search( $recordName, $this->mappingApiToRecord );
  85. return $apiMethod;
  86. }
  87. /**
  88. * @ignore
  89. */
  90. public function getDefaultSecondaryDimension($apiMethod)
  91. {
  92. if(isset($this->defaultMappingApiToSecondaryDimension[$apiMethod])) {
  93. return $this->defaultMappingApiToSecondaryDimension[$apiMethod];
  94. }
  95. return false;
  96. }
  97. protected function getRecordNameForAction($apiMethod, $secondaryDimension = false)
  98. {
  99. if (empty($secondaryDimension)) {
  100. $secondaryDimension = $this->getDefaultSecondaryDimension($apiMethod);
  101. }
  102. $record = $this->mappingApiToRecord[$apiMethod];
  103. if(!is_array($record)) {
  104. return $record;
  105. }
  106. // when secondaryDimension is incorrectly set
  107. if(empty($record[$secondaryDimension])) {
  108. return key($record);
  109. }
  110. return $record[$secondaryDimension];
  111. }
  112. /**
  113. * @ignore
  114. * @param $apiMethod
  115. * @return array
  116. */
  117. public function getSecondaryDimensions($apiMethod)
  118. {
  119. $records = $this->mappingApiToRecord[$apiMethod];
  120. if(!is_array($records)) {
  121. return false;
  122. }
  123. return array_keys($records);
  124. }
  125. protected function checkSecondaryDimension($apiMethod, $secondaryDimension)
  126. {
  127. if (empty($secondaryDimension)) {
  128. return;
  129. }
  130. $isSecondaryDimensionValid =
  131. isset($this->mappingApiToRecord[$apiMethod])
  132. && isset($this->mappingApiToRecord[$apiMethod][$secondaryDimension]);
  133. if (!$isSecondaryDimensionValid) {
  134. throw new \Exception(
  135. "Secondary dimension '$secondaryDimension' is not valid for the API $apiMethod. ".
  136. "Use one of: " . implode(", ", $this->getSecondaryDimensions($apiMethod))
  137. );
  138. }
  139. }
  140. protected function getDataTable($name, $idSite, $period, $date, $segment, $expanded = false, $idSubtable = null, $secondaryDimension = false)
  141. {
  142. Piwik::checkUserHasViewAccess($idSite);
  143. $this->checkSecondaryDimension($name, $secondaryDimension);
  144. $recordName = $this->getRecordNameForAction($name, $secondaryDimension);
  145. $dataTable = Archive::getDataTableFromArchive($recordName, $idSite, $period, $date, $segment, $expanded, $idSubtable);
  146. $this->filterDataTable($dataTable);
  147. return $dataTable;
  148. }
  149. public function getCategory($idSite, $period, $date, $segment = false, $expanded = false, $secondaryDimension = false)
  150. {
  151. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded, $idSubtable = false, $secondaryDimension);
  152. }
  153. public function getAction($idSite, $period, $date, $segment = false, $expanded = false, $secondaryDimension = false)
  154. {
  155. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded, $idSubtable = false, $secondaryDimension);
  156. }
  157. public function getName($idSite, $period, $date, $segment = false, $expanded = false, $secondaryDimension = false)
  158. {
  159. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded, $idSubtable = false, $secondaryDimension);
  160. }
  161. public function getActionFromCategoryId($idSite, $period, $date, $idSubtable, $segment = false)
  162. {
  163. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded = false, $idSubtable);
  164. }
  165. public function getNameFromCategoryId($idSite, $period, $date, $idSubtable, $segment = false)
  166. {
  167. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded = false, $idSubtable);
  168. }
  169. public function getCategoryFromActionId($idSite, $period, $date, $idSubtable, $segment = false)
  170. {
  171. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded = false, $idSubtable);
  172. }
  173. public function getNameFromActionId($idSite, $period, $date, $idSubtable, $segment = false)
  174. {
  175. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded = false, $idSubtable);
  176. }
  177. public function getActionFromNameId($idSite, $period, $date, $idSubtable, $segment = false)
  178. {
  179. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded = false, $idSubtable);
  180. }
  181. public function getCategoryFromNameId($idSite, $period, $date, $idSubtable, $segment = false)
  182. {
  183. return $this->getDataTable(__FUNCTION__, $idSite, $period, $date, $segment, $expanded = false, $idSubtable);
  184. }
  185. /**
  186. * @param DataTable $dataTable
  187. */
  188. protected function filterDataTable($dataTable)
  189. {
  190. $dataTable->filter('Sort', array(Metrics::INDEX_NB_VISITS));
  191. $dataTable->queueFilter('ReplaceColumnNames');
  192. $dataTable->queueFilter('ReplaceSummaryRowLabel');
  193. $dataTable->filter(function (DataTable $table) {
  194. $row = $table->getRowFromLabel(Archiver::EVENT_NAME_NOT_SET);
  195. if ($row) {
  196. $row->setColumn('label', Piwik::translate('General_NotDefined', Piwik::translate('Events_EventName')));
  197. }
  198. });
  199. // add processed metric avg_event_value
  200. $dataTable->queueFilter('ColumnCallbackAddColumnQuotient',
  201. array('avg_event_value',
  202. 'sum_event_value',
  203. 'nb_events_with_value',
  204. $precision = 2,
  205. $shouldSkipRows = true)
  206. );
  207. }
  208. }