Plugin Directory

Changeset 3440551


Ignore:
Timestamp:
01/15/2026 05:35:10 PM (5 weeks ago)
Author:
killiansantos
Message:

Update version 1.1.0

Location:
loginease/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • loginease/trunk/includes/class-login.php

    r3362368 r3440551  
    11<?php
    2 if ( ! defined( 'ABSPATH' ) ) {
     2if (!defined('ABSPATH')) {
    33    exit;
    44}
     
    1111 * enqueuing external CSS/JS files.
    1212 */
    13 class LoginEase_Login {
     13class LoginEase_Login
     14{
    1415    private static $opts = null;
    1516
    16     public static function init_hooks() {
    17         self::$opts = get_option( 'loginease_settings', [] );
    18 
    19         add_filter( 'wp_redirect', [ __CLASS__, 'prevent_login_redirect' ], 0, 2 );
    20         add_action( 'init', [ __CLASS__, 'maybe_block_default_login_and_admin' ], 1 );
    21         add_action( 'admin_init', [ __CLASS__, 'maybe_block_wp_admin' ], 1 );
    22         add_action( 'login_init', [ __CLASS__, 'maybe_block_wp_login' ], 1 );
    23         add_action( 'login_init', [ __CLASS__, 'block_lost_password_if_passwordless' ], 0 );
    24         add_action( 'init', [ __CLASS__, 'add_custom_login_rewrite' ], 5 );
    25         add_filter( 'query_vars', [ __CLASS__, 'add_query_vars' ] );
    26         add_action( 'template_redirect', [ __CLASS__, 'maybe_handle_custom_slug' ], 1 );
    27         add_filter( 'authenticate', [ __CLASS__, 'loginease_authenticate' ], 30, 3 );
    28         add_filter( 'login_message', [ __CLASS__, 'add_sent_message' ] );
    29         add_filter( 'body_class', [ __CLASS__, 'body_class_notice' ] );
    30         add_action( 'login_form_login', [ __CLASS__, 'process_login_request' ] );
    31         add_action( 'login_form', [ __CLASS__, 'add_loginease_button' ], 20 );
    32         add_action( 'login_enqueue_scripts', [ __CLASS__, 'enqueue_styles_scripts' ] );
    33         add_action( 'login_enqueue_scripts', [ __CLASS__, 'disable_lost_password_link' ] );
    34         add_action( 'login_enqueue_scripts', [ __CLASS__, 'hide_password_login_fields' ], 20 );
    35         add_filter( 'login_url', [ __CLASS__, 'filter_login_url' ], 10, 3 );
    36         add_filter( 'allow_password_reset', [ __CLASS__, 'disable_password_reset_if_passwordless' ], 10, 2 );
    37     }
    38 
    39     private static function get_options() {
    40         if ( null === self::$opts ) {
    41             self::$opts = get_option( 'loginease_settings', [] );
     17    public static function init_hooks()
     18    {
     19        self::$opts = get_option('loginease_settings', []);
     20
     21        add_filter('wp_redirect', [__CLASS__, 'prevent_login_redirect'], 0, 2);
     22        add_action('init', [__CLASS__, 'maybe_block_default_login_and_admin'], 1);
     23        add_action('admin_init', [__CLASS__, 'maybe_block_wp_admin'], 1);
     24        add_action('login_init', [__CLASS__, 'maybe_block_wp_login'], 1);
     25        add_action('login_init', [__CLASS__, 'block_lost_password_if_passwordless'], 0);
     26        add_action('init', [__CLASS__, 'add_custom_login_rewrite'], 5);
     27        add_filter('query_vars', [__CLASS__, 'add_query_vars']);
     28        add_action('template_redirect', [__CLASS__, 'maybe_handle_custom_slug'], 1);
     29        add_filter('authenticate', [__CLASS__, 'loginease_authenticate'], 30, 3);
     30        add_filter('login_message', [__CLASS__, 'add_sent_message']);
     31        add_filter('body_class', [__CLASS__, 'body_class_notice']);
     32        add_action('login_form_login', [__CLASS__, 'process_login_request']);
     33        add_action('login_form', [__CLASS__, 'add_loginease_button'], 20);
     34        add_action('login_enqueue_scripts', [__CLASS__, 'enqueue_styles_scripts']);
     35        add_action('login_enqueue_scripts', [__CLASS__, 'disable_lost_password_link']);
     36        add_action('login_enqueue_scripts', [__CLASS__, 'hide_password_login_fields'], 20);
     37        add_filter('login_url', [__CLASS__, 'filter_login_url'], 10, 3);
     38        add_filter('allow_password_reset', [__CLASS__, 'disable_password_reset_if_passwordless'], 10, 2);
     39    }
     40
     41    private static function get_options()
     42    {
     43        if (null === self::$opts) {
     44            self::$opts = get_option('loginease_settings', []);
    4245        }
    4346        return self::$opts;
    4447    }
    4548
    46     public static function is_custom_login_enabled() {
     49    public static function is_custom_login_enabled()
     50    {
    4751        $options = self::get_options();
    48         return ! empty( $options['enable_custom_login'] );
    49     }
    50 
    51     public static function get_custom_login_slug() {
     52        return !empty($options['enable_custom_login']);
     53    }
     54
     55    public static function get_custom_login_slug()
     56    {
    5257        $options = self::get_options();
    53         $slug = isset( $options['custom_login_slug'] ) && $options['custom_login_slug'] !== '' ? $options['custom_login_slug'] : 'connexion';
    54         return sanitize_title( $slug );
    55     }
    56 
    57     public static function block_lost_password_if_passwordless() {
    58         $opts = self::get_options();
    59         if ( empty( $opts['disable_password_login'] ) ) {
    60             return;
    61         }
    62         $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '';
    63         if ( in_array( $action, [ 'lostpassword', 'resetpass' ], true ) ) {
    64             wp_safe_redirect( self::get_login_url() );
    65             exit;
    66         }
    67     }
    68 
    69     public static function disable_password_reset_if_passwordless( $allow, $user_id ) {
    70         $opts = self::get_options();
    71         if ( ! empty( $opts['disable_password_login'] ) ) {
     58        $slug = isset($options['custom_login_slug']) && $options['custom_login_slug'] !== '' ? $options['custom_login_slug'] : 'connexion';
     59        return sanitize_title($slug);
     60    }
     61
     62    public static function block_lost_password_if_passwordless()
     63    {
     64        $opts = self::get_options();
     65        if (empty($opts['disable_password_login'])) {
     66            return;
     67        }
     68        $action = isset($_GET['action']) ? sanitize_text_field(wp_unslash($_GET['action'])) : '';
     69        if (in_array($action, ['lostpassword', 'resetpass'], true)) {
     70            wp_safe_redirect(self::get_login_url());
     71            exit;
     72        }
     73    }
     74
     75    public static function disable_password_reset_if_passwordless($allow, $user_id)
     76    {
     77        $opts = self::get_options();
     78        if (!empty($opts['disable_password_login'])) {
    7279            return false;
    7380        }
     
    7582    }
    7683
    77     public static function disable_lost_password_link() {
    78         $opts = self::get_options();
    79         if ( empty( $opts['disable_password_login'] ) ) {
    80             return;
    81         }
    82         add_filter( 'gettext', function ( $translated_text, $text, $domain ) {
    83             if ( 'Lost your password?' === $text || 'Forgot your password?' === $text ) {
     84    public static function disable_lost_password_link()
     85    {
     86        $opts = self::get_options();
     87        if (empty($opts['disable_password_login'])) {
     88            return;
     89        }
     90        add_filter('gettext', function ($translated_text, $text, $domain) {
     91            if ('Lost your password?' === $text || 'Forgot your password?' === $text) {
    8492                return '';
    8593            }
    8694            return $translated_text;
    87         }, 10, 3 );
    88     }
    89 
    90     public static function hide_password_login_fields() {
    91         $opts = self::get_options();
    92         if ( empty( $opts['disable_password_login'] ) ) {
    93             return;
    94         }
    95         $current_action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : 'login';
    96         if ( 'login' !== $current_action ) {
     95        }, 10, 3);
     96    }
     97
     98    public static function hide_password_login_fields()
     99    {
     100        $opts = self::get_options();
     101        if (empty($opts['disable_password_login'])) {
     102            return;
     103        }
     104        $current_action = isset($_GET['action']) ? sanitize_text_field(wp_unslash($_GET['action'])) : 'login';
     105        if ('login' !== $current_action) {
    97106            return;
    98107        }
     
    100109    }
    101110
    102     public static function enqueue_styles_scripts() {
    103     $opts = self::get_options();
    104 
    105     $disable_password_login = ! empty( $opts['disable_password_login'] );
    106     $current_action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : 'login';
    107 
    108     if ( $disable_password_login && in_array( $current_action, [ 'lostpassword', 'resetpass' ], true ) ) {
    109         wp_safe_redirect( self::get_login_url() );
    110         exit;
    111     }
    112     if ( in_array( $current_action, [ 'lostpassword', 'resetpass' ], true ) ) {
    113         return;
    114     }
    115 
    116     // Construction correcte de la base URL du plugin
    117     $plugin_url_base = plugin_dir_url( dirname( __FILE__ ) );
    118 
    119     // Enqueue sans numéro de version (false)
    120     wp_enqueue_style(
    121         'loginease-style',
    122         $plugin_url_base . 'assets/css/loginease-style.css',
    123         []
    124     );
    125 
    126     wp_enqueue_script(
    127         'loginease-script',
    128         $plugin_url_base . 'assets/js/loginease-script.js',
    129         [],
    130     );
    131 }
    132 
    133     public static function add_custom_login_rewrite() {
    134         $opts = self::get_options();
    135         if ( empty( $opts['enable_custom_login'] ) ) {
     111    public static function enqueue_styles_scripts()
     112    {
     113        $opts = self::get_options();
     114
     115        $disable_password_login = !empty($opts['disable_password_login']);
     116        $current_action = isset($_GET['action']) ? sanitize_text_field(wp_unslash($_GET['action'])) : 'login';
     117
     118        if ($disable_password_login && in_array($current_action, ['lostpassword', 'resetpass'], true)) {
     119            wp_safe_redirect(self::get_login_url());
     120            exit;
     121        }
     122        if (in_array($current_action, ['lostpassword', 'resetpass'], true)) {
     123            return;
     124        }
     125
     126        // Construction correcte de la base URL du plugin
     127        $plugin_url_base = plugin_dir_url(dirname(__FILE__));
     128
     129        // Enqueue sans numéro de version (false)
     130        wp_enqueue_style(
     131            'loginease-style',
     132            $plugin_url_base . 'assets/css/loginease-style.css',
     133            []
     134        );
     135
     136        wp_enqueue_script(
     137            'loginease-script',
     138            $plugin_url_base . 'assets/js/loginease-script.js',
     139            [],
     140        );
     141    }
     142
     143    public static function add_custom_login_rewrite()
     144    {
     145        $opts = self::get_options();
     146        if (empty($opts['enable_custom_login'])) {
    136147            return;
    137148        }
    138149        $slug = self::get_custom_login_slug();
    139150
    140         add_rewrite_tag( '%loginease_custom%', '([^&]+)' );
    141         add_rewrite_rule( '^' . preg_quote( $slug, '/' ) . '/?$', 'index.php?loginease_custom=1', 'top' );
     151        add_rewrite_tag('%loginease_custom%', '([^&]+)');
     152        add_rewrite_rule('^' . preg_quote($slug, '/') . '/?$', 'index.php?loginease_custom=1', 'top');
    142153
    143154        global $wp_rewrite;
    144         if ( isset( $wp_rewrite ) && is_object( $wp_rewrite ) && property_exists( $wp_rewrite, 'rules' ) ) {
     155        if (isset($wp_rewrite) && is_object($wp_rewrite) && property_exists($wp_rewrite, 'rules')) {
    145156            $rule_key = '^' . $slug . '/?$';
    146157            $rule_value = 'index.php?loginease_custom=1';
    147158            $rules = (array) $wp_rewrite->rules;
    148             if ( ! isset( $rules[ $rule_key ] ) ) {
    149                 $wp_rewrite->rules = [ $rule_key => $rule_value ] + $rules;
    150             }
    151         }
    152     }
    153 
    154     public static function add_query_vars( $vars ) {
     159            if (!isset($rules[$rule_key])) {
     160                $wp_rewrite->rules = [$rule_key => $rule_value] + $rules;
     161            }
     162        }
     163    }
     164
     165    public static function add_query_vars($vars)
     166    {
    155167        $vars[] = 'loginease_custom';
    156168        return $vars;
    157169    }
    158170
    159     public static function maybe_handle_custom_slug() {
    160         $opts = self::get_options();
    161         if ( empty( $opts['enable_custom_login'] ) ) {
     171    public static function maybe_handle_custom_slug()
     172    {
     173        $opts = self::get_options();
     174        if (empty($opts['enable_custom_login'])) {
    162175            return;
    163176        }
    164177        $slug = self::get_custom_login_slug();
    165         $qv = get_query_var( 'loginease_custom' );
    166         $matched = ( (string) $qv === '1' );
    167         if ( ! $matched ) {
    168             $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
    169             $request_path = wp_parse_url( $request_uri, PHP_URL_PATH );
    170             $site_path = wp_parse_url( site_url(), PHP_URL_PATH );
    171             $site_path = $site_path ? ( '/' . trim( $site_path, '/' ) ) : '';
    172             $expected = rtrim( $site_path, '/' ) . '/' . $slug . '/';
    173             if ( strpos( $expected, '/' ) !== 0 ) {
    174                 $expected = '/' . ltrim( $expected, '/' );
    175             }
    176             if ( untrailingslashit( $request_path ) === untrailingslashit( $expected ) ) {
     178        $qv = get_query_var('loginease_custom');
     179        $matched = ((string) $qv === '1');
     180        if (!$matched) {
     181            $request_uri = isset($_SERVER['REQUEST_URI']) ? wp_unslash($_SERVER['REQUEST_URI']) : '';
     182            $request_path = wp_parse_url($request_uri, PHP_URL_PATH);
     183            $site_path = wp_parse_url(site_url(), PHP_URL_PATH);
     184            $site_path = $site_path ? ('/' . trim($site_path, '/')) : '';
     185            $expected = rtrim($site_path, '/') . '/' . $slug . '/';
     186            if (strpos($expected, '/') !== 0) {
     187                $expected = '/' . ltrim($expected, '/');
     188            }
     189            if (untrailingslashit($request_path) === untrailingslashit($expected)) {
    177190                $matched = true;
    178191            }
    179192        }
    180         if ( $matched ) {
    181             $target = site_url( 'wp-login.php' );
    182             $args = [ 'loginease' => $slug ];
    183             if ( isset( $_GET['redirect_to'] ) && $_GET['redirect_to'] !== '' ) {
    184                 $args['redirect_to'] = wp_unslash( $_GET['redirect_to'] );
    185             }
    186             if ( isset( $_GET['loginease_token'] ) && $_GET['loginease_token'] !== '' ) {
    187                 $args['loginease_token'] = wp_unslash( $_GET['loginease_token'] );
    188             }
    189             $target = add_query_arg( $args, $target );
    190             wp_safe_redirect( $target, 302 );
    191             exit;
    192         }
    193     }
    194 
    195     public static function maybe_block_default_login_and_admin() {
    196         $opts = self::get_options();
    197         if ( empty( $opts['enable_custom_login'] ) ) {
    198             return;
    199         }
    200         if ( defined( 'WP_CLI' ) && WP_CLI ) {
    201             return;
    202         }
    203         if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) {
    204             return;
    205         }
    206         $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
    207         $path = wp_parse_url( $request_uri, PHP_URL_PATH );
    208         $basename = strtolower( basename( $path ) );
    209         $disable_password_login = ! empty( $opts['disable_password_login'] );
    210         $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '';
    211         if ( $disable_password_login && in_array( $action, [ 'lostpassword', 'resetpass' ], true ) ) {
     193        if ($matched) {
     194            $target = site_url('wp-login.php');
     195            $args = ['loginease' => $slug];
     196            if (isset($_GET['redirect_to']) && $_GET['redirect_to'] !== '') {
     197                $args['redirect_to'] = wp_unslash($_GET['redirect_to']);
     198            }
     199            if (isset($_GET['loginease_token']) && $_GET['loginease_token'] !== '') {
     200                $args['loginease_token'] = wp_unslash($_GET['loginease_token']);
     201            }
     202            $target = add_query_arg($args, $target);
     203            wp_safe_redirect($target, 302);
     204            exit;
     205        }
     206    }
     207
     208    public static function maybe_block_default_login_and_admin()
     209    {
     210        $opts = self::get_options();
     211        if (empty($opts['enable_custom_login'])) {
     212            return;
     213        }
     214        if (defined('WP_CLI') && WP_CLI) {
     215            return;
     216        }
     217        if (function_exists('is_user_logged_in') && is_user_logged_in()) {
     218            return;
     219        }
     220        $request_uri = isset($_SERVER['REQUEST_URI']) ? wp_unslash($_SERVER['REQUEST_URI']) : '';
     221        $path = wp_parse_url($request_uri, PHP_URL_PATH);
     222        $basename = strtolower(basename($path));
     223        $disable_password_login = !empty($opts['disable_password_login']);
     224        $action = isset($_GET['action']) ? sanitize_text_field(wp_unslash($_GET['action'])) : '';
     225        if ($disable_password_login && in_array($action, ['lostpassword', 'resetpass'], true)) {
    212226            self::send_404_and_exit();
    213227        }
    214         if ( in_array( $basename, [ 'admin-ajax.php', 'admin-post.php' ], true ) ) {
    215             return;
    216         }
    217         if ( isset( $_GET['loginease_token'] ) && $_GET['loginease_token'] !== '' ) {
    218             return;
    219         }
    220         if ( isset( $_GET['loginease'] ) && $_GET['loginease'] === ( isset( $opts['custom_login_slug'] ) ? sanitize_title( $opts['custom_login_slug'] ) : 'connexion' ) ) {
    221             return;
    222         }
    223         if ( $basename === 'wp-login.php' || strpos( '/' . ltrim( (string) $path, '/' ), '/wp-admin' ) === 0 ) {
     228        if (in_array($basename, ['admin-ajax.php', 'admin-post.php'], true)) {
     229            return;
     230        }
     231        if (isset($_GET['loginease_token']) && $_GET['loginease_token'] !== '') {
     232            return;
     233        }
     234        if (isset($_GET['loginease']) && $_GET['loginease'] === (isset($opts['custom_login_slug']) ? sanitize_title($opts['custom_login_slug']) : 'connexion')) {
     235            return;
     236        }
     237        if ($basename === 'wp-login.php' || strpos('/' . ltrim((string) $path, '/'), '/wp-admin') === 0) {
    224238            self::send_404_and_exit();
    225239        }
    226240    }
    227241
    228     public static function maybe_block_wp_admin() {
    229         $opts = self::get_options();
    230         if ( empty( $opts['enable_custom_login'] ) ) {
    231             return;
    232         }
    233         if ( defined( 'WP_CLI' ) && WP_CLI ) {
    234             return;
    235         }
    236         if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) {
     242    public static function maybe_block_wp_admin()
     243    {
     244        $opts = self::get_options();
     245        if (empty($opts['enable_custom_login'])) {
     246            return;
     247        }
     248        if (defined('WP_CLI') && WP_CLI) {
     249            return;
     250        }
     251        if (function_exists('is_user_logged_in') && is_user_logged_in()) {
    237252            return;
    238253        }
    239254        $basename = '';
    240         if ( isset( $_SERVER['PHP_SELF'] ) ) {
    241             $basename = strtolower( basename( wp_unslash( $_SERVER['PHP_SELF'] ) ) );
    242             if ( in_array( $basename, [ 'admin-ajax.php', 'admin-post.php' ], true ) ) {
     255        if (isset($_SERVER['PHP_SELF'])) {
     256            $basename = strtolower(basename(wp_unslash($_SERVER['PHP_SELF'])));
     257            if (in_array($basename, ['admin-ajax.php', 'admin-post.php'], true)) {
    243258                return;
    244259            }
    245260        }
    246261        if (
    247             ( isset( $_GET['loginease'] ) && $_GET['loginease'] === self::get_custom_login_slug() )
    248             || ( isset( $_GET['loginease_token'] ) && $_GET['loginease_token'] !== '' )
     262            (isset($_GET['loginease']) && $_GET['loginease'] === self::get_custom_login_slug())
     263            || (isset($_GET['loginease_token']) && $_GET['loginease_token'] !== '')
    249264        ) {
    250265            return;
     
    253268    }
    254269
    255     public static function maybe_block_wp_login() {
    256         $opts = self::get_options();
    257         if ( empty( $opts['enable_custom_login'] ) ) {
    258             return;
    259         }
    260         if ( defined( 'WP_CLI' ) && WP_CLI ) {
    261             return;
    262         }
    263         if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) {
    264             return;
    265         }
    266         if ( isset( $_GET['loginease_token'] ) && $_GET['loginease_token'] !== '' ) {
    267             return;
    268         }
    269         if ( isset( $_GET['loginease'] ) && $_GET['loginease'] === self::get_custom_login_slug() ) {
    270             return;
    271         }
    272         $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
     270    public static function maybe_block_wp_login()
     271    {
     272        $opts = self::get_options();
     273        if (empty($opts['enable_custom_login'])) {
     274            return;
     275        }
     276        if (defined('WP_CLI') && WP_CLI) {
     277            return;
     278        }
     279        if (function_exists('is_user_logged_in') && is_user_logged_in()) {
     280            return;
     281        }
     282        if (isset($_GET['loginease_token']) && $_GET['loginease_token'] !== '') {
     283            return;
     284        }
     285        if (isset($_GET['loginease']) && $_GET['loginease'] === self::get_custom_login_slug()) {
     286            return;
     287        }
     288        $request_uri = isset($_SERVER['REQUEST_URI']) ? wp_unslash($_SERVER['REQUEST_URI']) : '';
    273289        $path_info = '';
    274         if ( ! empty( $_SERVER['PATH_INFO'] ) ) {
    275             $path_info = trim( wp_unslash( $_SERVER['PATH_INFO'] ), '/' );
     290        if (!empty($_SERVER['PATH_INFO'])) {
     291            $path_info = trim(wp_unslash($_SERVER['PATH_INFO']), '/');
    276292        } else {
    277             $pos = strpos( $request_uri, 'wp-login.php' );
    278             if ( $pos !== false ) {
    279                 $after = substr( $request_uri, $pos + strlen( 'wp-login.php' ) );
    280                 $path_info = trim( wp_parse_url( $after, PHP_URL_PATH ), '/' );
    281             }
    282         }
    283         if ( $path_info !== '' && $path_info === self::get_custom_login_slug() ) {
     293            $pos = strpos($request_uri, 'wp-login.php');
     294            if ($pos !== false) {
     295                $after = substr($request_uri, $pos + strlen('wp-login.php'));
     296                $path_info = trim(wp_parse_url($after, PHP_URL_PATH), '/');
     297            }
     298        }
     299        if ($path_info !== '' && $path_info === self::get_custom_login_slug()) {
    284300            return;
    285301        }
     
    287303    }
    288304
    289     public static function prevent_login_redirect( $location, $status ) {
    290         $opts = self::get_options();
    291         if ( empty( $opts['enable_custom_login'] ) ) {
     305    public static function prevent_login_redirect($location, $status)
     306    {
     307        $opts = self::get_options();
     308        if (empty($opts['enable_custom_login'])) {
    292309            return $location;
    293310        }
    294         if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) {
     311        if (function_exists('is_user_logged_in') && is_user_logged_in()) {
    295312            return $location;
    296313        }
    297         if ( defined( 'WP_CLI' ) && WP_CLI ) {
     314        if (defined('WP_CLI') && WP_CLI) {
    298315            return $location;
    299316        }
    300         $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
    301         $path = wp_parse_url( $request_uri, PHP_URL_PATH );
    302         $normalized = '/' . ltrim( (string) $path, '/' );
    303         if ( strpos( $normalized, '/wp-admin' ) === 0 ) {
    304             if ( false !== stripos( $location, 'wp-login.php' ) ) {
     317        $request_uri = isset($_SERVER['REQUEST_URI']) ? wp_unslash($_SERVER['REQUEST_URI']) : '';
     318        $path = wp_parse_url($request_uri, PHP_URL_PATH);
     319        $normalized = '/' . ltrim((string) $path, '/');
     320        if (strpos($normalized, '/wp-admin') === 0) {
     321            if (false !== stripos($location, 'wp-login.php')) {
    305322                self::send_404_and_exit();
    306323            }
    307             if ( function_exists( 'wp_login_url' ) ) {
     324            if (function_exists('wp_login_url')) {
    308325                $login_url = wp_login_url();
    309                 if ( $login_url && 0 === strpos( $location, $login_url ) ) {
     326                if ($login_url && 0 === strpos($location, $login_url)) {
    310327                    self::send_404_and_exit();
    311328                }
     
    315332    }
    316333
    317     private static function send_404_and_exit() {
    318         if ( ! headers_sent() ) {
    319             status_header( 404 );
     334    private static function send_404_and_exit()
     335    {
     336        if (!headers_sent()) {
     337            status_header(404);
    320338            nocache_headers();
    321339        }
    322         if ( function_exists( 'get_404_template' ) ) {
     340        if (function_exists('get_404_template')) {
    323341            $template = get_404_template();
    324             if ( $template && file_exists( $template ) ) {
     342            if ($template && file_exists($template)) {
    325343                include $template;
    326344                exit;
    327345            }
    328346        }
    329         if ( function_exists( 'wp_die' ) ) {
    330             wp_die( '<h1>404 Not Found</h1>', '404 Not Found', [ 'response' => 404 ] );
    331         }
    332         if ( isset( $_SERVER['SERVER_PROTOCOL'] ) ) {
    333             header( sanitize_text_field( wp_unslash( $_SERVER['SERVER_PROTOCOL'] ) ) . ' 404 Not Found', true, 404 );
     347        if (function_exists('wp_die')) {
     348            wp_die('<h1>404 Not Found</h1>', '404 Not Found', ['response' => 404]);
     349        }
     350        if (isset($_SERVER['SERVER_PROTOCOL'])) {
     351            header(sanitize_text_field(wp_unslash($_SERVER['SERVER_PROTOCOL'])) . ' 404 Not Found', true, 404);
    334352        } else {
    335             header( 'HTTP/1.0 404 Not Found', true, 404 );
     353            header('HTTP/1.0 404 Not Found', true, 404);
    336354        }
    337355        echo '<h1>404 Not Found</h1>';
     
    339357    }
    340358
    341     public static function add_sent_message( $message ) {
    342         if ( isset( $_GET['loginease_status'] ) ) {
    343             $status = sanitize_text_field( wp_unslash( $_GET['loginease_status'] ) );
    344             switch ( $status ) {
     359    public static function add_sent_message($message)
     360    {
     361        if (isset($_GET['loginease_status'])) {
     362            $status = sanitize_text_field(wp_unslash($_GET['loginease_status']));
     363            switch ($status) {
    345364                case 'sent':
    346                     $message .= '<p class="message loginease-sent-message">' . esc_html__( 'A magic login link has been sent to your email.', 'loginease' ) . '</p>';
     365                    $message .= '<p class="message loginease-sent-message">' . esc_html__('A magic login link has been sent to your email.', 'loginease') . '</p>';
    347366                    break;
    348367                case 'invalid':
    349                     $message .= '<p class="message loginease-error-message">' . esc_html__( 'Invalid or expired login link.', 'loginease' ) . '</p>';
     368                    $message .= '<p class="message loginease-error-message">' . esc_html__('Invalid or expired login link.', 'loginease') . '</p>';
    350369                    break;
    351370            }
     
    354373    }
    355374
    356     public static function body_class_notice( $classes ) {
    357         if ( isset( $_GET['loginease_status'] ) && sanitize_text_field( wp_unslash( $_GET['loginease_status'] ) ) === 'sent' ) {
     375    public static function body_class_notice($classes)
     376    {
     377        if (isset($_GET['loginease_status']) && sanitize_text_field(wp_unslash($_GET['loginease_status'])) === 'sent') {
    358378            $classes[] = 'loginease-email-sent';
    359379        }
     
    361381    }
    362382
    363     public static function filter_login_url( $login_url, $redirect = '', $force_reauth = false ) {
    364         if ( ! self::is_custom_login_enabled() ) {
     383    public static function filter_login_url($login_url, $redirect = '', $force_reauth = false)
     384    {
     385        if (!self::is_custom_login_enabled()) {
    365386            return $login_url;
    366387        }
    367388        $slug = self::get_custom_login_slug();
    368         $url = site_url( '/' . $slug . '/' );
    369         if ( ! empty( $redirect ) ) {
    370             $url = add_query_arg( 'redirect_to', rawurlencode( $redirect ), $url );
     389        $url = site_url('/' . $slug . '/');
     390        if (!empty($redirect)) {
     391            $url = add_query_arg('redirect_to', rawurlencode($redirect), $url);
    371392        }
    372393        return $url;
    373394    }
    374395
    375     public static function get_login_url( $redirect = '' ) {
    376         return wp_login_url( $redirect );
    377     }
    378 
    379     public static function process_login_request() {
    380         $opts = self::get_options();
    381         $disable_password_login = ! empty( $opts['disable_password_login'] );
    382         if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) {
    383             return;
    384         }
    385         if ( $disable_password_login && isset( $_POST['wp-submit'] ) ) {
    386             wp_safe_redirect( wp_login_url() );
    387             exit;
    388         }
    389         if ( isset( $_POST['loginease_submit'] ) && check_admin_referer( 'login', '_wpnonce' ) ) {
    390             $login_or_email_raw = isset( $_POST['log'] ) ? wp_unslash( $_POST['log'] ) : '';
    391             $login_or_email = sanitize_text_field( $login_or_email_raw );
    392             $redirect_url = add_query_arg( 'loginease_status', 'sent', self::get_login_url() );
    393             if ( empty( $login_or_email ) ) {
    394                 wp_safe_redirect( add_query_arg( 'login', 'empty', self::get_login_url() ) );
     396    public static function get_login_url($redirect = '')
     397    {
     398        return wp_login_url($redirect);
     399    }
     400
     401    public static function process_login_request()
     402    {
     403        $opts = self::get_options();
     404        $disable_password_login = !empty($opts['disable_password_login']);
     405        if (function_exists('is_user_logged_in') && is_user_logged_in()) {
     406            return;
     407        }
     408        if ($disable_password_login && isset($_POST['wp-submit'])) {
     409            wp_safe_redirect(wp_login_url());
     410            exit;
     411        }
     412        if (isset($_POST['loginease_submit']) && check_admin_referer('login', '_wpnonce')) {
     413            $login_or_email_raw = isset($_POST['log']) ? wp_unslash($_POST['log']) : '';
     414            $login_or_email = sanitize_text_field($login_or_email_raw);
     415            $redirect_url = add_query_arg('loginease_status', 'sent', self::get_login_url());
     416            if (empty($login_or_email)) {
     417                wp_safe_redirect(add_query_arg('login', 'empty', self::get_login_url()));
    395418                exit;
    396419            }
    397             $user = is_email( $login_or_email ) ? get_user_by( 'email', $login_or_email ) : get_user_by( 'login', $login_or_email );
    398             if ( ! $user ) {
    399                 wp_safe_redirect( $redirect_url );
     420            $user = is_email($login_or_email) ? get_user_by('email', $login_or_email) : get_user_by('login', $login_or_email);
     421            if (!$user) {
     422                wp_safe_redirect($redirect_url);
    400423                exit;
    401424            }
    402             $token = self::generate_token_for_user( $user->ID );
    403             self::send_login_email( $user, $token );
    404             wp_safe_redirect( $redirect_url );
    405             exit;
    406         }
    407         if ( isset( $_GET['loginease_token'] ) ) {
    408             $token = sanitize_text_field( wp_unslash( $_GET['loginease_token'] ) );
    409             self::login_with_token( $token );
    410         }
    411     }
    412 
    413     public static function loginease_authenticate( $user, $username, $password ) {
    414         if ( isset( $_POST['loginease_submit'] ) ) {
    415             if ( empty( $username ) ) {
    416                 return new WP_Error( 'empty_username', __( 'Missing username or email.', 'loginease' ) );
     425            $token = self::generate_token_for_user($user->ID);
     426            self::send_login_email($user, $token);
     427            wp_safe_redirect($redirect_url);
     428            exit;
     429        }
     430
     431        // Afficher formulaire de confirmation si token fourni dans URL mais pas encore confirmé
     432        if (isset($_GET['loginease_token']) && !isset($_POST['confirm_login'])) {
     433            $token = sanitize_text_field(wp_unslash($_GET['loginease_token']));
     434
     435            global $wpdb;
     436            $table = $wpdb->prefix . 'loginease_tokens';
     437            $now = current_time('mysql');
     438
     439            $row = $wpdb->get_row($wpdb->prepare(
     440                "SELECT * FROM $table WHERE token = %s AND expire > %s AND used = 0",
     441                $token,
     442                $now
     443            ));
     444
     445            if (!$row) {
     446                wp_safe_redirect(add_query_arg('loginease_status', 'invalid', self::get_login_url()));
     447                exit;
     448            }
     449
     450            // Affiche formulaire simple de confirmation (vous pouvez customiser HTML/CSS)
     451            wp_die(
     452                '<form method="POST" class="loginease-confirm-form" style="max-width:400px;margin:2em auto;padding:1em;border:1px solid #ccc;border-radius:4px;text-align:center;">' .
     453                wp_nonce_field('confirm_login', '_wpnonce', true, false) .
     454                '<input type="hidden" name="loginease_token" value="' . esc_attr($token) . '" />' .
     455                '<p style="margin-bottom:1em;">' . esc_html__('Vous avez cliqué sur un lien de connexion sécurisé. Confirmez-vous que vous souhaitez vous connecter ?', 'loginease') . '</p>' .
     456                '<button type="submit" name="confirm_login" style="background:#21759b;color:#fff;border:none;padding:0.5em 1em;cursor:pointer;border-radius:2px;">' . esc_html__('Confirmer la connexion', 'loginease') . '</button>' .
     457                '</form>',
     458                esc_html__('Confirmation de connexion', 'loginease'),
     459                ['response' => 200]
     460            );
     461            exit;
     462        }
     463
     464        // Traitement de la confirmation : validation du token, login et marquage du token utilisé
     465        if (isset($_POST['confirm_login']) && check_admin_referer('confirm_login', '_wpnonce')) {
     466            $token = isset($_POST['loginease_token']) ? sanitize_text_field(wp_unslash($_POST['loginease_token'])) : '';
     467
     468            global $wpdb;
     469            $table = $wpdb->prefix . 'loginease_tokens';
     470            $now = current_time('mysql');
     471
     472            $row = $wpdb->get_row(
     473                $wpdb->prepare(
     474                    "SELECT * FROM $table WHERE token = %s AND expire > %s AND used = 0",
     475                    $token,
     476                    $now
     477                )
     478            );
     479
     480            if (!$row) {
     481                wp_safe_redirect(add_query_arg('loginease_status', 'invalid', self::get_login_url()));
     482                exit;
     483            }
     484
     485            // Marquer le token comme utilisé
     486            $wpdb->update($table, ['used' => 1], ['id' => $row->id], ['%d'], ['%d']);
     487
     488            // Connexion effective de l'utilisateur
     489            wp_set_current_user($row->user_id);
     490            wp_set_auth_cookie($row->user_id);
     491
     492            if (class_exists('LoginEase_Logger')) {
     493                LoginEase_Logger::log($row->user_id, 'Magic link confirmed');
     494                LoginEase_Logger::cleanup();
     495            }
     496
     497            // Redirection finale (vers redirect_to ou tableau de bord)
     498            $redirect_to = isset($_REQUEST['redirect_to']) ? esc_url_raw(wp_unslash($_REQUEST['redirect_to'])) : admin_url();
     499            wp_safe_redirect($redirect_to);
     500            exit;
     501        }
     502    }
     503
     504    public static function loginease_authenticate($user, $username, $password)
     505    {
     506        if (isset($_POST['loginease_submit'])) {
     507            if (empty($username)) {
     508                return new WP_Error('empty_username', __('Missing username or email.', 'loginease'));
    417509            }
    418510            // Return null to prevent default password login attempt and allow magic login process.
     
    422514    }
    423515
    424     private static function generate_token_for_user( $user_id ) {
     516    private static function generate_token_for_user($user_id)
     517    {
    425518        global $wpdb;
    426519        $table = $wpdb->prefix . 'loginease_tokens';
    427         $now = current_time( 'mysql' );
    428         $wpdb->query( $wpdb->prepare( "DELETE FROM $table WHERE expire < %s OR used = 1", $now ) );
    429         $token = wp_generate_password( 20, false, false );
    430         $opts = self::get_options();
    431         $minutes = isset( $opts['token_expiration'] ) ? (int) $opts['token_expiration'] : 15;
    432         $expire_time = date_i18n( 'Y-m-d H:i:s', current_time( 'timestamp' ) + ( $minutes * 60 ) );
     520        $now = current_time('mysql');
     521        $wpdb->query($wpdb->prepare("DELETE FROM $table WHERE expire < %s OR used = 1", $now));
     522        $token = wp_generate_password(20, false, false);
     523        $opts = self::get_options();
     524        $minutes = isset($opts['token_expiration']) ? (int) $opts['token_expiration'] : 15;
     525        $expire_time = date_i18n('Y-m-d H:i:s', current_time('timestamp') + ($minutes * 60));
    433526        $wpdb->insert(
    434527            $table,
    435528            [
    436529                'user_id' => $user_id,
    437                 'token'   => $token,
    438                 'expire'  => $expire_time,
    439                 'used'    => 0,
     530                'token' => $token,
     531                'expire' => $expire_time,
     532                'used' => 0,
    440533            ],
    441             [ '%d', '%s', '%s', '%d' ]
     534            ['%d', '%s', '%s', '%d']
    442535        );
    443536        return $token;
    444537    }
    445538
    446     private static function send_login_email( $user, $token ) {
    447         $opts = self::get_options();
    448         $minutes = isset( $opts['token_expiration'] ) ? (int) $opts['token_expiration'] : 15;
    449         $expire_date = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), current_time( 'timestamp' ) + $minutes * 60 );
    450         $login_url = add_query_arg( 'loginease_token', rawurlencode( $token ), self::get_login_url() );
    451         $subject = sprintf( __( 'Your login link for %s', 'loginease' ), get_bloginfo( 'name' ) );
     539    private static function send_login_email($user, $token)
     540    {
     541        $opts = self::get_options();
     542        $minutes = isset($opts['token_expiration']) ? (int) $opts['token_expiration'] : 15;
     543        $expire_date = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), current_time('timestamp') + $minutes * 60);
     544        $login_url = add_query_arg('loginease_token', rawurlencode($token), self::get_login_url());
     545        $subject = sprintf(__('Your login link for %s', 'loginease'), get_bloginfo('name'));
    452546        $message = sprintf(
    453             __( "Hello,\n\nHere is your secure login link:\n\n%1\$s\n\nValid until %2\$s\n\nRegards,\n%3\$s", 'loginease' ),
     547            __("Hello,\n\nHere is your secure login link:\n\n%1\$s\n\nValid until %2\$s\n\nRegards,\n%3\$s", 'loginease'),
    454548            $login_url,
    455549            $expire_date,
    456             get_bloginfo( 'name' )
     550            get_bloginfo('name')
    457551        );
    458         wp_mail( $user->user_email, $subject, $message );
    459     }
    460 
    461     public static function login_with_token( $token ) {
     552        wp_mail($user->user_email, $subject, $message);
     553    }
     554
     555    public static function login_with_token($token)
     556    {
    462557        global $wpdb;
    463558        $table = $wpdb->prefix . 'loginease_tokens';
    464         $now = current_time( 'mysql' );
     559        $now = current_time('mysql');
    465560        $row = $wpdb->get_row(
    466561            $wpdb->prepare(
     
    470565            )
    471566        );
    472         if ( ! $row ) {
    473             wp_safe_redirect( add_query_arg( 'loginease_status', 'invalid', self::get_login_url() ) );
    474             exit;
    475         }
    476         $wpdb->update( $table, [ 'used' => 1 ], [ 'id' => $row->id ], [ '%d' ], [ '%d' ] );
    477         wp_set_current_user( $row->user_id );
    478         wp_set_auth_cookie( $row->user_id );
    479         if ( class_exists( 'LoginEase_Logger' ) ) {
    480             LoginEase_Logger::log( $row->user_id, 'Magic link' );
     567        if (!$row) {
     568            wp_safe_redirect(add_query_arg('loginease_status', 'invalid', self::get_login_url()));
     569            exit;
     570        }
     571        $wpdb->update($table, ['used' => 1], ['id' => $row->id], ['%d'], ['%d']);
     572        wp_set_current_user($row->user_id);
     573        wp_set_auth_cookie($row->user_id);
     574        if (class_exists('LoginEase_Logger')) {
     575            LoginEase_Logger::log($row->user_id, 'Magic link');
    481576            LoginEase_Logger::cleanup();
    482577        }
    483         $redirect_to = isset( $_REQUEST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_REQUEST['redirect_to'] ) ) : admin_url();
    484         wp_safe_redirect( $redirect_to );
     578        $redirect_to = isset($_REQUEST['redirect_to']) ? esc_url_raw(wp_unslash($_REQUEST['redirect_to'])) : admin_url();
     579        wp_safe_redirect($redirect_to);
    485580        exit;
    486581    }
    487582
    488     public static function add_loginease_button() {
    489         $opts = self::get_options();
    490         $disable_password_login = ! empty( $opts['disable_password_login'] );
    491         if ( isset( $_GET['action'] ) && sanitize_text_field( wp_unslash( $_GET['action'] ) ) !== 'login' ) {
    492             return;
    493         }
    494         wp_nonce_field( 'login', '_wpnonce' );
     583    public static function add_loginease_button()
     584    {
     585        $opts = self::get_options();
     586        $disable_password_login = !empty($opts['disable_password_login']);
     587        if (isset($_GET['action']) && sanitize_text_field(wp_unslash($_GET['action'])) !== 'login') {
     588            return;
     589        }
     590        wp_nonce_field('login', '_wpnonce');
    495591        $btn_class = $disable_password_login ? 'button button-primary' : 'button button-secondary';
    496         echo '<input type="submit" name="loginease_submit" id="loginease_submit" class="' . esc_attr( $btn_class ) . '" value="' . esc_attr__( 'Send me a login link', 'loginease' ) . '" />';
     592        echo '<input type="submit" name="loginease_submit" id="loginease_submit" class="' . esc_attr($btn_class) . '" value="' . esc_attr__('Send me a login link', 'loginease') . '" />';
    497593    }
    498594}
  • loginease/trunk/loginease.php

    r3362368 r3440551  
    33* Plugin Name: LoginEase
    44* Description: Passwordless login via magic link directly on the native WordPress login form, without shortcode.
    5 * Version: 1.0.0
     5* Version: 1.1.0
    66* Requires at least: 6.0
    7 * Requires PHP: 7.4
     7* Requires PHP: 8.0
    88* Author: Killian Santos
    99* Author URI: https://killian-santos.com/
  • loginease/trunk/readme.txt

    r3362368 r3440551  
    44Tags: login, passwordless, magic link, authentication, security
    55Requires at least: 6.0
    6 Tested up to: 6.8
    7 Requires PHP: 7.4
    8 Stable tag: 1.0.0
     6Tested up to: 6.9
     7Requires PHP: 8.0
     8Stable tag: 1.1.0
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    4141== Changelog ==
    4242
     43= 1.1.0 = 
     44* NEW: When logging in via a magic link, a confirmation message is now displayed for the user to explicitly approve the login. This step prevents the link from expiring prematurely, especially for users whose email security systems automatically scan links, which could cause the link to expire before the user can actually log in.
     45
    4346= 1.0.0 = 
    4447* Launch of the first public version of LoginEase
Note: See TracChangeset for help on using the changeset viewer.