|
Server : LiteSpeed System : Linux premium92.web-hosting.com 4.18.0-553.44.1.lve.el8.x86_64 #1 SMP Thu Mar 13 14:29:12 UTC 2025 x86_64 User : rbnsfqys ( 805) PHP Version : 8.1.33 Disable Function : NONE Directory : /home/rbnsfqys/public_html/wp-content/plugins/latepoint/lib/helpers/ |
<?php
/*
* Copyright (c) 2023 LatePoint LLC. All rights reserved.
*/
class OsRolesHelper {
public static array $capabilities_for_controllers;
public static function get_capabilities_for_all_controllers(){
if(isset(self::$capabilities_for_controllers)) return self::$capabilities_for_controllers;
$capabilities = include(LATEPOINT_CONFIG_ABSPATH . 'capabilities_for_controllers.php');
/**
* Get array of capabilities for all controllers
*
* @since 4.7.0
* @hook latepoint_capabilities_for_controllers
*
* @param {array} $capabilities array of controllers with their default and per action capablities
* @returns {array} The filtered array of controllers with capability information
*/
self::$capabilities_for_controllers = apply_filters('latepoint_capabilities_for_controllers', $capabilities);
return self::$capabilities_for_controllers;
}
public static function build_capability_name_from_model_action(string $model_class, string $action): string{
$capability_names_for_models = [
'OsActivityModel' => 'activity',
'OsAgentModel' => 'agent',
'OsAgentMetaModel' => 'agent',
'OsOrderModel' => 'booking',
'OsOrderIntentModel' => 'booking',
'OsOrderMetaModel' => 'booking',
'OsBookingModel' => 'booking',
'OsBookingMetaModel' => 'booking',
'OsConnectorModel' => 'connection',
'OsCustomerModel' => 'customer',
'OsCustomerMetaModel' => 'customer',
'OsLocationModel' => 'location',
'OsLocationCategoryModel' => 'location',
'OsServiceModel' => 'service',
'OsServiceExtraModel' => 'service',
'OsServiceMetaModel' => 'service',
'OsBundleModel' => 'bundle',
'OsServiceCategoryModel' => 'service',
'OsTransactionModel' => 'transaction',
'OsInvoiceModel' => 'invoice',
'OsProcessJobModel' => 'settings',
'OsStepSettingsModel' => 'settings',
'OsProcessModel' => 'settings',
'OsSettingsModel' => 'settings',
'OsWorkPeriodModel' => 'settings',
];
/**
* Get array of key => value connections between model name and capability name
*
* @since 4.7.0
* @hook latepoint_capability_names_for_models
*
* @param {array} $capability_names_for_models array of key => value pairs of model name => capability name
* @returns {array} The filtered array of value pairs
*/
$capability_names_for_models = apply_filters('latepoint_capability_names_for_models', $capability_names_for_models);
if(isset($capability_names_for_models[$model_class])){
$capability = $capability_names_for_models[$model_class].'__'.$action;
$all_actions = self::get_all_available_actions_list();
if(in_array($capability, $all_actions)){
return $capability;
}else{
$capability = $capability_names_for_models[$model_class].'__edit';
if(in_array($capability, $all_actions)) return $capability;
}
}
return '';
}
public static function can_user_make_action_on_model_record(OsModel $model, string $action){
if(OsAuthHelper::get_current_user()->backend_user_type == LATEPOINT_USER_TYPE_ADMIN) return true; // admins are allowed to do everything
// check if customer is logged in and tries to edit records that belong to them
if(OsAuthHelper::is_customer_logged_in()){
// if it's customer - they can edit their customer record and also their bookings
if($model instanceof OsBookingModel && $model->customer_id == OsAuthHelper::get_logged_in_customer_id()){
return true;
}
if($model instanceof OsCustomerModel && $model->id == OsAuthHelper::get_logged_in_customer_id()){
return true;
}
}
// if customer is not logged in or logged in customer doesn't have rights to access this record, check if backend user has
if(self::can_user_perform_model_action(get_class($model), $action)){
switch(get_class($model)){
case 'OsBookingModel':
if(OsAuthHelper::get_current_user()->are_all_records_allowed('agent')) return true;
$allowed_ids = OsAuthHelper::get_current_user()->get_allowed_records('agent');
if($allowed_ids && in_array($model->agent_id, $allowed_ids)) return true;
break;
case 'OsCustomerModel':
// check if this customer has any bookings with allowed agents
if(OsAuthHelper::get_current_user()->are_all_records_allowed('agent')) return true;
$allowed_ids = OsAuthHelper::get_current_user()->get_allowed_records('agent');
$bookings = new OsBookingModel();
if($allowed_ids){
if($allowed_ids && in_array($model->agent_id, $allowed_ids)) return true;
$has_bookings_with_allowed_agents = $bookings->select('id')->where(['agent_id' => $allowed_ids, 'customer_id' => $model->id])->set_limit(1)->get_results();
if(!empty($has_bookings_with_allowed_agents)){
return true;
}
}
break;
}
}
return false;
}
public static function can_user_perform_model_action(string $model_class, string $action): bool{
$capability = self::build_capability_name_from_model_action($model_class, $action);
$can = !empty($capability) ? self::can_user($capability) : true;
return $can;
}
/**
*
* Get capabilities required to access specific action of the controller
*
* @param string $controller_name class name of the controller
* @param string $action action name
* @return array
*/
public static function get_capabilities_required_for_controller_action(string $controller_name, string $action): array{
$required_capabilities = ['settings__edit']; // default capabilities, if not set on controller/action level
$capabilities_for_controllers = self::get_capabilities_for_all_controllers();
if(isset($capabilities_for_controllers[$controller_name])){
// try to get capabilities that are specific for action, if not get default for controller
if(isset($capabilities_for_controllers[$controller_name]['per_action'][$action])){
$required_capabilities = $capabilities_for_controllers[$controller_name]['per_action'][$action];
}elseif(isset($capabilities_for_controllers[$controller_name]['default'])){
$required_capabilities = $capabilities_for_controllers[$controller_name]['default'];
}
}
/**
* Get array of capabilities required to access controller's action
*
* @since 4.7.0
* @hook latepoint_get_capabilities_for_controller_action
*
* @param {array} $required_capabilities array of required capabilities
* @returns {array} The filtered array of required capabilities
*/
return apply_filters('latepoint_get_capabilities_for_controller_action', $required_capabilities, $controller_name, $action);
}
public static function save_capabilities_list_for_agent_role(array $capabilities){
return OsSettingsHelper::save_setting_by_name('agent_role_capabilities', wp_json_encode($capabilities));
}
public static function get_capabilities_list_for_agent_role(){
$capabilities = json_decode(OsSettingsHelper::get_settings_value('agent_role_capabilities', ''), true);
if(empty($capabilities)) $capabilities = self::get_default_capabilities_list_for_agent_role();
/**
* Get array of permitted actions for agent role
*
* @since 4.7.0
* @hook latepoint_get_capabilities_list_for_agent_role
*
* @param {array} $capabilities array of actions permitted to admin user type
* @returns {array} The filtered array of permitted actions
*/
return apply_filters('latepoint_get_capabilities_list_for_agent_role', $capabilities);
}
public static function get_all_available_actions_list_grouped(){
$actions = self::get_all_available_actions_list();
$groups = [];
foreach($actions as $action){
$object = explode('__', $action);
$groups[$object[0]][] = $object[1];
}
return $groups;
}
public static function save_from_params(array $role_params){
$role = \LatePoint\Misc\Role::generate_from_params($role_params);
if(empty($role->wp_role)) return new WP_Error('invalid_wp_role', __('WP Role invalid', 'latepoint'));
switch($role->user_type){
case LATEPOINT_USER_TYPE_AGENT:
if(self::save_capabilities_list_for_agent_role($role->get_capabilities())){
return true;
}else{
return new WP_Error('error_saving_role', __('WP Agent role can not be saved', 'latepoint'));
}
break;
case LATEPOINT_USER_TYPE_CUSTOM:
$roles = self::get_custom_roles();
$roles[$role->wp_role] = $role->as_array_to_save();
if(OsSettingsHelper::save_setting_by_name('custom_roles', wp_json_encode($roles))){
// register in WP (it's ok to register it on every save, we remove it first and then add, to make sure display name is updated)
$role->register_in_wp();
return true;
}else{
return new WP_Error('error_saving_role', __('WP Role can not be saved', 'latepoint'));
}
break;
default:
return new WP_Error('invalid_role_type', __('Invalid role type', 'latepoint'));
break;
}
}
public static function get_wp_roles_list($remove_admins = true) : array{
// this makes sure that the default customer role is created, before showing a list of roles
OsSettingsHelper::get_default_wp_role_for_new_customers();
global $wp_roles;
if (!isset($wp_roles)) {
$wp_roles = new WP_Roles();
}
$roles = $wp_roles->get_names();
if($remove_admins){
unset($roles['administrator']);
unset($roles['editor']);
unset($roles['shop_manager']);
unset($roles['sc_shop_manager']);
}
/**
* List of WP roles that you can assign to a new customer
*
* @since 5.2.0
* @hook latepoint_wp_roles_list_for_customer
*
* @param {array} $roles list of roles in array
* @param {array} $remove_admins whether to remove admin roles or not
* @returns {array} The filtered list of roles
*/
return apply_filters('latepoint_wp_roles_list_for_customer', $roles, $remove_admins);
}
public static function register_customer_role(){
// Register Customer Role
add_role( LATEPOINT_WP_CUSTOMER_ROLE, __('LatePoint Customer', 'latepoint'), array( 'read' => true ) );
}
public static function register_roles_in_wp(){
// Register Agent Role
$role = \LatePoint\Misc\Role::get_from_wp_role(LATEPOINT_WP_AGENT_ROLE);
$role->register_in_wp();
self::register_customer_role();
// Register Custom Roles
$custom_roles = self::get_custom_roles(true);
if($custom_roles){
foreach($custom_roles as $custom_role){
$custom_role->register_in_wp();
}
}
}
public static function get_model_types_for_allowed_records(){
return ['agent', 'service', 'location'];
}
public static function generate_role_id(){
return strtolower('role_'.OsUtilHelper::random_text('alnum', 8));
}
public static function get_custom_roles($as_objects = false): array{
$roles = json_decode(\OsSettingsHelper::get_settings_value('custom_roles', ''), true) ?? [];
if($as_objects){
$roles_objects = [];
foreach($roles as $role_params){
$roles_objects[$role_params['wp_role']] = \LatePoint\Misc\Role::generate_from_params($role_params);
}
return $roles_objects;
}else{
return $roles;
}
}
public static function save_custom_roles(array $roles){
return \OsSettingsHelper::save_setting_by_name('custom_roles', wp_json_encode($roles));
}
public static function delete(string $wp_role): bool{
// can't delete default roles (admin and agent)
if(in_array($wp_role, [LATEPOINT_WP_ADMIN_ROLE, LATEPOINT_WP_AGENT_ROLE])) return false;
// get all custom roles to make sure the one that needs to be deleted is custom role
$custom_roles = self::get_custom_roles();
if(isset($custom_roles[$wp_role])){
unset($custom_roles[$wp_role]);
self::save_custom_roles($custom_roles);
remove_role($wp_role);
}
return true;
}
public static function get_default_roles(): array{
$roles = [];
$roles[] = new \LatePoint\Misc\Role(LATEPOINT_USER_TYPE_ADMIN);
$roles[] = new \LatePoint\Misc\Role(LATEPOINT_USER_TYPE_AGENT);
return $roles;
}
public static function description_for_action($action_code){
$action_descriptions = [
'resource_schedule' => __('Edit custom schedule of individual agent, location or service.', 'latepoint'),
'settings' => __('Access to all settings pages, including general schedule and booking steps.', 'latepoint'),
'connection' => __('Ability to connect agents to services and locations.', 'latepoint'),
'chat' => __('Ability to send messages to customers (available with chat addon).', 'latepoint'),
];
/**
* List of detailed descriptions for available actions
*
* @since 4.7.2
* @hook latepoint_roles_action_descriptions
*
* @param {array} $action_descriptions Array of descriptions for available actions
* @param {string} $action_code Programmatic code of the action being filtered
* @returns {array} The filtered array of action descriptions
*/
$action_descriptions = apply_filters('latepoint_roles_action_descriptions', $action_descriptions, $action_code);
return $action_descriptions[$action_code] ?? '';
}
public static function name_for_action($action_code){
$action_names = [
'chat' => __('Chat', 'latepoint'),
'activity' => __('Activity Logs', 'latepoint'),
'agent' => __('Agents', 'latepoint'),
'service' => __('Services', 'latepoint'),
'bundle' => __('Bundle', 'latepoint'),
'location' => __('Locations', 'latepoint'),
'booking' => __('Bookings & Orders', 'latepoint'),
'customer' => __('Customers', 'latepoint'),
'transaction' => __('Payments', 'latepoint'),
'invoice' => __('Invoice', 'latepoint'),
'order' => __('Order', 'latepoint'),
'resource_schedule' => __('Resource Schedules', 'latepoint'),
'settings' => __('Settings', 'latepoint'),
'connection' => __('Connections', 'latepoint'),
'edit' => __('Edit', 'latepoint'),
'delete' => __('Delete', 'latepoint'),
'view' => __('View', 'latepoint'),
'create' => __('Create', 'latepoint'),
];
/**
* List of human-friendly names for available actions
*
* @since 4.7.2
* @hook latepoint_roles_action_names
*
* @param {array} $action_names Array of names for available actions
* @param {string} $action_code Programmatic code of the action being filtered
* @returns {array} The filtered array of action names
*/
$action_names = apply_filters('latepoint_roles_action_names', $action_names, $action_code);
return $action_names[$action_code] ?? $action_code;
}
public static function get_default_capabilities_list_for_agent_role(){
$capabilities = [
'agent__view', 'agent__edit' ,
'booking__view', 'booking__delete' ,'booking__create', 'booking__edit',
'customer__view', 'customer__delete' ,'customer__create', 'customer__edit',
'transaction__view', 'transaction__delete' ,'transaction__create', 'transaction__edit',
'invoice__view', 'invoice__delete' ,'invoice__create', 'invoice__edit',
'activity__view', 'activity__delete' ,'activity__create', 'activity__edit',
'chat__edit', 'resource_schedule__edit'
];
/**
* Default list of permitted actions available for agent user type
*
* @since 4.7.0
* @hook latepoint_roles_get_default_capabilities_list_for_agent_role
*
* @param {array} $capabilities array of permitted actions available to agent user type by default
* @returns {array} The filtered array of permitted actions
*/
return apply_filters('latepoint_roles_get_default_capabilities_list_for_agent_role', $capabilities);
}
public static function get_all_available_actions_list(){
$actions = [
'agent__view', 'agent__delete' ,'agent__create', 'agent__edit' ,
'service__view', 'service__delete' ,'service__create', 'service__edit' ,
'bundle__view', 'bundle__delete' ,'bundle__create', 'bundle__edit' ,
'location__view', 'location__delete' ,'location__create', 'location__edit' ,
'service_extra__view', 'service_extra__delete' ,'service_extra__create', 'service_extra__edit' ,
'booking__view', 'booking__delete' ,'booking__create', 'booking__edit' ,
'customer__view', 'customer__delete' ,'customer__create', 'customer__edit' ,
'transaction__view', 'transaction__delete' ,'transaction__create', 'transaction__edit' ,
'invoice__view', 'invoice__delete' ,'invoice__create', 'invoice__edit' ,
'activity__view', 'activity__delete' ,'activity__create', 'activity__edit' ,
'chat__edit', 'resource_schedule__edit', 'settings__edit', 'connection__edit'
];
/**
* All available actions to be attached to a user role
*
* @since 4.7.0
* @hook latepoint_roles_get_all_available_actions_list
*
* @param {array} $actions array of actions that can be attached to a user role
* @returns {array} The filtered array of actions
*/
return apply_filters('latepoint_roles_get_all_available_actions_list', $actions);
}
/**
* @param \LatePoint\Misc\Role $role
* @return \LatePoint\Misc\User[]
*/
public static function get_users_for_role(\LatePoint\Misc\Role $role): array{
$users = [];
$wp_users = [];
switch($role->user_type){
case LATEPOINT_USER_TYPE_ADMIN:
$wp_users = get_users(['role__in' => LATEPOINT_WP_ADMIN_ROLE]);
break;
case LATEPOINT_USER_TYPE_AGENT:
$wp_users = get_users(['role' => LATEPOINT_WP_AGENT_ROLE]);
break;
case LATEPOINT_USER_TYPE_CUSTOM:
if($role->wp_role) $wp_users = get_users(['role' => $role->wp_role]);
break;
}
foreach($wp_users as $wp_user){
$users[] = \LatePoint\Misc\User::load_from_wp_user($wp_user);
}
return $users;
}
public static function get_user_roles($user): array {
return [];
}
/**
* Checks if currently logged in user has certain capabilities
*
* @param array|string $capabilities array or string of capabilities that you want to check if logged in user has or not
* @return bool
*/
public static function can_user($capabilities) :bool{
if (OsAuthHelper::get_current_user()) {
return OsAuthHelper::get_current_user()->has_capability( $capabilities );
}
return false;
}
public static function get_allowed_records(string $model_type, $load_from_db = false){
return OsAuthHelper::get_current_user()->get_allowed_records($model_type, $load_from_db);
}
public static function are_all_records_allowed(string $model_type = '', $load_from_db = false): bool{
return OsAuthHelper::get_current_user()->are_all_records_allowed($model_type, $load_from_db);
}
/*
* Pass filter object or an array of arguments for a query to be filtered based on what logged in user is allowed to access
*/
public static function filter_allowed_records_from_arguments_or_filter($args_or_filter){
$model_types = ['agent', 'location', 'service'];
foreach($model_types as $model_type){
if(!OsAuthHelper::get_current_user()->are_all_records_allowed($model_type)){
$prop = $model_type.'_id';
// get value that needs to be filtered by allowed records
$value = ($args_or_filter instanceof \LatePoint\Misc\Filter) ? $args_or_filter->$prop ?? [] : $args_or_filter[$prop] ?? [];
if(empty($value)){
// no value is set - limit it to allowed records
$value = OsAuthHelper::get_current_user()->get_allowed_records($model_type);
}else{
// value is set - make sure it's in the allowed records list, if not - set to allowed records
$allowed_from_set = array_intersect(is_array($value) ? $value : [$value], OsAuthHelper::get_current_user()->get_allowed_records($model_type));
$value = empty($allowed_from_set) ? OsAuthHelper::get_current_user()->get_allowed_records($model_type) : $allowed_from_set;
}
if($args_or_filter instanceof \LatePoint\Misc\Filter){
$args_or_filter->$prop = $value;
}elseif(is_array($args_or_filter)){
$args_or_filter[$prop] = $value;
}
}
}
return $args_or_filter;
}
}