/includes/core/classes/class-cp-cluster-toolbar.php
https://gitlab.com/clusterpress/clusterpress · PHP · 404 lines · 181 code · 62 blank · 161 comment · 33 complexity · 051ef8f7f95a8ce0092cf6a1580006d2 MD5 · raw file
- <?php
- /**
- * ClusterPress Toolbar Class.
- *
- * Extends the WP Admin Bar to manage any Cluster's Toolbar.
- *
- * @package ClusterPress\core\classes
- * @subpackage cluster-toolbar
- *
- * @since 1.0.0
- */
- /**
- * Make sure the WP_Admin_Bar is loaded.
- */
- if ( ! class_exists( 'WP_Admin_Bar' ) ) {
- require_once( ABSPATH . WPINC . '/class-wp-admin-bar.php' );
- }
- /**
- * The ClusterPress Toolbars class.
- *
- * @since 1.0.0
- */
- class CP_Cluster_Toolbar extends WP_Admin_Bar {
- /**
- * Only Used to avoid the WP Admin Bar to run the parent method.
- *
- * @since 1.0.0
- */
- public function initialize() {}
- /**
- * Only Used to avoid the WP Admin Bar to run the parent method.
- *
- * @since 1.0.0
- */
- public function add_menus() {}
- /**
- * Only Used to avoid the WP Admin Bar to run the parent method.
- *
- * @since 1.0.0
- */
- public function render() {}
- /**
- * Add a node to the nav items.
- *
- * @since 1.0.0
- *
- * @param array $args {
- * @see WP_Admin_Bar::add_node() for the argument descriptions.
- * }
- */
- public function add_node( $args ) {
- $r = wp_parse_args( $args, array(
- 'capability' => 'cp_read_single_user',
- ) );
- parent::add_node( $r );
- }
- /**
- * Edit a node of the nav.
- *
- * @since 1.0.0
- *
- * @param string $node_id The Node ID to edit (NB: ClusterPress is using the rewrite_ids).
- * @param array $args {
- * @see WP_Admin_Bar::add_node() for the argument descriptions.
- * }
- */
- public function edit_node( $node_id, $args = array() ) {
- $node = $this->get_node( $node_id );
- if ( ! $node ) {
- return false;
- }
- $r = wp_parse_args( $args, (array) $node );
- $this->_set_node( $r );
- }
- /**
- * Set the URLs of the nav items.
- *
- * @since 1.0.0
- *
- * @param array $args {
- * An array of arguments.
- * @type WP_User|WP_Site $object The Object the nav item applies to.
- * @type string $type The Object type (WP_User or WP_Site).
- * @type string $parent_group The Parent Nav. Defaults to 'single-bar'.
- * @type string $url_callback The callback function to build the URL.
- * @type string $filter The name of the filter to override the nav item's data.
- * @type array $capability_args An array containing the capability and additional arguments.
- * }
- * @return array The list of nav items.
- */
- public function populate_urls( $args = array() ) {
- $r = wp_parse_args( $args, array(
- 'object' => null,
- 'type' => '',
- 'parent_group' => 'single-bar',
- 'url_callback' => '',
- 'filter' => '',
- 'capability_args' => array(),
- ) );
- if ( empty( $r['object'] ) || empty( $r['type'] ) || empty( $r['url_callback'] ) || ! is_a( $r['object'], $r['type'] ) ) {
- return false;
- }
- $nodes = wp_list_filter( $this->get_nodes(), array( 'parent_group' => $r['parent_group'] ) );
- if ( ! is_array( $nodes ) ) {
- return false;
- }
- foreach ( $nodes as $key => $node ) {
- $args = array();
- if ( 'home' !== $node->id ) {
- $args = array(
- 'rewrite_id' => $node->id,
- 'slug' => $node->slug,
- );
- // Build the url for nav items having a parent.
- if ( ! empty( $node->parent ) ) {
- $parent = wp_list_filter( $nodes, array( 'id' => $node->parent ) );
- if ( $parent ) {
- $parent = reset( $parent );
- $args['slug'] = trailingslashit( $parent->slug ) . $args['slug'];
- $args['rewrite_id'] = $parent->id;
- }
- // Check if there is a parent to set his url to the first found child.
- } else {
- $childnodes = wp_list_filter( $nodes, array( 'parent' => $node->id ) );
- if ( $childnodes ) {
- $first_child = reset( $childnodes );
- $args['slug'] = trailingslashit( $args['slug'] ) . $first_child->slug;
- }
- }
- }
- // Do not generate links to items the user can't access to.
- if ( ! current_user_can( $nodes[ $key ]->capability, $r['capability_args'] ) ) {
- continue;
- }
- if ( is_callable( $r['url_callback'] ) ) {
- $nodes[ $key ]->href = call_user_func_array( $r['url_callback'], array( $args, $r['object'] ) );
- }
- }
- if ( ! empty( $r['filter'] ) ) {
- /**
- * Dynamic filter to edit the nav node once the URL is set
- * @see CP_User_Cluster::get_account_bar_menus() for an example.
- *
- * @since 1.0.0
- *
- * @param array $nodes A list of nav objects.
- * @param WP_User|WP_Site $object The object the nav applies to.
- */
- $nodes = apply_filters( $r['filter'], $nodes, $r['object'] );
- }
- return $nodes;
- }
- /**
- * Validate the current user's access to the nav and set some nav metas.
- *
- * @since 1.0.0
- *
- * @param array $args {
- * An array of arguments.
- * @type array $nodes The list of nav items.
- * @type WP_User|WP_Site $object The Object the nav item applies to.
- * @type WP_Query $query The WordPress query being processed.
- * @type string $default_cap The required capability to view the nav item's content.
- * @type string $filter_prefix The prefix of the filter to override the nav item's data.
- * }
- * @return $result An array containing the values of the Action and Sub Action globals.
- */
- public function validate_access( $args = array() ) {
- $r = wp_parse_args( $args, array(
- 'nodes' => array(),
- 'object' => null,
- 'query' => null,
- 'default_cap' => 'manage_options',
- 'filter_prefix' => 'cp_cluster',
- ) );
- $result = array(
- 'action' => '',
- 'subaction' => '',
- );
- if ( empty( $r['nodes'] ) || ! is_array( $r['nodes'] ) || empty( $r['query'] ) || ! is_a( $r['query'], 'WP_Query' ) ) {
- return $result;
- }
- foreach ( $r['nodes'] as $node ) {
- $args = array();
- $qv = $r['query']->get( $node->id );
- if ( $qv ) {
- // First look for subactions
- $childnodes = wp_list_filter( $r['nodes'], array( 'parent' => $node->id, 'slug' => $qv ) );
- if ( $childnodes ) {
- $childnode = reset( $childnodes );
- if ( isset( $childnode->meta['classes'] ) ) {
- $childnode->meta['classes'] = array_merge( $childnode->meta['classes'], array( 'current' ) );
- } else {
- $childnode->meta['classes'] = array( 'current' );
- }
- $this->edit_node( $childnode->id, (array) $childnode );
- // Set the subaction
- $result['subaction'] = $qv;
- }
- // Take care of meta.
- if ( isset( $node->meta['classes'] ) ) {
- $node->meta['classes'] = array_merge( $node->meta['classes'], array( 'current' ) );
- } else {
- $node->meta['classes'] = array( 'current' );
- }
- // Manage access
- if ( ! isset( $node->capability ) ) {
- $node->capability = $r['default_cap'];
- }
- // No access at all or not viewing self profile.
- if ( ! current_user_can( $node->capability ) ) {
- // Reset the result array.
- return array(
- 'action' => '',
- 'subaction' => '',
- );
- }
- // Set the current action
- $result['action'] = $node->slug;
- }
- /**
- * Dynamic filter to allow overrides just before validating the nav.
- *
- * @since 1.0.0
- *
- * @param object $node The nav item's data.
- * @param WP_User|WP_Site $object The object the nav applies to.
- */
- $this->edit_node( $node->id, (array) apply_filters( $r['filter_prefix'] . '_' . $node->id, $node, $r['object'] ) );
- }
- return $result;
- }
- /**
- * Get all nodes for a given toolbar parent group
- *
- * @since 1.0.0
- *
- * @param string $toolbar The parent group of the nav.
- * @return array The list of nav items.
- */
- public function get_toolbar_nodes( $toolbar = 'single-bar' ) {
- return wp_list_filter( $this->get_nodes(), array( 'parent_group' => $toolbar ) );
- }
- /**
- * Get a nav item using its slug argument.
- *
- * @since 1.0.0
- *
- * @param string $slug The slug of the nav item.
- * @retun object The nav item object.
- */
- public function get_node_by_slug( $slug = '' ) {
- $nodes = $this->get_nodes();
- $node = wp_list_filter( $nodes, array( 'slug' => $slug ) );
- if ( ! is_array( $node ) ) {
- return false;
- }
- return reset( $node );
- }
- /**
- * Sort the nav items according to their position argument.
- *
- * @since 1.0.0
- *
- * @param array $items The nav items.
- * @return array The sorted nav items.
- */
- public function sort_items( $items ) {
- $sorted = array();
- foreach ( $items as $item ) {
- // Default position
- $position = 99;
- if ( isset( $item->position ) ) {
- $position = (int) $item->position;
- }
- // If position is already taken, move to the first next available
- if ( isset( $sorted[ $position ] ) ) {
- $sorted_keys = array_keys( $sorted );
- do {
- $position += 1;
- } while ( in_array( $position, $sorted_keys ) );
- }
- $sorted[ $position ] = $item;
- }
- ksort( $sorted );
- return $sorted;
- }
- /**
- * Check if there is a nav matching the requested arguments.
- *
- * @since 1.0.0
- *
- * @param array $args {
- * An array of arguments.
- * @type string $parent The parent nav items must match.
- * @type string $parent_group The Parent's nav. Defaults to 'single-bar'.
- * }
- * @return bool Whether there are some nav items to dsiplay.
- */
- public function has_items( $args = array() ) {
- $this->current_nav = null;
- $r = wp_parse_args( $args, array(
- 'parent' => false,
- 'parent_group' => 'single-bar',
- ) );
- $items = $this->get_nodes();
- // Filter according to args
- $items = wp_list_filter( $items, $r );
- // Remove toolbar menus the user can't access to.
- foreach ( $items as $k => $n ) {
- if ( ! current_user_can( $n->capability ) ) {
- unset( $items[ $k ] );
- }
- }
- // Filter again to remove the items the user has no access to.
- $this->current_nav = array_values( $this->sort_items( $items ) );
- $this->current_nav_index = 0;
- return ! empty( $this->current_nav );
- }
- /**
- * Iterate nav items within the Nav loop.
- *
- * @since 1.0.0.
- */
- public function nav_items() {
- if ( isset( $this->current_nav[ $this->current_nav_index ] ) ) {
- return true;
- }
- $this->current_nav_index = 0;
- unset( $this->current_item );
- return false;
- }
- /**
- * Set the nav item being iterated on.
- *
- * @since 1.0.0
- */
- public function nav_item() {
- $this->current_item = $this->current_nav[ $this->current_nav_index ];
- $this->current_nav_index += 1;
- }
- }