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 | } |