Skip to content

KB API: admin create/update/delete for articles and categories, in v1.0 (#1948 reconciled) - #1953

Merged
nkissebe merged 2 commits into
2.4-mainfrom
kb-api-write-1948
Oct 21, 2026
Merged

nkissebe merged 2 commits into
2.4-mainfrom
kb-api-write-1948

Conversation

@nkissebe

Copy link
Copy Markdown
Contributor

Supersedes #1948 (head on a fork). denphi's commit rebased onto 2.4-main, then a second commit that folds the new write operations into entriesv1_0.php instead of adding entriesv1_1.php:

Why one version. Hubzero\Api\Component\Loader serves the highest entriesv*.php for unversioned calls, so v1.1 would have silently replaced v1.0 for the consumer of #1942's public feed, and the two files duplicated ~300 lines of list/read code. In the merged controller list and read behave exactly as before for every caller; the only additions are for Super Users (state=0|1|2|all on list, reading an unpublished article), plus a tags field on read.

Review fixes applied.

  • Category delete: Nested::destroy() corrupts lft/rgt when the subtree has grandchildren (gap closed once per level and again for stale models). Rows are now destroyed deepest-first, each a leaf at the time, then the shared tree is rebuilt.
  • Category update stored the alias as sent (model derives one only on create); now normalised, empty falls back to title.
  • Alias uniqueness scoped to the extension, any parent — matching com_kb/site/router.php, which resolves categories by bare alias.
  • JSON body keys id/task/controller/… are no longer merged into the request, so a body cannot retarget the route.
  • state, access, created, created_by validated (422 with specific messages).
  • Misleading comments on language loading / model includes corrected.

Not changed: moves still use saveAsChildOf() + rebuild(1), as the admin save does.

🤖 Generated with Claude Code

denphi and others added 2 commits October 21, 2026 13:18
A new entriesv1_1.php would have become the default for every
unversioned /api/kb call -- the loader picks the highest version it
finds -- so the consumer of #1942's public feed would have moved onto
it unasked, and the two files carried the same list/read code twice.
The write tasks and the categories endpoint now live in v1.0; list and
read behave exactly as before for every caller unless a Super User
asks for a state, and a Super User may read an unpublished article.

Fixes on the way in:
- deleting a category with grandchildren corrupted the nested set:
  Nested::destroy() closes the gap once per level and again for the
  stale descendant models it holds. Rows now go deepest first, each a
  leaf when it does, followed by a rebuild of the shared tree
- a posted category alias was stored as sent on update (the model only
  derives one on create); it is normalised, and an empty one falls
  back to the title
- the alias clash check matched the site's routing: any category of
  the extension, not siblings of any extension
- a JSON body could name another id, or another task, and redirect
  the request; route variables are no longer taken from the body
- state, access, created and created_by are validated before saving
- comments described language loading and model includes the code
  did not do

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@nkissebe
nkissebe merged commit 0ef954f into 2.4-main Oct 21, 2026
3 checks passed
@nkissebe
nkissebe deleted the kb-api-write-1948 branch October 21, 2026 17:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants