3runoDesign/setRobot

View on GitHub
app/Lib/Lock.php

Summary

Maintainability
B
6 hrs
Test Coverage
<?php

namespace App\Lib;

use function App\config;

class Lock
{
    private $is_login_page;

    private $get_login_url;
    private $get_register_url;
    private $get_lostpassword_url;
    private $get_resetpass_url;
    private $get_profile_user_url;

    /**
     * Lock constructor.
     */
    public function __construct()
    {
        $this->get_login_url = get_permalink( get_page_by_title(config('pages')['default']['login'])->ID );
        $this->get_register_url = get_permalink( get_page_by_title(config('pages')['default']['register'])->ID);
        $this->get_lostpassword_url = get_permalink( get_page_by_title(config('pages')['default']['lostpassword'])->ID);
        $this->get_resetpass_url = get_permalink( get_page_by_title(config('pages')['default']['resetpass'])->ID);
        $this->get_profile_user_url = get_permalink( get_page_by_title(config('pages')['default']['profile_user'])->ID);

        $this->is_login_page = substr( $_SERVER['REQUEST_URI'], 0, 2 + strlen(get_page_by_title(config('pages')['default']['login'])->post_name) ) === '/' . get_page_by_title(config('pages')['default']['login'])->post_name .'/';

        $this->subscribe();
    }



    /**
     * Does the reuqest parsing. Checks if the login page exists
     * and redirects the visitor to that same page if he is not logged in.
     *
     * @param mixed $wp
     * @return void
     */
    public function parse_request($wp)
    {
        if($this->is_login_page && is_user_logged_in()) {
            wp_redirect( home_url('?action=is_user_logged') );
            exit();
        }
    }

    /**
     * Redirect user to custom login page rather than wp-pages.php
     */
    public function redirect_to_custom_login() {
        if($_SERVER['REQUEST_METHOD'] == 'GET') {
            $redirect_to = isset($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : null;
            if(is_user_logged_in()) {
                $this->redirect_logged_in_user($redirect_to); // TODO: Redirects the user to the correct page depending on whether or not admin
                exit;
            }
            $login_url = $this->get_login_url;
            if(!empty($redirect_to)) {
                $login_url = add_query_arg('redirect_to', $redirect_to, $login_url);
            }
            wp_redirect($login_url);
            exit;
        }
    }

    /**
     * Redirect the user after authentication if there were any errors.
     *
     * @param Wp_User|Wp_Error  $user       The signed in user, or the errors that have occurred during login.
     * @param string            $username   The user name used to log in.
     * @param string            $password   The password used to log in.
     *
     * @return Wp_User|Wp_Error The logged in user, or error information if there were errors.
     */
    public function maybe_redirect_at_authenticate($user, $username, $password) {
        if($_SERVER['REQUEST_METHOD'] === 'POST') {
            if(is_wp_error($user)) {
                $error_codes = join(',', $user->get_error_codes());
                $login_url = $this->get_login_url;
                $login_url = add_query_arg('login', $error_codes, $login_url);
                wp_redirect($login_url);
                exit;
            }
        }
        return $user;
    }

    /**
     * Redirect to custom login page after user has been logged out
     */
    public function redirect_after_logout() {
        $redirect_url = $this->get_login_url;
        $redirect_url = add_query_arg('logged_out', 'true', $redirect_url);
        wp_safe_redirect($redirect_url);
        exit;
    }

    /**
     * Returns the URL to which the user should be redirected after the (successful) login.
     *
     * @param string           $redirect_to           The redirect destination URL.
     * @param string           $requested_redirect_to The requested redirect destination URL passed as a parameter.
     * @param WP_User|WP_Error $user                  WP_User object if login was successful, WP_Error object otherwise.
     *
     * @return string Redirect URL
     */
    public function redirect_after_login( $redirect_to, $requested_redirect_to, $user ) {
        $redirect_url = home_url();
        if ( ! isset( $user->ID ) ) {
            return $redirect_url;
        }
        if ( user_can( $user, 'manage_options' ) ) {
            // Use the redirect_to parameter if one is set, otherwise redirect to admin dashboard.
            if ( $requested_redirect_to == '' ) {
                $redirect_url = admin_url();
            } else {
                $redirect_url = $requested_redirect_to;
            }
        } else {
            // Non-admin users always go to their account page after login
            $redirect_url = $this->get_logged_in_url($user); // TODO: Redirects the user to the correct page depending on whether or not admin
        }
        return wp_validate_redirect( $redirect_url, home_url() );
    }

    /**
     * Redirects the user to the custom registration page instead
     * of wp-pages.php?action=register.
     */
    public function redirect_to_custom_register() {
        if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
            if ( is_user_logged_in() ) {
                $this->redirect_logged_in_user(); // TODO: Redirects the user to the correct page depending on whether or not admin
            } else {
                wp_redirect( $this->get_register_url );
            }
            exit;
        }
    }

    /**
     * Handles the registration of a new user.
     *
     * Used through the action hook "login_form_register" activated on wp-pages.php
     * when accessed through the registration action.
     */
    public function do_register_user() {
        if('POST' == $_SERVER['REQUEST_METHOD']) {
            $redirect_url = $this->get_register_url;
            if(!get_option('users_can_register')) {
                $redirect_url = add_query_arg('register-errors', 'closed', $redirect_url);
            } else if(empty($_POST['foobar'])) {
                $email = $_POST['email'];
                $first_name = sanitize_text_field($_POST['first_name']);
                $last_name = sanitize_text_field($_POST['last_name']);

                $result = $this->register_user($email, $first_name, $last_name);

                do_action('lock_after_register', $_POST, $result);

                if(is_wp_error($result)) {
                    $errors = join(',', $result->get_error_codes());
                    $redirect_url = add_query_arg('register-errors', $errors, $redirect_url);
                } else {
                    $redirect_url = $this->get_login_url;
                    $redirect_url = add_query_arg('registered', $email, $redirect_url);
                }
            }
            wp_redirect($redirect_url);
            exit;
        }
    }

    /**
     * Redirects the user to the custom "Forgot your password?" page instead of
     * wp-pages.php?action=lostpassword.
     */
    public function redirect_to_custom_lostpassword() {
        if('GET' == $_SERVER['REQUEST_METHOD']) {
            if(is_user_logged_in()) {
                $this->redirect_logged_in_user(); // TODO: Redirects the user to the correct page depending on whether or not admin
                exit;
            }
            wp_redirect($this->get_lostpassword_url);
            exit;
        }
    }

    /**
     * Initiates password reset
     */
    public function do_password_lost() {
        if('POST' == $_SERVER['REQUEST_METHOD']) {
            $errors = retrieve_password();
            if(is_wp_error($errors)) {
                $redirect_url = $this->get_lostpassword_url;
                $redirect_url = add_query_arg('errors', join(',', $errors->get_error_codes()), $redirect_url);
            } else {
                $redirect_url = $this->get_login_url;
                $redirect_url = add_query_arg('checkemail', 'confirm', $redirect_url);
            }
            wp_redirect($redirect_url);
            exit;
        }
    }

    /**
     * Redirects to the custom password reset page, or the login page
     * if there are errors.
     */
    public function redirect_to_custom_resetpass() {
        if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
            // Verify key / login combo
            $user = check_password_reset_key( $_REQUEST['key'], $_REQUEST['login'] );
            if ( ! $user || is_wp_error( $user ) ) {
                if ( $user && $user->get_error_code() === 'expired_key' ) {
                    $redirect_url = $this->get_login_url;
                    $redirect_url = add_query_arg('login', 'expiredkey', $redirect_url);
                    wp_redirect( $redirect_url );
                } else {
                    $redirect_url = $this->get_login_url();
                    $redirect_url = add_query_arg('login', 'invalidkey', $redirect_url);
                    wp_redirect( $redirect_url );
                }
                exit;
            }
            $redirect_url = $this->get_resetpass_url;
            $redirect_url = add_query_arg( 'login', esc_attr( $_REQUEST['login'] ), $redirect_url );
            $redirect_url = add_query_arg( 'key', esc_attr( $_REQUEST['key'] ), $redirect_url );
            wp_redirect( $redirect_url );
            exit;
        }
    }

    /**
     * Resets the user's password if the password reset form was submitted.
     */
    public function do_password_reset() {
        if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
            $rp_key = $_REQUEST['rp_key'];
            $rp_login = $_REQUEST['rp_login'];

            $user = check_password_reset_key( $rp_key, $rp_login );

            if ( ! $user || is_wp_error( $user ) ) {
                if ( $user && $user->get_error_code() === 'expired_key' ) {
                    $redirect_url = $this->get_login_url;
                    $redirect_url = add_query_arg('login', 'expiredkey', $redirect_url);
                    wp_redirect( $redirect_url );
                } else {
                    $redirect_url = $this->get_login_url;
                    $redirect_url = add_query_arg('login', 'invalidkey', $redirect_url);
                    wp_redirect( $redirect_url );
                }
            }

            if ( isset( $_POST['pass1'] ) ) {
                if ( $_POST['pass1'] != $_POST['pass2'] ) {
                    // Passwords don't match
                    $redirect_url = $this->get_resetpass_url;
                    $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
                    $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url );
                    $redirect_url = add_query_arg( 'error', 'password_reset_mismatch', $redirect_url );
                    wp_redirect( $redirect_url );
                    exit;
                }
                if ( empty( $_POST['pass1'] ) ) {
                    // Password is empty
                    $redirect_url = $this->get_resetpass_url;

                    $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
                    $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url );
                    $redirect_url = add_query_arg( 'error', 'password_reset_empty', $redirect_url );

                    wp_redirect( $redirect_url );
                    exit;
                }
                // Parameter checks OK, reset password
                reset_password( $user, $_POST['pass1'] );
                $redirect_url = $this->get_login_url;
                $redirect_url = add_query_arg('password', 'changed', $redirect_url);
                wp_redirect( $redirect_url );
            } else {
                echo "Invalid request.";
            }
            exit;
        }
    }

    /**
     * Redirects the user to the correct page depending on whether or not admin
     *
     * @param string $redirect_to An optional redirect_to URL for admin users
     */
    private function redirect_logged_in_user($redirect_to = null) {
        $user = wp_get_current_user();
        if(user_can($user, 'manage_options')) {
            if($redirect_to) {
                wp_safe_redirect($redirect_to);
            } else {
                wp_redirect(admin_url());
            }
        } else {
            //TODO: add filter here or use settings page
            wp_redirect($this->get_logged_in_url($user));
        }
        exit;
    }

    /**
     * Get url for logged in users
     *
     * @return string The logged in redirect URL
     */
    function get_logged_in_url($user) {
        //TODO: Write settings page that takes pages and use their IDs
        /**
         * Filter to get custom logged in url
         *
         * @since 1.0.0
         *
         */
        return apply_filters('lock_logged_in_url', $this->get_profile_user_url, $user);
    }

//    public function registration_redirect() {
//        return redirect_logged_in_user(home_url(/));
//    }

    /**
     * Subscribe to WordPress hooks
     *
     * * @return void
     */
    private function subscribe()
    {
        // Login hooks
        add_action('login_form_login', [$this, 'redirect_to_custom_login']);
        add_filter('authenticate', [$this, 'maybe_redirect_at_authenticate'], 101, 3);
        add_action('wp_logout', [$this, 'redirect_after_logout']);
        add_filter('login_redirect', [$this, 'redirect_after_login'], 10, 3);
        add_action( 'parse_request', array( &$this, 'parse_request' ) );

        // Register hooks
        add_action('login_form_register', [$this, 'redirect_to_custom_register']);
        add_action('login_form_register', [$this, 'do_register_user']);
//        add_filter('registration_redirect', [$this, 'registration_redirect']);

        // Reset/Lost password hooks
        add_action('login_form_lostpassword', [$this, 'redirect_to_custom_lostpassword']);
        add_action('login_form_lostpassword', [$this, 'do_password_lost']);
        add_action('login_form_rp', [$this, 'redirect_to_custom_resetpass']);
        add_action('login_form_resetpass', [$this, 'redirect_to_custom_resetpass']);
        add_action('login_form_rp', [$this, 'do_password_reset']);
        add_action('login_form_resetpass', [$this, 'do_password_reset']);
    }
}