Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"wp-coding-standards/wpcs": "^3",
"dealerdirect/phpcodesniffer-composer-installer": "^1",
"yoast/phpunit-polyfills": "^4",
"phpunit/phpunit": "^9.6"
"phpunit/phpunit": "^9.6",
"php-stubs/wp-cli-stubs": "^2.12"
},
"config": {
"autoloader-suffix": "WebberZoneKnowledgeBase",
Expand Down
10 changes: 10 additions & 0 deletions docs/02-kb-advanced/syncing-docs-with-github.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ Go to **Knowledge Base → GitHub** and select the **Import** tab. Select your m

Later imports only process files that have changed. Only `.md` and `.markdown` files are imported, from the folder and all its subfolders; other files are ignored.

## Import with WP-CLI *(Pro only)*

Run the import from the command line using your saved GitHub mappings:

```bash
wp wzkb github import --mapping=all --verbose
```

For previews, export, and other options, see [Knowledge Base WP-CLI commands](https://webberzone.com/support/knowledgebase/knowledge-base-wp-cli/).

## Step 5: Set up automatic sync (optional)

To import automatically on every push, add a webhook to your repository:
Expand Down
120 changes: 120 additions & 0 deletions docs/03-kb-developer-docs/knowledge-base-wp-cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
slug: knowledge-base-wp-cli
title: "Knowledge Base WP-CLI commands"
products: [knowledgebase]
sections: ["03-kb-developer-docs"]
tags: [developer, github, knowledgebase, pro, wp-cli]
status: publish
order: 0
toc: true
---

[toc]

[Knowledge Base Pro](https://webberzone.com/plugins/knowledgebase/) provides WP-CLI commands for search, status, cache, settings, ratings, Ask the Docs, and GitHub documentation sync. Install WP-CLI and configure your repositories in the GitHub settings before running the commands.

## Search and status

```bash
wp wzkb status --format=json
wp wzkb search "getting started" --limit=10
wp wzkb rating stats 123 --format=json
```

Status shows the plugin version, site, article counts, section count, and product count. Search returns published articles without passwords; `--limit` accepts 1 to 100. Rating statistics include total votes, sum, positive votes, and average for the requested article.

## Cache and settings

```bash
wp wzkb cache clear --dry-run
wp wzkb cache clear --yes
wp wzkb settings get kb_slug
wp wzkb settings export > settings.json
```

Cache clearing also runs the cache-cleared action used by Knowledge Base. Settings export returns saved settings as JSON and strips tokens and other registered sensitive fields. Settings get returns an effective non-sensitive value as JSON. Sensitive and unknown keys are refused. These commands do not modify settings.

## Ask the Docs *(Pro only)*

```bash
wp wzkb ai status --format=json
wp wzkb ai ask "How do I start?"
wp wzkb ai gaps-list --limit=50 --page=1 --format=json
wp wzkb ai cache-clear --dry-run
wp wzkb ai gaps-clear --dry-run
```

Ask uses the configured provider, cache, and request limits and can incur provider charges. The result is JSON. On the command line, requests without a visitor IP share the normal unknown-visitor rate limit. The gaps list groups unanswered questions from the last 30 calendar days in the site time zone.

`cache-clear` clears cached answers and provider status. `gaps-clear` permanently deletes all recorded questions, including answered questions. Each prompts for confirmation; pass `--yes` to run unattended. Both support `--dry-run`.

## GitHub commands *(Pro only)*

## Choose a repository mapping

Show enabled mappings and their indexes:

```bash
wp wzkb github status
```

Select a mapping with `--mapping=0`, all enabled mappings with `--mapping=all` or `--all`, or a repository with `--repo=owner/name`. Use only one selector. A repository used by multiple mappings must be selected by index. Mapping indexes can change when you reorder settings rows.

Status and diff default to all enabled mappings. Import and export require an explicit selector. The commands use the global GitHub token unless a mapping has its own token. Use the global WP-CLI `--url=<site>` option to select a multisite site.

## Import articles

Preview or import all enabled mappings:

```bash
wp wzkb github import --mapping=all --dry-run
wp wzkb github import --mapping=all --verbose
```

The import uses each mapping's branch, folder, product, status, and duplicate settings. `--verbose` shows each file as it is processed in table mode. The final table includes the action, article ID, notes, warnings, and errors.

Import one file, or process it again even if its saved SHA matches:

```bash
wp wzkb github import --mapping=0 --file=docs/start.md
wp wzkb github import --mapping=0 --file=docs/start.md --force
```

`--force` bypasses the unchanged SHA check. It does not bypass source locks or duplicate-handling settings. Files absent from the remote tree are not automatically deleted by this command. An excluded file can draft or permanently delete its linked article according to the mapping.

A dry run predicts actions without saving articles or terms, sideloading media, or changing GitHub. Hooks and concurrent changes can affect the actual result. Use `--user=<admin>` to assign an author and retain HTML allowed by that WordPress user. Without a user, WordPress applies its normal content filtering and uses author ID 0.

## Check differences

```bash
wp wzkb github diff --mapping=0 --format=json
```

`remote_changed` compares the remote file with the saved source SHA. `export_differs` compares it with Markdown generated from the current article. Formatting can change during a Markdown round trip. `not_imported` includes files that have no linked article, including intentionally excluded files.

## Export articles

Enable **Push-back** and provide a token with write access for each selected mapping. Preview generated Markdown or export:

```bash
wp wzkb github export --mapping=0 --post=123 --dry-run --format=json
wp wzkb github export --mapping=0 --yes
```

`--post=<id>` limits the export to a linked article. CLI export checks the saved source SHA against GitHub and reports a conflict when the remote file is missing or changed. Import and review the file before trying again. If the generated and remote Markdown match but the saved baseline is outdated, import to reconcile the baseline.

Exports use non-force branch updates. If an export phase fails, use its job ID to retry:

```bash
wp wzkb github export --job=<job_id> --yes --format=json
```

Do not combine `--job` with a selector, `--post`, or `--dry-run`. Jobs are eligible for cleanup after one hour of inactivity. If GitHub updated the branch but local sync state changed concurrently, the command reports an error and preserves the newer local state.

## Output and confirmations

GitHub status, diff, import, and export support `--format=table`, `json`, `csv`, and `yaml`. Table is the default. For exact exported Markdown, use JSON or YAML. WP-CLI prefixes CSV cells beginning with a hyphen with an apostrophe for spreadsheet safety.

Import and export ask for confirmation. Use `--yes` for unattended runs. Declining exits successfully without writing. A command exits with code `1` for invalid input or any failed operation; successful rows remain visible when other rows fail. A diff by itself is not an error.

Use `wp help wzkb github` or `wp help wzkb github import` to view command help.
10 changes: 5 additions & 5 deletions includes/admin/class-import-export.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function process_export(): void {
$settings = array();
}

$settings = $this->strip_sensitive_fields( $settings );
$settings = self::strip_sensitive_fields( $settings );

ignore_user_abort( true );
nocache_headers();
Expand Down Expand Up @@ -143,7 +143,7 @@ public function process_import(): void {

// Preserve all sensitive values from the existing settings — they are
// site-specific encrypted values and are never present in the export file.
$sensitive_keys = $this->get_sensitive_keys();
$sensitive_keys = self::get_sensitive_keys();
$existing_secrets = array_intersect_key( $existing, array_flip( $sensitive_keys['top_level'] ) );

// Merge: imported values win for non-sensitive keys; existing wins for sensitive ones.
Expand Down Expand Up @@ -253,8 +253,8 @@ public function render_card(): void {
* @param array $settings Settings array to sanitize for export.
* @return array
*/
private function strip_sensitive_fields( array $settings ): array {
$sensitive = $this->get_sensitive_keys();
public static function strip_sensitive_fields( array $settings ): array {
$sensitive = self::get_sensitive_keys();

foreach ( $sensitive['top_level'] as $key ) {
unset( $settings[ $key ] );
Expand Down Expand Up @@ -290,7 +290,7 @@ private function strip_sensitive_fields( array $settings ): array {
*
* @return array{top_level: string[], repeater: array<string, string[]>}
*/
private function get_sensitive_keys(): array {
private static function get_sensitive_keys(): array {
$top_level = array();
$repeater = array();

Expand Down
18 changes: 13 additions & 5 deletions includes/util/class-cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,15 @@ public function ajax_clearcache() {
* @since 2.3.0
*
* @param array $meta_keys Array of meta keys to delete.
* @param bool $failed Whether a database operation failed, passed by reference.
* @return int Number of meta keys deleted.
*/
public static function delete( $meta_keys = array() ) {
public static function delete( $meta_keys = array(), &$failed = null ) {
global $wpdb;

$rows_deleted = 0;

$default_meta_keys = self::get_keys();
$default_meta_keys = self::get_keys( $failed );

if ( ! empty( $meta_keys ) ) {
$meta_keys = array_intersect( $default_meta_keys, (array) $meta_keys );
Expand All @@ -82,7 +83,7 @@ public static function delete( $meta_keys = array() ) {
}

foreach ( $meta_keys as $meta_key ) {
$rows_deleted += (int) $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$result = $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"
DELETE FROM {$wpdb->termmeta}
Expand All @@ -91,6 +92,11 @@ public static function delete( $meta_keys = array() ) {
$meta_key
)
);
if ( false === $result ) {
$failed = true;
} else {
$rows_deleted += (int) $result;
}
}

return $rows_deleted;
Expand All @@ -99,9 +105,10 @@ public static function delete( $meta_keys = array() ) {
/**
* Get the default meta keys used for the cache
*
* @return array Transient meta keys
* @param bool $failed Whether the lookup failed, passed by reference.
* @return array Transient meta keys.
*/
public static function get_keys() {
public static function get_keys( &$failed = null ) {
global $wpdb;

$keys = array();
Expand All @@ -113,6 +120,7 @@ public static function get_keys() {
";

$results = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$failed = '' !== $wpdb->last_error;

$keys = wp_list_pluck( $results, 'meta_key' );

Expand Down
8 changes: 8 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,14 @@ You can report security bugs through the Patchstack Vulnerability Disclosure Pro

== Changelog ==

= 3.3.0 =

Release date: TBD

**Added**

* [Pro] WP-CLI commands for search, status, cache, settings, ratings, Ask the Docs, and GitHub documentation sync.

= 3.2.4 =

Release date: 3 November 2026
Expand Down
Loading