Teknik is a suite of services with attractive and functional interfaces. https://www.teknik.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Manager.php 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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\ViewDataTable;
  10. use Piwik\Common;
  11. use Piwik\Option;
  12. use Piwik\Piwik;
  13. use Piwik\Plugin\ViewDataTable;
  14. use Piwik\Plugins\CoreVisualizations\Visualizations\Cloud;
  15. use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
  16. use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Bar;
  17. use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Pie;
  18. use Piwik\Plugins\Goals\Visualizations\Goals;
  19. use Piwik\Plugins\Insights\Visualizations\Insight;
  20. use Piwik\Plugin\Manager as PluginManager;
  21. /**
  22. * ViewDataTable Manager.
  23. *
  24. */
  25. class Manager
  26. {
  27. /**
  28. * Returns the viewDataTable IDs of a visualization's class lineage.
  29. *
  30. * @see self::getVisualizationClassLineage
  31. *
  32. * @param string $klass The visualization class.
  33. *
  34. * @return array
  35. */
  36. public static function getIdsWithInheritance($klass)
  37. {
  38. $klasses = Common::getClassLineage($klass);
  39. $result = array();
  40. foreach ($klasses as $klass) {
  41. try {
  42. $result[] = $klass::getViewDataTableId();
  43. } catch (\Exception $e) {
  44. // in case $klass did not define an id: eg Plugin\ViewDataTable
  45. continue;
  46. }
  47. }
  48. return $result;
  49. }
  50. /**
  51. * Returns all registered visualization classes. Uses the 'Visualization.getAvailable'
  52. * event to retrieve visualizations.
  53. *
  54. * @return array Array mapping visualization IDs with their associated visualization classes.
  55. * @throws \Exception If a visualization class does not exist or if a duplicate visualization ID
  56. * is found.
  57. * @return array
  58. */
  59. public static function getAvailableViewDataTables()
  60. {
  61. $klassToExtend = '\\Piwik\\Plugin\\ViewDataTable';
  62. /** @var string[] $visualizations */
  63. $visualizations = PluginManager::getInstance()->findMultipleComponents('Visualizations', $klassToExtend);
  64. /**
  65. * Triggered when gathering all available DataTable visualizations.
  66. *
  67. * Plugins that want to expose new DataTable visualizations should subscribe to
  68. * this event and add visualization class names to the incoming array.
  69. *
  70. * **Example**
  71. *
  72. * public function addViewDataTable(&$visualizations)
  73. * {
  74. * $visualizations[] = 'Piwik\\Plugins\\MyPlugin\\MyVisualization';
  75. * }
  76. *
  77. * @param array &$visualizations The array of all available visualizations.
  78. * @ignore
  79. * @deprecated since 2.5.0 Place visualization in a "Visualizations" directory instead.
  80. */
  81. Piwik::postEvent('ViewDataTable.addViewDataTable', array(&$visualizations));
  82. $result = array();
  83. foreach ($visualizations as $viz) {
  84. if (!class_exists($viz)) {
  85. throw new \Exception("Invalid visualization class '$viz' found in Visualization.getAvailableVisualizations.");
  86. }
  87. if (!is_subclass_of($viz, $klassToExtend)) {
  88. throw new \Exception("ViewDataTable class '$viz' does not extend Plugin/ViewDataTable");
  89. }
  90. $vizId = $viz::getViewDataTableId();
  91. if (isset($result[$vizId])) {
  92. throw new \Exception("ViewDataTable ID '$vizId' is already in use!");
  93. }
  94. $result[$vizId] = $viz;
  95. }
  96. return $result;
  97. }
  98. /**
  99. * Returns all available visualizations that are not part of the CoreVisualizations plugin.
  100. *
  101. * @return array Array mapping visualization IDs with their associated visualization classes.
  102. */
  103. public static function getNonCoreViewDataTables()
  104. {
  105. $result = array();
  106. foreach (static::getAvailableViewDataTables() as $vizId => $vizClass) {
  107. if (false === strpos($vizClass, 'Piwik\\Plugins\\CoreVisualizations')
  108. && false === strpos($vizClass, 'Piwik\\Plugins\\Goals\\Visualizations\\Goals')) {
  109. $result[$vizId] = $vizClass;
  110. }
  111. }
  112. return $result;
  113. }
  114. /**
  115. * This method determines the default set of footer icons to display below a report.
  116. *
  117. * $result has the following format:
  118. *
  119. * ```
  120. * array(
  121. * array( // footer icon group 1
  122. * 'class' => 'footerIconGroup1CssClass',
  123. * 'buttons' => array(
  124. * 'id' => 'myid',
  125. * 'title' => 'My Tooltip',
  126. * 'icon' => 'path/to/my/icon.png'
  127. * )
  128. * ),
  129. * array( // footer icon group 2
  130. * 'class' => 'footerIconGroup2CssClass',
  131. * 'buttons' => array(...)
  132. * ),
  133. * ...
  134. * )
  135. * ```
  136. */
  137. public static function configureFooterIcons(ViewDataTable $view)
  138. {
  139. $result = array();
  140. // add normal view icons (eg, normal table, all columns, goals)
  141. $normalViewIcons = array(
  142. 'class' => 'tableAllColumnsSwitch',
  143. 'buttons' => array(),
  144. );
  145. if ($view->config->show_table) {
  146. $normalViewIcons['buttons'][] = static::getFooterIconFor(HtmlTable::ID);
  147. }
  148. if ($view->config->show_table_all_columns) {
  149. $normalViewIcons['buttons'][] = static::getFooterIconFor(HtmlTable\AllColumns::ID);
  150. }
  151. if ($view->config->show_goals) {
  152. $goalButton = static::getFooterIconFor(Goals::ID);
  153. if (Common::getRequestVar('idGoal', false) == 'ecommerceOrder') {
  154. $goalButton['icon'] = 'plugins/Morpheus/images/ecommerceOrder.gif';
  155. }
  156. $normalViewIcons['buttons'][] = $goalButton;
  157. }
  158. if ($view->config->show_ecommerce) {
  159. $normalViewIcons['buttons'][] = array(
  160. 'id' => 'ecommerceOrder',
  161. 'title' => Piwik::translate('General_EcommerceOrders'),
  162. 'icon' => 'plugins/Morpheus/images/ecommerceOrder.gif',
  163. 'text' => Piwik::translate('General_EcommerceOrders')
  164. );
  165. $normalViewIcons['buttons'][] = array(
  166. 'id' => 'ecommerceAbandonedCart',
  167. 'title' => Piwik::translate('General_AbandonedCarts'),
  168. 'icon' => 'plugins/Morpheus/images/ecommerceAbandonedCart.gif',
  169. 'text' => Piwik::translate('General_AbandonedCarts')
  170. );
  171. }
  172. $normalViewIcons['buttons'] = array_filter($normalViewIcons['buttons']);
  173. if (!empty($normalViewIcons['buttons'])) {
  174. $result[] = $normalViewIcons;
  175. }
  176. // add insight views
  177. $insightsViewIcons = array(
  178. 'class' => 'tableInsightViews',
  179. 'buttons' => array(),
  180. );
  181. // add graph views
  182. $graphViewIcons = array(
  183. 'class' => 'tableGraphViews tableGraphCollapsed',
  184. 'buttons' => array(),
  185. );
  186. if ($view->config->show_all_views_icons) {
  187. if ($view->config->show_bar_chart) {
  188. $graphViewIcons['buttons'][] = static::getFooterIconFor(Bar::ID);
  189. }
  190. if ($view->config->show_pie_chart) {
  191. $graphViewIcons['buttons'][] = static::getFooterIconFor(Pie::ID);
  192. }
  193. if ($view->config->show_tag_cloud) {
  194. $graphViewIcons['buttons'][] = static::getFooterIconFor(Cloud::ID);
  195. }
  196. }
  197. $nonCoreVisualizations = static::getNonCoreViewDataTables();
  198. foreach ($nonCoreVisualizations as $id => $klass) {
  199. if ($klass::canDisplayViewDataTable($view)) {
  200. $footerIcon = static::getFooterIconFor($id);
  201. if (Insight::ID == $footerIcon['id']) {
  202. $insightsViewIcons['buttons'][] = static::getFooterIconFor($id);
  203. } else {
  204. $graphViewIcons['buttons'][] = static::getFooterIconFor($id);
  205. }
  206. }
  207. }
  208. $graphViewIcons['buttons'] = array_filter($graphViewIcons['buttons']);
  209. if (!empty($insightsViewIcons['buttons'])
  210. && $view->config->show_insights
  211. ) {
  212. $result[] = $insightsViewIcons;
  213. }
  214. if (!empty($graphViewIcons['buttons'])) {
  215. $result[] = $graphViewIcons;
  216. }
  217. return $result;
  218. }
  219. /**
  220. * Returns an array with information necessary for adding the viewDataTable to the footer.
  221. *
  222. * @param string $viewDataTableId
  223. *
  224. * @return array
  225. */
  226. private static function getFooterIconFor($viewDataTableId)
  227. {
  228. $tables = static::getAvailableViewDataTables();
  229. if (!array_key_exists($viewDataTableId, $tables)) {
  230. return;
  231. }
  232. $klass = $tables[$viewDataTableId];
  233. return array(
  234. 'id' => $klass::getViewDataTableId(),
  235. 'title' => Piwik::translate($klass::FOOTER_ICON_TITLE),
  236. 'icon' => $klass::FOOTER_ICON,
  237. );
  238. }
  239. public static function clearAllViewDataTableParameters()
  240. {
  241. Option::deleteLike('viewDataTableParameters_%');
  242. }
  243. public static function clearUserViewDataTableParameters($userLogin)
  244. {
  245. Option::deleteLike('viewDataTableParameters_' . $userLogin . '_%');
  246. }
  247. public static function getViewDataTableParameters($login, $controllerAction)
  248. {
  249. $paramsKey = self::buildViewDataTableParametersOptionKey($login, $controllerAction);
  250. $params = Option::get($paramsKey);
  251. if (empty($params)) {
  252. return array();
  253. }
  254. $params = json_decode($params);
  255. $params = (array) $params;
  256. return $params;
  257. }
  258. public static function saveViewDataTableParameters($login, $controllerAction, $parametersToOverride)
  259. {
  260. $params = self::getViewDataTableParameters($login, $controllerAction);
  261. foreach ($parametersToOverride as $key => $value) {
  262. if ($key === 'viewDataTable'
  263. && !empty($params[$key])
  264. && $params[$key] !== $value) {
  265. if (!empty($params['columns'])) {
  266. unset($params['columns']);
  267. }
  268. if (!empty($params['columns_to_display'])) {
  269. unset($params['columns_to_display']);
  270. }
  271. }
  272. $params[$key] = $value;
  273. }
  274. $paramsKey = self::buildViewDataTableParametersOptionKey($login, $controllerAction);
  275. Option::set($paramsKey, json_encode($params));
  276. }
  277. private static function buildViewDataTableParametersOptionKey($login, $controllerAction)
  278. {
  279. return sprintf('viewDataTableParameters_%s_%s', $login, $controllerAction);
  280. }
  281. }