upskill-event-manager/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-registration.php
bengizmo 37f7b426b6 feat: Implement auto page creation & fix login E2E tests
Implements automatic creation of required plugin pages (Community Login,
Trainer Registration, Trainer Dashboard) upon plugin activation. This
addresses E2E test failures caused by missing pages in the test
environment.

- Adds activation hook in `hvac-community-events.php` to call
  `hvac_ce_create_required_pages`.
- The callback function checks for existing pages by slug and creates
  them using `wp_insert_post` if missing. Includes debug logging.

Also fixes issues identified during E2E test debugging:
- Corrects fatal error in `includes/community/class-login-handler.php`
  by replacing undefined constant `HVAC_COMMUNITY_EVENTS_PATH` with
  `HVAC_CE_PLUGIN_DIR`.
- Updates `tests/e2e/tests/login.spec.ts` to use the correct selector
  `#wp-submit` for the login form submit button instead of
  `button[type="submit"]`.

Documentation updates:
- Adds `docs/automatic-page-creation-plan.md`.
- Updates `README.md` regarding automatic page creation.
- Updates Memory Bank files (`decisionLog.md`, `progress.md`,
  `activeContext.md`).

Note: Activation hook logging did not appear during WP-CLI activation,
requiring further investigation if page creation issues persist. E2E
test confirmation pending.
2025-03-28 17:18:21 -03:00

409 lines
No EOL
16 KiB
PHP

