From 474109a5df0a06f5343ab184838fe2d80e3872a8 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 11 Jan 2026 19:23:20 +0000
Subject: [PATCH] =Fixed timeline CRUD.js issue where this.activeItem was set null when we still needed it

---
 inc/managers/LoginManager.php |  255 +++++++++++++++++++++++---------------------------
 1 files changed, 119 insertions(+), 136 deletions(-)

diff --git a/inc/managers/LoginManager.php b/inc/managers/LoginManager.php
index 7ded3ba..8b632ca 100644
--- a/inc/managers/LoginManager.php
+++ b/inc/managers/LoginManager.php
@@ -17,10 +17,7 @@
 class LoginManager
 {
 	protected Features $siteFeatures;
-	protected ?MagicLinkManager $magicLink = null;
 	protected ?MetaForm $metaForm = null;
-	protected EmailManager $emailManager;
-	protected AjaxRateLimiter $rateLimiter;
 	protected CacheManager $cache;
 
 
@@ -44,8 +41,7 @@
 	public function __construct()
 	{
 		$this->siteFeatures = Features::forSite();
-		$this->emailManager = new EmailManager();
-		$this->rateLimiter = new AjaxRateLimiter();
+
 
 		$this->cache = CacheManager::for('login');
 
@@ -67,10 +63,19 @@
 		// Login success handling
 		add_action('wp_login', [$this, 'handleSuccessfulLogin'], 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 +95,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
@@ -287,6 +292,34 @@
 			}
 		}
 	}
+	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
+	$logout_url = wp_nonce_url($logout_url, 'log-out');
+
+	return $logout_url;
+}
 	public function getLoginPage():int|false
 	{
 		return (int)get_option(BASE.'login_page');
@@ -308,7 +341,6 @@
 		if (!Features::forSite()->has('magicLink')) {
 			return;
 		}
-		$this->magicLink = new MagicLinkManager();
 	}
 
 	/*********************************************************************
@@ -597,7 +629,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>';
@@ -664,10 +697,7 @@
 	/*************************************************************************
  	*	SECURITY & VALIDATION
 	*************************************************************************/
