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 +28 -2 4.5.44.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 = [];
@@ -94,14 +106,26 @@
94 106 array_push($glossary_term_ids, $term_object->term_id);
95 107 }
96 108 }
97 109 } else {
98 - $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
99 119 }
100 120
101 121 return $glossary_term_ids;
102 122 }
103 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
104 128 public function build_base_query(): array {
105 129 $where = $this->wpdb->prepare("{$this->wpdb->posts}.post_type = %s", 'docs');
106 130 return [
107 131 'where' => $where,
@@ -199,8 +223,9 @@
199 223
200 224 return $where;
201 225 }
202 226
227 + // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
203 228 public function get_faq_posts(): array {
204 229 return get_posts([
205 230 'numberposts' => -1,
206 231 'post_type' => 'betterdocs_faq',
@@ -205,8 +230,9 @@
205 230 'numberposts' => -1,
206 231 'post_type' => 'betterdocs_faq',
207 232 'fields' => 'ids',
208 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.
209 235 'suppress_filters' => true,
210 236 ]);
211 237 }
212 238