706 lines
18 KiB
PHP
706 lines
18 KiB
PHP
<?php
|
|
/**
|
|
* The AWB_Access_Control class.
|
|
*
|
|
* @package fusion-builder
|
|
*/
|
|
|
|
// Exit if accessed directly.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* The AWB_Access_Control class.
|
|
*
|
|
* @since 3.9
|
|
*/
|
|
class AWB_Access_Control {
|
|
|
|
/**
|
|
* The one, true instance of this object.
|
|
*
|
|
* @static
|
|
* @access private
|
|
* @since 3.9
|
|
* @var object
|
|
*/
|
|
private static $instance;
|
|
|
|
/**
|
|
* Disabled post types.
|
|
*
|
|
* @access private
|
|
* @since 3.9
|
|
* @var array
|
|
*/
|
|
private static $allowed_post_types = [
|
|
'fusion_tb_layout',
|
|
'fusion_tb_section',
|
|
'awb_off_canvas',
|
|
'fusion_icons',
|
|
'fusion_form',
|
|
'slide',
|
|
'fusion_template',
|
|
'fusion_element',
|
|
'avada_library',
|
|
'avada_portfolio',
|
|
'avada_faq',
|
|
'post',
|
|
'page',
|
|
];
|
|
|
|
/**
|
|
* Capabilities data.
|
|
*
|
|
* @access private
|
|
* @since 3.9
|
|
* @var array
|
|
*/
|
|
private static $capabilities;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @access public
|
|
*/
|
|
public function __construct() {
|
|
$this->set_capabilities();
|
|
$this->add_hooks();
|
|
}
|
|
|
|
/**
|
|
* Creates or returns an instance of this class.
|
|
*
|
|
* @static
|
|
* @access public
|
|
* @since 3.9
|
|
* @return object
|
|
*/
|
|
public static function get_instance() {
|
|
|
|
// If an instance hasn't been created and set to $instance create an instance and set it to $instance.
|
|
if ( null === self::$instance ) {
|
|
self::$instance = new AWB_Access_Control();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Sets capabilities from fusion settings.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @return void
|
|
*/
|
|
private function set_capabilities() {
|
|
$option = get_option( 'fusion_builder_settings', [] );
|
|
|
|
if ( null === self::$capabilities && isset( $option['capabilities'] ) ) {
|
|
self::$capabilities = $option['capabilities'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds necessary hooks for access control.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @return void
|
|
*/
|
|
private function add_hooks() {
|
|
|
|
// Live editor access.
|
|
add_filter( 'fusion_load_live_editor', [ $this, 'load_live_editor' ], PHP_INT_MAX, 1 );
|
|
|
|
// Backend builder access.
|
|
add_filter( 'awb_load_builder', [ $this, 'load_builder' ], PHP_INT_MAX, 1 );
|
|
|
|
// Page Options.
|
|
add_filter( 'awb_add_po_metabox', [ $this, 'page_options' ], PHP_INT_MAX, 2 );
|
|
|
|
// Dashboard Menu CPTs.
|
|
add_filter( 'awb_dashboard_menu_cpt', [ $this, 'dashboard_menu_cpt' ], PHP_INT_MAX, 2 );
|
|
|
|
// Form submissions filter.
|
|
add_filter( 'awb_view_forms_submissions', [ $this, 'forms_submissions' ], PHP_INT_MAX, 1 );
|
|
|
|
// Live editor new post menu.
|
|
add_filter( 'awb_live_editor_cpt', [ $this, 'live_editor_cpt' ], PHP_INT_MAX, 2 );
|
|
|
|
// Dashboard Menu Options.
|
|
add_filter( 'awb_dashboard_options_menu', [ $this, 'dashboard_menu_options' ], PHP_INT_MAX, 1 );
|
|
|
|
// Global elements.
|
|
add_filter( 'awb_global_elements_access', [ $this, 'global_element_access' ], PHP_INT_MAX, 1 );
|
|
|
|
// Global elements hook.
|
|
add_action( 'load-post.php', [ $this, 'direct_edit_access' ] );
|
|
}
|
|
|
|
/**
|
|
* Should user be able to access the dashboard options menu?
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default Current default value.
|
|
* @return bool
|
|
*/
|
|
public function dashboard_menu_options( $default ) {
|
|
return $this->request_general_filter( $default, 'global_options' );
|
|
}
|
|
|
|
/**
|
|
* Should user be able to access the global elements?
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default Current default value.
|
|
* @return bool
|
|
*/
|
|
public function global_element_access( $default ) {
|
|
return $this->request_general_filter( $default, 'global_elements' );
|
|
}
|
|
|
|
/**
|
|
* Should user be able to access the forms submissions?
|
|
*
|
|
* @since 3.9.2
|
|
* @access public
|
|
* @param bool $default Current default value.
|
|
* @return bool
|
|
*/
|
|
public function forms_submissions( $default ) {
|
|
return $this->request_general_filter( $default, 'fusion_form_submissions' );
|
|
}
|
|
|
|
/**
|
|
* Should user be able to edit the post directly?
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function direct_edit_access() {
|
|
$post_id = isset( $_GET['post'] ) ? sanitize_text_field( wp_unslash( $_GET['post'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification
|
|
$post_type = get_post_type( $post_id );
|
|
|
|
if ( $post_type ) {
|
|
// Skip built in posts.
|
|
if ( in_array( $post_type, [ 'post', 'page' ], true ) ) {
|
|
return;
|
|
}
|
|
|
|
// Global elements access.
|
|
if ( isset( $post_id ) && 'yes' === get_post_meta( $post_id, '_fusion_is_global', true ) && ! apply_filters( 'awb_global_elements_access', true ) ) {
|
|
wp_die( __( 'Sorry, you are not allowed to access this page.' ), 403 ); // phpcs:ignore WordPress.Security.EscapeOutput
|
|
}
|
|
|
|
// CPTs access.
|
|
if ( in_array( $post_type, self::get_allowed_post_types(), true ) && ! apply_filters( 'awb_dashboard_menu_cpt', true, $post_type ) ) {
|
|
wp_die( __( 'Sorry, you are not allowed to access this page.' ), 403 ); // phpcs:ignore WordPress.Security.EscapeOutput
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Should user be able to access the dashboard CPT menu?
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default Current default value.
|
|
* @param string $post_type Current post type.
|
|
* @return bool
|
|
*/
|
|
public function dashboard_menu_cpt( $default, $post_type ) {
|
|
$post_type = empty( $post_type ) ? $this->get_current_post_type() : $post_type;
|
|
|
|
if ( 'post' === $post_type || 'page' === $post_type ) {
|
|
return true;
|
|
}
|
|
|
|
return $this->request_cpt_filter( $default, $post_type, 'dashboard_menu' );
|
|
}
|
|
|
|
/**
|
|
* Should user be able to access the Live editor CPT menu?
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default Current default value.
|
|
* @param string $post_type Current post type.
|
|
* @return bool
|
|
*/
|
|
public function live_editor_cpt( $default, $post_type ) {
|
|
$post_type = empty( $post_type ) ? $this->get_current_post_type() : $post_type;
|
|
|
|
return $this->request_cpt_filter( $default, $post_type, 'avada_live' );
|
|
}
|
|
|
|
/**
|
|
* Should user be able to access page options?
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default Current default value.
|
|
* @param string $post_type Current post type.
|
|
* @return bool
|
|
*/
|
|
public function page_options( $default, $post_type ) {
|
|
return $this->request_cpt_filter( $default, $post_type, 'page_options' );
|
|
}
|
|
|
|
/**
|
|
* Live editor filter.
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default The default value.
|
|
* @return bool
|
|
*/
|
|
public function load_live_editor( $default ) {
|
|
$post_type = $this->get_current_post_type();
|
|
|
|
return $this->request_cpt_filter( $default, $post_type, 'avada_live' );
|
|
}
|
|
|
|
/**
|
|
* Live builder.
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default The default value.
|
|
* @return bool
|
|
*/
|
|
public function load_builder( $default ) {
|
|
$post_type = $this->get_current_post_type();
|
|
|
|
return $this->request_cpt_filter( $default, $post_type, 'avada_builder' );
|
|
}
|
|
|
|
/**
|
|
* Filters general request.
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default Current default value.
|
|
* @param string $request request type.
|
|
* @return bool
|
|
*/
|
|
public function request_general_filter( $default, $request ) {
|
|
|
|
if ( $this->is_administrator() ) {
|
|
return true;
|
|
}
|
|
|
|
if ( ! $this->role_can( $this->get_current_user_highest_role(), $request ) ) {
|
|
$default = false;
|
|
}
|
|
|
|
return $default;
|
|
}
|
|
|
|
/**
|
|
* Filters CTP request.
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param bool $default Current default value.
|
|
* @param string $post_type Current post type.
|
|
* @param string $request request type.
|
|
* @return bool
|
|
*/
|
|
public function request_cpt_filter( $default, $post_type, $request ) {
|
|
|
|
if ( $this->is_administrator() || ! in_array( $post_type, self::get_allowed_post_types(), true ) ) {
|
|
return true;
|
|
}
|
|
|
|
if ( ! $this->role_can_for_cpt( $this->get_current_user_highest_role(), $request, $post_type ) ) {
|
|
$default = false;
|
|
}
|
|
|
|
return $default;
|
|
}
|
|
|
|
/**
|
|
* Checks if role has specified access for CPT.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @param string $role The role.
|
|
* @param string $type The access type.
|
|
* @param string $post_type The post type.
|
|
* @return bool
|
|
*/
|
|
private function role_can_for_cpt( $role, $type, $post_type ) {
|
|
$post_type = in_array( $post_type, [ 'fusion_template', 'fusion_element' ], true ) ? 'avada_library' : $post_type;
|
|
$role = $this->get_role_id( $role );
|
|
|
|
if ( ( in_array( $post_type, self::get_allowed_post_types(), true ) && is_array( self::$capabilities ) && isset( self::$capabilities[ $role ] ) && in_array( $post_type . '_' . $type, self::$capabilities[ $role ], true ) ) || null === self::$capabilities ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Checks if role has specified access.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @param string $role The role.
|
|
* @param string $type The access type.
|
|
* @return bool
|
|
*/
|
|
private function role_can( $role, $type ) {
|
|
$role = $this->get_role_id( $role );
|
|
|
|
if ( ( is_array( self::$capabilities ) && isset( self::$capabilities[ $role ] ) && in_array( $type, self::$capabilities[ $role ], true ) ) || null === self::$capabilities ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Gets role ID.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @param string $role The role.
|
|
* @return string
|
|
*/
|
|
private function get_role_id( $role ) {
|
|
return strtolower( str_replace( [ ' ', '-' ], '_', $role ) );
|
|
}
|
|
|
|
/**
|
|
* Gets current post type.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function get_current_post_type() {
|
|
global $typenow, $pagenow;
|
|
|
|
$post_type = $typenow;
|
|
|
|
if ( is_admin() ) {
|
|
if ( 'edit.php' === $pagenow && '' === $typenow ) {
|
|
$post_type = 'post';
|
|
}
|
|
|
|
if ( '' === $post_type ) {
|
|
$post_type = $this->get_custom_screen_post_type();
|
|
}
|
|
} elseif ( ! is_admin() && isset( $_SERVER['REQUEST_URI'] ) && false === strpos( $_SERVER['REQUEST_URI'], 'fb-edit' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
|
$post_type = get_post_type();
|
|
} elseif ( isset( $_SERVER['REQUEST_URI'] ) && false !== strpos( $_SERVER['REQUEST_URI'], 'fb-edit' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
|
$post_type = $this->get_live_editor_post_type();
|
|
}
|
|
|
|
$post_type = in_array( $post_type, [ 'fusion_template', 'fusion_element' ], true ) ? 'avada_library' : $post_type;
|
|
|
|
return apply_filters( 'awb_access_control_current_screen_post_type', $post_type );
|
|
}
|
|
|
|
/**
|
|
* Gets current page post type in live editor.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function get_live_editor_post_type() {
|
|
global $wp_rewrite;
|
|
|
|
$fusion_settings = class_exists( 'Fusion_Settings' ) ? awb_get_fusion_settings() : false;
|
|
$url = $this->get_current_page_url();
|
|
$post_type = '';
|
|
$portfolio_slug = $fusion_settings && '' !== $fusion_settings->get( 'portfolio_slug' ) ? $fusion_settings->get( 'portfolio_slug' ) : 'portfolio-items';
|
|
$faqs_slug = $fusion_settings && '' !== $fusion_settings->get( 'faq_slug' ) ? $fusion_settings->get( 'faq_slug' ) : 'faq-items';
|
|
$post_types = [
|
|
'awb_off_canvas' => 'awb_off_canvas',
|
|
'fusion_tb_section' => 'fusion_tb_section',
|
|
'fusion_form' => 'fusion_form',
|
|
'fusion_element' => 'fusion_element',
|
|
'fusion_template' => 'fusion_template',
|
|
'avada_portfolio' => $portfolio_slug,
|
|
'avada_faq' => $faqs_slug,
|
|
];
|
|
|
|
foreach ( $post_types as $item ) {
|
|
if ( false !== strpos( $url, $item ) ) {
|
|
$post_type = $item;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( empty( $post_type ) && ! is_null( $wp_rewrite ) ) {
|
|
$post_type = get_post_type( url_to_postid( $url ) );
|
|
}
|
|
|
|
if ( false === $post_type && get_home_url() === $url && 'page' === get_option( 'show_on_front' ) ) {
|
|
$post_type = 'page';
|
|
}
|
|
|
|
return $post_type;
|
|
}
|
|
|
|
/**
|
|
* Gets current page URL.
|
|
*
|
|
* @since 3.9.2
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function get_current_page_url() {
|
|
$url = '';
|
|
if ( isset( $_SERVER['HTTPS'] ) && 'on' === $_SERVER['HTTPS'] ) {
|
|
$url = 'https://';
|
|
} else {
|
|
$url = 'http://';
|
|
}
|
|
|
|
$url .= isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
|
$url .= isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
|
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* Gets post type for custom screens.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function get_custom_screen_post_type() {
|
|
$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
|
|
$screens = [
|
|
'avada-layout-sections' => 'fusion_tb_section',
|
|
'avada-off-canvas' => 'awb_off_canvas',
|
|
'avada-icons' => 'fusion_icons',
|
|
'avada-forms' => 'fusion_form',
|
|
'avada-form-entries' => 'fusion_form',
|
|
'avada-library' => 'avada_library',
|
|
];
|
|
|
|
return isset( $screens[ $page ] ) ? $screens[ $page ] : '';
|
|
}
|
|
|
|
/**
|
|
* Checks if current user is administrator.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @return bool
|
|
*/
|
|
private function is_administrator() {
|
|
return current_user_can( 'administrator' );
|
|
}
|
|
|
|
/**
|
|
* Gets current logged in user highest role.
|
|
*
|
|
* @since 3.9
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private function get_current_user_highest_role() {
|
|
$role = [];
|
|
|
|
if ( is_user_logged_in() ) {
|
|
$user = wp_get_current_user();
|
|
$user_roles = (array) $user->roles;
|
|
|
|
foreach ( $user_roles as $user_role ) {
|
|
$role_data = get_role( $user_role );
|
|
$capabilities_count = isset( $role_data->capabilities ) ? count( $role_data->capabilities ) : 0;
|
|
if ( empty( $role ) ) {
|
|
$role['role'] = $user_role;
|
|
$role['capabilities'] = $capabilities_count;
|
|
} elseif ( $capabilities_count > $role['capabilities'] ) {
|
|
$role['role'] = $user_role;
|
|
$role['capabilities'] = $capabilities_count;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isset( $role['role'] ) && isset( wp_roles()->get_names()[ $role['role'] ] ) ) {
|
|
return $this->get_role_id( wp_roles()->get_names()[ $role['role'] ] );
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if current capability is available for role and echos/returns checked.
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @param string $role_id The role ID.
|
|
* @param string $capability The capability to check for.
|
|
* @param bool $echo Should echo or return value.
|
|
* @return mixed
|
|
*/
|
|
public static function maybe_checked( $role_id, $capability, $echo = true ) {
|
|
if ( ( is_array( self::$capabilities ) && isset( self::$capabilities[ $role_id ] ) && in_array( $capability, self::$capabilities[ $role_id ], true ) ) || null === self::$capabilities ) {
|
|
if ( $echo ) {
|
|
echo 'checked';
|
|
} else {
|
|
return 'checked';
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates dummy library object.
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
public static function get_library_object() {
|
|
$obj = new stdClass();
|
|
|
|
$obj->label = __( 'Avada Library', 'fusion-builder' );
|
|
$obj->name = 'avada_library';
|
|
|
|
return $obj;
|
|
}
|
|
|
|
/**
|
|
* Prefixes Avada in post label if does not exist.
|
|
*
|
|
* @since 3.9
|
|
* @param array $post The post object.
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
public static function get_post_type_label( $post ) {
|
|
$label = '';
|
|
if ( ( is_object( $post ) && property_exists( $post, '_builtin' ) && $post->_builtin ) || false !== strpos( $post->label, 'Avada' ) ) {
|
|
$label = $post->label;
|
|
} else {
|
|
$label = __( 'Avada', 'fusion-builder' ) . ' ' . $post->label;
|
|
}
|
|
|
|
return apply_filters( 'awb_access_control_post_type_label', $label );
|
|
}
|
|
|
|
/**
|
|
* Method to display options.
|
|
*
|
|
* @since 3.9
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public static function display_options() {
|
|
$roles = self::get_user_roles();
|
|
$post_types = self::get_allowed_post_types();
|
|
|
|
// Remove templates and elements. So that library option can be used for both.
|
|
$post_types = array_diff( $post_types, [ 'fusion_template', 'fusion_element' ] );
|
|
|
|
foreach ( $roles as $role ) {
|
|
self::display_options_for_a_role( $role, $post_types );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Displays options for a role.
|
|
*
|
|
* @since 3.9
|
|
* @param array $role Object of user role.
|
|
* @param array $post_types Object of post types.
|
|
* @access private
|
|
* @return void
|
|
*/
|
|
private static function display_options_for_a_role( $role, $post_types ) {
|
|
$template = locate_template( [ 'template-user-roles.php' ] );
|
|
if ( ! empty( $template ) ) {
|
|
include $template;
|
|
} else {
|
|
include FUSION_BUILDER_PLUGIN_DIR . 'templates/template-user-roles.php';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets user roles.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public static function get_user_roles() {
|
|
$roles = get_editable_roles();
|
|
|
|
// Remove admin role.
|
|
unset( $roles['administrator'] );
|
|
|
|
return $roles;
|
|
}
|
|
|
|
/**
|
|
* Checks if role has got specific WP core capabilities.
|
|
*
|
|
* @since 3.9
|
|
* @param string $role The WP user role.
|
|
* @param array $capabilities Array of capabilities.
|
|
* @param string $operator The and/or operator.
|
|
* @access private
|
|
* @return boolean
|
|
*/
|
|
public static function wp_role_has_core_capability( $role, $capabilities, $operator = 'and' ) {
|
|
$role_can = false;
|
|
foreach ( $capabilities as $capability ) {
|
|
if ( isset( $role['capabilities'][ $capability ] ) && true === $role['capabilities'][ $capability ] ) {
|
|
$role_can = true;
|
|
} elseif ( 'and' === $operator ) {
|
|
$role_can = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $role_can;
|
|
}
|
|
|
|
/**
|
|
* Checks if user has certain WP core capability for a post.
|
|
*
|
|
* @since 3.9
|
|
* @param string $post_type The post type.
|
|
* @param string $capability The capability.
|
|
* @access private
|
|
* @return boolean
|
|
*/
|
|
public static function wp_user_can_for_post( $post_type, $capability ) {
|
|
$post_type_object = get_post_type_object( $post_type );
|
|
return current_user_can( $post_type_object->cap->{$capability} );
|
|
}
|
|
|
|
/**
|
|
* Gets allowed post types.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public static function get_allowed_post_types() {
|
|
return apply_filters( 'awb_access_control_post_types', self::$allowed_post_types );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Instantiates the AWB_Access_Control class.
|
|
* Make sure the class is properly set-up.
|
|
*
|
|
* @since object 3.9
|
|
* @return object AWB_Access_Control
|
|
*/
|
|
function AWB_Access_Control() { // phpcs:ignore WordPress.NamingConventions
|
|
return AWB_Access_Control::get_instance();
|
|
}
|
|
AWB_Access_Control();
|