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