spivurno of Gravity Wiz
4/29/2014 - 2:57 PM

Gravity Wiz // Multiple Roles for Gravity Forms User Registration Add-on

Gravity Wiz // Multiple Roles for Gravity Forms User Registration Add-on

<?php
/**
* Multiple Roles for Gravity Forms User Registration
*
* Adds support for assigning users multiple roles via a User Registration feed. Also adds support for managing
* multiple roles on the WordPress user profile view.
*
* @author    David Smith <david@gravitywiz.com>
* @license   GPL-2.0+
* @link      http://gravitywiz.com/...
* @copyright 2013 Gravity Wiz
*/ 
class GWMultipleRoles {
	
	/**
	* TODO:
	* + figure out how to handle "No role on this site" on the user profile page: http://grab.by/sBj2
	* + add support showing all roles in the User list view "Role" column: http://grab.by/sBiQ
	* + add support for Network mode
	*/
	
	function __construct() {
		
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
		
		add_action( 'gform_user_registration_add_option_group', array( $this, 'output_user_reg_footer_script' ) );
		add_filter( 'gform_user_registration_save_config', array( $this, 'save_roles_to_feed' ) );
		add_action( 'gform_user_registered', array( $this, 'add_roles_to_new_user' ), 10, 2 );
		add_action( 'gform_user_updated', array( $this, 'add_roles_to_updated_user' ), 10, 2 );
		
		add_action( 'admin_footer-user-edit.php', array( $this, 'output_user_edit_footer_script' ) );
		add_action( 'load-user-edit.php', array( $this, 'add_user_edit_multi_role_support' ) );
		 
	}
	
	function enqueue_scripts() {
		
		/*print_r( get_current_screen() );
		exit;*/
		
		if( ! $this->is_gfur_feed_edit_page() && ! $this->is_user_profile_page() )
			return;
		
		wp_enqueue_style( 'chosen', '//cdnjs.cloudflare.com/ajax/libs/chosen/1.0/chosen.min.css' );
		wp_enqueue_script( 'chosen', '//cdnjs.cloudflare.com/ajax/libs/chosen/1.0/chosen.jquery.min.js', array( 'jquery' ), '1.0' );
		
	}
	
	function add_footer_script_hook() {
		add_filter( 'admin_print_footer_scripts', array( $this, 'output_footer_script' ), 11 );
	}
	
	function output_user_reg_footer_script() {
		
		$feed_id = rgget( 'id' );
		$feed = $feed_id ? GFUserData::get_feed( $feed_id ) : array();
		
		$selected_roles = rgpost( 'gf_user_registration_role' );
		if( ! $selected_roles )
			$selected_roles = rgars( $feed, 'meta/roles' );
			
		$selected_roles_js = ! empty( $selected_roles ) ? json_encode( $selected_roles ) : '[]';
		
		?>
		
		<style type="text/css"> .chosen-container-multi .chosen-choices li.search-field input[type="text"] { height: auto; } </style>
		
		<script type="text/javascript">
		
		var gwmr = {};
		
		(function($){
		
			gwmr.initRoleMultiSelect = function() {
				
				var roleSelect = $( '#gf_user_registration_role' ),
					selectedRoles = <?php echo $selected_roles_js; ?>;
				
				roleSelect
					.prop( 'multiple', true )
					.attr( 'name', roleSelect.attr( 'name' ) + '[]' )
					.attr( 'data-placeholder', '<?php _e( 'Select Roles' ); ?>' );
				
				roleSelect.find( 'option' ).each( function(i){
					$(this).prop( 'selected', $.inArray( $(this).val(), selectedRoles ) != -1 );
				} );
				
				if( roleSelect.is( ':visible' ) )
					roleSelect.chosen();
				
			}
			
			gwmr.pollForChosenReadyState = function() {
				
				var roleSelect = jQuery( '#gf_user_registration_role' );
				
				if( roleSelect.is( ':visible' ) ) {
					roleSelect.chosen();
				} else {
					setTimeout( gwmr.pollForChosenReadyState, 250 );
				}
				
			}
			
			gwmr.initRoleMultiSelect();
			
			$(document).bind( 'gform_user_registration_form_selected', function() {
				gwmr.pollForChosenReadyState();
			});
				
		})(jQuery);
		
		</script>
		
		<?php
	}
	
