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.

WidgetsList.php 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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;
  10. use Piwik\Cache\PluginAwareStaticCache;
  11. use Piwik\Plugin\Report;
  12. use Piwik\Plugin\Widgets;
  13. /**
  14. * Manages the global list of reports that can be displayed as dashboard widgets.
  15. *
  16. * Reports are added as dashboard widgets through the {@hook WidgetsList.addWidgets}
  17. * event. Observers for this event should call the {@link add()} method to add reports.
  18. *
  19. * @api
  20. * @method static \Piwik\WidgetsList getInstance()
  21. */
  22. class WidgetsList extends Singleton
  23. {
  24. /**
  25. * List of widgets
  26. *
  27. * @var array
  28. */
  29. protected static $widgets = array();
  30. /**
  31. * Indicates whether the hook was posted or not
  32. *
  33. * @var bool
  34. */
  35. protected static $hookCalled = false;
  36. /**
  37. * In get() we won't use a cached result in case this is true. Instead we will sort the widgets again and cache
  38. * a new result. To make tests work...
  39. * @var bool
  40. */
  41. private static $listCacheToBeInvalidated = false;
  42. /**
  43. * Returns all available widgets.
  44. *
  45. * @return array Array Mapping widget categories with an array of widget information, eg,
  46. * ```
  47. * array(
  48. * 'Visitors' => array(
  49. * array(...), // info about first widget in this category
  50. * array(...) // info about second widget in this category, etc.
  51. * ),
  52. * 'Visits' => array(
  53. * array(...),
  54. * array(...)
  55. * ),
  56. * )
  57. * ```
  58. */
  59. public static function get()
  60. {
  61. $cache = self::getCacheForCompleteList();
  62. if (!self::$listCacheToBeInvalidated && $cache->has()) {
  63. return $cache->get();
  64. }
  65. self::addWidgets();
  66. uksort(self::$widgets, array('Piwik\WidgetsList', '_sortWidgetCategories'));
  67. $widgets = array();
  68. foreach (self::$widgets as $key => $v) {
  69. $category = Piwik::translate($key);
  70. if (isset($widgets[$category])) {
  71. $v = array_merge($widgets[$category], $v);
  72. }
  73. $widgets[$category] = $v;
  74. }
  75. $cache->set($widgets);
  76. self::$listCacheToBeInvalidated = false;
  77. return $widgets;
  78. }
  79. private static function addWidgets()
  80. {
  81. if (!self::$hookCalled) {
  82. self::$hookCalled = true;
  83. /**
  84. * @ignore
  85. * @deprecated
  86. */
  87. Piwik::postEvent('WidgetsList.addWidgets');
  88. $widgetsList = self::getInstance();
  89. foreach (Report::getAllReports() as $report) {
  90. if ($report->isEnabled()) {
  91. $report->configureWidget($widgetsList);
  92. }
  93. }
  94. $widgetContainers = Widgets::getAllWidgets();
  95. foreach ($widgetContainers as $widgetContainer) {
  96. $widgets = $widgetContainer->getWidgets();
  97. foreach ($widgets as $widget) {
  98. $widgetsList->add($widget['category'], $widget['name'], $widget['module'], $widget['method'], $widget['params']);
  99. }
  100. }
  101. foreach ($widgetContainers as $widgetContainer) {
  102. $widgetContainer->configureWidgetsList($widgetsList);
  103. }
  104. }
  105. }
  106. /**
  107. * Sorting method for widget categories
  108. *
  109. * @param string $a
  110. * @param string $b
  111. * @return bool
  112. */
  113. protected static function _sortWidgetCategories($a, $b)
  114. {
  115. $order = array(
  116. 'VisitsSummary_VisitsSummary',
  117. 'Live!',
  118. 'General_Visitors',
  119. 'UserSettings_VisitorSettings',
  120. 'DevicesDetection_DevicesDetection',
  121. 'General_Actions',
  122. 'Events_Events',
  123. 'Actions_SubmenuSitesearch',
  124. 'Referrers_Referrers',
  125. 'Goals_Goals',
  126. 'Goals_Ecommerce',
  127. '_others_',
  128. 'Example Widgets',
  129. 'ExamplePlugin_exampleWidgets',
  130. );
  131. if (($oa = array_search($a, $order)) === false) {
  132. $oa = array_search('_others_', $order);
  133. }
  134. if (($ob = array_search($b, $order)) === false) {
  135. $ob = array_search('_others_', $order);
  136. }
  137. return $oa > $ob;
  138. }
  139. /**
  140. * Adds a report to the list of dashboard widgets.
  141. *
  142. * @param string $widgetCategory The widget category. This can be a translation token.
  143. * @param string $widgetName The name of the widget. This can be a translation token.
  144. * @param string $controllerName The report's controller name (same as the plugin name).
  145. * @param string $controllerAction The report's controller action method name.
  146. * @param array $customParameters Extra query parameters that should be sent while getting
  147. * this report.
  148. */
  149. public static function add($widgetCategory, $widgetName, $controllerName, $controllerAction, $customParameters = array())
  150. {
  151. $widgetName = Piwik::translate($widgetName);
  152. $widgetUniqueId = 'widget' . $controllerName . $controllerAction;
  153. foreach ($customParameters as $name => $value) {
  154. if (is_array($value)) {
  155. // use 'Array' for backward compatibility;
  156. // could we switch to using $value[0]?
  157. $value = 'Array';
  158. }
  159. $widgetUniqueId .= $name . $value;
  160. }
  161. if (!array_key_exists($widgetCategory, self::$widgets)) {
  162. self::$widgets[$widgetCategory] = array();
  163. }
  164. self::$listCacheToBeInvalidated = true;
  165. self::$widgets[$widgetCategory][] = array(
  166. 'name' => $widgetName,
  167. 'uniqueId' => $widgetUniqueId,
  168. 'parameters' => array('module' => $controllerName,
  169. 'action' => $controllerAction
  170. ) + $customParameters
  171. );
  172. }
  173. /**
  174. * Removes one or more widgets from the widget list.
  175. *
  176. * @param string $widgetCategory The widget category. Can be a translation token.
  177. * @param string|false $widgetName The name of the widget to remove. Cannot be a
  178. * translation token. If not supplied, the entire category
  179. * will be removed.
  180. */
  181. public static function remove($widgetCategory, $widgetName = false)
  182. {
  183. if (!isset(self::$widgets[$widgetCategory])) {
  184. return;
  185. }
  186. if (empty($widgetName)) {
  187. unset(self::$widgets[$widgetCategory]);
  188. self::$listCacheToBeInvalidated = true;
  189. return;
  190. }
  191. foreach (self::$widgets[$widgetCategory] as $id => $widget) {
  192. if ($widget['name'] == $widgetName || $widget['name'] == Piwik::translate($widgetName)) {
  193. unset(self::$widgets[$widgetCategory][$id]);
  194. self::$listCacheToBeInvalidated = true;
  195. return;
  196. }
  197. }
  198. }
  199. /**
  200. * Returns `true` if a report exists in the widget list, `false` if otherwise.
  201. *
  202. * @param string $controllerName The controller name of the report.
  203. * @param string $controllerAction The controller action of the report.
  204. * @return bool
  205. */
  206. public static function isDefined($controllerName, $controllerAction)
  207. {
  208. $widgetsList = self::get();
  209. foreach ($widgetsList as $widgets) {
  210. foreach ($widgets as $widget) {
  211. if ($widget['parameters']['module'] == $controllerName
  212. && $widget['parameters']['action'] == $controllerAction
  213. ) {
  214. return true;
  215. }
  216. }
  217. }
  218. return false;
  219. }
  220. /**
  221. * Method to reset the widget list
  222. * For testing only
  223. * @ignore
  224. */
  225. public static function _reset()
  226. {
  227. self::$widgets = array();
  228. self::$hookCalled = false;
  229. self::getCacheForCompleteList()->clear();
  230. }
  231. private static function getCacheForCompleteList()
  232. {
  233. return new PluginAwareStaticCache('WidgetsList');
  234. }
  235. }