You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: AGENTS.md
+26-26Lines changed: 26 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ This file provides guidance to Codex (Codex.ai/code) when working with code in t
4
4
5
5
## Plugin Overview
6
6
7
-
WebberZone Knowledge Base Pro (v3.1.0 is currently in development) is a WordPress plugin (namespace `WebberZone\Knowledge_Base`) that creates a multi-product knowledge base system. It uses a freemium model via Freemius integration — free core features with premium features in `/includes/pro/`.
7
+
WebberZone Knowledge Base Pro (v3.1.0 is currently in development) is a WordPress plugin (namespace `WebberZone\Knowledge_Base`) that creates a multi-product knowledge base system. It uses a freemium model via Freemius integration -- free core features with premium features in `/includes/pro/`.
8
8
9
9
-**Plugin entry**: `knowledgebase.php` (defines constants, loads Freemius via `load-freemius.php`, registers autoloader, and directly requires `includes/options-api.php` and `includes/functions.php`)
10
10
-**PHP**: 7.4+ | **WordPress**: 6.7+
@@ -20,7 +20,7 @@ composer test # Run phpcs + phpcompat + phpstan
**Hook Registry** (`includes/util/class-hook-registry.php`): Custom wrapper around WordPress actions/filters with duplicate prevention and closure support. All components register hooks through this instead of calling `add_action()`/`add_filter()` directly.
76
76
77
77
**Settings**: Global `$wzkb_settings` populated at plugin load. Read via `wzkb_get_option( $key )` or `wzkb_get_settings()`. Settings page in `includes/admin/class-settings.php`.
78
78
79
79
**Caching** (`includes/util/class-cache.php`): Term meta-based caching (not transients) with expiry timestamps. AJAX endpoint for admin cache clearing. Use atomic operations when modifying cached data.
80
80
81
-
**Free vs Pro**: The pro plugin (`knowledgebase-pro/`) is a **standalone, complete replacement** for the free plugin (`knowledgebase/`). It contains its own full copy of all free files (e.g. `includes/frontend/class-shortcodes.php`) **plus** the premium-only code in `includes/pro/`. Activating either version auto-deactivates the other. When adding or editing free-tier features, always edit the file inside `knowledgebase-pro/`— never the sibling `knowledgebase/` directory. Pro-only features are conditionally instantiated in `Main::init()` and live exclusively in `includes/pro/`.
81
+
**Free vs Pro**: The pro plugin (`knowledgebase-pro/`) is a **standalone, complete replacement** for the free plugin (`knowledgebase/`). It contains its own full copy of all free files (e.g. `includes/frontend/class-shortcodes.php`) **plus** the premium-only code in `includes/pro/`. Activating either version auto-deactivates the other. When adding or editing free-tier features, always edit the file inside `knowledgebase-pro/`-- never the sibling `knowledgebase/` directory. Pro-only features are conditionally instantiated in `Main::init()` and live exclusively in `includes/pro/`.
82
82
83
83
### Component Map
84
84
@@ -88,7 +88,7 @@ npm run zip # Create full plugin zip
-**`class-content-importer.php`**— Converts Markdown → Gutenberg blocks (or classic HTML). Handles frontmatter parsing, `[toc]`→`knowledgebase/toc` block or `[kbtoc]` shortcode, image URL resolution. Image blocks always hand-build their `<figure>/<img/>` HTML — never use `outer_html()` (DOMDocument) for image output, as it introduces whitespace and non-self-closing tags that fail Gutenberg block validation.
115
-
-**`class-import-processor.php`**— Core importer: SHA change detection, taxonomy assignment (`sections`→`wzkb_category`, `tags`→`wzkb_tag`, `products`→`wzkb_product`), image sideloading, rename/delete handlers. All three taxonomy types auto-create missing terms by slug. `_wzkb_github_source_url` is populated from a constructed `github.com` blob URL (Git Trees API does not return `html_url`). Developer hooks: `wzkb_github_skip_file`, `wzkb_github_pre_import`, `wzkb_github_post_import`, `wzkb_github_markdown_html`. `fix_image_block_attrs()` runs after sideloading to rebuild `<!-- wp:image -->` comments — only non-sourced attrs (`id`, `sizeSlug`, `linkDestination`) go in the comment; `url`/`alt` are sourced and must be omitted or Gutenberg triggers "Attempt to recover".
116
-
-**`class-link-rewriter.php`**— Rewrites relative `.md` hrefs to WP post permalinks using a path-map transient (`wzkb_github_path_map`, 24 hr TTL).
117
-
-**`class-webhook-handler.php`**— REST endpoint `POST /wzkb/v1/github/webhook` (HMAC-SHA256 validated). Handles push events: added/modified/removed/renamed files. Passes `mapping['branch']` as `$ref` to `process_file()`— do not hardcode `''` here. Accepts both `.md` and `.markdown` extensions. Admin validate endpoint: `GET /wzkb/v1/github/validate`.
118
-
-**`class-import-wizard.php`**— Admin UI page (`wzkb-github-import`) for manual one-off imports. AJAX-driven: `wzkb_github_import_list_files` builds the task list (with SHA pre-skip detection), `wzkb_github_import_process_one` processes a single file and returns result data including permalink and taxonomy terms. Script: `includes/admin/js/github-import-wizard.js`, localised as `WZKBImportWizard`.
-**`class-content-converter.php`**-- Converts Markdown -> Gutenberg blocks (or classic HTML). Handles frontmatter parsing, `[toc]`->`knowledgebase/toc` block or `[kbtoc]` shortcode, image URL resolution. Image blocks always hand-build their `<figure>/<img/>` HTML -- never use `outer_html()` (DOMDocument) for image output, as it introduces whitespace and non-self-closing tags that fail Gutenberg block validation.
115
+
-**`class-import-processor.php`**-- Core importer: SHA change detection, taxonomy assignment (`sections`->`wzkb_category`, `tags`->`wzkb_tag`, `products`->`wzkb_product`), image sideloading, rename/delete handlers. All three taxonomy types auto-create missing terms by slug. `_wzkb_github_source_url` is populated from a constructed `github.com` blob URL (Git Trees API does not return `html_url`). Developer hooks: `wzkb_github_skip_file`, `wzkb_github_pre_import`, `wzkb_github_post_import`, `wzkb_github_markdown_html`. `fix_image_block_attrs()` runs after sideloading to rebuild `<!-- wp:image -->` comments -- only non-sourced attrs (`id`, `sizeSlug`, `linkDestination`) go in the comment; `url`/`alt` are sourced and must be omitted or Gutenberg triggers "Attempt to recover".
116
+
-**`class-link-rewriter.php`**-- Rewrites relative `.md` hrefs to WP post permalinks using a path-map transient (`wzkb_github_path_map`, 24 hr TTL).
117
+
-**`class-webhook-handler.php`**-- REST endpoint `POST /wzkb/v1/github/webhook` (HMAC-SHA256 validated). Handles push events: added/modified/removed/renamed files. Passes `mapping['branch']` as `$ref` to `process_file()`-- do not hardcode `''` here. Accepts both `.md` and `.markdown` extensions. Admin validate endpoint: `GET /wzkb/v1/github/validate`.
118
+
-**`class-import-wizard.php`**-- Admin UI page (`wzkb-github-import`) for manual one-off imports. AJAX-driven: `wzkb_github_import_list_files` builds the task list (with SHA pre-skip detection), `wzkb_github_import_process_one` processes a single file and returns result data including permalink and taxonomy terms. Script: `includes/admin/js/github-import-wizard.js`, localised as `WZKBImportWizard`.
119
119
120
-
**`Import_Processor` public surface**: `get_file_list( $owner, $repo, $mapping, $ref )` wraps `list_markdown_files`; `get_pre_skip_info( $owner, $repo, $path, $tree_sha )` returns existing post data if SHA unchanged, `null` otherwise. `find_github_post()` is `protected` (not private) — subclasses can override.
120
+
**`Import_Processor` public surface**: `get_file_list( $owner, $repo, $mapping, $ref )` wraps `list_markdown_files`; `get_pre_skip_info( $owner, $repo, $path, $tree_sha )` returns existing post data if SHA unchanged, `null` otherwise. `find_github_post()` is `protected` (not private) -- subclasses can override.
121
121
122
-
**Repeater `live_update_field_options`**: pass an `id → label` map in the repeater field args as `'live_update_field_options' => [ id => name ]`; `class-settings-form.php` emits it as `data-live-update-field-options` JSON on the wrapper div; JS reads it to resolve raw values (e.g. term IDs) to human-readable titles in the repeater row header.
122
+
**Repeater `live_update_field_options`**: pass an `id -> label` map in the repeater field args as `'live_update_field_options' => [ id => name ]`; `class-settings-form.php` emits it as `data-live-update-field-options` JSON on the wrapper div; JS reads it to resolve raw values (e.g. term IDs) to human-readable titles in the repeater row header.
123
123
124
124
**Post meta keys** stored per imported article: `_wzkb_github_repo`, `_wzkb_github_path`, `_wzkb_github_sha`, `_wzkb_github_last_sync`, `_wzkb_github_source_url`, `_wzkb_github_doc_id`.
125
125
126
-
**Frontmatter fields** (YAML at top of `.md` file): `title`, `sections`/`categories`/`category`/`section` (→`wzkb_category`), `tags`/`tag` (→`wzkb_tag`), `products`/`product` (→`wzkb_product`), `order`/`menu_order`, `status`, `toc` (bool). `sections` supports path notation for hierarchy: `"Parent/Child"` finds or creates `Child` as a term under `Parent`; plain slugs without `/` remain top-level.
126
+
**Frontmatter fields** (YAML at top of `.md` file): `title`, `sections`/`categories`/`category`/`section` (->`wzkb_category`), `tags`/`tag` (->`wzkb_tag`), `products`/`product` (->`wzkb_product`), `order`/`menu_order`, `status`, `toc` (bool). `sections` supports path notation for hierarchy: `"Parent/Child"` finds or creates `Child` as a term under `Parent`; plain slugs without `/` remain top-level.
127
127
128
-
**Repository mappings** are configured in Settings → GitHub tab as a repeater (`github_repositories`). Each mapping has: `repo_owner`, `repo_name`, `folder_path`, `product_id`, `branch`, `pat`, `default_status`, `duplicate_handling`, `delete_removed`, `status`. The per-mapping `pat` field (sensitive, encrypted) overrides the global `github_pat` for that mapping — use this when repositories belong to different owners or organisations (fine-grained PATs are scoped per owner). The global `github_pat` and `github_webhook_secret` are also `sensitive` type (encrypted at rest). `API::with_pat( $pat )` returns a cloned API instance with the override applied; `Import_Processor::api_for_mapping( $mapping )` selects the right instance automatically.
128
+
**Repository mappings** are configured in Settings -> GitHub tab as a repeater (`github_repositories`). Each mapping has: `repo_owner`, `repo_name`, `folder_path`, `product_id`, `branch`, `pat`, `default_status`, `duplicate_handling`, `delete_removed`, `status`. The per-mapping `pat` field (sensitive, encrypted) overrides the global `github_pat` for that mapping -- use this when repositories belong to different owners or organisations (fine-grained PATs are scoped per owner). The global `github_pat` and `github_webhook_secret` are also `sensitive` type (encrypted at rest). `API::with_pat( $pat )` returns a cloned API instance with the override applied; `Import_Processor::api_for_mapping( $mapping )` selects the right instance automatically.
129
129
130
-
The `repo_name` field uses TomSelect autocomplete (`field_class: 'ts_autocomplete'` + `field_attributes` from `Settings::get_github_repo_search_attributes()`). The backend is `wp_ajax_wzkb_github_repo_search` (registered in `Settings::__construct()`), which queries `GET /search/repositories?q=…` via the global PAT and returns `{ id: repo-name, name: owner/repo-name }` items. The `ts_autocomplete` class is picked up automatically by `includes/admin/settings/js/tom-select-init.js`, already enqueued by `Settings_API` on settings pages — do not re-enqueue or re-implement TomSelect.
130
+
The `repo_name` field uses TomSelect autocomplete (`field_class: 'ts_autocomplete'` + `field_attributes` from `Settings::get_github_repo_search_attributes()`). The backend is `wp_ajax_wzkb_github_repo_search` (registered in `Settings::__construct()`), which queries `GET /search/repositories?q=...` via the global PAT and returns `{ id: repo-name, name: owner/repo-name }` items. The `ts_autocomplete` class is picked up automatically by `includes/admin/settings/js/tom-select-init.js`, already enqueued by `Settings_API` on settings pages -- do not re-enqueue or re-implement TomSelect.
131
131
132
132
### Block Development
133
133
134
-
Blocks are in `includes/blocks/src/[block-name]/`. Each block has its own `block.json`, React `edit.js`, and server-side render via PHP. After editing block source, run `npm run build:[block-name]`— never edit files in `build/` directly.
134
+
Blocks are in `includes/blocks/src/[block-name]/`. Each block has its own `block.json`, React `edit.js`, and server-side render via PHP. After editing block source, run `npm run build:[block-name]`-- never edit files in `build/` directly.
135
135
136
136
### Public Helper Functions
137
137
138
138
`includes/functions.php` exposes the plugin's public API. Key functions:
-`wzkb_get_kb_url()`, `wzkb_get_product_sections_list()`, `wzkb_get_term_hierarchy_path()`-- URL and taxonomy helpers
145
145
146
146
Settings are stored as a single serialized array under option key `wzkb_settings`. All settings filters use the prefix `wzkb_` (e.g. `wzkb_get_option_{$key}`).
0 commit comments