PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.15.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.15.2
5.12.0 5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Notification / Manager.php
matomo / app / core / Notification Last commit date
Manager.php 4 years ago
Manager.php
224 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9 namespace Piwik\Notification;
10
11 use Piwik\Notification;
12 use Piwik\Session;
13 use Piwik\Session\SessionNamespace;
14
15 /**
16 * Posts and removes UI notifications (see {@link Piwik\Notification} to learn more).
17 *
18 */
19 class Manager
20 {
21 const MAX_NOTIFICATIONS_IN_SESSION = 30;
22 /**
23 * @var SessionNamespace
24 */
25 private static $session = null;
26
27 /**
28 * @var Notification[]
29 */
30 private static $notifications = array();
31
32 /**
33 * Posts a notification that will be shown in Piwik's status bar. If a notification with the same ID
34 * has been posted and has not been closed/removed, it will be replaced with `$notification`.
35 *
36 * @param string $id A unique identifier for this notification. The ID must be a valid HTML
37 * element ID. It can only contain alphanumeric characters (underscores can
38 * be used).
39 * @param Notification $notification The notification to post.
40 * @return bool true if the notification was added, false if it was ignored because there were too many
41 * pending ones.
42 * @api
43 */
44 public static function notify($id, Notification $notification)
45 {
46 self::checkId($id);
47
48 self::removeOldestNotificationsIfThereAreTooMany();
49 return self::addNotification($id, $notification);
50 }
51
52 /**
53 * Removes a posted notification by ID.
54 *
55 * @param string $id The notification ID, see {@link notify()}.
56 */
57 public static function cancel($id)
58 {
59 self::checkId($id);
60
61 self::removeNotification($id);
62 }
63
64 /**
65 * Removes all temporary notifications.
66 *
67 * Call this method after the notifications have been
68 * displayed to make sure temporary notifications won't be displayed twice.
69 */
70 public static function cancelAllNonPersistent()
71 {
72 foreach (static::getAllNotifications() as $id => $notification) {
73 if (Notification::TYPE_PERSISTENT != $notification->type) {
74 static::removeNotification($id);
75 }
76 }
77 }
78
79 /**
80 * Determine all notifications that needs to be displayed. They are sorted by priority. Highest priorities first.
81 * @return \ArrayObject
82 */
83 public static function getAllNotificationsToDisplay()
84 {
85 $notifications = static::getAllNotifications();
86
87 uasort($notifications, function ($n1, $n2) {
88 /** @var Notification $n1 */ /** @var Notification $n2 */
89 if ($n1->getPriority() == $n2->getPriority()) {
90 return 0;
91 }
92
93 return $n1->getPriority() > $n2->getPriority() ? -1 : 1;
94 });
95
96 return $notifications;
97 }
98
99 /**
100 * @param $id
101 * @throws \Exception In case id is empty or if id contains non word characters
102 */
103 private static function checkId($id)
104 {
105 if (empty($id)) {
106 throw new \Exception('Notification ID is empty.');
107 }
108
109 if (!preg_match('/^\w*$/', $id)) {
110 throw new \Exception('Invalid Notification ID given. Only word characters (AlNum + underscore) allowed.');
111 }
112 }
113
114 private static function addNotification($id, Notification $notification)
115 {
116 self::saveNotificationAcrossUiRequestsIfNeeded($id, $notification);
117
118 if (count(self::$notifications) >= self::MAX_NOTIFICATIONS_IN_SESSION) {
119 return false;
120 }
121
122 // we store all kinda notifications here so in case the session is not enabled or disabled later there is still
123 // a chance it gets delivered to the UI during the same request.
124 self::$notifications[$id] = $notification;
125
126 return true;
127 }
128
129 private static function saveNotificationAcrossUiRequestsIfNeeded($id, Notification $notification)
130 {
131 if (self::isSessionEnabled()) {
132 // we need to save even non persistent notifications if possible. Otherwise if there's a redirect
133 // a notification is not shown on the next page view
134 $session = static::getSession();
135 $session->notifications[$id] = $notification;
136 }
137 }
138
139 private static function removeOldestNotificationsIfThereAreTooMany()
140 {
141 if (!self::isSessionEnabled()) {
142 return;
143 }
144
145 $maxNotificationsInSession = self::MAX_NOTIFICATIONS_IN_SESSION;
146
147 $session = static::getSession();
148
149 while (count($session->notifications) >= $maxNotificationsInSession) {
150 array_shift($session->notifications);
151 }
152 }
153
154 private static function getAllNotifications()
155 {
156 if (!self::isSessionEnabled()) {
157 return array();
158 }
159
160 $notifications = self::$notifications;
161
162 foreach ($notifications as $id => $notification) {
163 // we copy them over to the session if possible and persist it in case the session was not yet
164 // writable / enabled at the time the notification was added.
165 self::saveNotificationAcrossUiRequestsIfNeeded($id, $notification);
166 }
167
168 if (self::isSessionEnabled()) {
169 $session = static::getSession();
170 foreach ($session->notifications as $id => $notification) {
171 $notifications[$id] = $notification;
172 }
173 }
174
175 return $notifications;
176 }
177
178 private static function removeNotification($id)
179 {
180 if (array_key_exists($id, self::$notifications)) {
181 unset(self::$notifications[$id]);
182 }
183
184 if (self::isSessionEnabled()) {
185 $session = static::getSession();
186 if (array_key_exists($id, $session->notifications)) {
187 unset($session->notifications[$id]);
188 }
189 }
190 }
191
192 private static function isSessionEnabled()
193 {
194 return Session::isWritable() && Session::isReadable();
195 }
196
197 /**
198 * @return SessionNamespace
199 */
200 private static function getSession()
201 {
202 if (!isset(static::$session)) {
203 static::$session = new SessionNamespace('notification');
204 }
205
206 if (empty(static::$session->notifications) && self::isSessionEnabled()) {
207 static::$session->notifications = array();
208 }
209
210 return static::$session;
211 }
212
213 public static function cancelAllNotifications()
214 {
215 self::$notifications = [];
216 }
217
218 // for tests
219 public static function getPendingInMemoryNotifications()
220 {
221 return self::$notifications;
222 }
223 }
224