Merge pull request #22324 from totten/master-queue-table
[civicrm-core.git] / CRM / Utils / Recent.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * @package CRM
14 * @copyright CiviCRM LLC https://civicrm.org/licensing
15 */
16
17 /**
18 * Recent items utility class.
19 */
20 class CRM_Utils_Recent {
21
22 /**
23 * Store name
24 *
25 * @var string
26 */
27 const MAX_ITEMS = 30, STORE_NAME = 'CRM_Utils_Recent';
28
29 /**
30 * The list of recently viewed items.
31 *
32 * @var array
33 */
34 static private $_recent = NULL;
35
36 /**
37 * Maximum stack size
38 * @var int
39 */
40 static private $_maxItems = 10;
41
42 /**
43 * Initialize this class and set the static variables.
44 */
45 public static function initialize() {
46 $maxItemsSetting = Civi::settings()->get('recentItemsMaxCount');
47 if (isset($maxItemsSetting) && $maxItemsSetting > 0 && $maxItemsSetting < self::MAX_ITEMS) {
48 self::$_maxItems = $maxItemsSetting;
49 }
50 if (!self::$_recent) {
51 $session = CRM_Core_Session::singleton();
52 self::$_recent = $session->get(self::STORE_NAME);
53 if (!self::$_recent) {
54 self::$_recent = [];
55 }
56 }
57 }
58
59 /**
60 * Return the recently viewed array.
61 *
62 * @return array
63 * the recently viewed array
64 */
65 public static function &get() {
66 self::initialize();
67 return self::$_recent;
68 }
69
70 /**
71 * Add an item to the recent stack.
72 *
73 * @param string $title
74 * The title to display.
75 * @param string $url
76 * The link for the above title.
77 * @param string $id
78 * Object id.
79 * @param string $type
80 * @param int $contactId
81 * @param string $contactName
82 * @param array $others
83 */
84 public static function add(
85 $title,
86 $url,
87 $id,
88 $type,
89 $contactId,
90 $contactName,
91 $others = []
92 ) {
93 // Abort if this entity type is not supported
94 if (!self::isProviderEnabled($type)) {
95 return;
96 }
97
98 // Ensure item is not already present in list
99 self::removeItems(['id' => $id, 'type' => $type]);
100
101 if (!is_array($others)) {
102 $others = [];
103 }
104
105 array_unshift(self::$_recent,
106 [
107 'title' => $title,
108 'url' => $url,
109 'id' => $id,
110 'type' => $type,
111 'contact_id' => $contactId,
112 'contactName' => $contactName,
113 'subtype' => $others['subtype'] ?? NULL,
114 'isDeleted' => $others['isDeleted'] ?? FALSE,
115 'image_url' => $others['imageUrl'] ?? NULL,
116 'edit_url' => $others['editUrl'] ?? NULL,
117 'delete_url' => $others['deleteUrl'] ?? NULL,
118 ]
119 );
120
121 // Keep the list trimmed to max length
122 while (count(self::$_recent) > self::$_maxItems) {
123 array_pop(self::$_recent);
124 }
125
126 CRM_Utils_Hook::recent(self::$_recent);
127
128 $session = CRM_Core_Session::singleton();
129 $session->set(self::STORE_NAME, self::$_recent);
130 }
131
132 /**
133 * Callback for hook_civicrm_post().
134 * @param \Civi\Core\Event\PostEvent $event
135 */
136 public static function on_hook_civicrm_post(\Civi\Core\Event\PostEvent $event) {
137 if ($event->action === 'delete' && $event->id && CRM_Core_Session::getLoggedInContactID()) {
138 // Is this an entity that might be in the recent items list?
139 $providersPermitted = Civi::settings()->get('recentItemsProviders') ?: array_keys(self::getProviders());
140 if (in_array($event->entity, $providersPermitted)) {
141 self::del(['id' => $event->id, 'type' => $event->entity]);
142 }
143 }
144 }
145
146 /**
147 * Remove items from the array that match given props
148 * @param array $props
149 */
150 private static function removeItems(array $props) {
151 self::initialize();
152
153 self::$_recent = array_filter(self::$_recent, function($item) use ($props) {
154 foreach ($props as $key => $val) {
155 if (isset($item[$key]) && $item[$key] != $val) {
156 return TRUE;
157 }
158 }
159 return FALSE;
160 });
161 }
162
163 /**
164 * Delete item(s) from the recently-viewed list.
165 *
166 * @param array $removeItem
167 * Item to be removed.
168 */
169 public static function del($removeItem) {
170 self::removeItems($removeItem);
171 CRM_Utils_Hook::recent(self::$_recent);
172 $session = CRM_Core_Session::singleton();
173 $session->set(self::STORE_NAME, self::$_recent);
174 }
175
176 /**
177 * Delete an item from the recent stack.
178 *
179 * @param string $id
180 * @deprecated
181 */
182 public static function delContact($id) {
183 CRM_Core_Error::deprecatedFunctionWarning('del');
184 self::del(['contact_id' => $id]);
185 }
186
187 /**
188 * Check if a provider is allowed to add stuff.
189 * If corresponding setting is empty, all are allowed
190 *
191 * @param string $providerName
192 * @return bool
193 */
194 public static function isProviderEnabled($providerName) {
195
196 // Join contact types to providerName 'Contact'
197 $contactTypes = CRM_Contact_BAO_ContactType::contactTypes(TRUE);
198 if (in_array($providerName, $contactTypes)) {
199 $providerName = 'Contact';
200 }
201 $allowed = TRUE;
202
203 // Use core setting recentItemsProviders if configured
204 $providersPermitted = Civi::settings()->get('recentItemsProviders');
205 if ($providersPermitted) {
206 $allowed = in_array($providerName, $providersPermitted);
207 }
208 // Else allow
209 return $allowed;
210 }
211
212 /**
213 * Gets the list of available providers to civi's recent items stack
214 *
215 * @return array
216 */
217 public static function getProviders() {
218 $providers = [
219 'Contact' => ts('Contacts'),
220 'Relationship' => ts('Relationships'),
221 'Activity' => ts('Activities'),
222 'Note' => ts('Notes'),
223 'Group' => ts('Groups'),
224 'Case' => ts('Cases'),
225 'Contribution' => ts('Contributions'),
226 'Participant' => ts('Participants'),
227 'Grant' => ts('Grants'),
228 'Membership' => ts('Memberships'),
229 'Pledge' => ts('Pledges'),
230 'Event' => ts('Events'),
231 'Campaign' => ts('Campaigns'),
232 ];
233
234 return $providers;
235 }
236
237 }