Jake Vanderwerf
2026-05-12 c32ed859f4abd1591c882f4f2a6ee16b1ec275e2
inc/blocks/FormBlock.php
@@ -1,11 +1,9 @@
<?php
namespace JVBase\blocks;
use JVBase\managers\CacheManager;
use JVBase\meta\MetaManager;
use JVBase\managers\CloudflareTurnstile;
use Exception;
use WP_Block;
use JVBase\managers\Cache;
use JVBase\meta\Form;
use JVBase\base\Site;
if (!defined('ABSPATH')) {
   exit; // Exit if accessed directly
@@ -18,8 +16,8 @@
 */
class FormBlock
{
   protected static FormBlock|null $instance = null;
   protected CacheManager $cache;
   protected static ?FormBlock $instance = null;
   protected Cache $cache;
   protected array $forms;
   protected string $form_contact;
@@ -35,7 +33,7 @@
   public function __construct()
   {
      $this->cache = new CacheManager('form_blocks', HOUR_IN_SECONDS);
      $this->cache = Cache::for('forms', WEEK_IN_SECONDS);
      // Initialize forms from filter
      $this->forms = $this->registerForms();
@@ -46,14 +44,36 @@
      // Register forms data for the block editor
      add_action('enqueue_block_editor_assets', [$this, 'localizeFormsData']);
      add_action('init', [$this, 'registerBlock']);
      add_filter('render_block', [$this, 'maybeEnqueueScripts'], 10, 2);
   }
   /**
    * Enqueue scripts when rendering form block
    */
   public function maybeEnqueueScripts(string $block_content, array $block): string
   {
      // Only process our form blocks
      if ($block['blockName'] !== 'jvb/forms') {
         return $block_content;
      }
      // Enqueue Turnstile if needed
      if (Site::hasIntegration('cloudflare')) {
         $cloudflare = JVB()->connect('cloudflare');
         if ($cloudflare->isSetUp()) {
            $cloudflare->enqueueTurnstileScripts();
         }
      }
      return $block_content;
   }
   public function registerBlock()
   {
      register_block_type($this->path, [
         'render_callback' => [$this, 'render']
         'render_callback' => [$this, 'render'],
         'style' => 'jvb-icons-forms',
      ]);
   }
@@ -94,9 +114,7 @@
         'sections' => []
      ];
      $config = array_merge($defaults, $config);
      return $config;
      return array_merge($defaults, $config);
   }
   /**
@@ -111,16 +129,12 @@
      }
      $cache_key = $this->cache->generateKey($block);
      $cached = $this->cache->get($cache_key);
      if ($cached) {
         return $cached;
      }
      $rendered = $this->renderForm($form_type, $block);
      $this->cache->set($cache_key, $rendered);
      return $rendered;
      return $this->cache->remember(
         $cache_key,
         function() use ($form_type, $block) {
            return $this->renderForm($form_type, $block);
         }
      );
   }
   /**
@@ -165,7 +179,6 @@
      $this->renderTurnstile();
      $this->renderFormEnd($type, $form_id);
      echo '</div>';
      return ob_get_clean();
   }
@@ -263,8 +276,8 @@
         }
      }
      echo '<form id="' . esc_attr($form_id) . '" data-form-id="'.esc_attr($type).'" data-save="form" data-noautosave>';
      wp_nonce_field('jvb_form_' . $type);
      echo '<form id="' . esc_attr($form_id) . '" data-form-id="'.esc_attr($type).'" data-save="form">';
//    wp_nonce_field('jvb_form_' . $type);
   }
   /**
@@ -278,30 +291,36 @@
         return;
      }
      // Create MetaManager instance for form rendering
      $meta = new MetaManager();
      // If sections are defined, render in sections
      if (!empty($form_config['sections'])) {
         $this->renderSections($type, $meta);
         $this->renderSections($type);
      } else {
         echo jvbFormStatus();
         // Render fields directly
         foreach ($form_config['fields'] as $field_name => $field_config) {
            $meta->render('form', $field_name, $field_config);
            echo Form::render($field_name, null, $field_config);
         }
         $submit_text = $form_config['submit'] ?? 'Submit';
         echo '<button type="submit" class="button primary">' . esc_html($submit_text) . '</button>';
      }
   }
   /**
    * Render form sections
    */
   protected function renderSections(string $type, MetaManager $meta): void
   protected function renderSections(string $type): void
   {
      $form_config = $this->forms[$type];
      $sections = $form_config['sections'];
      $fields = $form_config['fields'];
      $total = count($sections);
      echo '<div class="container">';
      if ($total > 1) {
         echo '<div class="form-progress">';
         jvbRenderProgressBar('<span class="step-text">Step <span class="current">1</span> of ' . $total . '</span>');
         echo '</div>';
      }
      // Render navigation if multiple sections
      if (count($sections) > 1) {
@@ -311,21 +330,24 @@
            $active_class = $i === 1 ? ' active' : '';
            $aria_selected = $i === 1 ? 'true' : 'false';
            echo '<button type="button" class="tab' . $active_class . '" data-tab="' . esc_attr($slug) . '" role="tab" aria-selected="' . $aria_selected . '">';
            echo '<button type="button" class="tab' . $active_class . '" data-tab="' . esc_attr($slug) . '" data-step="'.$i.'" role="tab" aria-selected="' . $aria_selected . '">';
            echo '<span class="step-number">' . $i . '</span>';
            echo '<h2>' . esc_html($section['label'] ?? $section) . '</h2>';
            echo '</button>';
            $i++;
         }
         echo '</nav>';
      }
      echo jvbFormStatus();
      // Render section content
      $i = 0;
      $total = count($sections);
      foreach ($sections as $slug => $section) {
         $active_class = $i === 0 ? ' active' : '';
         $is_last = $i === ($total -1);
         echo '<section id="' . esc_attr($slug) . '" class="tab-content' . $active_class . '" data-tab="' . esc_attr($slug) . '" role="tabpanel">';
         echo '<section id="' . esc_attr($slug) . '" class="tab-content' . $active_class . '" data-tab="' . esc_attr($slug) . '" data-step="'.($i + 1).'" role="tabpanel">';
         if (is_array($section) && !empty($section['title'])) {
            echo '<h2>' . esc_html($section['title']) . '</h2>';
@@ -341,17 +363,33 @@
         });
         foreach ($section_fields as $field_name => $field_config) {
            $meta->render('form', $field_name, $field_config);
            echo Form::render($field_name, null, $field_config);
         }
         if ($i === ($total - 1)){
            $submit_text = $form_config['submit'] ?? 'Submit';
            // Submit button
            echo '<div class="form-actions">';
            echo '<button type="submit">' . esc_html($submit_text) . '</button>';
            echo '</div>';
         // Add step navigation buttons
         echo '<div class="step-navigation row btw">';
         if ($i > 0) {
            echo '<button type="button" class="button secondary prev-step" data-action="prev-step">';
            echo jvbIcon('caret-left');
            echo '<span>Previous</span>';
            echo '</button>';
         } else {
            echo '<div></div>'; // Spacer for flex layout
         }
         if ($is_last) {
            $submit_text = $form_config['submit'] ?? 'Submit';
            echo '<button type="submit" class="button primary">' . esc_html($submit_text) . '</button>';
         } else {
            echo '<button type="button" class="button primary next-step" data-action="next-step">';
            echo '<span>Next Step</span>';
            echo jvbIcon('caret-right');
            echo '</button>';
         }
         echo '</div>'; // .step-navigation
         echo '</section>';
         $i++;
      }
@@ -364,7 +402,7 @@
    */
   protected function renderTurnstile(): void
   {
      if (!jvbSiteUsesCloudflare()) {
      if (!Site::hasIntegration('cloudflare')) {
         return;
      }
@@ -389,19 +427,6 @@
      echo '<input type="hidden" name="timestamp" value="' . time() . '">';
      echo '</form>';
      echo '<template class="formSummary">
      <section class="form-summary">
      <h2></h2>
      <div class="message"><p>You\'ll get an email with this information, too. If you need to make any changes, respond to that email.</p></div>
      <h3>Summary:</h3>';
      foreach($form_config['fields'] as $field=>$config) {
         $label = $config['summaryTitle'] ?? $config['label'];
         echo '<div id="'.$field.'"><h4>'.$label.'</h4><div></div></div>';
      }
      echo '</section></template>';
   }
   /**
@@ -423,11 +448,6 @@
         ];
      }
      error_log('Form Localization: '.print_r([
         'formTypes' => $form_types,
         'availableForms' => $this->forms,
         'nonce'        => wp_create_nonce('jvbForm')
      ], true));
      wp_localize_script('jvb-forms-editor-script', 'jvbFormsData', [
         'formTypes' => $form_types,
         'availableForms' => $this->forms,