LLMS_Admin_User_Custom_Fields

Add Custom User Fields to user admin panel screens Applies to edit-user.php, user-new.php, & profile.php


Description Description


Source Source

File: includes/admin/class.llms.admin.user.custom.fields.php

class LLMS_Admin_User_Custom_Fields {

	private $fields = array();

	/**
	 * Constructor
	 * @since    2.7.0
	 * @version  3.13.0
	 */
	public function __construct() {

		// output custom fields on edit screens
		$field_actions = array(
			'show_user_profile',
			'edit_user_profile',
			'user_new_form',
		);
		foreach ( $field_actions as $action ) {
			add_action( $action, array( $this, 'output_custom_fields' ), 10, 1 );
			add_action( $action, array( $this, 'output_instructors_assistant_fields' ), 10, 1 );
		}

		// allow errors to be output before saving field data
		// save the data if no errors are encountered
		add_action( 'user_profile_update_errors', array( $this, 'add_errors' ), 10, 3 );

		// save data when a new user is created
		add_action( 'edit_user_created_user', array( $this, 'save' ) );

	}

	/**
	 * Validate custom fields
	 * During updates will save data
	 * Creation is saved during a different action
	 * @param    obj    &$errors  Instance of WP_Error
	 * @param    bool   $update   true if updating a profile, false if a new user
	 * @param    obj    $user     Instance of WP_User for the user being updated
	 * @return   void
	 * @since    2.7.0
	 * @version  3.13.0
	 */
	public function add_errors( &$errors, $update, $user ) {

		$this->get_fields();

		$error = $this->validate_fields( $user );

		if ( $error ) {

			$errors->add( '', $error, '' );

			if ( $update ) {
				$this->save();
			}

			// don't save
			remove_action( 'edit_user_created_user', array( $this, 'save' ) );

			return;

		}

		// if updating, save here since there's no other save specific admin action (that I could find)
		if ( $update ) {
			$this->save( $user );
		}

	}

	/**
	 * Retrieve an associative array of custom fields and custom field data
	 * @return   array
	 * @since    2.7.0
	 * @version  3.13.0
	 */
	public function get_fields() {

		$fields = apply_filters( 'lifterlms_get_user_custom_fields', array(

			'llms_billing_address_1' => array(
				'description' => '',
				'label' => __( 'Billing Address 1', 'lifterlms' ),
				'required' => false,
				'type'  => 'text',
				'value' => '',
			),

			'llms_billing_address_2' => array(
				'description' => '',
				'label' => __( 'Billing Address 2', 'lifterlms' ),
				'required' => false,
				'type'  => 'text',
				'value' => '',
			),

			'llms_billing_city' => array(
				'description' => '',
				'label' => __( 'Billing City', 'lifterlms' ),
				'required' => false,
				'type'  => 'text',
				'value' => '',
			),

			'llms_billing_state' => array(
				'description' => '',
				'label' => __( 'Billing State', 'lifterlms' ),
				'required' => false,
				'type'  => 'text',
				'value' => '',
			),

			'llms_billing_zip' => array(
				'description' => '',
				'label' => __( 'Billing Zip Code', 'lifterlms' ),
				'required' => false,
				'type'  => 'text',
				'value' => '',
			),

			'llms_billing_country' => array(
				'description' => '',
				'label' => __( 'Billing Country', 'lifterlms' ),
				'required' => false,
				'type'  => 'text',
				'value' => '',
			),

			'llms_phone' => array(
				'description' => '',
				'label' => __( 'Phone', 'lifterlms' ),
				'required' => false,
				'type'  => 'text',
				'value' => '',
			),

		) );

		$this->fields = $fields;

		return $this->fields;

	}

	/**
	 * Load usermeta data into the array of fields retrieved from $this->get_fields
	 * meta data is added to the array under the key "value" for each field
	 * if no data is found for a particular field the value is still added as an empty string
	 * @param    mixed  $user   Instance of WP_User or WP User ID
	 * @return   array
	 * @since    2.7.0
	 * @version  2.7.0
	 */
	public function get_fields_with_data( $user ) {

		if ( is_numeric( $user ) ) {
			$user = new WP_User( $user );
		}

		$this->get_fields();

		foreach ( $this->fields as $field => $data ) {

			$this->fields[ $field ]['value'] = apply_filters( 'lifterlms_get_user_custom_field_value_' . $field, $user->get( $field ), $user, $field );

		}

		return $this->fields;

	}

	/**
	 * Output custom field data fields as HTML inputs
	 * @param    mixed  $user   Instance of WP_User or WP User ID
	 * @return   void
	 * @since    2.7.0
	 * @version  3.24.0
	 */
	public function output_custom_fields( $user ) {

		if ( is_numeric( $user ) || is_a( $user, 'WP_User' ) ) {
			$this->get_fields_with_data( $user );
		} else {
			$this->get_fields();
		}

		llms_get_template( 'admin/user-edit.php', array(
			'section_title' => __( 'LifterLMS Profile', 'lifterlms' ),
			'fields' => $this->fields,
		) );

	}

