| @@ -45,10 +45,20 @@ | ||
| 45 | 45 | __('<strong>Error:</strong> This email address is already registered. Please login or try resetting your password.', 'fluent-community') |
| 46 | 46 | ); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | + /** | |
| 50 | + * MemberPress rejects every `register_post` while its "Disable WordPress registration form" | |
| 51 | + * option is on (default on). That option targets wp-login.php, not the community portal, which has its own registration gate. | |
| 52 | + */ | |
| 53 | + $hadMeprBlocker = remove_action('register_post', 'MeprUsersCtrl::maybe_disable_wp_registration_form', 10); | |
| 54 | + | |
| 49 | 55 | do_action('register_post', $sanitized_user_login, $user_email, $errors); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound |
| 50 | 56 | |
| 57 | + if ($hadMeprBlocker) { | |
| 58 | + add_action('register_post', 'MeprUsersCtrl::maybe_disable_wp_registration_form', 10, 3); | |
| 59 | + } | |
| 60 | + | |
| 51 | 61 | if ($errors->has_errors()) { |
| 52 | 62 | return $errors; |
| 53 | 63 | } |
| 54 | 64 | |
| @@ -128,15 +138,88 @@ | ||
| 128 | 138 | |
| 129 | 139 | return $user; |
| 130 | 140 | } |
| 131 | 141 | |
| 142 | + /** | |
| 143 | + * The slug this plugin is known by inside FluentAuth. | |
| 144 | + */ | |
| 145 | + const FLUENT_AUTH_HOST = 'fluent-community'; | |
| 146 | + | |
| 147 | + /** | |
| 148 | + * Whether FluentAuth's login stack is usable on this screen. | |
| 149 | + * | |
| 150 | + * Note the order this has to be asked in: adoptFluentAuth() is what makes the answer | |
| 151 | + * yes on a site whose shortcode setting is off, so the auth screen adopts first and | |
| 152 | + * asks second. Everywhere else - a plugin wondering whether the portal is running | |
| 153 | + * FluentAuth's forms - the question stands on its own. | |
| 154 | + */ | |
| 132 | 155 | public static function isFluentAuthAvailable() |
| 133 | 156 | { |
| 134 | - if (defined('FLUENT_AUTH_VERSION') && FLUENT_AUTH_VERSION) { | |
| 135 | - return (new \FluentAuth\App\Hooks\Handlers\CustomAuthHandler())->isEnabled(); | |
| 157 | + if (!defined('FLUENT_AUTH_VERSION') || !FLUENT_AUTH_VERSION) { | |
| 158 | + return false; | |
| 136 | 159 | } |
| 137 | 160 | |
| 138 | - return false; | |
| 161 | + return (new \FluentAuth\App\Hooks\Handlers\CustomAuthHandler())->isEnabled(); | |
| 162 | + } | |
| 163 | + | |
| 164 | + /** | |
| 165 | + * Tells FluentAuth this plugin exists, so it recognises the admin-ajax posts our | |
| 166 | + * auth screen makes later. Cheap enough to run on every request, which is what it | |
| 167 | + * has to do - the form post is a request of its own. | |
| 168 | + * | |
| 169 | + * @return void | |
| 170 | + */ | |
| 171 | + public static function registerWithFluentAuth() | |
| 172 | + { | |
| 173 | + if (!self::hasFluentAuthBridge()) { | |
| 174 | + return; | |
| 175 | + } | |
| 176 | + | |
| 177 | + \FluentAuth\App\Services\LoginBridge::register( | |
| 178 | + self::FLUENT_AUTH_HOST, | |
| 179 | + 'is_fcom_auth', | |
| 180 | + /* | |
| 181 | + * Our own login endpoint. Unreachable while the portal renders FluentAuth's | |
| 182 | + * form, but a site that filters the adoption back off falls through to it, | |
| 183 | + * and this is what keeps the second factor arriving as a form there rather | |
| 184 | + * than as the error message handleUserLogin() would otherwise print. | |
| 185 | + */ | |
| 186 | + ['fcom_user_login_form'] | |
| 187 | + ); | |
| 188 | + } | |
| 189 | + | |
| 190 | + /** | |
| 191 | + * Hands the screen being rendered to FluentAuth: its shortcodes render here even | |
| 192 | + * where the site has the front end forms switched off, its assets load, and its | |
| 193 | + * endpoints answer the posts this screen's forms make. | |
| 194 | + * | |
| 195 | + * @return bool whether FluentAuth took it | |
| 196 | + */ | |
| 197 | + public static function adoptFluentAuth() | |
| 198 | + { | |
| 199 | + if (!self::hasFluentAuthBridge()) { | |
| 200 | + return false; | |
| 201 | + } | |
| 202 | + | |
| 203 | + \FluentAuth\App\Services\LoginBridge::adopt([ | |
| 204 | + 'host' => self::FLUENT_AUTH_HOST | |
| 205 | + ]); | |
| 206 | + | |
| 207 | + return true; | |
| 208 | + } | |
| 209 | + | |
| 210 | + /** | |
| 211 | + * @return bool whether the installed FluentAuth is new enough to be adopted | |
| 212 | + */ | |
| 213 | + private static function hasFluentAuthBridge() | |
| 214 | + { | |
| 215 | + // FluentAuth's autoloader requires the mapped file unconditionally, so probing | |
| 216 | + // for a class an older release does not ship is a fatal error, not a false. | |
| 217 | + return defined('FLUENT_AUTH_VERSION') | |
| 218 | + && FLUENT_AUTH_VERSION | |
| 219 | + && defined('FLUENT_AUTH_PLUGIN_PATH') | |
| 220 | + && file_exists(FLUENT_AUTH_PLUGIN_PATH . 'app/Services/LoginBridge.php') | |
| 221 | + && class_exists('\FluentAuth\App\Services\LoginBridge'); | |
| 139 | 222 | } |
| 140 | 223 | |
| 141 | 224 | public static function getTermsText() |
| 142 | 225 | { |