PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.2.0
LatePoint – Calendar Booking Plugin for Appointments and Events v5.2.0
5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 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.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / misc / user.php
latepoint / lib / misc Last commit date
blocked_period.php 1 year ago booked_period.php 1 year ago booking_request.php 1 year ago booking_resource.php 1 year ago booking_slot.php 1 year ago filter.php 1 year ago process_action.php 9 months ago process_event.php 1 year ago role.php 1 year ago router.php 1 year ago step.php 1 year ago stripe_connect_customer.php 1 year ago time_period.php 1 year ago user.php 1 year ago work_period.php 1 year ago
user.php
359 lines
1 <?php
2 /*
3 * Copyright (c) 2023 LatePoint LLC. All rights reserved.
4 */
5
6 namespace LatePoint\Misc;
7
8 class User{
9 public ?string $backend_user_type = null;
10 public ?\WP_User $wp_user = null;
11 public array $roles = [];
12
13 public ?\OsAgentModel $agent = null;
14 public ?\OsCustomerModel $customer = null;
15
16 public ?string $wp_capability = null;
17 protected array $allowed_records = ['agent' => [], 'service' => [], 'location' => []];
18 protected array $capabilities = [];
19
20
21 function __construct(){
22 }
23
24
25 public function get_wp_user_meta($meta_key, $default = ''){
26 $meta_value = $default;
27 if($this->wp_user){
28 $meta_value = get_user_meta($this->wp_user->ID, $meta_key, true);
29 if(empty($meta_value)) $meta_value = $default;
30 }
31 return $meta_value;
32 }
33
34
35 public function update_wp_user_meta($meta_key, $meta_value){
36 if($this->wp_user){
37 update_user_meta($this->wp_user->ID, $meta_key, $meta_value);
38 }
39 }
40
41 /**
42 *
43 * Checks if user has a certain capability
44 *
45 * @param array|string $capability single capability or an array of capabilities to check if user has or not
46 * @return bool
47 */
48 public function has_capability($capability): bool{
49 if($this->has_backend_access()){
50 // only backend user types have capabilities, check if it's a backend user type first
51 if(is_array($capability)){
52 $can = empty(array_diff($capability, $this->get_capabilities()));
53 }else{
54 $can = in_array($capability, $this->get_capabilities());
55 }
56 }else{
57 $can = false;
58 }
59 /**
60 * Checks if a user has certain capability
61 *
62 * @since 4.7.0
63 * @hook latepoint_user_has_capability
64 *
65 * @param {bool} $can answer to a question if user has a capability
66 * @param {array|string} $capability array or a single capability that needs to be checked
67 * @returns {bool} answer to a question if user has a capability
68 */
69 return apply_filters('latepoint_user_has_capability', $can, $capability);
70 }
71
72 public static function load_from_wp_user(\WP_User $wp_user): User{
73 $user = new self();
74 $user->wp_user = $wp_user;
75
76 if(in_array('administrator', $wp_user->roles)){
77 // ADMIN
78 $user->backend_user_type = LATEPOINT_USER_TYPE_ADMIN;
79 $user->wp_capability = 'manage_options';
80 }elseif(in_array(LATEPOINT_WP_AGENT_ROLE, $wp_user->roles)){
81 // AGENT
82 $user->backend_user_type = LATEPOINT_USER_TYPE_AGENT;
83 $user->wp_capability = 'edit_bookings';
84 // get connected agent model
85 $agent = new \OsAgentModel();
86 $agent = $agent->where(['wp_user_id' => $wp_user->ID])->set_limit(1)->get_results_as_models();
87 if($agent) $user->agent = $agent;
88 }else{
89 // see if it's one of custom roles
90 $custom_roles = \OsRolesHelper::get_custom_roles();
91 foreach($custom_roles as $custom_role){
92 if(!empty($wp_user->roles) && in_array($custom_role['wp_role'], $wp_user->roles)){
93 $user->backend_user_type = LATEPOINT_USER_TYPE_CUSTOM;
94 $user->wp_capability = 'manage_latepoint';
95 break;
96 }
97 }
98 }
99 $user->set_roles();
100 $user->set_capabilities();
101 $user->set_allowed_records();
102 return $user;
103 }
104
105 public function set_roles(){
106 if(empty($this->wp_user)) return;
107 if($this->wp_user->roles){
108 foreach($this->wp_user->roles as $role){
109 $this->roles[] = Role::get_from_wp_role($role);
110 }
111 }
112 }
113
114 /*
115 * Check if user has custom permissions set to access actions, instead of using default ones attached to the role
116 */
117 public function is_custom_capabilities(): bool{
118 return(!empty($this->get_custom_capabilities()));
119 }
120
121 /*
122 * Check if user has custom access to model records, instead of using default ones attached to the role
123 */
124 public function is_custom_allowed_records(): bool{
125 return(!empty($this->get_custom_allowed_records()));
126 }
127
128
129 // PERMITTED ACTIONS
130 // -----------------
131
132 public function clear_custom_capabilities(){
133 return delete_user_meta($this->wp_user->ID, 'latepoint_custom_capabilities');
134 }
135
136 public function set_custom_capabilities($capabilities){
137 return update_user_meta($this->wp_user->ID, 'latepoint_custom_capabilities', $capabilities);
138 }
139
140 public function get_custom_capabilities(){
141 return get_user_meta($this->wp_user->ID, 'latepoint_custom_capabilities', true);
142 }
143
144 public function get_capabilities(){
145 return $this->capabilities;
146 }
147
148 protected function set_capabilities(){
149 switch($this->backend_user_type){
150 case LATEPOINT_USER_TYPE_ADMIN:
151 // admins always get all permissions
152 $this->capabilities = \OsRolesHelper::get_all_available_actions_list();
153 break;
154 case LATEPOINT_USER_TYPE_AGENT:
155 case LATEPOINT_USER_TYPE_CUSTOM:
156 $custom = $this->get_custom_capabilities();
157 if(empty($custom)){
158 foreach($this->roles as $role){
159 $this->capabilities = array_merge($this->capabilities, $role->get_capabilities());
160 }
161 }else{
162 $this->capabilities = maybe_unserialize($custom);
163 }
164 break;
165 }
166 }
167
168
169 // ALLOWED RECORDS
170 // -----------------
171
172 public function clear_custom_allowed_records(){
173 return delete_user_meta($this->wp_user->ID, 'latepoint_custom_allowed_records');
174 }
175
176 public function set_custom_allowed_records($allowed_records){
177 if(empty($allowed_records)){
178 return $this->clear_custom_allowed_records();
179 }else{
180 return update_user_meta($this->wp_user->ID, 'latepoint_custom_allowed_records', $allowed_records);
181 }
182 }
183
184 public function get_custom_allowed_records(){
185 return get_user_meta($this->wp_user->ID, 'latepoint_custom_allowed_records', true);
186 }
187
188 public function get_allowed_records(string $model_type, $load_from_db = false){
189 if($load_from_db){
190 // do not calculate allowed records based on what connections are available, just load from database whatever is set
191 $custom = $this->get_custom_allowed_records();
192 if($custom){
193 $custom_records = maybe_unserialize($custom);
194 return !empty($custom_records[$model_type]) ? $custom_records[$model_type] : [];
195 }else{
196 return LATEPOINT_ALL;
197 }
198 }else{
199 return !empty($this->allowed_records[$model_type]) ? $this->allowed_records[$model_type] : [];
200 }
201 }
202
203 public function is_single_record_allowed(string $model_type): bool{
204 return $this->are_all_records_allowed($model_type) ? false : (count($this->get_allowed_records($model_type)) == 1);
205 }
206
207 public function are_all_records_allowed(string $model_type = '', $load_from_db = false): bool{
208 if($load_from_db && $model_type){
209 $allowed_records = $this->get_allowed_records($model_type, true);
210 return ($allowed_records == LATEPOINT_ALL);
211 }else{
212 if($model_type){
213 return ($this->allowed_records[$model_type] == LATEPOINT_ALL);
214 }else{
215 return (($this->allowed_records['agent'] == LATEPOINT_ALL) && ($this->allowed_records['location'] == LATEPOINT_ALL) && ($this->allowed_records['service'] == LATEPOINT_ALL));
216 }
217 }
218 }
219
220 public function check_if_allowed_record_id($id, string $model_type){
221 if(empty($id)) return false;
222 if($this->are_all_records_allowed($model_type)) return $id;
223 if(array_intersect([$id], $this->get_allowed_records($model_type))) return $id;
224 return false;
225 }
226
227 public function clean_query_args($args){
228 $model_types = ['agent', 'service', 'location'];
229 foreach($model_types as $model_type){
230 if(empty($args[$model_type.'_id']) && !$this->are_all_records_allowed($model_type)){
231 $args[$model_type.'_id'] = $this->get_allowed_records($model_type);
232 }
233 }
234 return $args;
235 }
236
237 protected function set_allowed_records(){
238 switch($this->backend_user_type){
239 case LATEPOINT_USER_TYPE_ADMIN:
240 $this->allowed_records['agent'] = LATEPOINT_ALL;
241 $this->allowed_records['service'] = LATEPOINT_ALL;
242 $this->allowed_records['location'] = LATEPOINT_ALL;
243 break;
244 case LATEPOINT_USER_TYPE_AGENT:
245 if($this->agent){
246 $this->allowed_records['agent'] = [$this->agent->id] ?? [];
247 $connection = new \OsConnectorModel();
248 $connections = $connection->where(['agent_id' => $this->agent->id])->get_results_as_models();
249
250 if($connections){
251 foreach($connections as $connection){
252 if(!in_array($connection->service_id, $this->allowed_records['service'])) $this->allowed_records['service'][] = $connection->service_id;
253 if(!in_array($connection->location_id, $this->allowed_records['location'])) $this->allowed_records['location'][] = $connection->location_id;
254 }
255 }
256 }
257 break;
258 case LATEPOINT_USER_TYPE_CUSTOM:
259 // each user has their own settings, by default they allowed to access ALL, query DB to find custom settings
260 $custom = $this->get_custom_allowed_records();
261 if(empty($custom)){
262 $this->allowed_records['agent'] = LATEPOINT_ALL;
263 $this->allowed_records['service'] = LATEPOINT_ALL;
264 $this->allowed_records['location'] = LATEPOINT_ALL;
265 }else{
266 $custom_records = maybe_unserialize($custom);
267 $model_types = ['agent', 'service', 'location'];
268 $connection = new \OsConnectorModel();
269 // (e.g. if specific locations are selected - make sure agents and services are filtered to only have those that are connected to that location)
270 foreach($model_types as $model_type){
271 if($custom_records[$model_type] != LATEPOINT_ALL){
272 $connection->where([$model_type.'_id' => $custom_records[$model_type]]);
273 }
274 }
275 $allowed_connections = $connection->get_results_as_models();
276 foreach($allowed_connections as $allowed_connection){
277 if(!in_array($allowed_connection->agent_id, $this->allowed_records['agent'])) $this->allowed_records['agent'][] = $allowed_connection->agent_id;
278 if(!in_array($allowed_connection->service_id, $this->allowed_records['service'])) $this->allowed_records['service'][] = $allowed_connection->service_id;
279 if(!in_array($allowed_connection->location_id, $this->allowed_records['location'])) $this->allowed_records['location'][] = $allowed_connection->location_id;
280 }
281 }
282 break;
283 }
284 }
285
286
287 public function get_link_to_settings(): string{
288 switch($this->backend_user_type){
289 case LATEPOINT_USER_TYPE_ADMIN:
290 return \OsRouterHelper::build_link(['settings', 'general']);
291 case LATEPOINT_USER_TYPE_AGENT:
292 return \OsRouterHelper::build_link(['agents', 'edit_form'], ['id' => $this->agent->id]);
293 }
294 return '';
295 }
296
297 public function get_avatar_url(): string{
298 // if backend user logged in - try to get their avatar first, before trying to get customer url
299 if($this->backend_user_type){
300 if($this->agent) return $this->agent->get_avatar_url();
301 if($this->wp_user) return get_avatar_url($this->wp_user->user_email);
302 }
303 if($this->customer) return $this->customer->get_avatar_url();
304 if($this->wp_user) return get_avatar_url($this->wp_user->user_email);
305 return '';
306 }
307
308 public function get_display_name(){
309 if($this->backend_user_type){
310 if($this->agent) return $this->agent->full_name;
311 if($this->wp_user) return $this->wp_user->display_name;
312 }
313 if($this->customer) return $this->customer->full_name;
314 if($this->wp_user) return $this->wp_user->display_name;
315 }
316
317 public function get_user_type_label(){
318 $labels = [
319 LATEPOINT_USER_TYPE_ADMIN => __('Administrator', 'latepoint'),
320 LATEPOINT_USER_TYPE_AGENT => __('Agent', 'latepoint'),
321 LATEPOINT_USER_TYPE_CUSTOM => __('Custom', 'latepoint')
322 ];
323 if($this->backend_user_type){
324 if($this->backend_user_type == LATEPOINT_USER_TYPE_CUSTOM){
325 if($this->roles && ($this->roles[0] instanceof Role)){
326 return $this->roles[0]->name;
327 }else{
328 return $labels[$this->backend_user_type];
329 }
330 }else{
331 return $labels[$this->backend_user_type];
332 }
333 }elseif($this->customer){
334 return __('Customer', 'latepoint');
335 }
336 }
337
338 public static function get_backend_user_types(){
339 $backend_user_types = [LATEPOINT_USER_TYPE_ADMIN, LATEPOINT_USER_TYPE_AGENT, LATEPOINT_USER_TYPE_CUSTOM];
340 /**
341 * Get array of user levels that can access backend
342 *
343 * @since 4.7.0
344 * @hook latepoint_get_backend_user_types
345 *
346 * @param {array} $backend_user_types array of user levels (strings) that can access backend
347 * @returns {array} The filtered array of user types
348 */
349 return apply_filters('latepoint_get_backend_user_types', $backend_user_types);
350 }
351
352 public function has_backend_access(): bool{
353 return in_array($this->backend_user_type, self::get_backend_user_types());
354 }
355
356 public static function allowed_props(): array{
357 return [];
358 }
359 }