#!/bin/bash # Manage WordPress categories and tags: list existing ones or create new # ones, so post.sh's CATEGORIES/TAGS (numeric IDs) can be filled in. USER="" # WP user PASSWORD="" # application password generated for your WP user SERVER="" # server hostname, optionally with subdirectories USER_AGENT="Mozilla/5.0 (X11; Linux x86_64) wordpress-rest-curl/1.0" # some hosts block curl's default UA as bot traffic SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/lib/config.sh" # CLI options: # --site NAME same config layering as post.sh # --type TYPE 'category' (default) or 'tag' # --list list existing terms as "idnameslugcount" # --create NAME create a new term, print its id # --find NAME print the id of an existing term with an exact name # match, or exit 1 if none exists SITE="" TYPE="category" ACTION="" NAME="" while [[ $# -gt 0 ]]; do case "$1" in --site) SITE="$2"; shift 2 ;; --type) TYPE="$2"; shift 2 ;; --list) ACTION="list"; shift ;; --create) ACTION="create"; NAME="$2"; shift 2 ;; --find) ACTION="find"; NAME="$2"; shift 2 ;; *) echo "Unknown argument: $1" >&2 exit 1 ;; esac done [[ "$TYPE" == "category" || "$TYPE" == "tag" ]] || { echo "Unknown --type: $TYPE (expected 'category' or 'tag')" >&2; exit 1; } [[ -n "$ACTION" ]] || { echo "Specify one of --list, --create NAME, --find NAME" >&2; exit 1; } wp_load_config ENDPOINT_PATH="/wp-json/wp/v2/categories" [[ "$TYPE" == "tag" ]] && ENDPOINT_PATH="/wp-json/wp/v2/tags" case "$ACTION" in list) wp_api_list_all "$ENDPOINT_PATH" | jq -r '[.id, .name, .slug, .count] | @tsv' ;; find) FOUND_ID=$(wp_api_list_all "$ENDPOINT_PATH" | jq -r --arg name "$NAME" 'select(.name == $name) | .id' | head -n1) if [[ -n "$FOUND_ID" ]]; then echo "$FOUND_ID" else echo "No $TYPE named '$NAME' found." >&2 exit 1 fi ;; create) PAYLOAD=$(jq -n --arg name "$NAME" '{name: $name}') BODY=$(wp_api_call POST "$ENDPOINT_PATH" -H "Content-Type: application/json" --data "$PAYLOAD") || exit 1 echo "$BODY" | jq -r '.id' ;; esac