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