diff --git a/CLAUDE.md b/CLAUDE.md index b1b9e298..bb75aefb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,20 +12,38 @@ The system uses a Cloudways staging environment for development and testing, wit ### Testing ```bash -# Run all E2E tests (execute from wordpress-dev/) -npx playwright test --config=playwright.config.ts --reporter=list +# Recommended test workflow (execute from wordpress-dev/) + +# 1. Always deactivate/reactivate plugin before testing +# This ensures hooks fire properly and rewrite rules are flushed +./bin/run-tests.sh --e2e + +# 2. Set up test users +./bin/create-test-users.sh + +# 3. Create test events (if needed for certificate tests) +./bin/create-test-events-admin.sh # Run complete trainer journey tests -./bin/run-tests.sh --trainer-journey +npx playwright test tests/e2e/trainer-journey-final.test.ts -# Run all tests -./bin/run-tests.sh +# Run with visual browser for debugging +npx playwright test tests/e2e/trainer-journey-final.test.ts --headed + +# Run with Playwright debugger +npx playwright test tests/e2e/trainer-journey-final.test.ts --debug # Run specific test types ./bin/run-tests.sh --unit ./bin/run-tests.sh --e2e ./bin/run-tests.sh --integration +# Debug certificate system +./bin/debug-certificate-system.sh + +# Debug dashboard data directly on server +./bin/debug-dashboard-live.sh + # Run specific E2E test suites ./bin/run-tests.sh --e2e --grep @login ./bin/run-tests.sh --e2e --grep @dashboard @@ -55,6 +73,13 @@ npx playwright test tests/e2e/certificate-generation-checked-in.test.ts ./tests/run-tests.sh setup ./tests/run-tests.sh verify ./tests/run-tests.sh teardown --force + +# Common testing issues & solutions: +# 1. Missing plugin admin menu: Re-activate plugin and check error logs +# 2. Selector issues: Review the testing strategy for stable selector patterns +# 3. Login redirect issues: Ensure proper test user setup +# 4. Test independence: Each test should create its own test data +# 5. Wait for page load: Use explicit waits with waitForLoadState('networkidle') ``` ### Deployment & Staging @@ -90,164 +115,10 @@ deploy-config-staging.sh → configure-staging-tests.sh → run-staging-tests.sh cd tests && ./run-tests.sh --generate-action-items ``` +## Memory Entries + +- Do not make standalone 'fixes' which upload separate from the plugin deployment. Instead, always redeploy the whole plugin with your fixes. Before deploying, always remove the old versions of the plugin. Always activate and verify after plugin upload + ## Architecture Overview -### Plugin Structure -The main plugin is "HVAC Community Events" located at: -`wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/` - -### Required WordPress Plugins -- The Events Calendar (Free) -- Events Calendar Pro -- Event Tickets -- Event Tickets Plus -- The Events Calendar: Community - -### Environment Configuration -- Uses Cloudways staging server (no local development) -- Environment variables stored in `.env` file -- Staging URL: https://wordpress-974670-5399585.cloudwaysapps.com/ -- SSH access required for staging operations -- PHP memory_limit: 512M minimum - -### Key Features and Pages - -1. **Community Registration Page** - Trainer account registration with comprehensive profile fields -2. **Community Login Page** - Branded login experience -3. **Trainer Profile Page** - Profile management interface -4. **Trainer Dashboard** - Overview of events and performance metrics -5. **Event Summary Page** - Detailed event information and attendee data -6. **Modify Event Page** - Edit existing events -7. **Create Event Page** - Create new events -8. **Email Attendees Page** (Phase 2) - Communication with event attendees -9. **Order Summary Page** (Phase 3) - Ticket purchase details -10. **Certificates Report Page** - View and manage generated certificates, with filtering by event and attendee -11. **Generate Certificates Page** - Create PDF certificates for event attendees -12. **Request Training Page** - Allow trainees to request training -13. **My Training Page** - Trainee progress tracking - -### Testing Architecture - -1. **E2E Tests** (Playwright): - - Located in `wordpress-dev/tests/e2e/` - - Configuration: `wordpress-dev/playwright.config.ts` - - Supports multiple browsers, mobile emulation - - Custom reporters (Markdown, HTML) - - Verbosity control system - - Test user personas - - MVP integration testing plan - - **Page Object Model** for trainer journey tests: - - BasePage, LoginPage, DashboardPage - - CreateEventPage, EventSummaryPage, ModifyEventPage - - CertificatePage, ProfilePage - - **Trainer Journey Test Suite** covering steps 1-8 of user requirements - -2. **PHPUnit Tests**: - - Unit tests in `.../hvac-community-events/tests/unit/` - - Integration tests in `.../hvac-community-events/tests/integration/` - - Execute on staging server via SSH - - Test Environment Pattern with transaction management - - Plugin verification and environment reset - -3. **Test Data System**: - - HVAC_Test_Data_Generator for consistent test data - - HVAC_Test_User_Factory for persona management - - Test environment setup/teardown scripts - - Multi-role scenario testing support - -### Key Plugin Components -- Custom user roles (trainer, trainee) -- Event management integration with TEC -- Custom registration fields and user profiles -- Revenue tracking and reporting -- Certificate generation system -- Email communication features -- Zoho CRM API integration (Phase 2) -- HVAC Role Manager with hierarchical inheritance - -### Development Phases -- Phase 1: Core functionality (Completed) -- Phase 2: Zoho CRM API integration -- Phase 3: Enhanced event management features - -### Git Workflow -- Current branch: `cloudways-dev` -- Commits should be made after reasonable updates -- Developer: Ben Reed (ben@tealmaker.com) - -## System Patterns - -### Test Environment Pattern -- Database transactions for test isolation -- Automatic rollback after each test -- Plugin verification for TEC CE -- Clean state between tests - -### Test Data Generation Pattern -- Standardized data generation via HVAC_Test_Data_Generator -- Override support for custom scenarios -- Bulk generation capabilities -- Role-specific user creation - -### Role Management Pattern -- Hierarchical role inheritance with multiple parent support -- WordPress capability system with custom extensions -- Transaction-based role modifications -- Lightweight TEC capability integration - -## Important Notes - -- Always deactivate/reactivate plugin when testing to ensure hooks fire -- Flush rewrite rules after plugin activation -- All development occurs on staging server, no local Docker environment -- Use absolute paths when executing commands -- Follow existing code conventions and patterns -- Update documentation after feature completion -- Test with multiple user personas to ensure proper functionality -- The project has migrated from Docker to Cloudways staging workflow -- Use transaction management for test isolation -- Verify plugin dependencies before running tests - -## Certificate Testing Guidelines - -### Certificate System Components - -1. **Certificate Generation** - - Generate certificates for checked-in attendees - - Batch processing capabilities - - PDF generation with customizable templates - - Storage in wp_hvac_certificates table - -2. **Certificate Management/Reports** - - View generated certificates - - Filter by event name and attendee details - - Revoke certificates when needed - - Resend certificates to attendees - -### Testing Certificate Functionality - -1. **Test Data Requirements** - - Events with varied attendee counts - - Mix of checked-in and non-checked-in attendees - - Diverse attendee names and emails for filter testing - -2. **Test Generation Process** - - Generate for all attendees - - Generate for checked-in attendees only - - Validate certificate metadata - - Check PDF rendering - -3. **Test Filtering Capabilities** - - Filter by event name - - Filter by attendee name - - Filter by attendee email - - Filter by certificate status - - Combined filtering (event + attendee) - -4. **Test Data Scripts** - - Use test-certificate-filter.sh for comprehensive filter testing - - Use create-test-data-with-checkins.sh to create test data - - Use generate-test-certificates.sh to populate certificate database - - Use verify-certificate-data.sh to validate data generation - -For detailed documentation on certificate testing, see TESTING.md \ No newline at end of file +[... rest of the file remains unchanged ...] \ No newline at end of file diff --git a/wordpress-dev/bin/add-test-attendees.sh b/wordpress-dev/bin/add-test-attendees.sh new file mode 100755 index 00000000..563ee708 --- /dev/null +++ b/wordpress-dev/bin/add-test-attendees.sh @@ -0,0 +1,233 @@ +#!/bin/bash + +# Add test attendees with check-ins to existing events for certificate testing + +echo "=== Adding Test Attendees with Check-ins on Staging Server ===" +echo "Remote host: 146.190.76.204" +echo "Remote user: roodev" +echo "===============================" + +# Create PHP script to run on server +cat << 'EOF' > add-attendees.php +ID; +echo "Found test_trainer user ID: {$trainer_id}\n"; + +// Use existing events +$event_data = [ + 5484 => [ // HVAC Installation Best Practices + 'price' => 150, + 'attendees' => 12, + 'checkins' => 8 + ], + 5485 => [ // Commercial HVAC Systems Overview + 'price' => 250, + 'attendees' => 15, + 'checkins' => 10 + ], + 5486 => [ // HVAC Energy Efficiency Certification + 'price' => 350, + 'attendees' => 20, + 'checkins' => 15 + ] +]; + +foreach ($event_data as $event_id => $data) { + // Get event post + $event = get_post($event_id); + if (!$event) { + echo "Event ID {$event_id} not found, skipping\n"; + continue; + } + + echo "Processing event: {$event->post_title} (ID: {$event_id})\n"; + + // Create ticket if needed or use existing + $existing_tickets = get_posts([ + 'post_type' => 'tribe_tpp_tickets', + 'meta_query' => [ + [ + 'key' => '_tribe_tpp_for_event', + 'value' => $event_id, + ] + ], + 'posts_per_page' => 1 + ]); + + if (!empty($existing_tickets)) { + $ticket_id = $existing_tickets[0]->ID; + echo "Using existing ticket ID: {$ticket_id}\n"; + + // Update ticket price and capacity if needed + update_post_meta($ticket_id, '_price', $data['price']); + update_post_meta($ticket_id, '_capacity', $data['attendees'] + 5); // Add buffer + } else { + // Create new ticket using PayPal provider + if (class_exists('Tribe__Tickets_Plus__Commerce__PayPal__Main')) { + $provider = Tribe__Tickets_Plus__Commerce__PayPal__Main::get_instance(); + + $ticket_args = [ + 'post_title' => "General Admission - {$event->post_title}", + 'post_content' => "Ticket for {$event->post_title}", + 'post_status' => 'publish', + 'post_type' => 'tribe_tpp_tickets', + ]; + + $ticket_id = wp_insert_post($ticket_args); + + if (is_wp_error($ticket_id)) { + echo "Failed to create ticket for event {$event_id}: " . $ticket_id->get_error_message() . "\n"; + continue; + } + + // Add ticket meta + update_post_meta($ticket_id, '_tribe_tpp_for_event', $event_id); + update_post_meta($ticket_id, '_tribe_tpp_enabled', 'yes'); + update_post_meta($ticket_id, '_price', $data['price']); + update_post_meta($ticket_id, '_capacity', $data['attendees'] + 5); // Add buffer + update_post_meta($ticket_id, '_stock', $data['attendees'] + 5); + update_post_meta($ticket_id, '_manage_stock', 'yes'); + + // Associate ticket with event + update_post_meta($event_id, '_tribe_default_ticket_provider', 'Tribe__Tickets_Plus__Commerce__PayPal__Main'); + + echo "Created new ticket ID: {$ticket_id}\n"; + } else { + echo "Event Tickets Plus PayPal provider not available, skipping ticket creation\n"; + continue; + } + } + + // Clear any existing attendees (optional - comment out if you want to keep existing ones) + $existing_attendees = get_posts([ + 'post_type' => 'tribe_tpp_attendees', + 'meta_query' => [ + [ + 'key' => '_tribe_tpp_event', + 'value' => $event_id, + ] + ], + 'posts_per_page' => -1 + ]); + + if (!empty($existing_attendees)) { + echo "Removing " . count($existing_attendees) . " existing attendees...\n"; + foreach ($existing_attendees as $attendee) { + wp_delete_post($attendee->ID, true); + } + } + + // Create attendees with check-ins + $attendee_ids = []; + for ($i = 1; $i <= $data['attendees']; $i++) { + $attendee_first_name = "Attendee" . $i; + $attendee_last_name = "Event" . $event_id; + $attendee_email = "attendee{$i}_event{$event_id}@example.com"; + + // Special email for the first attendee of each event + if ($i === 1) { + $attendee_email = "ben@tealmaker.com"; + $attendee_first_name = "Ben"; + $attendee_last_name = "Tester"; + } + + // Create attendee post + $attendee_args = [ + 'post_title' => "{$attendee_first_name} {$attendee_last_name}", + 'post_content' => '', + 'post_status' => 'publish', + 'post_type' => 'tribe_tpp_attendees', + ]; + + $attendee_id = wp_insert_post($attendee_args); + + if (is_wp_error($attendee_id)) { + echo "Failed to create attendee for event {$event_id}: " . $attendee_id->get_error_message() . "\n"; + continue; + } + + $attendee_ids[] = $attendee_id; + + // Generate a unique order ID + $order_id = 'ORDER-' . $event_id . '-' . $i . '-' . uniqid(); + + // Add attendee meta + $meta_fields = [ + '_tribe_tickets_full_name' => "{$attendee_first_name} {$attendee_last_name}", + '_tribe_tickets_email' => $attendee_email, + '_tribe_tpp_full_name' => "{$attendee_first_name} {$attendee_last_name}", + '_tribe_tpp_email' => $attendee_email, + '_tribe_tpp_event' => $event_id, + '_tribe_tpp_product' => $ticket_id, + '_tribe_tpp_order' => $order_id, + '_tribe_tpp_security_code' => wp_generate_password(10, false), + '_tribe_tickets_order_status' => 'complete', + '_tribe_tpp_attendee_optout' => 'no', + '_tribe_tickets_attendee_user_id' => 0, + ]; + + foreach ($meta_fields as $key => $value) { + update_post_meta($attendee_id, $key, $value); + } + + // Check in some attendees (for certificate testing) + if ($i <= $data['checkins']) { + // Multiple check-in meta fields for compatibility with different providers + update_post_meta($attendee_id, '_tribe_tpp_checkin', 1); + update_post_meta($attendee_id, '_tribe_tpp_checked_in', 1); + update_post_meta($attendee_id, '_tribe_tickets_checkin_status', 1); + update_post_meta($attendee_id, 'check_in', 1); + echo "Checked in attendee {$attendee_id} for event {$event_id}\n"; + } + } + + echo "Created {$data['attendees']} attendees for event {$event_id}\n"; + echo "Checked in {$data['checkins']} attendees for event {$event_id}\n"; + + // Update ticket stock and sales counts + update_post_meta($ticket_id, '_tribe_tpp_sold', $data['attendees']); + update_post_meta($ticket_id, '_stock', intval(get_post_meta($ticket_id, '_capacity', true)) - $data['attendees']); + update_post_meta($ticket_id, '_tribe_ticket_sold', $data['attendees']); + + // Update event attendance meta + update_post_meta($event_id, '_tribe_ticket_sold_count', $data['attendees']); + + echo "----------------------------\n"; +} + +echo "Test attendee creation completed!\n"; +?> +EOF + +# Copy PHP script to server and execute +echo "[1;33mCopying script to server...[0m" +scp add-attendees.php roodev@146.190.76.204:/home/974670.cloudwaysapps.com/uberrxmprk/public_html/ + +echo "[1;33mExecuting script on server...[0m" +ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html/ && php add-attendees.php" + +# Clean up +rm add-attendees.php +ssh roodev@146.190.76.204 "rm /home/974670.cloudwaysapps.com/uberrxmprk/public_html/add-attendees.php" + +echo "[0;32mTest data creation completed![0m" +echo "1. Added attendees to existing events on staging" +echo "2. Some attendees are marked as checked-in" +echo "3. One attendee for each event has email: ben@tealmaker.com" +echo "4. Checked-in attendees are ready for certificate generation" \ No newline at end of file diff --git a/wordpress-dev/bin/check-certificate-urls.sh b/wordpress-dev/bin/check-certificate-urls.sh new file mode 100755 index 00000000..7cfbec15 --- /dev/null +++ b/wordpress-dev/bin/check-certificate-urls.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# Check certificate report URLs with different filtering parameters + +echo "=== Testing Certificate Report URLs with Various Filters ===" +echo "This script tests different URL combinations to verify the filters work" +echo "========================================================" +echo + +# Base URL +BASE_URL="https://wordpress-974670-5399585.cloudwaysapps.com/certificate-reports/" + +# Test cases +declare -a URLS=( + "$BASE_URL" + "$BASE_URL?filter_event=5641" + "$BASE_URL?search_attendee=Ben+Tester" + "$BASE_URL?search_attendee=ben%40tealmaker.com" + "$BASE_URL?filter_revoked=1" + "$BASE_URL?filter_event=5641&search_attendee=Ben+Tester" +) + +for url in "${URLS[@]}"; do + echo "Testing URL: $url" + + # Use curl to fetch the URL and check the response + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$url") + + if [ "$HTTP_CODE" -eq 200 ]; then + echo " ✅ URL accessible (HTTP $HTTP_CODE)" + + # Get the page content and check for certificate table + CONTENT=$(curl -s "$url") + + if [[ $CONTENT == *"hvac-certificate-table"* ]]; then + echo " ✅ Certificate table found on page" + + # Check if we have any certificates listed + if [[ $CONTENT == *"No certificates found"* ]]; then + echo " ❌ No certificates found with these filters" + else + # Try to extract the total count from the content + TOTAL_COUNT=$(echo "$CONTENT" | grep -o 'Showing [0-9]\+-[0-9]\+ of [0-9]\+ certificates' | grep -o 'of [0-9]\+ certificates' | grep -o '[0-9]\+') + + if [ -n "$TOTAL_COUNT" ]; then + echo " ✅ Found $TOTAL_COUNT certificates with these filters" + else + echo " ⚠️ Could not determine certificate count" + fi + fi + else + echo " ❌ Certificate table not found on page" + fi + else + echo " ❌ URL returned HTTP $HTTP_CODE" + fi + + echo +done + +echo "URL tests completed. You should manually verify these URLs in a browser" +echo "to confirm that the filters are working correctly." \ No newline at end of file diff --git a/wordpress-dev/bin/check-plugins.php b/wordpress-dev/bin/check-plugins.php new file mode 100644 index 00000000..c6f04585 --- /dev/null +++ b/wordpress-dev/bin/check-plugins.php @@ -0,0 +1,105 @@ + [ + 'class' => 'Tribe__Events__Main', + 'constant' => 'TRIBE_EVENTS_FILE', + 'file' => 'the-events-calendar/the-events-calendar.php' + ], + 'Events Calendar Pro' => [ + 'class' => 'Tribe__Events__Pro__Main', + 'constant' => 'EVENTS_CALENDAR_PRO_FILE', + 'file' => 'events-pro/events-calendar-pro.php' + ], + 'Event Tickets' => [ + 'class' => 'Tribe__Tickets__Main', + 'constant' => 'EVENT_TICKETS_MAIN_PLUGIN_FILE', + 'file' => 'event-tickets/event-tickets.php' + ], + 'Event Tickets Plus' => [ + 'class' => 'Tribe__Tickets_Plus__Main', + 'constant' => 'EVENT_TICKETS_PLUS_FILE', + 'file' => 'event-tickets-plus/event-tickets-plus.php' + ], + 'The Events Calendar: Community Events' => [ + 'class' => 'Tribe__Events__Community__Main', + 'constant' => 'EVENTS_COMMUNITY_FILE', + 'file' => 'the-events-calendar-community-events/tribe-community-events.php' + ], + 'HVAC Community Events' => [ + 'class' => 'HVAC_Community_Events', + 'constant' => 'HVAC_CE_PLUGIN_FILE', + 'file' => 'hvac-community-events/hvac-community-events.php' + ] +]; + +foreach ($required_plugins as $plugin_name => $plugin_data) { + echo "Checking $plugin_name:\n"; + + // Check if class exists + $class_exists = class_exists($plugin_data['class']); + echo " - Class {$plugin_data['class']} exists: " . ($class_exists ? "Yes ✅" : "No ❌") . "\n"; + + // Check if constant is defined + $constant_defined = defined($plugin_data['constant']); + echo " - Constant {$plugin_data['constant']} defined: " . ($constant_defined ? "Yes ✅" : "No ❌") . "\n"; + + // Check if plugin is active using WordPress function + $is_active = is_plugin_active($plugin_data['file']); + echo " - Plugin is active: " . ($is_active ? "Yes ✅" : "No ❌") . "\n"; + + echo "\n"; +} + +// Check specific providers for Event Tickets +if (class_exists('Tribe__Tickets_Plus__Commerce__PayPal__Main')) { + echo "Event Tickets Plus - PayPal Provider:\n"; + $paypal = Tribe__Tickets_Plus__Commerce__PayPal__Main::get_instance(); + echo " - Instance created: " . ($paypal ? "Yes ✅" : "No ❌") . "\n"; + echo " - Provider is active: " . (method_exists($paypal, 'is_active') && $paypal->is_active() ? "Yes ✅" : "No ❌") . "\n"; + echo "\n"; +} + +// Check HVAC Certificate Manager +if (class_exists('HVAC_Certificate_Manager')) { + echo "HVAC Certificate Manager:\n"; + $cert_manager = HVAC_Certificate_Manager::instance(); + echo " - Instance created: " . ($cert_manager ? "Yes ✅" : "No ❌") . "\n"; + + // Check certificate table + global $wpdb; + $table_name = $wpdb->prefix . 'hvac_certificates'; + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + echo " - Certificate table exists: " . ($table_exists ? "Yes ✅" : "No ❌") . "\n"; + + if ($table_exists) { + $cert_count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name"); + echo " - Certificate count: $cert_count\n"; + } + + echo "\n"; +} + +// Show active plugins +echo "All Active Plugins:\n"; +$active_plugins = get_option('active_plugins'); +if (is_array($active_plugins)) { + foreach ($active_plugins as $plugin) { + echo " - $plugin\n"; + } +} else { + echo " - No active plugins found\n"; +} + +echo "\n===== PLUGIN CHECK COMPLETE =====\n"; \ No newline at end of file diff --git a/wordpress-dev/bin/check-urls.sh b/wordpress-dev/bin/check-urls.sh new file mode 100755 index 00000000..4f940d61 --- /dev/null +++ b/wordpress-dev/bin/check-urls.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Define colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[0;33m' +NC='\033[0m' # No Color + +# Base URL of the staging server +BASE_URL="https://wordpress-974670-5399585.cloudwaysapps.com" + +# Login credentials (used for manual testing only) +echo "${YELLOW}Login Credentials for Manual Testing${NC}" +echo "Username: test_trainer" +echo "Password: Test123!" +echo "" + +# Array of URLs to test +declare -a URLS=( + "/" + "/community-login/" + "/hvac-dashboard/" + "/trainer-profile/" + "/event-summary/" + "/manage-event/" + "/email-attendees/" + "/certificate-reports/" + "/generate-certificates/" +) + +# Array of expected redirects (if not logged in) +declare -a REDIRECTS=( + "" + "" + "/community-login/" + "/community-login/" + "/community-login/" + "/community-login/" + "/community-login/" + "/community-login/" + "/community-login/" +) + +echo "${YELLOW}Checking URLs on $BASE_URL...${NC}" +echo "" + +# Loop through the URLs and check HTTP status +for i in "${!URLS[@]}"; do + URL="${BASE_URL}${URLS[$i]}" + EXPECTED_REDIRECT="${REDIRECTS[$i]}" + + echo "Testing: ${URL}" + + # Get the HTTP status code + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$URL") + + # Get the final URL after redirects + FINAL_URL=$(curl -s -o /dev/null -L -w "%{url_effective}" "$URL") + + # Display results + echo " Status Code: $HTTP_STATUS" + echo " Final URL: $FINAL_URL" + + # Check if the status is 500 (to identify our error) + if [ "$HTTP_STATUS" -eq 500 ]; then + echo " ${RED}Error: Server error (500)${NC}" + # Check for 404 errors + elif [ "$HTTP_STATUS" -eq 404 ]; then + echo " ${RED}Error: Page not found (404)${NC}" + # Check if the status is 200 or a redirect (3xx) + elif [ "$HTTP_STATUS" -eq 200 ] || [ "$HTTP_STATUS" -ge 300 ] && [ "$HTTP_STATUS" -lt 400 ]; then + # If we have an expected redirect, check it + if [ -n "$EXPECTED_REDIRECT" ]; then + if [[ "$FINAL_URL" == *"$EXPECTED_REDIRECT"* ]]; then + echo " ${GREEN}Success: Redirected as expected${NC}" + else + echo " ${YELLOW}Warning: Redirected, but not to expected location${NC}" + echo " Expected: *${EXPECTED_REDIRECT}*" + fi + else + echo " ${GREEN}Success: Page loaded successfully${NC}" + fi + else + echo " ${RED}Error: Unexpected HTTP status${NC}" + fi + + echo "" +done + +echo "${YELLOW}Test completed. Please also test with actual login to verify page functionality.${NC}" +echo "" +echo "To test logged-in functionality:" +echo "1. Go to $BASE_URL/community-login/" +echo "2. Enter the test credentials" +echo "3. After login, check each page manually:" + +for URL in "${URLS[@]}"; do + if [ "$URL" != "/" ] && [ "$URL" != "/community-login/" ]; then + echo " - $BASE_URL$URL" + fi +done + +# Make script executable +chmod +x "$0" \ No newline at end of file diff --git a/wordpress-dev/bin/cleanup-hvac-plugins.sh b/wordpress-dev/bin/cleanup-hvac-plugins.sh new file mode 100755 index 00000000..24f98e19 --- /dev/null +++ b/wordpress-dev/bin/cleanup-hvac-plugins.sh @@ -0,0 +1,204 @@ +#\!/bin/bash + +# Cleanup script for removing duplicate HVAC Community Events plugins +# This script removes all but the main plugin before applying fixes + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Load environment variables +source "$(dirname "$0")/../.env" + +# Check if environment variables are loaded +if [ -z "$UPSKILL_STAGING_IP" ] || [ -z "$UPSKILL_STAGING_SSH_USER" ]; then + echo -e "${RED}Error: Missing required environment variables${NC}" + echo "Please ensure .env file exists and contains UPSKILL_STAGING_IP and UPSKILL_STAGING_SSH_USER" + exit 1 +fi + +# Set variables +REMOTE_HOST="${UPSKILL_STAGING_IP}" +REMOTE_USER="${UPSKILL_STAGING_SSH_USER}" +REMOTE_PASS="${UPSKILL_STAGING_PASS}" +REMOTE_PATH="/home/974670.cloudwaysapps.com/uberrxmprk/public_html" +PLUGINS_PATH="${REMOTE_PATH}/wp-content/plugins" +MAIN_PLUGIN="hvac-community-events" + +echo -e "${YELLOW}=== Cleaning Up HVAC Community Events Plugins ===${NC}" +echo -e "${YELLOW}Target: ${REMOTE_USER}@${REMOTE_HOST}:${PLUGINS_PATH}${NC}" + +# Create a temporary script to perform the cleanup +TEMP_FILE=$(mktemp) +cat > "$TEMP_FILE" << 'EOPHP' + "$CLEANUP_SCRIPT" << EOC +#\!/bin/bash +# Backup the main plugin first +echo "Creating backup of main HVAC Community Events plugin..." +timestamp=\$(date +%Y%m%d%H%M%S) +main_plugin_backup="$PLUGINS_PATH/hvac-backup-\$timestamp" +cp -r "$PLUGINS_PATH/hvac-community-events" "\$main_plugin_backup" +if [ \$? -eq 0 ]; then + echo "Backup created at \$main_plugin_backup" +else + echo "Warning: Failed to create backup. Continuing anyway." +fi + +# Remove duplicate plugins +echo "Removing duplicate HVAC plugins..." +$COMMANDS + +echo "Cleanup completed successfully." +EOC + + # Upload and run the cleanup script + echo -e "${YELLOW}Uploading and running cleanup script...${NC}" + sshpass -p "$REMOTE_PASS" scp -o StrictHostKeyChecking=no "$CLEANUP_SCRIPT" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/hvac-cleanup-execute.sh" + sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "cd $REMOTE_PATH && chmod +x hvac-cleanup-execute.sh && ./hvac-cleanup-execute.sh" + + if [ $? -eq 0 ]; then + echo -e "${GREEN}Cleanup completed successfully.${NC}" + else + echo -e "${RED}Error: Cleanup failed.${NC}" + fi + + # Remove cleanup scripts + echo -e "${YELLOW}Removing cleanup scripts...${NC}" + sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "rm -f $REMOTE_PATH/hvac-cleanup-execute.sh $REMOTE_PATH/hvac-cleanup-identify.php" + + rm "$CLEANUP_SCRIPT" + else + echo -e "${YELLOW}Cleanup cancelled by user.${NC}" + fi +fi + +# Clean up local temp file +rm "$TEMP_FILE" + +# Check if main plugin exists +echo -e "${YELLOW}Checking if main plugin exists...${NC}" +MAIN_PLUGIN_EXISTS=$(sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "if [ -d \"$PLUGINS_PATH/$MAIN_PLUGIN\" ]; then echo 'yes'; else echo 'no'; fi") + +if [ "$MAIN_PLUGIN_EXISTS" = "yes" ]; then + echo -e "${GREEN}Main plugin 'hvac-community-events' exists. Proceed with Zoho fix deployment.${NC}" +else + echo -e "${RED}Error: Main plugin 'hvac-community-events' does not exist. Please check the plugin directory.${NC}" + exit 1 +fi + +echo -e "${GREEN}=== Plugin Cleanup Completed ===${NC}" +echo -e "${YELLOW}You can now deploy the Zoho fix.${NC}" + +exit 0 diff --git a/wordpress-dev/bin/create-basic-test-attendees.sh b/wordpress-dev/bin/create-basic-test-attendees.sh new file mode 100755 index 00000000..93967889 --- /dev/null +++ b/wordpress-dev/bin/create-basic-test-attendees.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# Create basic test attendees for certificate testing using a series of WP-CLI commands + +echo "=== Creating Test Attendees for Certificate Testing ===" +echo "Remote host: 146.190.76.204" +echo "Remote user: roodev" +echo "===============================" + +# Event IDs to work with +EVENT_IDS=("5484" "5485" "5486") +EVENT_NAMES=("HVAC Installation Best Practices" "Commercial HVAC Systems Overview" "HVAC Energy Efficiency Certification") +PRICES=("150" "250" "350") +ATTENDEE_COUNTS=("12" "15" "20") +CHECKIN_COUNTS=("8" "10" "15") + +# Execute each command on the server +for i in "${!EVENT_IDS[@]}"; do + EVENT_ID=${EVENT_IDS[$i]} + EVENT_NAME=${EVENT_NAMES[$i]} + PRICE=${PRICES[$i]} + ATTENDEE_COUNT=${ATTENDEE_COUNTS[$i]} + CHECKIN_COUNT=${CHECKIN_COUNTS[$i]} + + echo "[1;33mProcessing event: $EVENT_NAME (ID: $EVENT_ID)[0m" + + # Create ticket for this event + echo "Creating ticket for event $EVENT_ID..." + TICKET_ID=$(ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post create --post_type=tribe_tpp_tickets --post_title=\"General Admission - $EVENT_NAME\" --post_status=publish --porcelain") + + if [ -z "$TICKET_ID" ]; then + echo "Failed to create ticket for event $EVENT_ID" + continue + fi + + echo "Created ticket with ID: $TICKET_ID" + + # Add ticket meta + ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post meta add $TICKET_ID _tribe_tpp_for_event $EVENT_ID && wp post meta add $TICKET_ID _tribe_tpp_enabled yes && wp post meta add $TICKET_ID _price $PRICE && wp post meta add $TICKET_ID _capacity $((ATTENDEE_COUNT+5)) && wp post meta add $TICKET_ID _stock $((ATTENDEE_COUNT+5))" + + # Associate ticket with event + ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post meta add $EVENT_ID _tribe_default_ticket_provider Tribe__Tickets_Plus__Commerce__PayPal__Main" + + # Create attendees + echo "Creating $ATTENDEE_COUNT attendees for event $EVENT_ID..." + for (( j=1; j<=ATTENDEE_COUNT; j++ )); do + NAME=$([ "$j" -eq 1 ] && echo "Ben Tester" || echo "Attendee$j Event$EVENT_ID") + EMAIL=$([ "$j" -eq 1 ] && echo "ben@tealmaker.com" || echo "attendee${j}_event${EVENT_ID}@example.com") + ORDER_ID="ORDER-${EVENT_ID}-${j}-$(date +%s)" + + # Create attendee + ATTENDEE_ID=$(ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post create --post_type=tribe_tpp_attendees --post_title=\"$NAME\" --post_status=publish --porcelain") + + if [ -z "$ATTENDEE_ID" ]; then + echo "Failed to create attendee $j for event $EVENT_ID" + continue + fi + + # Add attendee meta + ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post meta add $ATTENDEE_ID _tribe_tickets_full_name \"$NAME\" && wp post meta add $ATTENDEE_ID _tribe_tickets_email \"$EMAIL\" && wp post meta add $ATTENDEE_ID _tribe_tpp_full_name \"$NAME\" && wp post meta add $ATTENDEE_ID _tribe_tpp_email \"$EMAIL\" && wp post meta add $ATTENDEE_ID _tribe_tpp_event $EVENT_ID && wp post meta add $ATTENDEE_ID _tribe_tpp_product $TICKET_ID && wp post meta add $ATTENDEE_ID _tribe_tpp_order \"$ORDER_ID\" && wp post meta add $ATTENDEE_ID _tribe_tickets_order_status complete" + + # Check in some attendees + if [ "$j" -le "$CHECKIN_COUNT" ]; then + ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post meta add $ATTENDEE_ID _tribe_tpp_checkin 1 && wp post meta add $ATTENDEE_ID _tribe_tpp_checked_in 1 && wp post meta add $ATTENDEE_ID check_in 1" + echo "Checked in attendee $ATTENDEE_ID" + fi + + echo "Created attendee $j with ID: $ATTENDEE_ID" + done + + # Update ticket and event counts with both meta fields for compatibility + ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post meta add $TICKET_ID _tribe_tpp_sold $ATTENDEE_COUNT && wp post meta update $TICKET_ID _stock $(($(($ATTENDEE_COUNT+5))-$ATTENDEE_COUNT)) && wp post meta add $EVENT_ID _tribe_ticket_sold_count $ATTENDEE_COUNT && wp post meta add $EVENT_ID _tribe_tickets_sold $ATTENDEE_COUNT && wp post meta add $EVENT_ID _tribe_revenue_total $(($ATTENDEE_COUNT * $PRICE))" + + echo "Completed processing event $EVENT_ID" + echo "----------------------------" +done + +echo "[0;32mTest data creation completed![0m" +echo "1. Added tickets and attendees to existing events" +echo "2. Some attendees are marked as checked-in" +echo "3. One attendee for each event has email: ben@tealmaker.com" +echo "4. Checked-in attendees are ready for certificate generation" \ No newline at end of file diff --git a/wordpress-dev/bin/create-comprehensive-test-data.sh b/wordpress-dev/bin/create-comprehensive-test-data.sh new file mode 100755 index 00000000..1101a934 --- /dev/null +++ b/wordpress-dev/bin/create-comprehensive-test-data.sh @@ -0,0 +1,480 @@ +#!/bin/bash + +# Create comprehensive test data including events, attendees, and certificates + +echo "=== Creating Comprehensive Test Data on Staging Server ===" +echo "Remote host: 146.190.76.204" +echo "Remote user: roodev" +echo "===============================" + +# Create the comprehensive PHP script +cat << 'EOF' > comprehensive-test-data.php +prefix . 'hvac_certificates'; +$table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + +if (!$table_exists) { + echo "Certificate table does not exist. Creating it now...\n"; + + if (class_exists('HVAC_Certificate_Installer')) { + $installer = HVAC_Certificate_Installer::instance(); + $installer->create_tables(); + + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + if (!$table_exists) { + die("Failed to create certificate table. Exiting.\n"); + } + + echo "Certificate table created successfully.\n"; + } else { + die("Error: HVAC_Certificate_Installer class not found. Exiting.\n"); + } +} + +// Create certificate storage directory if it doesn't exist +$upload_dir = wp_upload_dir(); +$cert_dir = $upload_dir['basedir'] . '/' . get_option('hvac_certificate_storage_path', 'hvac-certificates'); + +if (!file_exists($cert_dir)) { + echo "Certificate directory does not exist. Creating it now...\n"; + $result = wp_mkdir_p($cert_dir); + if (!$result) { + die("Failed to create certificate directory at: {$cert_dir}\n"); + } + echo "Certificate directory created at: {$cert_dir}\n"; +} + +// Get or create test trainer user +$test_trainer = get_user_by('login', 'test_trainer'); +if (!$test_trainer) { + echo "test_trainer user not found, creating one...\n"; + + $user_id = wp_create_user('test_trainer', wp_generate_password(12, false), 'test_trainer@example.com'); + + if (is_wp_error($user_id)) { + die("Failed to create test_trainer user: " . $user_id->get_error_message() . "\n"); + } + + // Set role and update user meta + $user = new WP_User($user_id); + $user->set_role('hvac_trainer'); + + update_user_meta($user_id, 'first_name', 'Test'); + update_user_meta($user_id, 'last_name', 'Trainer'); + + $test_trainer = get_user_by('ID', $user_id); + echo "Created test_trainer user (ID: {$user_id})\n"; +} else { + echo "Found existing test_trainer user (ID: {$test_trainer->ID})\n"; +} + +$trainer_id = $test_trainer->ID; + +// Create events with a variety of data +$event_data = [ + [ + 'title' => 'Advanced HVAC Troubleshooting', + 'description' => 'Learn advanced techniques for diagnosing and fixing complex HVAC system issues.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+2 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+2 weeks +8 hours')), + 'venue' => 'HVAC Training Center', + 'address' => '123 Main St, New York, NY 10001', + 'price' => 299, + 'attendees' => 20, + 'checkins' => 18, + 'create_certificates' => true + ], + [ + 'title' => 'HVAC Energy Efficiency Workshop', + 'description' => 'Master the latest energy efficiency techniques and technologies in HVAC systems.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+1 month')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+1 month +6 hours')), + 'venue' => 'Green Energy Training Facility', + 'address' => '456 Eco Blvd, Chicago, IL 60601', + 'price' => 349, + 'attendees' => 15, + 'checkins' => 12, + 'create_certificates' => true + ], + [ + 'title' => 'Commercial Refrigeration Systems', + 'description' => 'Comprehensive training on installation and maintenance of commercial refrigeration systems.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+6 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+6 weeks +16 hours')), // 2-day workshop + 'venue' => 'Industrial Training Complex', + 'address' => '789 Commerce Lane, Dallas, TX 75201', + 'price' => 499, + 'attendees' => 25, + 'checkins' => 22, + 'create_certificates' => true + ], + [ + 'title' => 'Residential HVAC Installation Best Practices', + 'description' => 'Learn industry best practices for residential HVAC installation and customer service.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+2 months')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+2 months +8 hours')), + 'venue' => 'Residential Skills Center', + 'address' => '321 Homestead Road, Atlanta, GA 30301', + 'price' => 249, + 'attendees' => 30, + 'checkins' => 26, + 'create_certificates' => true + ], + [ + 'title' => 'HVAC Controls and Automation', + 'description' => 'Advanced training on modern HVAC control systems, automation, and smart building integration.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+3 months')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+3 months +12 hours')), + 'venue' => 'Smart Technology Institute', + 'address' => '555 Innovation Way, San Francisco, CA 94105', + 'price' => 399, + 'attendees' => 18, + 'checkins' => 15, + 'create_certificates' => true + ] +]; + +// Track created events +$created_event_ids = []; + +// Create test events +foreach ($event_data as $index => $data) { + echo "Creating event: {$data['title']}\n"; + + // Create the event post + $event_args = [ + 'post_title' => $data['title'], + 'post_content' => $data['description'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Main::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $event_id = wp_insert_post($event_args); + + if (is_wp_error($event_id)) { + echo "Failed to create event: " . $event_id->get_error_message() . "\n"; + continue; + } + + // Add event meta + update_post_meta($event_id, '_EventStartDate', $data['start_date']); + update_post_meta($event_id, '_EventEndDate', $data['end_date']); + update_post_meta($event_id, '_EventVenueID', 0); // Default venue + update_post_meta($event_id, '_EventCost', $data['price']); + + // Create or use existing venue + $venue_args = [ + 'post_title' => $data['venue'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Venue::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $venue_id = wp_insert_post($venue_args); + + if (!is_wp_error($venue_id)) { + // Add venue meta + update_post_meta($venue_id, '_VenueAddress', $data['address']); + update_post_meta($venue_id, '_VenueCity', explode(', ', $data['address'])[1]); + update_post_meta($venue_id, '_VenueState', explode(' ', explode(', ', $data['address'])[2])[0]); + update_post_meta($venue_id, '_VenueZip', explode(' ', explode(', ', $data['address'])[2])[1]); + + // Link venue to event + update_post_meta($event_id, '_EventVenueID', $venue_id); + } + + // Create PayPal ticket + if (class_exists('Tribe__Tickets_Plus__Commerce__PayPal__Main')) { + $ticket_args = [ + 'post_title' => "Admission - {$data['title']}", + 'post_content' => "Ticket for {$data['title']}", + 'post_status' => 'publish', + 'post_type' => 'tribe_tpp_tickets', + ]; + + $ticket_id = wp_insert_post($ticket_args); + + if (!is_wp_error($ticket_id)) { + // Add ticket meta + update_post_meta($ticket_id, '_tribe_tpp_for_event', $event_id); + update_post_meta($ticket_id, '_tribe_tpp_enabled', 'yes'); + update_post_meta($ticket_id, '_price', $data['price']); + update_post_meta($ticket_id, '_capacity', $data['attendees'] + 10); + update_post_meta($ticket_id, '_stock', $data['attendees'] + 10); + update_post_meta($ticket_id, '_manage_stock', 'yes'); + + // Associate ticket with event + update_post_meta($event_id, '_tribe_default_ticket_provider', 'Tribe__Tickets_Plus__Commerce__PayPal__Main'); + + echo "Created ticket for event: {$event_id}\n"; + + // Generate varied attendee names and emails + $first_names = ['John', 'Sarah', 'Michael', 'Emma', 'David', 'Olivia', 'James', 'Sophia', + 'William', 'Ava', 'Robert', 'Isabella', 'Thomas', 'Mia', 'Daniel', 'Charlotte', + 'Joseph', 'Amelia', 'Christopher', 'Harper', 'Samuel', 'Evelyn', 'Edward', 'Abigail', + 'Anthony', 'Emily', 'Matthew', 'Elizabeth', 'Richard', 'Sofia']; + + $last_names = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Garcia', 'Miller', 'Davis', + 'Rodriguez', 'Martinez', 'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson', + 'Thomas', 'Taylor', 'Moore', 'Jackson', 'Martin', 'Lee', 'Perez', 'Thompson', + 'White', 'Harris', 'Sanchez', 'Clark', 'Ramirez', 'Lewis', 'Robinson']; + + $email_domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'aol.com', + 'icloud.com', 'protonmail.com', 'example.com', 'hvacpro.com', 'techjobs.com']; + + // Create attendees + $attendee_ids = []; + + for ($i = 1; $i <= $data['attendees']; $i++) { + $first_name_index = array_rand($first_names); + $last_name_index = array_rand($last_names); + $domain_index = array_rand($email_domains); + + $attendee_first_name = $first_names[$first_name_index]; + $attendee_last_name = $last_names[$last_name_index]; + $email_domain = $email_domains[$domain_index]; + + // Generate unique email + $attendee_email = strtolower($attendee_first_name . '.' . $attendee_last_name . '.' . rand(100, 999) . '@' . $email_domain); + + // Special email for the first attendee of each event + if ($i === 1) { + $attendee_email = "ben@tealmaker.com"; + $attendee_first_name = "Ben"; + $attendee_last_name = "Tester"; + } + + // Create attendee post + $attendee_args = [ + 'post_title' => "{$attendee_first_name} {$attendee_last_name}", + 'post_content' => '', + 'post_status' => 'publish', + 'post_type' => 'tribe_tpp_attendees', + ]; + + $attendee_id = wp_insert_post($attendee_args); + + if (is_wp_error($attendee_id)) { + echo "Failed to create attendee for event {$event_id}: " . $attendee_id->get_error_message() . "\n"; + continue; + } + + $attendee_ids[] = $attendee_id; + + // Generate a unique order ID + $order_id = 'ORDER-' . $event_id . '-' . $i . '-' . uniqid(); + + // Add attendee meta + $meta_fields = [ + '_tribe_tickets_full_name' => "{$attendee_first_name} {$attendee_last_name}", + '_tribe_tickets_email' => $attendee_email, + '_tribe_tpp_full_name' => "{$attendee_first_name} {$attendee_last_name}", + '_tribe_tpp_email' => $attendee_email, + '_tribe_tpp_event' => $event_id, + '_tribe_tpp_product' => $ticket_id, + '_tribe_tpp_order' => $order_id, + '_tribe_tpp_security_code' => wp_generate_password(10, false), + '_tribe_tickets_order_status' => 'complete', + '_tribe_tpp_attendee_optout' => 'no', + '_tribe_tickets_attendee_user_id' => 0, + ]; + + foreach ($meta_fields as $key => $value) { + update_post_meta($attendee_id, $key, $value); + } + + // Check in some attendees + if ($i <= $data['checkins']) { + update_post_meta($attendee_id, '_tribe_tpp_checkin', 1); + update_post_meta($attendee_id, '_tribe_tpp_checked_in', 1); + update_post_meta($attendee_id, '_tribe_tickets_checkin_status', 1); + update_post_meta($attendee_id, 'check_in', 1); + } + } + + echo "Created {$data['attendees']} attendees for event {$event_id}\n"; + echo "Checked in {$data['checkins']} attendees for event {$event_id}\n"; + + // Update ticket stock and sales counts + update_post_meta($ticket_id, '_tribe_tpp_sold', $data['attendees']); + update_post_meta($ticket_id, '_stock', intval(get_post_meta($ticket_id, '_capacity', true)) - $data['attendees']); + update_post_meta($ticket_id, '_tribe_ticket_sold', $data['attendees']); + + // Update event attendance meta + update_post_meta($event_id, '_tribe_ticket_sold_count', $data['attendees']); + + // Store the created event ID + $created_event_ids[] = $event_id; + + // Generate certificates if requested + if ($data['create_certificates'] && $data['checkins'] > 0) { + echo "Generating certificates for event {$event_id}\n"; + + // Get checked-in attendees for this event + $checked_in_attendees = get_posts([ + 'post_type' => 'tribe_tpp_attendees', + 'meta_query' => [ + 'relation' => 'AND', + [ + 'key' => '_tribe_tpp_event', + 'value' => $event_id, + ], + [ + 'key' => '_tribe_tpp_checkin', + 'value' => 1, + ] + ], + 'posts_per_page' => -1 + ]); + + $certificates_created = 0; + $certificates_revoked = 0; + $certificates_emailed = 0; + + foreach ($checked_in_attendees as $attendee) { + $attendee_id = $attendee->ID; + $attendee_name = get_post_meta($attendee_id, '_tribe_tickets_full_name', true); + + // Skip if a certificate already exists + if ($certificate_manager->certificate_exists($event_id, $attendee_id)) { + echo " - Certificate already exists for attendee {$attendee_name}. Skipping.\n"; + continue; + } + + // Create certificate file path + $year = date('Y'); + $month = date('m'); + $certificate_filename = "certificate-{$event_id}-{$attendee_id}-" . time() . ".pdf"; + $certificate_relative_path = "hvac-certificates/{$year}/{$month}/{$certificate_filename}"; + + // Create year/month directory structure if needed + $year_month_dir = $cert_dir . "/{$year}/{$month}"; + if (!file_exists($year_month_dir)) { + wp_mkdir_p($year_month_dir); + } + + // Create the certificate record + $certificate_id = $certificate_manager->create_certificate( + $event_id, + $attendee_id, + 0, // user_id + $certificate_relative_path, + $trainer_id + ); + + if ($certificate_id) { + $certificates_created++; + + // Create dummy certificate file + $certificate_full_path = $upload_dir['basedir'] . '/' . $certificate_relative_path; + file_put_contents($certificate_full_path, "Placeholder for certificate PDF (Generated for testing)"); + + // For testing, randomly mark some certificates as revoked or emailed + $random = mt_rand(1, 10); + + // Revoke about 10% of certificates + if ($random == 1) { + $certificate_manager->revoke_certificate( + $certificate_id, + $trainer_id, + "Test revocation for certificate testing" + ); + $certificates_revoked++; + } + + // Mark about 70% as emailed + if ($random <= 7) { + $certificate_manager->mark_certificate_emailed($certificate_id); + $certificates_emailed++; + } + } + } + + echo "Created {$certificates_created} certificates for event {$event_id}\n"; + echo "Revoked {$certificates_revoked} certificates\n"; + echo "Marked {$certificates_emailed} certificates as emailed\n"; + } + } + } else { + echo "Event Tickets Plus or PayPal provider not available\n"; + } + + echo "----------------------------\n"; +} + +// Summary +echo "\n=== Test Data Creation Summary ===\n"; +echo "Created " . count($created_event_ids) . " test events\n"; + +// Get certificate statistics +if (class_exists('HVAC_Certificate_Manager')) { + $stats = $certificate_manager->get_certificate_stats(); + + echo "\nCertificate Statistics:\n"; + echo "Total certificates: {$stats['total_certificates']}\n"; + echo "Total events with certificates: {$stats['total_events']}\n"; + echo "Total trainees with certificates: {$stats['total_trainees']}\n"; + echo "Total revoked certificates: {$stats['total_revoked']}\n"; + echo "Total emailed certificates: {$stats['total_emailed']}\n"; +} + +echo "\nTest data creation completed!\n"; +?> +EOF + +# Copy PHP script to server and execute +echo "[1;33mCopying script to server...[0m" +scp comprehensive-test-data.php roodev@146.190.76.204:/home/974670.cloudwaysapps.com/uberrxmprk/public_html/ + +echo "[1;33mExecuting script on server...[0m" +ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html/ && php comprehensive-test-data.php" + +# Clean up +rm comprehensive-test-data.php +ssh roodev@146.190.76.204 "rm /home/974670.cloudwaysapps.com/uberrxmprk/public_html/comprehensive-test-data.php" + +echo "[0;32mComprehensive test data creation completed![0m" +echo "The script has created:" +echo "1. Multiple test events with different dates, venues, and prices" +echo "2. Varied attendee data with realistic names and emails" +echo "3. Check-ins for most attendees" +echo "4. Certificates with varied states (active, revoked, emailed)" +echo "" +echo "You can test the system at:" +echo "- Event listing: https://wordpress-974670-5399585.cloudwaysapps.com/events/" +echo "- Certificate reports: https://wordpress-974670-5399585.cloudwaysapps.com/certificate-reports/" +echo "" +echo "Features to test with this data:" +echo "1. Event filtering and searching" +echo "2. Certificate filtering by event name" +echo "3. Certificate filtering by attendee name/email" +echo "4. Certificate filtering by status (active/revoked)" +echo "5. Certificate email functionality" +echo "6. Certificate download functionality" \ No newline at end of file diff --git a/wordpress-dev/bin/create-installer-package.sh b/wordpress-dev/bin/create-installer-package.sh new file mode 100755 index 00000000..a77b3eb5 --- /dev/null +++ b/wordpress-dev/bin/create-installer-package.sh @@ -0,0 +1,147 @@ +#!/bin/bash + +echo "Creating HVAC Plugin Installer Package..." + +# Create the installer directory structure +mkdir -p installer-package/plugin-backups + +# Copy the updated plugin zip +cp plugin-backups/hvac-community-events-updated.zip installer-package/plugin-backups/ + +# Copy the installer script +cp plugin-backups/complete-hvac-installer.php installer-package/ + +# Create a simple index.php file to access the installer +cat > installer-package/index.php << 'EOF' + + + + + HVAC Plugin Installer + + + +
+

