PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.2
4.9.2 4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 All 200 releases
← All changes | includes/Admin/WPExporter.php +35 -6 4.5.04.9.2 View file →
@@ -10,8 +10,19 @@
10 10 if ( ! defined( 'ABSPATH' ) ) {
11 11 exit; // Exit if accessed directly.
12 12 }
13 13
14 +/**
15 + * SQL building helpers below interpolate WP-provided $wpdb table identifiers
16 + * (`$wpdb->posts`, `$wpdb->term_relationships`, `$wpdb->term_taxonomy`) and use
17 + * dynamic %d placeholder lists derived from integer arrays. Suppressing the
18 + * related PHPCS notices class-wide rather than per-call.
19 + *
20 + * phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
21 + * phpcs:disable WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
22 + * phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
23 + * phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
24 + */
14 25 #[\AllowDynamicProperties]
15 26 class WPExporter {
16 27 /**
17 28 * @var array
@@ -61,9 +72,10 @@
61 72
62 73 // Handle additional filters (author, dates, meta)
63 74 $where .= $this->build_additional_filters();
64 75
65 - // Get the main doc post IDs
76 + // $join/$where are composed from prepared fragments above; identifiers are WP-provided.
77 + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,PluginCheck.Security.DirectDB.UnescapedDBParameter
66 78 $post_ids = $this->wpdb->get_col( "SELECT DISTINCT {$this->wpdb->posts}.ID FROM {$this->wpdb->posts} $join WHERE $where" );
67 79
68 80 // Handle FAQ posts separately
69 81 $faq_post_ids = [];
@@ -73,8 +85,10 @@
73 85
74 86 // Combine post IDs
75 87 $all_post_ids = array_merge( $post_ids, $faq_post_ids );
76 88
89 + $all_post_ids = WPMLSupport::expand_with_translations( $all_post_ids );
90 +
77 91 // Handle featured images
78 92 $thumbnail_ids = $this->get_thumbnail_ids( $all_post_ids );
79 93
80 94 // Generate final post IDs array
@@ -92,14 +106,26 @@
92 106 array_push($glossary_term_ids, $term_object->term_id);
93 107 }
94 108 }
95 109 } else {
96 - $glossary_term_ids = $this->wpdb->get_col( "SELECT term_id from {$this->wpdb->term_taxonomy} where taxonomy='{$this->args['content']}';" );
110 + // $this->wpdb->term_taxonomy is a WP-core table identifier; %s placeholder binds taxonomy name.
111 + // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,PluginCheck.Security.DirectDB.UnescapedDBParameter
112 + $glossary_term_ids = $this->wpdb->get_col(
113 + $this->wpdb->prepare(
114 + "SELECT term_id FROM {$this->wpdb->term_taxonomy} WHERE taxonomy = %s",
115 + (string) $this->args['content']
116 + )
117 + );
118 + // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,PluginCheck.Security.DirectDB.UnescapedDBParameter
97 119 }
98 120
99 121 return $glossary_term_ids;
100 122 }
101 123
124 + // The query-builder methods below interpolate only $wpdb core table names
125 + // ({$this->wpdb->posts}, etc.) — never user input — and bind every value via
126 + // %s/%d placeholders, so the InterpolatedNotPrepared warnings are spurious.
127 + // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
102 128 public function build_base_query(): array {
103 129 $where = $this->wpdb->prepare("{$this->wpdb->posts}.post_type = %s", 'docs');
104 130 return [
105 131 'where' => $where,
@@ -197,14 +223,17 @@
197 223
198 224 return $where;
199 225 }
200 226
227 + // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
201 228 public function get_faq_posts(): array {
202 229 return get_posts([
203 - 'numberposts' => -1,
204 - 'post_type' => 'betterdocs_faq',
205 - 'fields' => 'ids',
206 - 'post_status' => 'publish'
230 + 'numberposts' => -1,
231 + 'post_type' => 'betterdocs_faq',
232 + 'fields' => 'ids',
233 + 'post_status' => 'publish',
234 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.SuppressFilters_suppress_filters -- intentional: export the raw, untranslated FAQ set so multilingual filters don't drop or swap rows during export.
235 + 'suppress_filters' => true,
207 236 ]);
208 237 }
209 238
210 239 public function get_thumbnail_ids(array $post_ids): array {