From 86c6cd3cc099d2480932ede03c12cea01e625c94 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 26 Apr 2026 21:56:28 +0000
Subject: [PATCH] =Requiring files based on Site class settings

---
 inc/managers/LoginManager.php |  352 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 176 insertions(+), 176 deletions(-)

diff --git a/inc/managers/LoginManager.php b/inc/managers/LoginManager.php
index 525a53f..d86d1e8 100644
--- a/inc/managers/LoginManager.php
+++ b/inc/managers/LoginManager.php
@@ -1,12 +1,10 @@
 <?php
 namespace JVBase\managers;
 
-use JVBase\blocks\CustomBlocks;
+use JVBase\base\Site;
 use JVBase\forms\TaxonomySelector;
-use JVBase\meta\MetaManager;
-use JVBase\meta\MetaForm;
-use JVBase\managers\AjaxRateLimiter;
-use JVBase\utility\Features;
+use JVBase\meta\Form;
+
 use WP_Error;
 use WP_User;
 
@@ -16,12 +14,8 @@
 
 class LoginManager
 {
-	protected Features $siteFeatures;
-	protected ?MagicLinkManager $magicLink = null;
-	protected ?MetaForm $metaForm = null;
-	protected EmailManager $emailManager;
-	protected AjaxRateLimiter $rateLimiter;
-	protected CacheManager $cache;
+	protected ?Form $form = null;
+	protected Cache $cache;
 
 
 	protected array $forms =[];
@@ -43,14 +37,10 @@
 
 	public function __construct()
 	{
-		$this->siteFeatures = Features::forSite();
-		$this->emailManager = new EmailManager();
-
-
-		$this->cache = CacheManager::for('login');
+		$this->cache = Cache::for('login');
 
 		// Initialize magic link support if enabled
-		if ($this->siteFeatures->has('magicLink')) {
+		if (Site::has('magicLink')) {
 			$this->initMagicLinkSupport();
 		}
 
@@ -67,10 +57,20 @@
 		// Login success handling
 		add_action('wp_login', [$this, 'handleSuccessfulLogin'], 10, 2);
 
+		add_filter('lostpassword_url', [$this, 'resetPasswordUrl'], 10, 2);
+		add_filter( 'login_url', [$this, 'loginUrl'], 10, 3 );
+		add_filter( 'logout_url', [$this, 'logoutUrl'], 10, 2 );
 		// Allow other features to register handlers
 		do_action('jvbLoginManagerInit', $this);
+		add_action('user_register', array($this, 'saveRegistrationFields'), 999, 2);
+		add_filter('the_seo_framework_sitemap_exclude_ids', [$this, 'excludeLoginSitemap'], 10, 1);
 	}
 
+	public function excludeLoginSitemap(array $ids): array
+	{
+		$ids[] = $this->getLoginPage();
+		return $ids;
+	}
 	/**************************************************************************
 	   * SETUP & CONFIGURATION
 	**************************************************************************/
@@ -90,7 +90,7 @@
 			return;
 		}
 		// Build custom login URL with all query args
-		$custom_login_page = home_url('/login');
+		$custom_login_page = home_url('/login/');
 		$query_args = $_GET;
 
 		// Remove WordPress internal args
@@ -125,7 +125,7 @@
 					'placeholder'=> 'look@me.com'
 				]
 			];
-			if (Features::forSite()->has('referrals')) {
+			if (Site::has('referrals')) {
 				$fields['referral_code'] = [
 					'type'	=> 'text',
 					'required'=> false,
@@ -222,12 +222,14 @@
 						'type' => 'email',
 						'label' => __('Email Address', 'jvb'),
 						'required' => true,
+						'autocomplete'	=> 'email',
 						'placeholder' => 'look@me.com',
 					],
 					'user_password' => [
 						'type' => 'text',
 						'subtype'=> 'password',
 						'label' => __('Password', 'jvb'),
+						'autocomplete' => 'current-password',
 						'required' => true,
 					],
 					'remember_me' => [
@@ -287,6 +289,40 @@
 			}
 		}
 	}