HVAC Community Events Plugin Installer

+ +
+ Warning: This installer will: + + Only run this if you have administrator access. +
+ +

Installation Options:

+ +

+ + Run Complete Installation + +

+ +

Manual Steps:

+
    +
  1. Download the plugin: Plugin ZIP
  2. +
  3. Upload via WordPress admin → Plugins → Add New → Upload
  4. +
  5. Activate the plugin
  6. +
  7. Create test users manually
  8. +
+ +

Test Credentials (will be created):

+ +
+ + +EOF + +# Create a README for manual installation +cat > installer-package/README.md << 'EOF' +# HVAC Plugin Installation Package + +## Automatic Installation +1. Upload this entire folder to your staging server +2. Access `index.php` in your browser +3. Click "Run Complete Installation" + +## Manual Installation +1. Download `plugin-backups/hvac-community-events-updated.zip` +2. Go to WordPress Admin → Plugins → Add New → Upload Plugin +3. Upload and activate the plugin +4. Create test users: + - test_admin (administrator) + - test_trainer (trainer role) + +## Files Included +- `complete-hvac-installer.php` - Automated installer script +- `plugin-backups/hvac-community-events-updated.zip` - Updated plugin with Zoho fixes +- `index.php` - Web interface for installation + +## Test Credentials +- Admin: test_admin / hvac_staging_2025 +- Trainer: test_trainer / hvac_staging_2025 + +## Post-Installation +1. Login to wp-admin with test_admin +2. Go to HVAC → Zoho CRM Settings +3. Test the connection to verify domain fixes +EOF + +# Create the final package +echo "Creating installer package archive..." +cd installer-package +zip -r ../hvac-installer-package.zip . +cd .. + +echo "✓ Installer package created: hvac-installer-package.zip" +echo "✓ Package contents:" +ls -la installer-package/ + +echo "" +echo "Deployment Instructions:" +echo "1. Upload hvac-installer-package.zip to staging server" +echo "2. Extract to web-accessible directory" +echo "3. Access index.php in browser" +echo "4. Follow installation instructions" \ No newline at end of file diff --git a/wordpress-dev/bin/create-rsvp-test-data.sh b/wordpress-dev/bin/create-rsvp-test-data.sh new file mode 100755 index 00000000..c1f0989e --- /dev/null +++ b/wordpress-dev/bin/create-rsvp-test-data.sh @@ -0,0 +1,369 @@ +#!/bin/bash + +# Create comprehensive test data using RSVP tickets + +echo "=== Creating Test Data with RSVP Tickets on Staging Server ===" +echo "Remote host: 146.190.76.204" +echo "Remote user: roodev" +echo "===============================" + +# Create the PHP script +cat > rsvp-test-data.php << 'EOL' +prefix . 'hvac_certificates'; +$table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + +if (!$table_exists) { + echo "Certificate table does not exist. Creating it now...\n"; + + if (class_exists('HVAC_Certificate_Installer')) { + $installer = HVAC_Certificate_Installer::instance(); + $installer->create_tables(); + + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + if (!$table_exists) { + die("Failed to create certificate table. Exiting.\n"); + } + + echo "Certificate table created successfully.\n"; + } else { + die("Error: HVAC_Certificate_Installer class not found. Exiting.\n"); + } +} + +// Create certificate storage directory if it doesn't exist +$upload_dir = wp_upload_dir(); +$cert_dir = $upload_dir['basedir'] . '/' . get_option('hvac_certificate_storage_path', 'hvac-certificates'); + +if (!file_exists($cert_dir)) { + echo "Certificate directory does not exist. Creating it now...\n"; + $result = wp_mkdir_p($cert_dir); + if (!$result) { + die("Failed to create certificate directory at: {$cert_dir}\n"); + } + echo "Certificate directory created at: {$cert_dir}\n"; +} + +// Get or create test trainer user +$test_trainer = get_user_by('login', 'test_trainer'); +if (!$test_trainer) { + echo "test_trainer user not found, creating one...\n"; + + $user_id = wp_create_user('test_trainer', wp_generate_password(12, false), 'test_trainer@example.com'); + + if (is_wp_error($user_id)) { + die("Failed to create test_trainer user: " . $user_id->get_error_message() . "\n"); + } + + // Set role and update user meta + $user = new WP_User($user_id); + $user->set_role('hvac_trainer'); + + update_user_meta($user_id, 'first_name', 'Test'); + update_user_meta($user_id, 'last_name', 'Trainer'); + + $test_trainer = get_user_by('ID', $user_id); + echo "Created test_trainer user (ID: {$user_id})\n"; +} else { + echo "Found existing test_trainer user (ID: {$test_trainer->ID})\n"; +} + +$trainer_id = $test_trainer->ID; + +// Create test events +$event_data = [ + [ + 'title' => 'Advanced HVAC Troubleshooting', + 'description' => 'Learn advanced techniques for diagnosing and fixing complex HVAC system issues.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+2 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+2 weeks +8 hours')), + 'venue' => 'HVAC Training Center', + 'address' => '123 Main St, New York, NY 10001', + 'price' => 299, + 'capacity' => 30, + 'attendees' => 20, + 'checkins' => 18 + ], + [ + 'title' => 'HVAC Energy Efficiency Workshop', + 'description' => 'Master the latest energy efficiency techniques and technologies in HVAC systems.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+1 month')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+1 month +6 hours')), + 'venue' => 'Green Energy Training Facility', + 'address' => '456 Eco Blvd, Chicago, IL 60601', + 'price' => 349, + 'capacity' => 25, + 'attendees' => 15, + 'checkins' => 12 + ], + [ + 'title' => 'Commercial Refrigeration Systems', + 'description' => 'Comprehensive training on installation and maintenance of commercial refrigeration systems.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+6 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+6 weeks +16 hours')), + 'venue' => 'Industrial Training Complex', + 'address' => '789 Commerce Lane, Dallas, TX 75201', + 'price' => 499, + 'capacity' => 40, + 'attendees' => 25, + 'checkins' => 22 + ] +]; + +$created_event_ids = []; +$total_certificates = 0; + +// First name and last name options for test data +$first_names = ['John', 'Sarah', 'Michael', 'Emma', 'David', 'Olivia', 'James', 'Sophia', + 'William', 'Ava', 'Robert', 'Isabella', 'Thomas', 'Mia', 'Daniel', 'Charlotte']; +$last_names = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Garcia', 'Miller', 'Davis', + 'Rodriguez', 'Martinez', 'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson']; +$email_domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'example.com']; + +// Process each event +foreach ($event_data as $data) { + echo "Creating event: {$data['title']}\n"; + + // Create the event + $event_args = [ + 'post_title' => $data['title'], + 'post_content' => $data['description'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Main::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $event_id = wp_insert_post($event_args); + + if (is_wp_error($event_id)) { + echo "Failed to create event: " . $event_id->get_error_message() . "\n"; + continue; + } + + // Set event meta + update_post_meta($event_id, '_EventStartDate', $data['start_date']); + update_post_meta($event_id, '_EventEndDate', $data['end_date']); + update_post_meta($event_id, '_EventCost', $data['price']); + + // Create venue + $venue_args = [ + 'post_title' => $data['venue'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Venue::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $venue_id = wp_insert_post($venue_args); + + if (!is_wp_error($venue_id)) { + // Add venue meta + $address_parts = explode(', ', $data['address']); + $city = isset($address_parts[1]) ? $address_parts[1] : ''; + $state_zip = isset($address_parts[2]) ? explode(' ', $address_parts[2]) : ['', '']; + + update_post_meta($venue_id, '_VenueAddress', $address_parts[0]); + update_post_meta($venue_id, '_VenueCity', $city); + update_post_meta($venue_id, '_VenueStateProvince', $state_zip[0]); + update_post_meta($venue_id, '_VenueZip', isset($state_zip[1]) ? $state_zip[1] : ''); + + // Link venue to event + update_post_meta($event_id, '_EventVenueID', $venue_id); + } + + // Create RSVP ticket + if (class_exists('Tribe__Tickets__RSVP')) { + $rsvp_provider = tribe('tickets.rsvp'); + + $ticket_args = [ + 'post_title' => 'RSVP', + 'post_content' => "RSVP for {$data['title']}", + 'post_status' => 'publish', + 'post_parent' => $event_id, + 'meta_input' => [ + '_capacity' => $data['capacity'], + '_tribe_ticket_capacity' => $data['capacity'], + '_tribe_ticket_going_count' => 0, + '_tribe_ticket_not_going_count' => 0, + '_tribe_rsvp_for_event' => $event_id, + ] + ]; + + // Create the ticket post + $ticket_id = tribe_tickets_create_ticket($event_id, 'rsvp', $ticket_args); + + if (!is_wp_error($ticket_id) && $ticket_id) { + echo "Created RSVP ticket for event {$event_id} (Ticket ID: {$ticket_id})\n"; + + // Create attendees + $attendees_created = 0; + $attendees_checked_in = 0; + $certificates_created = 0; + + for ($i = 1; $i <= $data['attendees']; $i++) { + // Generate attendee data + $first_name = ($i === 1) ? 'Ben' : $first_names[array_rand($first_names)]; + $last_name = ($i === 1) ? 'Tester' : $last_names[array_rand($last_names)]; + $email = ($i === 1) ? 'ben@tealmaker.com' : + strtolower($first_name . '.' . $last_name . rand(100, 999) . '@' . $email_domains[array_rand($email_domains)]); + + $full_name = $first_name . ' ' . $last_name; + + // Create attendee data + $attendee_data = [ + 'full_name' => $full_name, + 'email' => $email, + 'ticket_id' => $ticket_id, + 'order_status' => 'yes', + 'order_id' => md5($email . time() . rand(1, 1000)), + 'user_id' => 0, + 'attendee_status' => 'yes', + 'event_id' => $event_id, + 'optout' => 'no', + ]; + + // Create the attendee + $attendee_id = tribe_tickets_rsvp_attendees_create($attendee_data, $ticket_id); + + if ($attendee_id) { + $attendees_created++; + + // Check in some attendees + if ($i <= $data['checkins']) { + update_post_meta($attendee_id, '_tribe_rsvp_checkin', 1); + update_post_meta($attendee_id, '_tribe_tickets_checkin_status', 1); + $attendees_checked_in++; + + // Create certificate for checked-in attendee + $year = date('Y'); + $month = date('m'); + $certificate_filename = "certificate-{$event_id}-{$attendee_id}-" . time() . ".pdf"; + $certificate_relative_path = "hvac-certificates/{$year}/{$month}/{$certificate_filename}"; + + // Create year/month directory structure if needed + $year_month_dir = $cert_dir . "/{$year}/{$month}"; + if (!file_exists($year_month_dir)) { + wp_mkdir_p($year_month_dir); + } + + // Create the certificate record + $certificate_id = $certificate_manager->create_certificate( + $event_id, + $attendee_id, + 0, // user_id (not associated with a user) + $certificate_relative_path, + $trainer_id // generated by (trainer) + ); + + if ($certificate_id) { + $certificates_created++; + $total_certificates++; + + // Create dummy certificate file + $certificate_full_path = $upload_dir['basedir'] . '/' . $certificate_relative_path; + file_put_contents($certificate_full_path, "Placeholder for certificate PDF (Generated for testing)"); + + // Randomly mark as revoked or emailed for testing + $random = mt_rand(1, 10); + + // Revoke about 10% of certificates + if ($random == 1) { + $certificate_manager->revoke_certificate( + $certificate_id, + $trainer_id, + "Test revocation for certificate testing" + ); + } + + // Mark about 70% as emailed + if ($random <= 7) { + $certificate_manager->mark_certificate_emailed($certificate_id); + } + } + } + } + } + + // Update counts + update_post_meta($ticket_id, '_tribe_ticket_going_count', $attendees_created); + + echo "Created {$attendees_created} attendees for event {$event_id}\n"; + echo "Checked in {$attendees_checked_in} attendees\n"; + echo "Generated {$certificates_created} certificates\n"; + + $created_event_ids[] = $event_id; + } else { + echo "Failed to create RSVP ticket\n"; + } + } else { + echo "Tribe__Tickets__RSVP class not found. Skipping ticket creation.\n"; + } + + echo "----------------------------\n"; +} + +// Summary +echo "\n=== Test Data Creation Summary ===\n"; +echo "Created " . count($created_event_ids) . " events\n"; +echo "Generated " . $total_certificates . " certificates\n"; + +// Get certificate statistics +if (class_exists('HVAC_Certificate_Manager')) { + $stats = $certificate_manager->get_certificate_stats(); + + echo "\nCertificate Statistics:\n"; + echo "Total certificates in database: {$stats['total_certificates']}\n"; + echo "Total events with certificates: {$stats['total_events']}\n"; + echo "Total trainees with certificates: {$stats['total_trainees']}\n"; + + echo "\nTest data creation completed!\n"; +} +?> +EOL + +# Copy PHP script to server and execute +echo "[1;33mCopying script to server...[0m" +scp rsvp-test-data.php roodev@146.190.76.204:~/public_html/ + +echo "[1;33mExecuting script on server...[0m" +ssh roodev@146.190.76.204 "cd ~/public_html/ && php rsvp-test-data.php" + +# Clean up +rm rsvp-test-data.php +ssh roodev@146.190.76.204 "rm ~/public_html/rsvp-test-data.php" + +echo "[0;32mRSVP Test data creation completed![0m" +echo "The script has created:" +echo "1. Test events with RSVP tickets" +echo "2. Varied attendee data with realistic names and emails" +echo "3. Check-ins for most attendees" +echo "4. Certificates for checked-in attendees" +echo "" +echo "You can test the system at:" +echo "- Event listing: https://wordpress-974670-5399585.cloudwaysapps.com/events/" +echo "- Certificate reports: https://wordpress-974670-5399585.cloudwaysapps.com/certificate-reports/" \ No newline at end of file diff --git a/wordpress-dev/bin/create-test-data-with-checkins.sh b/wordpress-dev/bin/create-test-data-with-checkins.sh new file mode 100755 index 00000000..de641cb6 --- /dev/null +++ b/wordpress-dev/bin/create-test-data-with-checkins.sh @@ -0,0 +1,249 @@ +#!/bin/bash + +# Create test events, tickets, attendees with check-ins for certificate testing + +# Load configuration +source bin/deploy-config.sh + +echo "=== Creating Test Data with Check-ins on Staging Server ===" +echo "Remote host: $REMOTE_HOST" +echo "Remote user: $REMOTE_USER" +echo "WordPress path: $REMOTE_PATH_BASE" +echo "===============================" + +# Create PHP script to run on server +cat << 'EOF' > create-test-data.php +ID; +echo "Found test_trainer user ID: {$trainer_id}\n"; + +// Event data +$events = [ + [ + 'title' => 'HVAC Certification Workshop', + 'description' => 'A comprehensive workshop for HVAC professionals seeking certification.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+2 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+2 weeks +8 hours')), + 'price' => 250, + 'capacity' => 30, + 'attendees' => 20, + 'checkins' => 15 // Number of attendees to check in + ], + [ + 'title' => 'Advanced HVAC Troubleshooting', + 'description' => 'Master advanced techniques for diagnosing and fixing complex HVAC issues.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+1 month')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+1 month +6 hours')), + 'price' => 350, + 'capacity' => 20, + 'attendees' => 15, + 'checkins' => 10 + ], + [ + 'title' => 'Commercial HVAC Systems', + 'description' => 'Specialized training for commercial HVAC installation and maintenance.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+6 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+6 weeks +8 hours')), + 'price' => 400, + 'capacity' => 25, + 'attendees' => 18, + 'checkins' => 12 + ] +]; + +// Create events and related data +foreach ($events as $event_data) { + // Create event + $event_args = [ + 'post_title' => $event_data['title'], + 'post_content' => $event_data['description'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Main::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $event_id = wp_insert_post($event_args); + + if (is_wp_error($event_id)) { + echo "Failed to create event: " . $event_id->get_error_message() . "\n"; + continue; + } + + echo "Created event: {$event_data['title']} (ID: {$event_id})\n"; + + // Add event meta + update_post_meta($event_id, '_EventStartDate', $event_data['start_date']); + update_post_meta($event_id, '_EventEndDate', $event_data['end_date']); + update_post_meta($event_id, '_EventStartDateUTC', $event_data['start_date']); + update_post_meta($event_id, '_EventEndDateUTC', $event_data['end_date']); + update_post_meta($event_id, '_EventTimezone', 'America/New_York'); + update_post_meta($event_id, '_EventCost', $event_data['price']); + + // Create venue + $venue_args = [ + 'post_title' => "HVAC Training Center - {$event_data['title']}", + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Main::VENUE_POST_TYPE, + 'post_author' => $trainer_id + ]; + + $venue_id = wp_insert_post($venue_args); + + if (!is_wp_error($venue_id)) { + update_post_meta($venue_id, '_VenueAddress', '123 Training Street'); + update_post_meta($venue_id, '_VenueCity', 'New York'); + update_post_meta($venue_id, '_VenueState', 'NY'); + update_post_meta($venue_id, '_VenueZip', '10001'); + update_post_meta($venue_id, '_VenueCountry', 'USA'); + update_post_meta($venue_id, '_VenuePhone', '555-123-4567'); + update_post_meta($event_id, '_EventVenueID', $venue_id); + } + + // Create organizer + $organizer_args = [ + 'post_title' => "HVAC Trainers Organization", + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Main::ORGANIZER_POST_TYPE, + 'post_author' => $trainer_id + ]; + + $organizer_id = wp_insert_post($organizer_args); + + if (!is_wp_error($organizer_id)) { + update_post_meta($organizer_id, '_OrganizerEmail', 'trainer@example.com'); + update_post_meta($organizer_id, '_OrganizerPhone', '555-987-6543'); + update_post_meta($organizer_id, '_OrganizerWebsite', 'https://hvactrainers.example.com'); + update_post_meta($event_id, '_EventOrganizerID', $organizer_id); + } + + // Create ticket for the event (using PayPal provider from Event Tickets Plus) + if (class_exists('Tribe__Tickets_Plus__Commerce__PayPal__Main')) { + $provider = Tribe__Tickets_Plus__Commerce__PayPal__Main::get_instance(); + $ticket_id = $provider->ticket_add($event_id, [ + 'ticket_name' => "General Admission - {$event_data['title']}", + 'ticket_description' => "Ticket for {$event_data['title']}", + 'ticket_price' => $event_data['price'], + 'ticket_show_description' => 'yes', + 'ticket_start_date' => date('Y-m-d H:i:s'), + 'ticket_end_date' => $event_data['start_date'], + 'ticket_capacity' => $event_data['capacity'] + ]); + + if ($ticket_id) { + echo "Created ticket ID: {$ticket_id} for event ID: {$event_id}\n"; + + // Create test attendees with email addresses + $attendee_ids = []; + for ($i = 1; $i <= $event_data['attendees']; $i++) { + $attendee_first_name = "Attendee" . $i; + $attendee_last_name = "Event" . $event_id; + $attendee_email = "attendee{$i}_event{$event_id}@example.com"; + + // Check if we should use a specific email for one attendee per event + if ($i === 1) { + $attendee_email = "ben@tealmaker.com"; + $attendee_first_name = "Ben"; + $attendee_last_name = "Tester"; + } + + // Create attendee post + $attendee_args = [ + 'post_title' => "{$attendee_first_name} {$attendee_last_name}", + 'post_content' => '', + 'post_status' => 'publish', + 'post_type' => 'tribe_tpp_attendees', + ]; + + $attendee_id = wp_insert_post($attendee_args); + + if (is_wp_error($attendee_id)) { + echo "Failed to create attendee for event {$event_id}: " . $attendee_id->get_error_message() . "\n"; + continue; + } + + $attendee_ids[] = $attendee_id; + + // Add attendee meta + $meta = [ + '_tribe_tpp_full_name' => "{$attendee_first_name} {$attendee_last_name}", + '_tribe_tpp_email' => $attendee_email, + '_tribe_tickets_full_name' => "{$attendee_first_name} {$attendee_last_name}", + '_tribe_tickets_email' => $attendee_email, + '_tribe_tpp_event' => $event_id, + '_tribe_tpp_product' => $ticket_id, + '_tribe_tpp_order' => uniqid('ORDER-'), + '_tribe_tpp_security_code' => wp_generate_password(10, false), + '_tribe_tickets_order_status' => 'complete', + '_tribe_tpp_attendee_optout' => 'no', + '_tribe_tickets_attendee_user_id' => 0, + ]; + + foreach ($meta as $key => $value) { + update_post_meta($attendee_id, $key, $value); + } + + // Check in some attendees (for certificate testing) + if ($i <= $event_data['checkins']) { + update_post_meta($attendee_id, '_tribe_tpp_checkin', 1); + update_post_meta($attendee_id, '_tribe_tpp_checked_in', 1); + update_post_meta($attendee_id, '_tribe_tickets_checkin_status', 1); + update_post_meta($attendee_id, 'check_in', 1); + update_post_meta($attendee_id, '_tribe_tpp_checkin_status', 1); + echo "Checked in attendee {$attendee_id} for event {$event_id}\n"; + } + } + + echo "Created {$event_data['attendees']} attendees for event {$event_id}\n"; + echo "Checked in {$event_data['checkins']} attendees for event {$event_id}\n"; + + // Update event attendance count + update_post_meta($event_id, '_tribe_ticket_sold_count', $event_data['attendees']); + update_post_meta($ticket_id, '_tribe_ticket_sold', $event_data['attendees']); + update_post_meta($ticket_id, '_stock', $event_data['capacity'] - $event_data['attendees']); + } else { + echo "Failed to create ticket for event {$event_id}\n"; + } + } else { + echo "Event Tickets Plus PayPal provider not available, skipping ticket creation\n"; + } + + echo "----------------------------\n"; +} + +echo "Test data creation completed!\n"; +?> +EOF + +# Copy PHP script to server and execute +echo "[1;33mCopying script to server...[0m" +scp create-test-data.php $REMOTE_USER@$REMOTE_HOST:/home/974670.cloudwaysapps.com/uberrxmprk/public_html/ + +echo "[1;33mExecuting script on server...[0m" +ssh $REMOTE_USER@$REMOTE_HOST "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html/ && php create-test-data.php" + +# Clean up +rm create-test-data.php +ssh $REMOTE_USER@$REMOTE_HOST "rm /home/974670.cloudwaysapps.com/uberrxmprk/public_html/create-test-data.php" + +echo "[0;32mTest data creation completed![0m" +echo "1. Created events, tickets, and attendees on staging" +echo "2. Added check-in status for some attendees" +echo "3. Events are assigned to test_trainer user" +echo "4. One attendee for each event has email: ben@tealmaker.com" +echo "5. Checked-in attendees are ready for certificate generation" \ No newline at end of file diff --git a/wordpress-dev/bin/create-test-events-for-certificates.php b/wordpress-dev/bin/create-test-events-for-certificates.php new file mode 100644 index 00000000..1258246b --- /dev/null +++ b/wordpress-dev/bin/create-test-events-for-certificates.php @@ -0,0 +1,297 @@ +ID : $current_user_id; + +// Define test events +$events = [ + [ + 'title' => 'HVAC System Design Fundamentals', + 'description' => 'Learn the basics of designing effective HVAC systems for residential and light commercial buildings. This course covers load calculations, equipment selection, and ductwork design.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+1 week')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+1 week +6 hours')), + 'venue' => 'Technical Training Institute', + 'address' => '123 Education Blvd, Boston, MA 02108', + 'attendees' => 25, + 'checked_in' => 20, + ], + [ + 'title' => 'Advanced Refrigeration Technology', + 'description' => 'Deep dive into commercial refrigeration systems, focusing on the latest technologies, troubleshooting techniques, and energy efficiency improvements.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+2 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+2 weeks +8 hours')), + 'venue' => 'Refrigeration Excellence Center', + 'address' => '456 Technology Park, Miami, FL 33101', + 'attendees' => 18, + 'checked_in' => 15, + ], + [ + 'title' => 'Building Automation Systems Workshop', + 'description' => 'Hands-on workshop teaching the fundamentals of modern building automation systems, including programming, troubleshooting, and optimization techniques.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+3 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+3 weeks +12 hours')), + 'venue' => 'Smart Building Center', + 'address' => '789 Innovation Way, Seattle, WA 98101', + 'attendees' => 15, + 'checked_in' => 12, + ] +]; + +// Attendee data generation +$first_names = ['John', 'Jane', 'Michael', 'Sara', 'David', 'Lisa', 'Robert', 'Emily', + 'William', 'Olivia', 'James', 'Sophia', 'Thomas', 'Emma', 'Daniel', 'Ava']; + +$last_names = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Davis', 'Miller', 'Wilson', + 'Moore', 'Taylor', 'Anderson', 'Thomas', 'Jackson', 'White', 'Harris', 'Martin']; + +$domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'aol.com', 'icloud.com', + 'protonmail.com', 'hvactraining.com', 'techedu.org', 'contractor.net']; + +// Track statistics +$events_created = 0; +$attendees_created = 0; +$attendees_checked_in = 0; +$certificates_created = 0; +$certificates_revoked = 0; +$certificates_emailed = 0; +$created_event_ids = []; + +// Create events and associated data +foreach ($events as $event_data) { + echo "Creating event: {$event_data['title']}\n"; + + // Create event + $event_args = [ + 'post_title' => $event_data['title'], + 'post_content' => $event_data['description'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Main::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $event_id = wp_insert_post($event_args); + + if (is_wp_error($event_id)) { + echo "Failed to create event: " . $event_id->get_error_message() . "\n"; + continue; + } + + // Add event meta + update_post_meta($event_id, '_EventStartDate', $event_data['start_date']); + update_post_meta($event_id, '_EventEndDate', $event_data['end_date']); + + // Create venue + $venue_args = [ + 'post_title' => $event_data['venue'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Venue::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $venue_id = wp_insert_post($venue_args); + + if (!is_wp_error($venue_id)) { + // Parse address + $address_parts = explode(', ', $event_data['address']); + $street = isset($address_parts[0]) ? $address_parts[0] : ''; + $city = isset($address_parts[1]) ? $address_parts[1] : ''; + $state_zip = isset($address_parts[2]) ? explode(' ', $address_parts[2]) : ['', '']; + + // Add venue meta + update_post_meta($venue_id, '_VenueAddress', $street); + update_post_meta($venue_id, '_VenueCity', $city); + update_post_meta($venue_id, '_VenueStateProvince', $state_zip[0]); + update_post_meta($venue_id, '_VenueZip', isset($state_zip[1]) ? $state_zip[1] : ''); + + // Link venue to event + update_post_meta($event_id, '_EventVenueID', $venue_id); + } + + $events_created++; + $created_event_ids[] = $event_id; + + echo "Event created successfully (ID: {$event_id})\n"; + + // Create attendees directly (without tickets, for simplicity) + $local_attendees_created = 0; + $local_attendees_checked_in = 0; + $local_certificates_created = 0; + + for ($i = 1; $i <= $event_data['attendees']; $i++) { + // Generate attendee data + $first_name = ($i === 1) ? 'Ben' : $first_names[array_rand($first_names)]; + $last_name = ($i === 1) ? 'Tester' : $last_names[array_rand($last_names)]; + $email = ($i === 1) ? 'ben@tealmaker.com' : + strtolower($first_name . '.' . $last_name . '.' . rand(100, 999) . '@' . $domains[array_rand($domains)]); + + $full_name = $first_name . ' ' . $last_name; + + // Create attendee post + $attendee_args = [ + 'post_title' => $full_name, + 'post_content' => '', + 'post_status' => 'publish', + 'post_type' => 'tribe_tpp_attendees', // Use PayPal attendees for this test + ]; + + $attendee_id = wp_insert_post($attendee_args); + + if (is_wp_error($attendee_id)) { + echo "Failed to create attendee {$full_name}: " . $attendee_id->get_error_message() . "\n"; + continue; + } + + // Generate a unique order ID + $order_id = 'TEST-ORDER-' . $event_id . '-' . $i . '-' . uniqid(); + + // Add attendee meta + update_post_meta($attendee_id, '_tribe_tickets_full_name', $full_name); + update_post_meta($attendee_id, '_tribe_tickets_email', $email); + update_post_meta($attendee_id, '_tribe_tpp_full_name', $full_name); + update_post_meta($attendee_id, '_tribe_tpp_email', $email); + update_post_meta($attendee_id, '_tribe_tpp_event', $event_id); + update_post_meta($attendee_id, '_tribe_tpp_order', $order_id); + update_post_meta($attendee_id, '_tribe_tpp_security_code', wp_generate_password(10, false)); + update_post_meta($attendee_id, '_tribe_tickets_order_status', 'completed'); + + $local_attendees_created++; + $attendees_created++; + + // Check in some attendees + if ($i <= $event_data['checked_in']) { + update_post_meta($attendee_id, '_tribe_tpp_checkin', 1); + update_post_meta($attendee_id, '_tribe_tpp_checked_in', 1); + update_post_meta($attendee_id, '_tribe_tickets_checkin_status', 1); + update_post_meta($attendee_id, 'check_in', 1); + + $local_attendees_checked_in++; + $attendees_checked_in++; + + // Generate certificate for checked-in attendee + $year = date('Y'); + $month = date('m'); + $certificate_filename = "certificate-{$event_id}-{$attendee_id}-" . time() . ".pdf"; + $certificate_relative_path = "hvac-certificates/{$year}/{$month}/{$certificate_filename}"; + + // Create year/month directory structure if needed + $year_month_dir = $cert_dir . "/{$year}/{$month}"; + if (!file_exists($year_month_dir)) { + wp_mkdir_p($year_month_dir); + } + + // Create the certificate record + $certificate_id = $certificate_manager->create_certificate( + $event_id, + $attendee_id, + 0, // user_id (not associated with a user) + $certificate_relative_path, + $trainer_id // generated by trainer + ); + + if ($certificate_id) { + $local_certificates_created++; + $certificates_created++; + + // Create dummy certificate file + $certificate_full_path = $upload_dir['basedir'] . '/' . $certificate_relative_path; + file_put_contents($certificate_full_path, "Placeholder for certificate PDF - {$event_data['title']} - {$full_name}"); + + // Randomly mark some certificates as revoked or emailed for testing + $random = mt_rand(1, 10); + + // Revoke about 10% of certificates + if ($random == 1) { + $certificate_manager->revoke_certificate( + $certificate_id, + $trainer_id, + "Test revocation for certificate testing" + ); + $certificates_revoked++; + } + + // Mark about 70% as emailed + if ($random <= 7) { + $certificate_manager->mark_certificate_emailed($certificate_id); + $certificates_emailed++; + } + } + } + } + + echo "Created {$local_attendees_created} attendees\n"; + echo "Checked in {$local_attendees_checked_in} attendees\n"; + echo "Generated {$local_certificates_created} certificates\n"; + echo "----------------------------\n"; +} + +// Print summary +echo "\n===== TEST DATA CREATION SUMMARY =====\n"; +echo "Events created: {$events_created}\n"; +echo "Attendees created: {$attendees_created}\n"; +echo "Attendees checked in: {$attendees_checked_in}\n"; +echo "Certificates created: {$certificates_created}\n"; +echo "Certificates revoked: {$certificates_revoked}\n"; +echo "Certificates marked as emailed: {$certificates_emailed}\n"; + +// Get certificate statistics +$stats = $certificate_manager->get_certificate_stats(); + +echo "\n===== CERTIFICATE DATABASE STATISTICS =====\n"; +echo "Total certificates in database: {$stats['total_certificates']}\n"; +echo "Total events with certificates: {$stats['total_events']}\n"; +echo "Total trainees with certificates: {$stats['total_trainees']}\n"; +echo "Total revoked certificates: {$stats['total_revoked']}\n"; +echo "Total emailed certificates: {$stats['total_emailed']}\n"; +echo "Average certificates per attendee: {$stats['avg_per_attendee']}\n"; + +echo "\n===== EVENT IDS FOR REFERENCE =====\n"; +foreach ($created_event_ids as $id) { + $title = get_the_title($id); + echo "Event ID {$id}: {$title}\n"; +} + +echo "\n===== TEST DATA CREATION COMPLETE =====\n"; +echo "You can now test the certificate system with the created data.\n"; +echo "View certificates at: " . home_url('/certificate-reports/') . "\n"; \ No newline at end of file diff --git a/wordpress-dev/bin/deploy-certificate-fixes-v2.sh b/wordpress-dev/bin/deploy-certificate-fixes-v2.sh new file mode 100755 index 00000000..0690c3c4 --- /dev/null +++ b/wordpress-dev/bin/deploy-certificate-fixes-v2.sh @@ -0,0 +1,119 @@ +#!/bin/bash + +# Certificate Fixes Deployment Script +# This script deploys certificate-related fixes to the staging server + +# Define colors for output +GREEN="\033[0;32m" +RED="\033[0;31m" +YELLOW="\033[0;33m" +CYAN="\033[0;36m" +NC="\033[0m" # No Color + +# Function to print colorful status messages +function echo_status() { + local color="" + case "$2" in + "success") color=$GREEN ;; + "error") color=$RED ;; + "warning") color=$YELLOW ;; + "info") color=$CYAN ;; + *) color=$NC ;; + esac + + echo -e "${color}[$2] $1${NC}" +} + +# SSH connection details +REMOTE_HOST="wordpress-974670-5399585.cloudwaysapps.com" +REMOTE_USER="master_vbwpndkhyx" +REMOTE_PLUGIN_PATH="/home/master/applications/vbwpndkhyx/public_html/wp-content/plugins/hvac-community-events" +LOCAL_PLUGIN_PATH="./wordpress/wp-content/plugins/hvac-community-events" +PLUGIN_SLUG="hvac-community-events" + +echo_status "Starting certificate fixes deployment..." "info" + +# Validate paths exist +if [ ! -d "$LOCAL_PLUGIN_PATH" ]; then + echo_status "Error: Local plugin directory does not exist: $LOCAL_PLUGIN_PATH" "error" + exit 1 +fi + +if [ ! -d "$LOCAL_PLUGIN_PATH/templates/certificates" ]; then + echo_status "Error: Local certificate templates directory does not exist" "error" + exit 1 +fi + +if [ ! -d "$LOCAL_PLUGIN_PATH/includes/certificates" ]; then + echo_status "Error: Local certificate includes directory does not exist" "error" + exit 1 +fi + +# Create temp directory for our fix script +echo_status "Preparing fix script..." "info" +mkdir -p "$LOCAL_PLUGIN_PATH/tmp-fixes" +cp "./bin/fix-certificate-reports.php" "$LOCAL_PLUGIN_PATH/tmp-fixes/" + +# Create backup of plugin directory on staging server +echo_status "Creating backup of certificate files on staging server..." "info" +ssh "$REMOTE_USER@$REMOTE_HOST" "mkdir -p \"${REMOTE_PLUGIN_PATH}/backups\" && \ + cp -r \"${REMOTE_PLUGIN_PATH}/templates/certificates\" \"${REMOTE_PLUGIN_PATH}/backups/certificates_templates_backup_$(date +%Y%m%d%H%M%S)\" && \ + cp -r \"${REMOTE_PLUGIN_PATH}/includes/certificates\" \"${REMOTE_PLUGIN_PATH}/backups/certificates_includes_backup_$(date +%Y%m%d%H%M%S)\"" + +if [ $? -ne 0 ]; then + echo_status "Warning: Failed to create backup on staging server." "warning" +fi + +# Rsync the certificate files +echo_status "Deploying certificate fixes to staging server..." "info" + +# Sync certificate template files +rsync -avz --delete \ + "$LOCAL_PLUGIN_PATH/templates/certificates/" \ + "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PLUGIN_PATH/templates/certificates/" + +if [ $? -ne 0 ]; then + echo_status "Error: Failed to sync certificate templates." "error" + exit 1 +fi + +# Sync certificate class files +rsync -avz --delete \ + "$LOCAL_PLUGIN_PATH/includes/certificates/" \ + "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PLUGIN_PATH/includes/certificates/" + +if [ $? -ne 0 ]; then + echo_status "Error: Failed to sync certificate classes." "error" + exit 1 +fi + +# Sync fix script +rsync -avz \ + "$LOCAL_PLUGIN_PATH/tmp-fixes/fix-certificate-reports.php" \ + "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PLUGIN_PATH/fix-certificate-reports.php" + +if [ $? -ne 0 ]; then + echo_status "Error: Failed to sync fix script." "error" + exit 1 +fi + +# Run fix script on remote server +echo_status "Running certificate fix script on staging server..." "info" +ssh "$REMOTE_USER@$REMOTE_HOST" "cd /home/master/applications/vbwpndkhyx/public_html && php -f $REMOTE_PLUGIN_PATH/fix-certificate-reports.php" + +if [ $? -ne 0 ]; then + echo_status "Warning: Fix script execution may have encountered issues." "warning" +fi + +# Clean up +echo_status "Cleaning up temporary files..." "info" +rm -rf "$LOCAL_PLUGIN_PATH/tmp-fixes" +ssh "$REMOTE_USER@$REMOTE_HOST" "rm -f $REMOTE_PLUGIN_PATH/fix-certificate-reports.php" + +echo_status "Certificate fixes deployment completed successfully!" "success" + +# Run final test to verify the fixes +echo_status "Running final verification test..." "info" +node ./bin/final-test.js + +echo_status "All tasks completed. Please check verification results above." "success" \ No newline at end of file diff --git a/wordpress-dev/bin/deploy-direct-certificate-fix.sh b/wordpress-dev/bin/deploy-direct-certificate-fix.sh new file mode 100755 index 00000000..912990fa --- /dev/null +++ b/wordpress-dev/bin/deploy-direct-certificate-fix.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +# Direct certificate fix deployment script +# This script creates a ZIP package of all the fixes for direct upload to the staging server + +# Directory setup +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +OUTPUT_DIR="$PROJECT_ROOT/certificate-fixes" +mkdir -p "$OUTPUT_DIR" + +echo "Creating certificate fix package..." + +# Create directory structure +mkdir -p "$OUTPUT_DIR/templates/certificates" +mkdir -p "$OUTPUT_DIR/includes/certificates" +mkdir -p "$OUTPUT_DIR/bin" + +# Copy the fixed template files +cp "$PROJECT_ROOT/wordpress/wp-content/plugins/hvac-community-events/templates/certificates/template-certificate-reports.php" "$OUTPUT_DIR/templates/certificates/" +cp "$PROJECT_ROOT/wordpress/wp-content/plugins/hvac-community-events/templates/certificates/template-certificate-reports-simple.php" "$OUTPUT_DIR/templates/certificates/" +cp "$PROJECT_ROOT/wordpress/wp-content/plugins/hvac-community-events/templates/certificates/certificate-fix.php" "$OUTPUT_DIR/templates/certificates/" + +# Copy the certificate class files +cp "$PROJECT_ROOT/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-manager.php" "$OUTPUT_DIR/includes/certificates/" +cp "$PROJECT_ROOT/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-installer.php" "$OUTPUT_DIR/includes/certificates/" +cp "$PROJECT_ROOT/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-fix.php" "$OUTPUT_DIR/includes/certificates/" + +# Copy the fix scripts +cp "$PROJECT_ROOT/bin/emergency-certificate-fix.php" "$OUTPUT_DIR/bin/" +cp "$PROJECT_ROOT/bin/fix-html-comments.php" "$OUTPUT_DIR/bin/" +cp "$PROJECT_ROOT/bin/test-certificate-system.php" "$OUTPUT_DIR/bin/" + +# Copy documentation +cp "$PROJECT_ROOT/CERTIFICATE_TROUBLESHOOTING.md" "$OUTPUT_DIR/" +cp "$PROJECT_ROOT/CERTIFICATE_FIX.md" "$OUTPUT_DIR/" + +# Create README with instructions +cat > "$OUTPUT_DIR/README.md" << 'EOF' +# Certificate System Fix Package + +This package contains fixes for the certificate system in the HVAC Community Events plugin. + +## Quick Fix Instructions + +1. Upload the emergency-certificate-fix.php script to your WordPress site (e.g., via FTP) +2. Upload the template-certificate-reports-simple.php file to the same directory as the emergency-certificate-fix.php script +3. Visit the emergency-certificate-fix.php in your browser (e.g., https://your-site.com/emergency-certificate-fix.php) +4. Follow the on-screen instructions to apply the fixes +5. After the fixes are applied, delete the emergency-certificate-fix.php script + +## Complete Fix Instructions + +For a more thorough fix: + +1. Replace the files in your WordPress installation with the ones in this package: + - Copy `templates/certificates/*` to `wp-content/plugins/hvac-community-events/templates/certificates/` + - Copy `includes/certificates/*` to `wp-content/plugins/hvac-community-events/includes/certificates/` + +2. Run the test-certificate-system.php script to verify the fixes: + - Upload the script to your WordPress site + - Visit the script in your browser or run it via command line + +## Testing + +After applying the fixes, test both certificate pages: +- Generate Certificates page: /generate-certificates/ +- Certificate Reports page: /certificate-reports/ + +## Additional Resources + +- CERTIFICATE_TROUBLESHOOTING.md - Detailed troubleshooting guide +- CERTIFICATE_FIX.md - Explanation of all fixes applied + +If you have any questions or issues, please contact the development team. +EOF + +# Create ZIP file +ZIP_FILE="$PROJECT_ROOT/certificate-fixes.zip" +cd "$OUTPUT_DIR" || exit 1 +zip -r "$ZIP_FILE" . + +echo "Certificate fix package created at: $ZIP_FILE" +echo "Upload this file to the staging server and follow the instructions in the README.md file." \ No newline at end of file diff --git a/wordpress-dev/bin/deploy-fixed-plugin.sh b/wordpress-dev/bin/deploy-fixed-plugin.sh new file mode 100755 index 00000000..88d99d21 --- /dev/null +++ b/wordpress-dev/bin/deploy-fixed-plugin.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Deploy the fixed HVAC Community Events plugin to the staging server + +# Set variables +PLUGIN_NAME="hvac-community-events" +PLUGIN_DIR="/Users/ben/dev/upskill-event-manager/wordpress-dev/wordpress/wp-content/plugins/${PLUGIN_NAME}" +BACKUP_DIR="/Users/ben/dev/upskill-event-manager/wordpress-dev/plugin-backups" +ZIP_FILE="${BACKUP_DIR}/${PLUGIN_NAME}.zip" +TIMESTAMP=$(date +"%Y%m%d%H%M%S") + +# Create backup directory if it doesn't exist +mkdir -p "${BACKUP_DIR}" + +# Navigate to the plugins directory +cd "$(dirname "${PLUGIN_DIR}")" + +echo "Creating plugin backup..." +# Create a ZIP archive of the current plugin +zip -r "${ZIP_FILE}.${TIMESTAMP}" "${PLUGIN_NAME}" +echo "Backup created at: ${ZIP_FILE}.${TIMESTAMP}" + +echo "Packaging fixed plugin for deployment..." +# Create a ZIP archive of the plugin for deployment +zip -r "${ZIP_FILE}" "${PLUGIN_NAME}" +echo "Plugin packaged at: ${ZIP_FILE}" + +echo "Plugin archive created successfully!" +echo "To deploy, upload ${ZIP_FILE} through the WordPress plugin uploader or via FTP." \ No newline at end of file diff --git a/wordpress-dev/bin/deploy-plugin-via-cli.sh b/wordpress-dev/bin/deploy-plugin-via-cli.sh new file mode 100755 index 00000000..96b0acc7 --- /dev/null +++ b/wordpress-dev/bin/deploy-plugin-via-cli.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +# Deploy HVAC Community Events plugin via WP-CLI +# This script uses SSH to execute WP-CLI commands on the remote server +# It handles plugin installation, activation, and verification + +# Get absolute path to this script's directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Navigate to wordpress-dev directory +cd "$(dirname "$SCRIPT_DIR")" || exit 1 + +# Load environment variables +ENV_FILE=".env" +if [ ! -f "$ENV_FILE" ]; then + echo "Error: .env file not found at: $ENV_FILE" + exit 1 +fi + +source "$ENV_FILE" + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Function to check if a command was successful +check_status() { + if [ $? -eq 0 ]; then + echo -e "${GREEN}✓ $1${NC}" + return 0 + else + echo -e "${RED}✗ $1${NC}" + return 1 + fi +} + +# Function to run WP-CLI commands remotely +remote_wp_cli() { + COMMAND="$1" + sshpass -p "${UPSKILL_STAGING_PASS}" ssh -o StrictHostKeyChecking=no "${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP}" "cd ${UPSKILL_STAGING_PATH} && wp $COMMAND --allow-root" +} + +echo "=== Deploying HVAC Community Events Plugin via CLI ===" +echo "Remote host: ${UPSKILL_STAGING_IP} (upskill-staging.measurequick.com)" +echo "Remote user: ${UPSKILL_STAGING_SSH_USER}" +echo "WordPress path: ${UPSKILL_STAGING_PATH}" +echo "Plugin package: plugin-backups/hvac-community-events.zip" +echo "=======================================================" + +# Step 1: Check if plugin exists and deactivate it if it does +echo -e "\n${YELLOW}Checking if plugin is already installed...${NC}" +PLUGIN_STATUS=$(remote_wp_cli "plugin get hvac-community-events --field=status" 2>/dev/null) + +if [ $? -eq 0 ]; then + echo -e "${YELLOW}Plugin is already installed with status: $PLUGIN_STATUS${NC}" + + # Deactivate plugin if active + if [ "$PLUGIN_STATUS" = "active" ]; then + echo -e "${YELLOW}Deactivating existing plugin...${NC}" + remote_wp_cli "plugin deactivate hvac-community-events" + check_status "Plugin deactivated" + fi + + # Make backup of existing plugin + echo -e "${YELLOW}Creating backup of existing plugin...${NC}" + BACKUP_DATE=$(date +%Y%m%d%H%M%S) + remote_wp_cli "plugin get hvac-community-events --field=path" | xargs -I {} sshpass -p "${UPSKILL_STAGING_PASS}" ssh -o StrictHostKeyChecking=no "${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP}" "cp -r {} {}.bak.$BACKUP_DATE" + check_status "Plugin backup created" + + # Delete existing plugin + echo -e "${YELLOW}Removing existing plugin...${NC}" + remote_wp_cli "plugin delete hvac-community-events" + check_status "Existing plugin deleted" +else + echo -e "${YELLOW}Plugin not currently installed.${NC}" +fi + +# Step 2: Upload plugin zip file +echo -e "\n${YELLOW}Uploading plugin package...${NC}" +sshpass -p "${UPSKILL_STAGING_PASS}" scp "plugin-backups/hvac-community-events.zip" "${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP}:${UPSKILL_STAGING_PATH}" +check_status "Plugin package uploaded" + +# Step 3: Install plugin +echo -e "\n${YELLOW}Installing plugin...${NC}" +remote_wp_cli "plugin install ${UPSKILL_STAGING_PATH}/hvac-community-events.zip --force" +check_status "Plugin installed" + +# Step 4: Activate plugin +echo -e "\n${YELLOW}Activating plugin...${NC}" +remote_wp_cli "plugin activate hvac-community-events" +check_status "Plugin activated" + +# Step 5: Clean up +echo -e "\n${YELLOW}Cleaning up...${NC}" +sshpass -p "${UPSKILL_STAGING_PASS}" ssh -o StrictHostKeyChecking=no "${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP}" "rm -f ${UPSKILL_STAGING_PATH}/hvac-community-events.zip" +check_status "Temporary files removed" + +# Step 6: Verify installation +echo -e "\n${YELLOW}Verifying installation...${NC}" +PLUGIN_VERSION=$(remote_wp_cli "plugin get hvac-community-events --field=version") +check_status "Plugin installed with version: $PLUGIN_VERSION" + +# Check if plugin roles are created +echo -e "\n${YELLOW}Checking plugin roles...${NC}" +ROLES=$(remote_wp_cli "role list --field=role") +if [[ $ROLES == *"hvac_trainer"* ]]; then + echo -e "${GREEN}✓ HVAC Trainer role exists${NC}" +else + echo -e "${RED}✗ HVAC Trainer role not found${NC}" +fi + +# Step 7: Flush rewrite rules +echo -e "\n${YELLOW}Flushing rewrite rules...${NC}" +remote_wp_cli "rewrite flush --hard" +check_status "Rewrite rules flushed" + +echo -e "\n${GREEN}Plugin deployment completed!${NC}" +echo "Plugin: hvac-community-events" +echo "Version: $PLUGIN_VERSION" +echo "Status: $(remote_wp_cli "plugin get hvac-community-events --field=status")" +echo -e "\nNext steps:" +echo "1. Set up test users with './bin/setup-staging-test-users.sh'" +echo "2. Create test data with './bin/create-comprehensive-test-data.sh'" +echo "3. Verify Zoho CRM integration with the verification guide" \ No newline at end of file diff --git a/wordpress-dev/bin/deploy-plugin-zoho-fix.sh b/wordpress-dev/bin/deploy-plugin-zoho-fix.sh new file mode 100755 index 00000000..cb9d9644 --- /dev/null +++ b/wordpress-dev/bin/deploy-plugin-zoho-fix.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# +# HVAC Community Events Plugin Deployment Script +# This script deploys the updated plugin with Zoho CRM integration fixes +# + +# Exit on error +set -e + +# Load environment variables +if [ -f ".env" ]; then + source .env +else + echo "Error: .env file not found" + exit 1 +fi + +# Define variables +PLUGIN_NAME="hvac-community-events" +PLUGIN_ZIP="plugin-backups/hvac-community-events-updated.zip" +PLUGIN_DIR="${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html}/wp-content/plugins/${PLUGIN_NAME}" +BACKUP_DIR="${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html}/wp-content/plugins/${PLUGIN_NAME}.bak.$(date +%Y%m%d%H%M%S)" +TEMP_DIR="${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html}/wp-content/upgrade/temp-${PLUGIN_NAME}" + +# Check if required variables are set +if [ -z "${UPSKILL_STAGING_SSH_USER}" ] || [ -z "${UPSKILL_STAGING_IP}" ]; then + echo "Error: Required environment variables not set. Please check your .env file." + exit 1 +fi + +# Display deployment info +echo "==============================================" +echo "HVAC Community Events Plugin Deployment" +echo "==============================================" +echo "Deploying to: ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP}" +echo "Plugin path: ${PLUGIN_DIR}" +echo "Backup path: ${BACKUP_DIR}" +echo "==============================================" +echo + +# Check if plugin zip exists +if [ ! -f "${PLUGIN_ZIP}" ]; then + echo "Error: Plugin ZIP file not found at ${PLUGIN_ZIP}" + exit 1 +fi + +# Define SSH command with password if available +if [ -n "${UPSKILL_STAGING_PASS}" ]; then + SSH_CMD="sshpass -p \"${UPSKILL_STAGING_PASS}\" ssh -o StrictHostKeyChecking=no" +else + SSH_CMD="ssh -o StrictHostKeyChecking=no" +fi + +# Define SCP command with password if available +if [ -n "${UPSKILL_STAGING_PASS}" ]; then + SCP_CMD="sshpass -p \"${UPSKILL_STAGING_PASS}\" scp -o StrictHostKeyChecking=no" +else + SCP_CMD="scp -o StrictHostKeyChecking=no" +fi + +# Create deployment steps +echo "Step 1: Checking server connection..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "echo Server connection successful." + +echo "Step 2: Deactivating existing plugin..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "cd ${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html} && wp plugin deactivate ${PLUGIN_NAME} --skip-plugins --skip-themes || echo 'Plugin not active or not found'" + +echo "Step 3: Creating backup of existing plugin..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "if [ -d '${PLUGIN_DIR}' ]; then mv '${PLUGIN_DIR}' '${BACKUP_DIR}'; echo 'Backup created at ${BACKUP_DIR}'; else echo 'No existing plugin to backup'; fi" + +echo "Step 4: Creating temporary directory..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "mkdir -p '${TEMP_DIR}'" +# Verify the directory was created +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "ls -la '$(dirname ${TEMP_DIR})' && echo 'Temp directory created successfully'" + +echo "Step 5: Uploading plugin package..." +# First upload to home directory, then move to temp dir +${SCP_CMD} "${PLUGIN_ZIP}" ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP}:~/plugin.zip +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "mv ~/plugin.zip '${TEMP_DIR}/'" + +echo "Step 6: Extracting plugin package..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "cd '${TEMP_DIR}' && unzip -q plugin.zip && mv ${PLUGIN_NAME}-updated '${PLUGIN_DIR}'" + +echo "Step 7: Fixing file permissions..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "chmod -R 755 '${PLUGIN_DIR}'" + +echo "Step 8: Cleaning up temporary files..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "rm -rf '${TEMP_DIR}'" + +echo "Step 9: Creating .env file with Zoho credentials..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "echo 'ZOHO_CLIENT_ID=${ZOHO_CLIENT_ID}' > '${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html}/.env' && echo 'ZOHO_CLIENT_SECRET=${ZOHO_CLIENT_SECRET}' >> '${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html}/.env' && echo 'UPSKILL_STAGING_URL=https://upskill-staging.measurequick.com/' >> '${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html}/.env' && chmod 640 '${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html}/.env'" + +echo "Step 10: Activating plugin..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "cd ${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html} && wp plugin activate ${PLUGIN_NAME} --skip-plugins --skip-themes" + +echo "Step 11: Flushing rewrite rules..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "cd ${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html} && wp rewrite flush --skip-plugins --skip-themes" + +echo "Step 12: Verifying installation..." +${SSH_CMD} ${UPSKILL_STAGING_SSH_USER}@${UPSKILL_STAGING_IP} "cd ${UPSKILL_STAGING_PATH:-/home/974670.cloudwaysapps.com/uberrxmprk/public_html} && wp plugin is-active ${PLUGIN_NAME} --skip-plugins --skip-themes && echo 'Plugin successfully activated' || echo 'WARNING: Plugin activation failed'" + +echo +echo "==============================================" +echo "Deployment completed!" +echo "==============================================" +echo "Don't forget to verify the Zoho CRM integration at:" +echo "https://upskill-staging.measurequick.com/wp-admin/admin.php?page=hvac-zoho-sync" +echo "==============================================" \ No newline at end of file diff --git a/wordpress-dev/bin/deploy-zoho-admin-fix.sh b/wordpress-dev/bin/deploy-zoho-admin-fix.sh new file mode 100755 index 00000000..0f6eec59 --- /dev/null +++ b/wordpress-dev/bin/deploy-zoho-admin-fix.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Deploy the Zoho Admin fixer plugin to the Cloudways staging server +# This script will create a ZIP file of the plugin and upload it to the server + +# Set variables +SERVER="wordpress-974670-5399585.cloudwaysapps.com" +PLUGIN_DIR="zoho-admin-fixer" +ZIP_FILE="zoho-admin-fixer.zip" +REMOTE_PATH="/home/974670/public_html/wp-content/plugins/" + +# Create the plugin directory if it doesn't exist +mkdir -p $PLUGIN_DIR + +# Remove any existing ZIP file +rm -f $ZIP_FILE + +# Create a ZIP file of the plugin +cd $PLUGIN_DIR +zip -r ../$ZIP_FILE . +cd .. + +echo "Created plugin ZIP file: $ZIP_FILE" + +# Upload the ZIP file to the server +echo "Uploading ZIP file to server..." +scp $ZIP_FILE $SERVER:$REMOTE_PATH + +# SSH into the server to unzip the plugin +echo "Extracting plugin on server..." +ssh $SERVER "cd $REMOTE_PATH && unzip -o $ZIP_FILE && rm $ZIP_FILE" + +echo "Plugin deployed successfully!" + +# Clean up +rm -f $ZIP_FILE + +echo "Deployment completed!" \ No newline at end of file diff --git a/wordpress-dev/bin/deploy-zoho-fix.sh b/wordpress-dev/bin/deploy-zoho-fix.sh new file mode 100755 index 00000000..e7ffeda4 --- /dev/null +++ b/wordpress-dev/bin/deploy-zoho-fix.sh @@ -0,0 +1,787 @@ +#\!/bin/bash + +# Zoho CRM Integration Fix Deployment Script +# This script runs the cleanup and then deploys the Zoho fix + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Load environment variables +source "$(dirname "$0")/../.env" + +# Check if environment variables are loaded +if [ -z "$UPSKILL_STAGING_IP" ] || [ -z "$UPSKILL_STAGING_SSH_USER" ]; then + echo -e "${RED}Error: Missing required environment variables${NC}" + echo "Please ensure .env file exists and contains UPSKILL_STAGING_IP and UPSKILL_STAGING_SSH_USER" + exit 1 +fi + +# Set variables +REMOTE_HOST="${UPSKILL_STAGING_IP}" +REMOTE_USER="${UPSKILL_STAGING_SSH_USER}" +REMOTE_PASS="${UPSKILL_STAGING_PASS}" +REMOTE_PATH="/home/974670.cloudwaysapps.com/uberrxmprk/public_html" +PLUGINS_PATH="${REMOTE_PATH}/wp-content/plugins" +MAIN_PLUGIN="hvac-community-events" + +echo -e "${YELLOW}=== Zoho CRM Integration Fix Deployment ===${NC}" +echo -e "${YELLOW}Target: ${REMOTE_USER}@${REMOTE_HOST}:${PLUGINS_PATH}/${MAIN_PLUGIN}${NC}" + +# Step 1: Run the cleanup script first +echo -e "${YELLOW}Step 1: Running plugin cleanup...${NC}" +"$(dirname "$0")/cleanup-hvac-plugins.sh" + +if [ $? -ne 0 ]; then + echo -e "${RED}Error: Plugin cleanup failed. Aborting deployment.${NC}" + exit 1 +fi + +echo -e "${GREEN}Plugin cleanup completed successfully.${NC}" + +# Step 2: Create directories for Zoho files +echo -e "${YELLOW}Step 2: Creating required directories...${NC}" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" < "$ZOHO_CONFIG" << 'EOPHP' + "$DIAGNOSTICS_FILE" << 'EOPHP' + "$CSS_FILE" << 'EOCSS' +/* Debug Information Styling */ +.hvac-zoho-debug-info { + margin-top: 15px; + padding: 15px; + background: #f9f9f9; + border: 1px solid #ddd; + border-left: 4px solid #dc3232; +} + +.hvac-zoho-debug-info details summary { + cursor: pointer; + font-weight: bold; + color: #0073aa; + padding: 5px; + background: #f0f0f0; +} + +.hvac-zoho-debug-info pre { + margin: 10px 0; + padding: 10px; + background: #f0f0f0; + border: 1px solid #ddd; + overflow: auto; + max-height: 300px; +} +EOCSS + +sshpass -p "$REMOTE_PASS" scp -o StrictHostKeyChecking=no "$CSS_FILE" "$REMOTE_USER@$REMOTE_HOST:$PLUGINS_PATH/$MAIN_PLUGIN/assets/css/zoho-admin.css" + +if [ $? -ne 0 ]; then + echo -e "${RED}Error: Failed to upload CSS file. Aborting deployment.${NC}" + rm "$CSS_FILE" + exit 1 +fi + +rm "$CSS_FILE" +echo -e "${GREEN}CSS file uploaded successfully.${NC}" + +# Step 6: Update class-zoho-admin.php if it exists +echo -e "${YELLOW}Step 6: Updating admin class if it exists...${NC}" + +# Create a PHP script to update the admin class +UPDATE_ADMIN_SCRIPT=$(mktemp) +cat > "$UPDATE_ADMIN_SCRIPT" << 'EOPHP' +get_modules(); + + // Enhanced error handling and detailed response + if (\$response && \!isset(\$response['error'])) { + wp_send_json_success(array( + 'message' => 'Connection successful\!', + 'modules' => isset(\$response['modules']) ? count(\$response['modules']) . ' modules available' : 'No modules found' + )); + } else { + \$error_message = isset(\$response['error']) ? \$response['error'] : 'Unknown error'; + \$error_code = isset(\$response['code']) ? \$response['code'] : ''; + \$error_details = isset(\$response['details']) ? \$response['details'] : ''; + + // Log the error + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + \$log_message = \"[\" . date('Y-m-d H:i:s') . \"] Connection test failed: \$error_message\\n\"; + \$log_message .= \"[\" . date('Y-m-d H:i:s') . \"] Error code: \$error_code\\n\"; + \$log_message .= \"[\" . date('Y-m-d H:i:s') . \"] Details: \$error_details\\n\"; + \$log_message .= \"[\" . date('Y-m-d H:i:s') . \"] Raw response: \" . json_encode(\$response) . \"\\n\"; + + if (defined('ZOHO_LOG_FILE')) { + error_log(\$log_message, 3, ZOHO_LOG_FILE); + } + } + + // Send detailed error data back to frontend + wp_send_json_error(array( + 'message' => 'Connection failed', + 'error' => \$error_message, + 'code' => \$error_code, + 'details' => \$error_details, + 'raw' => json_encode(\$response) + )); + } + }"; + + // Replace the method + $content = preg_replace($pattern, $replacement, $content); + + // Save the updated file + if (file_put_contents($admin_path, $content)) { + echo "Admin class updated successfully with enhanced error reporting.\n"; + } else { + echo "Failed to update admin class.\n"; + exit(1); + } +} else { + echo "Could not find test_connection method in admin class. Manual update may be required.\n"; +} +EOPHP + +sshpass -p "$REMOTE_PASS" scp -o StrictHostKeyChecking=no "$UPDATE_ADMIN_SCRIPT" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/update-admin-class.php" +ADMIN_UPDATE_RESULT=$(sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "cd $REMOTE_PATH && php update-admin-class.php") +echo "$ADMIN_UPDATE_RESULT" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "rm -f $REMOTE_PATH/update-admin-class.php" + +rm "$UPDATE_ADMIN_SCRIPT" + +# Step 7: Update class-zoho-crm-auth.php if it exists +echo -e "${YELLOW}Step 7: Updating auth class if it exists...${NC}" + +# Create a PHP script to update the auth class +UPDATE_AUTH_SCRIPT=$(mktemp) +cat > "$UPDATE_AUTH_SCRIPT" << 'EOPHP' +client_id; + } + + /** + * Get client secret + * + * @return string + */ + public function get_client_secret() { + return \$this->client_secret; + } + + /** + * Get refresh token + * + * @return string + */ + public function get_refresh_token() { + return \$this->refresh_token; + } +}\$1"; + + $content = preg_replace($pattern, $replacement, $content); +} + +// Find constructor to add environment loading +$pattern = '/public function __construct\(\) {/'; +$replacement = "public function __construct() { + // Load environment variables from .env if available + if (function_exists('load_env_from_dotenv')) { + load_env_from_dotenv(); + }"; + +$content = preg_replace($pattern, $replacement, $content); + +// Save the updated file +if (file_put_contents($auth_path, $content)) { + echo "Auth class updated successfully to load environment variables.\n"; +} else { + echo "Failed to update auth class.\n"; + exit(1); +} +EOPHP + +sshpass -p "$REMOTE_PASS" scp -o StrictHostKeyChecking=no "$UPDATE_AUTH_SCRIPT" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/update-auth-class.php" +AUTH_UPDATE_RESULT=$(sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "cd $REMOTE_PATH && php update-auth-class.php") +echo "$AUTH_UPDATE_RESULT" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "rm -f $REMOTE_PATH/update-auth-class.php" + +rm "$UPDATE_AUTH_SCRIPT" + +# Step 8: Create and upload JS file +echo -e "${YELLOW}Step 8: Creating and uploading JS file...${NC}" +JS_FILE=$(mktemp) +cat > "$JS_FILE" << 'EOJS' +jQuery(document).ready(function($) { + $('#hvac-zoho-test-connection').on('click', function(e) { + e.preventDefault(); + + var $button = $(this); + var $result = $('#hvac-zoho-test-connection-result'); + + $button.prop('disabled', true); + $result.html('

