Class for an access control to restrict to members only.
Description
Source
File: src/modules/access-controls/members.php
class Members extends Access_Control implements Assets_Submodule_Interface { /** * Template tag handler for email notifications. * * @since 1.0.0 * @var Template_Tag_Handler */ protected $template_tag_handler; /** * Template tag handler for email address fields. * * @since 1.0.0 * @var Template_Tag_Handler */ protected $template_tag_handler_email_only; /** * Temporary storage for email from name. * * @since 1.0.0 * @var string */ protected $from_name = ''; /** * Temporary storage for email from email. * * @since 1.0.0 * @var string */ protected $from_email = ''; /** * Bootstraps the submodule by setting properties. * * @since 1.0.0 */ protected function bootstrap() { $this->slug = 'members'; $this->title = __( 'Members', 'torro-forms' ); $this->description = __( 'Allows you to make this form available to logged-in members only.', 'torro-forms' ); Field_Manager::register_field_type( 'autocompletewithbutton', Autocomplete_With_Button::class ); $this->register_template_tag_handlers(); $this->module->manager()->ajax()->register_action( 'invite_member', array( $this, 'ajax_invite_member' ) ); } /** * Determines whether the current user can access a specific form or submission. * * @since 1.0.0 * * @param Form $form Form object. * @param Submission|null $submission Submission object, or null if no submission is set. * @return bool|WP_Error True if the form or submission can be accessed, false or error object otherwise. */ public function can_access( $form, $submission = null ) { if ( ! is_user_logged_in() ) { $message = $this->get_form_option( $form->id, 'login_required_message' ); if ( empty( $message ) ) { $message = $this->get_default_login_required_message(); } return new WP_Error( 'must_be_logged_in', $message ); } $allowed_roles = $this->get_form_option( $form->id, 'allowed_roles', array() ); $allowed_user_ids = $this->get_form_option( $form->id, 'allowed_users', array() ); $allowed_user_ids = array_map( 'absint', array_unique( array_filter( $allowed_user_ids ) ) ); if ( empty( $allowed_roles ) && empty( $allowed_user_ids ) ) { return true; } if ( ! empty( $allowed_roles ) ) { $user = wp_get_current_user(); $intersected_roles = array_intersect( array_values( $user->roles ), $allowed_roles ); if ( ! empty( $intersected_roles ) ) { return true; } } if ( ! empty( $allowed_user_ids ) ) { if ( in_array( get_current_user_id(), $allowed_user_ids, true ) ) { return true; } } $message = $this->get_form_option( $form->id, 'not_selected_message' ); if ( empty( $message ) ) { $message = $this->get_default_not_selected_message(); } return new WP_Error( 'not_selected', $message ); } /** * Returns the available meta fields for the submodule. * * @since 1.0.0 * * @return array Associative array of `$field_slug => $field_args` pairs. */ public function get_meta_fields() { $meta_fields = parent::get_meta_fields(); $role_choices = array(); foreach ( wp_roles()->roles as $role => $details ) { $role_choices[ $role ] = translate_user_role( $details['name'] ); } $meta_fields['allowed_roles'] = array( 'type' => count( $role_choices ) > 8 ? 'multiselect' : 'multibox', 'label' => __( 'Allowed Roles', 'torro-forms' ), 'description' => __( 'If you select user roles here, only users with these roles are granted access to the form.', 'torro-forms' ), 'choices' => $role_choices, ); $meta_fields['allowed_users'] = array( 'type' => 'autocompletewithbutton', 'label' => __( 'Allowed Users', 'torro-forms' ), 'description' => __( 'If you select users here, only these users are granted access to the form.', 'torro-forms' ), 'repeatable' => true, 'autocomplete' => array( 'rest_placeholder_search_route' => 'wp/v2/users?search=%search%', 'rest_placeholder_label_route' => 'wp/v2/users/%value%', 'value_generator' => '%id%', /* translators: 1: user display name, 2: user ID */ 'label_generator' => sprintf( __( '%1$s (User ID %2$s)', 'torro-forms' ), '%name%', '%id%' ), ), 'input_classes' => array( 'torro-member-invitation-input' ), 'button_label' => __( 'Send Invitation', 'torro-forms' ), 'button_attrs' => array( 'class' => 'button-link torro-send-invitation', 'disabled' => true, ), ); $meta_fields['login_required_message'] = array( 'type' => 'text', 'label' => __( '“Login required” Message', 'torro-forms' ), 'description' => __( 'Enter the message to show to the user in case they are not logged in.', 'torro-forms' ), 'default' => $this->get_default_login_required_message(), 'input_classes' => array( 'regular-text' ), 'wrap_classes' => array( 'has-torro-tooltip-description' ), ); $meta_fields['not_selected_message'] = array( 'type' => 'text', 'label' => __( '“Not eligible” Message', 'torro-forms' ), 'description' => __( 'Enter the message to show to the user when they are logged in, but have not been selected to participate.', 'torro-forms' ), 'default' => $this->get_default_not_selected_message(), 'input_classes' => array( 'regular-text' ), 'wrap_classes' => array( 'has-torro-tooltip-description' ), ); return $meta_fields; } /** * Returns the available settings sections for the submodule. * * @since 1.0.0 * * @return array Associative array of `$section_slug => $section_args` pairs. */ public function get_settings_sections() { $settings_sections = parent::get_settings_sections(); $settings_sections['invitation_email'] = array( 'title' => __( 'Invitation Email Template', 'torro-forms' ), 'description' => __( 'Setup mail templates for inviting a user to a form.', 'torro-forms' ), ); $settings_sections['reinvitation_email'] = array( 'title' => __( 'Renvitation Email Template', 'torro-forms' ), 'description' => __( 'Setup mail templates for reinviting a user to a form.', 'torro-forms' ), ); return $settings_sections; } /** * Returns the available settings fields for the submodule. * * @since 1.0.0 * * @return array Associative array of `$field_slug => $field_args` pairs. */ public function get_settings_fields() { $settings_fields = parent::get_settings_fields(); $domain = wp_parse_url( home_url( '/' ), PHP_URL_HOST ); if ( ! $domain ) { // Fall back to a random domain. $domain = 'yourwebsite.com'; } $settings_fields['invitation_from_name'] = array( 'section' => 'invitation_email', 'type' => 'templatetagtext', 'label' => __( 'From Name', 'torro-forms' ), 'input_classes' => array( 'regular-text' ), 'default' => '{sitetitle}', 'template_tag_handler' => $this->template_tag_handler, ); $settings_fields['invitation_from_email'] = array( 'section' => 'invitation_email', 'type' => 'templatetagemail', 'label' => __( 'From Email', 'torro-forms' ), /* translators: %s: email address */ 'description' => sprintf( __( 'This email address should contain the same domain like your website (e.g. %s).', 'torro-forms' ), 'email@' . $domain ), 'input_classes' => array( 'regular-text' ), 'default' => '{adminemail}', 'template_tag_handler' => $this->template_tag_handler_email_only, ); $settings_fields['invitation_subject'] = array( 'section' => 'invitation_email', 'type' => 'templatetagtext', 'label' => __( 'Subject', 'torro-forms' ), 'input_classes' => array( 'regular-text' ), 'default' => $this->get_default_invitation_subject(), 'template_tag_handler' => $this->template_tag_handler, ); $settings_fields['invitation_message'] = array( 'section' => 'invitation_email', 'type' => 'templatetagwysiwyg', 'label' => __( 'Message', 'torro-forms' ), 'rows' => 12, 'media_buttons' => true, 'wpautop' => true, 'default' => $this->get_default_invitation_message(), 'template_tag_handler' => $this->template_tag_handler, ); $settings_fields['reinvitation_from_name'] = array( 'section' => 'reinvitation_email', 'type' => 'templatetagtext', 'label' => __( 'From Name', 'torro-forms' ), 'input_classes' => array( 'regular-text' ), 'default' => '{sitetitle}', 'template_tag_handler' => $this->template_tag_handler, ); $settings_fields['reinvitation_from_email'] = array( 'section' => 'reinvitation_email', 'type' => 'templatetagemail', 'label' => __( 'From Email', 'torro-forms' ), /* translators: %s: email address */ 'description' => sprintf( __( 'This email address should contain the same domain like your website (e.g. %s).', 'torro-forms' ), 'email@' . $domain ), 'input_classes' => array( 'regular-text' ), 'default' => '{adminemail}', 'template_tag_handler' => $this->template_tag_handler_email_only, ); $settings_fields['reinvitation_subject'] = array( 'section' => 'reinvitation_email', 'type' => 'templatetagtext', 'label' => __( 'Subject', 'torro-forms' ), 'input_classes' => array( 'regular-text' ), 'default' => $this->get_default_reinvitation_subject(), 'template_tag_handler' => $this->template_tag_handler, ); $settings_fields['reinvitation_message'] = array( 'section' => 'reinvitation_email', 'type' => 'templatetagwysiwyg', 'label' => __( 'Message', 'torro-forms' ), 'rows' => 12, 'media_buttons' => true, 'wpautop' => true, 'default' => $this->get_default_reinvitation_message(), 'template_tag_handler' => $this->template_tag_handler, ); return $settings_fields; } /** * Registers all assets the submodule provides. * * @since 1.0.0 * * @param Assets $assets The plugin assets instance. */ public function register_assets( $assets ) { $assets->register_script( 'admin-member-invitations', 'assets/dist/js/admin-member-invitations.js', array( 'deps' => array( 'wp-util', 'jquery' ), 'in_footer' => true, 'localize_name' => 'torroMemberInvitations', 'localize_data' => array( 'ajaxPrefix' => $this->module->manager()->ajax()->get_prefix(), 'ajaxInviteMemberNonce' => $this->module->manager()->ajax()->get_nonce( 'invite_member' ), ), ) ); } /** * Enqueues scripts and stylesheets on the form editing screen. * * @since 1.0.0 * * @param Assets $assets The plugin assets instance. */ public function enqueue_form_builder_assets( $assets ) { $assets->enqueue_script( 'admin-member-invitations' ); } /** * Sends an email invitation to a member. * * @since 1.0.0 * * @param array $data AJAX data, including $userId and $formId arguments. * @return array|WP_Error AJAX response array, or error object in case of failure. */ public function ajax_invite_member( $data ) { if ( empty( $data['userId'] ) || empty( $data['formId'] ) ) { return new WP_Error( 'missing_parameters', __( 'Missing request parameters.', 'torro-forms' ) ); } $user = get_user_by( 'id', $data['userId'] ); if ( ! $user || ! $user->exists() ) { return new WP_Error( 'cannot_find_user', __( 'Could not find user.', 'torro-forms' ) ); } $form = $this->module->manager()->forms()->get( $data['formId'] ); if ( ! $form ) { return new WP_Error( 'cannot_find_form', __( 'Could not find form.', 'torro-forms' ) ); } $mode = $this->is_user_invited( (int) $user->ID, $form->id ) ? 'reinvitation' : 'invitation'; $from_name = $this->get_option( $mode . '_from_name', '{sitetitle}' ); $from_email = $this->get_option( $mode . '_from_email', '{adminemail}' ); $subject = $this->get_option( $mode . '_subject', call_user_func( array( $this, 'get_default_' . $mode . '_subject' ) ) ); $message = $this->get_option( $mode . '_message', call_user_func( array( $this, 'get_default_' . $mode . '_message' ) ) ); $from_name = $this->template_tag_handler->process_content( $from_name, array( $form, $user ) ); $from_email = $this->template_tag_handler_email_only->process_content( $from_email, array( $form, $user ) ); $subject = $this->template_tag_handler->process_content( $subject, array( $form, $user ) ); $message = $this->template_tag_handler->process_content( $message, array( $form, $user ) ); $message = wpautop( $message ); add_filter( 'wp_mail_content_type', array( $this, 'override_content_type' ) ); add_filter( 'wp_mail_from_name', array( $this, 'override_from_name' ) ); add_filter( 'wp_mail_from', array( $this, 'override_from_email' ) ); $this->from_name = $from_name; $this->from_email = $from_email; $result = wp_mail( $user->user_email, $subject, $message ); $this->from_name = ''; $this->from_email = ''; remove_filter( 'wp_mail_content_type', array( $this, 'override_content_type' ) ); remove_filter( 'wp_mail_from_name', array( $this, 'override_from_name' ) ); remove_filter( 'wp_mail_from', array( $this, 'override_from_email' ) ); if ( ! $result ) { if ( 'reinvitation' === $mode ) { /* translators: %s: user display name */ return new WP_Error( 'cannot_reinvite_user', sprintf( __( 'User %s could not be reinvited.', 'torro-forms' ), $user->display_name ) ); } /* translators: %s: user display name */ return new WP_Error( 'cannot_invite_user', sprintf( __( 'User %s could not be invited.', 'torro-forms' ), $user->display_name ) ); } $this->set_user_invited( (int) $user->ID, $form->id ); if ( 'reinvitation' === $mode ) { return array( /* translators: %s: user display name */ 'message' => sprintf( __( 'User %s was successfully reinvited.', 'torro-forms' ), $user->display_name ), ); } return array( /* translators: %s: user display name */ 'message' => sprintf( __( 'User %s was successfully invited.', 'torro-forms' ), $user->display_name ), ); } /** * Gets the email content type. * * @since 1.0.0 * * @return string Email content type. */ public function override_content_type() { return 'text/html'; } /** * Gets the email from name. * * @since 1.0.0 * * @return string Email from name. */ public function override_from_name() { return $this->from_name; } /** * Gets the email from email. * * @since 1.0.0 * * @return string Email from email. */ public function override_from_email() { return $this->from_email; } /** * Checks whether a user has been previously invited to a form. * * @since 1.0.0 * * @param int $user_id User ID. * @param int $form_id Form ID. * @return bool True if the user has been invited, false otherwise. */ protected function is_user_invited( $user_id, $form_id ) { $meta_key = $this->module->manager()->get_prefix() . 'invited_users'; $data = $this->module->manager()->forms()->get_meta( $form_id, $meta_key ); if ( ! is_array( $data ) ) { return false; } $data = array_map( 'absint', $data ); if ( ! in_array( $user_id, $data, true ) ) { return false; } return true; } /** * Sets a user as invited to a form. * * @since 1.0.0 * * @param int $user_id User ID. * @param int $form_id Form ID. */ protected function set_user_invited( $user_id, $form_id ) { if ( $this->is_user_invited( $user_id, $form_id ) ) { return; } $meta_key = $this->module->manager()->get_prefix() . 'invited_users'; $this->module->manager()->forms()->add_meta( $form_id, $meta_key, $user_id ); } /** * Returns the default message to display when the user is not logged in. * * @since 1.0.0 * * @return string Message to display. */ protected function get_default_login_required_message() { return __( 'You have to be logged in to participate.', 'torro-forms' ); } /** * Returns the default message to display when the user has not been selected. * * @since 1.0.0 * * @return string Message to display. */ protected function get_default_not_selected_message() { return __( 'You have not been selected to participate.', 'torro-forms' ); } /** * Returns the default subject for an invitation email, including placeholders. * * @since 1.0.0 * * @return string Invitation email subject. */ protected function get_default_invitation_subject() { /* translators: %s: form title */ return sprintf( __( 'Invitation to the form “%s”', 'torro-forms' ), '{formtitle}' ); } /** * Returns the default subject for a reinvitation email, including placeholders. * * @since 1.0.0 * * @return string Reinvitation email subject. */ protected function get_default_reinvitation_subject() { /* translators: %s: form title */ return sprintf( __( 'Reinvitation to the form “%s”', 'torro-forms' ), '{formtitle}' ); } /** * Returns the default message for an invitation email, including placeholders. * * @since 1.0.0 * * @return string Invitation email message. */ protected function get_default_invitation_message() { /* translators: %s: user display name */ $message = sprintf( __( 'Dear %s,', 'torro-forms' ), '{userdisplayname}' ) . "\n\n"; /* translators: %s: form title */ $message .= sprintf( __( 'You have been invited to participate in the form “%s” which you can find at the following URL:', 'torro-forms' ), '{formtitle}' ) . "\n\n"; $message .= '<a href="{formurl}">{formurl}</a>' . "\n\n"; $message .= __( 'Thanks in advance for participating!', 'torro-forms' ) . "\n\n"; $message .= '{sitetitle}'; return $message; } /** * Returns the default message for a reinvitation email, including placeholders. * * @since 1.0.0 * * @return string Reinvitation email message. */ protected function get_default_reinvitation_message() { /* translators: %s: user display name */ $message = sprintf( __( 'Dear %s,', 'torro-forms' ), '{userdisplayname}' ) . "\n\n"; /* translators: %s: form title */ $message .= sprintf( __( 'As a reminder, a while ago you have been invited to participate in the form “%s” which you can find at the following URL:', 'torro-forms' ), '{formtitle}' ) . "\n\n"; $message .= '<a href="{formurl}">{formurl}</a>' . "\n\n"; $message .= __( 'If you have already participated by now, please ignore this email. Thanks!', 'torro-forms' ) . "\n\n"; $message .= '{sitetitle}'; return $message; } /** * Registers the template tag handler for member invitations. * * @since 1.0.0 */ protected function register_template_tag_handlers() { $tags = array( 'sitetitle' => array( 'group' => 'global', 'label' => __( 'Site Title', 'torro-forms' ), 'description' => __( 'Inserts the site title.', 'torro-forms' ), 'callback' => function() { return get_bloginfo( 'name' ); }, ), 'sitetagline' => array( 'group' => 'global', 'label' => __( 'Site Tagline', 'torro-forms' ), 'description' => __( 'Inserts the site tagline.', 'torro-forms' ), 'callback' => function() { return get_bloginfo( 'description' ); }, ), 'siteurl' => array( 'group' => 'global', 'label' => __( 'Site URL', 'torro-forms' ), 'description' => __( 'Inserts the site home URL.', 'torro-forms' ), 'callback' => function() { return home_url( '/' ); }, ), 'adminemail' => array( 'group' => 'global', 'label' => __( 'Site Admin Email', 'torro-forms' ), 'description' => __( 'Inserts the site admin email.', 'torro-forms' ), 'callback' => function() { return get_option( 'admin_email' ); }, ), 'userip' => array( 'group' => 'global', 'label' => __( 'User IP', 'torro-forms' ), 'description' => __( 'Inserts the current user IP address.', 'torro-forms' ), 'callback' => function() { $validated_ip = filter_var( $_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP ); if ( empty( $validated_ip ) ) { return '0.0.0.0'; } return $validated_ip; }, ), 'refererurl' => array( 'group' => 'global', 'label' => __( 'Referer URL', 'torro-forms' ), 'description' => __( 'Inserts the current referer URL.', 'torro-forms' ), 'callback' => function() { return wp_get_referer(); }, ), 'formtitle' => array( 'group' => 'form', 'label' => __( 'Form Title', 'torro-forms' ), 'description' => __( 'Inserts the form title.', 'torro-forms' ), 'callback' => function( $form ) { return $form->title; }, ), 'formurl' => array( 'group' => 'form', 'label' => __( 'Form URL', 'torro-forms' ), 'description' => __( 'Inserts the URL to the form.', 'torro-forms' ), 'callback' => function( $form ) { return get_permalink( $form->id ); }, ), 'formediturl' => array( 'group' => 'form', 'label' => __( 'Form Edit URL', 'torro-forms' ), 'description' => __( 'Inserts the edit URL for the form.', 'torro-forms' ), 'callback' => function( $form ) { return get_edit_post_link( $form->id ); }, ), 'useremail' => array( 'group' => 'user', 'label' => __( 'User Email', 'torro-forms' ), 'description' => __( 'Inserts the email address for the user.', 'torro-forms' ), 'callback' => function( $form, $user ) { return $user->user_email; }, ), 'username' => array( 'group' => 'user', 'label' => __( 'Username', 'torro-forms' ), 'description' => __( 'Inserts the username.', 'torro-forms' ), 'callback' => function( $form, $user ) { return $user->user_login; }, ), 'userdisplayname' => array( 'group' => 'user', 'label' => __( 'User Display Name', 'torro-forms' ), 'description' => __( 'Inserts the full display name the user has chosen to be addressed with.', 'torro-forms' ), 'callback' => function( $form, $user ) { return $user->display_name; }, ), ); $groups = array( 'global' => _x( 'Global', 'template tag group', 'torro-forms' ), 'form' => _x( 'Form', 'template tag group', 'torro-forms' ), 'user' => _x( 'User', 'template tag group', 'torro-forms' ), ); $this->template_tag_handler = new Template_Tag_Handler( $this->slug, $tags, array( Form::class, WP_User::class ), $groups ); $this->template_tag_handler_email_only = new Template_Tag_Handler( $this->slug . '_email_only', array( 'adminemail' => $tags['adminemail'], 'useremail' => $tags['useremail'], ), array( Form::class, WP_User::class ), array( 'global' => $groups['global'], 'user' => $groups['user'], ) ); $this->module->manager()->template_tag_handlers()->register( $this->template_tag_handler ); $this->module->manager()->template_tag_handlers()->register( $this->template_tag_handler_email_only ); } }
Changelog
Version | Description |
---|---|
1.0.0 | Introduced. |
Methods
- enqueue_form_builder_assets — Enqueues scripts and stylesheets on the form editing screen.
- register_assets — Registers all assets the submodule provides.