Jake Vanderwerf
2026-03-03 772462eeca3002a1d52508aeba485aab2b4742ad
inc/integrations/Integrations.php
@@ -2,10 +2,12 @@
namespace JVBase\integrations;
use Exception;
use JVBase\managers\CacheManager;
use JVBase\managers\UploadManager;
use JVBase\meta\MetaManager;
use JVBase\managers\Cache;
use JVBase\meta\Form;
use JVBase\meta\Meta;
use JVBase\managers\ErrorHandler;
use JVBase\registrar\helpers\AddIntegrationFields;
use JVBase\registrar\Registrar;
use WP_Error;
use WP_Post;
use WP_REST_Request;
@@ -91,12 +93,13 @@
      'test_connection' => 'Test Connection',
   ];
   protected array $allowedContent = [];
   /**
    * Caching Configuration
    */
   protected ?string $cacheName = null;
   protected CacheManager $cache;
   protected Cache $cache;
   protected array $cacheStrategy = [
      'aggressive' => 3600,  // 1 hour for stable data (e.g., profile info)
      'moderate' => 300,     // 5 minutes for semi-dynamic data (e.g., posts)
@@ -131,8 +134,8 @@
      'update' => false,     // Can update already-shared posts
      'delete' => false,     // Can remove posts from the service
   ];
   protected array $syncPostTypes = []; // Post types that can be synced (e.g., ['artwork', 'tattoo']): usually built by querying the global JVB_CONTENT if the integration name exists as a key in [ 'integrations' => []]
   protected array $syncTaxonomies = []; // Post types that can be synced (e.g., ['artwork', 'tattoo']): usually built by querying the global JVB_CONTENT if the integration name exists as a key in [ 'integrations' => []]
   protected array $syncPostTypes = []; // Post types that can be synced (e.g., ['artwork', 'tattoo']): usually built by Registrar.php if the integration name exists as a key in [ 'integrations' => []]
   protected array $syncTaxonomies = []; // Post types that can be synced (e.g., ['artwork', 'tattoo']): usually built by Registrar.php if the integration name exists as a key in [ 'integrations' => []]
   protected array $contentTypes = [];   // Integration's available content types. Set by child classes' getContentTypes
   protected bool $has_content = false; // Whether integration has content that can sync
   /**
@@ -167,7 +170,7 @@
   {
      $this->cacheName = $this->cacheName ?: $this->service_name;
      $this->userID = $userID;
      $this->cache = CacheManager::for('integrations_' . $this->cacheName, $this->ttl);
      $this->cache = Cache::for('integrations_' . $this->cacheName, $this->ttl);
      // Load error stats from cache
      $this->loadErrorStats();
@@ -295,12 +298,10 @@
      $postTypes = get_option($key, false);
      if (!$postTypes) {
         $postTypes = [];
         // Get from JVB_CONTENT
         foreach (JVB_CONTENT as $type => $config) {
            if (array_key_exists('integrations', $config) && array_key_exists($this->service_name, $config['integrations'])) {
               $postTypes[] = $type;
         foreach (Registrar::getRegistered('post') as $registrar) {
            $registrar = Registrar::getInstance($registrar);
            if ($registrar->hasIntegration($this->service_name)) {
               $postTypes[] = $registrar->getSlug();
            }
         }
@@ -318,11 +319,9 @@
      if (!$taxonomies) {
         // Combine both content and taxonomy filtering
         $taxonomies = [];
         // Get from JVB_TAXONOMY (content taxonomies)
         foreach (JVB_TAXONOMY as $type => $config) {
            if (jvbCheck('is_content', $config) &&
               isset($config['integrations'][$this->service_name])) {
               $taxonomies[] = $type;
         foreach (Registrar::getFeatured('is_content', 'term') as $registrar) {
            if ($registrar->hasIntegration($this->service_name)) {
               $taxonomies[] = $registrar->getSlug();
            }
         }
@@ -669,7 +668,7 @@
   protected function clearCache():array
   {
      $success = $this->cache->clear();
      $success = $this->cache->flush();
      return [
         'success'   => $success,
      ];
@@ -2081,20 +2080,11 @@
    */
   protected function mapFieldsToService(int $postID, array $mapping): array
   {
      $meta_manager = new MetaManager($postID, 'post');
      $post = get_post($postID);
      $meta_manager = Meta::forPost($postID);
      $service_data = [];
      foreach ($mapping as $wp_field => $service_field) {
         $value = null;
         // Check if it's a post field
         if (property_exists($post, $wp_field)) {
            $value = $post->$wp_field;
         } else {
            // It's a meta field
            $value = $meta_manager->getValue($wp_field);
         }
         $value = $meta_manager->get($wp_field);
         if ($value !== null && $value !== '') {
            $this->setNestedValue($service_data, $service_field, $value);
@@ -2133,23 +2123,34 @@
    */
   public function handleSavePost(int $postID, WP_Post $post, bool $update): void
   {
      if (jvbNoSaveIt($postID, $post)) {
      if (!$postID || $postID === 0) {
         return;
      }
      $postType = jvbNoBase($post->post_type);
      if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
      if (wp_is_post_revision($postID)) return;
      $registrar = Registrar::getInstance($postType);
      if (!$registrar){
         return;
      }
      if (empty($this->syncPostTypes)) {
         return;
      }
      $config = JVB_CONTENT[jvbNoBase($post->post_type)]??null;
      if (!$config) {
         return;
      }
      $settings = $config['integrations'][$this->service_name]??null;
      $settings = $registrar->hasIntegration($this->service_name)??null;
      if (!$settings) {
         return;
      }
      $settings = $registrar->getIntegrationConfig($this->service_name);
      if (!$settings){
         return;
      }
      $fields = $this->getSyncFields($postID, 'post', ['schedule_'.$this->service_name]);
      if (!$fields['share_to_'.$this->service_name]) {
         return;
@@ -2169,7 +2170,7 @@
   protected function getSyncFields(int $postID, string $type, array $additional = []):array
   {
      $meta = new MetaManager($postID, $type);
      $meta = new Meta($postID, $type);
      $fieldsToCheck = [
         'share_to_' . $this->service_name,
         '_keep_synced_' . $this->service_name,
@@ -2252,13 +2253,13 @@
      if (!in_array($noBase, $this->syncTaxonomies)) {
         return;
      }
      // Check if taxonomy is content-type
      $config = JVB_TAXONOMY[$noBase] ?? null;
      if (!$config || !($config['is_content'] ?? false)) {
      $registrar = Registrar::getInstance($noBase);
      if (!$registrar->hasFeature('is_content')) {
         return;
      }
      $settings = $config['integrations'][$this->service_name] ?? null;
      $settings = $registrar->getIntegrationConfig($this->service_name);
      if (!$settings) {
         return;
      }
@@ -2930,7 +2931,7 @@
         return '';
      }
      $meta = new MetaManager($this->userID, 'integrations');
      $meta = Meta::forOptions($this->userID.'_integrations');
      $is_connected = $this->isSetUp();
      $credentials = $this->getCredentials();
@@ -3007,7 +3008,7 @@
                  $config['value'] = $credentials[$name]??'';
                  $config['autocomplete'] = 'off';
                  $config['base'] = $this->service_name.'_';
                  $meta->render('form', $name, $config);
                  echo Form::render($name, '', $config);
               }
            }
            if ($this->handleWebhooks) {
@@ -3038,7 +3039,7 @@
                     $config['value'] = $credentials[$name]??'';
                     $config['base'] = $this->service_name.'_';
                     $config['autocomplete'] = 'off';
                     $meta->render('form', $name, $config);
                     Form::render($name,null, $config);
                  }
                  ?>
               </details>
@@ -3277,7 +3278,7 @@
      if (empty($types)) {
         return;
      }
      $meta = new MetaManager($this->userID, 'integrations');
      $meta = Meta::forOptions($this->userID.'_integrations');
      ?>
      <form>
         <h1><?= $this->title?> Defaults:</h1>
@@ -3289,16 +3290,19 @@
            $config['base'] = $this->service_name.'_';
            $config['autocomplete'] = 'off';
            $meta->render('form', $name, $config);
            echo Form::render($name, null, $config);
         }
         foreach ($this->syncPostTypes as $type) {
            $config = JVB_CONTENT[$type];
            $registrar = Registrar::getInstance($type);
            $icon = $registrar->getIcon();
            $icon = $icon === '' ? jvbDefaultIcon() : $icon;
            ?>
            <details>
               <summary><?= jvbIcon($config['icon']) ?><?= $config['singular']?> Defaults</summary>
               <summary><?= jvbIcon($icon) ?><?= $registrar->getSingular()?> Defaults</summary>
               <?php
               $fields = new \JVBase\registry\providers\IntegrationFieldProvider();
               $fields = $fields->getIntegrationFields($this->service_name, $config);
               $fields = new AddIntegrationFields($this->service_name);
               $fields = $fields->getIntegrationFields();
               foreach($fields as $name=>$c) {
                  $c['required'] = false;
                  if ($c['type'] === 'number') {
@@ -3309,7 +3313,7 @@
                     $c['hint'] = $c['description'];
                     unset($c['description']);
                  }
                  $meta->render('form', $name, $c);
                  echo Form::render($name, null, $c);
               }
               ?>
            </details>
@@ -3339,17 +3343,16 @@
      $enabled = get_option($key);
      if (!$enabled) {
         $enabled = [];
         foreach (array_merge(JVB_CONTENT, JVB_TAXONOMY) as $content => $config) {
            if (!array_key_exists('integrations', $config)) {
         foreach (Registrar::getRegistered() as $registrar) {
            $registrar = Registrar::getInstance($registrar);
            if (!$registrar->hasIntegration($this->service_name)) {
               continue;
            }
            if (!array_key_exists($this->service_name, $config['integrations'])) {
            $type = $registrar->getIntegration($this->service_name)->getContent_type();
            if (!$type) {
               continue;
            }
            if (!array_key_exists('content_type', $config['integrations'][$this->service_name])) {
               continue;
            }
            $type = $config['integrations'][$this->service_name]['content_type'];
            if (!in_array($type, $enabled)) {
               $enabled[] = $type;
            }
@@ -3525,4 +3528,18 @@
   {
      $this->token_refresh_attempted = false;
   }
   public function getAllowedContent():array
   {
      return $this->allowedContent;
   }
   /**
    * Used by JVBase\registrar\helpers\AddIntegrationFields.php
    * @return array
    */
   public function getAdditionalFields(?string $content_type = null):array
   {
      return [];
   }
}