	/**
	 * Add instructor parent fields for use when creating instructor's assistants
	 * @param    mixed  $user   Instance of WP_User or WP User ID
	 * @return   void
	 * @since    3.13.0
	 * @version  3.23.0
	 */
	public function output_instructors_assistant_fields( $user ) {

		if ( is_numeric( $user ) || is_a( $user, 'WP_User' ) ) {
			$instructor = llms_get_instructor( $user );
			$selected = $instructor->get( 'parent_instructors' );
			if ( empty( $selected ) && ! is_array( $selected ) ) {
				$selected = array();
			}
		} else {
			$selected = array( get_current_user_id() );
		}

		// only let admins & lms managers select the parent for an instructor's assistant
		if ( current_user_can( 'manage_lifterlms' ) ) {

			$users = get_users( array(
				'role__in' => array( 'administrator', 'lms_manager', 'instructor' ),
			) );
			?>
			<table class="form-table" id="llms-parent-instructors-table" style="display:none;">
				<tr class="form-field">
					<th scope="row"><label for="llms-parent-instructors"><?php _e( 'Parent Instructor(s)', 'lifterlms' ); ?></label></th>
					<td>
						<select class="regular-text" id="llms-parent-instructors" name="llms_parent_instructors[]" multiple="multiple">
							<?php foreach ( $users as $user ) : ?>
								<option value="<?php echo $user->ID; ?>"<?php selected( in_array( $user->ID, $selected ) ); ?>>
									<?php echo $user->display_name; ?>
								</option>
							<?php endforeach; ?>
						</select>
					</td>
				</tr>
			</table>
			<?php

			add_action( 'admin_print_footer_scripts', array( $this, 'output_instructors_assistant_scripts' ) );

			// this will be the case for Instructors only
			// show a hidden field with the current user's info
			// when saving it will only save if the created user's role is instructor's assistant
		} elseif ( 'add-new-user' === $user ) {
			echo '<input type="hidden" name="llms_parent_instructors[]" value="' . get_current_user_id() . '">';
		}

	}

	/**
	 * Output JS to handle user interaction with the instructor's parent field
	 * Display custom field ONLY when creating/editing an instructor's assistant
	 * @return   void
	 * @since    3.13.0
	 * @version  3.13.0
	 */
	public function output_instructors_assistant_scripts() {
		?><script>
			( function( $ ) {
				var $role = $( '#role' ),
					$parent = $( '#llms-parent-instructors-table' );
				$role.closest( '.form-table' ).after( $parent );
				$role.on( 'change', function() {
					if ( 'instructors_assistant' === $( this ).val() ) {
						$parent.show();
					} else {
						$parent.hide();
					}
				} ).trigger( 'change' );
			} )( jQuery );
		</script><?php
	}

	/**
	 * Save custom field data for a user
	 * @param    mixed     $user  WP_User or WP_User ID
	 * @return   void
	 * @since    3.13.0
	 * @version  3.13.0
	 */
	public function save( $user ) {

		if ( is_numeric( $user ) ) {
			$user = new WP_User( $user );
			// an object that's not a WP_User gets passed in during updates
		} elseif ( isset( $user->ID ) ) {
			$user = new WP_User( $user->ID );
		}

		// saves custom fields
		foreach ( $this->fields as $field => $data ) {

			update_user_meta( $user->ID, $field, sanitize_text_field( apply_filters( 'lifterlms_save_custom_user_field_' . $field, $_POST[ $field ], $user, $field ) ) );

		}

		// save instructor assistant's parent instructor
		if ( in_array( 'instructors_assistant', $user->roles ) && ! empty( $_POST['llms_parent_instructors'] ) ) {

			$instructor = llms_get_instructor( $user );
			$instructor->add_parent( $_POST['llms_parent_instructors'] );

		}

	}

	/**
	 * Validate custom fields
	 * By default only checks for valid as core fields don't have any special validation
	 * If adding custom fields, hook into the action run after required validation
	 * to add special validation rules for your field
	 *
	 * @param    mixed  $user   Instance of WP_User or WP User ID
	 * @return   mixed          false if no validation errors, string (the error message) if validation errors occurred
	 * @since    2.7.0
	 * @version  2.7.0
	 */
	public function validate_fields( $user ) {

		// ensure there's no missing required fields
		foreach ( $this->fields as $field => $data ) {

			// return an error message for empty required fields
			if ( empty( $_POST[ $field ] ) && $data['required'] ) {

				return sprintf( __( 'Required field "%s" is missing.', 'lifterlms' ), $data['label'] );

			} // End if().
			else {

				/**
				 * Run custom validation against the field
				 * If filter function returns a truthy, validation will stop, fields will not be saved,
				 * and an error message will be displayed on screen
				 * This should return false or a string which will be used as the error message
				 * @since  2.7.0
				 */
				$error_msg = apply_filters( 'lifterlms_validate_custom_user_field_' . $field, false, $field, $user );

				if ( $error_msg ) {

					return $error_msg;

				}
			}
		}

		return false;

	}

}

Top ↑

Changelog Changelog

Changelog
Version Description
2.7.0 Introduced.

Top ↑

Methods Methods

  • __construct — Constructor
  • add_errors — Validate custom fields During updates will save data Creation is saved during a different action
  • get_fields — Retrieve an associative array of custom fields and custom field data
  • get_fields_with_data — Load usermeta data into the array of fields retrieved from $this->get_fields meta data is added to the array under the key "value" for each field if no data is found for a particular field the value is still added as an empty string
  • output_custom_fields — Output custom field data fields as HTML inputs
  • output_instructors_assistant_fields — Add instructor parent fields for use when creating instructor's assistants
  • output_instructors_assistant_scripts — Output JS to handle user interaction with the instructor's parent field Display custom field ONLY when creating/editing an instructor's assistant
  • save — Save custom field data for a user
  • validate_fields — Validate custom fields By default only checks for valid as core fields don't have any special validation If adding custom fields, hook into the action run after required validation to add special validation rules for your field

Top ↑

User Contributed Notes User Contributed Notes

You must log in before being able to contribute a note or feedback.