Plugin Directory

source: listdom/tags/5.0.1/app/includes/user.php

Last change on this file was 3392570, checked in by Webilia, 2 weeks ago

Released Listdom 5.0.1

File size: 15.7 KB
Line 
1<?php
2
3class LSD_User extends LSD_Base
4{
5    public const META_VERIFICATION_STATUS = 'lsd_email_verification_status';
6    public const META_VERIFICATION_TOKEN = 'lsd_email_verification_token';
7
8    public static function requires_email_verification(): bool
9    {
10        $auth = LSD_Options::auth();
11        return !empty($auth['register']['email_verification']);
12    }
13
14    public static function is_email_verified(int $user_id): bool
15    {
16        if (!$user_id) return false;
17
18        if (!self::requires_email_verification()) return true;
19
20        $status = get_user_meta($user_id, self::META_VERIFICATION_STATUS, true);
21        if ($status === 'pending') return false;
22        if ($status === 'verified') return true;
23
24        // Treat users without a status as verified to preserve backward compatibility.
25        return true;
26    }
27
28    public static function verification_required_message(): string
29    {
30        $message = esc_html__('Your account is pending email verification. Please check your inbox to confirm your email address.', 'listdom');
31        return apply_filters('lsd_email_verification_required_message', $message);
32    }
33
34    public static function verification_success_message(): string
35    {
36        $message = esc_html__('Your email address has been verified. You can now log in.', 'listdom');
37        return apply_filters('lsd_email_verification_success_message', $message);
38    }
39
40    public static function verification_failed_message(): string
41    {
42        $message = esc_html__('Email verification link is invalid or has already been used.', 'listdom');
43        return apply_filters('lsd_email_verification_failed_message', $message);
44    }
45
46    public static function request_email_verification(int $user_id): string
47    {
48        if (!$user_id) return '';
49
50        $token = wp_generate_password(32, false);
51
52        update_user_meta($user_id, self::META_VERIFICATION_TOKEN, $token);
53        update_user_meta($user_id, self::META_VERIFICATION_STATUS, 'pending');
54        update_user_meta($user_id, 'lsd_email_verification_requested', current_time('mysql'));
55
56        return $token;
57    }
58
59    public static function verification_url(int $user_id, string $token): string
60    {
61        $url = add_query_arg([
62            'lsd_verify' => $user_id,
63            'lsd_key' => $token,
64        ], home_url('/'));
65
66        return apply_filters('lsd_email_verification_url', $url, $user_id, $token);
67    }
68
69    public static function maybe_send_verification_email(int $user_id)
70    {
71        if (!$user_id || !self::requires_email_verification()) return;
72
73        $status = get_user_meta($user_id, self::META_VERIFICATION_STATUS, true);
74        if ($status === 'verified') return;
75
76        $token = get_user_meta($user_id, self::META_VERIFICATION_TOKEN, true);
77
78        // When a pending token already exists, reuse it to avoid invalidating
79        // previously issued verification links (for example, when multiple
80        // registration hooks trigger this method).
81        if ($status !== 'pending' || !$token)
82        {
83            $token = self::request_email_verification($user_id);
84            if (!$token) return;
85        }
86
87        $url = self::verification_url($user_id, $token);
88
89        do_action('lsd_user_email_verification', $user_id, $token, $url);
90    }
91
92    public static function verify_email(int $user_id, string $token): bool
93    {
94        if (!$user_id) return false;
95
96        $token = sanitize_text_field($token);
97        if (!$token) return false;
98
99        $saved_token = get_user_meta($user_id, self::META_VERIFICATION_TOKEN, true);
100        if (!$saved_token) return false;
101
102        $is_valid = function_exists('hash_equals')
103            ? hash_equals($saved_token, $token)
104            : $saved_token === $token;
105
106        if (!$is_valid) return false;
107
108        delete_user_meta($user_id, self::META_VERIFICATION_TOKEN);
109        update_user_meta($user_id, self::META_VERIFICATION_STATUS, 'verified');
110        update_user_meta($user_id, 'lsd_email_verification_time', current_time('mysql'));
111
112        do_action('lsd_user_email_verified', $user_id);
113
114        return true;
115    }
116
117    public static function create(string $email)
118    {
119        $email = sanitize_email($email);
120
121        $exists = email_exists($email);
122        if ($exists) return $exists;
123        else
124        {
125            $results = register_new_user($email, $email);
126            if (!is_wp_error($results)) return $results;
127        }
128
129        return 0;
130    }
131
132    public static function register($user_login, $user_email, $password = null)
133    {
134        // Password
135        if (!$password) $password = wp_generate_password();
136
137        // Errors
138        $errors = new WP_Error();
139        $sanitized_user_login = sanitize_user($user_login);
140
141        /**
142         * Filters the email address of a user being registered.
143         *
144         * @param string $user_email The email address of the new user.
145         * @since 2.1.0
146         *
147         */
148        $user_email = apply_filters('user_registration_email', $user_email);
149
150        // Check the username.
151        if ('' === $sanitized_user_login) $errors->add('empty_username', wp_kses_post(__('<strong>Error</strong>: Please enter a username.', 'listdom')));
152        else if (!validate_username($user_login))
153        {
154            $errors->add('invalid_username', wp_kses_post(__('<strong>Error</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.', 'listdom')));
155            $sanitized_user_login = '';
156        }
157        else if (username_exists($sanitized_user_login)) $errors->add('username_exists', wp_kses_post(__('<strong>Error</strong>: This username is already registered. Please choose another one.', 'listdom')));
158        else
159        {
160            /** This filter is documented in wp-includes/user.php */
161            $illegal_user_logins = (array) apply_filters('illegal_user_logins', []);
162            if (in_array(strtolower($sanitized_user_login), array_map('strtolower', $illegal_user_logins), true)) $errors->add('invalid_username', wp_kses_post(__('<strong>Error</strong>: Sorry, that username is not allowed.', 'listdom')));
163        }
164
165        // Check the email address.
166        if ('' === $user_email) $errors->add('empty_email', wp_kses_post(__('<strong>Error</strong>: Please type your email address.', 'listdom')));
167        else if (!is_email($user_email))
168        {
169            $errors->add('invalid_email', wp_kses_post(__('<strong>Error</strong>: The email address isn&#8217;t correct.', 'listdom')));
170            $user_email = '';
171        }
172        else if (email_exists($user_email)) $errors->add('email_exists', wp_kses_post(__('<strong>Error</strong>: This email is already registered. Please choose another one.', 'listdom')));
173
174        /**
175         * Fires when submitting registration form data, before the user is created.
176         *
177         * @param string $sanitized_user_login The submitted username after being sanitized.
178         * @param string $user_email The submitted email.
179         * @param WP_Error $errors Contains any errors with submitted username and email,
180         *                                       e.g., an empty field, an invalid username or email,
181         *                                       or an existing username or email.
182         * @since 2.1.0
183         *
184         */
185        do_action('register_post', $sanitized_user_login, $user_email, $errors);
186
187        /**
188         * Filters the errors encountered when a new user is being registered.
189         *
190         * The filtered WP_Error object may, for example, contain errors for an invalid
191         * or existing username or email address. A WP_Error object should always be returned,
192         * but may or may not contain errors.
193         *
194         * If any errors are present in $errors, this will abort the user's registration.
195         *
196         * @param WP_Error $errors A WP_Error object containing any errors encountered
197         *                                       during registration.
198         * @param string $sanitized_user_login User's username after it has been sanitized.
199         * @param string $user_email User's email.
200         * @since 2.1.0
201         *
202         */
203        $errors = apply_filters('registration_errors', $errors, $sanitized_user_login, $user_email);
204
205        // Return Errors
206        if ($errors->has_errors()) return $errors;
207
208        $user_id = wp_create_user($sanitized_user_login, $password, $user_email);
209        if (!$user_id || is_wp_error($user_id))
210        {
211            $errors->add('registerfail', sprintf(
212                /* translators: %s: Support email address. */
213                wp_kses_post(__('<strong>Error</strong>: Couldn&#8217;t register you&hellip; please contact the <a href="mailto:%s">site admin</a>!', 'listdom')),
214                get_option('admin_email')
215            ));
216
217            return $errors;
218        }
219
220        update_user_option($user_id, 'default_password_nag', true, true); // Set up the password change nag.
221
222        /**
223         * Fires after a new user registration has been recorded.
224         *
225         * @param int $user_id ID of the newly registered user.
226         * @since 4.4.0
227         *
228         */
229        do_action('register_new_user', $user_id);
230
231        self::maybe_send_verification_email($user_id);
232
233        return $user_id;
234    }
235
236    public static function login($user_id)
237    {
238        wp_clear_auth_cookie();
239        wp_set_current_user($user_id);
240        wp_set_auth_cookie($user_id);
241    }
242
243    /**
244     * @param int $listing_id
245     * @param string $email
246     * @param string $password
247     * @param string $fullname
248     * @return int|mixed|WP_Error|null
249     */
250    public static function listing(int $listing_id, string $email, string $password = '', string $fullname = '')
251    {
252        if (!is_email($email)) return null;
253
254        $user_id = null;
255        $exists = email_exists($email);
256
257        if ($exists) $user_id = $exists;
258        else
259        {
260            $password = trim($password) ? sanitize_text_field($password) : wp_generate_password();
261            $registered = LSD_User::register($email, $email, $password);
262
263            if (!is_wp_error($registered))
264            {
265                $user_id = $registered;
266                if (trim($fullname))
267                {
268                    [$first_name, $last_name] = LSD_Main::get_name_parts(sanitize_text_field($fullname));
269
270                    // Update User
271                    wp_update_user([
272                        'ID' => $user_id,
273                        'first_name' => $first_name,
274                        'last_name' => $last_name,
275                        'display_name' => trim($first_name . ' ' . $last_name),
276                    ]);
277                }
278            }
279        }
280
281        // Assign Listing to new Owner
282        LSD_Main::assign($listing_id, $user_id);
283
284        // User ID
285        return $user_id;
286    }
287
288    public static function get_user_avatar($id_or_email = null, $size = 96)
289    {
290        if (!$id_or_email)
291        {
292            $user_id = get_current_user_id();
293            if (!$user_id) return '';
294
295            $id_or_email = $user_id;
296        }
297
298        return get_avatar($id_or_email, $size);
299    }
300
301    public static function get_user_info($username = ''): array
302    {
303        if ($username)
304        {
305            if (is_numeric($username)) $user = get_user_by('ID', $username);
306            else $user = get_user_by('login', $username);
307        }
308        else
309        {
310            $user_id = get_current_user_id();
311            if (!$user_id) return [];
312
313            $user = get_userdata($user_id);
314        }
315
316        if (!($user instanceof WP_User)) return [];
317
318        $meta_keys = [
319            'lsd_profile_image' => 'profile_image',
320            'lsd_hero_image' => 'hero_image',
321            'lsd_job_title' => 'job_title',
322            'description' => 'bio',
323            'lsd_phone' => 'phone',
324            'lsd_mobile' => 'mobile',
325            'lsd_website' => 'website',
326            'lsd_fax' => 'fax',
327            'lsd_facebook' => 'facebook',
328            'lsd_twitter' => 'twitter',
329            'lsd_pinterest' => 'pinterest',
330            'lsd_linkedin' => 'linkedin',
331            'lsd_instagram' => 'instagram',
332            'lsd_whatsapp' => 'whatsapp',
333            'lsd_youtube' => 'youtube',
334            'lsd_tiktok' => 'tiktok',
335            'lsd_telegram' => 'telegram',
336        ];
337
338        $user_meta = [];
339        foreach ($meta_keys as $meta_key => $field_name)
340        {
341            $user_meta[$field_name] = get_user_meta($user->ID, $meta_key, true) ?: '';
342        }
343
344        return array_merge([
345            'ID' => $user->ID,
346            'display_name' => $user->display_name,
347            'email' => $user->user_email,
348            'description' => $user->description,
349            'first_name' => $user->first_name ?: '',
350            'last_name' => $user->last_name ?: '',
351        ], $user_meta);
352    }
353
354    public static function send_forgot_password_email(WP_User $user): bool
355    {
356        // Generate password reset key and link
357        $reset_key = get_password_reset_key($user);
358        if (is_wp_error($reset_key)) return false;
359
360        $reset_link = network_site_url("wp-login.php?action=rp&key=$reset_key&login=" . rawurlencode($user->user_login), 'login');
361
362        // Send password reset email
363        $message = esc_html__('Someone has requested a password reset for the following account:', 'listdom') . "\r\n\r\n";
364        $message .= network_home_url('/') . "\r\n\r\n";
365        $message .= sprintf(
366            /* translators: %s: Username for the account. */
367            esc_html__('Username: %s', 'listdom'),
368            $user->user_login
369        ) . "\r\n\r\n";
370        $message .= esc_html__('If this was a mistake, just ignore this email and nothing will happen.', 'listdom') . "\r\n\r\n";
371        $message .= esc_html__('To reset your password, visit the following address:', 'listdom') . "\r\n\r\n";
372        $message .= '<a href="' . esc_url($reset_link) . '">' . esc_url($reset_link) . '</a>' . "\r\n";
373
374        return wp_mail($user->user_email, esc_html__('Password Reset Request', 'listdom'), $message);
375    }
376
377    public static function profile_link(int $id): string
378    {
379        $auth = LSD_Options::auth();
380
381        $profile_page_id = isset($auth['profile']['page']) && $auth['profile']['page'] ? $auth['profile']['page'] : 0;
382        $profile_page = $profile_page_id ? get_post($profile_page_id) : null;
383
384        // Listdom Profile Page
385        if ($profile_page instanceof WP_Post && $profile_page->post_status === 'publish')
386        {
387            // User
388            $user = get_user($id);
389
390            if ($user && isset($user->user_login))
391            {
392                // URL Structure
393                $structure = get_option('permalink_structure');
394
395                // URL
396                $url = get_permalink($profile_page);
397
398                // Main
399                $main = new LSD_Main();
400
401                $slug = $user->user_login;
402                if (is_email($slug)) $slug = $user->ID;
403
404                // Generate URL
405                if ($structure) return trim($url, '/ ') . '/' . sanitize_title($slug);
406                else return $main->add_qs_var('user', sanitize_title($slug), $url);
407            }
408        }
409
410        return get_author_posts_url($id);
411    }
412
413    public static function all_roles(): array
414    {
415        $roles = [];
416        foreach (wp_roles()->roles as $key => $details) $roles[$key] = translate_user_role($details['name']);
417
418        return $roles;
419    }
420
421    public static function roles(bool $only_keys = false): array
422    {
423        $roles = apply_filters('lsd_user_supported_roles', [
424            'subscriber' => esc_html__('Subscriber', 'listdom'),
425            'contributor' => esc_html__('Contributor', 'listdom'),
426            'listdom_author' => esc_html__('Listdom Author', 'listdom'),
427            'listdom_publisher' => esc_html__('Listdom Publisher', 'listdom'),
428        ]);
429
430        // Only Keys
431        if ($only_keys) return array_keys($roles);
432
433        return $roles;
434    }
435}
Note: See TracBrowser for help on using the repository browser.