| | |
| | | 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; |
| | |
| | | '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) |
| | |
| | | '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 |
| | | /** |
| | |
| | | { |
| | | $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(); |
| | |
| | | $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(); |
| | | } |
| | | } |
| | | |
| | |
| | | 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 $type) { |
| | | $registrar = Registrar::getInstance($type); |
| | | if ($registrar->hasIntegration($this->service_name)) { |
| | | $taxonomies[] = $registrar->getSlug(); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | protected function clearCache():array |
| | | { |
| | | $success = $this->cache->clear(); |
| | | $success = $this->cache->flush(); |
| | | return [ |
| | | 'success' => $success, |
| | | ]; |
| | |
| | | $params = $this->addOAuthParams($params); |
| | | } |
| | | |
| | | $auth_url = $this->oauth['authorize'] . '?' . http_build_query($params); |
| | | |
| | | |
| | | return $auth_url; |
| | | return $this->oauth['authorize'] . '?' . http_build_query($params); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | 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); |
| | |
| | | */ |
| | | 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; |
| | |
| | | |
| | | 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, |
| | |
| | | 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; |
| | | } |
| | |
| | | return ''; |
| | | } |
| | | |
| | | $meta = new MetaManager($this->userID, 'integrations'); |
| | | $meta = Meta::forOptions($this->userID.'_integrations'); |
| | | $is_connected = $this->isSetUp(); |
| | | $credentials = $this->getCredentials(); |
| | | |
| | |
| | | ?> |
| | | <form id="<?=$this->service_name?>" class="integration <?php echo $is_connected ? 'connected' : 'disconnected'; ?>" |
| | | data-service="<?php echo esc_attr($this->service_name); ?>"> |
| | | <div class="header row btw"> |
| | | <div class="header row x-btw"> |
| | | <h3><?php echo esc_html($this->title); ?></h3> |
| | | <div class="setup"> |
| | | <?php if ($is_connected): ?> |
| | |
| | | $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) { |
| | |
| | | $config['value'] = $credentials[$name]??''; |
| | | $config['base'] = $this->service_name.'_'; |
| | | $config['autocomplete'] = 'off'; |
| | | $meta->render('form', $name, $config); |
| | | Form::render($name,null, $config); |
| | | } |
| | | ?> |
| | | </details> |
| | |
| | | } |
| | | ?> |
| | | </div> |
| | | <div class="actions row btw wrap"> |
| | | <div class="actions row x-btw wrap"> |
| | | <?php |
| | | foreach ($this->buttons as $action => $label) { |
| | | if (!$is_connected && $action !== 'save_credentials') { |
| | |
| | | if (empty($types)) { |
| | | return; |
| | | } |
| | | $meta = new MetaManager($this->userID, 'integrations'); |
| | | $meta = Meta::forOptions($this->userID.'_integrations'); |
| | | ?> |
| | | <form> |
| | | <h1><?= $this->title?> Defaults:</h1> |
| | |
| | | |
| | | $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') { |
| | |
| | | $c['hint'] = $c['description']; |
| | | unset($c['description']); |
| | | } |
| | | $meta->render('form', $name, $c); |
| | | echo Form::render($name, null, $c); |
| | | } |
| | | ?> |
| | | </details> |
| | |
| | | $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; |
| | | } |
| | |
| | | { |
| | | $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 []; |
| | | } |
| | | } |