-	protected function checkAjaxRateLimit(string $action): bool
-	{
-		return $this->rateLimiter->checkLimit($action);
-	}
+
 	protected function checkRequestId(): bool
 	{
 		$request_id = $_POST['request_id'] ?? '';
@@ -815,7 +845,7 @@
 
 	protected function maybeMagicLink(): void
 	{
-		if (!$this->magicLink || !in_array($this->action, ['login', 'lostpassword'])) {
+		if (!JVB()->magicLink() || !in_array($this->action, ['login', 'lostpassword'])) {
 			return;
 		}
 		?>
@@ -841,154 +871,102 @@
 		$action = $this->getAction();
 		ob_start();
 		?>
-		<script type="text/javascript">
-		window.checkedEmails = new Set();
-		document.addEventListener('DOMContentLoaded', () => {
-			const form = document.querySelector('.login form');
-			if (!form) return;
 
-			if (!window.jvbForm) {
-				console.error('jvbForm not loaded');
-				return;
-			}
+document.addEventListener('DOMContentLoaded', async function () {
+		window.auth.subscribe(event => {
+			if (event === 'auth-loaded') {
+				const form = document.querySelector('.login form');
+				if (!form) return;
 
-			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);
-				} else if (event === 'field-validated' && data.name === 'user_email') {
-					if (!window.checkedEmails.has(data.value)){
-						checkEmail(data.value, data);
-					}
+				if (!window.jvbForm) {
+					console.error('jvbForm not loaded');
+					return;
 				}
-			});
+
+				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);
+					}
+				});
 
 
-			async function handleFormSubmission(data) {
+				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;
-				// Show uploading status
+
+
 				window.LoginController.showFormStatus(formId, 'uploading');
 
 				try {
 					submit.disabled = true;
 					submit.textContent = 'Loading...';
-					const response = await fetch(`${jvbSettings.api}<?=($action === 'magic') ? $action : 'auth/'.$action?>`, {
+					const response = await window.auth.fetch(`${jvbSettings.api}auth/<?php echo $action; ?>`, {
 						method: 'POST',
-						headers: {
-							'Content-Type': 'application/json',
-							'X-WP-Nonce': jvbSettings.nonce
-						},
-						body: JSON.stringify(formData)
+						body: JSON.stringify(realFormData)
 					});
 
-					const result = await response.json();
+						const result = await response.json();
 
-					// Handle errors
-					if (!response.ok) {
+						// Handle errors
+						if (!response.ok) {
+							window.LoginController.showFormStatus(formId, 'error');
+							window.LoginController.handleFormError(form, result);
+							return;
+						}
+
+						// Handle success
+						window.LoginController.showFormStatus(formId, 'submitted');
+
+						// Show success message briefly before redirect
+						if (result.message) {
+							window.LoginController.handleFormSuccess(form, result);
+						}
+
+						if (window.auth && typeof window.auth.handleLogin === 'function' && Object.hasOwn(result, 'auth')) {
+							console.log('Awaiting Auth...');
+							await window.auth.handleLogin(result.auth); // Pass the full result
+						}
+
+						// Handle redirect
+						if (result.redirect) {
+							setTimeout(() => {
+								window.location.href = result.redirect;
+							}, 100); // Brief delay to show success message
+						}
+
+					} catch (error) {
+						console.error('Form submission error:', error);
 						window.LoginController.showFormStatus(formId, 'error');
-						window.LoginController.handleFormError(form, result);
-						return;
+						window.LoginController.handleFormError(form, {
+							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;
-				}
-			}
-			async function checkEmail(email, input) {
-				window.checkedEmails.add(email);
-				let wrapper = input.closest('.field');
-				let submit = input.closest('form').querySelector('[type=submit]');
-				try {
-					submit.disabled = true;
-					window.LoginController.showSuccess(wrapper, 'Checking our records...');
-					const response = await fetch(`${jvbSettings.api}auth/email`, {
-						method: 'POST',
-						headers: {
-							'Content-Type': 'application/json',
-							'X-WP-Nonce': jvbSettings.nonce
-						},
-						body: JSON.stringify({ email: email })
-					});
-
-					const result = await response.json();
-
-					if (!response.ok) {
-						return; // On error, allow to proceed (fail open)
-					}
-
-					if (result.exists) {
-						<?php
-						switch ($action) {
-							case 'register':
-								echo 'window.LoginController.showError(wrapper,\'This email is already registered. Log in instead?\');';
-								break;
-							case 'login':
-							case 'lostpassword':
-							case 'magic':
-								echo 'window.LoginController.showSuccess(wrapper,\'Email exists in our system.\');';
-								break;
-						}
-						?>
-					} else {
-						<?php
-						switch ($action) {
-							case 'register':
-								echo 'window.LoginController.showSuccess(wrapper,\'Email is available!\');';
-								break;
-							case 'login':
-							case 'lostpassword':
-							case 'magic':
-								echo 'window.LoginController.showError(wrapper,\'This email doesn\\\'t seem to exist in our system. Create account instead?\');';
-								break;
-						}
-						?>
-					}
-
-					return true; // Email is available
-				} catch (error) {
-					console.error('Email check failed:', error);
-					return true; // On network error, allow to proceed
-				}finally {
-					submit.disabled = false;
 				}
 			}
 		});
 
+});
 
-		</script>
+
+
 		<?php
 		$script = ob_get_clean();
 
@@ -1022,6 +1000,11 @@
 		wp_safe_redirect($login_url);
 		exit;
 	}
+
+	public function saveRegistrationFields(int $user_id, array $userdata):void
+	{
+
+	}
 }
 
 // Initialize the login manager

--
Gitblit v1.10.0