'kb_doc_page', 'post_status' => ['publish', 'draft', 'private'], 'posts_per_page' => 1, 'fields' => 'ids', 'no_found_rows' => true, 'meta_query' => [ 'relation' => 'AND', [ 'key' => '_kb_gitlab_project_id', 'value' => $projectId, ], [ 'key' => '_kb_gitlab_branch', 'value' => $branch, ], [ 'key' => '_kb_markdown_source_path', 'value' => $sourcePath, ], ], ]); return (int) ($query->posts[0] ?? 0); } public function save(array $data, bool $dryRun = false): int { $existingId = $this->findBySource($data['project_id'], $data['branch'], $data['source_path']); if ($existingId) { $oldChecksum = (string) get_post_meta($existingId, '_kb_page_checksum', true); $oldRendererVersion = (string) get_post_meta($existingId, '_kb_renderer_version', true); if ($oldChecksum === $data['checksum'] && $oldRendererVersion === $data['renderer_version']) { ImportLogger::info('Page unchanged: ' . $data['source_path']); return $existingId; } } if ($dryRun) { ImportLogger::info(($existingId ? 'Would update page: ' : 'Would import page: ') . $data['source_path']); return $existingId; } $postData = [ 'post_type' => 'kb_doc_page', 'post_status' => 'publish', 'post_title' => $data['title'], 'post_name' => $data['page_slug'] ?: 'index', 'post_content' => $data['html'], 'post_excerpt' => wp_trim_words(wp_strip_all_tags($data['html']), 35), ]; if ($existingId) { $postData['ID'] = $existingId; $postId = wp_update_post(wp_slash($postData), true); } else { $postId = wp_insert_post(wp_slash($postData), true); } if (is_wp_error($postId)) { ImportLogger::error('Failed to save page ' . $data['source_path'] . ': ' . $postId->get_error_message()); return 0; } $meta = [ '_kb_gitlab_project_id' => $data['project_id'], '_kb_gitlab_project_path' => $data['project_path'], '_kb_gitlab_branch' => $data['branch'], '_kb_gitlab_commit_sha' => $data['commit_sha'], '_kb_markdown_component' => $data['component'], '_kb_markdown_component_title' => $data['component_title'], '_kb_markdown_version' => $data['version'], '_kb_markdown_module' => $data['module'], '_kb_markdown_page_path' => $data['page_path'], '_kb_markdown_source_path' => $data['source_path'], '_kb_page_checksum' => $data['checksum'], '_kb_last_imported_at' => current_time('mysql'), '_kb_nav_order' => (string) $data['nav_order'], '_kb_parent_page_path' => $data['parent_page_path'], '_kb_product_slug' => $data['product_slug'], '_kb_version_slug' => sanitize_title($data['version']), '_kb_page_slug' => $data['page_slug'], '_kb_nav_tree' => wp_json_encode($data['nav_tree']), '_kb_renderer_version' => $data['renderer_version'], ]; foreach ($meta as $key => $value) { update_post_meta((int) $postId, $key, $value); } wp_set_object_terms((int) $postId, [$data['product_term_id']], 'kb_product'); wp_set_object_terms((int) $postId, [$data['version_term_id']], 'kb_version'); wp_set_object_terms((int) $postId, [$data['component']], 'kb_component'); ImportLogger::info(($existingId ? 'Page updated: ' : 'Page imported: ') . $data['source_path']); return (int) $postId; } public function findFrontendPage(string $productSlug, string $versionSlug, string $pageSlug): ?\WP_Post { return $this->findFrontendPageInProducts([$productSlug], $versionSlug, $pageSlug); } public function findFrontendPageInProducts(array $productSlugs, string $versionSlug, string $pageSlug): ?\WP_Post { $productSlugs = array_values(array_filter(array_map('sanitize_title', $productSlugs))); $pageSlug = $pageSlug ?: ''; if (! $productSlugs) { return null; } $query = new \WP_Query([ 'post_type' => 'kb_doc_page', 'post_status' => 'publish', 'posts_per_page' => 1, 'no_found_rows' => true, 'meta_query' => [ 'relation' => 'AND', ['key' => '_kb_version_slug', 'value' => $versionSlug], ['key' => '_kb_page_slug', 'value' => $pageSlug], ], 'tax_query' => [ ['taxonomy' => 'kb_product', 'field' => 'slug', 'terms' => $productSlugs], ], ]); return $query->have_posts() ? $query->posts[0] : null; } }