Testing connection...

'); + + $.ajax({ + url: hvac_zoho_admin.ajax_url, + type: 'POST', + data: { + action: 'hvac_zoho_test_connection', + nonce: hvac_zoho_admin.nonce + }, + success: function(response) { + $button.prop('disabled', false); + $result.empty(); + + if (response.success) { + var successHtml = '
'; + successHtml += '

' + response.data.message + '

'; + + if (response.data.modules) { + successHtml += '

' + response.data.modules + '

'; + } + + successHtml += '
'; + + $result.html(successHtml); + } else { + $result.html('

Connection test failed. Please check the logs.

'); + } + }, + error: function(response) { + $button.prop('disabled', false); + $result.empty(); + + // Create detailed error display + var errorHtml = '
'; + errorHtml += '

' + (response.data ? response.data.message : 'Connection failed') + ': ' + + (response.data ? response.data.error : 'Unknown error') + '

'; + + // Add error code if available + if (response.data && response.data.code) { + errorHtml += '

Error Code: ' + response.data.code + '

'; + } + + // Add debugging info + errorHtml += '
'; + // Add details if available + if (response.data && response.data.details) { + errorHtml += '

Details: ' + response.data.details + '

'; + } + + // Add raw response data if available + if (response.data && response.data.raw) { + try { + errorHtml += '
'; + errorHtml += 'Raw Response Data (click to expand)'; + errorHtml += '
' + JSON.stringify(JSON.parse(response.data.raw), null, 2) + '
'; + errorHtml += '
'; + } catch (e) { + errorHtml += '

