WP Manifestindependent plugin directory
manifest / editor / rendar-editorial-controls

Rendar Editorial Controls

Opt-in editorial controls for the WordPress block editor

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/rendar-digital/rendar-editorial-controls/archive/refs/heads/main.zip
Updates itself. It ships its own updater (Update URI header), so new versions appear under Dashboard → Updates.

Rendar Editorial Controls 0.1.1

Standalone WordPress plugin for optional editorial controls in the block editor. Requires WP 6.6+ (PluginDocumentSettingPanel in wp.editor, block-editor hooks, REST post meta and Settings API) and PHP 7.4+. PHP 7.4 is a lint target, not a full runtime integration environment. The disposable SQLite WordPress acceptance harness is documented in tests/integration/README.md; consult its per-version evidence rather than inferring coverage from the stub suites.

Three independently enabled modules under Settings → Editorial Controls:

  • Featured: _focal_point object {x,y} in [0,1] on eligible REST post types supporting both thumbnail and custom-fields, including pages and CPTs when configured. Existing meta is unchanged; toggling off never deletes it. Permission: edit_post per record. The panel is only enqueued for enabled eligible post types.
  • GB image: optional GenerateBlocks media Settings shortcut (acceptance fixture: GB 2.5.0-rc.1 / Pro 2.8.0-rc.1, both requiring WP 6.7+; the base plugin still supports WP 6.6 without this module) for aspect ratio, scale and a static image object-position picker. Writes only via GB onStyleChange to its editable style data; no PHP frontend output. Skips when the GB media editor script is absent or the block/context isn't a supported generateblocks/media image. No automatic featured-image binding.
  • Tags: post_tag-only editor selector. Typed tokens remain pending/error on lookup/create failure, with serialized requests and bounded exponential backoff, explicit Retry. Uses a server-authoritative lookup before creation; term_exists assigns the existing term ID. Categories and other taxonomies remain core.

Tag policy: Default exact means literal trimmed name equality (PHP bytes after DB candidate lookup), rather than the old near-duplicate rule. No guessed JS/PHP accent parity; browser keys are literal trimmed tokens, only for queue identity. aggressive is an optional server-side normalization policy: WordPress remove_accents with an explicit en_US locale, Unicode case-folding when mbstring is available, and punctuation/whitespace folding while preserving letters and numbers in every script (including mixed-script names). Only WP-supported accent mappings are equivalent: WP does not map ffi to ffi. Browser keys remain literal queue identities; only the server determines equivalence. It builds a normalized index of at most 50,000 post_tag rows on the first lookup after a relevant change, stored in one fixed non-autoloaded wp_option alongside a small generation option, across HTTP requests even without a persistent object cache. Create/edit/delete and term count updates invalidate the generation. A concurrent invalidation makes an older scan fail closed; a late old writer's payload is ignored on the next lookup, not treated as current. This is not an atomic resolve/create transaction. At 50,001 rows, or 500 equivalent candidates for one key, lookup returns 503 and creation is blocked. A rebuild reads the whole taxonomy and can be costly (and the stored option large) on a 28k-tag site; test latency and storage on a real site before enabling. There is no periodic expiry/rebuild; a cache write failure returns 503 instead of automatically scanning again for another token in the same request. Prepared token LIKE is not a safe substitute for an exhaustive Unicode index. This policy may group meanings you did not intend, and the server cannot guarantee core's own collation/term_exists shares this definition. Neither policy creates when lookup fails or is incomplete.

Development

php tests/php-unit.php && node tests/normalize-queue.mjs && node tests/scope.mjs && node tests/gb-image.mjs; lint with bash bin/php-lint (the script propagates any PHP parse failure). Run bash tests/php-lint.sh, node tests/tags-component.mjs and bash tests/build-zip.sh for the lint, hostile-name component and archive regressions. tests/test-updater.php needs a real WordPress core: set WP_CORE_DIR or run bin/provision-wp-core to fetch CI's pinned version (docs/wp-core-pin.md); it skips itself with a message if WP_CORE_DIR is unset outside CI, and CI hard-fails instead. The Node suites load the production JS; the PHP suite uses isolated WordPress stubs and a fake DB, not an actual WP site. bash bin/build-zip on a clean commit produces dist/rendar-editorial-controls-0.1.1.zip with stable plugin root and no dev/test files. See docs/API.md and docs/featured-gb.md.

Automatic updates

The plugin checks its own public GitHub Releases (releases/latest/download/info.json, cached 12 hours, 1 hour after a failure) and fails quietly. The static Update URI: https://updates.rendar.digital/rendar-editorial-controls header is only an identifier so WordPress.org cannot claim the slug; it is not a server. No credentials or wp-config.php setup are needed. Automatic updates use WordPress's normal Plugins-screen opt-in and cron. To turn update checks off entirely, add define( 'RENDAR_UPDATES_DISABLED', true ); to wp-config.php. Network-activate on multisite to register the hooks across the network. The updater lives in inc/class-rec-updater.php plus one require_once/new pair in the main file; a WordPress.org build removes exactly those.

To cut a release after review: update the plugin header and REC_VERSION together to a stable X.Y.Z, commit and test, create/push tag vX.Y.Z, then publish a non-draft GitHub Release on that tag. .github/workflows/release.yml validates the versions, runs tests and bin/build-zip, and attaches rendar-editorial-controls.zip (root rendar-editorial-controls/) and info.json (slug, name, version, tag, package, requires, requires_php, tested, last_updated, changelog from the matching CHANGELOG.md section). Publishing is a separate decision.

Operational limits

The editor-only panel does not alter rendering. The featured panel stores an object, not CSS. GB may need additional site-specific wiring for dynamic images; the shortcut itself never wires them. A settings switch changes registration/UI, not existing content or meta. Tag queue state is in browser memory only: do not navigate away from a pending/error token without retrying or recording it. Initial assigned IDs without resolved names await the core store fetch. Integration coverage uses a disposable SQLite backend only; no MySQL/MariaDB or real site traffic is implied. Read docs/integration-acceptance.md for executed cases and limitations. Editor asset enqueue remains at priority 20 (after typical core/plugin registration); the GB shortcut explicitly depends on the GB media editor handle. Featured and Tags have no hook dependency on unrelated panels.

License

GPL-2.0-or-later. See LICENSE.