Add gravity flow demo
This commit is contained in:
584
backend/wordpress/wp-content/plugins/view-admin-as/includes/class-compat.php
Executable file
584
backend/wordpress/wp-content/plugins/view-admin-as/includes/class-compat.php
Executable file
@@ -0,0 +1,584 @@
|
||||
<?php
|
||||
/**
|
||||
* View Admin As - Class Compat
|
||||
*
|
||||
* @author Jory Hogeveen <info@keraweb.nl>
|
||||
* @package View_Admin_As
|
||||
*/
|
||||
|
||||
if ( ! defined( 'VIEW_ADMIN_AS_DIR' ) ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatibility class.
|
||||
*
|
||||
* @author Jory Hogeveen <info@keraweb.nl>
|
||||
* @package View_Admin_As
|
||||
* @since 1.6
|
||||
* @version 1.8
|
||||
* @uses \VAA_View_Admin_As_Base Extends class
|
||||
*/
|
||||
final class VAA_View_Admin_As_Compat extends VAA_View_Admin_As_Base
|
||||
{
|
||||
/**
|
||||
* The single instance of the class.
|
||||
*
|
||||
* @since 1.6
|
||||
* @static
|
||||
* @var \VAA_View_Admin_As_Compat
|
||||
*/
|
||||
private static $_instance = null;
|
||||
|
||||
/**
|
||||
* Populate the instance.
|
||||
*
|
||||
* @since 1.6
|
||||
* @since 1.6.1 $vaa param.
|
||||
* @access protected
|
||||
* @param \VAA_View_Admin_As $vaa The main VAA object.
|
||||
*/
|
||||
protected function __construct( $vaa ) {
|
||||
self::$_instance = $this;
|
||||
parent::__construct( $vaa );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix compatibility issues.
|
||||
*
|
||||
* @since 0.1
|
||||
* @since 1.6 Moved third_party_compatibility() to this class from main class.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
$this->add_action( 'vaa_view_admin_as_init', array( $this, 'init_after' ) );
|
||||
|
||||
/**
|
||||
* Add our caps to the members plugin.
|
||||
* Hook `members_get_capabilities` also used by:
|
||||
* - User Role Editor (URE) >> Own filter: `ure_full_capabilites`
|
||||
* - WPFront User Role Editor
|
||||
* - Capability Manager Enhanced >> Own filter: `capsman_get_capabilities`
|
||||
* - Pods
|
||||
* - Yoast SEO 5.8+
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
$this->add_filter( 'members_get_capabilities', array( $this, 'get_vaa_capabilities' ) );
|
||||
$this->add_action( 'members_register_cap_groups', array( $this, 'action_members_register_cap_group' ) );
|
||||
|
||||
/**
|
||||
* Add our caps to the User Role Editor plugin (URE).
|
||||
* @since 1.6.4
|
||||
*/
|
||||
$this->add_filter( 'ure_capabilities_groups_tree', array( $this, 'filter_ure_capabilities_groups_tree' ) );
|
||||
$this->add_filter( 'ure_custom_capability_groups', array( $this, 'filter_ure_custom_capability_groups' ), 10, 2 );
|
||||
|
||||
/**
|
||||
* Get all capabilities.
|
||||
* @since 1.5
|
||||
*/
|
||||
$this->add_filter( 'view_admin_as_get_capabilities', array( $this, 'get_capabilities' ), 10, 2 );
|
||||
|
||||
/**
|
||||
* WP Admin UI Customize 1.5.11+.
|
||||
* @since 1.7.4
|
||||
*/
|
||||
// wauc_admin_bar_default_load
|
||||
$this->add_filter( 'wauc_admin_bar_menu_add_nodes', array( $this, 'filter_wauc_admin_bar_menu_add_nodes' ), 10, 2 );
|
||||
$this->add_filter( 'wauc_admin_bar_filter_load', array( $this, 'filter_wauc_admin_bar_filter_load' ) );
|
||||
$this->add_filter( 'wauc_admin_bar_menu_widget_no_submenu', array( $this, 'filter_wauc_admin_bar_menu_widget_no_submenu' ) );
|
||||
$this->add_filter( 'wauc_admin_bar_menu_widget_title_readonly_vaa', '__return_true' );
|
||||
$this->add_filter( 'wauc_admin_bar_menu_widget_disable_target_vaa', '__return_true' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix compatibility issues on load.
|
||||
* Called from 'vaa_view_admin_as_init' hook (after loading all data).
|
||||
*
|
||||
* @since 1.6.1
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function init_after() {
|
||||
|
||||
if ( $this->store->get_view() &&
|
||||
(int) $this->store->get_curUser()->ID === (int) $this->store->get_selectedUser()->ID
|
||||
) {
|
||||
// Only apply the filter if the current user is modified.
|
||||
$this->add_filter( 'pods_is_admin', array( $this, 'filter_pods_caps_check' ), 99, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's current capabilities and merges with capabilities from other plugins.
|
||||
*
|
||||
* @since 1.6
|
||||
* @access public
|
||||
* @see \VAA_View_Admin_As_Compat::init()
|
||||
*
|
||||
* @param array $caps The capabilities.
|
||||
* @param bool[] $args Pass arguments to get only certain capabilities.
|
||||
* @return array Both key and values are the capabilities.
|
||||
*/
|
||||
public function get_capabilities( $caps = array(), $args = array() ) {
|
||||
|
||||
$args = wp_parse_args( $args, array(
|
||||
'vaa' => true, // Get VAA related capabilities?
|
||||
'wp' => true, // Get WP core related capabilities?
|
||||
'plugins' => true, // Get capabilities from plugin hooks and filters?
|
||||
) );
|
||||
|
||||
if ( $args['vaa'] ) {
|
||||
$caps = $this->get_vaa_capabilities( $caps );
|
||||
}
|
||||
|
||||
if ( $args['wp'] ) {
|
||||
$caps = $this->get_wordpress_capabilities( $caps );
|
||||
}
|
||||
|
||||
if ( $args['plugins'] ) {
|
||||
$caps = $this->get_plugin_capabilities( $caps );
|
||||
}
|
||||
|
||||
// @since 1.8 Make sure both keys and values are capabilities.
|
||||
$all_caps = array();
|
||||
foreach ( $caps as $cap_key => $cap ) {
|
||||
if ( is_string( $cap ) && ! is_numeric( $cap ) ) {
|
||||
$all_caps[ $cap ] = $cap;
|
||||
} else {
|
||||
$all_caps[ $cap_key ] = $cap_key;
|
||||
}
|
||||
}
|
||||
|
||||
return $all_caps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our capabilities to an existing list of capabilities.
|
||||
*
|
||||
* @since 1.6
|
||||
* @since 1.7.3 Renamed from add_capabilities().
|
||||
* @access public
|
||||
* @see \VAA_View_Admin_As_Compat::init()
|
||||
*
|
||||
* @param array $caps The capabilities.
|
||||
* @return array
|
||||
*/
|
||||
public function get_vaa_capabilities( $caps = array() ) {
|
||||
|
||||
// Allow VAA modules to add their capabilities.
|
||||
foreach ( (array) apply_filters( 'view_admin_as_add_capabilities', array( 'view_admin_as' ) ) as $cap ) {
|
||||
$caps[ $cap ] = $cap;
|
||||
}
|
||||
|
||||
return $caps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all capabilities from WP core or WP objects.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @param array $caps The capabilities.
|
||||
* @return array
|
||||
*/
|
||||
public function get_wordpress_capabilities( $caps = array() ) {
|
||||
|
||||
// @since 1.7.1 Store available capabilities existing in roles.
|
||||
foreach ( $this->store->get_roles() as $key => $role ) {
|
||||
if ( is_array( $role->capabilities ) ) {
|
||||
foreach ( $role->capabilities as $cap => $grant ) {
|
||||
$caps[ (string) $cap ] = $cap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.7.1 Add post type and taxonomy caps.
|
||||
* @since 1.7.3 Prevent duplicate array keys.
|
||||
*/
|
||||
$wp_objects = array_merge(
|
||||
array_values( (array) get_post_types( array(), 'objects' ) ),
|
||||
array_values( (array) get_taxonomies( array(), 'objects' ) )
|
||||
);
|
||||
foreach ( $wp_objects as $obj ) {
|
||||
if ( isset( $obj->cap ) ) {
|
||||
// WP stores the object caps as general_cap_name => actual_cap.
|
||||
$caps = array_merge( array_combine( (array) $obj->cap, (array) $obj->cap ), $caps );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Other WordPress capabilities.
|
||||
* @since 1.7.4
|
||||
*/
|
||||
$caps = array_merge( array(
|
||||
// @since 4.9
|
||||
'activate_plugin',
|
||||
'deactivate_plugin',
|
||||
'deactivate_plugins',
|
||||
'install_languages',
|
||||
'update_languages',
|
||||
), $caps );
|
||||
|
||||
/**
|
||||
* Network capabilities.
|
||||
* @since 1.5.3
|
||||
* @since 1.7.2 Added new WP 4.8 caps.
|
||||
* https://make.wordpress.org/core/2017/05/22/multisite-focused-changes-in-4-8/
|
||||
* @see https://codex.wordpress.org/Roles_and_Capabilities
|
||||
*/
|
||||
if ( is_multisite() ) {
|
||||
$network_caps = array(
|
||||
'manage_network',
|
||||
'manage_sites',
|
||||
'manage_network_users',
|
||||
'manage_network_plugins',
|
||||
'manage_network_themes',
|
||||
'manage_network_options',
|
||||
);
|
||||
if ( VAA_API::validate_wp_version( '4.8' ) ) {
|
||||
$network_caps[] = 'upgrade_network';
|
||||
$network_caps[] = 'setup_network';
|
||||
}
|
||||
$caps = array_merge( array_combine( $network_caps, $network_caps ), $caps );
|
||||
}
|
||||
|
||||
return $caps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all capabilities from other plugins.
|
||||
*
|
||||
* Disable some PHPMD checks for this method.
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @todo Refactor to enable above checks?
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @param array $caps The capabilities.
|
||||
* @return array
|
||||
*/
|
||||
public function get_plugin_capabilities( $caps = array() ) {
|
||||
|
||||
// WooCommerce caps are not accessible but are assigned to roles on install.
|
||||
// get_wordpress_capabilities() will find them.
|
||||
|
||||
// @since 1.7.1 Gravity Forms.
|
||||
if ( VAA_API::exists_callable( array( 'GFCommon', 'all_caps' ) ) ) {
|
||||
$caps = array_merge( (array) GFCommon::all_caps(), $caps );
|
||||
}
|
||||
|
||||
// @since 1.7.1 User Role Editor.
|
||||
if ( VAA_API::exists_callable( array( 'URE_Own_Capabilities', 'get_caps' ) ) ) {
|
||||
$caps = array_merge( (array) URE_Own_Capabilities::get_caps(), $caps );
|
||||
}
|
||||
$caps = apply_filters( 'ure_full_capabilites', $caps );
|
||||
|
||||
// @since 1.7.1 WPFront User Role Editor.
|
||||
if ( class_exists( 'WPFront_User_Role_Editor' ) && ! empty( WPFront_User_Role_Editor::$ROLE_CAPS ) ) {
|
||||
$caps = array_merge( (array) WPFront_User_Role_Editor::$ROLE_CAPS, $caps );
|
||||
}
|
||||
|
||||
// @since 1.7.1 User Roles and Capabilities.
|
||||
if ( VAA_API::exists_callable( array( 'Solvease_Roles_Capabilities_User_Caps', 'solvease_roles_capabilities_caps' ) ) ) {
|
||||
$caps = array_merge( (array) Solvease_Roles_Capabilities_User_Caps::solvease_roles_capabilities_caps(), $caps );
|
||||
}
|
||||
|
||||
// @since 1.7.1 bbPress.
|
||||
if ( function_exists( 'bbp_get_caps_for_role' ) ) {
|
||||
if ( function_exists( 'bbp_get_keymaster_role' ) ) {
|
||||
$bbp_keymaster_role = bbp_get_keymaster_role();
|
||||
} else {
|
||||
$bbp_keymaster_role = apply_filters( 'bbp_get_keymaster_role', 'bbp_keymaster' );
|
||||
}
|
||||
$caps = array_merge( (array) bbp_get_caps_for_role( $bbp_keymaster_role ), $caps );
|
||||
}
|
||||
|
||||
// @since 1.7.1 BuddyPress.
|
||||
if ( class_exists( 'BuddyPress' ) ) {
|
||||
$caps = array_merge(
|
||||
array(
|
||||
'bp_moderate',
|
||||
'bp_xprofile_change_field_visibility',
|
||||
// @todo Check usage of capabilities below.
|
||||
/*
|
||||
'throttle',
|
||||
'keep_gate',
|
||||
'moderate_comments',
|
||||
'edit_cover_image',
|
||||
'edit_avatar',
|
||||
'edit_favorites',
|
||||
'edit_favorites_of',
|
||||
'add_tag_to',
|
||||
'edit_tag_by_on',
|
||||
'change_user_password',
|
||||
'moderate',
|
||||
'browse_deleted',
|
||||
'view_by_ip',
|
||||
'write_posts',
|
||||
'write_topic',
|
||||
'write_topics',
|
||||
'move_topic',
|
||||
'stick_topic',
|
||||
'close_topic',
|
||||
'edit_topic',
|
||||
'delete_topic',
|
||||
'delete_forum',
|
||||
'manage_forums',
|
||||
'manage_tags',
|
||||
*/
|
||||
),
|
||||
// @see bp_get_community_caps() >> bp-core-caps.php.
|
||||
apply_filters( 'bp_get_community_caps', array() ),
|
||||
$caps
|
||||
);
|
||||
} // End if().
|
||||
|
||||
// @since 1.7.4 Yoast SEO 5.5+ Load integration on front end.
|
||||
if ( ! is_admin() ) {
|
||||
/**
|
||||
* @since 1.8 Yoast SEO - Check for API function.
|
||||
* @link https://github.com/Yoast/wordpress-seo/pull/9365
|
||||
*/
|
||||
if ( function_exists( 'wpseo_get_capabilities' ) ) {
|
||||
$caps = array_merge( (array) wpseo_get_capabilities(), $caps );
|
||||
} elseif ( defined( 'WPSEO_VERSION' ) ) {
|
||||
$yoast_seo_caps = array(
|
||||
'wpseo_bulk_edit',
|
||||
'wpseo_edit_advanced_metadata',
|
||||
'wpseo_manage_options',
|
||||
);
|
||||
$caps = array_merge( $yoast_seo_caps, $caps );
|
||||
}
|
||||
}
|
||||
|
||||
// Members.
|
||||
if ( function_exists( 'members_get_plugin_capabilities' ) ) {
|
||||
$caps = array_merge( (array) members_get_plugin_capabilities(), $caps );
|
||||
}
|
||||
// Get caps from multiple plugins through the Members filter.
|
||||
$caps = apply_filters( 'members_get_capabilities', $caps );
|
||||
|
||||
// Pods.
|
||||
$caps = apply_filters( 'pods_roles_get_capabilities', $caps );
|
||||
|
||||
return $caps;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix compatibility issues Pods Framework 2.0+.
|
||||
*
|
||||
* @since 1.0.1
|
||||
* @since 1.6 Moved to this class from main class.
|
||||
* @since 1.6.2 Check for all provided capabilities.
|
||||
* @access public
|
||||
* @see \VAA_View_Admin_As_Compat::init()
|
||||
*
|
||||
* @param bool $bool Boolean provided by the pods_is_admin hook (not used).
|
||||
* @param array $caps String or Array provided by the pods_is_admin hook.
|
||||
* @return bool
|
||||
*/
|
||||
public function filter_pods_caps_check( $bool, $caps ) {
|
||||
|
||||
foreach ( (array) $caps as $capability ) {
|
||||
if ( $this->vaa->view()->current_view_can( $capability ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our capabilities to our own group in the Members plugin.
|
||||
*
|
||||
* @see members_register_cap_group()
|
||||
*
|
||||
* @since 1.6
|
||||
* @access public
|
||||
* @see \VAA_View_Admin_As_Compat::init()
|
||||
*/
|
||||
public function action_members_register_cap_group() {
|
||||
if ( ! function_exists( 'members_register_cap_group' ) ) {
|
||||
return;
|
||||
}
|
||||
// Register the vaa group.
|
||||
members_register_cap_group( 'view_admin_as',
|
||||
array(
|
||||
'label' => esc_html__( 'View Admin As', VIEW_ADMIN_AS_DOMAIN ),
|
||||
'caps' => $this->get_vaa_capabilities(),
|
||||
'icon' => 'dashicons-visibility',
|
||||
'diff_added' => true,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our our own capability group in the URE plugin.
|
||||
*
|
||||
* @since 1.6.4
|
||||
* @access public
|
||||
* @see \VAA_View_Admin_As_Compat::init()
|
||||
* @see \URE_Capabilities_Groups_Manager::get_groups_tree()
|
||||
* @param array $groups Current groups
|
||||
* @return array
|
||||
*/
|
||||
public function filter_ure_capabilities_groups_tree( $groups ) {
|
||||
$groups = (array) $groups;
|
||||
$groups['view_admin_as'] = array(
|
||||
'caption' => esc_html__( 'View Admin As', VIEW_ADMIN_AS_DOMAIN ),
|
||||
'parent' => 'custom',
|
||||
'level' => 3,
|
||||
);
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our capabilities to our own group in the URE plugin.
|
||||
*
|
||||
* @since 1.6.4
|
||||
* @access public
|
||||
* @see \VAA_View_Admin_As_Compat::init()
|
||||
* @see \URE_Capabilities_Groups_Manager::get_cap_groups()
|
||||
* @param array $groups Current capability groups
|
||||
* @param string $cap_id Capability identifier
|
||||
* @return array
|
||||
*/
|
||||
public function filter_ure_custom_capability_groups( $groups, $cap_id ) {
|
||||
if ( in_array( $cap_id, $this->get_vaa_capabilities(), true ) ) {
|
||||
$groups = (array) $groups;
|
||||
$groups[] = 'view_admin_as';
|
||||
}
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force user setting location when WAUC is active.
|
||||
*
|
||||
* Disable some PHPMD checks for this method.
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @todo Refactor to enable above checks?
|
||||
*
|
||||
* @since 1.7.4
|
||||
* @access public
|
||||
* @see \WP_Admin_UI_Customize::admin_bar_menu()
|
||||
* @param array $wauc_nodes
|
||||
* @param array $all_nodes
|
||||
* @return array
|
||||
*/
|
||||
public function filter_wauc_admin_bar_menu_add_nodes( $wauc_nodes, $all_nodes ) {
|
||||
|
||||
$admin_menu_location = $this->store->get_userSettings( 'admin_menu_location' );
|
||||
$vaa_root = VAA_View_Admin_As_Admin_Bar::$root;
|
||||
|
||||
$check = array(
|
||||
'depth' => 'main',
|
||||
);
|
||||
if ( 'my-account' === $admin_menu_location ) {
|
||||
$check['depth'] = 'sub';
|
||||
$check['location'] = 'right';
|
||||
$check['parent'] = $admin_menu_location;
|
||||
}
|
||||
|
||||
// Compat when this node is added twice.
|
||||
foreach ( $wauc_nodes as $location => $levels ) {
|
||||
foreach ( $levels as $depth => $nodes ) {
|
||||
foreach ( $nodes as $id => $node ) {
|
||||
if ( isset( $node['id'] ) && $vaa_root === $node['id'] ) {
|
||||
|
||||
$current = array(
|
||||
'depth' => $depth,
|
||||
'location' => $location,
|
||||
'parent' => $node['parent'],
|
||||
);
|
||||
|
||||
foreach ( $check as $key => $val ) {
|
||||
if ( $val !== $current[ $key ] ) {
|
||||
unset( $wauc_nodes[ $location ][ $depth ][ $id ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure all VAA nodes will be added.
|
||||
$wauc_nodes['vaa'] = array( 'sub' => array() );
|
||||
foreach ( $all_nodes as $node ) {
|
||||
$id = ( ! empty( $node->id ) ) ? $node->id : null;
|
||||
if ( $vaa_root !== $id && 0 === strpos( $id, $vaa_root ) ) {
|
||||
$wauc_nodes['vaa']['sub'][] = (array) $node;
|
||||
}
|
||||
}
|
||||
|
||||
return $wauc_nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove our nodes from the WAUC admin bar editor.
|
||||
* @since 1.7.4
|
||||
* @access public
|
||||
* @see \WP_Admin_UI_Customize::admin_bar_filter_load()
|
||||
* @param array $all_nodes
|
||||
* @return array
|
||||
*/
|
||||
public function filter_wauc_admin_bar_filter_load( $all_nodes ) {
|
||||
|
||||
if ( empty( $all_nodes['right'] ) ) {
|
||||
return $all_nodes;
|
||||
}
|
||||
|
||||
$slug = VAA_View_Admin_As_Admin_Bar::$root;
|
||||
|
||||
foreach ( (array) $all_nodes['right'] as $location => $nodes ) {
|
||||
if ( 0 !== strpos( $location, 'sub' ) ) {
|
||||
continue;
|
||||
}
|
||||
foreach ( $nodes as $key => $node ) {
|
||||
// Check if node ID starts with `vaa-` and node parent starts with `vaa`.
|
||||
if ( 0 === strpos( $node->id , $slug . '-' ) && 0 === strpos( $node->parent , $slug ) ) {
|
||||
unset( $all_nodes['right'][ $location ][ $key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
return $all_nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove submenu options for WAUC.
|
||||
* @since 1.7.4
|
||||
* @see \WP_Admin_UI_Customize::admin_bar_menu_widget()
|
||||
* @param array $no_submenu
|
||||
* @return array
|
||||
*/
|
||||
public function filter_wauc_admin_bar_menu_widget_no_submenu( $no_submenu ) {
|
||||
$no_submenu[] = VAA_View_Admin_As_Admin_Bar::$root;
|
||||
return $no_submenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main Instance.
|
||||
*
|
||||
* Ensures only one instance of this class is loaded or can be loaded.
|
||||
*
|
||||
* @since 1.6
|
||||
* @access public
|
||||
* @static
|
||||
* @param \VAA_View_Admin_As $caller The referrer class.
|
||||
* @return \VAA_View_Admin_As_Compat $this
|
||||
*/
|
||||
public static function get_instance( $caller = null ) {
|
||||
if ( is_null( self::$_instance ) ) {
|
||||
self::$_instance = new self( $caller );
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
} // End class VAA_View_Admin_As_Compat.
|
||||
Reference in New Issue
Block a user