service_name.'_sync_to'; self::$deleteFrom = $this->service_name.'_delete_from'; self::$syncFrom = $this->service_name.'_sync_from'; //TODO: What is the difference between sync_from and import? self::$import = $this->service_name.'import_from'; } public function getServiceItemID(int $itemID, string $type = 'post'):string { return match($type) { 'post' => Meta::forPost($itemID)->get("_{$this->service_name}_item_id"), 'term','taxonomy' => Meta::forTerm($itemID)->get("_{$this->service_name}_item_id"), 'user' => Meta::forUser($itemID)->get("_{$this->service_name}_item_id"), default => '' }; } protected function updateItemStatus(int|array $items, string $status = 'pending', string $type = 'post'):void { if (!is_array($items)) { $items = [$items]; } foreach ($items as $ID) { match ($type) { 'post' => Meta::forPost($ID)->set('_'.$this->service_name.'_sync_status', $status), 'term' => Meta::forTerm($ID)->set('_'.$this->service_name.'_sync_status', $status), 'user' => Meta::forUser($ID)->set('_'.$this->service_name.'_sync_status', $status), default => false }; } } public function findWPItem(string $integrationID, ?string $type = null):array|false { if (empty($integrationID)) { error_log('Integrations::findWPItem No Integration ID received.'); return false; } $types = ['post', 'term', 'user']; if (!is_null($type) && !in_array($type, $types)) { error_log('Integrations::findWPItem invalid type sent: '.$type.'; defaulting to checking all'); $type = null; } if (!is_null($type)) { return $this->queryWPType($integrationID, $type); } else { foreach ($types as $type) { $check = $this->queryWPType($integrationID, $type); if ($check) { return $check; } } } return false; } /** * @param string $integrationID * @param string|null $type * @return array|false if success, an array of $ID and $type */ public function queryWPType(string $integrationID, ?string $type = null):array|false { if (!in_array($type, ['post', 'term', 'user'])) { return $this->findWPItem($integrationID); } return match($type) { 'post' => $this->findWPPost($integrationID), 'term' => $this->findWPTerm($integrationID), 'user' => $this->findWPUser($integrationID), default => false }; } public function findWPPost(string $integrationID):array|false { if (empty($integrationID)) { return false; } $get = new WP_Query([ 'meta_query' => [ 'key' => BASE."_{$this->service_name}_item_id", 'value' => $integrationID, ], 'fields' => 'ids', 'posts_per_page' => 1, ]); return $get->have_posts() && !empty($get->posts) ? [$get->posts[0], 'post'] : false; } public function findWPTerm(string $integrationID):array|false { if (empty($integrationID)) { return false; } $get = get_terms([ 'meta_query' => [ 'key' => BASE."_{$this->service_name}_item_id", 'value' => $integrationID, ], 'fields' => 'ids', 'hide_empty'=> true, 'number' => 1 ]); return is_wp_error($get) || empty($get) ? false : [$get[0], 'term']; } public function findWPUser(string $integrationID):array|false { if (empty($integrationID)) { return false; } $get = get_users([ 'meta_query' => [ 'key' => BASE."_{$this->service_name}_item_id", 'value' => $integrationID, ], 'fields' => 'ids', 'number' => 1, ]); return is_wp_error($get) || empty($get) ? false : [$get[0], 'user']; } public function registerQueueTypes():void { if (empty($this->syncTaxonomies) && empty($this->syncPostTypes)) { return; } $queue = JVB()->queue(); $executor = new IntegrationExecutor(); $queue->registry()->register(self::$syncTo, new TypeConfig( mergeable: new DefaultMerger('items'), executor: $executor, chunkKey: 'items', chunkSize: 50, maxRetries: 3, )); if ($this->canSync['delete']) { $queue->registry()->register(self::$deleteFrom, new TypeConfig( mergeable: new DefaultMerger('external_ids'), executor: $executor, chunkKey: 'external_ids', chunkSize: 200, maxRetries: 2 )); } $queue->registry()->register(self::$syncFrom, new TypeConfig( executor: $executor, maxRetries: 3 )); $this->registerAdditionalQueueTypes($executor); } /** * Empty. Integration extensions can register additional operation types here * @param IntegrationExecutor $executor * @return void */ protected function registerAdditionalQueueTypes(IntegrationExecutor $executor):void {} /** * @return void Sets the $this->contentTypes, which is an array of TYPE => [$fields] * Should probably set the endpoints here as well, which would be an array of [ TYPE => [ 'create' => '','update' =>'', 'delete'=>'', 'batchCreate'=>'','batchUpdate'=>'', 'batchDelete'=>''] endpoints */ abstract protected function setContentTypes():void; }