+	public function loginUrl(string $login_url, string $redirect, bool $force_reauth):string
+	{
+		// This will append /custom-login/ to you main site URL as configured in general settings (ie https://domain.com/custom-login/)
+		$login_url = site_url( '/login/', 'login' );
+		if ( ! empty( $redirect ) ) {
+			$login_url = add_query_arg( 'redirect_to', urlencode( $redirect ), $login_url );
+		}
+		if ( $force_reauth ) {
+			$login_url = add_query_arg( 'reauth', '1', $login_url );
+		}
+		return $login_url;
+	}
+
+	public function logoutUrl(string $logout_url, string $redirect): string
+	{
+		// Build custom logout URL
+		$logout_url = site_url('/login/', 'login');
+		$logout_url = add_query_arg('action', 'logout', $logout_url);
+
+		if (!empty($redirect)) {
+			$logout_url = add_query_arg('redirect_to', urlencode($redirect), $logout_url);
+		}
+
+		// Add nonce for security
+		return wp_nonce_url($logout_url, 'log-out');
+	}
+	public function resetPasswordUrl(string $url, string $redirect):string
+	{
+		error_log('reset Password Url:'.print_r($url, true));
+		error_log('reset password redirect: '.print_r($redirect, true));
+
+		return str_replace('wp_login.php', 'login/', $url);
+
+	}
 	public function getLoginPage():int|false
 	{
 		return (int)get_option(BASE.'login_page');
@@ -305,10 +341,9 @@
 
 	protected function initMagicLinkSupport(): void
 	{
-		if (!Features::forSite()->has('magicLink')) {
+		if (!Site::has('magicLink')) {
 			return;
 		}
-		$this->magicLink = new MagicLinkManager();
 	}
 
 	/*********************************************************************
@@ -369,17 +404,11 @@
 	protected function setup():void
 	{
 		$this->action = $this->getAction();
-		if (in_array($this->action, ['logout']) || array_key_exists('loggedout', $_GET)) {
+		if ($this->action == 'logout' || array_key_exists('loggedout', $_GET)) {
 			wp_logout();
 			wp_redirect(esc_attr($_GET['redirect_to'] ?? get_home_url()));
 			exit;
 		}
-		if (in_array($this->action, ['rp', 'resetpass']) && !is_user_logged_in()) {
-			wp_redirect(wp_login_url());
-			exit;
-		} elseif (is_user_logged_in()) {
-			wp_redirect(get_home_url(null, '/dash/'));
-		}
 		$this->setupLabels();
 		$this->setupFields();
 		$this->setupTitle();
@@ -406,11 +435,9 @@
 	protected function customStyles():void
 	{
 		$logo = get_theme_mod('custom_logo');
-		$small = $large = '';
 		if ($logo) {
-			$small = wp_get_attachment_image_src($logo, 'medium')[0];
-			$large = wp_get_attachment_image_src($logo, 'large')[0];
-
+			$small = wp_get_attachment_image_src($logo, 'medium')[0]??'';
+			$large = wp_get_attachment_image_src($logo, 'large')[0]??'';
 		}
 		echo '<style>
 			.login header,
@@ -501,7 +528,6 @@
 
 	protected function renderForms():void
 	{
-		$this->metaForm = new MetaForm();
 		$form = $this->action.'form';
 		?>
 		<section class="login-box col btw">
@@ -520,7 +546,7 @@
 				do_action('jvb_add_token_inputs', $this->action);
 
 				foreach ($this->fields as $name => $config) {
-					$this->metaForm->render($name, '', $config);
+					echo Form::render($name, '', $config);
 				}
 
 				$this->maybeTurnstile();
@@ -597,7 +623,8 @@
             $checked = (is_user_logged_in() && current_user_can('prefers_dark_theme', true)) ? ' checked' : '';
             $title = ($checked == '') ? 'Toggle Dark Mode' : 'Toggle Light Mode';
             echo '<label title="'.$title.'" id="theme-switch" class="toggle-switch" for="theme-switcher">
-                    <input class="theme-switch row" id="theme-switcher" type="checkbox"'.$checked.' data-setting="theme" data-theme role="switch" name="dark-mode"><span class="slider">'.
+    				<span class="screen-reader-text">Toggle dark mode</span>
+                    <input class="theme-switch row" id="theme-switcher" name="theme-switcher" type="checkbox"'.$checked.' data-setting="theme" data-theme name="dark-mode" aria-label="Toggle dark mode"><span class="slider">'.
 					jvbIcon('sun-dim', ['title'=> 'Light Mode']).
 					jvbIcon('moon', ['title'=>'Dark Mode']).
 					'</span></label>';
@@ -684,7 +711,7 @@
 
 	protected function maybeTurnstile(): void
 	{
-		if (!Features::hasIntegration('cloudflare')) {
+		if (!Site::hasIntegration('cloudflare')) {
 			return;
 		}
 		JVB()->connect('cloudflare')->renderTurnstile();
@@ -692,7 +719,7 @@
 
 	protected function maybeTurnstileScripts(): void
 	{
-		if (!Features::hasIntegration('cloudflare')) {
+		if (!Site::hasIntegration('cloudflare')) {
 			return;
 		}
 		JVB()->connect('cloudflare')->enqueueTurnstileScripts();
@@ -700,7 +727,7 @@
 
 	protected function verifyTurnstile(): bool
 	{
-		if (!Features::hasIntegration('cloudflare')) {
+		if (!Site::hasIntegration('cloudflare')) {
 			return true; // Not enabled, pass verification
 		}
 
@@ -753,66 +780,25 @@
 	{
 		switch ($this->action) {
 			case 'register':
-				return [
-					'title' => JVB_LOGIN['register']['title'] ?? 'Create Your Account',
-					'description' => JVB_LOGIN['register']['description'] ?? [],
-					'extra' => JVB_LOGIN['register']['extra'] ?? [],
-					'footer' => JVB_LOGIN['register']['footer'] ?? '',
-					'email' => JVB_LOGIN['register']['email']['subject'] ?? '['.get_bloginfo('name').'] Finish Creating Your Account',
-					'submit' => JVB_LOGIN['register']['submit'] ?? 'Create Account',
-					'successTitle' => JVB_LOGIN['register']['success']['title'] ?? 'Success!',
-					'successDescription' => JVB_LOGIN['register']['success']['description'] ?? ['See your email for next steps','(Check your spam folder if you cannot find it after a couple minutes.)'],
-				];
+				return Site::login()->getLabels('register');
 			case 'lostpassword':
-				return [
-					'title' => JVB_LOGIN['forgot_password']['title'] ?? 'Reset Password',
-					'description' => JVB_LOGIN['forgot_password']['description'] ?? [],
-					'extra' => JVB_LOGIN['forgot_password']['extra'] ?? [],
-					'footer' => JVB_LOGIN['forgot_password']['footer'] ?? '',
-					'submit' => JVB_LOGIN['forgot_password']['submit'] ?? 'Send Reset Link',
-					'successTitle' => JVB_LOGIN['forgot_password']['success']['title'] ?? 'Success!',
-					'successDescription' => JVB_LOGIN['forgot_password']['success']['description'] ?? ['Check your email for reset instructions'],
-				];
+				return Site::login()->getLabels('lostPassword');
 			case 'resetpass':
-				return [
-					'title' => JVB_LOGIN['reset_pass']['title'] ?? 'Reset Your Password',
-					'description' => JVB_LOGIN['reset_pass']['description'] ?? [],
-					'extra' => JVB_LOGIN['reset_pass']['extra'] ?? [],
-					'footer' => JVB_LOGIN['reset_pass']['footer'] ?? '',
-					'submit' => JVB_LOGIN['reset_pass']['submit'] ?? 'Reset Password',
-				];
+			case 'rp':
+				return Site::login()->getLabels('resetPassword');
 			case 'logout':
-				return [
-					'title' => JVB_LOGIN['logout']['title'] ?? 'Logged Out!',
-					'description' => JVB_LOGIN['logout']['description'] ?? [],
-					'extra' => JVB_LOGIN['logout']['extra'] ?? [],
-					'footer' => JVB_LOGIN['logout']['footer'] ?? '',
-					'submit' => JVB_LOGIN['logout']['submit'] ?? '',
-				];
+				return Site::login()->getLabels('logout');
 			case 'magic':
-				return [
-					'title' => JVB_LOGIN['magic']['title'] ?? 'Log in with Magic Link',
-					'description' => JVB_LOGIN['magic']['description'] ?? ['Enter your email.','You\'ll get an email with a magic link.','Click it, and you\'re logged in!'],
-					'extra' => JVB_LOGIN['magic']['extra'] ?? [],
-					'footer' => JVB_LOGIN['magic']['footer'] ?? '',
-					'submit' => JVB_LOGIN['magic']['submit'] ?? jvbIcon('magic-wand').'Send Magic Link',
-
-				];
+				return Site::login()->getLabels('magic');
 			case 'login':
 			default:
-				return [
-					'title' => JVB_LOGIN['login']['title'] ?? 'Sign in',
-					'description' => JVB_LOGIN['login']['description'] ?? [],
-					'extra' => JVB_LOGIN['login']['extra'] ?? [],
-					'footer' => JVB_LOGIN['login']['footer'] ?? '',
-					'submit' => JVB_LOGIN['login']['submit'] ?? 'Sign In',
-				];
+				return Site::login()->getLabels('login');
 		}
 	}
 
 	protected function maybeMagicLink(): void
 	{
-		if (!$this->magicLink || !in_array($this->action, ['login', 'lostpassword'])) {
+		if (!JVB()->magicLink() || !in_array($this->action, ['login', 'lostpassword'])) {
 			return;
 		}
 		?>
@@ -828,110 +814,119 @@
 		SCRIPTS
 	************************************************************************/
 	public function enqueueScripts(): void
-	{
-		if (!$this->isLoginPage()) {
-			return;
-		}
+{
+    if (!$this->isLoginPage()) {
+        return;
+    }
 
-		$this->maybeTurnstileScripts();
-		wp_enqueue_script('jvb-form');
-		$action = $this->getAction();
-		ob_start();
-		?>
+    $this->maybeTurnstileScripts();
+    wp_enqueue_script('jvb-form');
+    $action = $this->getAction();
 
-		document.addEventListener('DOMContentLoaded', () => {
-			const form = document.querySelector('.login form');
-			if (!form) return;
+    $redirect_to = isset($_GET['redirect_to']) ? esc_url_raw($_GET['redirect_to']) : '';
+    $has_turnstile = Site::hasIntegration('cloudflare');
 
-			if (!window.jvbForm) {
-				console.error('jvbForm not loaded');
-				return;
-			}
+    ob_start();
 
-			window.LoginController = new window.jvbForm();
-			window.LoginController.registerForm(form, {
-				autosave: false,
-				endpoint: <?= "'{$action}'" ?>,
-				formStatus: false,
-				cache: false,
-			});
+    ?>
 
-			window.LoginController.subscribe((event, data) => {
-				if (event === 'form-submit') {
-					handleFormSubmission(data);
-				}
-			});
+	document.addEventListener('DOMContentLoaded', async function () {
+		const hasTurnstile = <?= json_encode($has_turnstile) ?>;
+		const redirectTo = <?= json_encode($redirect_to) ?>;
 
+		window.auth.subscribe(event => {
+			if (event === 'auth-loaded') {
+				const form = document.querySelector('.login form');
+				if (!form || !window.jvbForm) return;
 
-			async function handleFormSubmission(data) {
-			let realFormData = data.fullData;
-			const { formId, config, data: formData } = data;
-
-
-			const form = config.element;
-
-			const submit = form.querySelector('[type=submit]');
-			let oldText = submit.textContent;
-
-
-			window.LoginController.showFormStatus(formId, 'uploading');
-
-			try {
-				submit.disabled = true;
-				submit.textContent = 'Loading...';
-				const response = await fetch(`${jvbSettings.api}<?=($action === 'magic') ? $action : 'auth/'.$action?>`, {
-					method: 'POST',
-					headers: {
-                		'Content-Type': 'application/json',
-						'X-WP-Nonce': jvbSettings.nonce
-					},
-					body: JSON.stringify(realFormData)
+				window.jvbForm.registerForm(form, {
+					endpoint: '<?= $action ?>',
+					showStatus: false,
+					cache: false,
 				});
 
-					const result = await response.json();
+				window.jvbForm.subscribe((event, data) => {
+					if (event === 'form-submit') {
+						const { config } = data;
+						const formElement = config.element;
 
-					// Handle errors
-					if (!response.ok) {
-						window.LoginController.showFormStatus(formId, 'error');
-						window.LoginController.handleFormError(form, result);
-						return;
+						// Collect current form data
+						const formData = new FormData(formElement);
+						const formObject = Object.fromEntries(formData.entries());
+
+						let params = new URLSearchParams(window.location.search);
+						if (params.has('key')) {
+							formObject['key'] = params.get('key');
+						}
+						if (params.has('login')) {
+							formObject['login'] = params.get('login');
+						}
+
+						// Add redirect_to from URL
+						if (redirectTo) {
+							formObject.redirect_to = redirectTo;
+						}
+
+						const submit = formElement.querySelector('[type=submit]');
+						const oldText = submit.textContent;
+
+						window.jvbForm.showFormStatus(config.id, 'uploading');
+
+						submit.disabled = true;
+						submit.textContent = 'Loading...';
+
+						window.auth.fetch(`${jvbSettings.api}auth/<?= $action ?>`, {
+							method: 'POST',
+							body: JSON.stringify(formObject)
+						})
+						.then(response => response.json().then(result => ({ response, result })))
+						.then(({ response, result }) => {
+							if (!response.ok) {
+								window.jvbForm.showFormStatus(config.id, 'error');
+								window.jvbForm.handleFormError(formElement, result);
+								return;
+							}
+
+							window.jvbForm.showFormStatus(config.id, 'submitted');
+
+							if (result.message) {
+								window.jvbForm.handleFormSuccess(formElement, result);
+							}
+
+							if (window.auth?.handleLogin && result.auth) {
+								return window.auth.handleLogin(result.auth).then(() => {
+									if (result.redirect) {
+										setTimeout(() => {
+											window.location.href = result.redirect;
+										}, 100);
+									}
+								});
+							} else if (result.redirect) {
+								setTimeout(() => {
+									window.location.href = result.redirect;
+								}, 100);
+							}
+						})
+						.catch(error => {
+							console.error('Form submission error:', error);
+							window.jvbForm.showFormStatus(config.id, 'error');
+							window.jvbForm.handleFormError(formElement, {
+								message: 'Network error. Please check your connection and try again.',
+								code: 'network_error'
+							});
+						})
+						.finally(() => {
+							submit.textContent = oldText;
+							submit.disabled = false;
+						});
 					}
-
-					// Handle success
-					window.LoginController.showFormStatus(formId, 'submitted');
-
-					// Show success message briefly before redirect
-					if (result.message) {
-						window.LoginController.handleFormSuccess(form, result);
-					}
-
-					// Handle redirect
-					if (result.redirect) {
-						setTimeout(() => {
-							window.location.href = result.redirect;
-						}, 500); // Brief delay to show success message
-					}
-
-				} catch (error) {
-					console.error('Form submission error:', error);
-					window.LoginController.showFormStatus(formId, 'error');
-					window.LoginController.handleFormError(form, {
-						message: 'Network error. Please check your connection and try again.',
-						code: 'network_error'
-					});
-				} finally {
-					submit.textContent = oldText;
-					submit.disabled = false;
-				}
+				});
 			}
-
 		});
+	});
 
-
-
-		<?php
+	<?php
 		$script = ob_get_clean();
-
 		wp_add_inline_script('jvb-form', $script);
 	}
 
@@ -962,6 +957,11 @@
 		wp_safe_redirect($login_url);
 		exit;
 	}
+
+	public function saveRegistrationFields(int $user_id, array $userdata):void
+	{
+
+	}
 }
 
 // Initialize the login manager

--
Gitblit v1.10.0