	function output_user_edit_footer_script() {
		
		$user_id = rgget( 'user_id' );
		$user = new WP_User( $user_id );
		
		$selected_roles_js = ! empty( $user->roles ) ? json_encode( array_values( $user->roles ) ) : '[]';
		
		?>
		
		<style type="text/css">
		/* Custom */
		.chosen-container-multi .chosen-choices li.search-field input[type="text"] { height: auto; }
		</style>
		
		<script type="text/javascript">
		
		var gwmr = {};
		
		(function($){
		
			gwmr.initRoleMultiSelect = function() {
				
				var roleSelect = $( '#role' ),
					selectedRoles = <?php echo $selected_roles_js; ?>;
				
				roleSelect
					.prop( 'multiple', true )
					.attr( 'name', roleSelect.attr( 'name' ) + '[]' )
					.attr( 'data-placeholder', '<?php _e( 'Select Roles' ); ?>' );
				
				roleSelect.find( 'option' ).each( function(i){
					$(this).prop( 'selected', $.inArray( $(this).val(), selectedRoles ) != -1 );
				} );
				
				if( roleSelect.is( ':visible' ) )
					roleSelect.chosen();
				
			}
			
			gwmr.initRoleMultiSelect();
				
		})(jQuery);
		
		</script>
		
		<?php
	}
	
	function save_roles_to_feed( $feed ) {
		
		// capture roles from original "role" property
		$feed['meta']['roles'] = $feed['meta']['role'];
		
		// set original "role" property to empty string so no role is assigned by default
		$feed['meta']['role'] = '';
		
		return $feed;
	}
	
	function add_roles_to_new_user( $user_id, $feed ) {
		
		$user = new WP_User( $user_id );
		$this->remove_user_roles( $user ); // remove any default roles (i.e. 'subscriber')
		
		$roles = rgar( $feed['meta'], 'roles' );
		$this->add_user_roles( $user, $roles );
		
	}
	
	function add_roles_to_updated_user( $user_id, $feed ) {
		
		$user = new WP_User( $user_id );
		
		if( ! $this->is_preserve_role_enabled( $feed ) )
			$this->remove_user_roles( $user );
		
		$roles = rgar( $feed['meta'], 'roles' );
		$this->add_user_roles( $user, $roles );
		
	}
	
	/**
	* The "Preserve current role" option is represented as an empty string. Look for an empty string in the feed's 
	* 'roles' property to determine if this option is enabled.
	* 
	* @param mixed $roles
	*/
	function is_preserve_role_enabled( $feed ) {
		$roles = rgar( $feed['meta'], 'roles' );
		return count( $roles ) > count( array_filter( $roles ) );
	}
	
	function add_user_edit_multi_role_support() {
		
		if( empty( $_POST ) )
			return;
		
		// set 'role' to 'roles'
		$_POST['roles'] = $_POST['role'];
		
		// avoid WP error and bypass WP handling roles
		$_POST['role'] = '';
		
		// add a hook after WP has updated the user's roles (removes them all) and then add back the selected roles
		add_action( 'profile_update', array( $this, 'add_roles_to_edited_user' ) );
		
	}
	
	function add_roles_to_edited_user( $user_id ) {
		
		$user = new WP_User( $user_id );
		$roles = $_POST['roles'];
		
		$this->add_user_roles( $user, $roles );
		
	}
	
	function remove_user_roles( $user ) {
		foreach( $user->roles as $role ) {
			$user->remove_role( $role );
		}
	}
	
	function add_user_roles( $user, $roles ) {
		foreach( $roles as $role ) {
			$user->add_role( $role );
		}
	}
	
	function is_gfur_feed_edit_page() {
		return isset( $_GET['page'] ) && $_GET['page'] == 'gf_user_registration';
	}
	
	function is_user_profile_page() {
		return get_current_screen() && get_current_screen()->id == 'user-edit';
	}
	
}

new GWMultipleRoles();