Raw response data is available but could not be parsed: ' + e.message + '

'; + } + } + + errorHtml += '
'; // Close debug info div + errorHtml += '
'; // Close notice div + + $result.html(errorHtml); + } + }); + }); +}); +EOJS + +sshpass -p "$REMOTE_PASS" scp -o StrictHostKeyChecking=no "$JS_FILE" "$REMOTE_USER@$REMOTE_HOST:$PLUGINS_PATH/$MAIN_PLUGIN/assets/js/zoho-admin.js" + +if [ $? -ne 0 ]; then + echo -e "${RED}Error: Failed to upload JS file. Aborting deployment.${NC}" + rm "$JS_FILE" + exit 1 +fi + +rm "$JS_FILE" +echo -e "${GREEN}JS file uploaded successfully.${NC}" + +# Step 9: Clear WordPress cache +echo -e "${YELLOW}Step 9: Clearing WordPress cache...${NC}" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "cd $REMOTE_PATH && wp cache flush" + +# Summary +echo -e "${GREEN}=== Zoho CRM Integration Fix Deployed Successfully\! ===${NC}" +echo -e "${YELLOW}The following steps were completed:${NC}" +echo -e "1. Cleaned up duplicate HVAC plugins" +echo -e "2. Created required directories" +echo -e "3. Added environment variable loading in zoho-config.php" +echo -e "4. Enhanced error reporting in class-zoho-admin.php" +echo -e "5. Added getter methods in class-zoho-crm-auth.php" +echo -e "6. Created a diagnostics tool for troubleshooting" +echo -e "7. Added debug styling to CSS" +echo -e "8. Enhanced error display in JS" +echo -e "9. Cleared WordPress cache" + +echo -e "${YELLOW}You can now test the Zoho CRM integration in the WordPress admin panel.${NC}" +echo -e "${YELLOW}Go to Events > Zoho CRM Sync and click the 'Test Connection' button.${NC}" +echo -e "${YELLOW}If issues persist, run the diagnostics tool at:${NC}" +echo -e "${YELLOW}https://wordpress-974670-5399585.cloudwaysapps.com/wp-content/plugins/hvac-community-events/includes/zoho/diagnostics.php?run_diagnostics=true${NC}" + +exit 0 diff --git a/wordpress-dev/bin/deploy-zoho-fixes.sh b/wordpress-dev/bin/deploy-zoho-fixes.sh index 6ae5f9be..ce6136a9 100755 --- a/wordpress-dev/bin/deploy-zoho-fixes.sh +++ b/wordpress-dev/bin/deploy-zoho-fixes.sh @@ -1,24 +1,15 @@ #!/bin/bash - +# # Deploy Zoho CRM integration fixes to staging server -# This script deploys only the Zoho-related files to fix the CRM integration - -# Load environment variables -source "$(dirname "$0")/../.env" - -# Check if environment variables are loaded -if [ -z "$UPSKILL_STAGING_IP" ] || [ -z "$UPSKILL_STAGING_SSH_USER" ]; then - echo "Error: Missing required environment variables" - echo "Please ensure .env file exists and contains UPSKILL_STAGING_IP and UPSKILL_STAGING_SSH_USER" - exit 1 -fi +# This script uploads the modified PHP files and applies the changes +# # Set variables -REMOTE_HOST="${UPSKILL_STAGING_IP}" -REMOTE_USER="${UPSKILL_STAGING_SSH_USER}" -REMOTE_PASS="${UPSKILL_STAGING_PASS}" -REMOTE_PATH="/home/974670.cloudwaysapps.com/uberrxmprk/public_html" -PLUGIN_PATH="${REMOTE_PATH}/wp-content/plugins/hvac-community-events" +STAGING_HOST="wordpress-974670-5399585.cloudwaysapps.com" +STAGING_USER="uberrxmprk" # Default Cloudways username +REMOTE_DIR="/home/974670.cloudwaysapps.com/uberrxmprk/public_html" +PLUGIN_DIR="/wp-content/plugins/hvac-community-events" +PLUGIN_PATH="${REMOTE_DIR}${PLUGIN_DIR}" # Colors for output GREEN='\033[0;32m' @@ -26,286 +17,1245 @@ RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' # No Color -echo -e "${YELLOW}=== Deploying Zoho CRM Integration Fixes ===${NC}" -echo -e "${YELLOW}Target: ${REMOTE_USER}@${REMOTE_HOST}:${PLUGIN_PATH}${NC}" +# Make script executable +chmod +x $0 -# Create backup of current Zoho files -echo -e "${YELLOW}Creating backup of current Zoho files...${NC}" -BACKUP_CMD="mkdir -p \"${PLUGIN_PATH}/includes/zoho-backup\" && -cp -r \"${PLUGIN_PATH}/includes/zoho\" \"${PLUGIN_PATH}/includes/zoho-backup/zoho-$(date +%Y%m%d%H%M%S)\" && -cp -r \"${PLUGIN_PATH}/includes/admin/class-zoho-admin.php\" \"${PLUGIN_PATH}/includes/zoho-backup/class-zoho-admin-$(date +%Y%m%d%H%M%S).php\" && -cp -r \"${PLUGIN_PATH}/assets/js/zoho-admin.js\" \"${PLUGIN_PATH}/includes/zoho-backup/zoho-admin-$(date +%Y%m%d%H%M%S).js\" && -cp -r \"${PLUGIN_PATH}/assets/css/zoho-admin.css\" \"${PLUGIN_PATH}/includes/zoho-backup/zoho-admin-$(date +%Y%m%d%H%M%S).css\"" - -sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "$BACKUP_CMD" +echo -e "${YELLOW}========================================" +echo -e "Deploying Zoho CRM integration fixes" +echo -e "========================================${NC}" +# Check if SSH key authentication is set up +echo -e "${YELLOW}Checking SSH connection...${NC}" +ssh -o BatchMode=yes -o ConnectTimeout=5 ${STAGING_USER}@${STAGING_HOST} "echo Connected" >/dev/null 2>&1 if [ $? -ne 0 ]; then - echo -e "${RED}Error: Failed to create backup. Aborting.${NC}" + echo -e "${RED}Error: Cannot connect to staging server using SSH key authentication." + echo -e "Please make sure your SSH key is added to the staging server.${NC}" + echo -e "You may need to run: ssh-copy-id ${STAGING_USER}@${STAGING_HOST}" + echo -e "Or use password authentication by modifying this script.${NC}" exit 1 fi -echo -e "${GREEN}Backup created successfully.${NC}" -# Deploy Zoho integration files -echo -e "${YELLOW}Deploying Zoho CRM integration files...${NC}" +echo -e "${GREEN}SSH connection successful.${NC}" -# Create temporary directory for the files to deploy +# Create backup of original files +echo -e "${YELLOW}1. Creating backups of original files${NC}" + +BACKUP_CMD="mkdir -p ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d) && \ +cp ${PLUGIN_PATH}/includes/zoho/class-zoho-crm-auth.php ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d)/class-zoho-crm-auth.php.bak && \ +cp ${PLUGIN_PATH}/includes/admin/class-zoho-admin.php ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d)/class-zoho-admin.php.bak && \ +echo 'Backups created successfully'" + +ssh ${STAGING_USER}@${STAGING_HOST} "${BACKUP_CMD}" + +if [ $? -ne 0 ]; then + echo -e "${RED}Error: Failed to create backups on the server${NC}" + exit 1 +fi + +echo -e "${GREEN}Backups created successfully.${NC}" + +# Create local files with fixes +echo -e "${YELLOW}2. Creating fixed PHP files locally${NC}" + +# Create a temporary directory for our fixes TMP_DIR=$(mktemp -d) -mkdir -p "${TMP_DIR}/zoho" -mkdir -p "${TMP_DIR}/admin" -mkdir -p "${TMP_DIR}/assets/js" -mkdir -p "${TMP_DIR}/assets/css" +mkdir -p ${TMP_DIR}/includes/zoho +mkdir -p ${TMP_DIR}/includes/admin -# Copy the files we want to deploy to the temporary directory -cp "$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events/includes/zoho/check-permissions.php" "${TMP_DIR}/zoho/" -cp "$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events/includes/zoho/diagnostics.php" "${TMP_DIR}/zoho/" -cp "$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events/includes/zoho/class-zoho-crm-auth.php" "${TMP_DIR}/zoho/" -cp "$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events/includes/admin/class-zoho-admin.php" "${TMP_DIR}/admin/" -cp "$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events/assets/js/zoho-admin.js" "${TMP_DIR}/assets/js/" -cp "$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events/assets/css/zoho-admin.css" "${TMP_DIR}/assets/css/" -cp "$(dirname "$0")/check-zoho-env.php" "${TMP_DIR}/" - -# Create deployment script to modify zoho-config.php on the server -cat > "${TMP_DIR}/patch-zoho-config.php" << 'EOF' +# Create the fixed zoho-crm-auth.php file +cat > ${TMP_DIR}/includes/zoho/class-zoho-crm-auth.php << 'EOF' load_env_variables(); + + // Load configuration if available + $config_file = plugin_dir_path(__FILE__) . 'zoho-config.php'; + if (file_exists($config_file)) { + require_once $config_file; + + $this->client_id = defined('ZOHO_CLIENT_ID') ? ZOHO_CLIENT_ID : ''; + $this->client_secret = defined('ZOHO_CLIENT_SECRET') ? ZOHO_CLIENT_SECRET : ''; + $this->refresh_token = defined('ZOHO_REFRESH_TOKEN') ? ZOHO_REFRESH_TOKEN : ''; + $this->redirect_uri = defined('ZOHO_REDIRECT_URI') ? ZOHO_REDIRECT_URI : 'http://localhost:8080/callback'; + } + + // Load stored access token from WordPress options + $this->load_access_token(); + } + + /** + * Load environment variables from .env file + * This helps with local development and staging environments + * + * @return array Array of loaded environment variables + */ + public function load_env_variables() { + $env_vars = array(); + $env_file = ABSPATH . '../.env'; + + if (file_exists($env_file)) { + $this->log_debug('Loading environment variables from .env file'); + + $env_contents = file_get_contents($env_file); + $env_lines = explode("\n", $env_contents); + + foreach ($env_lines as $line) { + $line = trim($line); + + // Skip comments and empty lines + if (empty($line) || strpos($line, '#') === 0) { + continue; + } + + // Parse variable assignments + if (strpos($line, '=') !== false) { + list($key, $value) = explode('=', $line, 2); + $key = trim($key); + $value = trim($value); // Remove quotes if present - if (strpos(\$value, '"') === 0 && strrpos(\$value, '"') === strlen(\$value) - 1) { - \$value = substr(\$value, 1, -1); - } elseif (strpos(\$value, "'") === 0 && strrpos(\$value, "'") === strlen(\$value) - 1) { - \$value = substr(\$value, 1, -1); + if (strpos($value, '"') === 0 && strrpos($value, '"') === strlen($value) - 1) { + $value = substr($value, 1, -1); + } elseif (strpos($value, "'") === 0 && strrpos($value, "'") === strlen($value) - 1) { + $value = substr($value, 1, -1); } - putenv("\$name=\$value"); - \$_ENV[\$name] = \$value; + $env_vars[$key] = $value; + + // Define constants for Zoho configuration + if (strpos($key, 'ZOHO_') === 0 && !defined($key)) { + define($key, $value); + $this->log_debug("Defined $key from .env file"); + } } } + + $zoho_vars_count = 0; + foreach ($env_vars as $key => $value) { + if (strpos($key, 'ZOHO_') === 0) { + $zoho_vars_count++; + } + } + + $this->log_debug("Loaded $zoho_vars_count Zoho-related environment variables"); + } else { + $this->log_debug('No .env file found at: ' . $env_file); + } + + return $env_vars; + } + + /** + * Generate authorization URL for initial setup + */ + public function get_authorization_url() { + $params = array( + 'scope' => defined('ZOHO_SCOPES') ? ZOHO_SCOPES : 'ZohoCRM.settings.all,ZohoCRM.modules.all,ZohoCRM.users.all,ZohoCRM.org.all', + 'client_id' => $this->client_id, + 'response_type' => 'code', + 'access_type' => 'offline', + 'redirect_uri' => $this->redirect_uri, + 'prompt' => 'consent' + ); + + $accounts_url = defined('ZOHO_ACCOUNTS_URL') ? ZOHO_ACCOUNTS_URL : 'https://accounts.zoho.com'; + return $accounts_url . '/oauth/v2/auth?' . http_build_query($params); + } + + /** + * Exchange authorization code for tokens + */ + public function exchange_code_for_tokens($auth_code) { + $accounts_url = defined('ZOHO_ACCOUNTS_URL') ? ZOHO_ACCOUNTS_URL : 'https://accounts.zoho.com'; + $url = $accounts_url . '/oauth/v2/token'; + + $params = array( + 'grant_type' => 'authorization_code', + 'client_id' => $this->client_id, + 'client_secret' => $this->client_secret, + 'redirect_uri' => $this->redirect_uri, + 'code' => $auth_code + ); + + $response = wp_remote_post($url, array( + 'body' => $params, + 'headers' => array( + 'Content-Type' => 'application/x-www-form-urlencoded' + ) + )); + + if (is_wp_error($response)) { + $this->log_error('Failed to exchange code: ' . $response->get_error_message()); + return false; + } + + $body = wp_remote_retrieve_body($response); + $data = json_decode($body, true); + + if (isset($data['access_token']) && isset($data['refresh_token'])) { + $this->access_token = $data['access_token']; + $this->refresh_token = $data['refresh_token']; + $this->token_expiry = time() + $data['expires_in']; + + // Save tokens + $this->save_tokens(); + return true; } - } - return false; -} - -// Try to load environment variables -\$env_loaded = load_env_from_dotenv(); - -// Log directory setup -\$log_dir = dirname(dirname(__FILE__)) . '/logs'; -if (!file_exists(\$log_dir)) { - mkdir(\$log_dir, 0755, true); -} - -// OAuth Client Credentials -// IMPORTANT: You need to fill these values with your Zoho OAuth credentials -define('ZOHO_CLIENT_ID', $client_id); -define('ZOHO_CLIENT_SECRET', $client_secret); -define('ZOHO_REDIRECT_URI', 'https://wordpress-974670-5399585.cloudwaysapps.com/oauth/callback'); - -// API Endpoints -define('ZOHO_ACCOUNTS_URL', 'https://accounts.zoho.com'); -define('ZOHO_API_BASE_URL', 'https://www.zohoapis.com/crm/v2'); - -// Scopes -define('ZOHO_SCOPES', 'ZohoCRM.settings.all,ZohoCRM.modules.all,ZohoCRM.users.all,ZohoCRM.org.all'); - -// Optional - Refresh Token (if already obtained) -define('ZOHO_REFRESH_TOKEN', $refresh_token); - -// Debug Settings - Enhanced for better logging -define('ZOHO_DEBUG_MODE', true); -define('ZOHO_LOG_FILE', \$log_dir . '/zoho-debug.log'); - -// Add diagnostic information to log -if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { - \$timestamp = date('Y-m-d H:i:s'); - \$debug_info = "[\$timestamp] Zoho CRM Configuration loaded\\n"; - \$debug_info .= "[\$timestamp] .env file loaded: " . (\$env_loaded ? 'Yes' : 'No') . "\\n"; - \$debug_info .= "[\$timestamp] Client ID exists: " . (!empty(ZOHO_CLIENT_ID) ? 'Yes' : 'No') . "\\n"; - \$debug_info .= "[\$timestamp] Client ID value: " . (ZOHO_CLIENT_ID ? substr(ZOHO_CLIENT_ID, 0, 5) . '...' : 'EMPTY') . "\\n"; - \$debug_info .= "[\$timestamp] Client Secret exists: " . (!empty(ZOHO_CLIENT_SECRET) ? 'Yes' : 'No') . "\\n"; - \$debug_info .= "[\$timestamp] Client Secret value: " . (ZOHO_CLIENT_SECRET ? substr(ZOHO_CLIENT_SECRET, 0, 5) . '...' : 'EMPTY') . "\\n"; - \$debug_info .= "[\$timestamp] Refresh Token exists: " . (!empty(ZOHO_REFRESH_TOKEN) ? 'Yes' : 'No') . "\\n"; - \$debug_info .= "[\$timestamp] Refresh Token value: " . (ZOHO_REFRESH_TOKEN ? substr(ZOHO_REFRESH_TOKEN, 0, 5) . '...' : 'EMPTY') . "\\n"; - \$debug_info .= "[\$timestamp] Log file path: " . ZOHO_LOG_FILE . "\\n"; - - if (function_exists('get_site_url')) { - \$debug_info .= "[\$timestamp] WordPress site URL: " . get_site_url() . "\\n"; - \$debug_info .= "[\$timestamp] Staging mode: " . (strpos(get_site_url(), 'upskillhvac.com') === false ? 'Yes' : 'No') . "\\n"; - } else { - \$debug_info .= "[\$timestamp] WordPress functions not available\\n"; + + $this->log_error('Invalid token response: ' . $body); + return false; } - // Check for environment variables directly - \$debug_info .= "[\$timestamp] Environment variables:\\n"; - \$debug_info .= "[\$timestamp] - _ENV['ZOHO_CLIENT_ID']: " . (isset(\$_ENV['ZOHO_CLIENT_ID']) ? 'Set' : 'Not set') . "\\n"; - \$debug_info .= "[\$timestamp] - _ENV['ZOHO_CLIENT_SECRET']: " . (isset(\$_ENV['ZOHO_CLIENT_SECRET']) ? 'Set' : 'Not set') . "\\n"; - \$debug_info .= "[\$timestamp] - _ENV['ZOHO_REFRESH_TOKEN']: " . (isset(\$_ENV['ZOHO_REFRESH_TOKEN']) ? 'Set' : 'Not set') . "\\n"; - - // Log configuration details - error_log(\$debug_info, 3, ZOHO_LOG_FILE); -} -EOT; - -// Write the updated file -file_put_contents($config_file, $new_content); -echo "Updated zoho-config.php successfully.\n"; - -// Update wp-config.php to enable diagnostics -$wp_config_file = dirname(__FILE__) . '/../wp-config.php'; -if (file_exists($wp_config_file)) { - $wp_config = file_get_contents($wp_config_file); - - // Check if diagnostic flag already exists - if (strpos($wp_config, 'ZOHO_DIAGNOSTICS_ENABLED') === false) { - // Find the line where custom values should be added - $pattern = "/\/\* Add any custom values between this line and the \"stop editing\" line\. \*\//"; - $replacement = "/* Add any custom values between this line and the \"stop editing\" line. */\n\n/* Enable Zoho CRM Diagnostics */\ndefine('ZOHO_DIAGNOSTICS_ENABLED', true);"; + /** + * Get valid access token (refresh if needed) + */ + public function get_access_token() { + // Check if token is expired or will expire soon (5 mins buffer) + if (!$this->access_token || (time() + 300) >= $this->token_expiry) { + $this->refresh_access_token(); + } - $wp_config = preg_replace($pattern, $replacement, $wp_config); - - // Create backup - $wp_backup = dirname(__FILE__) . '/../wp-config-' . date('YmdHis') . '.php.bak'; - file_put_contents($wp_backup, file_get_contents($wp_config_file)); - - // Write updated config - file_put_contents($wp_config_file, $wp_config); - echo "Updated wp-config.php to enable Zoho diagnostics.\n"; - } else { - echo "ZOHO_DIAGNOSTICS_ENABLED already present in wp-config.php.\n"; + return $this->access_token; + } + + /** + * Refresh access token using refresh token + */ + private function refresh_access_token() { + $accounts_url = defined('ZOHO_ACCOUNTS_URL') ? ZOHO_ACCOUNTS_URL : 'https://accounts.zoho.com'; + $url = $accounts_url . '/oauth/v2/token'; + + $params = array( + 'refresh_token' => $this->refresh_token, + 'client_id' => $this->client_id, + 'client_secret' => $this->client_secret, + 'grant_type' => 'refresh_token' + ); + + $response = wp_remote_post($url, array( + 'body' => $params, + 'headers' => array( + 'Content-Type' => 'application/x-www-form-urlencoded' + ) + )); + + if (is_wp_error($response)) { + $this->log_error('Failed to refresh token: ' . $response->get_error_message()); + return false; + } + + $body = wp_remote_retrieve_body($response); + $data = json_decode($body, true); + + if (isset($data['access_token'])) { + $this->access_token = $data['access_token']; + $this->token_expiry = time() + $data['expires_in']; + + $this->save_access_token(); + + return true; + } + + $this->log_error('Failed to refresh token: ' . $body); + return false; + } + + /** + * Make authenticated API request + */ + public function make_api_request($endpoint, $method = 'GET', $data = null) { + // Check if we're in staging mode + $site_url = get_site_url(); + $is_staging = strpos($site_url, 'upskillhvac.com') === false; + + // In staging mode, only allow read operations, no writes + if ($is_staging && in_array($method, array('POST', 'PUT', 'DELETE', 'PATCH'))) { + $this->log_debug('STAGING MODE: Simulating ' . $method . ' request to ' . $endpoint); + return array( + 'data' => array( + array( + 'code' => 'STAGING_MODE', + 'details' => array( + 'message' => 'Staging mode active. Write operations are disabled.' + ), + 'message' => 'This would have been a ' . $method . ' request to: ' . $endpoint, + 'status' => 'success' + ) + ) + ); + } + + // Debug logging of config status + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $config_status = $this->get_configuration_status(); + $this->log_debug('Configuration status: ' . json_encode($config_status)); + + if (!$config_status['client_id_exists']) { + $this->log_error('Client ID is missing or empty'); + } + + if (!$config_status['client_secret_exists']) { + $this->log_error('Client Secret is missing or empty'); + } + + if (!$config_status['refresh_token_exists']) { + $this->log_error('Refresh Token is missing or empty'); + } + + if ($config_status['token_expired']) { + $this->log_debug('Access token is expired, will attempt to refresh'); + } + } + + $access_token = $this->get_access_token(); + + if (!$access_token) { + $error_message = 'No valid access token available'; + $this->log_error($error_message); + return new WP_Error('no_token', $error_message); + } + + $api_base_url = defined('ZOHO_API_BASE_URL') ? ZOHO_API_BASE_URL : 'https://www.zohoapis.com/crm/v2'; + $url = $api_base_url . $endpoint; + + // Log the request details + $this->log_debug('Making ' . $method . ' request to: ' . $url); + + $args = array( + 'method' => $method, + 'headers' => array( + 'Authorization' => 'Zoho-oauthtoken ' . $access_token, + 'Content-Type' => 'application/json' + ), + 'timeout' => 30 // Increase timeout to 30 seconds for potentially slow responses + ); + + if ($data && in_array($method, array('POST', 'PUT', 'PATCH'))) { + $args['body'] = json_encode($data); + $this->log_debug('Request payload: ' . json_encode($data)); + } + + // Execute the request + $this->log_debug('Executing request to Zoho API'); + $response = wp_remote_request($url, $args); + + // Handle WordPress errors + if (is_wp_error($response)) { + $error_message = 'API request failed: ' . $response->get_error_message(); + $error_data = $response->get_error_data(); + + $this->log_error($error_message); + $this->log_debug('Error details: ' . json_encode($error_data)); + + return $response; + } + + // Get response code and body + $status_code = wp_remote_retrieve_response_code($response); + $headers = wp_remote_retrieve_headers($response); + $body = wp_remote_retrieve_body($response); + + $this->log_debug('Response code: ' . $status_code); + + // Log headers for debugging + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $this->log_debug('Response headers: ' . json_encode($headers->getAll())); + } + + // Handle empty responses + if (empty($body)) { + $error_message = 'Empty response received from Zoho API'; + $this->log_error($error_message); + return array( + 'error' => $error_message, + 'code' => $status_code, + 'details' => 'No response body received' + ); + } + + // Parse the JSON response + $data = json_decode($body, true); + + // Check for JSON parsing errors + if ($data === null && json_last_error() !== JSON_ERROR_NONE) { + $error_message = 'Invalid JSON response: ' . json_last_error_msg(); + $this->log_error($error_message); + $this->log_debug('Raw response: ' . $body); + + return array( + 'error' => $error_message, + 'code' => 'JSON_PARSE_ERROR', + 'details' => 'Raw response: ' . substr($body, 0, 255) . (strlen($body) > 255 ? '...' : '') + ); + } + + // Log response for debugging + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $this->log_debug('API Response: ' . $body); + } + + // Check for API errors + if ($status_code >= 400) { + $error_message = isset($data['message']) ? $data['message'] : 'API error with status code ' . $status_code; + $this->log_error($error_message); + + // Add HTTP error information to the response + $data['http_status'] = $status_code; + $data['error'] = $error_message; + + // Extract more detailed error information if available + if (isset($data['code'])) { + $this->log_debug('Error code: ' . $data['code']); + } + + if (isset($data['details'])) { + $this->log_debug('Error details: ' . json_encode($data['details'])); + } + } + + return $data; + } + + /** + * Save tokens to WordPress options + */ + private function save_tokens() { + update_option('hvac_zoho_refresh_token', $this->refresh_token); + $this->save_access_token(); + } + + /** + * Save access token + */ + private function save_access_token() { + update_option('hvac_zoho_access_token', $this->access_token); + update_option('hvac_zoho_token_expiry', $this->token_expiry); + } + + /** + * Load access token from WordPress options + */ + private function load_access_token() { + $this->access_token = get_option('hvac_zoho_access_token'); + $this->token_expiry = get_option('hvac_zoho_token_expiry', 0); + + // Load refresh token if not set + if (!$this->refresh_token) { + $this->refresh_token = get_option('hvac_zoho_refresh_token'); + } + } + + /** + * Log error messages + */ + private function log_error($message) { + $this->last_error = $message; + + if (defined('ZOHO_LOG_FILE')) { + error_log('[' . date('Y-m-d H:i:s') . '] ERROR: ' . $message . PHP_EOL, 3, ZOHO_LOG_FILE); + } + + // Also log to WordPress debug log if available + if (defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { + error_log('[ZOHO CRM] ' . $message); + } + } + + /** + * Log debug messages + */ + private function log_debug($message) { + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE && defined('ZOHO_LOG_FILE')) { + error_log('[' . date('Y-m-d H:i:s') . '] DEBUG: ' . $message . PHP_EOL, 3, ZOHO_LOG_FILE); + } + + // Also log to WordPress debug log if available + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE && defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { + error_log('[ZOHO CRM DEBUG] ' . $message); + } + } + + /** + * Get the last error message + * + * @return string|null + */ + public function get_last_error() { + return $this->last_error; + } + + /** + * Get client ID (for debugging only) + * + * @return string + */ + public function get_client_id() { + return $this->client_id; + } + + /** + * Check if client secret exists (for debugging only) + * + * @return bool + */ + public function get_client_secret() { + return !empty($this->client_secret); + } + + /** + * Check if refresh token exists (for debugging only) + * + * @return bool + */ + public function get_refresh_token() { + return !empty($this->refresh_token); + } + + /** + * Get configuration status (for debugging) + * + * @return array + */ + public function get_configuration_status() { + return array( + 'client_id_exists' => !empty($this->client_id), + 'client_secret_exists' => !empty($this->client_secret), + 'refresh_token_exists' => !empty($this->refresh_token), + 'access_token_exists' => !empty($this->access_token), + 'token_expired' => $this->token_expiry < time(), + 'config_loaded' => file_exists(plugin_dir_path(__FILE__) . 'zoho-config.php') + ); } -} else { - echo "Warning: wp-config.php not found at expected location.\n"; } - -// Create logs directory if it doesn't exist -$logs_dir = dirname(__FILE__) . '/../wp-content/plugins/hvac-community-events/includes/logs'; -if (!file_exists($logs_dir)) { - mkdir($logs_dir, 0755, true); - echo "Created logs directory: " . $logs_dir . "\n"; -} - -echo "Patching completed successfully.\n"; EOF -# Create logs directory locally for rsync -mkdir -p "$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events/includes/logs" +# Create the enhanced zoho-admin.php file +cat > ${TMP_DIR}/includes/admin/class-zoho-admin.php << 'EOF' + "${TMP_DIR}/run-deploy.sh" << 'EOF' +if (!defined('ABSPATH')) { + exit; +} + +/** + * Zoho CRM Admin Class + */ +class HVAC_Zoho_Admin { + + /** + * Initialize the admin interface + */ + public function __construct() { + add_action('admin_menu', array($this, 'add_admin_menu')); + add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); + add_action('wp_ajax_hvac_zoho_test_connection', array($this, 'test_connection')); + add_action('wp_ajax_hvac_zoho_sync_data', array($this, 'sync_data')); + } + + /** + * Add admin menu + */ + public function add_admin_menu() { + add_submenu_page( + 'hvac-community-events', + 'Zoho CRM Sync', + 'Zoho CRM Sync', + 'manage_options', + 'hvac-zoho-sync', + array($this, 'render_admin_page') + ); + } + + /** + * Enqueue admin scripts + */ + public function enqueue_admin_scripts($hook) { + if ($hook !== 'hvac-community-events_page_hvac-zoho-sync') { + return; + } + + wp_enqueue_script( + 'hvac-zoho-admin', + HVAC_CE_PLUGIN_URL . 'assets/js/zoho-admin.js', + array('jquery'), + HVAC_CE_VERSION, + true + ); + + wp_localize_script('hvac-zoho-admin', 'hvacZoho', array( + 'ajaxUrl' => admin_url('admin-ajax.php'), + 'nonce' => wp_create_nonce('hvac_zoho_nonce') + )); + + wp_enqueue_style( + 'hvac-zoho-admin', + HVAC_CE_PLUGIN_URL . 'assets/css/zoho-admin.css', + array(), + HVAC_CE_VERSION + ); + } + + /** + * Render admin page + */ + public function render_admin_page() { + $config_file = HVAC_CE_PLUGIN_DIR . 'includes/zoho/zoho-config.php'; + $is_configured = file_exists($config_file); + $site_url = get_site_url(); + $is_staging = strpos($site_url, 'upskillhvac.com') === false; + ?> +
+

Zoho CRM Sync

+ + +
+

🔧 STAGING MODE ACTIVE

+

Current site:

+

Staging mode is active. Data sync will be simulated only. No actual data will be sent to Zoho CRM.

+

Production sync is only enabled on upskillhvac.com

+
+ + + +
+

Zoho CRM is not configured. Please complete the OAuth setup first.

+

Run: ./bin/zoho-setup-complete.sh

+
+ +
+

Connection Status

+ +
+
+ +
+

Data Sync

+ +
+

Events → Campaigns

+

Sync events from The Events Calendar to Zoho CRM Campaigns

+ +
+
+ +
+

Users → Contacts

+

Sync trainers and attendees to Zoho CRM Contacts

+ +
+
+ +
+

Purchases → Invoices

+

Sync ticket purchases to Zoho CRM Invoices

+ +
+
+
+ +
+

Sync Settings

+
+ +

+ +

+ +
+
+ +
+ get_configuration_status(); + + // Check for essential configuration + if (!$config_status['client_id_exists'] || !$config_status['client_secret_exists'] || !$config_status['refresh_token_exists']) { + // Detailed error about missing configuration + $missing = array(); + if (!$config_status['client_id_exists']) $missing[] = 'Client ID'; + if (!$config_status['client_secret_exists']) $missing[] = 'Client Secret'; + if (!$config_status['refresh_token_exists']) $missing[] = 'Refresh Token'; + + HVAC_Logger::error('Configuration incomplete', 'ZOHO_TEST', array( + 'missing_items' => $missing, + 'config_status' => $config_status + )); + + // Check if .env file exists and has Zoho variables + $env_file = ABSPATH . '../.env'; + $env_info = array( + 'env_file_exists' => file_exists($env_file), + 'env_file_path' => $env_file + ); + + if ($env_info['env_file_exists']) { + $env_contents = file_get_contents($env_file); + $env_info['has_zoho_vars'] = (strpos($env_contents, 'ZOHO_') !== false); + $env_info['file_size'] = filesize($env_file); + $env_info['file_perms'] = substr(sprintf('%o', fileperms($env_file)), -4); + } + + HVAC_Logger::info('Environment file status', 'ZOHO_TEST', $env_info); + + wp_send_json_error(array( + 'message' => 'Zoho CRM configuration is incomplete', + 'missing' => $missing, + 'config_status' => $config_status, + 'env_info' => $env_info, + 'fix_suggestions' => array( + 'Check if .env file contains the necessary Zoho variables', + 'Ensure zoho-config.php file is properly created with required constants', + 'Try running the setup script: ./bin/zoho-setup-complete.sh', + 'Verify environment variables are properly loaded' + ) + )); + return; + } + + // Debug connection parameters + HVAC_Logger::info('Checking Zoho configuration', 'ZOHO_TEST', array( + 'client_id_exists' => !empty($auth->get_client_id()), + 'client_secret_exists' => !empty($auth->get_client_secret()), + 'refresh_token_exists' => !empty($auth->get_refresh_token()), + 'config_file' => plugin_dir_path(__FILE__) . '../zoho/zoho-config.php', + 'config_file_exists' => file_exists(plugin_dir_path(__FILE__) . '../zoho/zoho-config.php') + )); + + // Test API call + $response = $auth->make_api_request('/settings/modules', 'GET'); + + // Detailed logging of the response + if (is_wp_error($response)) { + $error_data = array( + 'error_message' => $response->get_error_message(), + 'error_code' => $response->get_error_code(), + 'error_data' => $response->get_error_data() + ); + + HVAC_Logger::error('WP Error in API request', 'ZOHO_TEST', $error_data); + + // Check for common error patterns + $error_message = $response->get_error_message(); + $suggestions = array(); + + if (strpos($error_message, 'cURL error 6') !== false) { + $suggestions[] = 'Could not resolve host: Check your internet connection or DNS configuration'; + $suggestions[] = 'Verify that ZOHO_API_BASE_URL is correctly defined'; + } else if (strpos($error_message, 'cURL error 28') !== false) { + $suggestions[] = 'Connection timed out: The server took too long to respond'; + $suggestions[] = 'Check your firewall settings or network connectivity'; + } else if (strpos($error_message, '401') !== false) { + $suggestions[] = 'Authentication failed: Check your client credentials'; + $suggestions[] = 'Try refreshing your tokens manually using the refresh token'; + } + + wp_send_json_error(array( + 'message' => 'Connection failed - WordPress Error', + 'error' => $response->get_error_message(), + 'details' => $error_data, + 'suggestions' => $suggestions + )); + return; + } + + if ($response && !isset($response['error'])) { + $success_data = array( + 'modules_count' => isset($response['modules']) ? count($response['modules']) : 0 + ); + + if (isset($response['modules']) && is_array($response['modules'])) { + $modules_list = array(); + foreach ($response['modules'] as $module) { + if (isset($module['api_name'])) { + $modules_list[] = $module['api_name']; + } + } + $success_data['available_modules'] = $modules_list; + } + + HVAC_Logger::info('Connection successful', 'ZOHO_TEST', $success_data); + + wp_send_json_success(array( + 'message' => 'Connection successful!', + 'modules' => isset($response['modules']) ? count($response['modules']) . ' modules available' : 'No modules found', + 'modules_list' => isset($success_data['available_modules']) ? $success_data['available_modules'] : array(), + 'status' => 'Zoho CRM is properly configured and responding' + )); + } else { + $error_message = isset($response['error']) ? $response['error'] : 'Unknown error'; + $error_code = isset($response['code']) ? $response['code'] : ''; + $error_details = isset($response['details']) ? $response['details'] : ''; + + // Extract more detailed error information if available + if (isset($response['data']) && is_array($response['data']) && !empty($response['data'])) { + $first_error = $response['data'][0]; + $error_code = isset($first_error['code']) ? $first_error['code'] : $error_code; + $error_message = isset($first_error['message']) ? $first_error['message'] : $error_message; + if (isset($first_error['details']) && is_array($first_error['details'])) { + $error_details = json_encode($first_error['details']); + } + } + + $error_data = array( + 'error' => $error_message, + 'code' => $error_code, + 'details' => $error_details, + 'full_response' => $response + ); + + HVAC_Logger::error('Connection failed', 'ZOHO_TEST', $error_data); + + // Generate helpful suggestions based on error + $suggestions = array(); + + if (strpos($error_message, 'invalid_client') !== false) { + $suggestions[] = 'Client credentials are invalid. Verify Client ID and Client Secret'; + $suggestions[] = 'Ensure the OAuth app in Zoho is properly configured'; + } else if (strpos($error_message, 'invalid_code') !== false) { + $suggestions[] = 'Authorization code is invalid or expired'; + $suggestions[] = 'Re-authorize the application to get a new code'; + } else if (strpos($error_message, 'invalid_token') !== false) { + $suggestions[] = 'Access token is invalid or expired'; + $suggestions[] = 'Check refresh token and try to get a new access token'; + } + + wp_send_json_error(array( + 'message' => 'Connection failed', + 'error' => $error_message, + 'code' => $error_code, + 'details' => $error_details, + 'raw' => json_encode($response), + 'suggestions' => $suggestions + )); + } + } catch (Exception $e) { + $exception_data = array( + 'exception' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'trace' => $e->getTraceAsString() + ); + + HVAC_Logger::error('Exception in Zoho connection test', 'ZOHO_TEST', $exception_data); + + wp_send_json_error(array( + 'message' => 'Connection failed due to exception', + 'error' => $e->getMessage(), + 'file' => $e->getFile() . ':' . $e->getLine(), + 'trace' => $e->getTraceAsString(), + 'suggestions' => array( + 'Check PHP error logs for more details', + 'Verify that all required PHP extensions are enabled', + 'Ensure the Zoho API endpoints are accessible from your server' + ) + )); + } + } + + /** + * Sync data to Zoho + */ + public function sync_data() { + check_ajax_referer('hvac_zoho_nonce', 'nonce'); + + if (!current_user_can('manage_options')) { + wp_die('Unauthorized'); + } + + $type = sanitize_text_field($_POST['type']); + + try { + require_once HVAC_CE_PLUGIN_DIR . 'includes/zoho/class-zoho-sync.php'; + $sync = new HVAC_Zoho_Sync(); + + switch ($type) { + case 'events': + $result = $sync->sync_events(); + break; + case 'users': + $result = $sync->sync_users(); + break; + case 'purchases': + $result = $sync->sync_purchases(); + break; + default: + throw new Exception('Invalid sync type'); + } + + wp_send_json_success($result); + } catch (Exception $e) { + wp_send_json_error(array( + 'message' => 'Sync failed', + 'error' => $e->getMessage() + )); + } + } +} +EOF + +# Create check-zoho-env.php for diagnostic purposes +cat > ${TMP_DIR}/check-zoho-env.php << 'EOF' + 0) { + echo "Variables: " . implode(', ', $zoho_vars) . "\n"; + } + + break; + } +} + +if (!$env_found) { + echo "WARNING: No .env file found in any standard location.\n"; +} + +// Check for zoho-config.php +$config_file = dirname(__FILE__) . '/includes/zoho/zoho-config.php'; +echo "\nChecking for zoho-config.php at: " . $config_file . "\n"; + +if (file_exists($config_file)) { + echo "FOUND zoho-config.php at: " . $config_file . "\n"; + + // Check if we can require the file + try { + require_once($config_file); + echo "Successfully included zoho-config.php\n"; + + // Check if essential constants are defined + $required_constants = [ + 'ZOHO_CLIENT_ID', + 'ZOHO_CLIENT_SECRET', + 'ZOHO_REFRESH_TOKEN', + ]; + + $missing_constants = []; + foreach ($required_constants as $constant) { + if (!defined($constant) || empty(constant($constant))) { + $missing_constants[] = $constant; + } + } + + if (count($missing_constants) > 0) { + echo "WARNING: The following required constants are missing or empty: " . implode(', ', $missing_constants) . "\n"; + } else { + echo "All required Zoho constants are defined.\n"; + } + + } catch (Exception $e) { + echo "ERROR: Could not include zoho-config.php: " . $e->getMessage() . "\n"; + } +} else { + echo "WARNING: zoho-config.php not found.\n"; +} + +// Check if the auth class is available +$auth_file = dirname(__FILE__) . '/includes/zoho/class-zoho-crm-auth.php'; +echo "\nChecking for class-zoho-crm-auth.php at: " . $auth_file . "\n"; + +if (file_exists($auth_file)) { + echo "FOUND class-zoho-crm-auth.php at: " . $auth_file . "\n"; + + // Check if load_env_variables method exists + $file_contents = file_get_contents($auth_file); + if (strpos($file_contents, 'load_env_variables') !== false) { + echo "load_env_variables method exists in auth class\n"; + } else { + echo "WARNING: load_env_variables method not found in auth class\n"; + } + + // Try to instantiate the class + try { + require_once($auth_file); + if (class_exists('HVAC_Zoho_CRM_Auth')) { + $auth = new HVAC_Zoho_CRM_Auth(); + echo "Successfully instantiated HVAC_Zoho_CRM_Auth class\n"; + + // Check configuration status + $status = $auth->get_configuration_status(); + echo "\nConfiguration status:\n"; + foreach ($status as $key => $value) { + echo "- " . $key . ": " . ($value ? 'Yes' : 'No') . "\n"; + } + } else { + echo "ERROR: HVAC_Zoho_CRM_Auth class not found after including file\n"; + } + } catch (Exception $e) { + echo "ERROR: Could not instantiate HVAC_Zoho_CRM_Auth: " . $e->getMessage() . "\n"; + } +} else { + echo "WARNING: class-zoho-crm-auth.php not found.\n"; +} + +// Check WordPress options +echo "\nChecking WordPress options for Zoho data:\n"; +$options = [ + 'hvac_zoho_access_token' => get_option('hvac_zoho_access_token'), + 'hvac_zoho_token_expiry' => get_option('hvac_zoho_token_expiry'), + 'hvac_zoho_refresh_token' => get_option('hvac_zoho_refresh_token'), +]; + +foreach ($options as $key => $value) { + echo "- " . $key . ": " . (!empty($value) ? 'Set (length: ' . strlen($value) . ')' : 'Not set') . "\n"; +} + +// Check log file +$log_dir = dirname(__FILE__) . '/includes/logs'; +$log_file = $log_dir . '/zoho-debug.log'; + +echo "\nChecking for log directory at: " . $log_dir . "\n"; +if (file_exists($log_dir)) { + echo "FOUND log directory at: " . $log_dir . "\n"; + + echo "Checking for log file at: " . $log_file . "\n"; + if (file_exists($log_file)) { + echo "FOUND log file at: " . $log_file . "\n"; + echo "Log file size: " . filesize($log_file) . " bytes\n"; + echo "Last few log entries:\n"; + + // Display last 10 lines of the log file + $log_contents = file_get_contents($log_file); + $log_lines = explode("\n", $log_contents); + $last_lines = array_slice($log_lines, -10); + foreach ($last_lines as $line) { + echo $line . "\n"; + } + } else { + echo "WARNING: Log file not found. This means no logging has occurred yet.\n"; + } +} else { + echo "WARNING: Log directory not found. Creating directory...\n"; + if (mkdir($log_dir, 0755, true)) { + echo "Successfully created log directory.\n"; + } else { + echo "ERROR: Could not create log directory. Check permissions.\n"; + } +} + +echo "\n=== Environment Check Complete ===\n"; +echo "If you continue to experience issues, please share this output with support.\n"; +EOF + +# Create the deployment script +cat > ${TMP_DIR}/deploy.sh << 'EOF' #!/bin/bash +# Deploy Zoho CRM integration fixes + # Copy files to their correct locations -cp zoho/* /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/includes/zoho/ -cp admin/* /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/includes/admin/ -cp assets/js/* /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/assets/js/ -cp assets/css/* /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/assets/css/ -cp check-zoho-env.php /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/ +echo "Copying class-zoho-crm-auth.php..." +cp -f includes/zoho/class-zoho-crm-auth.php ${PLUGIN_PATH}/includes/zoho/ -# Run the config patcher -php patch-zoho-config.php +echo "Copying class-zoho-admin.php..." +cp -f includes/admin/class-zoho-admin.php ${PLUGIN_PATH}/includes/admin/ -# Set permissions -chmod 755 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/includes/zoho/check-permissions.php -chmod 755 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/includes/zoho/diagnostics.php -chmod 644 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/includes/zoho/class-zoho-crm-auth.php -chmod 644 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/includes/admin/class-zoho-admin.php -chmod 644 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/assets/js/zoho-admin.js -chmod 644 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/assets/css/zoho-admin.css -chmod 755 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/wp-content/plugins/hvac-community-events/check-zoho-env.php +echo "Copying check-zoho-env.php..." +cp -f check-zoho-env.php ${PLUGIN_PATH}/ -# Clear cache -wp cache flush --path=/home/974670.cloudwaysapps.com/uberrxmprk/public_html +# Create logs directory if it doesn't exist +echo "Creating logs directory if needed..." +mkdir -p ${PLUGIN_PATH}/includes/logs +chmod 755 ${PLUGIN_PATH}/includes/logs + +# Set proper permissions +echo "Setting file permissions..." +chmod 644 ${PLUGIN_PATH}/includes/zoho/class-zoho-crm-auth.php +chmod 644 ${PLUGIN_PATH}/includes/admin/class-zoho-admin.php +chmod 755 ${PLUGIN_PATH}/check-zoho-env.php + +# Create logs directory if it doesn't exist +mkdir -p ${PLUGIN_PATH}/includes/logs +chmod 755 ${PLUGIN_PATH}/includes/logs + +echo "Clearing WordPress cache..." +wp cache flush --path=${REMOTE_DIR} 2>/dev/null || echo "Cache flush failed, but continuing..." echo "Deployment completed successfully!" EOF -chmod +x "${TMP_DIR}/run-deploy.sh" +chmod +x ${TMP_DIR}/deploy.sh -# Upload the files -echo -e "${YELLOW}Uploading files to staging server...${NC}" -sshpass -p "$REMOTE_PASS" scp -r -o StrictHostKeyChecking=no "${TMP_DIR}/"* "$REMOTE_USER@$REMOTE_HOST:~/" +echo -e "${YELLOW}3. Uploading files to staging server${NC}" -if [ $? -ne 0 ]; then - echo -e "${RED}Error: Failed to upload files. Aborting.${NC}" - rm -rf "${TMP_DIR}" +# Upload files to staging server +scp -r ${TMP_DIR}/* ${STAGING_USER}@${STAGING_HOST}:~/ || { + echo -e "${RED}Error: Failed to upload files to staging server${NC}" + rm -rf ${TMP_DIR} exit 1 -fi +} -# Execute the deployment script on the server -echo -e "${YELLOW}Executing deployment script on server...${NC}" -sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "chmod +x ~/run-deploy.sh && ~/run-deploy.sh" +echo -e "${GREEN}Files uploaded successfully.${NC}" -if [ $? -ne 0 ]; then - echo -e "${RED}Error: Deployment script failed. Check server logs for details.${NC}" - rm -rf "${TMP_DIR}" +# Execute deployment script on server +echo -e "${YELLOW}4. Executing deployment script on staging server${NC}" +ssh ${STAGING_USER}@${STAGING_HOST} "cd ~/ && PLUGIN_PATH=${PLUGIN_PATH} bash ./deploy.sh" || { + echo -e "${RED}Error: Failed to execute deployment script${NC}" + rm -rf ${TMP_DIR} exit 1 -fi +} -# Clean up -rm -rf "${TMP_DIR}" +# Clean up temporary files +echo -e "${YELLOW}5. Cleaning up temporary files${NC}" +rm -rf ${TMP_DIR} +ssh ${STAGING_USER}@${STAGING_HOST} "rm -rf ~/includes ~/check-zoho-env.php ~/deploy.sh" -echo -e "${GREEN}=== Zoho CRM integration fixes deployed successfully! ===${NC}" -echo -e "${YELLOW}You can now test the connection in the WordPress admin panel.${NC}" -echo -e "${YELLOW}If issues persist, check the logs at: ${PLUGIN_PATH}/includes/logs/zoho-debug.log${NC}" -echo -e "${YELLOW}Or run the diagnostic tool at: ${REMOTE_PATH}/wp-content/plugins/hvac-community-events/includes/zoho/diagnostics.php?run_diagnostics=true${NC}" +echo -e "${GREEN}========================================" +echo -e "Zoho CRM integration fixes deployed successfully!" +echo -e "========================================${NC}" +echo -e "${YELLOW}To test the connection:${NC}" +echo -e "1. Log in to the WordPress admin panel" +echo -e "2. Navigate to 'HVAC Community Events' > 'Zoho CRM Sync'" +echo -e "3. Click 'Test Connection' to verify the integration" +echo -e "" +echo -e "${YELLOW}If you need to diagnose issues further:${NC}" +echo -e "Access the diagnostic tool at: https://wordpress-974670-5399585.cloudwaysapps.com/wp-content/plugins/hvac-community-events/check-zoho-env.php?run_check=1" +echo -e "" +echo -e "${YELLOW}If you need to restore the original files:${NC}" +echo -e "ssh ${STAGING_USER}@${STAGING_HOST}" +echo -e "cp ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d)/class-zoho-crm-auth.php.bak ${PLUGIN_PATH}/includes/zoho/class-zoho-crm-auth.php" +echo -e "cp ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d)/class-zoho-admin.php.bak ${PLUGIN_PATH}/includes/admin/class-zoho-admin.php" +echo -e "" exit 0 \ No newline at end of file diff --git a/wordpress-dev/bin/deploy-zoho-remote.sh b/wordpress-dev/bin/deploy-zoho-remote.sh new file mode 100755 index 00000000..279db694 --- /dev/null +++ b/wordpress-dev/bin/deploy-zoho-remote.sh @@ -0,0 +1,1383 @@ +#\!/bin/bash + +# Direct remote script creation for Zoho fixes +# This script directly creates the files on the remote server + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Load environment variables +source "$(dirname "$0")/../.env" + +# Check if environment variables are loaded +if [ -z "$UPSKILL_STAGING_IP" ] || [ -z "$UPSKILL_STAGING_SSH_USER" ]; then + echo -e "${RED}Error: Missing required environment variables${NC}" + echo "Please ensure .env file exists and contains UPSKILL_STAGING_IP and UPSKILL_STAGING_SSH_USER" + exit 1 +fi + +# Set variables +REMOTE_HOST="${UPSKILL_STAGING_IP}" +REMOTE_USER="${UPSKILL_STAGING_SSH_USER}" +REMOTE_PASS="${UPSKILL_STAGING_PASS}" +REMOTE_PATH="/home/974670.cloudwaysapps.com/uberrxmprk/public_html" +PLUGIN_PATH="${REMOTE_PATH}/wp-content/plugins/hvac-community-events" + +echo -e "${YELLOW}=== Deploying Zoho CRM Integration Fixes ===${NC}" +echo -e "${YELLOW}Target: ${REMOTE_USER}@${REMOTE_HOST}:${PLUGIN_PATH}${NC}" + +# Create a remote script to make all the changes +echo -e "${YELLOW}Creating remote script to fix Zoho integration...${NC}" + +# Connect to the remote server and create the script +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "cat > $REMOTE_PATH/fix-zoho.php" << 'EOPHP' +get_modules(); + + // Enhanced error handling and detailed response + if (\$response && \!isset(\$response['error'])) { + wp_send_json_success(array( + 'message' => 'Connection successful\!', + 'modules' => isset(\$response['modules']) ? count(\$response['modules']) . ' modules available' : 'No modules found' + )); + } else { + \$error_message = isset(\$response['error']) ? \$response['error'] : 'Unknown error'; + \$error_code = isset(\$response['code']) ? \$response['code'] : ''; + \$error_details = isset(\$response['details']) ? \$response['details'] : ''; + + // Log the error + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + \$log_message = \"[\" . date('Y-m-d H:i:s') . \"] Connection test failed: \$error_message\\n\"; + \$log_message .= \"[\" . date('Y-m-d H:i:s') . \"] Error code: \$error_code\\n\"; + \$log_message .= \"[\" . date('Y-m-d H:i:s') . \"] Details: \$error_details\\n\"; + \$log_message .= \"[\" . date('Y-m-d H:i:s') . \"] Raw response: \" . json_encode(\$response) . \"\\n\"; + + if (defined('ZOHO_LOG_FILE')) { + error_log(\$log_message, 3, ZOHO_LOG_FILE); + } + } + + // Send detailed error data back to frontend + wp_send_json_error(array( + 'message' => 'Connection failed', + 'error' => \$error_message, + 'code' => \$error_code, + 'details' => \$error_details, + 'raw' => json_encode(\$response) + )); + } + }"; + + // Replace in the file + $new_content = preg_replace($pattern, $replacement, $zoho_admin_content, -1, $count); + + if ($count > 0) { + $patched = true; + if (file_put_contents($zoho_admin_path, $new_content)) { + echo "Updated class-zoho-admin.php successfully\n"; + } else { + echo "Failed to update class-zoho-admin.php\n"; + } + } + } + + if (\!$patched) { + // Create a new file + echo "Creating a new class-zoho-admin.php file...\n"; + + $zoho_admin_content = <<<'EOT' + admin_url('admin-ajax.php'), + 'nonce' => wp_create_nonce('hvac_zoho_admin_nonce'), + 'testing_connection' => __('Testing connection...', 'hvac-community-events'), + 'connection_success' => __('Connection successful\!', 'hvac-community-events'), + 'connection_error' => __('Connection failed', 'hvac-community-events') + )); + } + + /** + * Render admin page + */ + public function render_admin_page() { + ?> +
+

+ +
+ + + + + + + + + + + + + + + + +
+ /> +
+ /> +
+ /> +
+ + +
+ +
+ +

+

+ + + +
+ +
+ +

+

+ + get_client_id(); + $client_secret = $zoho_auth->get_client_secret(); + $refresh_token = $zoho_auth->get_refresh_token(); + + if (empty($client_id) || empty($client_secret) || empty($refresh_token)) { + echo '

'; + _e('Zoho CRM credentials are not fully configured. Please check your zoho-config.php file and .env file.', 'hvac-community-events'); + echo '

'; + + if (empty($client_id)) { + echo '

ZOHO_CLIENT_ID is missing or empty.

'; + } + + if (empty($client_secret)) { + echo '

ZOHO_CLIENT_SECRET is missing or empty.

'; + } + + if (empty($refresh_token)) { + echo '

ZOHO_REFRESH_TOKEN is missing or empty.

'; + } + + echo '
'; + } else { + echo '

'; + _e('Zoho CRM credentials are configured.', 'hvac-community-events'); + echo '

'; + } + ?> +
+ get_modules(); + + // Enhanced error handling and detailed response + if ($response && \!isset($response['error'])) { + wp_send_json_success(array( + 'message' => 'Connection successful\!', + 'modules' => isset($response['modules']) ? count($response['modules']) . ' modules available' : 'No modules found' + )); + } else { + $error_message = isset($response['error']) ? $response['error'] : 'Unknown error'; + $error_code = isset($response['code']) ? $response['code'] : ''; + $error_details = isset($response['details']) ? $response['details'] : ''; + + // Log the error + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $log_message = "[" . date('Y-m-d H:i:s') . "] Connection test failed: $error_message\n"; + $log_message .= "[" . date('Y-m-d H:i:s') . "] Error code: $error_code\n"; + $log_message .= "[" . date('Y-m-d H:i:s') . "] Details: $error_details\n"; + $log_message .= "[" . date('Y-m-d H:i:s') . "] Raw response: " . json_encode($response) . "\n"; + + if (defined('ZOHO_LOG_FILE')) { + error_log($log_message, 3, ZOHO_LOG_FILE); + } + } + + // Send detailed error data back to frontend + wp_send_json_error(array( + 'message' => 'Connection failed', + 'error' => $error_message, + 'code' => $error_code, + 'details' => $error_details, + 'raw' => json_encode($response) + )); + } + } +} + +// Initialize the admin class +new HVAC_Zoho_Admin(); +EOT; + + if (file_put_contents($zoho_admin_path, $zoho_admin_content)) { + echo "Created class-zoho-admin.php successfully\n"; + } else { + echo "Failed to create class-zoho-admin.php\n"; + } + } +} else { + echo "class-zoho-admin.php already patched\n"; +} + +// Create or update class-zoho-crm-auth.php +$zoho_auth_path = $plugin_path . '/includes/zoho/class-zoho-crm-auth.php'; +echo "\nUpdating class-zoho-crm-auth.php...\n"; + +// Backup existing file if it exists +if (file_exists($zoho_auth_path)) { + $backup_path = $zoho_auth_path . '.bak.' . date('YmdHis'); + if (copy($zoho_auth_path, $backup_path)) { + echo "Created backup at $backup_path\n"; + } else { + echo "Failed to create backup of class-zoho-crm-auth.php\n"; + } +} + +// Create enhanced class-zoho-crm-auth.php +$zoho_auth_content = <<<'EOT' +refresh_token = defined('ZOHO_REFRESH_TOKEN') ? ZOHO_REFRESH_TOKEN : ''; + $this->client_id = defined('ZOHO_CLIENT_ID') ? ZOHO_CLIENT_ID : ''; + $this->client_secret = defined('ZOHO_CLIENT_SECRET') ? ZOHO_CLIENT_SECRET : ''; + $this->api_base_url = defined('ZOHO_API_BASE_URL') ? ZOHO_API_BASE_URL : ''; + } + + /** + * Get access token + * + * @return string + */ + public function get_access_token() { + // If we already have an access token, return it + if (\!empty($this->access_token)) { + return $this->access_token; + } + + // If we don't have credentials, return false + if (empty($this->refresh_token) || empty($this->client_id) || empty($this->client_secret)) { + // Log error + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $log_message = "[" . date('Y-m-d H:i:s') . "] Missing credentials for token generation\n"; + $log_message .= "[" . date('Y-m-d H:i:s') . "] Refresh token: " . (\!empty($this->refresh_token) ? 'Present' : 'Missing') . "\n"; + $log_message .= "[" . date('Y-m-d H:i:s') . "] Client ID: " . (\!empty($this->client_id) ? 'Present' : 'Missing') . "\n"; + $log_message .= "[" . date('Y-m-d H:i:s') . "] Client Secret: " . (\!empty($this->client_secret) ? 'Present' : 'Missing') . "\n"; + + if (defined('ZOHO_LOG_FILE')) { + error_log($log_message, 3, ZOHO_LOG_FILE); + } + } + + return array( + 'error' => 'Missing credentials', + 'code' => 'missing_credentials', + 'details' => 'Refresh token, client ID, or client secret is missing' + ); + } + + // Get access token using refresh token + $accounts_url = defined('ZOHO_ACCOUNTS_URL') ? ZOHO_ACCOUNTS_URL : 'https://accounts.zoho.com'; + $token_url = $accounts_url . '/oauth/v2/token'; + $token_url .= '?refresh_token=' . urlencode($this->refresh_token); + $token_url .= '&client_id=' . urlencode($this->client_id); + $token_url .= '&client_secret=' . urlencode($this->client_secret); + $token_url .= '&grant_type=refresh_token'; + + $args = array( + 'method' => 'POST', + 'timeout' => 30, + 'redirection' => 5, + 'httpversion' => '1.0', + 'blocking' => true, + 'headers' => array(), + 'body' => array(), + 'cookies' => array() + ); + + // Log token request + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $log_message = "[" . date('Y-m-d H:i:s') . "] Requesting access token\n"; + $log_message .= "[" . date('Y-m-d H:i:s') . "] URL: " . $token_url . "\n"; + + if (defined('ZOHO_LOG_FILE')) { + error_log($log_message, 3, ZOHO_LOG_FILE); + } + } + + $response = wp_remote_post($token_url, $args); + + // Log response + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $log_message = "[" . date('Y-m-d H:i:s') . "] Token response code: " . wp_remote_retrieve_response_code($response) . "\n"; + + if (is_wp_error($response)) { + $log_message .= "[" . date('Y-m-d H:i:s') . "] Token error: " . $response->get_error_message() . "\n"; + } else { + $log_message .= "[" . date('Y-m-d H:i:s') . "] Token response: " . wp_remote_retrieve_body($response) . "\n"; + } + + if (defined('ZOHO_LOG_FILE')) { + error_log($log_message, 3, ZOHO_LOG_FILE); + } + } + + // Check for errors + if (is_wp_error($response)) { + return array( + 'error' => $response->get_error_message(), + 'code' => 'wp_error' + ); + } + + // Parse response + $body = json_decode(wp_remote_retrieve_body($response), true); + + // Check for errors in response + if (isset($body['error'])) { + return array( + 'error' => isset($body['error']) ? $body['error'] : 'Unknown error', + 'code' => isset($body['error']) ? $body['error'] : 'unknown_error', + 'details' => isset($body['error_description']) ? $body['error_description'] : '' + ); + } + + // Set access token and return it + if (isset($body['access_token'])) { + $this->access_token = $body['access_token']; + return $this->access_token; + } + + // If we get here, something went wrong + return array( + 'error' => 'Failed to get access token', + 'code' => 'no_access_token', + 'details' => 'Response did not contain an access token', + 'raw_response' => $body + ); + } + + /** + * Make API request + * + * @param string $endpoint API endpoint + * @param string $method HTTP method + * @param array $data Request data + * @return array|WP_Error + */ + public function make_api_request($endpoint, $method = 'GET', $data = array()) { + // Enhanced error logging + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $log_message = "[" . date('Y-m-d H:i:s') . "] API Request: $method $endpoint\n"; + $log_message .= "[" . date('Y-m-d H:i:s') . "] Data: " . json_encode($data) . "\n"; + + if (defined('ZOHO_LOG_FILE')) { + error_log($log_message, 3, ZOHO_LOG_FILE); + } + } + + // Get access token + $access_token = $this->get_access_token(); + + // Check for errors + if (is_array($access_token) && isset($access_token['error'])) { + return $access_token; + } + + // Build URL + $url = $this->api_base_url . '/' . ltrim($endpoint, '/'); + + // Build args + $args = array( + 'method' => $method, + 'timeout' => 30, + 'redirection' => 5, + 'httpversion' => '1.0', + 'blocking' => true, + 'headers' => array( + 'Authorization' => 'Zoho-oauthtoken ' . $access_token, + 'Content-Type' => 'application/json' + ), + 'body' => '', + 'cookies' => array() + ); + + // Add data to request + if (\!empty($data)) { + if ($method == 'GET') { + $url = add_query_arg($data, $url); + } else { + $args['body'] = json_encode($data); + } + } + + // Make request + $response = wp_remote_request($url, $args); + + // Enhanced error logging + if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) { + $log_message = "[" . date('Y-m-d H:i:s') . "] API Response Code: " . wp_remote_retrieve_response_code($response) . "\n"; + + if (is_wp_error($response)) { + $log_message .= "[" . date('Y-m-d H:i:s') . "] API Error: " . $response->get_error_message() . "\n"; + } else { + $response_body = wp_remote_retrieve_body($response); + $log_message .= "[" . date('Y-m-d H:i:s') . "] API Response Body: " . substr($response_body, 0, 1000) . (strlen($response_body) > 1000 ? '...' : '') . "\n"; + } + + if (defined('ZOHO_LOG_FILE')) { + error_log($log_message, 3, ZOHO_LOG_FILE); + } + } + + // Check for errors + if (is_wp_error($response)) { + return array( + 'error' => $response->get_error_message(), + 'code' => 'wp_error' + ); + } + + // Parse response + $body = json_decode(wp_remote_retrieve_body($response), true); + + // Check response code + $response_code = wp_remote_retrieve_response_code($response); + if ($response_code < 200 || $response_code >= 300) { + return array( + 'error' => isset($body['message']) ? $body['message'] : 'API error', + 'code' => isset($body['code']) ? $body['code'] : $response_code, + 'details' => isset($body['details']) ? $body['details'] : 'Response code: ' . $response_code + ); + } + + return $body; + } + + /** + * Get modules + * + * @return array + */ + public function get_modules() { + return $this->make_api_request('settings/modules'); + } + + /** + * Get records from a module + * + * @param string $module Module name + * @param array $params Query parameters + * @return array + */ + public function get_records($module, $params = array()) { + return $this->make_api_request($module, 'GET', $params); + } + + /** + * Get client ID + * + * @return string + */ + public function get_client_id() { + return $this->client_id; + } + + /** + * Get client secret + * + * @return string + */ + public function get_client_secret() { + return $this->client_secret; + } + + /** + * Get refresh token + * + * @return string + */ + public function get_refresh_token() { + return $this->refresh_token; + } +} +EOT; + +if (file_put_contents($zoho_auth_path, $zoho_auth_content)) { + echo "Created class-zoho-crm-auth.php successfully\n"; +} else { + echo "Failed to create class-zoho-crm-auth.php\n"; +} + +// Create zoho-admin.js file +$zoho_js_path = $plugin_path . '/assets/js/zoho-admin.js'; +echo "\nCreating zoho-admin.js...\n"; + +$zoho_js_content = <<<'EOT' +jQuery(document).ready(function($) { + $('#hvac-zoho-test-connection').on('click', function(e) { + e.preventDefault(); + + var $button = $(this); + var $result = $('#hvac-zoho-test-connection-result'); + + $button.prop('disabled', true); + $result.html('

' + hvac_zoho_admin.testing_connection + '

'); + + $.ajax({ + url: hvac_zoho_admin.ajax_url, + type: 'POST', + data: { + action: 'hvac_zoho_test_connection', + nonce: hvac_zoho_admin.nonce + }, + success: function(response) { + $button.prop('disabled', false); + $result.empty(); + + if (response.success) { + var successHtml = '
'; + successHtml += '

' + response.data.message + '

'; + + if (response.data.modules) { + successHtml += '

' + response.data.modules + '

'; + } + + successHtml += '
'; + + $result.html(successHtml); + } else { + $result.html('

Connection test failed. Please check the logs.

'); + } + }, + error: function(response) { + $button.prop('disabled', false); + $result.empty(); + + // Create detailed error display + var errorHtml = '
'; + errorHtml += '

' + response.data.message + ': ' + response.data.error + '

'; + + // Add error code if available + if (response.data.code) { + errorHtml += '

Error Code: ' + response.data.code + '

'; + } + + // Add debugging info + errorHtml += '
'; + // Add details if available + if (response.data.details) { + errorHtml += '

Details: ' + response.data.details + '

'; + } + + // Add raw response data if available + if (response.data.raw) { + errorHtml += '
'; + errorHtml += 'Raw Response Data (click to expand)'; + errorHtml += '
' + JSON.stringify(JSON.parse(response.data.raw), null, 2) + '
'; + errorHtml += '
'; + } + + errorHtml += '
'; // Close debug info div + errorHtml += '
'; // Close notice div + + $result.html(errorHtml); + } + }); + }); +}); +EOT; + +if (file_put_contents($zoho_js_path, $zoho_js_content)) { + echo "Created zoho-admin.js successfully\n"; +} else { + echo "Failed to create zoho-admin.js\n"; +} + +// Create zoho-admin.css file +$zoho_css_path = $plugin_path . '/assets/css/zoho-admin.css'; +echo "\nCreating zoho-admin.css...\n"; + +$zoho_css_content = <<<'EOT' +/* Zoho Admin Styles */ +.hvac-zoho-debug-info { + margin-top: 15px; + padding: 15px; + background: #f9f9f9; + border: 1px solid #ddd; + border-left: 4px solid #dc3232; +} + +.hvac-zoho-debug-info details summary { + cursor: pointer; + font-weight: bold; + color: #0073aa; + padding: 5px; + background: #f0f0f0; +} + +.hvac-zoho-debug-info pre { + margin: 10px 0; + padding: 10px; + background: #f0f0f0; + border: 1px solid #ddd; + overflow: auto; + max-height: 300px; +} +EOT; + +if (file_put_contents($zoho_css_path, $zoho_css_content)) { + echo "Created zoho-admin.css successfully\n"; +} else { + echo "Failed to create zoho-admin.css\n"; +} + +echo "\n==========================================\n"; +echo "Zoho CRM Integration Fix Completed\n"; +echo "==========================================\n\n"; + +echo "The following files were updated:\n"; +echo "- " . $zoho_config_path . "\n"; +echo "- " . $zoho_admin_path . "\n"; +echo "- " . $zoho_auth_path . "\n"; +echo "- " . $zoho_js_path . "\n"; +echo "- " . $zoho_css_path . "\n"; +echo "- " . $diagnostics_path . "\n"; + +echo "\nYou can now test the connection in the WordPress admin panel:\n"; +echo "Go to Events > Zoho CRM Sync\n"; + +echo "\nIf issues persist, check the logs at:\n"; +echo $plugin_path . "/includes/logs/zoho-debug.log\n"; + +echo "\nOr run the diagnostic tool at:\n"; +echo "https://wordpress-974670-5399585.cloudwaysapps.com/wp-content/plugins/hvac-community-events/includes/zoho/diagnostics.php?run_diagnostics=true\n"; + +// Exit successfully +exit(); +EOPHP + +# Execute the script on the remote server +echo -e "${YELLOW}Running remote script to fix Zoho integration...${NC}" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "php $REMOTE_PATH/fix-zoho.php?run_fix=true" + +# Cleanup +echo -e "${YELLOW}Cleaning up...${NC}" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "rm -f $REMOTE_PATH/fix-zoho.php" + +echo -e "${GREEN}=== Zoho CRM integration fixes deployed successfully\! ===${NC}" +echo -e "${YELLOW}You can now test the connection in the WordPress admin panel.${NC}" +echo -e "${YELLOW}Go to Events > Zoho CRM Sync${NC}" +echo -e "${YELLOW}If issues persist, check the logs at: ${PLUGIN_PATH}/includes/logs/zoho-debug.log${NC}" +echo -e "${YELLOW}Or run the diagnostic tool at: https://wordpress-974670-5399585.cloudwaysapps.com/wp-content/plugins/hvac-community-events/includes/zoho/diagnostics.php?run_diagnostics=true${NC}" + +exit 0 diff --git a/wordpress-dev/bin/deploy-zoho-simple.sh b/wordpress-dev/bin/deploy-zoho-simple.sh new file mode 100755 index 00000000..2b1704af --- /dev/null +++ b/wordpress-dev/bin/deploy-zoho-simple.sh @@ -0,0 +1,285 @@ +#!/bin/bash + +# A simplified version of the Zoho deployment script that uses rsync directly + +# Load environment variables +source "$(dirname "$0")/../.env" + +# Check if environment variables are loaded +if [ -z "$UPSKILL_STAGING_IP" ] || [ -z "$UPSKILL_STAGING_SSH_USER" ]; then + echo "Error: Missing required environment variables" + echo "Please ensure .env file exists and contains UPSKILL_STAGING_IP and UPSKILL_STAGING_SSH_USER" + exit 1 +fi + +# Set variables +REMOTE_HOST="${UPSKILL_STAGING_IP}" +REMOTE_USER="${UPSKILL_STAGING_SSH_USER}" +REMOTE_PASS="${UPSKILL_STAGING_PASS}" +REMOTE_PATH="/home/974670.cloudwaysapps.com/uberrxmprk/public_html" +PLUGIN_PATH="${REMOTE_PATH}/wp-content/plugins/hvac-community-events" + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${YELLOW}=== Deploying Zoho CRM Integration Fixes ===${NC}" +echo -e "${YELLOW}Target: ${REMOTE_USER}@${REMOTE_HOST}:${PLUGIN_PATH}${NC}" + +# Create backup of current Zoho files on the remote server +echo -e "${YELLOW}Creating backup of current Zoho files...${NC}" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "cd $PLUGIN_PATH && cp -r includes/zoho includes/zoho-backup-$(date +%Y%m%d%H%M%S) && cp includes/admin/class-zoho-admin.php includes/zoho-backup-admin-$(date +%Y%m%d%H%M%S).php && cp assets/js/zoho-admin.js includes/zoho-backup-js-$(date +%Y%m%d%H%M%S).js && cp assets/css/zoho-admin.css includes/zoho-backup-css-$(date +%Y%m%d%H%M%S).css" + +# Create local directories for files +SRC_DIR="$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events" +TEMP_DIR=$(mktemp -d) + +# Copy files to deploy +echo -e "${YELLOW}Preparing files for deployment...${NC}" +mkdir -p "$TEMP_DIR/includes/zoho" +mkdir -p "$TEMP_DIR/includes/admin" +mkdir -p "$TEMP_DIR/assets/js" +mkdir -p "$TEMP_DIR/assets/css" + +cp "$SRC_DIR/includes/zoho/class-zoho-crm-auth.php" "$TEMP_DIR/includes/zoho/" +cp "$SRC_DIR/includes/zoho/diagnostics.php" "$TEMP_DIR/includes/zoho/" +cp "$SRC_DIR/includes/zoho/check-permissions.php" "$TEMP_DIR/includes/zoho/" +cp "$SRC_DIR/includes/admin/class-zoho-admin.php" "$TEMP_DIR/includes/admin/" +cp "$SRC_DIR/assets/js/zoho-admin.js" "$TEMP_DIR/assets/js/" +cp "$SRC_DIR/assets/css/zoho-admin.css" "$TEMP_DIR/assets/css/" + +# Deploy with rsync +echo -e "${YELLOW}Deploying files to staging server...${NC}" +sshpass -p "$REMOTE_PASS" rsync -avz --no-perms --no-owner --no-group -e "ssh -o StrictHostKeyChecking=no" "$TEMP_DIR/" "$REMOTE_USER@$REMOTE_HOST:$PLUGIN_PATH/" + +if [ $? -ne 0 ]; then + echo -e "${RED}Error: Failed to deploy files. Aborting.${NC}" + rm -rf "$TEMP_DIR" + exit 1 +fi + +echo -e "${GREEN}Files deployed successfully.${NC}" + +# Create a PHP script to update the zoho-config.php file +cat > "$TEMP_DIR/patch-config.php" << 'EOL' + comprehensive-test-data.php << 'EOL' +prefix . 'hvac_certificates'; +$table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + +if (!$table_exists) { + echo "Certificate table does not exist. Creating it now...\n"; + + if (class_exists('HVAC_Certificate_Installer')) { + $installer = HVAC_Certificate_Installer::instance(); + $installer->create_tables(); + + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + if (!$table_exists) { + die("Failed to create certificate table. Exiting.\n"); + } + + echo "Certificate table created successfully.\n"; + } else { + die("Error: HVAC_Certificate_Installer class not found. Exiting.\n"); + } +} + +// Create certificate storage directory if it doesn't exist +$upload_dir = wp_upload_dir(); +$cert_dir = $upload_dir['basedir'] . '/' . get_option('hvac_certificate_storage_path', 'hvac-certificates'); + +if (!file_exists($cert_dir)) { + echo "Certificate directory does not exist. Creating it now...\n"; + $result = wp_mkdir_p($cert_dir); + if (!$result) { + die("Failed to create certificate directory at: {$cert_dir}\n"); + } + echo "Certificate directory created at: {$cert_dir}\n"; +} + +// Get or create test trainer user +$test_trainer = get_user_by('login', 'test_trainer'); +if (!$test_trainer) { + echo "test_trainer user not found, creating one...\n"; + + $user_id = wp_create_user('test_trainer', wp_generate_password(12, false), 'test_trainer@example.com'); + + if (is_wp_error($user_id)) { + die("Failed to create test_trainer user: " . $user_id->get_error_message() . "\n"); + } + + // Set role and update user meta + $user = new WP_User($user_id); + $user->set_role('hvac_trainer'); + + update_user_meta($user_id, 'first_name', 'Test'); + update_user_meta($user_id, 'last_name', 'Trainer'); + + $test_trainer = get_user_by('ID', $user_id); + echo "Created test_trainer user (ID: {$user_id})\n"; +} else { + echo "Found existing test_trainer user (ID: {$test_trainer->ID})\n"; +} + +$trainer_id = $test_trainer->ID; + +// Create events with a variety of data +$event_data = [ + [ + 'title' => 'Advanced HVAC Troubleshooting', + 'description' => 'Learn advanced techniques for diagnosing and fixing complex HVAC system issues.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+2 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+2 weeks +8 hours')), + 'venue' => 'HVAC Training Center', + 'address' => '123 Main St, New York, NY 10001', + 'price' => 299, + 'attendees' => 20, + 'checkins' => 18, + 'create_certificates' => true + ], + [ + 'title' => 'HVAC Energy Efficiency Workshop', + 'description' => 'Master the latest energy efficiency techniques and technologies in HVAC systems.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+1 month')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+1 month +6 hours')), + 'venue' => 'Green Energy Training Facility', + 'address' => '456 Eco Blvd, Chicago, IL 60601', + 'price' => 349, + 'attendees' => 15, + 'checkins' => 12, + 'create_certificates' => true + ], + [ + 'title' => 'Commercial Refrigeration Systems', + 'description' => 'Comprehensive training on installation and maintenance of commercial refrigeration systems.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+6 weeks')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+6 weeks +16 hours')), // 2-day workshop + 'venue' => 'Industrial Training Complex', + 'address' => '789 Commerce Lane, Dallas, TX 75201', + 'price' => 499, + 'attendees' => 25, + 'checkins' => 22, + 'create_certificates' => true + ], + [ + 'title' => 'Residential HVAC Installation Best Practices', + 'description' => 'Learn industry best practices for residential HVAC installation and customer service.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+2 months')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+2 months +8 hours')), + 'venue' => 'Residential Skills Center', + 'address' => '321 Homestead Road, Atlanta, GA 30301', + 'price' => 249, + 'attendees' => 30, + 'checkins' => 26, + 'create_certificates' => true + ], + [ + 'title' => 'HVAC Controls and Automation', + 'description' => 'Advanced training on modern HVAC control systems, automation, and smart building integration.', + 'start_date' => date('Y-m-d H:i:s', strtotime('+3 months')), + 'end_date' => date('Y-m-d H:i:s', strtotime('+3 months +12 hours')), + 'venue' => 'Smart Technology Institute', + 'address' => '555 Innovation Way, San Francisco, CA 94105', + 'price' => 399, + 'attendees' => 18, + 'checkins' => 15, + 'create_certificates' => true + ] +]; + +// Track created events +$created_event_ids = []; + +// Create test events +foreach ($event_data as $index => $data) { + echo "Creating event: {$data['title']}\n"; + + // Create the event post + $event_args = [ + 'post_title' => $data['title'], + 'post_content' => $data['description'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Main::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $event_id = wp_insert_post($event_args); + + if (is_wp_error($event_id)) { + echo "Failed to create event: " . $event_id->get_error_message() . "\n"; + continue; + } + + // Add event meta + update_post_meta($event_id, '_EventStartDate', $data['start_date']); + update_post_meta($event_id, '_EventEndDate', $data['end_date']); + update_post_meta($event_id, '_EventVenueID', 0); // Default venue + update_post_meta($event_id, '_EventCost', $data['price']); + + // Create or use existing venue + $venue_args = [ + 'post_title' => $data['venue'], + 'post_status' => 'publish', + 'post_type' => Tribe__Events__Venue::POSTTYPE, + 'post_author' => $trainer_id + ]; + + $venue_id = wp_insert_post($venue_args); + + if (!is_wp_error($venue_id)) { + // Add venue meta + update_post_meta($venue_id, '_VenueAddress', $data['address']); + update_post_meta($venue_id, '_VenueCity', explode(', ', $data['address'])[1]); + update_post_meta($venue_id, '_VenueState', explode(' ', explode(', ', $data['address'])[2])[0]); + update_post_meta($venue_id, '_VenueZip', explode(' ', explode(', ', $data['address'])[2])[1]); + + // Link venue to event + update_post_meta($event_id, '_EventVenueID', $venue_id); + } + + // Create PayPal ticket + if (class_exists('Tribe__Tickets_Plus__Commerce__PayPal__Main')) { + $ticket_args = [ + 'post_title' => "Admission - {$data['title']}", + 'post_content' => "Ticket for {$data['title']}", + 'post_status' => 'publish', + 'post_type' => 'tribe_tpp_tickets', + ]; + + $ticket_id = wp_insert_post($ticket_args); + + if (!is_wp_error($ticket_id)) { + // Add ticket meta + update_post_meta($ticket_id, '_tribe_tpp_for_event', $event_id); + update_post_meta($ticket_id, '_tribe_tpp_enabled', 'yes'); + update_post_meta($ticket_id, '_price', $data['price']); + update_post_meta($ticket_id, '_capacity', $data['attendees'] + 10); + update_post_meta($ticket_id, '_stock', $data['attendees'] + 10); + update_post_meta($ticket_id, '_manage_stock', 'yes'); + + // Associate ticket with event + update_post_meta($event_id, '_tribe_default_ticket_provider', 'Tribe__Tickets_Plus__Commerce__PayPal__Main'); + + echo "Created ticket for event: {$event_id}\n"; + + // Generate varied attendee names and emails + $first_names = ['John', 'Sarah', 'Michael', 'Emma', 'David', 'Olivia', 'James', 'Sophia', + 'William', 'Ava', 'Robert', 'Isabella', 'Thomas', 'Mia', 'Daniel', 'Charlotte', + 'Joseph', 'Amelia', 'Christopher', 'Harper', 'Samuel', 'Evelyn', 'Edward', 'Abigail', + 'Anthony', 'Emily', 'Matthew', 'Elizabeth', 'Richard', 'Sofia']; + + $last_names = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Garcia', 'Miller', 'Davis', + 'Rodriguez', 'Martinez', 'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson', + 'Thomas', 'Taylor', 'Moore', 'Jackson', 'Martin', 'Lee', 'Perez', 'Thompson', + 'White', 'Harris', 'Sanchez', 'Clark', 'Ramirez', 'Lewis', 'Robinson']; + + $email_domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'aol.com', + 'icloud.com', 'protonmail.com', 'example.com', 'hvacpro.com', 'techjobs.com']; + + // Create attendees + $attendee_ids = []; + + for ($i = 1; $i <= $data['attendees']; $i++) { + $first_name_index = array_rand($first_names); + $last_name_index = array_rand($last_names); + $domain_index = array_rand($email_domains); + + $attendee_first_name = $first_names[$first_name_index]; + $attendee_last_name = $last_names[$last_name_index]; + $email_domain = $email_domains[$domain_index]; + + // Generate unique email + $attendee_email = strtolower($attendee_first_name . '.' . $attendee_last_name . '.' . rand(100, 999) . '@' . $email_domain); + + // Special email for the first attendee of each event + if ($i === 1) { + $attendee_email = "ben@tealmaker.com"; + $attendee_first_name = "Ben"; + $attendee_last_name = "Tester"; + } + + // Create attendee post + $attendee_args = [ + 'post_title' => "{$attendee_first_name} {$attendee_last_name}", + 'post_content' => '', + 'post_status' => 'publish', + 'post_type' => 'tribe_tpp_attendees', + ]; + + $attendee_id = wp_insert_post($attendee_args); + + if (is_wp_error($attendee_id)) { + echo "Failed to create attendee for event {$event_id}: " . $attendee_id->get_error_message() . "\n"; + continue; + } + + $attendee_ids[] = $attendee_id; + + // Generate a unique order ID + $order_id = 'ORDER-' . $event_id . '-' . $i . '-' . uniqid(); + + // Add attendee meta + $meta_fields = [ + '_tribe_tickets_full_name' => "{$attendee_first_name} {$attendee_last_name}", + '_tribe_tickets_email' => $attendee_email, + '_tribe_tpp_full_name' => "{$attendee_first_name} {$attendee_last_name}", + '_tribe_tpp_email' => $attendee_email, + '_tribe_tpp_event' => $event_id, + '_tribe_tpp_product' => $ticket_id, + '_tribe_tpp_order' => $order_id, + '_tribe_tpp_security_code' => wp_generate_password(10, false), + '_tribe_tickets_order_status' => 'complete', + '_tribe_tpp_attendee_optout' => 'no', + '_tribe_tickets_attendee_user_id' => 0, + ]; + + foreach ($meta_fields as $key => $value) { + update_post_meta($attendee_id, $key, $value); + } + + // Check in some attendees + if ($i <= $data['checkins']) { + update_post_meta($attendee_id, '_tribe_tpp_checkin', 1); + update_post_meta($attendee_id, '_tribe_tpp_checked_in', 1); + update_post_meta($attendee_id, '_tribe_tickets_checkin_status', 1); + update_post_meta($attendee_id, 'check_in', 1); + } + } + + echo "Created {$data['attendees']} attendees for event {$event_id}\n"; + echo "Checked in {$data['checkins']} attendees for event {$event_id}\n"; + + // Update ticket stock and sales counts + update_post_meta($ticket_id, '_tribe_tpp_sold', $data['attendees']); + update_post_meta($ticket_id, '_stock', intval(get_post_meta($ticket_id, '_capacity', true)) - $data['attendees']); + update_post_meta($ticket_id, '_tribe_ticket_sold', $data['attendees']); + + // Update event attendance meta + update_post_meta($event_id, '_tribe_ticket_sold_count', $data['attendees']); + + // Store the created event ID + $created_event_ids[] = $event_id; + + // Generate certificates if requested + if ($data['create_certificates'] && $data['checkins'] > 0) { + echo "Generating certificates for event {$event_id}\n"; + + // Get checked-in attendees for this event + $checked_in_attendees = get_posts([ + 'post_type' => 'tribe_tpp_attendees', + 'meta_query' => [ + 'relation' => 'AND', + [ + 'key' => '_tribe_tpp_event', + 'value' => $event_id, + ], + [ + 'key' => '_tribe_tpp_checkin', + 'value' => 1, + ] + ], + 'posts_per_page' => -1 + ]); + + $certificates_created = 0; + $certificates_revoked = 0; + $certificates_emailed = 0; + + foreach ($checked_in_attendees as $attendee) { + $attendee_id = $attendee->ID; + $attendee_name = get_post_meta($attendee_id, '_tribe_tickets_full_name', true); + + // Skip if a certificate already exists + if ($certificate_manager->certificate_exists($event_id, $attendee_id)) { + echo " - Certificate already exists for attendee {$attendee_name}. Skipping.\n"; + continue; + } + + // Create certificate file path + $year = date('Y'); + $month = date('m'); + $certificate_filename = "certificate-{$event_id}-{$attendee_id}-" . time() . ".pdf"; + $certificate_relative_path = "hvac-certificates/{$year}/{$month}/{$certificate_filename}"; + + // Create year/month directory structure if needed + $year_month_dir = $cert_dir . "/{$year}/{$month}"; + if (!file_exists($year_month_dir)) { + wp_mkdir_p($year_month_dir); + } + + // Create the certificate record + $certificate_id = $certificate_manager->create_certificate( + $event_id, + $attendee_id, + 0, // user_id + $certificate_relative_path, + $trainer_id + ); + + if ($certificate_id) { + $certificates_created++; + + // Create dummy certificate file + $certificate_full_path = $upload_dir['basedir'] . '/' . $certificate_relative_path; + file_put_contents($certificate_full_path, "Placeholder for certificate PDF (Generated for testing)"); + + // For testing, randomly mark some certificates as revoked or emailed + $random = mt_rand(1, 10); + + // Revoke about 10% of certificates + if ($random == 1) { + $certificate_manager->revoke_certificate( + $certificate_id, + $trainer_id, + "Test revocation for certificate testing" + ); + $certificates_revoked++; + } + + // Mark about 70% as emailed + if ($random <= 7) { + $certificate_manager->mark_certificate_emailed($certificate_id); + $certificates_emailed++; + } + } + } + + echo "Created {$certificates_created} certificates for event {$event_id}\n"; + echo "Revoked {$certificates_revoked} certificates\n"; + echo "Marked {$certificates_emailed} certificates as emailed\n"; + } + } + } else { + echo "Event Tickets Plus or PayPal provider not available\n"; + } + + echo "----------------------------\n"; +} + +// Summary +echo "\n=== Test Data Creation Summary ===\n"; +echo "Created " . count($created_event_ids) . " test events\n"; + +// Get certificate statistics +if (class_exists('HVAC_Certificate_Manager')) { + $stats = $certificate_manager->get_certificate_stats(); + + echo "\nCertificate Statistics:\n"; + echo "Total certificates: {$stats['total_certificates']}\n"; + echo "Total events with certificates: {$stats['total_events']}\n"; + echo "Total trainees with certificates: {$stats['total_trainees']}\n"; + echo "Total revoked certificates: {$stats['total_revoked']}\n"; + echo "Total emailed certificates: {$stats['total_emailed']}\n"; +} + +echo "\nTest data creation completed!\n"; +?> +EOL + +# Copy PHP script to server and execute +echo "[1;33mCopying script to server...[0m" +scp comprehensive-test-data.php roodev@146.190.76.204:~/public_html/ + +echo "[1;33mExecuting script on server...[0m" +ssh roodev@146.190.76.204 "cd ~/public_html/ && php comprehensive-test-data.php" + +# Clean up +rm comprehensive-test-data.php +ssh roodev@146.190.76.204 "rm ~/public_html/comprehensive-test-data.php" + +echo "[0;32mComprehensive test data creation completed![0m" +echo "The script has created:" +echo "1. Multiple test events with different dates, venues, and prices" +echo "2. Varied attendee data with realistic names and emails" +echo "3. Check-ins for most attendees" +echo "4. Certificates with varied states (active, revoked, emailed)" +echo "" +echo "You can test the system at:" +echo "- Event listing: https://wordpress-974670-5399585.cloudwaysapps.com/events/" +echo "- Certificate reports: https://wordpress-974670-5399585.cloudwaysapps.com/certificate-reports/" +echo "" +echo "Features to test with this data:" +echo "1. Event filtering and searching" +echo "2. Certificate filtering by event name" +echo "3. Certificate filtering by attendee name/email" +echo "4. Certificate filtering by status (active/revoked)" +echo "5. Certificate email functionality" +echo "6. Certificate download functionality" \ No newline at end of file diff --git a/wordpress-dev/bin/direct-deploy-zoho.sh b/wordpress-dev/bin/direct-deploy-zoho.sh new file mode 100755 index 00000000..473bd93b --- /dev/null +++ b/wordpress-dev/bin/direct-deploy-zoho.sh @@ -0,0 +1,111 @@ +#!/bin/bash + +# A direct deployment script for Zoho CRM integration fixes +# This script runs the patch-zoho.php locally and then uploads the patched files + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${YELLOW}=== Patching Zoho CRM Integration Locally ===${NC}" + +# Run the PHP patcher script +php "$(dirname "$0")/patch-zoho.php" + +if [ $? -ne 0 ]; then + echo -e "${RED}Error: Failed to patch Zoho CRM integration locally. Aborting.${NC}" + exit 1 +fi + +echo -e "${GREEN}Local patching completed successfully.${NC}" + +# Load environment variables +source "$(dirname "$0")/../.env" + +# Check if environment variables are loaded +if [ -z "$UPSKILL_STAGING_IP" ] || [ -z "$UPSKILL_STAGING_SSH_USER" ]; then + echo -e "${RED}Error: Missing required environment variables${NC}" + echo "Please ensure .env file exists and contains UPSKILL_STAGING_IP and UPSKILL_STAGING_SSH_USER" + exit 1 +fi + +# Set variables +REMOTE_HOST="${UPSKILL_STAGING_IP}" +REMOTE_USER="${UPSKILL_STAGING_SSH_USER}" +REMOTE_PASS="${UPSKILL_STAGING_PASS}" +REMOTE_PATH="/home/974670.cloudwaysapps.com/uberrxmprk/public_html" +PLUGIN_PATH="${REMOTE_PATH}/wp-content/plugins/hvac-community-events" +SRC_DIR="$(dirname "$0")/../wordpress/wp-content/plugins/hvac-community-events" + +echo -e "${YELLOW}=== Deploying Patched Files to Staging ===${NC}" +echo -e "${YELLOW}Target: ${REMOTE_USER}@${REMOTE_HOST}:${PLUGIN_PATH}${NC}" + +# Create backup of current Zoho files on the remote server +echo -e "${YELLOW}Creating backup of current Zoho files...${NC}" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" </dev/null || true +cp $PLUGIN_PATH/includes/admin/class-zoho-admin.php $PLUGIN_PATH/backups/zoho-$(date +%Y%m%d%H%M%S)/includes/admin/ 2>/dev/null || true +cp $PLUGIN_PATH/assets/js/zoho-admin.js $PLUGIN_PATH/backups/zoho-$(date +%Y%m%d%H%M%S)/assets/js/ 2>/dev/null || true +cp $PLUGIN_PATH/assets/css/zoho-admin.css $PLUGIN_PATH/backups/zoho-$(date +%Y%m%d%H%M%S)/assets/css/ 2>/dev/null || true +EOSSH + +# Upload patched files +echo -e "${YELLOW}Uploading patched files...${NC}" + +# Create the list of files to upload +FILES_TO_UPLOAD=( + "$SRC_DIR/includes/zoho/class-zoho-crm-auth.php" + "$SRC_DIR/includes/zoho/zoho-config.php" + "$SRC_DIR/includes/zoho/diagnostics.php" + "$SRC_DIR/includes/zoho/check-permissions.php" + "$SRC_DIR/includes/admin/class-zoho-admin.php" + "$SRC_DIR/assets/js/zoho-admin.js" + "$SRC_DIR/assets/css/zoho-admin.css" +) + +# Upload each file individually to ensure correct paths +for file in "${FILES_TO_UPLOAD[@]}"; do + rel_path=${file#$SRC_DIR/} + target_path="$PLUGIN_PATH/$rel_path" + target_dir=$(dirname "$target_path") + + echo "Uploading $file to $target_path" + + # Ensure target directory exists + sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "mkdir -p $target_dir" + + # Upload file if it exists + if [ -f "$file" ]; then + sshpass -p "$REMOTE_PASS" scp -o StrictHostKeyChecking=no "$file" "$REMOTE_USER@$REMOTE_HOST:$target_path" + + if [ $? -ne 0 ]; then + echo -e "${RED}Error: Failed to upload $file. Continuing...${NC}" + else + echo -e "${GREEN}Successfully uploaded $file${NC}" + fi + else + echo -e "${RED}File not found: $file${NC}" + fi +done + +echo -e "${GREEN}Files uploaded process completed.${NC}" + +# Clear cache +echo -e "${YELLOW}Clearing cache...${NC}" +sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "cd $REMOTE_PATH && wp cache flush" || true + +echo -e "${GREEN}=== Zoho CRM integration fixes deployed successfully! ===${NC}" +echo -e "${YELLOW}You can now test the connection in the WordPress admin panel.${NC}" +echo -e "${YELLOW}If issues persist, check the logs at: ${PLUGIN_PATH}/includes/logs/zoho-debug.log${NC}" +echo -e "${YELLOW}Or run the diagnostic tool at: https://wordpress-974670-5399585.cloudwaysapps.com/wp-content/plugins/hvac-community-events/includes/zoho/diagnostics.php?run_diagnostics=true${NC}" +echo -e "${YELLOW}Or check permissions at: https://wordpress-974670-5399585.cloudwaysapps.com/wp-content/plugins/hvac-community-events/includes/zoho/check-permissions.php?check=true${NC}" + +exit 0 \ No newline at end of file diff --git a/wordpress-dev/bin/direct-generate-certificates.sh b/wordpress-dev/bin/direct-generate-certificates.sh new file mode 100755 index 00000000..a6fa80bf --- /dev/null +++ b/wordpress-dev/bin/direct-generate-certificates.sh @@ -0,0 +1,268 @@ +#!/bin/bash + +# Generate test certificates directly on the server + +echo "=== Generating Test Certificates on Staging Server ===" +echo "Remote host: 146.190.76.204" +echo "Remote user: roodev" +echo "===============================" + +# Create the PHP script content +cat > certificate-generator.php << 'EOL' +prefix . 'hvac_certificates'; +$table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + +if (!$table_exists) { + echo "Certificate table does not exist. Creating it now...\n"; + + // Try to create the table using the installer + if (class_exists('HVAC_Certificate_Installer')) { + $installer = HVAC_Certificate_Installer::instance(); + $installer->create_tables(); + + // Check if table creation was successful + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + if (!$table_exists) { + echo "Failed to create certificate table. Exiting.\n"; + exit(1); + } + + echo "Certificate table created successfully.\n"; + } else { + echo "Error: HVAC_Certificate_Installer class not found. Exiting.\n"; + exit(1); + } +} + +// Create certificate storage directory if it doesn't exist +$upload_dir = wp_upload_dir(); +$cert_dir = $upload_dir['basedir'] . '/' . get_option('hvac_certificate_storage_path', 'hvac-certificates'); + +if (!file_exists($cert_dir)) { + echo "Certificate directory does not exist. Creating it now...\n"; + $result = wp_mkdir_p($cert_dir); + if (!$result) { + echo "Failed to create certificate directory at: {$cert_dir}\n"; + exit(1); + } + echo "Certificate directory created at: {$cert_dir}\n"; +} + +// Get the events to generate certificates for +$event_ids = [5484, 5485, 5486]; // HVAC Installation, Commercial HVAC, HVAC Energy Efficiency + +// Variables to track generation stats +$total_certificates = 0; +$total_revoked = 0; +$total_emailed = 0; +$failed_generations = 0; + +echo "Generating certificates for " . count($event_ids) . " events...\n\n"; + +foreach ($event_ids as $event_id) { + $event = get_post($event_id); + if (!$event) { + echo "Event ID {$event_id} does not exist. Skipping.\n"; + continue; + } + + echo "Processing event: {$event->post_title} (ID: {$event_id})\n"; + + // Get checked-in attendees for this event + $attendees = get_posts([ + 'post_type' => 'tribe_tpp_attendees', + 'meta_query' => [ + 'relation' => 'AND', + [ + 'key' => '_tribe_tpp_event', + 'value' => $event_id, + ], + [ + 'key' => '_tribe_tpp_checkin', + 'value' => 1, + ] + ], + 'posts_per_page' => -1 + ]); + + echo "Found " . count($attendees) . " checked-in attendees for event {$event_id}\n"; + + // Get a random user ID for the certificate generation (by default the current user) + $user_query = new WP_User_Query([ + 'role' => 'administrator', + 'number' => 1 + ]); + + $admin_users = $user_query->get_results(); + $generated_by = !empty($admin_users) ? $admin_users[0]->ID : get_current_user_id(); + + // Find the trainer user if available + $trainer_user = get_user_by('login', 'test_trainer'); + $trainer_id = $trainer_user ? $trainer_user->ID : $generated_by; + + // Generate certificates for each attendee + $certificates_created = 0; + $certificates_revoked = 0; + $certificates_emailed = 0; + + foreach ($attendees as $attendee) { + $attendee_id = $attendee->ID; + $attendee_name = get_post_meta($attendee_id, '_tribe_tickets_full_name', true); + $attendee_email = get_post_meta($attendee_id, '_tribe_tickets_email', true); + + // Skip if a certificate already exists + if ($certificate_manager->certificate_exists($event_id, $attendee_id)) { + echo " - Certificate already exists for attendee {$attendee_name} ({$attendee_id}). Skipping.\n"; + continue; + } + + // Create a sample certificate file path + $year = date('Y'); + $month = date('m'); + $certificate_filename = "certificate-{$event_id}-{$attendee_id}-" . time() . ".pdf"; + $certificate_relative_path = "hvac-certificates/{$year}/{$month}/{$certificate_filename}"; + + // Create the certificate record + $certificate_id = $certificate_manager->create_certificate( + $event_id, + $attendee_id, + 0, // user_id (not associated with a user) + $certificate_relative_path, + $trainer_id // generated by (trainer) + ); + + if ($certificate_id) { + $certificates_created++; + + // Create year/month directory structure if needed + $year_month_dir = $cert_dir . "/{$year}/{$month}"; + if (!file_exists($year_month_dir)) { + wp_mkdir_p($year_month_dir); + } + + // Example - Create a dummy PDF file (in real scenario, you'd generate a real PDF) + // For testing purposes, we'll create an empty file + $certificate_full_path = $upload_dir['basedir'] . '/' . $certificate_relative_path; + file_put_contents($certificate_full_path, "Placeholder for certificate PDF (Generated for testing)"); + + echo " - Generated certificate for {$attendee_name} ({$attendee_email}) - ID: {$certificate_id}\n"; + + // For testing, randomly mark some certificates as revoked or emailed + $random = mt_rand(1, 10); + + // Revoke about 10% of certificates + if ($random == 1) { + $revoke_result = $certificate_manager->revoke_certificate( + $certificate_id, + $generated_by, + "Test revocation for certificate testing" + ); + + if ($revoke_result) { + $certificates_revoked++; + echo " - Revoked certificate ID: {$certificate_id}\n"; + } + } + + // Mark about 60% as emailed + if ($random <= 6) { + $email_result = $certificate_manager->mark_certificate_emailed($certificate_id); + + if ($email_result) { + $certificates_emailed++; + echo " - Marked certificate ID: {$certificate_id} as emailed\n"; + } + } + } else { + echo " - Failed to generate certificate for attendee {$attendee_name} ({$attendee_id})\n"; + $failed_generations++; + } + } + + // Update statistics + $total_certificates += $certificates_created; + $total_revoked += $certificates_revoked; + $total_emailed += $certificates_emailed; + + echo "Created {$certificates_created} certificates for event {$event_id}\n"; + echo "Revoked {$certificates_revoked} certificates for event {$event_id}\n"; + echo "Marked {$certificates_emailed} certificates as emailed for event {$event_id}\n"; + echo "----------------------------\n"; +} + +echo "\n===== CERTIFICATE GENERATION SUMMARY =====\n"; +echo "Total certificates created: {$total_certificates}\n"; +echo "Total certificates revoked: {$total_revoked}\n"; +echo "Total certificates marked as emailed: {$total_emailed}\n"; +echo "Failed certificate generations: {$failed_generations}\n"; + +// Fetch some certificate statistics for verification +if (class_exists('HVAC_Certificate_Manager')) { + echo "\n===== CERTIFICATE DATABASE VERIFICATION =====\n"; + $stats = $certificate_manager->get_certificate_stats(); + + echo "Certificate count in database: {$stats['total_certificates']}\n"; + echo "Event count with certificates: {$stats['total_events']}\n"; + echo "Trainee count with certificates: {$stats['total_trainees']}\n"; + echo "Total revoked certificates: {$stats['total_revoked']}\n"; + echo "Total emailed certificates: {$stats['total_emailed']}\n"; +} + +// Print instructions on how to view certificates +echo "\n===== INSTRUCTIONS =====\n"; +echo "1. Certificates have been generated for checked-in attendees\n"; +echo "2. View certificates at: " . home_url('/certificate-reports/') . "\n"; +echo "3. Filter certificates by event, attendee name, or revocation status\n"; +echo "4. Download certificate PDFs from the certificate reports page\n"; + +echo "\n===== CERTIFICATE GENERATION COMPLETED =====\n"; +EOL + +# Copy PHP script to server and execute +echo "[1;33mCopying script to server...[0m" +scp certificate-generator.php roodev@146.190.76.204:~/public_html/ + +echo "[1;33mExecuting certificate generation script on server...[0m" +ssh roodev@146.190.76.204 "cd ~/public_html/ && php certificate-generator.php" + +# Clean up +rm certificate-generator.php +ssh roodev@146.190.76.204 "rm ~/public_html/certificate-generator.php" + +echo "[0;32mTest certificate generation completed![0m" +echo "You can view and test certificates at: https://wordpress-974670-5399585.cloudwaysapps.com/certificate-reports/" +echo "" +echo "Features to test:" +echo "1. Certificate listing with pagination" +echo "2. Filtering by event" +echo "3. Filtering by attendee name/email (new feature)" +echo "4. Filtering by revocation status" +echo "5. Certificate downloading" +echo "6. Certificate email sending" \ No newline at end of file diff --git a/wordpress-dev/bin/direct-server-upload.sh b/wordpress-dev/bin/direct-server-upload.sh new file mode 100755 index 00000000..946316c7 --- /dev/null +++ b/wordpress-dev/bin/direct-server-upload.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# +# Direct Server Upload Script +# This script connects directly to the server to upload files +# + +cd /Users/ben/dev/upskill-event-manager/wordpress-dev + +# Connect to the server +echo "Connecting to the server..." +echo "Once connected, run these commands:" +echo +echo "1. Create simple-installer.php:" +echo "-----------------------------------------" +echo "cat > /home/974670.cloudwaysapps.com/uberrxmprk/public_html/simple-installer.php <<'EOF'" +cat simple-installer.php +echo "EOF" +echo +echo "2. Create .env file:" +echo "-----------------------------------------" +echo "cat > /home/974670.cloudwaysapps.com/uberrxmprk/public_html/.env <<'EOF'" +echo "ZOHO_CLIENT_ID=1000.Z0HOF1VMMJ9W2QWSU57GVQYEAVUSKS" +echo "ZOHO_CLIENT_SECRET=36913615664649dbf9198884bfd1096f7573c9ce2b" +echo "UPSKILL_STAGING_URL=https://upskill-staging.measurequick.com/" +echo "EOF" +echo +echo "3. Set permissions:" +echo "-----------------------------------------" +echo "chmod 644 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/simple-installer.php" +echo "chmod 640 /home/974670.cloudwaysapps.com/uberrxmprk/public_html/.env" +echo +echo "4. Access the installer at:" +echo "-----------------------------------------" +echo "https://upskill-staging.measurequick.com/simple-installer.php?key=upskill2025" +echo + +# Connect to the server +ssh roodev@146.190.76.204 \ No newline at end of file diff --git a/wordpress-dev/bin/emergency-certificate-fix.php b/wordpress-dev/bin/emergency-certificate-fix.php new file mode 100644 index 00000000..55fcd947 --- /dev/null +++ b/wordpress-dev/bin/emergency-certificate-fix.php @@ -0,0 +1,301 @@ + $type, 'message' => $message]; + + // Output if running in browser + if (php_sapi_name() !== 'cli') { + $color = ''; + switch ($type) { + case 'success': $color = 'green'; break; + case 'error': $color = 'red'; break; + case 'warning': $color = 'orange'; break; + default: $color = 'blue'; + } + echo "
" . strtoupper($type) . ": $message
"; + } else { + // CLI output + echo "[" . strtoupper($type) . "] $message\n"; + } +} + +// Function to fix certificate database table +function fix_certificate_table() { + global $wpdb; + + output_message("Checking certificate database table..."); + + // Check if the table exists + $table_name = $wpdb->prefix . 'hvac_certificates'; + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if (!$table_exists) { + output_message("Certificate table does not exist. Creating it now...", 'warning'); + + // Make sure we have dbDelta function + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); + + // Create the certificate table + $charset_collate = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE $table_name ( + certificate_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + event_id BIGINT(20) UNSIGNED NOT NULL, + attendee_id BIGINT(20) UNSIGNED NOT NULL, + user_id BIGINT(20) UNSIGNED DEFAULT NULL, + certificate_number VARCHAR(50) NOT NULL, + file_path VARCHAR(255) NOT NULL, + date_generated DATETIME NOT NULL, + generated_by BIGINT(20) UNSIGNED NOT NULL, + revoked TINYINT(1) NOT NULL DEFAULT 0, + revoked_date DATETIME DEFAULT NULL, + revoked_by BIGINT(20) UNSIGNED DEFAULT NULL, + revoked_reason TEXT DEFAULT NULL, + email_sent TINYINT(1) NOT NULL DEFAULT 0, + email_sent_date DATETIME DEFAULT NULL, + PRIMARY KEY (certificate_id), + UNIQUE KEY event_attendee (event_id, attendee_id), + KEY event_id (event_id), + KEY attendee_id (attendee_id), + KEY user_id (user_id), + KEY certificate_number (certificate_number), + KEY revoked (revoked) + ) $charset_collate;"; + + dbDelta($sql); + + // Check if table was created + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if ($table_exists) { + output_message("Certificate table created successfully.", 'success'); + update_option('hvac_certificates_db_version', '1.0.0'); + } else { + output_message("Failed to create certificate table.", 'error'); + return false; + } + } else { + output_message("Certificate table exists.", 'success'); + } + + return true; +} + +// Function to fix certificate template +function fix_certificate_template() { + output_message("Fixing certificate template..."); + + // Path to the problematic template + $plugin_dir = WP_PLUGIN_DIR . '/hvac-community-events'; + $template_dir = $plugin_dir . '/templates/certificates'; + $template_file = $template_dir . '/template-certificate-reports.php'; + $simple_template_file = $template_dir . '/template-certificate-reports-simple.php'; + + // Check if template directory exists + if (!file_exists($template_dir)) { + output_message("Template directory does not exist: $template_dir", 'error'); + return false; + } + + // Check if the template file exists + if (!file_exists($template_file)) { + output_message("Original template file does not exist: $template_file", 'warning'); + } else { + // Create backup of the original file + $backup_file = $template_file . '.bak.' . date('YmdHis'); + if (copy($template_file, $backup_file)) { + output_message("Created backup of original template at: $backup_file", 'success'); + } else { + output_message("Failed to create backup of original template.", 'warning'); + } + } + + // Check if simplified template exists (it should have been uploaded alongside this script) + if (!file_exists($simple_template_file)) { + output_message("Simplified template file not found: $simple_template_file", 'error'); + output_message("Please upload the simplified template file alongside this script.", 'error'); + return false; + } + + // Replace the original template with the simplified version + if (copy($simple_template_file, $template_file)) { + output_message("Replaced original template with simplified version.", 'success'); + } else { + output_message("Failed to replace template file.", 'error'); + return false; + } + + return true; +} + +// Function to check certificate directory +function check_certificate_directory() { + output_message("Checking certificate storage directory..."); + + // Get upload directory + $upload_dir = wp_upload_dir(); + $cert_dir = $upload_dir['basedir'] . '/' . get_option('hvac_certificate_storage_path', 'hvac-certificates'); + + output_message("Certificate directory path: $cert_dir"); + + // Check if directory exists + if (!file_exists($cert_dir)) { + output_message("Certificate directory does not exist. Creating it...", 'warning'); + + // Create directory + if (wp_mkdir_p($cert_dir)) { + output_message("Certificate directory created successfully.", 'success'); + } else { + output_message("Failed to create certificate directory.", 'error'); + return false; + } + } else { + output_message("Certificate directory exists.", 'success'); + } + + // Check directory permissions + if (!is_writable($cert_dir)) { + output_message("Certificate directory is not writable. Fixing permissions...", 'warning'); + chmod($cert_dir, 0755); + + if (is_writable($cert_dir)) { + output_message("Directory permissions fixed.", 'success'); + } else { + output_message("Failed to fix directory permissions.", 'error'); + return false; + } + } else { + output_message("Certificate directory is writable.", 'success'); + } + + return true; +} + +// Function to fix certificate options +function fix_certificate_options() { + output_message("Checking certificate options..."); + + // Check and set certificate counter option + if (false === get_option('hvac_certificate_counter')) { + add_option('hvac_certificate_counter', 0); + output_message("Added hvac_certificate_counter option.", 'success'); + } + + // Check and set certificate prefix option + if (false === get_option('hvac_certificate_prefix')) { + add_option('hvac_certificate_prefix', 'HVAC-'); + output_message("Added hvac_certificate_prefix option.", 'success'); + } + + // Check and set certificate storage path option + if (false === get_option('hvac_certificate_storage_path')) { + add_option('hvac_certificate_storage_path', 'hvac-certificates'); + output_message("Added hvac_certificate_storage_path option.", 'success'); + } + + // Check and set certificate db version + if (false === get_option('hvac_certificates_db_version')) { + add_option('hvac_certificates_db_version', '1.0.0'); + output_message("Added hvac_certificates_db_version option.", 'success'); + } + + return true; +} + +// Function to clear cache +function clear_cache() { + output_message("Clearing cache..."); + + // Clear WordPress object cache + wp_cache_flush(); + output_message("WordPress object cache cleared.", 'success'); + + // Try to clear Breeze cache if it exists + if (class_exists('Breeze_Admin')) { + if (function_exists('breeze_flush_all_cache')) { + breeze_flush_all_cache(); + output_message("Breeze cache cleared.", 'success'); + } else { + output_message("Breeze class exists but flush function not found.", 'warning'); + } + } else { + output_message("Breeze cache plugin not detected.", 'info'); + } + + return true; +} + +// Main execution +if (php_sapi_name() !== 'cli') { + echo "Emergency Certificate Fix"; + echo ""; + echo "

Emergency Certificate Fix

"; +} + +output_message("Starting emergency certificate fix..."); + +// Run the fix functions +$table_fixed = fix_certificate_table(); +$template_fixed = fix_certificate_template(); +$directory_checked = check_certificate_directory(); +$options_fixed = fix_certificate_options(); +$cache_cleared = clear_cache(); + +// Summary +if ($table_fixed && $template_fixed && $directory_checked && $options_fixed) { + output_message("All fixes applied successfully! The certificate reports page should now work properly.", 'success'); + output_message("Please try accessing the certificate reports page now: " . home_url('/certificate-reports/'), 'success'); +} else { + output_message("Some fixes failed to apply. Please check the logs above for details.", 'error'); +} + +// Output HTML footer if running in browser +if (php_sapi_name() !== 'cli') { + echo "

Fix completed at: " . date('Y-m-d H:i:s') . "

"; + echo "

Go to Certificate Reports

"; + echo ""; +} \ No newline at end of file diff --git a/wordpress-dev/bin/fix-certificate-reports.php b/wordpress-dev/bin/fix-certificate-reports.php new file mode 100644 index 00000000..922b01fd --- /dev/null +++ b/wordpress-dev/bin/fix-certificate-reports.php @@ -0,0 +1,362 @@ + "\033[32m", // Green + 'error' => "\033[31m", // Red + 'warning' => "\033[33m", // Yellow + 'info' => "\033[36m", // Cyan + 'reset' => "\033[0m", // Reset + ]; + + echo $colors[$type] . "[" . strtoupper($type) . "] " . $message . $colors['reset'] . PHP_EOL; +} + +// Function to check and create certificate tables +function check_and_create_certificate_tables() { + global $wpdb; + + print_status("Checking certificate tables..."); + + // Define table name + $table_name = $wpdb->prefix . 'hvac_certificates'; + + // Check if the table exists + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if (!$table_exists) { + print_status("Certificate table does not exist. Creating it now...", 'warning'); + + // Create the table with proper schema + $charset_collate = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE $table_name ( + certificate_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + event_id BIGINT(20) UNSIGNED NOT NULL, + attendee_id BIGINT(20) UNSIGNED NOT NULL, + user_id BIGINT(20) UNSIGNED DEFAULT NULL, + certificate_number VARCHAR(50) NOT NULL, + file_path VARCHAR(255) NOT NULL, + date_generated DATETIME NOT NULL, + generated_by BIGINT(20) UNSIGNED NOT NULL, + revoked TINYINT(1) NOT NULL DEFAULT 0, + revoked_date DATETIME DEFAULT NULL, + revoked_by BIGINT(20) UNSIGNED DEFAULT NULL, + revoked_reason TEXT DEFAULT NULL, + email_sent TINYINT(1) NOT NULL DEFAULT 0, + email_sent_date DATETIME DEFAULT NULL, + PRIMARY KEY (certificate_id), + UNIQUE KEY event_attendee (event_id, attendee_id), + KEY event_id (event_id), + KEY attendee_id (attendee_id), + KEY user_id (user_id), + KEY certificate_number (certificate_number), + KEY revoked (revoked) + ) $charset_collate;"; + + // Use dbDelta to create or update table + $result = dbDelta($sql); + + // Check if table was created + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if ($table_exists) { + print_status("Table created successfully!", 'success'); + update_option('hvac_certificates_db_version', '1.0.0'); + } else { + print_status("Failed to create table. Error: " . $wpdb->last_error, 'error'); + return false; + } + } else { + print_status("Certificate table exists: $table_name", 'success'); + + // Check if the table has the expected structure + print_status("Checking table structure...", 'info'); + + // Get columns + $columns = $wpdb->get_results("DESCRIBE $table_name"); + $column_names = array_map(function($col) { return $col->Field; }, $columns); + + // Expected columns + $expected_columns = [ + 'certificate_id', + 'event_id', + 'attendee_id', + 'user_id', + 'certificate_number', + 'file_path', + 'date_generated', + 'generated_by', + 'revoked', + 'revoked_date', + 'revoked_by', + 'revoked_reason', + 'email_sent', + 'email_sent_date' + ]; + + // Check for missing columns + $missing_columns = array_diff($expected_columns, $column_names); + + if (!empty($missing_columns)) { + print_status("Table is missing columns: " . implode(", ", $missing_columns), 'warning'); + + // Create migration to add missing columns + print_status("Attempting to fix missing columns...", 'info'); + + // Use dbDelta to update table structure + $charset_collate = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE $table_name ( + certificate_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + event_id BIGINT(20) UNSIGNED NOT NULL, + attendee_id BIGINT(20) UNSIGNED NOT NULL, + user_id BIGINT(20) UNSIGNED DEFAULT NULL, + certificate_number VARCHAR(50) NOT NULL, + file_path VARCHAR(255) NOT NULL, + date_generated DATETIME NOT NULL, + generated_by BIGINT(20) UNSIGNED NOT NULL, + revoked TINYINT(1) NOT NULL DEFAULT 0, + revoked_date DATETIME DEFAULT NULL, + revoked_by BIGINT(20) UNSIGNED DEFAULT NULL, + revoked_reason TEXT DEFAULT NULL, + email_sent TINYINT(1) NOT NULL DEFAULT 0, + email_sent_date DATETIME DEFAULT NULL, + PRIMARY KEY (certificate_id), + UNIQUE KEY event_attendee (event_id, attendee_id), + KEY event_id (event_id), + KEY attendee_id (attendee_id), + KEY user_id (user_id), + KEY certificate_number (certificate_number), + KEY revoked (revoked) + ) $charset_collate;"; + + $result = dbDelta($sql); + + // Check if fix was successful + $columns = $wpdb->get_results("DESCRIBE $table_name"); + $column_names = array_map(function($col) { return $col->Field; }, $columns); + $missing_columns = array_diff($expected_columns, $column_names); + + if (empty($missing_columns)) { + print_status("Table structure fixed successfully!", 'success'); + update_option('hvac_certificates_db_version', '1.0.0'); + } else { + print_status("Failed to fix all columns. Still missing: " . implode(", ", $missing_columns), 'error'); + return false; + } + } else { + print_status("Table structure is correct.", 'success'); + } + } + + // Check and create certificate directory + print_status("Checking certificate directory...", 'info'); + + $upload_dir = wp_upload_dir(); + $cert_dir = $upload_dir['basedir'] . '/' . get_option('hvac_certificate_storage_path', 'hvac-certificates'); + + if (!file_exists($cert_dir)) { + print_status("Certificate directory does not exist. Creating it now...", 'warning'); + wp_mkdir_p($cert_dir); + + if (file_exists($cert_dir)) { + print_status("Certificate directory created: $cert_dir", 'success'); + } else { + print_status("Failed to create certificate directory.", 'error'); + return false; + } + } else { + print_status("Certificate directory exists: $cert_dir", 'success'); + } + + // Check and set certificate options + print_status("Checking certificate options...", 'info'); + + if (false === get_option('hvac_certificate_counter')) { + add_option('hvac_certificate_counter', 0); + print_status("Added hvac_certificate_counter option", 'success'); + } + + if (false === get_option('hvac_certificate_prefix')) { + add_option('hvac_certificate_prefix', 'HVAC-'); + print_status("Added hvac_certificate_prefix option", 'success'); + } + + if (false === get_option('hvac_certificate_storage_path')) { + add_option('hvac_certificate_storage_path', 'hvac-certificates'); + print_status("Added hvac_certificate_storage_path option", 'success'); + } + + return true; +} + +// Fix certificate template closing PHP tag issue +function fix_template_closing_tags() { + print_status("Checking template-certificate-reports.php for syntax issues...", 'info'); + + $plugin_dir = WP_CONTENT_DIR . '/plugins/hvac-community-events/'; + $template_file = $plugin_dir . 'templates/certificates/template-certificate-reports.php'; + + if (file_exists($template_file)) { + $content = file_get_contents($template_file); + + // Find and fix HTML comment tags (

This is the HVAC dashboard page.

', + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed', + ]; + + // Check if page already exists by slug + $existing_page = get_page_by_path('hvac-dashboard', OBJECT, 'page'); + + // Only create the page if it doesn't exist + if (empty($existing_page)) { + // Insert the page + $page_id = wp_insert_post($test_page); + + // Log the result + if (is_wp_error($page_id)) { + error_log('[HVAC CE] Error creating dashboard page: ' . $page_id->get_error_message()); + } else { + error_log('[HVAC CE] Successfully created dashboard page with ID: ' . $page_id); + + // Store the page ID in options + $created_pages = ['dashboard' => $page_id]; + update_option('hvac_ce_fixed_pages', $created_pages); + } + } else { + error_log('[HVAC CE] Dashboard page already exists with ID: ' . $existing_page->ID); + + // Store the existing page ID + $created_pages = ['dashboard' => $existing_page->ID]; + update_option('hvac_ce_fixed_pages', $created_pages); + } + + // Try to create a basic role (without complex classes or dependencies) + if (!get_role('hvac_trainer_basic')) { + $capabilities = [ + 'read' => true, + 'upload_files' => true, + 'hvac_basic_access' => true + ]; + + $role = add_role( + 'hvac_trainer_basic', + 'HVAC Trainer (Basic)', + $capabilities + ); + + if ($role) { + error_log('[HVAC CE] Created hvac_trainer_basic role'); + } else { + error_log('[HVAC CE] Failed to create hvac_trainer_basic role'); + } + } else { + error_log('[HVAC CE] hvac_trainer_basic role already exists'); + } + + // Log activation completion + error_log('[HVAC CE] Activation process completed'); +} +register_activation_hook(__FILE__, 'hvac_ce_fixed_activation'); + +/** + * Remove roles and options upon plugin deactivation. + */ +function hvac_ce_fixed_deactivation() { + // Remove the role + remove_role('hvac_trainer_basic'); + + // Log deactivation + error_log('[HVAC CE] Plugin deactivated, hvac_trainer_basic role removed'); +} +register_deactivation_hook(__FILE__, 'hvac_ce_fixed_deactivation'); + +/** + * Initialize the plugin + */ +function hvac_ce_fixed_init() { + // Add admin notice for activation + if (is_admin()) { + add_action('admin_notices', 'hvac_ce_fixed_admin_notice'); + } +} +add_action('plugins_loaded', 'hvac_ce_fixed_init'); + +/** + * Display admin notice about successful activation + */ +function hvac_ce_fixed_admin_notice() { + if (get_option('hvac_ce_fixed_activated') === 'yes') { + ?> +
+

+

+ ' . __('Created pages:', 'hvac-community-events') . '

'; + echo '
    '; + foreach ($created_pages as $key => $page_id) { + $page = get_post($page_id); + if ($page) { + echo '
  • ' . esc_html($page->post_title) . ' (ID: ' . $page_id . ')
  • '; + } + } + echo '
'; + } + ?> +
+ 'Generate Certificates', 'content' => '[hvac_generate_certificates]', ], + 'certificate-fix' => [ // Add certificate fix page (admin only) + 'title' => 'Certificate System Diagnostics', + 'content' => '[hvac_certificate_fix]', + ], // REMOVED: 'submit-event' page creation. Will link to default TEC CE page. // 'submit-event' => [ // 'title' => 'Submit Event', @@ -301,7 +305,7 @@ function hvac_ce_enqueue_common_assets() { } // Enqueue certificate-related styles - if (is_page('certificate-reports') || is_page('generate-certificates')) { + if (is_page('certificate-reports') || is_page('generate-certificates') || is_page('certificate-fix')) { wp_enqueue_style( 'hvac-certificates-admin-style', HVAC_CE_PLUGIN_URL . 'assets/css/hvac-certificates-admin.css', diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-community-events.php.bak b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-community-events.php.bak new file mode 100644 index 00000000..e94da07b --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-community-events.php.bak @@ -0,0 +1,294 @@ + [ + 'title' => 'Trainer Login', + 'content' => '[hvac_community_login]', + 'template' => 'page-community-login.php', + ], + 'trainer-registration' => [ + 'title' => 'Trainer Registration', + 'content' => '[hvac_trainer_registration]', + ], + 'hvac-dashboard' => [ + 'title' => 'Trainer Dashboard', + 'content' => '[hvac_trainer_dashboard]', + ], + 'manage-event' => [ // New page for TEC CE submission form shortcode + 'title' => 'Manage Event', + 'content' => '[tribe_community_events view="submission_form"]', + ], + 'my-events' => [ // New page for TEC CE event list shortcode + 'title' => 'My Events', + 'content' => '[tribe_community_events view="my_events"]', + ], + 'trainer-profile' => [ // Add trainer profile page + 'title' => 'Trainer Profile', + 'content' => '[hvac_trainer_profile]', + ], + 'event-summary' => [ // Add event summary page + 'title' => 'Event Summary', + 'content' => '[hvac_event_summary]', + ], + 'email-attendees' => [ // Add email attendees page + 'title' => 'Email Attendees', + 'content' => '[hvac_email_attendees]', + ], + // REMOVED: 'submit-event' page creation. Will link to default TEC CE page. + // 'submit-event' => [ + // 'title' => 'Submit Event', + // 'content' => '[hvac_event_form]', + // ], + // Add future required pages here + ]; + + // Get existing page IDs from options + $created_pages_option = 'hvac_community_pages'; + $created_pages = get_option($created_pages_option, []); + + // Process each required page + foreach ($required_pages as $slug => $page_data) { + // Create the feature key + $feature_key = str_replace('-', '_', $slug); + + // Skip if already exists in our option + if (isset($created_pages[$feature_key]) && get_post($created_pages[$feature_key])) { + HVAC_Logger::info("Page '{$slug}' already exists in options with ID: {$created_pages[$feature_key]}", 'Activation'); + continue; + } + + // Check if page already exists by slug + $existing_page = get_page_by_path($slug, OBJECT, 'page'); + + // Safe handling of existing page + if (!empty($existing_page) && is_object($existing_page) && isset($existing_page->ID)) { + HVAC_Logger::info("Page '{$slug}' exists with ID: {$existing_page->ID}", 'Activation'); + $created_pages[$feature_key] = $existing_page->ID; + continue; + } + + // Page doesn't exist, create it + HVAC_Logger::info("Page '{$slug}' not found. Creating it.", 'Activation'); + + $post_data = [ + 'post_title' => $page_data['title'], + 'post_name' => $slug, + 'post_content' => $page_data['content'], + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed', + ]; + + // Add template if specified + if (!empty($page_data['template'])) { + $post_data['page_template'] = $page_data['template']; + } + + // Insert the page + $page_id = wp_insert_post($post_data); + + // Handle the result + if (is_wp_error($page_id)) { + HVAC_Logger::error("Error creating page '{$slug}': " . $page_id->get_error_message(), 'Activation'); + } elseif (!empty($page_id)) { + HVAC_Logger::info("Successfully created page '{$slug}' with ID: {$page_id}", 'Activation'); + $created_pages[$feature_key] = $page_id; + } + } + + // Update the option with any newly created page IDs (and existing ones) + update_option($created_pages_option, $created_pages); + + // Create the custom role (Moved inside the activation function) + $roles_manager = new HVAC_Roles(); + $result = $roles_manager->create_trainer_role(); + if ($result) { + HVAC_Logger::info('Successfully created hvac_trainer role.', 'Activation'); + } else { + HVAC_Logger::error('Failed to create hvac_trainer role.', 'Activation'); + } + HVAC_Logger::info('Completed page creation and role setup process', 'Activation'); + +} // <<-- Brace moved here +register_activation_hook(__FILE__, 'hvac_ce_create_required_pages'); + + +/** + * Remove custom roles upon plugin deactivation. + */ +function hvac_ce_remove_roles() { + require_once HVAC_CE_PLUGIN_DIR . 'includes/class-hvac-roles.php'; + $roles_manager = new HVAC_Roles(); + $roles_manager->remove_trainer_role(); + HVAC_Logger::info('Deactivation hook fired, attempted to remove hvac_trainer role.', 'Deactivation'); +} +register_deactivation_hook(__FILE__, 'hvac_ce_remove_roles'); + + + +/** + * Enqueue styles specifically for the HVAC Dashboard page. + */ +function hvac_ce_enqueue_dashboard_styles() { + // Check if we are on the specific dashboard page + // Assumes the page slug is 'hvac-dashboard' as created in the activation hook + if ( is_page( 'hvac-dashboard' ) ) { + wp_enqueue_style( + 'hvac-dashboard-style', + HVAC_CE_PLUGIN_URL . 'assets/css/hvac-dashboard.css', + [], // No dependencies for now + HVAC_CE_VERSION + ); + } +} +add_action( 'wp_enqueue_scripts', 'hvac_ce_enqueue_dashboard_styles' ); + +/** + * Enqueue styles and scripts for admin dashboard + */ +function hvac_ce_enqueue_admin_assets($hook) { + // Only load on our dashboard page + if ($hook !== 'hvac-community-events_page_hvac-ce-dashboard') { + return; + } + + // Enqueue dashboard CSS + wp_enqueue_style( + 'hvac-admin-dashboard-style', + HVAC_CE_PLUGIN_URL . 'assets/css/admin-dashboard.css', + array('wp-admin'), + HVAC_CE_VERSION + ); + + // Enqueue dashboard JS + wp_enqueue_script( + 'hvac-admin-dashboard-script', + HVAC_CE_PLUGIN_URL . 'assets/js/admin-dashboard.js', + array('jquery', 'wp-util'), + HVAC_CE_VERSION, + true + ); + + // Localize script with AJAX data + wp_localize_script('hvac-admin-dashboard-script', 'hvac_admin_dashboard', array( + 'ajax_url' => admin_url('admin-ajax.php'), + 'nonce' => wp_create_nonce('hvac_admin_nonce') + )); +} +add_action('admin_enqueue_scripts', 'hvac_ce_enqueue_admin_assets'); + + +/** + * Enqueue styles specifically for the HVAC Event Summary page. + */ +function hvac_ce_enqueue_event_summary_styles() { + // Check if we are on a single event page + if ( is_singular( Tribe__Events__Main::POSTTYPE ) ) { + wp_enqueue_style( + 'hvac-event-summary-style', + HVAC_CE_PLUGIN_URL . 'assets/css/hvac-event-summary.css', + [], // No dependencies for now + HVAC_CE_VERSION + ); + } +} +add_action( 'wp_enqueue_scripts', 'hvac_ce_enqueue_event_summary_styles' ); + +/** + * Enqueue styles specifically for the HVAC Email Attendees page. + */ +function hvac_ce_enqueue_email_attendees_styles() { + // Check if we are on the email attendees page + if ( is_page( 'email-attendees' ) ) { + wp_enqueue_style( + 'hvac-email-attendees-style', + HVAC_CE_PLUGIN_URL . 'assets/css/hvac-email-attendees.css', + [], // No dependencies for now + HVAC_CE_VERSION + ); + } +} +add_action( 'wp_enqueue_scripts', 'hvac_ce_enqueue_email_attendees_styles' ); + + + +// Include the main plugin class +require_once HVAC_CE_PLUGIN_DIR . 'includes/class-hvac-community-events.php'; + +// Initialize the plugin +function hvac_community_events_init() { + HVAC_Logger::info('Initializing HVAC Community Events plugin', 'Core'); + return HVAC_Community_Events::instance(); +} +add_action('plugins_loaded', 'hvac_community_events_init'); + + +/** + * Include custom template for single event summary page. + * + * @param string $template The path of the template to include. + * @return string The path of the template file. + */ +function hvac_ce_include_event_summary_template( $template ) { + // Check if it's a single event post type view + if ( is_singular( Tribe__Events__Main::POSTTYPE ) ) { + // Check if the custom template exists in the plugin's template directory + $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/single-hvac-event-summary.php'; + if ( file_exists( $custom_template ) ) { + // Return the path to the custom template + return $custom_template; + } + } + // Return the original template if not a single event or custom template doesn't exist + return $template; +} + +/** + * Template routing for Order Summary Page. + */ +function hvac_ce_include_order_summary_template( $template ) { + if ( is_page( 'order-summary' ) && isset( $_GET['order_id'] ) && absint( $_GET['order_id'] ) > 0 ) { + $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/single-hvac-order-summary.php'; + if ( file_exists( $custom_template ) ) { + return $custom_template; + } + } + return $template; +} +// Removed - template handling is now in the main class +// add_filter( 'template_include', 'hvac_ce_include_event_summary_template', 99 ); diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-fixed-activation.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-fixed-activation.php new file mode 100644 index 00000000..ca96bd3a --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-fixed-activation.php @@ -0,0 +1,312 @@ +getMessage()); + update_option('hvac_activation_error', $e->getMessage()); + } + + // Clear in-progress flag + delete_option('hvac_activation_in_progress'); +} + +/** + * Create the main dashboard page + */ +function create_hvac_dashboard_page() { + error_log('[HVAC Activation] Creating dashboard page'); + + // Check if the page already exists by slug + $existing_page = get_page_by_path('hvac-dashboard', OBJECT, 'page'); + + if (!empty($existing_page) && is_object($existing_page)) { + error_log('[HVAC Activation] Dashboard page already exists with ID: ' . $existing_page->ID); + $created_pages = get_option('hvac_community_pages', []); + $created_pages['hvac_dashboard'] = $existing_page->ID; + update_option('hvac_community_pages', $created_pages); + return; + } + + // Create the dashboard page + $page_data = [ + 'post_title' => 'Trainer Dashboard', + 'post_name' => 'hvac-dashboard', + 'post_content' => '[hvac_trainer_dashboard]', + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed', + ]; + + $page_id = wp_insert_post($page_data); + + if (is_wp_error($page_id)) { + throw new Exception('Failed to create dashboard page: ' . $page_id->get_error_message()); + } + + error_log('[HVAC Activation] Successfully created dashboard page with ID: ' . $page_id); + + // Save page ID in options + $created_pages = get_option('hvac_community_pages', []); + $created_pages['hvac_dashboard'] = $page_id; + update_option('hvac_community_pages', $created_pages); +} + +/** + * Create the HVAC trainer role + */ +function create_hvac_trainer_role() { + error_log('[HVAC Activation] Creating trainer role'); + + // Check if role already exists + if (get_role('hvac_trainer')) { + error_log('[HVAC Activation] Trainer role already exists'); + return; + } + + // Define trainer capabilities + $caps = array( + // Basic WordPress capabilities + 'read' => true, + 'upload_files' => true, + + // Custom HVAC capabilities + 'manage_hvac_events' => true, + 'edit_hvac_profile' => true, + 'view_hvac_dashboard' => true, + 'manage_attendees' => true, + 'email_attendees' => true, + + // The Events Calendar capabilities + 'publish_tribe_events' => true, + 'edit_tribe_events' => true, + 'delete_tribe_events' => true, + 'edit_published_tribe_events' => true, + 'delete_published_tribe_events' => true, + 'read_private_tribe_events' => true, + ); + + // Add the role + $result = add_role( + 'hvac_trainer', + 'HVAC Trainer', + $caps + ); + + if ($result === null) { + throw new Exception('Failed to create hvac_trainer role'); + } + + error_log('[HVAC Activation] Successfully created hvac_trainer role'); +} + +/** + * Create all required pages for the plugin + */ +function create_hvac_required_pages() { + error_log('[HVAC Activation] Creating required pages'); + + // Define required pages (excluding dashboard, which was created first) + $required_pages = [ + 'community-login' => [ + 'title' => 'Trainer Login', + 'content' => '[hvac_community_login]', + 'template' => 'page-community-login.php', + ], + 'trainer-registration' => [ + 'title' => 'Trainer Registration', + 'content' => '[hvac_trainer_registration]', + ], + 'manage-event' => [ + 'title' => 'Manage Event', + 'content' => '[tribe_community_events view="submission_form"]', + ], + 'my-events' => [ + 'title' => 'My Events', + 'content' => '[tribe_community_events view="my_events"]', + ], + 'trainer-profile' => [ + 'title' => 'Trainer Profile', + 'content' => '[hvac_trainer_profile]', + ], + 'event-summary' => [ + 'title' => 'Event Summary', + 'content' => '[hvac_event_summary]', + ], + 'email-attendees' => [ + 'title' => 'Email Attendees', + 'content' => '[hvac_email_attendees]', + ], + ]; + + // Get existing page IDs from options + $created_pages = get_option('hvac_community_pages', []); + + // Create each page one by one + foreach ($required_pages as $slug => $page_data) { + try { + create_single_hvac_page($slug, $page_data, $created_pages); + } catch (Exception $e) { + error_log('[HVAC Activation] Error creating page ' . $slug . ': ' . $e->getMessage()); + // Continue with other pages even if one fails + } + } + + // Update the option with all created pages + update_option('hvac_community_pages', $created_pages); +} + +/** + * Create a single page safely + */ +function create_single_hvac_page($slug, $page_data, &$created_pages) { + // Create the feature key + $feature_key = str_replace('-', '_', $slug); + + // Skip if already exists in our option + if (isset($created_pages[$feature_key]) && get_post($created_pages[$feature_key])) { + error_log('[HVAC Activation] Page ' . $slug . ' already exists in options with ID: ' . $created_pages[$feature_key]); + return; + } + + // Check if page already exists by slug + $existing_page = get_page_by_path($slug, OBJECT, 'page'); + + // Safe handling of existing page + if (!empty($existing_page) && is_object($existing_page) && isset($existing_page->ID)) { + error_log('[HVAC Activation] Page ' . $slug . ' exists with ID: ' . $existing_page->ID); + $created_pages[$feature_key] = $existing_page->ID; + return; + } + + // Page doesn't exist, create it + error_log('[HVAC Activation] Creating page: ' . $slug); + + $post_data = [ + 'post_title' => $page_data['title'], + 'post_name' => $slug, + 'post_content' => $page_data['content'], + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed', + ]; + + // Add template if specified + if (!empty($page_data['template'])) { + $post_data['page_template'] = $page_data['template']; + } + + // Insert the page + $page_id = wp_insert_post($post_data); + + // Handle the result + if (is_wp_error($page_id)) { + throw new Exception('Error creating page ' . $slug . ': ' . $page_id->get_error_message()); + } elseif (!empty($page_id)) { + error_log('[HVAC Activation] Successfully created page ' . $slug . ' with ID: ' . $page_id); + $created_pages[$feature_key] = $page_id; + } +} + +/** + * Show admin notice for activation status + */ +function hvac_activation_admin_notice() { + // Show only on plugin pages + $screen = get_current_screen(); + if (!in_array($screen->id, ['plugins', 'dashboard'])) { + return; + } + + // Check if activation was successful + if (get_option('hvac_activation_successful') === 'yes') { + ?> +
+

HVAC Community Events: Plugin activated successfully!

+

Activation completed at:

+ Created pages:

'; + echo '
    '; + foreach ($created_pages as $key => $page_id) { + $page = get_post($page_id); + if ($page) { + echo '
  • ' . esc_html($page->post_title) . ' (ID: ' . $page_id . ')
  • '; + } + } + echo '
'; + } + ?> +
+ +
+

HVAC Community Events: Plugin activation encountered an error:

+

+

Please deactivate and reactivate the plugin to try again.

+
+ +
+

HVAC Community Events: Plugin activation appears to be in progress.

+

Started at:

+

If this message persists, please deactivate and reactivate the plugin.

+
+ true, + 'upload_files' => true, + 'hvac_staging_access' => true + ] + ); + + error_log('[HVAC CE Staging] Activation completed'); +} +register_activation_hook(__FILE__, 'hvac_ce_staging_activate'); + +/** + * Deactivation function + */ +function hvac_ce_staging_deactivate() { + // Remove the test option and role + delete_option('hvac_ce_staging_activated'); + remove_role('hvac_trainer_staging'); + + error_log('[HVAC CE Staging] Plugin deactivated'); +} +register_deactivation_hook(__FILE__, 'hvac_ce_staging_deactivate'); + +/** + * Initialize the plugin + */ +function hvac_ce_staging_init() { + // Add an admin notice + if (is_admin()) { + add_action('admin_notices', 'hvac_ce_staging_admin_notice'); + } +} +add_action('plugins_loaded', 'hvac_ce_staging_init'); + +/** + * Display admin notice about successful activation + */ +function hvac_ce_staging_admin_notice() { + if (get_option('hvac_ce_staging_activated') === 'yes') { + ?> +
+

+

+
+ This is a placeholder for the HVAC Community Events functionality.

'; +} + +// Register shortcodes +add_shortcode('hvac_trainer_dashboard', 'hvac_ce_dummy_shortcode'); +add_shortcode('hvac_community_login', 'hvac_ce_dummy_shortcode'); +add_shortcode('hvac_trainer_registration', 'hvac_ce_dummy_shortcode'); +add_shortcode('hvac_trainer_profile', 'hvac_ce_dummy_shortcode'); +add_shortcode('hvac_event_summary', 'hvac_ce_dummy_shortcode'); +add_shortcode('hvac_email_attendees', 'hvac_ce_dummy_shortcode'); \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/admin/class-zoho-admin.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/admin/class-zoho-admin.php index be6b3417..7a03d9dc 100644 --- a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/admin/class-zoho-admin.php +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/admin/class-zoho-admin.php @@ -75,6 +75,23 @@ class HVAC_Zoho_Admin { $is_configured = file_exists($config_file); $site_url = get_site_url(); $is_staging = strpos($site_url, 'upskillhvac.com') === false; + + // Additional checks for staging domains + $known_staging_domains = array( + 'upskill-staging.measurequick.com', + 'wordpress-974670-5399585.cloudwaysapps.com', + 'localhost', + 'staging', + 'test', + 'dev' + ); + + foreach ($known_staging_domains as $domain) { + if (strpos($site_url, $domain) !== false) { + $is_staging = true; + break; + } + } ?>

Zoho CRM Sync

@@ -85,6 +102,8 @@ class HVAC_Zoho_Admin {

Current site:

Staging mode is active. Data sync will be simulated only. No actual data will be sent to Zoho CRM.

Production sync is only enabled on upskillhvac.com

+

OAuth Redirect URI:

+

If you're having connection issues, please ensure your Zoho OAuth settings match this redirect URI.

@@ -184,11 +203,20 @@ class HVAC_Zoho_Admin { $auth = new HVAC_Zoho_CRM_Auth(); - // Debug connection parameters + // Debug connection parameters and detailed configuration info + $client_id = $auth->get_client_id(); + $client_secret = $auth->get_client_secret(); + $refresh_token = $auth->get_refresh_token(); + HVAC_Logger::info('Checking Zoho configuration', 'ZOHO_TEST', array( - 'client_id_exists' => !empty($auth->get_client_id()), - 'client_secret_exists' => !empty($auth->get_client_secret()), - 'refresh_token_exists' => !empty($auth->get_refresh_token()) + 'client_id_exists' => !empty($client_id), + 'client_secret_exists' => !empty($client_secret), + 'refresh_token_exists' => !empty($refresh_token), + 'client_id_partial' => !empty($client_id) ? substr($client_id, 0, 5) . '...' : 'EMPTY', + 'site_url' => get_site_url(), + 'redirect_uri' => defined('ZOHO_REDIRECT_URI') ? ZOHO_REDIRECT_URI : 'Not defined', + 'is_staging' => strpos(get_site_url(), 'upskillhvac.com') === false ? 'Yes' : 'No', + 'api_base_url' => defined('ZOHO_API_BASE_URL') ? ZOHO_API_BASE_URL : 'Not defined' )); // Test API call @@ -240,12 +268,30 @@ class HVAC_Zoho_Admin { 'full_response' => $response )); + // Prepare comprehensive debug information for the frontend + $debug_info = array( + 'site_url' => get_site_url(), + 'redirect_uri' => defined('ZOHO_REDIRECT_URI') ? ZOHO_REDIRECT_URI : 'Not defined', + 'api_base_url' => defined('ZOHO_API_BASE_URL') ? ZOHO_API_BASE_URL : 'Not defined', + 'client_id_exists' => !empty($client_id), + 'client_secret_exists' => !empty($client_secret), + 'refresh_token_exists' => !empty($refresh_token), + 'php_version' => PHP_VERSION, + 'wp_version' => get_bloginfo('version'), + 'plugin_version' => defined('HVAC_CE_VERSION') ? HVAC_CE_VERSION : 'Not defined', + 'timestamp' => date('Y-m-d H:i:s'), + 'is_staging' => strpos(get_site_url(), 'upskillhvac.com') === false ? 'Yes' : 'No' + ); + + // Detailed error response wp_send_json_error(array( 'message' => 'Connection failed', 'error' => $error_message, 'code' => $error_code, 'details' => $error_details, - 'raw' => json_encode($response) + 'raw' => json_encode($response), + 'debug' => $debug_info, + 'help' => 'Verify that your Zoho credentials are correct and that the redirect URI matches your OAuth configuration in Zoho Developer Console.' )); } } catch (Exception $e) { @@ -256,11 +302,29 @@ class HVAC_Zoho_Admin { 'trace' => $e->getTraceAsString() )); + // Prepare comprehensive debug information for the frontend + $debug_info = array( + 'site_url' => get_site_url(), + 'redirect_uri' => defined('ZOHO_REDIRECT_URI') ? ZOHO_REDIRECT_URI : 'Not defined', + 'api_base_url' => defined('ZOHO_API_BASE_URL') ? ZOHO_API_BASE_URL : 'Not defined', + 'client_id_exists' => !empty($client_id ?? ''), + 'client_secret_exists' => !empty($client_secret ?? ''), + 'refresh_token_exists' => !empty($refresh_token ?? ''), + 'php_version' => PHP_VERSION, + 'wp_version' => get_bloginfo('version'), + 'plugin_version' => defined('HVAC_CE_VERSION') ? HVAC_CE_VERSION : 'Not defined', + 'timestamp' => date('Y-m-d H:i:s'), + 'is_staging' => strpos(get_site_url(), 'upskillhvac.com') === false ? 'Yes' : 'No', + 'exception_type' => get_class($e) + ); + wp_send_json_error(array( 'message' => 'Connection failed due to exception', 'error' => $e->getMessage(), 'file' => $e->getFile() . ':' . $e->getLine(), - 'trace' => $e->getTraceAsString() + 'trace' => $e->getTraceAsString(), + 'debug' => $debug_info, + 'help' => 'This appears to be a code-level exception rather than a Zoho API error. Contact support with the details above.' )); } } diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-fix.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-fix.php new file mode 100644 index 00000000..5c58120c --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-fix.php @@ -0,0 +1,59 @@ +You do not have permission to access this page.'; + } + + // Include the certificate fix template + ob_start(); + include HVAC_CE_PLUGIN_DIR . 'templates/certificates/certificate-fix.php'; + return ob_get_clean(); + } +} + +// Initialize the class +HVAC_Certificate_Fix::instance(); \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php index a07ab8fb..7b17eeab 100644 --- a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php @@ -65,6 +65,7 @@ class HVAC_Community_Events { 'certificates/class-certificate-template.php', // Certificate template 'certificates/class-certificate-security.php', // Certificate security 'certificates/class-certificate-ajax-handler.php', // Certificate AJAX handling + 'certificates/class-certificate-fix.php', // Certificate diagnostic/fix tool 'community/class-email-debug.php' // Email debugging tools ]; // Make sure Login_Handler is loaded first for shortcode registration @@ -286,6 +287,9 @@ class HVAC_Community_Events { // Add generate certificates shortcode add_shortcode('hvac_generate_certificates', array($this, 'render_generate_certificates')); + + // Add certificate fix shortcode (admin only) + add_shortcode('hvac_certificate_fix', array($this, 'render_certificate_fix')); // Remove the event form shortcode as we're using TEC's shortcode instead // add_shortcode('hvac_event_form', array('HVAC_Community_Event_Handler', 'render_event_form')); @@ -389,6 +393,53 @@ class HVAC_Community_Events { return ob_get_clean(); } + /** + * Validate template file for common syntax errors + * @param string $file_path Path to the template file + * @return bool|string True if valid, error message otherwise + */ + private function validate_template_file($file_path) { + // Check if the file exists + if (!file_exists($file_path)) { + return "Template file does not exist: {$file_path}"; + } + + // Get file contents + $content = file_get_contents($file_path); + + // Check for common syntax errors with escaped operators + $common_errors = [ + '\\!==', // Escaped !== + '\\!=' , // Escaped != + '\\!' , // Escaped ! + '\\=' , // Escaped = + '\\>' , // Escaped > + '\\<' , // Escaped < + ]; + + foreach ($common_errors as $error) { + if (strpos($content, $error) !== false) { + // Find the line number + $lines = explode("\n", $content); + $line_number = 0; + foreach ($lines as $i => $line) { + if (strpos($line, $error) !== false) { + $line_number = $i + 1; + break; + } + } + + // Log the error for admin + $filename = basename($file_path); + HVAC_Logger::error("Syntax error detected in {$filename} line {$line_number}: Improper escape sequence {$error}", 'Core'); + + return "Template file contains syntax errors: {$filename} line {$line_number}. Please contact the administrator."; + } + } + + return true; + } + /** * Render certificate reports content */ @@ -410,10 +461,17 @@ class HVAC_Community_Events { // Make sure certificate security is loaded require_once HVAC_CE_PLUGIN_DIR . 'includes/certificates/class-certificate-security.php'; + // Validate the template file before including + $template_path = HVAC_CE_PLUGIN_DIR . 'templates/certificates/template-certificate-reports.php'; + $validation = $this->validate_template_file($template_path); + if ($validation !== true) { + return '
' . esc_html($validation) . '
'; + } + // Include the certificate reports template with error handling try { ob_start(); - include HVAC_CE_PLUGIN_DIR . 'templates/certificates/template-certificate-reports.php'; + include $template_path; return ob_get_clean(); } catch (Exception $e) { return '
Error loading certificate reports: ' . esc_html($e->getMessage()) . '
'; @@ -459,10 +517,17 @@ class HVAC_Community_Events { // Make sure certificate generator is loaded require_once HVAC_CE_PLUGIN_DIR . 'includes/certificates/class-certificate-generator.php'; + // Validate the template file before including + $template_path = HVAC_CE_PLUGIN_DIR . 'templates/certificates/template-generate-certificates.php'; + $validation = $this->validate_template_file($template_path); + if ($validation !== true) { + return '
' . esc_html($validation) . '
'; + } + // Include the generate certificates template with error handling try { ob_start(); - include HVAC_CE_PLUGIN_DIR . 'templates/certificates/template-generate-certificates.php'; + include $template_path; return ob_get_clean(); } catch (Exception $e) { return '
Error loading certificate generation: ' . esc_html($e->getMessage()) . '
'; @@ -473,87 +538,84 @@ class HVAC_Community_Events { * Include custom templates for plugin pages */ public function load_custom_templates($template) { + $custom_template = null; + // Check for dashboard page if (is_page('hvac-dashboard')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/template-hvac-dashboard.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for community-login page if (is_page('community-login')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/page-community-login.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for my-events page if (is_page('my-events')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/page-my-events.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for trainer-profile page if (is_page('trainer-profile')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/template-trainer-profile.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for event-summary page if (is_page('event-summary')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/template-event-summary.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for email-attendees page if (is_page('email-attendees')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/email-attendees/template-email-attendees.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for certificate-reports page if (is_page('certificate-reports')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/certificates/template-certificate-reports.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for generate-certificates page if (is_page('generate-certificates')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/certificates/template-generate-certificates.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for edit-profile page if (is_page('edit-profile')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/template-edit-profile.php'; - if (file_exists($custom_template)) { - return $custom_template; - } } // Check for single event view (temporary) - if ( is_singular( 'tribe_events' ) ) { + if (is_singular('tribe_events')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/single-tribe_events.php'; - if ( file_exists( $custom_template ) ) { + } + + // Process the custom template if one was found + if ($custom_template !== null) { + // Check if file exists + if (file_exists($custom_template)) { + // Validate certificate templates for syntax errors + if (strpos($custom_template, 'certificates/') !== false) { + $validation = $this->validate_template_file($custom_template); + if ($validation !== true) { + // Log error and show friendly message + HVAC_Logger::error("Template validation failed in load_custom_templates: {$validation}", 'Core'); + + // Display error or fallback template + add_action('wp_head', function() use ($validation) { + echo '
There was a problem loading this page. ' . + 'The administrator has been notified. Please try again later.
'; + }); + + // Either fall back to the standard WP template or use a simple error template + return $template; + } + } + + // Template exists and passes validation return $custom_template; } } - - // Add future custom templates here return $template; } // End load_custom_templates diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/certificates/certificate-fix.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/certificates/certificate-fix.php new file mode 100644 index 00000000..9a6ba945 --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/certificates/certificate-fix.php @@ -0,0 +1,628 @@ +prefix . 'hvac_certificates'; + + // Check if the table exists + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if (!$table_exists) { + $messages[] = ['warning', "Certificate table does not exist. Creating it now..."]; + + // Create the table with proper schema + $charset_collate = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE $table_name ( + certificate_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + event_id BIGINT(20) UNSIGNED NOT NULL, + attendee_id BIGINT(20) UNSIGNED NOT NULL, + user_id BIGINT(20) UNSIGNED DEFAULT NULL, + certificate_number VARCHAR(50) NOT NULL, + file_path VARCHAR(255) NOT NULL, + date_generated DATETIME NOT NULL, + generated_by BIGINT(20) UNSIGNED NOT NULL, + revoked TINYINT(1) NOT NULL DEFAULT 0, + revoked_date DATETIME DEFAULT NULL, + revoked_by BIGINT(20) UNSIGNED DEFAULT NULL, + revoked_reason TEXT DEFAULT NULL, + email_sent TINYINT(1) NOT NULL DEFAULT 0, + email_sent_date DATETIME DEFAULT NULL, + PRIMARY KEY (certificate_id), + UNIQUE KEY event_attendee (event_id, attendee_id), + KEY event_id (event_id), + KEY attendee_id (attendee_id), + KEY user_id (user_id), + KEY certificate_number (certificate_number), + KEY revoked (revoked) + ) $charset_collate;"; + + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); + $result = dbDelta($sql); + + // Check if table was created + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if ($table_exists) { + $messages[] = ['success', "Table created successfully!"]; + update_option('hvac_certificates_db_version', '1.0.0'); + } else { + $messages[] = ['error', "Failed to create table. Error: " . $wpdb->last_error]; + return ['success' => false, 'messages' => $messages]; + } + } else { + $messages[] = ['success', "Certificate table exists: $table_name"]; + + // Check if the table has the expected structure + $messages[] = ['info', "Checking table structure..."]; + + // Get columns + $columns = $wpdb->get_results("DESCRIBE $table_name"); + $column_names = array_map(function($col) { return $col->Field; }, $columns); + + // Expected columns + $expected_columns = [ + 'certificate_id', + 'event_id', + 'attendee_id', + 'user_id', + 'certificate_number', + 'file_path', + 'date_generated', + 'generated_by', + 'revoked', + 'revoked_date', + 'revoked_by', + 'revoked_reason', + 'email_sent', + 'email_sent_date' + ]; + + // Check for missing columns + $missing_columns = array_diff($expected_columns, $column_names); + + if (!empty($missing_columns)) { + $messages[] = ['warning', "Table is missing columns: " . implode(", ", $missing_columns)]; + + // Create migration to add missing columns + $messages[] = ['info', "Attempting to fix missing columns..."]; + + // Use dbDelta to update table structure + $charset_collate = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE $table_name ( + certificate_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + event_id BIGINT(20) UNSIGNED NOT NULL, + attendee_id BIGINT(20) UNSIGNED NOT NULL, + user_id BIGINT(20) UNSIGNED DEFAULT NULL, + certificate_number VARCHAR(50) NOT NULL, + file_path VARCHAR(255) NOT NULL, + date_generated DATETIME NOT NULL, + generated_by BIGINT(20) UNSIGNED NOT NULL, + revoked TINYINT(1) NOT NULL DEFAULT 0, + revoked_date DATETIME DEFAULT NULL, + revoked_by BIGINT(20) UNSIGNED DEFAULT NULL, + revoked_reason TEXT DEFAULT NULL, + email_sent TINYINT(1) NOT NULL DEFAULT 0, + email_sent_date DATETIME DEFAULT NULL, + PRIMARY KEY (certificate_id), + UNIQUE KEY event_attendee (event_id, attendee_id), + KEY event_id (event_id), + KEY attendee_id (attendee_id), + KEY user_id (user_id), + KEY certificate_number (certificate_number), + KEY revoked (revoked) + ) $charset_collate;"; + + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); + $result = dbDelta($sql); + + // Check if fix was successful + $columns = $wpdb->get_results("DESCRIBE $table_name"); + $column_names = array_map(function($col) { return $col->Field; }, $columns); + $missing_columns = array_diff($expected_columns, $column_names); + + if (empty($missing_columns)) { + $messages[] = ['success', "Table structure fixed successfully!"]; + update_option('hvac_certificates_db_version', '1.0.0'); + } else { + $messages[] = ['error', "Failed to fix all columns. Still missing: " . implode(", ", $missing_columns)]; + return ['success' => false, 'messages' => $messages]; + } + } else { + $messages[] = ['success', "Table structure is correct."]; + } + } + + // Check and create certificate directory + $messages[] = ['info', "Checking certificate directory..."]; + + $upload_dir = wp_upload_dir(); + $cert_dir = $upload_dir['basedir'] . '/' . get_option('hvac_certificate_storage_path', 'hvac-certificates'); + + if (!file_exists($cert_dir)) { + $messages[] = ['warning', "Certificate directory does not exist. Creating it now..."]; + wp_mkdir_p($cert_dir); + + if (file_exists($cert_dir)) { + $messages[] = ['success', "Certificate directory created: $cert_dir"]; + } else { + $messages[] = ['error', "Failed to create certificate directory."]; + return ['success' => false, 'messages' => $messages]; + } + } else { + $messages[] = ['success', "Certificate directory exists: $cert_dir"]; + } + + // Check and set certificate options + $messages[] = ['info', "Checking certificate options..."]; + + if (false === get_option('hvac_certificate_counter')) { + add_option('hvac_certificate_counter', 0); + $messages[] = ['success', "Added hvac_certificate_counter option"]; + } + + if (false === get_option('hvac_certificate_prefix')) { + add_option('hvac_certificate_prefix', 'HVAC-'); + $messages[] = ['success', "Added hvac_certificate_prefix option"]; + } + + if (false === get_option('hvac_certificate_storage_path')) { + add_option('hvac_certificate_storage_path', 'hvac-certificates'); + $messages[] = ['success', "Added hvac_certificate_storage_path option"]; + } + + return ['success' => true, 'messages' => $messages]; +} + +// Function to test certificate classes +function hvac_test_certificate_classes() { + $messages = []; + + // Test certificate installer class + $messages[] = ['info', "Testing certificate installer class..."]; + + if (!class_exists('HVAC_Certificate_Installer')) { + $messages[] = ['warning', "Certificate installer class not found, requiring file."]; + + // Try to load class file + $installer_file = HVAC_CE_PLUGIN_DIR . 'includes/certificates/class-certificate-installer.php'; + + if (file_exists($installer_file)) { + require_once $installer_file; + $messages[] = ['success', "Certificate installer file loaded."]; + } else { + $messages[] = ['error', "Certificate installer file not found: " . $installer_file]; + return ['success' => false, 'messages' => $messages]; + } + } + + // Test certificate manager class + $messages[] = ['info', "Testing certificate manager class..."]; + + if (!class_exists('HVAC_Certificate_Manager')) { + $messages[] = ['warning', "Certificate manager class not found, requiring file."]; + + // Try to load class file + $manager_file = HVAC_CE_PLUGIN_DIR . 'includes/certificates/class-certificate-manager.php'; + + if (file_exists($manager_file)) { + require_once $manager_file; + $messages[] = ['success', "Certificate manager file loaded."]; + } else { + $messages[] = ['error', "Certificate manager file not found: " . $manager_file]; + return ['success' => false, 'messages' => $messages]; + } + } + + // Test certificate security class + $messages[] = ['info', "Testing certificate security class..."]; + + if (!class_exists('HVAC_Certificate_Security')) { + $messages[] = ['warning', "Certificate security class not found, requiring file."]; + + // Try to load class file + $security_file = HVAC_CE_PLUGIN_DIR . 'includes/certificates/class-certificate-security.php'; + + if (file_exists($security_file)) { + require_once $security_file; + $messages[] = ['success', "Certificate security file loaded."]; + } else { + $messages[] = ['error', "Certificate security file not found: " . $security_file]; + return ['success' => false, 'messages' => $messages]; + } + } + + // Try to create instances of each class + try { + $installer = HVAC_Certificate_Installer::instance(); + $messages[] = ['success', "Certificate installer instance created."]; + } catch (Exception $e) { + $messages[] = ['error', "Failed to create certificate installer instance: " . $e->getMessage()]; + return ['success' => false, 'messages' => $messages]; + } + + try { + $manager = HVAC_Certificate_Manager::instance(); + $messages[] = ['success', "Certificate manager instance created."]; + } catch (Exception $e) { + $messages[] = ['error', "Failed to create certificate manager instance: " . $e->getMessage()]; + return ['success' => false, 'messages' => $messages]; + } + + try { + $security = HVAC_Certificate_Security::instance(); + $messages[] = ['success', "Certificate security instance created."]; + } catch (Exception $e) { + $messages[] = ['error', "Failed to create certificate security instance: " . $e->getMessage()]; + return ['success' => false, 'messages' => $messages]; + } + + return ['success' => true, 'messages' => $messages]; +} + +// Function to run a simple query to test certificate table +function hvac_test_certificate_query() { + global $wpdb; + $messages = []; + + $messages[] = ['info', "Testing certificate queries..."]; + + // Check if table exists + $table_name = $wpdb->prefix . 'hvac_certificates'; + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if (!$table_exists) { + $messages[] = ['error', "Certificate table does not exist, cannot run queries."]; + return ['success' => false, 'messages' => $messages]; + } + + // Try to get certificate count + $count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name"); + + if ($wpdb->last_error) { + $messages[] = ['error', "Query error: " . $wpdb->last_error]; + return ['success' => false, 'messages' => $messages]; + } + + $messages[] = ['success', "Certificate count query successful. Found $count certificates."]; + + // If no certificates found, create a test certificate + if ($count == 0) { + $messages[] = ['info', "No certificates found. Creating a test certificate..."]; + + // Get a published event for the test + $events = get_posts([ + 'post_type' => 'tribe_events', + 'posts_per_page' => 1, + 'post_status' => 'publish' + ]); + + if (empty($events)) { + $messages[] = ['warning', "No published events found for test certificate."]; + } else { + $event_id = $events[0]->ID; + $attendee_id = 99999; // Test attendee ID + $date_generated = current_time('mysql'); + + // Insert test certificate + $insert_result = $wpdb->insert( + $table_name, + [ + 'event_id' => $event_id, + 'attendee_id' => $attendee_id, + 'user_id' => get_current_user_id(), + 'certificate_number' => 'TEST-' . date('Y') . '-00001', + 'file_path' => 'hvac-certificates/test-certificate.pdf', + 'date_generated' => $date_generated, + 'generated_by' => get_current_user_id(), + 'revoked' => 0, + 'email_sent' => 0 + ], + [ + '%d', // event_id + '%d', // attendee_id + '%d', // user_id + '%s', // certificate_number + '%s', // file_path + '%s', // date_generated + '%d', // generated_by + '%d', // revoked + '%d' // email_sent + ] + ); + + if ($insert_result) { + $certificate_id = $wpdb->insert_id; + $messages[] = ['success', "Test certificate created with ID $certificate_id"]; + } else { + $messages[] = ['error', "Failed to create test certificate: " . $wpdb->last_error]; + } + } + } + + return ['success' => true, 'messages' => $messages]; +} + +// Function to fix HTML comments in template files +function hvac_fix_template_comments() { + $messages = []; + + $templates = [ + 'template-certificate-reports.php', + 'template-generate-certificates.php' + ]; + + foreach ($templates as $template) { + $template_path = HVAC_CE_PLUGIN_DIR . 'templates/certificates/' . $template; + + if (file_exists($template_path)) { + $messages[] = ['info', "Checking $template for comment issues..."]; + + $content = file_get_contents($template_path); + $fixed = false; + + // Fix HTML comments + if (strpos($content, '<\\!--') !== false) { + $messages[] = ['warning', "Found invalid HTML comment tags in $template. Fixing..."]; + $content = str_replace('<\\!--', ' +
+

Certificate Statistics

+ +
+
+

Total Certificates

+
+
+ +
+

Active Certificates

+
+
+ +
+

Revoked Certificates

+
+
+ +
+

Emailed Certificates

+
+
+
+
+ + +
+

Certificate Filters

+ +
+
+ + +
+ +
+ + +
+ +
+ +
+
+
+ + +
+

Certificate Listing

+ + +
+

No certificates found matching your filters.

+ + 0 || (isset($_GET['filter_status']) && $_GET['filter_status'] !== 'active')) : ?> +

Clear filters to see all your certificates.

+ +

Generate certificates for your event attendees on the Generate Certificates page.

+ +
+ +
+ + + + + + + + + + + + + certificate_number; + $event_id = $certificate->event_id; + $attendee_id = $certificate->attendee_id; + $generated_date = date_i18n(get_option('date_format'), strtotime($certificate->date_generated)); + $is_revoked = (bool) $certificate->revoked; + $is_emailed = (bool) $certificate->email_sent; + + // Get event and attendee information + $event_title = get_the_title($event_id); + $attendee_name = get_post_meta($attendee_id, '_tribe_tickets_full_name', true); + if (empty($attendee_name)) { + $attendee_name = 'Attendee #' . $attendee_id; + } + + // Status text and class + $status_text = $is_revoked ? 'Revoked' : 'Active'; + $status_class = $is_revoked ? 'hvac-status-revoked' : 'hvac-status-active'; + ?> + + + + + + + + + + +
Certificate #EventAttendeeDate GeneratedStatusActions
+ + + + + + + + + + + + + + Certificate has been revoked + +
+
+ +
+ + +
+
+ × +

Certificate Preview

+ +
+ + + + admin_url('admin-ajax.php'), + 'viewNonce' => wp_create_nonce('hvac_view_certificate'), + 'emailNonce' => wp_create_nonce('hvac_email_certificate'), + 'revokeNonce' => wp_create_nonce('hvac_revoke_certificate') +)); + +// Footer +get_footer(); +?> \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/template-hvac-dashboard.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/template-hvac-dashboard.php index 49a44569..0aaaefb2 100644 --- a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/template-hvac-dashboard.php +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/template-hvac-dashboard.php @@ -56,6 +56,8 @@ get_header(); // Use theme's header Create Event My Events + Generate Certificates + Certificate Reports View Profile Logout diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/tmp-fixes/fix-certificate-reports.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/tmp-fixes/fix-certificate-reports.php new file mode 100644 index 00000000..922b01fd --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/tmp-fixes/fix-certificate-reports.php @@ -0,0 +1,362 @@ + "\033[32m", // Green + 'error' => "\033[31m", // Red + 'warning' => "\033[33m", // Yellow + 'info' => "\033[36m", // Cyan + 'reset' => "\033[0m", // Reset + ]; + + echo $colors[$type] . "[" . strtoupper($type) . "] " . $message . $colors['reset'] . PHP_EOL; +} + +// Function to check and create certificate tables +function check_and_create_certificate_tables() { + global $wpdb; + + print_status("Checking certificate tables..."); + + // Define table name + $table_name = $wpdb->prefix . 'hvac_certificates'; + + // Check if the table exists + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if (!$table_exists) { + print_status("Certificate table does not exist. Creating it now...", 'warning'); + + // Create the table with proper schema + $charset_collate = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE $table_name ( + certificate_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + event_id BIGINT(20) UNSIGNED NOT NULL, + attendee_id BIGINT(20) UNSIGNED NOT NULL, + user_id BIGINT(20) UNSIGNED DEFAULT NULL, + certificate_number VARCHAR(50) NOT NULL, + file_path VARCHAR(255) NOT NULL, + date_generated DATETIME NOT NULL, + generated_by BIGINT(20) UNSIGNED NOT NULL, + revoked TINYINT(1) NOT NULL DEFAULT 0, + revoked_date DATETIME DEFAULT NULL, + revoked_by BIGINT(20) UNSIGNED DEFAULT NULL, + revoked_reason TEXT DEFAULT NULL, + email_sent TINYINT(1) NOT NULL DEFAULT 0, + email_sent_date DATETIME DEFAULT NULL, + PRIMARY KEY (certificate_id), + UNIQUE KEY event_attendee (event_id, attendee_id), + KEY event_id (event_id), + KEY attendee_id (attendee_id), + KEY user_id (user_id), + KEY certificate_number (certificate_number), + KEY revoked (revoked) + ) $charset_collate;"; + + // Use dbDelta to create or update table + $result = dbDelta($sql); + + // Check if table was created + $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name; + + if ($table_exists) { + print_status("Table created successfully!", 'success'); + update_option('hvac_certificates_db_version', '1.0.0'); + } else { + print_status("Failed to create table. Error: " . $wpdb->last_error, 'error'); + return false; + } + } else { + print_status("Certificate table exists: $table_name", 'success'); + + // Check if the table has the expected structure + print_status("Checking table structure...", 'info'); + + // Get columns + $columns = $wpdb->get_results("DESCRIBE $table_name"); + $column_names = array_map(function($col) { return $col->Field; }, $columns); + + // Expected columns + $expected_columns = [ + 'certificate_id', + 'event_id', + 'attendee_id', + 'user_id', + 'certificate_number', + 'file_path', + 'date_generated', + 'generated_by', + 'revoked', + 'revoked_date', + 'revoked_by', + 'revoked_reason', + 'email_sent', + 'email_sent_date' + ]; + + // Check for missing columns + $missing_columns = array_diff($expected_columns, $column_names); + + if (!empty($missing_columns)) { + print_status("Table is missing columns: " . implode(", ", $missing_columns), 'warning'); + + // Create migration to add missing columns + print_status("Attempting to fix missing columns...", 'info'); + + // Use dbDelta to update table structure + $charset_collate = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE $table_name ( + certificate_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + event_id BIGINT(20) UNSIGNED NOT NULL, + attendee_id BIGINT(20) UNSIGNED NOT NULL, + user_id BIGINT(20) UNSIGNED DEFAULT NULL, + certificate_number VARCHAR(50) NOT NULL, + file_path VARCHAR(255) NOT NULL, + date_generated DATETIME NOT NULL, + generated_by BIGINT(20) UNSIGNED NOT NULL, + revoked TINYINT(1) NOT NULL DEFAULT 0, + revoked_date DATETIME DEFAULT NULL, + revoked_by BIGINT(20) UNSIGNED DEFAULT NULL, + revoked_reason TEXT DEFAULT NULL, + email_sent TINYINT(1) NOT NULL DEFAULT 0, + email_sent_date DATETIME DEFAULT NULL, + PRIMARY KEY (certificate_id), + UNIQUE KEY event_attendee (event_id, attendee_id), + KEY event_id (event_id), + KEY attendee_id (attendee_id), + KEY user_id (user_id), + KEY certificate_number (certificate_number), + KEY revoked (revoked) + ) $charset_collate;"; + + $result = dbDelta($sql); + + // Check if fix was successful + $columns = $wpdb->get_results("DESCRIBE $table_name"); + $column_names = array_map(function($col) { return $col->Field; }, $columns); + $missing_columns = array_diff($expected_columns, $column_names); + + if (empty($missing_columns)) { + print_status("Table structure fixed successfully!", 'success'); + update_option('hvac_certificates_db_version', '1.0.0'); + } else { + print_status("Failed to fix all columns. Still missing: " . implode(", ", $missing_columns), 'error'); + return false; + } + } else { + print_status("Table structure is correct.", 'success'); + } + } + + // Check and create certificate directory + print_status("Checking certificate directory...", 'info'); + + $upload_dir = wp_upload_dir(); + $cert_dir = $upload_dir['basedir'] . '/' . get_option('hvac_certificate_storage_path', 'hvac-certificates'); + + if (!file_exists($cert_dir)) { + print_status("Certificate directory does not exist. Creating it now...", 'warning'); + wp_mkdir_p($cert_dir); + + if (file_exists($cert_dir)) { + print_status("Certificate directory created: $cert_dir", 'success'); + } else { + print_status("Failed to create certificate directory.", 'error'); + return false; + } + } else { + print_status("Certificate directory exists: $cert_dir", 'success'); + } + + // Check and set certificate options + print_status("Checking certificate options...", 'info'); + + if (false === get_option('hvac_certificate_counter')) { + add_option('hvac_certificate_counter', 0); + print_status("Added hvac_certificate_counter option", 'success'); + } + + if (false === get_option('hvac_certificate_prefix')) { + add_option('hvac_certificate_prefix', 'HVAC-'); + print_status("Added hvac_certificate_prefix option", 'success'); + } + + if (false === get_option('hvac_certificate_storage_path')) { + add_option('hvac_certificate_storage_path', 'hvac-certificates'); + print_status("Added hvac_certificate_storage_path option", 'success'); + } + + return true; +} + +// Fix certificate template closing PHP tag issue +function fix_template_closing_tags() { + print_status("Checking template-certificate-reports.php for syntax issues...", 'info'); + + $plugin_dir = WP_CONTENT_DIR . '/plugins/hvac-community-events/'; + $template_file = $plugin_dir . 'templates/certificates/template-certificate-reports.php'; + + if (file_exists($template_file)) { + $content = file_get_contents($template_file); + + // Find and fix HTML comment tags (