<?php
/**
* Handles the HVAC trainer registration functionality
*/
if (!defined('ABSPATH')) {
exit;
}
class HVAC_Registration {
/**
* Constructor
*/
public function __construct() {
// Register shortcode for registration form
add_shortcode('hvac_trainer_registration', array($this, 'registration_form'));
// Handle form submission
add_action('init', array($this, 'process_registration'));
// Enqueue styles
add_action('wp_enqueue_scripts', array($this, 'enqueue_styles'));
}
/**
* Registration form shortcode
*/
public function registration_form() {
ob_start();
// Display validation errors if they exist
if ($errors = get_transient('hvac_registration_errors')) {
echo '<div class="hvac-errors">';
foreach ($errors as $error) {
echo '<p class="error">'.$error.'</p>';
}
echo '</div>';
delete_transient('hvac_registration_errors');
}
// Form HTML will be generated here
?>
<div class="hvac-registration-form">
<h2>HVAC Trainer Registration</h2>
<form method="post" action="">
<?php wp_nonce_field('hvac_trainer_registration', 'hvac_registration_nonce'); ?>
<!-- Personal Information Section -->
<div class="form-section">
<h3>Personal Information</h3>
<div class="form-row">
<label for="first_name">First Name *</label>
<input type="text" name="first_name" id="first_name" required>
</div>
<div class="form-row">
<label for="last_name">Last Name *</label>
<input type="text" name="last_name" id="last_name" required>
</div>
<!-- Additional fields will be added here -->
</div>
<!-- Business Information Section -->
<div class="form-section">
<h3>Business Information</h3>
<div class="form-row">
<label for="business_name">Business Name *</label>
<input type="text" name="business_name" id="business_name" required>
</div>
<div class="form-row">
<label for="business_phone">Business Phone *</label>
<input type="tel" name="business_phone" id="business_phone" required>
</div>
<div class="form-row">
<label for="business_email">Business Email *</label>
<input type="email" name="business_email" id="business_email" required>
</div>
<div class="form-row">
<label for="business_website">Business Website (optional)</label>
<input type="url" name="business_website" id="business_website">
</div>
</div>
<!-- Address Information Section -->
<div class="form-section">
<h3>Address Information</h3>
<div class="form-row">
<label for="user_country">Country *</label>
<select name="user_country" id="user_country" required>
<option value="">Select Country</option>
<option value="United States">United States</option>
<option value="Canada">Canada</option>
<option value="">---</option>
<?php
// Additional countries would be loaded here
?>
</select>
</div>
<div class="form-row">
<label for="user_state">State/Province *</label>
<select name="user_state" id="user_state" required>
<option value="Other">Other</option>
<!-- US states and Canadian provinces would be loaded here -->
</select>
<input type="text" name="user_state_other" id="user_state_other"
style="display:none; margin-top: 0.5rem;"
placeholder="Enter your state/province">
</div>
<div class="form-row">
<label for="user_city">City *</label>
<input type="text" name="user_city" id="user_city" required>
</div>
<div class="form-row">
<label for="user_zip">Zip/Postal Code *</label>
<input type="text" name="user_zip" id="user_zip" required>
</div>
</div>
<!-- Training Information Section -->
<div class="form-section">
<h3>Training Information</h3>
<div class="form-row">
<label>Business Type *</label>
<div class="checkbox-group">
<label><input type="radio" name="business_type" value="Manufacturer" required> Manufacturer</label>
<label><input type="radio" name="business_type" value="Distributor"> Distributor</label>
<label><input type="radio" name="business_type" value="Contractor"> Contractor</label>
<label><input type="radio" name="business_type" value="Consultant"> Consultant</label>
<label><input type="radio" name="business_type" value="Educator"> Educator</label>
<label><input type="radio" name="business_type" value="Government"> Government</label>
<label><input type="radio" name="business_type" value="Other"> Other</label>
</div>
</div>
<div class="form-row">
<label>Training Audience *</label>
<div class="checkbox-group">
<label><input type="checkbox" name="training_audience[]" value="Anyone"> Anyone (open to the public)</label>
<label><input type="checkbox" name="training_audience[]" value="Industry professionals"> Industry professionals</label>
<label><input type="checkbox" name="training_audience[]" value="Internal staff"> Internal staff in my company</label>
<label><input type="checkbox" name="training_audience[]" value="Registered students"> Registered students/members</label>
</div>
</div>
<!-- Additional training fields would go here -->
</div>
<div class="form-submit">
<input type="submit" name="hvac_register" value="Register">
</div>
</form>
</div>
<?php
return ob_get_clean();
}
/**
* Enqueue styles for the registration form
*/
public function enqueue_styles() {
wp_enqueue_style(
'hvac-registration-style',
HVAC_CE_PLUGIN_URL . 'assets/css/hvac-registration.css',
array(),
HVAC_CE_VERSION
);
wp_enqueue_script(
'hvac-registration-js',
HVAC_CE_PLUGIN_URL . 'assets/js/hvac-registration.js',
array('jquery'),
HVAC_CE_VERSION,
true
);
}
/**
* Process registration form submission
*/
public function process_registration() {
if (!isset($_POST['hvac_registration_nonce']) ||
!wp_verify_nonce($_POST['hvac_registration_nonce'], 'hvac_trainer_registration')) {
return;
}
// Validate and process form data
if (isset($_POST['hvac_register'])) {
$errors = $this->validate_registration($_POST);
if (empty($errors)) {
// Process valid form submission
$user_id = $this->create_trainer_account($_POST);
if ($user_id && !is_wp_error($user_id)) {
$this->send_registration_notification($user_id, $_POST);
wp_safe_redirect(home_url('/registration-success/'));
exit;
}
} else {
// Store errors to display to user
set_transient('hvac_registration_errors', $errors, 60);
wp_safe_redirect(wp_get_referer());
exit;
}
}
}
/**
* Validate registration form data
*/
/**
* Create HVAC trainer account
*/
private function create_trainer_account($data) {
// Generate username from email
$username = sanitize_user(current(explode('@', $data['business_email'])), true);
$counter = 1;
$original_username = $username;
// Ensure username is unique
while (username_exists($username)) {
$username = $original_username . $counter++;
}
// Create user
$user_id = wp_create_user(
$username,
$data['user_pass'],
$data['business_email']
);
if (is_wp_error($user_id)) {
return false;
}
// Set basic user info
wp_update_user([
'ID' => $user_id,
'first_name' => sanitize_text_field($data['first_name']),
'last_name' => sanitize_text_field($data['last_name']),
'display_name' => sanitize_text_field($data['first_name'] . ' ' . $data['last_name']),
'role' => 'hvac_trainer'
]);
// Save custom fields
update_user_meta($user_id, 'business_name', sanitize_text_field($data['business_name']));
update_user_meta($user_id, 'business_phone', sanitize_text_field($data['business_phone']));
update_user_meta($user_id, 'business_website', esc_url_raw($data['business_website']));
update_user_meta($user_id, 'user_country', sanitize_text_field($data['user_country']));
update_user_meta($user_id, 'user_state', sanitize_text_field($data['user_state']));
update_user_meta($user_id, 'user_city', sanitize_text_field($data['user_city']));
update_user_meta($user_id, 'user_zip', sanitize_text_field($data['user_zip']));
update_user_meta($user_id, 'business_type', sanitize_text_field($data['business_type']));
update_user_meta($user_id, 'training_audience', array_map('sanitize_text_field', $data['training_audience']));
// Create Events Calendar organizer profile
$this->create_organizer_profile($user_id, $data);
// Create venue if requested
if (isset($data['create_venue']) && $data['create_venue'] === 'Yes') {
$this->create_training_venue($user_id, $data);
}
// TODO: Send admin notification email
// TODO: Send welcome email to user
return true;
}
/**
* Create a training venue in The Events Calendar
*/
/**
* Create organizer profile in The Events Calendar
*/
private function create_organizer_profile($user_id, $data) {
if (!function_exists('tribe_create_organizer')) {
return false;
}
$organizer_data = array(
'Organizer' => sanitize_text_field($data['business_name']),
'Phone' => sanitize_text_field($data['business_phone']),
'Email' => sanitize_email($data['business_email']),
'Website' => esc_url_raw($data['business_website']),
);
$organizer_id = tribe_create_organizer($organizer_data);
if ($organizer_id) {
// Associate organizer with user
update_user_meta($user_id, '_hvac_organizer_id', $organizer_id);
return true;
}
return false;
}
private function create_training_venue($user_id, $data) {
if (!function_exists('tribe_create_venue')) {
return false;
}
$venue_data = array(
'Venue' => sanitize_text_field($data['business_name']),
'Address' => sanitize_text_field($data['user_city']),
'City' => sanitize_text_field($data['user_city']),
'State' => sanitize_text_field($data['user_state']),
'Zip' => sanitize_text_field($data['user_zip']),
'Country' => sanitize_text_field($data['user_country']),
'ShowMap' => true,
'ShowMapLink' => true
);
$venue_id = tribe_create_venue($venue_data);
if ($venue_id) {
// Associate venue with user
update_user_meta($user_id, '_hvac_training_venue_id', $venue_id);
return true;
}
return false;
}
/**
* Send admin notification about new trainer registration
*/
private function send_registration_notification($user_id, $data) {
$options = get_option('hvac_ce_options');
$emails = isset($options['notification_emails']) ?
array_map('trim', explode(',', $options['notification_emails'])) :
array(get_option('admin_email'));
if (empty($emails)) {
return false;
}
$user = get_userdata($user_id);
$subject = sprintf(__('New HVAC Trainer Registration: %s', 'hvac-ce'), $user->display_name);
$message = __('A new HVAC trainer has registered:', 'hvac-ce') . "\n\n";
$message .= __('Name:', 'hvac-ce') . ' ' . $user->first_name . ' ' . $user->last_name . "\n";
$message .= __('Email:', 'hvac-ce') . ' ' . $user->user_email . "\n";
$message .= __('Business:', 'hvac-ce') . ' ' . get_user_meta($user_id, 'business_name', true) . "\n";
$message .= __('Phone:', 'hvac-ce') . ' ' . get_user_meta($user_id, 'business_phone', true) . "\n";
$message .= __('Location:', 'hvac-ce') . ' ' .
get_user_meta($user_id, 'user_city', true) . ', ' .
get_user_meta($user_id, 'user_state', true) . "\n\n";
$message .= __('Business Type:', 'hvac-ce') . ' ' . get_user_meta($user_id, 'business_type', true) . "\n";
$message .= __('Training Audience:', 'hvac-ce') . ' ' .
implode(', ', get_user_meta($user_id, 'training_audience', true)) . "\n\n";
$message .= __('View profile:', 'hvac-ce') . ' ' .
admin_url('user-edit.php?user_id=' . $user_id);
foreach ($emails as $email) {
if (is_email($email)) {
wp_mail($email, $subject, $message);
}
}
return true;
}
public function validate_registration($data) { // Changed visibility to public
$errors = array();
// Required field validation
$required = array(
'first_name', 'last_name', 'business_name',
'business_phone', 'business_email', 'user_country',
'user_state', 'user_city', 'user_zip', 'business_type'
);
foreach ($required as $field) {
if (empty($data[$field])) {
$errors[$field] = 'This field is required';
}
}
// Email validation
if (!is_email($data['business_email'])) {
$errors['business_email'] = 'Please enter a valid email address';
}
// Password validation
if (empty($data['user_pass']) || strlen($data['user_pass']) < 8 ||
!preg_match('/[A-Z]/', $data['user_pass']) ||
!preg_match('/[a-z]/', $data['user_pass']) ||
!preg_match('/[0-9]/', $data['user_pass'])) {
$errors['user_pass'] = 'Password must be at least 8 characters with uppercase, lowercase and numbers';
}
// URL validation
if (!empty($data['business_website']) && !filter_var($data['business_website'], FILTER_VALIDATE_URL)) {
$errors['business_website'] = 'Please enter a valid website URL';
}
return $errors;
}
}